45

In 2010 Stefano Palazzo , asked a related question, Putting an arbitrary gtk.Widget into an appindicator.Indicator, and similar one was asked on StackOverflow. In both cases the consensus is that Ubuntu's App Indicators are limited. As Michael Ekstrand put it:

The Application Indicator menu support is based on D-Bus menus, which are limited in what they support - they only support basic menu functionality, not more exotic things such as arbitrary widgets.

However, it contradicts what we see in Bluetooth indicator today, in 2016: it uses toggle switches.

enter image description here

Same could be observed with Ubuntu One indicator from 13.04:

enter image description here

So obviously there is a way. I've studied indicator-bluetooth source code, but it's written in Vala. I,however, work primarily in python, and learning Vala just to rewrite all of my already existing indicators is a bit too much work.

So the core of the question : How can one use Gtk.Widgets, or at the very minimum a toggle switch just like in the Bluetooth indicator, using Python ?

NOTE: I am willing to put bounty on this question to reward an answer which will provide a working example in python. Other languages are not accepted.

Sergiy Kolodyazhnyy
  • 103,293
  • 19
  • 273
  • 492
  • 6
    Application indicator is limited even does not support icon on the fly (it just loads image file from filesystem). Those indicators you have mentioned are SYSTEM indicators (bluetooth, ubuntu one, sound, power ,...). They are different and they are not using libappindicator. I have already posted few posts that may help clarify the difference . I already got a system indicator working using C. but in python i'm still struggling. – user.dz Oct 03 '16 at 08:57
  • 2
    Is there a way to attract the attention of the Ubuntu core devs to this question? – don.joey Oct 04 '16 at 11:55
  • @don.joey I don't think there is and Ubuntu core devs aren't the people to ask. The menus are passed via DBus Menu API , which means the devs of that API would be more appropriate people to ask – Sergiy Kolodyazhnyy Oct 04 '16 at 20:12
  • 1
    At least `test = Gtk.CheckMenuItem("Monkey")` works adding a checkbutton, but there should be more. While that one works, this one *should* work, but doesn't: `Gtk.CheckMenuItemToggled("Monkey")`. I am pretty sure it can work anyhow. See: https://developer.gnome.org/gtk3/stable/GtkCheckMenuItem.html – Jacob Vlijm Oct 08 '16 at 17:11
  • 1
    @JacobVlijm yes, adding any single menuitem works, it also works to add a Gtk.Box and add Gtk.Label to that box, but nothing else( it says the widget can contain only one item. – Sergiy Kolodyazhnyy Oct 08 '16 at 17:21
  • Yeah, tried adding a box, works fine, but "normal" gui widgets are refused. It should also support a menu item with a toggle button. Not the GUI one, but a menu version. – Jacob Vlijm Oct 08 '16 at 17:27
  • Yup, check menuitem , radio menuitem, image menuitem - those 3 all work. Other widgets don't. I found one AskUbuntu answer, where OP contacted DBusMenu developers and they said it was planned to add support for other widgets. That was from 2011, so i hope something changed. – Sergiy Kolodyazhnyy Oct 08 '16 at 17:53
  • 1
    `Gtk.ImageMenuItem` is deprecated and discouraged to use btw: https://developer.gnome.org/gtkmm/stable/deprecated.html – Jacob Vlijm Oct 09 '16 at 07:56
  • Hi Serg, not an answer, but looking around, from more than one source, it seems that the policy on Gtk menus is more towards having a "pure", sobre menu, no widgets, no icons. The (little) options we had in the past are either gone, deprecated or discouraged otherwise. I don't believe we will find a working answer. Even less likely in future. – Jacob Vlijm Oct 11 '16 at 16:24
  • Also be careful to be specific to Unity7 or Unity8 since they are different in how they seem to support/expose widget capabilities. – Kristopher Ives Nov 27 '16 at 14:11
  • @SergiyKolodyazhnyy, I just knows about someone who forked my c system indicator template and created a system indicator with slider same as Canonical indicator (They use some DBus tricks). Here is the repo: https://github.com/okaresz/ScreenToolsSysIndicator , check the code around this `g_menu_item_set_attribute(brightnessItem, "x-canonical-type", "s", "com.canonical.unity.slider")` where he added the slider item. As I understand it, canonical made other components same way, but they are used internally, no public API or doc. – user.dz May 22 '17 at 10:23

1 Answers1

3

This problem exists because while AppIndicators make it easy to create an indicator menu, they do get in the way of making one. Let's look at the differences between example python code using AppIndicator and one using GLib Menus the way the Bluetooth code does.

Firstly you're instructed to make a gtk.Menu, these are old style Gtk menu objects that use Gtk.Action that are now deprecated. AppIndicator takes the gtk.Menu object from you during the set_menu(...) process and parses it, pushing each of the menus it finds onto the indicator service created using libdbusmenu. This process of parsing means that anything not supported by AppIndicator is filtered out, no matter what you do.

Next let's look at the Bluetooth menu. That's created using Gio.Menu objects, these are new style Gnome menus using the GAction system. It then registered it's own service without using AppIndicator or libdbusmenu and set's it's up using a custom x-canonical-type property to create the switch widget which is passed to libido for parsing.

This whole exercise is pretty bad, since it's all Canonical's own Unity customisations. So as soon as unity goes, there's no appindicators anyway.

Martin Owens -doctormo-
  • 19,860
  • 4
  • 63
  • 103
  • Following up on this (great) answer, Unity is now replaced with gnome, but `AppIndicator3` does work in Gnome (although it's a new lib called `AyatanaAppIndicator3`, it seems to be a drop in replacement). – Frug Dec 22 '22 at 03:10