diff --git a/aw_watcher_window/lib.py b/aw_watcher_window/lib.py index 010fb80..5ad669b 100644 --- a/aw_watcher_window/lib.py +++ b/aw_watcher_window/lib.py @@ -1,19 +1,77 @@ import sys +import json +import logging from typing import Optional +logger = logging.getLogger(__name__) -def get_current_window_linux() -> Optional[dict]: - from . import xlib - window = xlib.get_current_window() - if window is None: - cls = "unknown" - name = "unknown" - else: - cls = xlib.get_window_class(window) - name = xlib.get_window_name(window) +class Linux: + def __init__(self): + try: + import pydbus + self.bus = pydbus.SessionBus() + except ModuleNotFoundError: + logger.info("pydbus not installed, GNOME-Shell Wayland support disabled") + self.bus = False + self.gnome_shell = None + + if self.bus: + import gi.repository.GLib + try: + self.gnome_shell = self.bus.get("org.gnome.Shell") + self._setup_gnome() + except gi.repository.GLib.Error: + self.gnome_shell = None + + def get_current_window(self) -> dict: + if self.gnome_shell: + return self.get_current_window_gnome_shell() + + return self.get_current_window_x11() + + def _setup_gnome(self) -> None: + js_code = """ + global._aw_current_window = () => { + var window_list = global.get_window_actors(); + var active_window_actor = window_list.find(window => window.meta_window.has_focus()); + var active_window = active_window_actor.get_meta_window() + var vm_class = active_window.get_wm_class(); + var title = active_window.get_title() + var result = {"title": title, "appname": vm_class}; + return result + } + """ + ok, result = self.gnome_shell.Eval(js_code) + if not ok: + raise Error("failed seting up gnome-shell function: " + result) + + def get_current_window_gnome_shell(self) -> dict: + """get current app from GNOME Shell via dbus""" + + ok, result = self.gnome_shell.Eval("global._aw_current_window()") + if ok: + result_data = json.loads(result) + return result_data + + return {"appname": "unknown", "title": "unknown"} + + def get_current_window_x11(self) -> dict: + from . import xlib + window = xlib.get_current_window() + + if window is None: + cls = "unknown" + name = "unknown" + else: + cls = xlib.get_window_class(window) + name = xlib.get_window_name(window) + + return {"appname": cls, "title": name} + - return {"appname": cls, "title": name} +if sys.platform.startswith("linux"): + linux = Linux() def get_current_window_macos() -> Optional[dict]: @@ -41,7 +99,7 @@ def get_current_window_windows() -> Optional[dict]: def get_current_window() -> Optional[dict]: if sys.platform.startswith("linux"): - return get_current_window_linux() + return linux.get_current_window() elif sys.platform == "darwin": return get_current_window_macos() elif sys.platform in ["win32", "cygwin"]: diff --git a/pyproject.toml b/pyproject.toml index 07aa601..2cd5a3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,11 +15,20 @@ python-xlib = {version = "^0.26", platform = "linux"} pypiwin32 = {version = "223", platform = "win32"} wmi = {version = "^1.4.9", platform = "win32"} +# pydbus depends on PyGObject, which needs several system libs installed, +# to be able to be compiled: +# * gobject-introspection-devel +# * cairo-gobject-devel +pydbus = { version = "^0.6.0", platform = "linux", optional = true } + [tool.poetry.dev-dependencies] pytest = "^5.3.2" mypy = "^0.761" macholib = {version = "^1.13", platform = "darwin"} # Needed for pyinstaller +[tool.poetry.extras] +gnome = ["pydbus"] + [build-system] requires = ["poetry>=0.12"] build-backend = "poetry.masonry.api"