Skip to content

Instantly share code, notes, and snippets.

@snippins
Last active May 26, 2017 18:49
Show Gist options
  • Save snippins/255db0c804a2a81815ad484909ea241c to your computer and use it in GitHub Desktop.
Save snippins/255db0c804a2a81815ad484909ea241c to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
from __future__ import print_function
import re
import signal
import subprocess
import sys
import psutil
from gi.repository import Gio, Gtk, GLib
from Xlib import display, protocol, X, Xatom
class EWMH:
"""This class provides the ability to get and set properties defined
by the EWMH spec. It was blanty ripped out of pyewmh
* https://github.com/parkouss/pyewmh
"""
def __init__(self, _display=None, root = None):
self.display = _display or display.Display()
self.root = root or self.display.screen().root
def getActiveWindow(self):
"""Get the current active (toplevel) window or None (property _NET_ACTIVE_WINDOW)
:return: Window object or None"""
active_window = self._getProperty('_NET_ACTIVE_WINDOW')
if active_window == None:
return None
return self._createWindow(active_window[0])
def _getProperty(self, _type, win=None):
if not win:
win = self.root
atom = win.get_full_property(self.display.get_atom(_type), X.AnyPropertyType)
if atom:
return atom.value
def _setProperty(self, _type, data, win=None, mask=None):
"""Send a ClientMessage event to the root window"""
if not win:
win = self.root
if type(data) is str:
dataSize = 8
else:
data = (data+[0]*(5-len(data)))[:5]
dataSize = 32
ev = protocol.event.ClientMessage(window=win, client_type=self.display.get_atom(_type), data=(dataSize, data))
if not mask:
mask = (X.SubstructureRedirectMask|X.SubstructureNotifyMask)
self.root.send_event(ev, event_mask=mask)
def _createWindow(self, wId):
if not wId:
return None
return self.display.create_resource_object('window', wId)
ewmh = EWMH()
win = ewmh.getActiveWindow()
window_id = hex(ewmh._getProperty('_NET_ACTIVE_WINDOW')[0])
window_pid = ewmh._getProperty('_NET_WM_PID', win)[0]
prompt = psutil.Process(window_pid).name() + ': '
gtk_bus_name = ewmh._getProperty('_GTK_UNIQUE_BUS_NAME', win)
gtk_menu_object_path = ewmh._getProperty('_GTK_MENUBAR_OBJECT_PATH', win)
gtk_app_object_path = ewmh._getProperty('_GTK_APPLICATION_OBJECT_PATH', win)
# Workaround Ctrl+C not working with gio-gtk3
signal.signal(signal.SIGINT, signal.SIG_DFL)
bus = Gio.bus_get_sync(Gio.BusType.SESSION)
menus = Gio.DBusMenuModel.get(bus, gtk_bus_name,
gtk_menu_object_path)
menus_ref = [menus]
n_items = -1
def iterate_menus(menus, level=0):
global menus_ref
print(level*"\t","callback,",menus," menusize: ",menus.get_n_items())
for i in range(menus.get_n_items()):
miter = menus.iterate_item_attributes(i)
while miter.next():
print(level*"\t","attr:",miter.get_name()," = ",miter.get_value())
miter = menus.iterate_item_links(i)
while miter.next():
menu = miter.get_value()
print(level*"\t","link:",miter.get_name()," = ",menu)
menus_ref.append(menu)
menu.connect("items-changed", on_items_changed, level+1)
menu.get_n_items()
def on_items_changed(menus, position, removed, added, level=0):
iterate_menus(menus, level)
menus.connect("items-changed", on_items_changed)
menus.get_n_items()
mainLoop = GLib.MainLoop.new(None, False).run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment