кстати. таким же образом можно рисовать попапы от комбо-боксов, без оверлеев. идеологически это будет более правильно: фрэймворк ожидает, что при открытии попапа мы уходим в цикл выбора, из которого возвращаемся только когда попап закрыт. и порядок notifications хочет именно такой (я тут выше где-то писал об этом). с одной стороны я сейчас в CFrames просто вешаю оверлей и обрабатываю его события штатно. а с другой — можно точно то же самое сделать и без оверлея.
вообще, мне система оверлеев не очень нравится. я понимаю, для чего она была сделана и какую задачу решает, но мне не нравится. во-первых, механизм слишком специфический. а во-вторых, слишком широкий. такая вот диалектика.
по сути, оверлей — это попап-окно поверх текущего окна. при этом оверлей для документа может быть только один, и ровно одного типа: который съедает все сообщения от мыши и клавы.
если подумать, то на самом деле это огрызок системы popup notifications, где оные оверлеи нужно иметь возможность открывать в количестве, и давать им выбор: или жрать все сообщения, или только мышь, когда она в границах попапа. таким образом мы сможем делать и всякие прикольные notifications в документах (в том числе с альфа-каналом, потому что технически LC позволяет блитать картиночки с альфой), и попапы.
хотя по уму, попапы надо делать вообще отдельными окнами host OS — чтобы они не были ограничены размером текущего окна. а то если у нас форма с одним комбо, например, по высоте как раз чтобы комбо влез — то попапу от комбо просто негде открыться, он и будет однострочным. работоспособно, но неудобно. в винде для этого используется стандартный виндокотрол, и в других местах TrackPopupMenu. а у нас на невинде такого трекера нет. а хочется.
в принципе, у меня в LC есть механика модальных окон: когда активно модальное окно, то запускается Loop.LoopModal, который почти обычный цикл обработки сообщений, но с некоторыми нюансами. нюанс такой, что в нём крутятся только immediate и insistent actions, и ещё система не посылает сообщения о юзерской активности и перерисовке никаким окнам кроме модального. i can get away with this, потому что у меня каждое окно имеет задний буфер; таким образом когда host OS просит нарисовать окно — я не посылаю ему сообщения, а просто блитаю кусок готового заднего буфера. соответственно, нет риска, что всё изменится, пока модал активен. там ещё небольшие патчи в Controllers для этого, но в целом оно вот так. фильтрация сообщений сделана на уровне бэкэнда, натурально. (кстати, input-цикл тоже фильтрует сообщения тем же механизмом; поэтому в таком цикле LC нормально реагирует на запросы отрисовки от системы).
так я к чему. попапы надо делать той же механикой, мне кажется. в иксах — используя override redirect, как и делают все тулкиты. это позволит нам использовать для кода попапов обычную механику views, с обычной отрисовкой и обработкой сообщений — но попапы больше не будут ограничены родительским окном. главное меню оставить на оверлеях пока (там много переделывать иначе), но добавить в бэкэнд штатный апи типа `TrackPopupMenu()`. на винде его можно делать через вызов оси, а на линуксах эмулировать ручками через механику модалов, например. в идеале, конечно, этот же апи надо и для главного меню использовать — тогда мы сможем без особых напрягов получить вложеные менюшки, например. а линейка главного меню останется обычным встраиваемым bar-ом.
у меню на оверлеях, впрочем, есть одно большое достоинство: оно не блокирует никакие actions. но это решаемо и в моём варианте: у меня в модалах предусмотрена возможность разрешить не только insistent, а все. также меню на оверлеях вызывает нормальные перерисовки окон через `Restore()` — и тут я не уверен, плюс это или минус.
вообще, идея такого верхнего меню довольно чужеродна для оберон-систем — поэтому оно так фигово впиховывается в BBCB; я так-то не очень уверен, что оно нужно именно в таком виде. возможно, его лучше сделать особым видом попап-меню, которое вызывается по другой кнопке, например (и вертикальным). омики в своё время его запилили чтобы выглядеть «нативно», но это давно уже не жёсткое требование.
p.s.: и, кстати, заодно сделать нормальный апи для регистрации как system-wide hotkeys, так и window hotkeys. чтобы можно было без меню их регистрировать, получать список, и ты пы. а меню пусть пользуется этим механизмом. тогда во многих случаях главное меню вообще можно в приложении не делать; или делать, но не подвязывать к нему хоткеи.
натурально, подвязывание хоткеев к меню имеет одно большое достоинтсво: discoverability. юзер посмотрел меню — там хоткеи написаны. но мне кажется, что всё-таки стоит разделить низкоуровневый механизм хоткеев, и высокоуровневую сущность типа менюшки. а то сейчас кадавр какой-то получается.
|