我需要能够在 Ubuntu 22.04 LTS(带有 Wayland 桌面)中获取当前活动窗口的应用程序名称和页面标题,无论应用程序是什么。我将使用 Python 实现它,因此对该环境友好的东西会很棒!
在 Ubuntu 的早期版本中对我有用的方法似乎在 22.04 中不起作用。在其他 Linux 发行版中有效的方法似乎在 22.04 中也不起作用。
我尝试了以下方法:
xprop -root _NET_ACTIVE_WINDOW
这为我提供了有关 Chromium、Firefox、Opera 和 Brave 的大量信息,但没有其他信息(不是终端、系统监视器、计算器、LibreOffice Writer 等)。相反,对于非 Web 浏览器,它似乎只返回 0。
我已经尝试过 gdbus 调用这里在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)
(false, '')
无论哪个应用程序处于活动状态,这都会持续返回。我尝试过 Wnck,它返回此错误:
Wnck-WARNING **: libwnck is designed to work in X11 only, no valid display found
我尝试将它们结合起来:
xdpyinfo | grep focus xwininfo -root -tree
但就像
_NET_ACTIVE_WINDOW
,这些为我提供了焦点网络浏览器的准确信息,但没有为其他应用程序提供准确信息。wmctrl -lx
我再次看到同样的事情,打开时只列出网络浏览器,没有列出任何其他打开的应用程序。我最接近成功的是使用它
pyatspi
来跟踪辅助功能事件。我必须GNOME_ACCESSIBILITY
在我的~/.profile
文件中专门打开它才能让 Firefox 使用它。但一旦我启动并运行它,它似乎可以正确地跟踪一切只要我想要跟踪的窗口已经打开。但是,如果我打开一个新应用程序(始终是 Chromium,但其他应用程序通常也会这样做),它
pyatspi
似乎会冻结。如果我能pyatspi
正常工作,那对我来说就足够了,但是每次打开应用程序时它都会冻结,这根本行不通。这是我的pyatspi
代码。#!/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()
所以,我的问题是,如何在 Ubuntu 22.04 中找出当前活动窗口的应用程序名称和标题?
提前致谢!