Pull to refresh

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

Reading time 3 min
Views 2.1K


Проблема с неработоспособностью 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
Tags:
Hubs:
+27
Comments 19
Comments Comments 19

Articles