I need to be able to get the current active Window's app name and page title in Ubuntu 22.04 LTS (with Wayland desktop), no matter what the app is. I'll be implementing it in python, so something friendly to that environment would be wonderful!
The ways that work for me in previous versions of Ubuntu don't seem to work properly in 22.04. The ways that work in other Linux distros also don't seem to work in 22.04.
I've tried the following:
xprop -root _NET_ACTIVE_WINDOW
This gives me great information for Chromium, Firefox, Opera and Brave, but nothing else (not Terminal, System Monitor, Calculator, LibreOffice Writer, etc). Instead, for non-web-browsers, it seems to just return 0.
I've tried the gdbus call here in python:
#!/usr/bin/env python3
import subprocess
if name == "main": while 1 == 1:
print('---------------') print('global.get_window_actors...') app_command = ("gdbus call -e -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval global.get_window_actors\(\)[`gdbus call -e -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval global.get_window_actors\(\).findIndex\(a\=\>a.meta_window.has_focus\(\)===true\) | cut -d\"'\" -f 2`].get_meta_window\(\).get_wm_class\(\)") app_process = subprocess.Popen(app_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) app_retval = app_process.stdout.read() app_retcode = app_process.wait() actorsApp = app_retval.decode('utf-8').strip() print(actorsApp) time.sleep(1)
This just consistently returns
(false, '')
, no matter what app is active.I've tried Wnck, which returns this error:
Wnck-WARNING **: libwnck is designed to work in X11 only, no valid display found
I tried combining these:
xdpyinfo | grep focus xwininfo -root -tree
But just like
_NET_ACTIVE_WINDOW
, these gave me accurate info for web browsers in focus, but not other apps.Looking at
wmctrl -lx
I see the same thing yet again, only web browsers are listed when open, not any other open apps.The closest to success I've come is using
pyatspi
to track accessibility events. I had to specially turn onGNOME_ACCESSIBILITY
in my~/.profile
file to get Firefox to work with it.But once I had it up and running it seems to track everything properly as long as the windows I want tracked are already open first. However, if I open a new app (consistently Chromium, but other apps usually do the same thing too), then
pyatspi
seems to freeze. If I could getpyatspi
to work right, that would be a sufficient solution for me, but with it freezing every time an app is opened, it just won't do. Here is mypyatspi
code.#!/usr/bin/env python3
import pyatspi from datetime import datetime, timedelta
class PyatspiMonitor: app = '' title = '' focusMoment = None eventPrint = ''
def getApplicationTitle(self, appName): print('getApplicationTitle() ' + str(datetime.now())) title = None try: if appName: i = 0 desktopCount = pyatspi.Registry.getDesktopCount() while i < desktopCount: try: desktop = pyatspi.Registry.getDesktop(i) for application in desktop: # While we do nothing with the attr data, it seems important # to grab it for pyatspi to see Chromium correctly try: attrs = str(node.getAttributes()) except: attrs = '' if application and application.name and application.name.lower() == appName.lower(): for node in application: title = node.name break if title: break desktop.setCacheMask(pyatspi.cache.NONE) if title: break except: pass i = i + 1 except Exception as e: print("getApplicationTitle() ERROR: " + str(e)) title = None return title def onEvent(self, e): try: if self.app: appname = "" title = '' try: appname = str(e.host_application.name) except: appname = "" # Make sure we don't override a valuable onFocus # event with stuff that's less valuable oneSecondAgo = datetime.now() - timedelta(seconds=1) if (self.focusMoment and self.focusMoment < oneSecondAgo) or (not self.focusMoment): if appname and appname.lower() == self.app.lower(): # This event is from the focused app try: title = str(e.source_name) except: title = '' if not title: # See if there's a meaningful change to the title of the active app # since its last onFocus event title = self.getApplicationTitle(self.app) if title: self.focusMoment = datetime.now() self.title = title toPrint = 'onEvent() RESULT: ' + self.app + ' - ' + self.title if self.eventPrint != toPrint: self.eventPrint = toPrint print(toPrint) except Exception as e: print("onEvent() ERROR: " + str(e)) pass def onFocus(self, e): try: # detail1 = 1 means this app received focus. # detail1 = 0 means focus left this app. if e.detail1: appname = "" try: appname = str(e.host_application.name) except: appname = "" if appname and appname.lower() != 'gnome-shell': self.focusMoment = datetime.now() self.app = appname try: title = str(e.source_name) except: title = None if not title: title = self.getApplicationTitle(appname) if not title: title = self.app self.title = title print('onFocus() RESULT: ' + self.app + ' - ' + self.title) except Exception as e: print("onFocus() ERROR: " + str(e)) pass def startMonitoring(self): try: print('startMonitoring()') pyatspi.Registry.registerEventListener(self.onFocus, "object:state-changed:focused") pyatspi.Registry.registerEventListener(self.onFocus, "object:state-changed:active") pyatspi.Registry.registerEventListener(self.onEvent, "object") pyatspi.Registry.start() except Exception as e: print("startMonitoring() ERROR: " + str(e)) pass
if name == "main": pyatspiMonitor = PyatspiMonitor() pyatspiMonitor.startMonitoring()
So, again, my question is, how can I find out the app name and title of the currently active window in Ubuntu 22.04?
Thanks in advance!
#ubuntu-next
channel in Ubuntu IRC – cocomac Apr 15 '22 at 21:40