188 lines
5.6 KiB
Python
188 lines
5.6 KiB
Python
#!/usr/bin/env python
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import traceback
|
|
|
|
import dbus
|
|
import dbus.service
|
|
from dbus.mainloop.glib import DBusGMainLoop
|
|
from gi.repository import GLib
|
|
|
|
|
|
ITEM_PATH = "/StatusNotifierItem"
|
|
MENU_PATH = "/StatusNotifierItem/Menu"
|
|
|
|
|
|
def variant(value):
|
|
return dbus.Variant(value)
|
|
|
|
|
|
class StatusNotifierItem(dbus.service.Object):
|
|
def __init__(self, bus):
|
|
super().__init__(bus, ITEM_PATH)
|
|
|
|
@dbus.service.method("org.freedesktop.DBus.Properties", in_signature="ss", out_signature="v")
|
|
def Get(self, interface, prop):
|
|
return variant(self.GetAll(interface)[prop])
|
|
|
|
@dbus.service.method("org.freedesktop.DBus.Properties", in_signature="s", out_signature="a{sv}")
|
|
def GetAll(self, interface):
|
|
if interface != "org.kde.StatusNotifierItem":
|
|
return {}
|
|
|
|
return dbus.Dictionary({
|
|
"Category": "ApplicationStatus",
|
|
"Id": "omarchy-test-tray",
|
|
"Title": "omarchy-test-tray",
|
|
"Status": "Active",
|
|
"WindowId": dbus.Int32(0),
|
|
"IconName": "dialog-information",
|
|
"IconThemePath": "",
|
|
"Menu": dbus.ObjectPath(MENU_PATH),
|
|
"ItemIsMenu": dbus.Boolean(False),
|
|
"ToolTip": dbus.Struct((
|
|
"",
|
|
dbus.Array([], signature="(iiay)"),
|
|
"omarchy-test-tray",
|
|
"",
|
|
), signature=None),
|
|
}, signature="sv")
|
|
|
|
@dbus.service.method("org.freedesktop.DBus.Properties", in_signature="ssv")
|
|
def Set(self, interface, prop, value):
|
|
return
|
|
|
|
@dbus.service.method("org.kde.StatusNotifierItem", in_signature="ii")
|
|
def ContextMenu(self, x, y):
|
|
return
|
|
|
|
@dbus.service.method("org.kde.StatusNotifierItem", in_signature="ii")
|
|
def Activate(self, x, y):
|
|
return
|
|
|
|
@dbus.service.method("org.kde.StatusNotifierItem", in_signature="ii")
|
|
def SecondaryActivate(self, x, y):
|
|
return
|
|
|
|
@dbus.service.method("org.kde.StatusNotifierItem", in_signature="is")
|
|
def Scroll(self, delta, orientation):
|
|
return
|
|
|
|
|
|
class DBusMenu(dbus.service.Object):
|
|
def __init__(self, bus, event_path):
|
|
super().__init__(bus, MENU_PATH)
|
|
self.event_path = event_path
|
|
|
|
@dbus.service.method("org.freedesktop.DBus.Properties", in_signature="ss", out_signature="v")
|
|
def Get(self, interface, prop):
|
|
return variant(self.GetAll(interface)[prop])
|
|
|
|
@dbus.service.method("org.freedesktop.DBus.Properties", in_signature="s", out_signature="a{sv}")
|
|
def GetAll(self, interface):
|
|
if interface != "com.canonical.dbusmenu":
|
|
return {}
|
|
return dbus.Dictionary({
|
|
"Version": dbus.UInt32(3),
|
|
"TextDirection": "ltr",
|
|
"Status": "normal",
|
|
"IconThemePath": dbus.Array([], signature="s"),
|
|
}, signature="sv")
|
|
|
|
@dbus.service.method("org.freedesktop.DBus.Properties", in_signature="ssv")
|
|
def Set(self, interface, prop, value):
|
|
return
|
|
|
|
@dbus.service.method("com.canonical.dbusmenu", in_signature="i", out_signature="b")
|
|
def AboutToShow(self, item_id):
|
|
return False
|
|
|
|
@dbus.service.method("com.canonical.dbusmenu", in_signature="ai", out_signature="aiai")
|
|
def AboutToShowGroup(self, item_ids):
|
|
return ([], [])
|
|
|
|
@dbus.service.method("com.canonical.dbusmenu", in_signature="iias", out_signature="u(ia{sv}av)")
|
|
def GetLayout(self, parent_id, recursion_depth, property_names):
|
|
print("GetLayout", int(parent_id), int(recursion_depth), list(property_names), flush=True)
|
|
child = (
|
|
dbus.Int32(2),
|
|
dbus.Dictionary({"label": "Sign in", "enabled": True}, signature="sv"),
|
|
dbus.Array([], signature="v"),
|
|
)
|
|
root = (
|
|
dbus.Int32(0),
|
|
dbus.Dictionary({"children-display": "submenu"}, signature="sv"),
|
|
dbus.Array([dbus.Struct(child, signature=None, variant_level=1)], signature="v"),
|
|
)
|
|
return (dbus.UInt32(1), dbus.Struct(root, signature=None))
|
|
|
|
@dbus.service.method("com.canonical.dbusmenu", in_signature="aias", out_signature="a(ia{sv})")
|
|
def GetGroupProperties(self, item_ids, property_names):
|
|
return []
|
|
|
|
@dbus.service.method("com.canonical.dbusmenu", in_signature="is", out_signature="v")
|
|
def GetProperty(self, item_id, name):
|
|
return variant("")
|
|
|
|
@dbus.service.method("com.canonical.dbusmenu", in_signature="isvu")
|
|
def Event(self, item_id, event_id, data, timestamp):
|
|
print("Event", int(item_id), str(event_id), flush=True)
|
|
if int(item_id) == 2 and str(event_id) == "clicked":
|
|
with open(self.event_path, "w", encoding="utf-8") as handle:
|
|
handle.write("clicked\n")
|
|
|
|
@dbus.service.method("com.canonical.dbusmenu", in_signature="a(isvu)", out_signature="ai")
|
|
def EventGroup(self, events):
|
|
for item_id, event_id, data, timestamp in events:
|
|
self.Event(item_id, event_id, data, timestamp)
|
|
return []
|
|
|
|
|
|
def register_with_watcher(bus):
|
|
watcher = dbus.Interface(
|
|
bus.get_object("org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher"),
|
|
"org.kde.StatusNotifierWatcher",
|
|
)
|
|
watcher.RegisterStatusNotifierItem(ITEM_PATH)
|
|
|
|
|
|
def main():
|
|
try:
|
|
return run()
|
|
except Exception:
|
|
traceback.print_exc()
|
|
return 1
|
|
|
|
|
|
def run():
|
|
event_path = os.environ["OMARCHY_TRAY_MENU_EVENT_RESULT"]
|
|
ready_path = os.environ["OMARCHY_TRAY_MENU_READY"]
|
|
|
|
DBusGMainLoop(set_as_default=True)
|
|
bus = dbus.SessionBus()
|
|
dbus.service.BusName("org.omarchy.TestStatusNotifier", bus)
|
|
|
|
StatusNotifierItem(bus)
|
|
DBusMenu(bus, event_path)
|
|
|
|
for _ in range(50):
|
|
try:
|
|
register_with_watcher(bus)
|
|
with open(ready_path, "w", encoding="utf-8") as handle:
|
|
handle.write("ready\n")
|
|
break
|
|
except dbus.DBusException:
|
|
time.sleep(0.1)
|
|
else:
|
|
print("timed out registering StatusNotifierItem", file=sys.stderr)
|
|
return 1
|
|
|
|
GLib.MainLoop().run()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|