3

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.

  1. 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.

  2. 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.

  3. I've tried Wnck, which returns this error:

    Wnck-WARNING **: libwnck is designed to work in X11 only, no valid display found
    
  4. 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.

  5. Looking at wmctrl -lx I see the same thing yet again, only web browsers are listed when open, not any other open apps.

  6. The closest to success I've come is using pyatspi to track accessibility events. I had to specially turn on GNOME_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 get pyatspi 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 my pyatspi 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!

muru
  • 197,895
  • 55
  • 485
  • 740
gcdev
  • 139
  • 2
    Ubuntu 22.04 has not been released yet, and is not supported here. However, check if switching to the X.Org session helps. – Archisman Panigrahi Apr 15 '22 at 20:02
  • 3
    The problem doesn't exist in 22-X.Org. It only exists in 22-Wayland. Still in need of a solution, ideally BEFORE 22 is released, so that my customers don't get angry when they move to 22 and my software breaks. – gcdev Apr 15 '22 at 20:49
  • 2
    @gcdev I get that you need a solution, but 22.04 isn't supported on Ask Ubuntu until it releases. You could try the #ubuntu-next channel in Ubuntu IRC – cocomac Apr 15 '22 at 21:40
  • The release date refers to ISO release date for new installs; no upgrades are offered for existing users. The gates open for 21.10 users to upgrade first, with the gates for 20.04 users not planned to be opened for months (that doesn't occur until after 22.04.1's release). You still have months if your customers are using a LTS release. Also 22 is a different product to 22.04; Ubuntu Core 22 comes out much later than Ubuntu 22.04 LTS on which it is based; again months. – guiverc Apr 15 '22 at 23:18
  • Ubuntu 22.04 doesn't yet exist; it's currently the development release Ubuntu jammy and remains that until it reaches RC state which isn't expected until after 14 April 2022, and isn't on-topic here until release on 21 April 2022. https://discourse.ubuntu.com/t/jammy-jellyfish-release-schedule/23906 Please refer https://askubuntu.com/help/on-topic. For support issues with Ubuntu jammy you'll need to use a #ubuntu-next or #ubuntu+1 site (IRC, UF etc) – guiverc Apr 15 '22 at 23:18
  • If you wish to report bugs, firstly thank you for helping test the release, but please see https://help.ubuntu.com/community/ReportingBugs and use a #ubuntu+1 site such as IRC, https://ubuntuforums.org/ etc. This site isn't tracked for ubuntu+1 or #ubuntu-next issues – guiverc Apr 15 '22 at 23:19
  • 1
    Highly interesting question, though. Please repost on 21 april. Yes, this is Wayland making such things very difficult. – vanadium Apr 16 '22 at 08:38
  • 1
    Has anyone found a solution yet? Is one of the solutions working again? – Silve2611 Jun 24 '22 at 12:53

0 Answers0