簡體   English   中英

Linux上C++如何實現全局菜單支持?

[英]How to implement global menu support in C++ on Linux?

我正在 C++ 開發跨平台應用程序。我們有一個菜單,它使用 macOS 上的全局菜單。 我希望在所有擁有它的平台上使用系統提供的全局菜單。 KDE 有一個全局菜單,下面是一個顯示 VS Code 菜單的例子:

我如何在 C++ 中實現它? 我聽說這可以使用 dbus 來完成,但我不知道該怎么做,要包含哪些標頭,要調用什么方法等。這個問題的一個很好的答案將包括指向描述如何使用的文檔的鏈接Linux 上的全局菜單 API,一個很好的答案將包含一個示例。

全局菜單是客戶端應用程序和服務器應用程序之間的折衷方案,兩者必須事先就菜單是什么以及如何以序列化方式表示菜單達成一致。

在 Linux 中,不難猜到,處理全局菜單信息沒有單一的約定,不過幸運的是目前只有兩種協議可以使用。 其中一個協議由 Qt 工具包實現,另一個由 Gtk 工具包實現。

兩者都使用 DBus 作為應用程序之間的通信方式,但協議完全不同並且都是動態的,因此每次客戶端應用程序中的菜單更改時都需要更新周期。

我認為最值得注意的是 Qt 的協議使用菜單項標識符,而 Gtk 的不使用,因此使用 Qt 的實現,您可以從一個更新周期到下一個更新周期重用一些菜單項,而使用 Gtk 實現,即使項目不會改變,您需要重新創建它們。

實際上,您可以擁有一個 Qt 應用程序並使用 Gtk 協議,或者您可以擁有一個 Gtk 應用程序並使用 Qt 協議。 但這只有在您以最基本和最原始的形式使用協議時才有可能,因為正如預期的那樣,工具包會在基本協議之上創建抽象層,以簡化用戶的工作,然后如果您打算使用這些抽象層,因為如果您需要一勞永逸地定義您的工具包是什么,而您在問題中還沒有這樣做。

這兩個協議都可以分解為兩個基本任務,第一個任務是從客戶端應用程序(或依賴客戶端應用程序的工具包,如果已經有的話)實現菜單提供程序(DBus)服務,第二部分包括通知到提供菜單的服務所在的服務器應用程序(使用全局菜單的應用程序)。

由於服務器應用程序默認為 windows 管理器,因此每個 window 共享其菜單服務位置的協議可以 go 來自每個客戶端注冊其菜單的另一個 DBUS 服務,將服務所在的路徑傳遞給 windows 管理器直接地。

這里問題又復雜了,因為 X11 的協議是基於每個 window 的xid ,而在 Wayland 中沒有傳遞菜單數據的標准方法,例如在 Gtk 中,您必須直接調用 window 管理器的 function . 來自 GDK 后端 ( https://gitlab.gnome.org/rmader/gtk/-/blob/16ac1a12fc93000124050bc4ee56a10374865d14/gdk/wayland/gdkwindow-wayland.c#L5016 )。

我只想提一下 Qt 的情況,其中在應用程序注冊菜單的地方使用了 window 管理器的外部接口。 此 DBus 服務是com.canonical.AppMenu.Registrar的服務: https://github.com/KDE/appmenu-runner/blob/master/src/com.canonical.AppMenu.Registrar.xml服務實現的示例可以可以在這里找到: https://github.com/SeptemberHX/dde-globalmenu-service

關於兩個菜單服務:

對於 Gtk 你可以檢查: https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI https://developer-old.gnome.org/gio/stable/gio-GMenuModel-exporter.html

對於Qt你可以查看: https://lazka.github.io/pgi-docs/Dbusmenu-0.4/index.html

這里有更多信息可以參考: https://hellosystem.github.io/docs/developer/menu.html

這也是如何在 gtk 應用程序中導出菜單欄的示例: https://developer-old.gnome.org/gtk4/stable/GtkApplicationWindow.html

不幸的是,在 Linux 中,很少有開發人員嘗試自己提供全局菜單,這意味着要擁有一個全局菜單,所做的就是使用與此類似的技術來破解應用程序: https://linuxhint.com/what-is -ld-library-path/並將代碼插入其中以將 window 小部件菜單轉換為序列化菜單,然后可以使用上述技術將其導出到 DBus。

所有這一切的好處是,理論上你不必做任何奇怪的事情來導出菜單,因為理論上你只需要提供一個菜單欄和已經制作的模塊來破解應用程序並導出菜單會處理其他一切。

模塊示例:

其他一些模塊已經集成到工具包中: https://codereview.qt-project.org/c/qt/qtbase/+/146234/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM