任意の gtk.Widget を appindicator.Indicator に配置する

任意の gtk.Widget を appindicator.Indicator に配置する

gtk.Menu 内に gtk.Widget を配置することは、最初に空の gtk.MenuItem を配置することで、ある程度機能します。信頼性は高くないようです - しかし、基本的には機能します。appindicator.Indicator では機能しません。エントリは空のままです。たとえば、child[border_size] を 32 に設定しても、同じです。

動作する唯一のウィジェットは gtk.Label (もちろん MenuItem、ImageMenuItem など) です。

これで、Me メニューに gtk.Entry が追加されたので、これを適切に実行できるはずです。どうすればいいでしょうか?

私が何を言っているのかを説明するサンプルコードを以下に示します。

    self.item = gtk.MenuItem()
    self.item.add(gtk.Label("hello world!"))
    self.menu.append(self.item)

上記のコードは機能しますが、次のコードは機能しません:

    self.item = gtk.MenuItem()
    self.item.add(gtk.Entry())
    self.menu.append(self.item)

self.menu が appindicator.Indicator である場合、gtk.Menu であれば、少なくとも Entry が表示されます。

実際に動作するコードを以下に示します。

import gtk
import appindicator

class AppIndicator (object):

    def __init__(self):
        self.ind = appindicator.Indicator("hello world client",
            "distributor-logo", appindicator.CATEGORY_APPLICATION_STATUS)
        self.ind.set_status (appindicator.STATUS_ACTIVE)
        self.menu = gtk.Menu()
        item = gtk.MenuItem()

        item.add(gtk.Label("hello world"))
        # item.add(gtk.Entry())

        self.menu.append(item)
        self.menu.show_all()
        self.ind.set_menu(self.menu)


indicator = AppIndicator()
gtk.main()

答え1

アプリケーション インジケーター メニューのサポートは D-Bus メニューに基づいていますが、サポート内容は限られています。つまり、基本的なメニュー機能のみがサポートされ、任意のウィジェットなどの特殊な機能はサポートされません。

このような機能をサポートするための大きな障害の 1 つは、アプリケーション インジケーター メニューが別のプロセス (アプリケーション インジケーター プロセス) によってレンダリングされるため、プログラムが直接そこに何かを描画できないことです。この問題を解決するには、D-Bus メニューで X-Embed のようなものをサポートするか、GTK のすべてが D-Bus 上で動作できるようにする必要があります。

答え2

Ubuntu のサウンド インジケーターには音量のスライダーがありますが、それがどのように可能なのか不思議に思いました。コードを調べてみると、一方で dbus 経由で入力できる GtkMenus があるようです。 https://developer.ubuntu.com/api/devel/ubuntu-12.04/c/dbusmenugtk/index.html

しかし、使い方がわかりません。pavucontrol と同じように、アプリごとに音量を制御できるサウンド インジケーターを作成したいと考えていました。

関連情報