如何获取 Ubuntu 22.04 中的当前活动窗口?

如何获取 Ubuntu 22.04 中的当前活动窗口?

我需要能够在 Ubuntu 22.04 LTS(带有 Wayland 桌面)中获取当前活动窗口的应用程序名称和页面标题,无论应用程序是什么。我将使用 Python 实现它,因此对该环境友好的东西会很棒!

在 Ubuntu 的早期版本中对我有用的方法似乎在 22.04 中不起作用。在其他 Linux 发行版中有效的方法似乎在 22.04 中也不起作用。

  1. 我尝试了以下方法:

    xprop -root _NET_ACTIVE_WINDOW
    

    这为我提供了有关 Chromium、Firefox、Opera 和 Brave 的大量信息,但没有其他信息(不是终端、系统监视器、计算器、LibreOffice Writer 等)。相反,对于非 Web 浏览器,它似乎只返回 0。

  2. 我已经尝试过 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, '')无论哪个应用程序处于活动状态,这都会持续返回。

  3. 我尝试过 Wnck,它返回此错误:

    Wnck-WARNING **: libwnck is designed to work in X11 only, no valid display found
    
  4. 我尝试将它们结合起来:

     xdpyinfo | grep focus
     xwininfo -root -tree
    

    但就像_NET_ACTIVE_WINDOW,这些为我提供了焦点网络浏览器的准确信息,但没有为其他应用程序提供准确信息。

  5. wmctrl -lx我再次看到同样的事情,打开时只列出网络浏览器,没有列出任何其他打开的应用程序。

  6. 我最接近成功的是使用它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 中找出当前活动窗口的应用程序名称和标题?

提前致谢!

相关内容