I would like to programmatically detect the active window, and its meta data -- like app name and title -- in Chromebook's Linux Crostini. Does anyone know how this can reliably be done?
FWIW, I've already tried the following three methods in python that, when combined, provide a full solution for Fedora, Ubuntu, Arch, Manjaro, Mint, etc. But none of them work on Crostini.
def getAppAndTitle():
title = ''
app = ''
try:
# METHOD 1: Try to get window id info from _NET_ACTIVE_WINDOW
actives = []
try:
actives = re.findall('0x([0-9a-fA-F]+)', subprocess.check_output("xprop -root _NET_ACTIVE_WINDOW", shell=True).decode('utf-8'))
except:
pass
if len(actives) > 0:
active_id = int(actives[0], 16)
if active_id != 0:
window_strs = ''
# Get the list of all window names & ids
try:
window_strs = subprocess.check_output("wmctrl -lx", shell=True).decode('utf-8')
except:
pass
for window_str in window_strs.splitlines():
acceptable = re.search('^0x([0-9a-fA-F]+)\s+\S+\s+(\S+)\s+\S+\s+(.*)$', window_str)
if acceptable:
acceptable_id = int(acceptable.group(1), 16)
if acceptable_id == active_id:
app, title = acceptable.group(2).strip(), acceptable.group(3).strip()
except Exception as e1:
pass
try:
# METHOD 2: Try to get window info from Wnck
if not (title and app):
screen = None
try:
screen = Wnck.Screen.get_default()
except Exception as e2:
pass
if screen:
screen.force_update()
active_window = screen.get_active_window()
if active_window:
title = active_window.get_name().strip()
app = active_window.get_application().get_name().strip()
except Exception as e1:
pass
try:
# METHOD 3: Designed for Wayland
if not (title and app):
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()
app_tuple_string = app_retval.decode('utf-8').strip()
# We now have a string that looks like:
# (true, "\"Qur'an App"\")
if app_tuple_string:
app_tuple_string = app_tuple_string.replace("(true", "(True")
app_tuple_string = app_tuple_string.replace("(false", "(False")
# We now have a string that looks like:
# (True, "\"Qur'an App"\")
app_tuple = ast.literal_eval(app_tuple_string)
if len(app_tuple) > 1:
app = app_tuple[1]
# We now have a string that looks like:
# "Qur'an App"
if app and isinstance(app, str) and (type(app) is str):
app = app.strip()
if len(app) > 2:
if (app[0:1] == '"' and app[-1] == '"') or (app[0:1] == "'" and app[-1] == "'"):
app = ast.literal_eval(app).strip()
# We now have a string that looks like:
# Qur'an App
title_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_title\(\)")
title_process = subprocess.Popen(title_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
title_retval = title_process.stdout.read()
title_retcode = title_process.wait()
title_tuple_string = title_retval.decode('utf-8').strip()
if title_tuple_string:
title_tuple_string = title_tuple_string.replace("(true", "(True")
title_tuple_string = title_tuple_string.replace("(false", "(False")
title_tuple = ast.literal_eval(title_tuple_string)
if len(title_tuple) > 1:
title = title_tuple[1]
if title and isinstance(title, str) and (type(title) is str):
title = title.strip()
if len(title) > 2:
if (title[0:1] == '"' and title[-1] == '"') or (title[0:1] == "'" and title[-1] == "'"):
title = ast.literal_eval(title)
if "error:" in app.lower():
title = ''
app = ''
except Exception as e1:
title = ''
app = ''
return app, title
Any thoughts on other ways of doing this?
I've been able to accomplish this using the following two terminal commands.
The first gets the tree of running windows.
The second tells me which of those is the one with focus.