Проблема с неработоспособностью HUD в MonoDevelop уходит корнями в старый баг, вызванный переходом на глобальное меню и заключавшийся в том, что менюшки у MonoDevelop не показывалось вообще никакой. Его "починили", выключив использование глобального меню как такового. Это же так просто, не фиксить проблему в своей кривой либе, а сделать чёрный список приложений.
Тяга к экономии пикселей и желание таки прикрутить HUD взяли своё. Целых два часа моего драгоценного времени, несколько костылей и всё таки завелось.
Небольшой экскурс в работу глобального меню: оно экспортируется приложением через D-Bus, а чтобы разработчики не писали дополнительный код, в Canonical наклепали хитровывернутых библиотек, берущих нормальное, человеческое меню оконного тулкита и экспортирующие его за разработчика, причём, как выяснилось, весьма криво, но об этом потом. При этом возможности вручную экспортнуть это меню нет. Точнее, есть какая-то мутная библиотечка с названием libdbusmenu и полным отсутствием хоть какой-то документации, не говоря уже о биндингах к чему-либо. Этакая проприетарщина наоборот — код открыт, но использовать его толком нельзя ввиду невозможности быстро понять, как с этим вообще работать. Таким образом реализовать в GnomePlatform.cs метод SetGlobalMenu (предусмотренный специально для систем с глобальным меню и реализованный в MacPlatform.cs) не представляется возможным, что ж, придётся разбираться с тем, почему не работает костыль с экспортилкой и придумывать свои костыли, чтобы оно заработало. Я такими извращениями не занимался со времён, когда нужно было заставить работать Навител на разнокалиберных китайских железках с изувеченной до неузнаваемости WinCE 4.2.
Первым делом я убрал костыль с занулением UBUNTU_MENUPROXY, надеясь на то, что все косяки уже починили и всё заработает. Чуда не произошло. Окей, смотрим, есть ли какие-то отладочные инструменты для глобального меню. Нашлась утилитка с названием current-menu-dump, выдавшая весьма интересные результаты: меню таки экспортируется, но его никто не показывает. Объяснения данному феномену на тот момент не нашлось, зато нагуглилась переменная окружения APPMENU_DISPLAY_BOTH, заставляющая экспортилку показывать ещё и нормальное меню. Результаты запуска получились ещё более дивными:
То есть, если навести на пункт меню в нормальном менюбаре, он тут же появляется и в глобальном меню.
Объясняется такое странное поведение сочетанием двух оригинальных технических решений:
- Unity не показывает пункты глобального меню первого уровня без подменю
- MonoDevelop использует «ленивую» загрузку пунктов меню, так что на старте этих подменю нет
Если среда не посылает события показа меню сама, мы сделаем это за неё. На скорую руку лепим <a href=«github.com/kekekeks/monodevelop-appmenu»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
Автор: kekekeks