aw_watcher_window/xprop.py
import sys
import subprocess
import re
import logging
from subprocess import PIPE
from typing import List
logger = logging.getLogger(__name__)
# req_version is 3.5 due to usage of subprocess.run
# It would be nice to be able to use 3.4 as well since it's still common as of May 2016
req_version = (3, 5)
cur_version = sys.version_info
if not cur_version >= req_version:
logger.error("Your Python version is too old, 3.5 or higher is required.")
exit(1)
def xprop_id(window_id) -> str:
cmd = ["xprop"]
cmd.append("-id")
cmd.append(window_id)
p = subprocess.run(cmd, stdout=PIPE)
return str(p.stdout, "utf8")
def xprop_root() -> str:
cmd = ["xprop"]
cmd.append("-root")
p = subprocess.run(cmd, stdout=PIPE)
return str(p.stdout, "utf8")
def get_active_window_id():
lines = xprop_root().split("\n")
match="_NET_ACTIVE_WINDOW(WINDOW)"
result = None
for line in lines:
if match in line:
result = line
break
wid = "0x0"
if result:
wids = re.findall("0x[0-9a-f]*", result)
if len(wids) > 0:
wid = wids[0]
return wid
def get_window_ids():
lines = xprop_root().split("\n")
client_list = next(filter(lambda x: "_NET_CLIENT_LIST(" in x, lines))
window_ids = re.findall("0x[0-9a-f]*", client_list)
return window_ids
def _extract_xprop_field(line):
return "".join(line.split("=")[1:]).strip(" \n")
def get_xprop_field(fieldname, xprop_output):
return list(map(_extract_xprop_field, re.findall(fieldname + ".*\n", xprop_output)))
def get_xprop_field_str(fieldname, xprop_output) -> str:
field = None
try:
field = get_xprop_field(fieldname, xprop_output)[0].strip('"')
except IndexError:
pass
if not field:
field = "unknown"
return field
def get_xprop_field_strlist(fieldname, xprop_output) -> List[str]:
return [s.strip('"') for s in get_xprop_field(fieldname, xprop_output)]
def get_xprop_field_int(fieldname, xprop_output) -> int:
field = None
try:
field = int(get_xprop_field(fieldname, xprop_output)[0])
except IndexError:
pass
if not field:
field = -1
return field
def get_xprop_field_class(xprop_output) -> List[str]:
classname: List[str] = []
try:
classname = [c.strip('", ') for c in get_xprop_field("WM_CLASS", xprop_output)[0].split(',')]
except IndexError:
pass
if not classname:
classname = ["unknown"]
return classname
def get_window(wid, active_window=False):
s = xprop_id(wid)
window = {
"id": wid,
"active": active_window,
"name": get_xprop_field_str("WM_NAME", s),
"class": get_xprop_field_class(s),
"desktop": get_xprop_field_int("WM_DESKTOP", s),
"command": get_xprop_field("WM_COMMAND", s),
"role": get_xprop_field_strlist("WM_WINDOW_ROLE", s),
"pid": get_xprop_field_int("WM_PID", s),
}
return window
def get_windows(wids, active_window_id=None):
return [get_window(wid, active_window=(wid == active_window_id)) for wid in wids]
if __name__ == "__main__":
from time import sleep
logging.basicConfig(level=logging.INFO)
while True:
sleep(1)
print("Active window id: " + str(get_active_window_id()))