Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak Wayland detection for robustness #2777

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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