- How to get current active window in Ubuntu 22.04?
- 1 Answer 1
- You must log in to answer this question.
- Linked
- Related
- Hot Network Questions
- Subscribe to RSS
- Get the process of the active window with Python in Linux
- 2 Answers 2
- How to get the current active window in Ubuntu 22.04? [closed]
- How do I get the active window on Gnome Wayland?
How to get current active window in Ubuntu 22.04?
Since Ubuntu 22.04 was released, this question is normal now.
I am writing a shell script which needs to get current active window name, so after searching for a tool for it, I decided to use xdotool.
But when I launch the terminal or settings, xdotool getwindowfocus getwindowname throws an error:
xdo_get_focused_window_sane failed (code=1)
xdo_focus_window reported an error
So how can I fix this error or how do I can get a current active window name?
1 Answer 1
xdotool only works for the Xorg display manager, not Wayland, and Wayland is default in Ubuntu 22.04. There is no equivalent way of selecting the focused window in Wayland. Your best bet if you need this functionality would be to switch to using Xorg and then the method you used to use will work.
If you want to stick with Wayland and are ok with digging rather deep to figure this out, you can use your window manager or compositor’s method of getting open windows. This is not portable across WMs, and isn’t possible in all situations. See this question about Gnome were it isn’t really possible at all.
You must log in to answer this question.
Linked
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.12.43529
Ubuntu and the circle of friends logo are trade marks of Canonical Limited and are used under licence.
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
Get the process of the active window with Python in Linux
However, I’m also interested in the name of the process (firefox, rstudio. ) that controls the window. Any ideas on how to proceed?
Some window names of course contain the process name as well, but no all (e.g. the Terminal). Also, my code does not find all window names (e.g. RStudio) either.
2 Answers 2
Take a look a this answer. It uses a command line tool called xprop and one called wmctrl to get the PID of the active window. Once you have the PID, you can get just about any info you want about the process. For example, to get the name of the process, you can execute the following command with the python subprocess module:
The above will give you the command’s name while this:
Will give you the commands full path.
Thank you @AnttiHaapala and @Steampunkery for the tips. Based on them I managed to revise my original code into an answer.
With xprop -root I get the window_id :
root = Popen( ['xprop', '-root', '_NET_ACTIVE_WINDOW'], stdout = PIPE ) stdout, stderr = root.communicate() m = re.search( b'^_NET_ACTIVE_WINDOW.* ([\w]+)$', stdout ) window_id = m.group( 1 )
Using the window_id , with xprop -id , I get the window name ( «WM_NAME» ):
window = Popen( ['xprop', '-id', window_id, 'WM_NAME'], stdout = PIPE ) stdout, stderr = window.communicate() wmatch = re.match( b'WM_NAME\(\w+\) = (?P.+)$', stdout ) windowname = wmatch.group( 'name' ).decode( 'UTF-8' ).strip( '"' )
as well as the names for the process ( «WM_CLASS» ):
processname1, processname2 = None, None process = Popen( ['xprop', '-id', window_id, 'WM_CLASS'], stdout = PIPE ) stdout, stderr = process.communicate() pmatch = re.match( b'WM_CLASS\(\w+\) = (?P.+)$', stdout ) processname1, processname2 = pmatch.group( 'name' ).decode( 'UTF-8' ).split( ', ' )
The complete code with some error checking etc.:
import os, re, sys, time from subprocess import PIPE, Popen def get_activityname(): root = Popen( ['xprop', '-root', '_NET_ACTIVE_WINDOW'], stdout = PIPE ) stdout, stderr = root.communicate() m = re.search( b'^_NET_ACTIVE_WINDOW.* ([\w]+)$', stdout ) if m is not None: window_id = m.group( 1 ) windowname = None window = Popen( ['xprop', '-id', window_id, 'WM_NAME'], stdout = PIPE ) stdout, stderr = window.communicate() wmatch = re.match( b'WM_NAME\(\w+\) = (?P.+)$', stdout ) if wmatch is not None: windowname = wmatch.group( 'name' ).decode( 'UTF-8' ).strip( '"' ) processname1, processname2 = None, None process = Popen( ['xprop', '-id', window_id, 'WM_CLASS'], stdout = PIPE ) stdout, stderr = process.communicate() pmatch = re.match( b'WM_CLASS\(\w+\) = (?P.+)$', stdout ) if pmatch is not None: processname1, processname2 = pmatch.group( 'name' ).decode( 'UTF-8' ).split( ', ' ) processname1 = processname1.strip( '"' ) processname2 = processname2.strip( '"' ) return < 'windowname': windowname, 'processname1': processname1, 'processname2': processname2 >return < 'windowname': None, 'processname1': None, 'processname2': None >if __name__ == '__main__': a = get_activityname() print( ''' 'windowname': %s, 'processname1': %s, 'processname2': %s ''' % ( a['windowname'], a['processname1'], a['processname2'] ) )
This should return the names for the window as well as the controlling process. It is able to fetch even the process name for RStudio which, for some reason, doesn’t have a window name ( «WM_NAME» ).
How to get the current active window in Ubuntu 22.04? [closed]
Bug reports and problems specific to development version of Ubuntu should be reported on Launchpad so that developers can see, track and fix these issues.
xprop -root _NET_ACTIVE_WINDOW
#!/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)
Wnck-WARNING **: libwnck is designed to work in X11 only, no valid display found
xdpyinfo | grep focus xwininfo -root -tree
#!/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?
How do I get the active window on Gnome Wayland?
There are other applications like ActivityWatch that would require the same functionality (RescueTime, arbtt, selfspy, etc.), they don't seem to support Wayland right now and I can't find any details about them planning to do so.
I'm now interested in implementing support for Gnome to start off with and follow up with others as the path becomes more clear.
A similar question concerning Weston has been asked here: get the list of active windows in wayland weston
Edit: I asked in #wayland on Freenode, got the following reply:
15:20:44 ErikBjare Hello everybody. I'm working on a piece of self-tracking software called ActivityWatch (https://github.com/ActivityWatch/activitywatch). I know this isn't exactly the right place to ask, but I was wondering if anyone knew anything about getting the active window in any Wayland-using DE. 15:20:57 ErikBjare Created a question on SO: https://stackoverflow.com/questions/45465016/how-do-i-get-the-active-window-on-gnome-wayland 15:21:25 ErikBjare Here's the issue in my repo for it: https://github.com/ActivityWatch/activitywatch/issues/92 15:22:54 ErikBjare There are a bunch of other applications that depend on it (RescueTime, selfspy, arbtt, ulogme, etc.) so they'd need it as well 15:24:23 blocage ErikBjare, in the core protocol you cannot know which windnow has the keyboard or cursor focus 15:24:39 blocage ErikBjare, in the wayland core protocol * 15:25:10 blocage ErikBjare, you can just know if your window has the focus or not, it a design choise 15:25:23 blocage avoid client spying each other 15:25:25 ErikBjare blocage: I'm aware, that's my reason for concern. I'm not saying it should be included or anything, but as it looks now every DE would need to implement it themselves if these kind of applications are to be supported 15:25:46 ErikBjare So wondering if anyone knew the teams working with Wayland on Gnome for example 15:26:11 ErikBjare But thanks for confirming 15:26:29 blocage ErikBjare, DE should create a custom extension, or use D-bus or other IPC 15:27:31 blocage ErikBjare, I guess some compositor are around here, but I do not know myself if there is such extension already 15:27:44 blocage compositor developers * 15:28:36 ErikBjare I don't think there is (I've done quite a bit of searching), so I guess I need to catch the attention of some DE developers 15:29:16 ErikBjare Thanks a lot though 15:29:42 ErikBjare blocage: Would you mind if I shared logs of our conversation in the issue? 15:30:05 blocage just use it :) it's public 15:30:19 ErikBjare ty :)
tl;dr: How do I get the active window on Gnome when using Wayland?