Skip to content

Commit

Permalink
feat: retrieve window information on KDE
Browse files Browse the repository at this point in the history
  • Loading branch information
dynobo committed Apr 22, 2024
1 parent 6de7bbf commit 36a2866
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 2 deletions.
79 changes: 78 additions & 1 deletion keyhint/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import re
import shutil
import subprocess
import tempfile
import textwrap
from datetime import datetime

logger = logging.getLogger("keyhint")

Expand Down Expand Up @@ -124,7 +127,7 @@ def has_window_calls_extension() -> bool:


def get_active_window_via_window_calls() -> tuple[str, str]:
"""Retrieve active window class and active window title on Wayland.
"""Retrieve active window class and active window title on Gnome + Wayland.
Inspired by https://gist.github.com/rbreaves/257c3edfa301786e66e964d7ac036269
Expand Down Expand Up @@ -165,6 +168,80 @@ def _get_cmd_result(cmd: str) -> str:
return wm_class, title


def get_active_window_via_kwin() -> tuple[str, str]:
"""Retrieve active window class and active window title on KDE + Wayland.
Returns:
Tuple(str, str): window class, window title
"""
kwin_script = textwrap.dedent("""
client = workspace.activeClient;
title = client.caption;
wm_class = client.resourceClass;
console.info(`keyhint_out: wm_class=${wm_class}, window_title=${title}`);
""")
logger.debug("kwin_script: %s", kwin_script)

with tempfile.NamedTemporaryFile(suffix=".js") as fh:
fh.write(kwin_script.encode())
cmd_load = (
"gdbus call --session --dest org.kde.KWin "
"--object-path /Scripting "
f"--method org.kde.KWin.Scripting.loadScript 'file://{fh.name}'"
)
logger.debug("cmd_load: %s", cmd_load)
stdout = subprocess.check_output(cmd_load, shell=True).decode() # noqa: S602

script_id = stdout[1:-1].split(", ", 1)[0]
logger.debug("script_id: %s", script_id)

since = str(datetime.now())

cmd_run = (
"gdbus call --session --dest org.kde.KWin "
"--object-path /Scripting "
f"--method org.kde.KWin.Scripting.run {script_id}"
)
logger.debug("cmd_run: %s", cmd_run)
subprocess.check_output(cmd_run, shell=True) # noqa: S602

cmd_stop = (
"gdbus call --session --dest org.kde.KWin "
"--object-path /Scripting "
f"--method org.kde.KWin.Scripting.stop {script_id}"
)
logger.debug("cmd_stop: %s", cmd_stop)
subprocess.check_output(cmd_stop, shell=True) # noqa: S602

cmd_unload = (
"gdbus call --session --dest org.kde.KWin "
"--object-path /Scripting "
f"--method org.kde.KWin.Scripting.unload {script_id}"
)
logger.debug("cmd_unload: %s", cmd_unload)
subprocess.check_output(cmd_unload, shell=True) # noqa: S602

log_messages = (
subprocess.check_output(
f'journalctl --user -o cat --since "{since}"',
shell=True, # noqa: S602
)
.decode()
.split("\n")
)
logger.debug("log_messages: %s", log_messages)
result_message = next(m for m in log_messages if "keyhint_out" in m)
match = re.match(r"keyhint_out: wm_class=(.+), window_title=(.+)", result_message)
if match:
wm_class = match.group(1)
title = match.group(2)
else:
logger.warning("Could not extract window info from KWin log")
wm_class = title = ""

return wm_class, title


def get_active_window_via_xprop() -> tuple[str, str]:
"""Retrieve active window class and active window title on Xorg desktops.
Expand Down
3 changes: 2 additions & 1 deletion keyhint/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ def init_last_active_window_info(self) -> tuple[str, str]:
else:
self.banner_window_calls.set_revealed(True)
logger.error("Window Calls extension not found!")

case _, "kde":
wm_class, wm_title = context.get_active_window_via_kwin()
case False, _:
if context.has_xprop():
wm_class, wm_title = context.get_active_window_via_xprop()
Expand Down

0 comments on commit 36a2866

Please sign in to comment.