From 0cdbee245eac31fc5e9daaf1e74946db8a5b5b84 Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Sun, 18 Aug 2024 23:26:44 -0400 Subject: [PATCH] Tweak Wayland detection for robustness --- gtk/src/toga_gtk/app.py | 5 ++--- gtk/src/toga_gtk/libs/gtk.py | 12 +++++++++++- gtk/src/toga_gtk/screens.py | 6 ++---- gtk/tests_backend/app.py | 6 ++++-- gtk/tests_backend/probe.py | 2 -- gtk/tests_backend/screens.py | 6 +++--- gtk/tests_backend/widgets/canvas.py | 4 ++-- gtk/tests_backend/window.py | 6 +++--- 8 files changed, 27 insertions(+), 20 deletions(-) diff --git a/gtk/src/toga_gtk/app.py b/gtk/src/toga_gtk/app.py index d2bdb8e3f7..4d4a48947b 100644 --- a/gtk/src/toga_gtk/app.py +++ b/gtk/src/toga_gtk/app.py @@ -1,5 +1,4 @@ import asyncio -import os import signal import sys from pathlib import Path @@ -12,7 +11,7 @@ from toga.handlers import simple_handler from .keys import gtk_accel -from .libs import TOGA_DEFAULT_STYLES, Gdk, Gio, GLib, Gtk +from .libs import IS_WAYLAND, TOGA_DEFAULT_STYLES, Gdk, Gio, GLib, Gtk from .screens import Screen as ScreenImpl @@ -206,7 +205,7 @@ def set_main_window(self, window): def get_screens(self): display = Gdk.Display.get_default() - if "WAYLAND_DISPLAY" in os.environ: # pragma: no-cover-if-linux-x + if IS_WAYLAND: # pragma: no-cover-if-linux-x # `get_primary_monitor()` doesn't work on wayland, so return as it is. return [ ScreenImpl(native=display.get_monitor(i)) diff --git a/gtk/src/toga_gtk/libs/gtk.py b/gtk/src/toga_gtk/libs/gtk.py index 40fd0034d5..6e302197d0 100644 --- a/gtk/src/toga_gtk/libs/gtk.py +++ b/gtk/src/toga_gtk/libs/gtk.py @@ -3,13 +3,23 @@ gi.require_version("Gdk", "3.0") gi.require_version("Gtk", "3.0") -from gi.repository import Gdk, GdkPixbuf, Gio, GLib, GObject, Gtk # noqa: E402, F401 +from gi.repository import ( # noqa: E402, F401 + Gdk, + GdkPixbuf, + GdkX11, + Gio, + GLib, + GObject, + Gtk, +) if Gdk.Screen.get_default() is None: # pragma: no cover raise RuntimeError( "Cannot identify an active display. Is the `DISPLAY` environment variable set correctly?" ) +IS_WAYLAND = not isinstance(Gdk.Display.get_default(), GdkX11.X11Display) + # The following imports will fail if the underlying libraries or their API # wrappers aren't installed; handle failure gracefully (see # https://github.com/beeware/toga/issues/26) diff --git a/gtk/src/toga_gtk/screens.py b/gtk/src/toga_gtk/screens.py index 1ef6f7a98a..a951ceb67f 100644 --- a/gtk/src/toga_gtk/screens.py +++ b/gtk/src/toga_gtk/screens.py @@ -1,9 +1,7 @@ -import os - from toga.screens import Screen as ScreenInterface from toga.types import Position, Size -from .libs import Gdk +from .libs import IS_WAYLAND, Gdk class Screen: @@ -31,7 +29,7 @@ def get_size(self) -> Size: return Size(geometry.width, geometry.height) def get_image_data(self): - if "WAYLAND_DISPLAY" in os.environ: # pragma: no cover + if IS_WAYLAND: # pragma: no cover # Not implemented on wayland due to wayland security policies. self.interface.factory.not_implemented("Screen.get_image_data() on Wayland") else: # pragma: no-cover-if-linux-wayland diff --git a/gtk/tests_backend/app.py b/gtk/tests_backend/app.py index 5c525e9d80..9c16a0198a 100644 --- a/gtk/tests_backend/app.py +++ b/gtk/tests_backend/app.py @@ -1,3 +1,4 @@ +import os from pathlib import Path import PIL.Image @@ -5,7 +6,7 @@ import toga from toga_gtk.keys import gtk_accel, toga_key -from toga_gtk.libs import Gdk, Gtk +from toga_gtk.libs import IS_WAYLAND, Gdk, Gtk from .dialogs import DialogsMixin from .probe import BaseProbe @@ -16,13 +17,14 @@ class AppProbe(BaseProbe, DialogsMixin): supports_key_mod3 = True # Gtk 3.24.41 ships with Ubuntu 24.04 where present() works on Wayland supports_current_window_assignment = not ( - BaseProbe.IS_WAYLAND and BaseProbe.GTK_VERSION < (3, 24, 41) + IS_WAYLAND and BaseProbe.GTK_VERSION < (3, 24, 41) ) def __init__(self, app): super().__init__() self.app = app assert isinstance(self.app._impl.native, Gtk.Application) + assert IS_WAYLAND is (os.environ.get("WAYLAND_DISPLAY", "") != "") @property def config_path(self): diff --git a/gtk/tests_backend/probe.py b/gtk/tests_backend/probe.py index 9f510ead54..d43bc875a2 100644 --- a/gtk/tests_backend/probe.py +++ b/gtk/tests_backend/probe.py @@ -1,5 +1,4 @@ import asyncio -import os import toga from toga_gtk.libs import Gtk @@ -7,7 +6,6 @@ class BaseProbe: GTK_VERSION = Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION - IS_WAYLAND = os.environ.get("WAYLAND_DISPLAY", "") != "" def repaint_needed(self): return Gtk.events_pending() diff --git a/gtk/tests_backend/screens.py b/gtk/tests_backend/screens.py index a31e6b0518..101bb02ac1 100644 --- a/gtk/tests_backend/screens.py +++ b/gtk/tests_backend/screens.py @@ -1,7 +1,7 @@ import pytest -from gi.repository import GdkX11 from toga.images import Image as TogaImage +from toga_gtk.libs import IS_WAYLAND, GdkX11 from .probe import BaseProbe @@ -12,7 +12,7 @@ def __init__(self, screen): self.screen = screen self._impl = screen._impl self.native = screen._impl.native - if self.IS_WAYLAND: + if IS_WAYLAND: # The native display type on Wayland is `__gi__.GdkWaylandMonitor` # However, that class can't be imported directly. pass @@ -20,7 +20,7 @@ def __init__(self, screen): assert isinstance(self.native, GdkX11.X11Monitor) def get_screenshot(self, format=TogaImage): - if self.IS_WAYLAND: + if IS_WAYLAND: pytest.skip("Screen.as_image() is not implemented on Wayland.") else: return self.screen.as_image(format=format) diff --git a/gtk/tests_backend/widgets/canvas.py b/gtk/tests_backend/widgets/canvas.py index 1d00c6649a..fd6f639201 100644 --- a/gtk/tests_backend/widgets/canvas.py +++ b/gtk/tests_backend/widgets/canvas.py @@ -2,7 +2,7 @@ from PIL import Image -from toga_gtk.libs import Gdk, Gtk +from toga_gtk.libs import IS_WAYLAND, Gdk, Gtk from .base import SimpleProbe @@ -12,7 +12,7 @@ class CanvasProbe(SimpleProbe): def reference_variant(self, reference): if reference == "multiline_text": - if self.IS_WAYLAND: + if IS_WAYLAND: return f"{reference}-gtk-wayland" else: return f"{reference}-gtk-x11" diff --git a/gtk/tests_backend/window.py b/gtk/tests_backend/window.py index b67e7ef6e7..ae6f6f0a07 100644 --- a/gtk/tests_backend/window.py +++ b/gtk/tests_backend/window.py @@ -1,4 +1,4 @@ -from toga_gtk.libs import Gdk, Gtk +from toga_gtk.libs import IS_WAYLAND, Gdk, Gtk from .dialogs import DialogsMixin from .probe import BaseProbe @@ -12,8 +12,8 @@ class WindowProbe(BaseProbe, DialogsMixin): supports_move_while_hidden = False supports_unminimize = False # Wayland mostly prohibits interaction with the larger windowing environment - supports_minimize = not BaseProbe.IS_WAYLAND - supports_placement = not BaseProbe.IS_WAYLAND + supports_minimize = not IS_WAYLAND + supports_placement = not IS_WAYLAND def __init__(self, app, window): super().__init__()