Прикручиваем Head Up Display к MonoDevelop или о том, как криво сделано глобальное меню в Ubuntu



    Проблема с неработоспособностью HUD в MonoDevelop уходит корнями в старый баг, вызванный переходом на глобальное меню и заключавшийся в том, что менюшки у MonoDevelop не показывалось вообще никакой. Его "починили", выключив использование глобального меню как такового. Это же так просто, не фиксить проблему в своей кривой либе, а сделать чёрный список приложений.
    Тяга к экономии пикселей и желание таки прикрутить HUD взяли своё. Целых два часа моего драгоценного времени, несколько костылей и всё таки завелось.

    Небольшой экскурс в работу глобального меню: оно экспортируется приложением через D-Bus, а чтобы разработчики не писали дополнительный код, в Canonical наклепали хитровывернутых библиотек, берущих нормальное, человеческое меню оконного тулкита и экспортирующие его за разработчика, причём, как выяснилось, весьма криво, но об этом потом. При этом возможности вручную экспортнуть это меню нет. Точнее, есть какая-то мутная библиотечка с названием libdbusmenu и полным отсутствием хоть какой-то документации, не говоря уже о биндингах к чему-либо. Этакая проприетарщина наоборот — код открыт, но использовать его толком нельзя ввиду невозможности быстро понять, как с этим вообще работать. Таким образом реализовать в GnomePlatform.cs метод SetGlobalMenu (предусмотренный специально для систем с глобальным меню и реализованный в MacPlatform.cs) не представляется возможным, что ж, придётся разбираться с тем, почему не работает костыль с экспортилкой и придумывать свои костыли, чтобы оно заработало. Я такими извращениями не занимался со времён, когда нужно было заставить работать Навител на разнокалиберных китайских железках с изувеченной до неузнаваемости WinCE 4.2.


    Первым делом я убрал костыль с занулением UBUNTU_MENUPROXY, надеясь на то, что все косяки уже починили и всё заработает. Чуда не произошло. Окей, смотрим, есть ли какие-то отладочные инструменты для глобального меню. Нашлась утилитка с названием current-menu-dump, выдавшая весьма интересные результаты: меню таки экспортируется, но его никто не показывает. Объяснения данному феномену на тот момент не нашлось, зато нагуглилась переменная окружения APPMENU_DISPLAY_BOTH, заставляющая экспортилку показывать ещё и нормальное меню. Результаты запуска получились ещё более дивными:



    То есть, если навести на пункт меню в нормальном менюбаре, он тут же появляется и в глобальном меню.

    Объясняется такое странное поведение сочетанием двух оригинальных технических решений:

    1. Unity не показывает пункты глобального меню первого уровня без подменю
    2. MonoDevelop использует «ленивую» загрузку пунктов меню, так что на старте этих подменю нет

    Если среда не посылает события показа меню сама, мы сделаем это за неё. На скорую руку лепим AddIn к MonoDevelop, находящий менюбар и пробегающийся по всем менюшкам, запускаем, происходит чудо: глобальное меню появилось и работает. Если бы не одна «мелкая» неприятность:



    П_одчёркивания в пунктах и отсутствие подсказки по хоткеям.

    Вызвано это снова кривой реализацией libappmenu: она не может адекватно обрабатывать сложные пункты меню, а они в MonoDevelop сложные, каждый пункт внутри — HBox с двумя Label'ами, одна для подписи, другая для хоткея, выровняны по левому и правому краю соответственно. Вылечилось это ловлей нотификации о изменении свойства «label» у, собственно, одного из Label'ов, за наличие которой хочется сказать большое человеческое спасибо разработчкикам GLib, ибо адекватной автоматической реализации IPropertyChanged для всех классов и свойств я даже в C# не видел.

    Чтобы заиметь у себя в MonoDevelop поддержку HUD и глобального меню, нужно поставить пакеты monodevelop-latest и monodevelop-appmenu из моего PPA (сборки только для 12.04):

    sudo apt-add-repository ppa:keks9n/monodevelop-latest
    sudo apt-get update
    sudo apt-get install  monodevelop-latest monodevelop-appmenu
    
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 19

      +6
      Ну в Моно тоже навелосипедили с менюхами, нехрен было их виджетами делать и потом рулить глобальным меню можно и ручками, сам я это делал и это все прекрасно работает!
        +3
        То есть, если я, например, пишу код по документации своего GUI-тулкита (который как раз позволяет в меню пихать всё, а кто-то опять делает свою ни с чем не совместимую реализацию DE, то я же и не прав? По поводу руления глобальным меню ручками, подкиньте ссылок на документацию, ибо я ничего не нашёл.
          +3
          Идея пихать в меню что-то сложнее обычных пунктов заранее ущербна.
          Берешь libdbusmenu и кидаешь пару вызовов dbus'а, точнее один единственный и радуешься. Спеки сейчас не покажу, но код плагинов для appmenu в инете лежит, смотри и юзай, там все прозрачно.
            +2
            Особенно порочно пихать туда чекбоксы, текстовые поля для поиска, индикаторы «подождите, загружается», и вообще — ишш чаво удумоли, менюшки им сложнее «About...» подавай.
        +2
        Всегда подозревал что сделано оно не очень.
        А что предлагают разработчики GlobalMenu для случаев когда простого меню не достаточно?
        Как например сделать кнопки или поле ввода в меню?
        Еще интересно, а это так по DBus и гоняется текстом или это так в дампе?
          +2
          > Как например сделать кнопки или поле ввода в меню?
          И главное, зачем это делать? :)
            +2
            Чекбокс воткнуть полезно бывает, например. Хотя, думаю, для чекбоксов каноникал что-нибудь придумали, надо читать документацию к libdbusmenu, которой нет.
              +1
              Там есть и показ хоткеев и чекбоксы и разделители и radiobutton'ы. Это охватывает 95% всех возможных использований.
              Единственное, что может быть еще нужно, так это поле ввода для организации поиска.
                +3
                Отлично, осталось написать к этому документацию. Ибо без документации только и остаётся городить костыли подобные описанному в статье.
                  0
                  Что-то мне не приходит в голову, зачем в меню может понадобиться поле ввода. Интересно, бывает ли такое под макосью.
                  Чекбоксы — святое, конечно (точнее toggle пункты меню)
                    0
                    Бывает
                      0
                      Понял. Смотрится, по моему мнению, ужасно, да и не место ему тут. По моему мнению.
                        0
                        Поле ввода в принципе спорный момент. Оно красивше смотрится в тулбаре самого окошка. Ну и на самом деле этот поиск по сути и есть тот самый HUD. Впрочем было бы хорошо иметь возможность через dbus с ним общаться дополнительно. В KDE есть же возможность юзать krunner.

                        Хочется DE независимую спеку на dbus для этого, а потом перевести на неё все DEшные велосипеды
                          0
                          Не тот же самый, оно ищет по меню и справке, HUD ищет по меню и индикаторам. И да, хотелось бы API для этого самого HUD, равно как и документацию по всем остальным велосипедам, которые они там понапридумывали. Обычно разработчики ОС в таких случаях выпускают что-то вроде SDK, где есть доки и примеры на всех поддерживаемых языках.
                            0
                            Так оно еще не стабилизировано. Обычно доки выпускают, когда есть стабильное API, пока такого еще нет. Даже на Unity нормальных доков нет, точнее есть дока, но с фразой, что оно все еще не до конца стабильно.
                            0
                            Мне кажется, что поиск должен быть либо не видимым, но быстровызываемым — как HUD, либо уж как в MS Office — всегда на виду. Help должен быть обычным пунктом меню с возможностью вызвать обычный хэлп. Потому что вот лично мне непонятно, что я найду этим (из скриншота) поиском.

                            И да, конечно я согласен про то, что стандартизация это хорошо, однако же надо понимать, что не любая программа хорошо загоняется в стандарт.
              0
              А что делать приложениям на Swing? Ужас. IDEA например.
                +1
                Городить ещё один враппер, экспортирующий Swing-овские менюшки, подключив к нему libdbusmenu через JNI. Причём спасение утопающих — дело самих утопающих, у Каноникал до этого ещё не скоро руки дойдут, у них даже офисный пакет пока что в HUD не может, хорошо хоть к Firefox'у поддержку прикрутили.
                  +2
                  Для Либре Офиса соорудили пакет, который, правда, не включили в дефолтную поставку. lo-menubar называется.

              Only users with full accounts can post comments. Log in, please.