From f179c95bc614e606e599a35579d802498c2d3bbe Mon Sep 17 00:00:00 2001 From: Sander Sweers Date: Sun, 16 Oct 2022 13:17:46 +0200 Subject: [PATCH 1/2] Applet: Make it a GtkApplication Needed for Gtk.Application.inhibit --- blueman/main/Applet.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/blueman/main/Applet.py b/blueman/main/Applet.py index 549160ba4..300a0026b 100644 --- a/blueman/main/Applet.py +++ b/blueman/main/Applet.py @@ -1,4 +1,6 @@ -from gi.repository import Gio, GLib +import gi +gi.require_version("Gtk", "3.0") +from gi.repository import Gio, GLib, Gtk import logging import signal from typing import Any, cast @@ -19,7 +21,7 @@ from blueman.plugins.applet.StatusIcon import StatusIcon -class BluemanApplet(Gio.Application): +class BluemanApplet(Gtk.Application): def __init__(self) -> None: super().__init__(application_id="org.blueman.Applet", flags=Gio.ApplicationFlags.FLAGS_NONE) setup_icon_path() From 0f6830d75bd82d548a3ffe45ed1edec26a5f8e7e Mon Sep 17 00:00:00 2001 From: Sander Sweers Date: Sun, 16 Oct 2022 13:32:36 +0200 Subject: [PATCH 2/2] GameControllerWakelock: Use Gtk.Application.inhibit * works on Xorg and Wayland. * uses xdg-desktop-portal but it requires an implementation --- .../plugins/applet/GameControllerWakelock.py | 95 ++++++++----------- configure.ac | 8 ++ meson.build | 4 + 3 files changed, 49 insertions(+), 58 deletions(-) diff --git a/blueman/plugins/applet/GameControllerWakelock.py b/blueman/plugins/applet/GameControllerWakelock.py index 693d40078..545e09327 100644 --- a/blueman/plugins/applet/GameControllerWakelock.py +++ b/blueman/plugins/applet/GameControllerWakelock.py @@ -1,25 +1,13 @@ from gettext import gettext as _ import logging -from typing import Any +from typing import Any, Dict from blueman.bluez.Device import Device -from blueman.Functions import launch from blueman.plugins.AppletPlugin import AppletPlugin -from blueman.plugins.errors import UnsupportedPlatformError import gi -gi.require_version('Gdk', '3.0') -try: - gi.require_version('GdkX11', '3.0') -except ValueError: - raise ImportError("Couldn't find required namespace GdkX11") - -from gi.repository import Gdk -from gi.repository import GdkX11 - - -if not isinstance(Gdk.Screen.get_default(), GdkX11.X11Screen): - raise UnsupportedPlatformError('Only X11 platform is supported') +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk class GameControllerWakelock(AppletPlugin): @@ -28,51 +16,42 @@ class GameControllerWakelock(AppletPlugin): __icon__ = "input-gaming-symbolic" def on_load(self) -> None: - self.wake_lock = 0 - screen = Gdk.Screen.get_default() - assert screen is not None - window = screen.get_root_window() - assert isinstance(window, GdkX11.X11Window) - self.root_window_id = "0x%x" % window.get_xid() + self.cookies: Dict[str, int] = {} def on_unload(self) -> None: - if self.wake_lock: - self.wake_lock = 1 - self.xdg_screensaver("resume") + for path, cookie in self.cookies.items(): + self.parent.uninhibit(cookie) + self.cookies = {} + + def _is_contoller(self, device: Device) -> bool: + klass = device["Class"] & 0x1fff + if klass == 0x504 or klass == 0x508: + return True + return False + + def _add_lock(self, path: str) -> None: + if path in self.cookies: + logging.warning(f"Cookie already exists for {path}") + return + + c = self.parent.inhibit(None, Gtk.ApplicationInhibitFlags.IDLE, "Blueman Gamecontroller Wakelock") + if c > 0: + self.cookies[path] = c + logging.debug(f"Inhibit success {c}") + else: + logging.warning("Inhibit failed") + + def _remove_lock(self, path: str) -> None: + c = self.cookies.pop(path, None) + if c is not None: + self.parent.uninhibit(c) + logging.debug(f"Inhibit removed {c}") + else: + logging.warning("No cookies found") def on_device_property_changed(self, path: str, key: str, value: Any) -> None: - if key == "Connected": - klass = Device(obj_path=path)["Class"] & 0x1fff - - if klass == 0x504 or klass == 0x508: - if value: - self.xdg_screensaver("suspend") - else: - self.xdg_screensaver("resume") - - def xdg_screensaver(self, action: str) -> None: - command = f"xdg-screensaver {action} {self.root_window_id}" - - if action == "resume": - if self.wake_lock <= 0: - self.wake_lock = 0 - elif self.wake_lock > 1: - self.wake_lock -= 1 - else: - ret = launch(command, sn=False) - if ret: - self.wake_lock -= 1 - else: - logging.error(f"{action} failed") - - elif action == "suspend": - if self.wake_lock >= 1: - self.wake_lock += 1 + if key == "Connected" and self._is_contoller(Device(obj_path=path)): + if value: + self._add_lock(path) else: - ret = launch(command, sn=False) - if ret: - self.wake_lock += 1 - else: - logging.error(f"{action} failed") - - logging.info(f"Number of locks: {self.wake_lock}") + self._remove_lock(path) diff --git a/configure.ac b/configure.ac index 10d807ced..2e7db8aa9 100644 --- a/configure.ac +++ b/configure.ac @@ -52,6 +52,14 @@ AC_MSG_ERROR([ifconfig or ip not found, install net-tools or iproute2]) fi fi +PKG_CHECK_EXISTS([xdg-desktop-portal], [portal_found=yes], [portal_found=no]) +AC_MSG_CHECKING([for XDG Desktop Portal]) +if test "x$portal_found" = "xno"; then + AC_MSG_RESULT([No Portal found some plugins may not work correctly]) +else + AC_MSG_RESULT([Portal found]) +fi + PKG_CHECK_MODULES([PYGOBJECT],[pygobject-3.0 >= 3.27.2]) AC_SUBST([PYGOBJECT_CFLAGS]) AC_SUBST([PYGOBJECT_LIBS]) diff --git a/meson.build b/meson.build index d7679a3d1..ccac96ab7 100644 --- a/meson.build +++ b/meson.build @@ -63,6 +63,10 @@ do_runtime_checks = get_option('runtime_deps_check') gtk = dependency('gtk+-3.0', version: '>= 3.10.', required: do_runtime_checks) +# Required for Gtk.Application.inhibit. +# Still requires a desktop implementation to work properly but we can check for that. +xdg_portal = dependency('xdg-desktop-portal', required: do_runtime_checks) + # Configure blueman apps foreach libexecapp: ['blueman-mechanism', 'blueman-rfcomm-watcher'] configure_file(