Skip to content

wayland

FreeBodyEngine.core.window.wayland #

BTN_CODE_TO_INDEX = {v: k for k, v in (LINUX_BTN_CODES.items())} module-attribute #

LINUX_BTN_CODES = {0: 272, 1: 273, 2: 274, 3: 275, 4: 276, 5: 277, 6: 278, 7: 279} module-attribute #

XKB_KEYSYM_TO_KEY = {} module-attribute #

WaylandMouse(window) #

Bases: Mouse

Unlike GLFWMouse, this doesn't poll button/position state each frame - Wayland only tells you about input via events. WaylandWindow's pointer callbacks push updates into this class as they arrive; update() just turns those into the same one-frame pressed/released latch shape that the rest of the engine expects from GLFWMouse.

Sets up per-button event/state tracking for window; positions start at the origin until a pointer-enter/motion event arrives.

drag_threshold = 0.2 instance-attribute #

last_click_time = -500 instance-attribute #

position = Vector(0, 0) instance-attribute #

scroll_delta = Vector(0, 0) instance-attribute #

window = window instance-attribute #

world_position = Vector(0, 0) instance-attribute #

get_double_click(button) #

True on the frame button was pressed as part of a double-click.

get_down(button) #

True for as long as button is held down.

get_pressed(button) #

True on the frame button was pressed.

get_released(button) #

True on the frame button was released.

get_scroll_delta() #

How far the scroll wheel moved this frame - see _on_pointer_axis.

hide_cursor() #

Hides the system cursor via the classic wl_pointer.set_cursor request with a null surface - cursor-shape-v1 has no "hidden" shape of its own, so hiding still goes through the older mechanism (the two aren't exclusive - whichever request was sent most recently for this pointer wins, per the protocol).

set_cursor(shape='default') #

Sets the system cursor's shape - see WaylandWindow._set_cursor_shape for the actual protocol call and the set of names supported.

update() #

Latches this frame's pressed/released events (set by pointer callbacks) and updates world-space position.

WaylandWindow(size, title) #

Bases: Window

Native Wayland window backend (xdg-shell), talking to the compositor directly rather than through GLFW.

Contains no graphics API code - EGL/OpenGL stays in the renderer, which uses native_display/native_surface below. Input is entirely event-driven (pointer/keyboard from the Wayland seat, gamepads read separately via evdev), unlike GLFW's poll-based get_key/get_cursor_pos.

Connects to the Wayland display, binds the required globals, and creates an xdg-shell toplevel surface.

Blocks until the compositor sends its first configure event, so a real size is known before this constructor returns control to the engine.

framebuffer_size property #

The window size scaled by the output's buffer scale factor.

mouse = None instance-attribute #

native_display property #

wl_display* as a ctypes.c_void_p, for handing to EGL / Vulkan / etc. (bridged from pywayland's cffi pointer - see _cdata_to_voidp above)

native_surface property #

wl_surface* as a ctypes.c_void_p, for handing to EGL / Vulkan / etc. (bridged from pywayland's cffi pointer - see _cdata_to_voidp above)

position property writable #

Always (0, 0) - the Wayland protocol does not expose a client window's position on screen.

size property writable #

The window's last known (requested or compositor-configured) size, in pixels.

window_type = 'wayland' instance-attribute #

close() #

Flags the window to close, closes any open gamepad devices, destroys the xdg-shell surfaces, and disconnects.

create_mouse() #

Creates this window's WaylandMouse and stores it so pointer callbacks (e.g. _on_pointer_motion) can reach it.

draw() #

Asks the renderer to swap buffers, presenting the frame.

get_clipboard_text() #

Returns the system clipboard's current text content, or None if it's empty, isn't text, or couldn't be read. Synchronous (reads a pipe the offering client writes into - the standard Wayland clipboard mechanism, the same one wl-paste itself uses) - fine for a user-initiated Ctrl+V, not something to call every frame.

is_ready() #

True until the compositor or user has requested this window close.

resize(window, width, height) #

Records the new size, updates the surface's window geometry, and fires WINDOW_RESIZE/FRAMEBUFFER_RESIZE.

The single path both the size setter and compositor-driven resizes (_on_toplevel_configure) go through, so local state and the events the rest of the engine listens for stay consistent either way.

set_clipboard_text(text) #

Sets the system clipboard's text content by handing it to wl-copy (wl-clipboard) as a subprocess, rather than this backend implementing the wl_data_device/wl_data_source write protocol itself.

There was a hand-rolled implementation here (create a wl_data_source, offer the same text mime types get_clipboard_text() reads, wl_data_device.set_selection() with a real input-event serial) that looked protocol-correct - verified with wl-paste itself, repeatedly - and still didn't work pasting into Firefox, for reasons that were never pinned down (this sandbox has no way to drive Firefox's own UI to see what it was actually doing differently). Rather than keep guessing at implementation details one at a time, this hands the job to the actual reference implementation real users already run daily for exactly this - wl-copy manages its own short-lived Wayland client connection entirely independently of this window (no serial from here needed at all), and is a known-good known quantity that every other clipboard tool on this system already works with. Silently does nothing if wl-copy isn't installed or the call fails - no worse than the old implementation's own silent no-op-if-nothing-clicked-yet behavior.

set_title(new_title) #

Sets the xdg-shell toplevel's title.

update() #

Flushes and dispatches pending Wayland events (non-blocking), polls gamepads, ticks key repeat, and quits once closed.