snapshot of https://github.com/ActivityWatch/aw-watcher-window.git (master, 2026-09-16; blobs > 131072B omitted)
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
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
This commit is contained in:
128
aw_watcher_window/xprop.py
Normal file
128
aw_watcher_window/xprop.py
Normal file
@@ -0,0 +1,128 @@
|
||||
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()))
|
||||
Reference in New Issue
Block a user