-
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Wayland support by forcing x11 (#470)
* Wayland support wip * Make glfw and qt work by forcing x11 * tweaks * Fix test * Update docs * Move some stuff to new gui utils module * force x11 on Wayland for wx too * Fix comment * Forcing an empty commit. --------- Co-authored-by: Korijn van Golen <[email protected]>
- Loading branch information
1 parent
cd3165f
commit eced145
Showing
13 changed files
with
268 additions
and
189 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
""" Private gui utilities. | ||
""" | ||
|
||
import os | ||
import sys | ||
import weakref | ||
import logging | ||
import ctypes.util | ||
from contextlib import contextmanager | ||
|
||
from .._coreutils import error_message_hash | ||
|
||
|
||
logger = logging.getLogger("wgpu") | ||
|
||
|
||
err_hashes = {} | ||
|
||
|
||
@contextmanager | ||
def log_exception(kind): | ||
"""Context manager to log any exceptions, but only log a one-liner | ||
for subsequent occurances of the same error to avoid spamming by | ||
repeating errors in e.g. a draw function or event callback. | ||
""" | ||
try: | ||
yield | ||
except Exception as err: | ||
# Store exc info for postmortem debugging | ||
exc_info = list(sys.exc_info()) | ||
exc_info[2] = exc_info[2].tb_next # skip *this* function | ||
sys.last_type, sys.last_value, sys.last_traceback = exc_info | ||
# Show traceback, or a one-line summary | ||
msg = str(err) | ||
msgh = error_message_hash(msg) | ||
if msgh not in err_hashes: | ||
# Provide the exception, so the default logger prints a stacktrace. | ||
# IDE's can get the exception from the root logger for PM debugging. | ||
err_hashes[msgh] = 1 | ||
logger.error(kind, exc_info=err) | ||
else: | ||
# We've seen this message before, return a one-liner instead. | ||
err_hashes[msgh] = count = err_hashes[msgh] + 1 | ||
msg = kind + ": " + msg.split("\n")[0].strip() | ||
msg = msg if len(msg) <= 70 else msg[:69] + "…" | ||
logger.error(msg + f" ({count})") | ||
|
||
|
||
def weakbind(method): | ||
"""Replace a bound method with a callable object that stores the `self` using a weakref.""" | ||
ref = weakref.ref(method.__self__) | ||
class_func = method.__func__ | ||
del method | ||
|
||
def proxy(*args, **kwargs): | ||
self = ref() | ||
if self is not None: | ||
return class_func(self, *args, **kwargs) | ||
|
||
proxy.__name__ = class_func.__name__ | ||
return proxy | ||
|
||
|
||
SYSTEM_IS_WAYLAND = "wayland" in os.getenv("XDG_SESSION_TYPE", "").lower() | ||
|
||
if sys.platform.startswith("linux") and SYSTEM_IS_WAYLAND: | ||
# Force glfw to use X11. Note that this does not work if glfw is already imported. | ||
if "glfw" not in sys.modules: | ||
os.environ["PYGLFW_LIBRARY_VARIANT"] = "x11" | ||
# Force Qt to use X11. Qt is more flexible - it ok if e.g. PySide6 is already imported. | ||
os.environ["QT_QPA_PLATFORM"] = "xcb" | ||
# Force wx to use X11, probably. | ||
os.environ["GDK_BACKEND"] = "x11" | ||
|
||
|
||
_x11_display = None | ||
|
||
|
||
def get_alt_x11_display(): | ||
"""Get (the pointer to) a process-global x11 display instance.""" | ||
# Ideally we'd get the real display object used by the GUI toolkit. | ||
# But this is not always possible. In that case, using an alt display | ||
# object can be used. | ||
global _x11_display | ||
assert sys.platform.startswith("linux") | ||
if _x11_display is None: | ||
x11 = ctypes.CDLL(ctypes.util.find_library("X11")) | ||
x11.XOpenDisplay.restype = ctypes.c_void_p | ||
_x11_display = x11.XOpenDisplay(None) | ||
return _x11_display | ||
|
||
|
||
_wayland_display = None | ||
|
||
|
||
def get_alt_wayland_display(): | ||
"""Get (the pointer to) a process-global Wayland display instance.""" | ||
# Ideally we'd get the real display object used by the GUI toolkit. | ||
# This creates a global object, similar to what we do for X11. | ||
# Unfortunately, this segfaults, so it looks like the real display object | ||
# is needed? Leaving this here for reference. | ||
global _wayland_display | ||
assert sys.platform.startswith("linux") | ||
if _wayland_display is None: | ||
wl = ctypes.CDLL(ctypes.util.find_library("wayland-client")) | ||
wl.wl_display_connect.restype = ctypes.c_void_p | ||
_wayland_display = wl.wl_display_connect(None) | ||
return _wayland_display |
Oops, something went wrong.