Some checks failed
Build / test on ubuntu-latest (py-3.9) (push) Failing after 2m36s
Build / typecheck (push) Successful in 1m38s
Build / test on macos-latest (py-3.9) (push) Has been cancelled
Build / test on windows-latest (py-3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Failing after 1s
129 lines
3.3 KiB
Python
129 lines
3.3 KiB
Python
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()))
|