LINUX.ORG.RU

tcl/tk - перехватить все события клавиатуры и мыши на будущее

 , ,


0

1

Продолжаем делать редактор на базе text. text лишь немногим умнее морковки, и он будет по многим вопросам обращаться за мудростью к серверу через сокеты и дожидаться ответа.

Например, пользователь нажал <Return>, перешёл на новую строчку и нужно вычислить автоотступ. Отправляется запрос на сервер о нажатии Return и запрос на автоотступ. Сервер вставляет Return в свою копию буфера редактирования. Теперь буфера одинаковы. Сервер вычисляет автоотступ и возвращает клиенту.

Но после нажатия <Return> и не дожидаясь ответа сервера, пользователь продолжает что-то печатать. Допустим, напечатал открывающую скобку. Чтобы не нарушить синхронизацию буферов, мы на обработчике <Return> в ctext включим режим заморозки.

В этом режиме событие нажатия на скобку должно записываться в некую очередь. В ctext ничего не будет вставлено.

Когда сервер ответит про автоотступ, text вставляет автоотступ и дальше говорит «разморозить».

После этого событие нажатия на скобку достаётся из очереди и применяется к уже новому состоянию буфера с вставленным автоотступом, что и есть единственно верное решение.

Глядя на всякого рода записыватели макросов клавиатуры (скажем, в моей клавиатуре такой есть), я вижу, что они записывают не совсем ту последовательность, которую я набиваю. Вставляют обычно задержки между отправкой событий нажатия. Также есть события от мыши. Также есть кнопки-модификаторы.

Внимание, вопрос: есть ли библиотека на tcl, которая это умеет? если нет, то куда копать?

★★★★★

Последнее исправление: den73 (всего исправлений: 2)

или посмотри, можно ли использовать tags в text: перед отправкой на сервер назначить тег в текущей позиции, после ответа найти по тегу и вставить туда

anonymous
()
Ответ на: комментарий от anonymous

den73 с другого компа

Не, теги не проходят. Нужно именно блокировать.

anonymous
()
Ответ на: den73 от anonymous

Вспомнил, что недавно выпиливал из tcltextedit-а макрорекордер. Пойду, посмотрю, как он сделан.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Посмотрел - отстой. А вот мне интересно, можно ли получить список всех биндингов, и каждый из них обернуть. Т.е. было

bind .text <key1> proc1
А стать должно
bind .text <key1> {if {$freeze} {
  [put_to_queue %a .. %z] 
} else {
  proc1
}

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Эх, что-то группа поддержки куда-то свалила :)

Пока вроде вижу такой выход - берём из дистрибутива text.tcl, ctext.tcl и надеемся, что там перечислен полный набор биндингов. Аккуратно берём каждый биндинг и вручную обёртываем его в эту обёртку.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

можно ли получить список всех биндингов,

bind tag ?sequence? ?+??script?

If neither sequence nor script is specified, then the return value is a list whose elements are all the sequences for which there exist bindings for tag.

и каждый из них обернуть

If sequence is specified without a script, then the script currently bound to sequence is returned

antares0 ★★★★
()
Последнее исправление: antares0 (всего исправлений: 1)
Ответ на: комментарий от antares0

Извините, наверное, надо научиться получше читать маны :) Видимо, нужно воспользовать сочетанием bind tag и bindtags. А я был близок - до bindtags уже докопался, а дальше только две буквы поменять в команде :)

Наверное, для декорации мне хватит операций со строками... хм-хм. Ура, день был не столь безплоден, как я думал.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Осудите план:

Делаю новый тег для bind. Беру все биндинги для Text, копирую их в этот тег. Каждый биндинг оборачиваю в проверку, не включён ли режим заморозки. Если не включён, то выполняю сразу, если включён, то откладываю.

Операция разморозки состоит в том, что я отправляю замороженные события по одному в after idle (или after 0, или after 50ms?) и после исчерпания замороженных событий отключаю режим заморозки.

Делаю я так сложно для того, чтобы не морочиться с разбором модификаторов клавиатуры, чтобы не перехватывать события, которые не предназначены моему виджету. Например, если пользователь нажал Alt-. для переключения в окно REPL, а редактор заморожен, то нет оснований заставлять пользователя ожидать разморозки редактора. Более того, это жизннено важно для отладки, когда сервер редактора повис.

Ну и вообще неплохо бы иметь библиотечку для метапрограммирования и шаблонирования. Пока уже сложились такие требования:

- подстановка метапараметров времени раскрытия шаблона. Пока окружаю шаблоны четырёхкратными угловыми скобками и делаю regsub.

- проверка, что в коде нет параметров, т.е. он не обращается ни к каким внешним переменным (ну или передавать список тех, к кому можно обращаться). Это нужно для «проверочных утверждений» (assert-ов) в ситуации, когда вычисление кода откладывается на потом и будет производиться в контексте, где текущие переменные могут быть недоступны.

- отложенная подстановка параметра. Здесь известно, что при выполнении кода в будущем будет определена некоторая переменная, которую и нужно будет использовать. Например, это будет если мы готовим тело для apply и при применении будут даны такие-то параметры.

При этом желательно, чтобы шаблоны кода задавались не строками, а были зрительно похожи на обычный код, т.е. с помощью {}. В общем-то, для такой библиотечки почти не нужно программирования. Это скорее должна быть статья, а не библиотечка. Может есть такая где-нибудь.

Самое обидное, что где-то в моём проекте уже есть наработки по этой теме, но я их потерял и не могу найти :)

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Похоже, что что-то начало получаться. Исходник вот.

Можно подать текстовому виджету команду «замри» и почти все события перестают в него поступать. Вместо этого они встают в очередь. Когда говоришь «отомри», события отрабатываются. Проверено, что работает ввод, удаление и щелчки мышью. Не перехыватывается пока copy/paste, но это связно с тем, что есть разные bindtag-и. Я перешиб только bindtag с именем Text - вместо него вставляется FreezableText. С остальными bindtag-ами нужно отдельно разбираться.

Заодно немного освоил МП для tcl - замыкания теперь выглядят почти красиво, а также научился делать «макросы». Вот составил текстик на эту тему, а то потом забуду.

План работы по созданию лиспового режима для редактора

den73 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.