Skip to content

Commit

Permalink
Tweak Wayland detection for robustness
Browse files Browse the repository at this point in the history
  • Loading branch information
rmartin16 committed Aug 19, 2024
1 parent f8d56ac commit 14b92b2
Show file tree
Hide file tree
Showing 9 changed files with 28 additions and 20 deletions.
1 change: 1 addition & 0 deletions changes/2777.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Toga's determination for whether a Linux host is running X11 or Wayland is now more robust.
5 changes: 2 additions & 3 deletions gtk/src/toga_gtk/app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio
import os
import signal
import sys
from pathlib import Path
Expand All @@ -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


Expand Down Expand Up @@ -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))
Expand Down
12 changes: 11 additions & 1 deletion gtk/src/toga_gtk/libs/gtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 2 additions & 4 deletions gtk/src/toga_gtk/screens.py
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions gtk/tests_backend/app.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import os
from pathlib import Path

import PIL.Image
import pytest

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
Expand All @@ -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):
Expand Down
2 changes: 0 additions & 2 deletions gtk/tests_backend/probe.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import asyncio
import os

import toga
from toga_gtk.libs import Gtk


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()
Expand Down
6 changes: 3 additions & 3 deletions gtk/tests_backend/screens.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -12,15 +12,15 @@ 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
else:
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)
4 changes: 2 additions & 2 deletions gtk/tests_backend/widgets/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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"
Expand Down
6 changes: 3 additions & 3 deletions gtk/tests_backend/window.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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__()
Expand Down

0 comments on commit 14b92b2

Please sign in to comment.