### Install PyWayland from Source Source: https://github.com/flacjacket/pywayland/blob/main/doc/install.rst Install PyWayland using the standard setup.py mechanism after obtaining the source code. This method allows for building against different Wayland protocol versions. ```bash $ python setup.py install ``` -------------------------------- ### Install PyWayland with pip Source: https://github.com/flacjacket/pywayland/blob/main/doc/install.rst Use this command to install PyWayland using pip after external dependencies are met. Any additional Python dependencies will be downloaded automatically. ```bash $ pip install pywayland ``` -------------------------------- ### Server-side Resource for WlCompositor Source: https://context7.com/flacjacket/pywayland/llms.txt Illustrates the server-side `Resource` class for handling client requests. This example sets up a `WlCompositor` interface, defines a handler for the `create_surface` request, and binds it to a resource. It uses a display with an added socket and dispatches events. ```python from pywayland.protocol.wayland import WlCompositor, WlSurface from pywayland.server import Display def handle_create_surface(compositor_resource, id_): """Handle wl_compositor.create_surface request from a client.""" client = compositor_resource._ptr # access raw client pointer if needed print(f"Client requests new surface with id={id_}") # In a real compositor: create a WlSurface resource and configure it def bind_compositor(resource): resource.dispatcher["create_surface"] = handle_create_surface resource.dispatcher["create_region"] = lambda r, id_: print(f"create_region id={id_}") print(f"Compositor resource id={resource.id} v={resource.version} created") with Display() as display: socket_name = display.add_socket() global_ = WlCompositor.global_class(display) global_.bind_func = bind_compositor loop = display.get_event_loop() loop.dispatch(50) display.flush_clients() ``` -------------------------------- ### Generate Wayland Protocol Files with Scanner Source: https://github.com/flacjacket/pywayland/blob/main/README.rst Use the pywayland.scanner module to generate Wayland protocol interface files from wayland.xml. This is necessary for running from source and tests. Ensure Wayland headers are installed. ```bash python -m pywayland.scanner ``` -------------------------------- ### Run PyWayland Test Suite Source: https://github.com/flacjacket/pywayland/blob/main/doc/install.rst Execute the test suite to verify your PyWayland installation. This command should be run from the root directory of the source code and requires pytest to be installed. ```bash $ pytest ``` -------------------------------- ### Dispatcher for WlOutput Event Handling Source: https://context7.com/flacjacket/pywayland/llms.txt Shows how to use the `Dispatcher` to route Wayland events to Python callables on the client side. This example attaches handlers for `geometry`, `mode`, and `done` events for a `WlOutput` object, collecting and printing output information. ```python from pywayland.client import Display from pywayland.protocol.wayland import WlOutput output_info = {} def geometry_handler(output, x, y, pw, ph, subpixel, make, model, transform): output_info["make"] = make output_info["model"] = model output_info["resolution"] = (pw, ph) def mode_handler(output, flags, width, height, refresh): output_info["mode"] = f"{width}x{height}@{refresh//1000}Hz" def done_handler(output): print("Output info complete:", output_info) with Display() as display: registry = display.get_registry() def on_global(registry, id_, interface, version): if interface == "wl_output": output = registry.bind(id_, WlOutput, version) # Attach handlers by name output.dispatcher["geometry"] = geometry_handler output.dispatcher["mode"] = mode_handler output.dispatcher["done"] = done_handler registry.dispatcher["global"] = on_global display.roundtrip() display.roundtrip() ``` -------------------------------- ### Create Anonymous Shared Memory Files with AnonymousFile Source: https://context7.com/flacjacket/pywayland/llms.txt Utilize AnonymousFile to create shared memory files for zero-copy buffer sharing with Wayland compositors. This example demonstrates creating a red buffer and displaying it. ```python import mmap from pywayland.client import Display from pywayland.protocol.wayland import WlCompositor, WlShm from pywayland.utils import AnonymousFile WIDTH, HEIGHT = 320, 240 STRIDE = WIDTH * 4 # ARGB8888 shm = None compositor = None def on_global(registry, id_, interface, version): global shm, compositor if interface == "wl_shm": shm = registry.bind(id_, WlShm, version) elif interface == "wl_compositor": compositor = registry.bind(id_, WlCompositor, version) with Display() as display: registry = display.get_registry() registry.dispatcher["global"] = on_global display.roundtrip() if shm and compositor: with AnonymousFile(STRIDE * HEIGHT) as fd: shm_data = mmap.mmap( fd, STRIDE * HEIGHT, prot=mmap.PROT_READ | mmap.PROT_WRITE, flags=mmap.MAP_SHARED ) # Fill with solid red (ARGB) shm_data.seek(0) shm_data.write(b"\x00\x00\xff\xff" * (WIDTH * HEIGHT)) pool = shm.create_pool(fd, STRIDE * HEIGHT) buffer = pool.create_buffer(0, WIDTH, HEIGHT, STRIDE, WlShm.format.argb8888.value) pool.destroy() surface = compositor.create_surface() surface.attach(buffer, 0, 0) surface.damage(0, 0, WIDTH, HEIGHT) surface.commit() display.roundtrip() print("Surface committed with red buffer") ``` -------------------------------- ### Build CFFI Module In-Place Source: https://github.com/flacjacket/pywayland/blob/main/doc/install.rst Execute this script to generate the CFFI module when running PyWayland from source. This step is only required for in-place development and assumes libwayland headers are correctly installed. ```python python pywayland/ffi_build.py ``` -------------------------------- ### Clone PyWayland Repository Source: https://github.com/flacjacket/pywayland/blob/main/doc/install.rst Clone the PyWayland git repository to obtain the source code. This is an alternative to installing from PyPI and allows for building from the latest improvements. ```bash $ git clone https://github.com/flacjacket/pywayland.git ``` -------------------------------- ### Client-side Proxy for WlPointer Source: https://context7.com/flacjacket/pywayland/llms.txt Demonstrates how to use the `Proxy` class to interact with Wayland objects on the client side. It acquires a pointer, sets up event handlers for motion and button events, and prints information about mouse movements and clicks. Ensure the `Display` is properly managed. ```python from pywayland.client import Display from pywayland.protocol.wayland import WlSeat, WlPointer pointer = None def seat_capabilities(seat, capabilities): global pointer has_pointer = capabilities & WlSeat.capability.pointer.value if has_pointer and pointer is None: pointer = seat.get_pointer() pointer.dispatcher["motion"] = lambda p, t, x, y: \ print(f"Mouse at ({x/256:.1f}, {y/256:.1f}) t={t}") pointer.dispatcher["button"] = lambda p, serial, t, button, state: \ print(f"Button {button} {'pressed' if state else 'released'}") print("Pointer acquired") with Display() as display: registry = display.get_registry() def on_global(registry, id_, interface, version): if interface == "wl_seat": seat = registry.bind(id_, WlSeat, version) seat.dispatcher["capabilities"] = seat_capabilities registry.dispatcher["global"] = on_global display.roundtrip() display.roundtrip() if pointer: print(f"Proxy destroyed: {pointer.destroyed}") pointer.destroy() print(f"Proxy destroyed: {pointer.destroyed}") ``` -------------------------------- ### Connect to Wayland Compositor using Display Source: https://context7.com/flacjacket/pywayland/llms.txt Demonstrates connecting to a Wayland compositor using the Display class, handling registry events, and dispatching events. Supports context-manager usage for automatic connect/disconnect, or explicit connect/disconnect. Can also connect via a file descriptor. ```python from pywayland.client import Display from pywayland.protocol.wayland import WlCompositor, WlShm def registry_global_handler(registry, id_, interface, version): if interface == "wl_compositor": compositor = registry.bind(id_, WlCompositor, version) print(f"Bound compositor v{version}") elif interface == "wl_shm": shm = registry.bind(id_, WlShm, version) print(f"Bound shm v{version}") def registry_global_remover(registry, id_): print(f"Global {id_} removed") # Context manager automatically calls connect() / disconnect() with Display() as display: registry = display.get_registry() registry.dispatcher["global"] = registry_global_handler registry.dispatcher["global_remove"] = registry_global_remover # Block until the server has sent all globals display.roundtrip() # Non-blocking dispatch of any pending events n = display.dispatch(block=False) print(f"Dispatched {n} events") fd = display.get_fd() print(f"Display fd: {fd}") # Explicit connect/disconnect (without context manager) display = Display("wayland-1") # named socket display.connect() try: display.roundtrip() finally: display.disconnect() # Connect via file descriptor import socket sock_a, sock_b = socket.socketpair() display = Display(sock_a.fileno()) display.connect() display.disconnect() ``` -------------------------------- ### server.Display Source: https://context7.com/flacjacket/pywayland/llms.txt Initializes a Wayland compositor display on the server side. This class manages the Unix socket for client connections, the registry for global objects, and the server's event loop. ```APIDOC ## `server.Display` — Create a Wayland compositor display The server-side `Display` creates a Wayland compositor endpoint. It manages the Unix socket, global object registry, client connections, and the server event loop. ### Methods - `add_socket(name=None)`: Adds a Unix socket for client connections. If `name` is None, an auto-selected socket is used. - `next_serial()`: Returns the next available serial number for events and requests. - `init_shm()`: Initializes support for shared memory buffers. - `add_shm_format(format)`: Adds a supported pixel format for shared memory buffers. - `get_event_loop()`: Retrieves the server's event loop. - `run()`: Starts the compositor event loop (blocks until `terminate()` is called). ### Usage Example ```python from pywayland.server import Display from pywayland.protocol.wayland import WlShm with Display() as display: socket_name = display.add_socket() print(f"Compositor listening on: {socket_name}") serial = display.next_serial() print(f"First serial: {serial}") display.init_shm() display.add_shm_format(WlShm.format.xbgr8888) event_loop = display.get_event_loop() # display.run() # Uncomment to start the event loop ``` -------------------------------- ### Generate Protocol Bindings with Protocol.parse_file() Source: https://context7.com/flacjacket/pywayland/llms.txt Demonstrates using `Protocol.parse_file()` to parse Wayland XML protocol definitions and `protocol.output()` to generate Python bindings. This is useful for creating client or server implementations for custom Wayland protocols. ```python from pywayland.scanner.protocol import Protocol # Parse a Wayland protocol XML file protocol = Protocol.parse_file("/usr/share/wayland/wayland.xml") print(f"Protocol name: {protocol.name}") print(f"Interfaces: {[i.name for i in protocol.interface]}") # Output: ['wl_display', 'wl_registry', 'wl_callback', 'wl_compositor', ...] # Generate Python bindings into an output directory import tempfile, os with tempfile.TemporaryDirectory() as tmpdir: all_imports = {i.name: protocol.name for i in protocol.interface} protocol.output(tmpdir, all_imports) generated = os.listdir(tmpdir) print(f"Generated: {generated}") # Output: ['wayland.py'] ``` -------------------------------- ### Create Wayland Compositor Display Source: https://context7.com/flacjacket/pywayland/llms.txt Initializes a server-side Wayland compositor display. Manages the Unix socket, global object registry, client connections, and the server event loop. Supports binding to auto-selected or named sockets and initializing shared memory. ```python from pywayland.server import Display with Display() as display: # Bind to an auto-selected socket (e.g. "wayland-1") socket_name = display.add_socket() print(f"Compositor listening on: {socket_name}") # Or bind to a named socket # display.add_socket("my-compositor") serial = display.next_serial() print(f"First serial: {serial}") # Initialize shared memory support display.init_shm() # Add extra pixel format for shm buffers from pywayland.protocol.wayland import WlShm display.add_shm_format(WlShm.format.xbgr8888) event_loop = display.get_event_loop() # Run the compositor event loop (blocks until terminate() is called) # display.run() ``` -------------------------------- ### Advertise Protocol Interface with Global Source: https://context7.com/flacjacket/pywayland/llms.txt Registers a Wayland interface with the compositor so clients can discover and bind to it via the registry. Use this to make your custom or standard Wayland interfaces available to clients. ```python from pywayland.protocol.wayland import WlCompositor from pywayland.server import Display def bind_compositor(resource): """Called when a client binds to wl_compositor.""" print(f"Client bound wl_compositor resource id={resource.id}, v={resource.version}") # Set up request handlers on the resource here # resource.dispatcher["create_surface"] = handle_create_surface with Display() as display: socket_name = display.add_socket() print(f"Socket: {socket_name}") # Advertise wl_compositor at the interface's maximum version compositor_global = WlCompositor.global_class(display) compositor_global.bind_func = bind_compositor # Run one iteration of the event loop loop = display.get_event_loop() loop.dispatch(0) display.flush_clients() # Clean up compositor_global.destroy() ``` -------------------------------- ### Global - Advertise a protocol interface to clients Source: https://context7.com/flacjacket/pywayland/llms.txt `Global` registers a Wayland interface with the compositor so that clients can discover and bind to it via the registry. ```APIDOC ## Global ### Description `Global` registers a Wayland interface with the compositor so that clients can discover and bind to it via the registry. ### Usage ```python from pywayland.protocol.wayland import WlCompositor from pywayland.server import Display def bind_compositor(resource): """Called when a client binds to wl_compositor.""" print(f"Client bound wl_compositor resource id={resource.id}, v={resource.version}") # Set up request handlers on the resource here # resource.dispatcher["create_surface"] = handle_create_surface with Display() as display: socket_name = display.add_socket() print(f"Socket: {socket_name}") # Advertise wl_compositor at the interface's maximum version compositor_global = WlCompositor.global_class(display) compositor_global.bind_func = bind_compositor # Run one iteration of the event loop loop = display.get_event_loop() loop.dispatch(0) display.flush_clients() # Clean up compositor_global.destroy() ``` ``` -------------------------------- ### Synchronize with Server using Display.roundtrip() Source: https://context7.com/flacjacket/pywayland/llms.txt Ensures all issued requests are processed by the server by sending a sync request and waiting for acknowledgment. Returns the number of dispatched events. Useful for populating globals and ensuring event arrival. ```python from pywayland.client import Display from pywayland.protocol.wayland import WlOutput outputs = [] def registry_handler(registry, id_, interface, version): if interface == "wl_output": output = registry.bind(id_, WlOutput, version) outputs.append(output) with Display() as display: registry = display.get_registry() registry.dispatcher["global"] = registry_handler # After roundtrip, all globals are populated display.roundtrip() print(f"Found {len(outputs)} output(s)") # Second roundtrip to let output events (geometry, mode) arrive display.roundtrip() ``` -------------------------------- ### Generate Wayland Protocol Bindings with pywayland-scanner Source: https://context7.com/flacjacket/pywayland/llms.txt Use the pywayland-scanner CLI to generate Python modules for Wayland protocols from XML definitions. Specify input files and output directories as needed. ```bash # Generate bindings for the core Wayland protocol (reads /usr/share/wayland/wayland.xml) pywayland-scanner ``` ```bash # Specify a custom XML input file and output directory pywayland-scanner -i /path/to/my-protocol.xml -o ./pywayland/protocol/ ``` ```bash # Also generate bindings for all wayland-protocols (unstable/staging/stable) pywayland-scanner --with-protocols -o ./pywayland/protocol/ ``` ```bash # Use a custom wayland-protocols data directory instead of pkg-config pywayland-scanner --with-protocols --input-protocols /opt/wayland-protocols/share/ ``` ```bash # Multiple input files at once pywayland-scanner \ -i /usr/share/wayland/wayland.xml \ -i /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml \ -o ./pywayland/protocol/ ``` -------------------------------- ### Scan Wayland Protocol XML and Output Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/scanner/index.rst Use Protocol.parse_file to scan an XML protocol definition and Protocol.output to generate scanner output to a directory. Ensure the XML file path and output directory path are correctly provided. ```python Protocol.parse_file(path_to_xml_file) Protocol.output(path_to_output_dir, {}) ``` -------------------------------- ### Display — Connect to a Wayland compositor Source: https://context7.com/flacjacket/pywayland/llms.txt The `Display` object represents a connection to a Wayland compositor. It can be used as a context manager for automatic connection and disconnection, or explicitly with `connect()` and `disconnect()` methods. It also supports connecting via a file descriptor. ```APIDOC ## Display ### Description `Display` is the root client object representing a connection to a Wayland compositor. It supports context-manager usage and manages the lifecycle of all child proxies and event queues. ### Usage ```python from pywayland.client import Display from pywayland.protocol.wayland import WlCompositor, WlShm def registry_global_handler(registry, id_, interface, version): if interface == "wl_compositor": compositor = registry.bind(id_, WlCompositor, version) print(f"Bound compositor v{version}") elif interface == "wl_shm": shm = registry.bind(id_, WlShm, version) print(f"Bound shm v{version}") def registry_global_remover(registry, id_): print(f"Global {id_} removed") # Context manager automatically calls connect() / disconnect() with Display() as display: registry = display.get_registry() registry.dispatcher["global"] = registry_global_handler registry.dispatcher["global_remove"] = registry_global_remover # Block until the server has sent all globals display.roundtrip() # Non-blocking dispatch of any pending events n = display.dispatch(block=False) print(f"Dispatched {n} events") fd = display.get_fd() print(f"Display fd: {fd}") # Explicit connect/disconnect (without context manager) display = Display("wayland-1") # named socket display.connect() try: display.roundtrip() finally: display.disconnect() # Connect via file descriptor import socket sock_a, sock_b = socket.socketpair() display = Display(sock_a.fileno()) display.connect() display.disconnect() ``` ``` -------------------------------- ### Flush Display Requests with Select Integration Source: https://context7.com/flacjacket/pywayland/llms.txt Sends pending client-side requests to the Wayland server immediately. Call before blocking on the display file descriptor in a custom event loop. Integrates with `select` for non-blocking I/O. ```python import select from pywayland.client import Display from pywayland.protocol.wayland import WlCompositor compositor = None def registry_handler(registry, id_, interface, version): global compositor if interface == "wl_compositor": compositor = registry.bind(id_, WlCompositor, version) with Display() as display: registry = display.get_registry() registry.dispatcher["global"] = registry_handler display.roundtrip() # Custom event loop integrating with select for _ in range(5): display.flush() fd = display.get_fd() readable, _, _ = select.select([fd], [], [], 0.1) if readable: display.dispatch(block=False) ``` -------------------------------- ### Listener and Signal - Observer pattern for Wayland signals Source: https://context7.com/flacjacket/pywayland/llms.txt `Listener` attaches a Python callable to a Wayland signal; `Signal` wraps a `wl_signal` and lets you emit events to all registered listeners. ```APIDOC ## Listener and Signal ### Description `Listener` attaches a Python callable to a Wayland signal; `Signal` wraps a `wl_signal` and lets you emit events to all registered listeners. ### Usage ```python from pywayland.server import Display, Listener from pywayland.server.listener import Signal def on_destroy(listener, data): print(f"Object destroyed, data={data}") # Create a custom signal sig = Signal() # Register a listener listener = Listener(on_destroy) sig.add(listener) # Emit the signal with arbitrary Python data sig.emit(data={"reason": "cleanup"}) # Remove all listeners (e.g. before destroying the owning object) sig.remove_listeners() # Typical server usage: listen for client destruction with Display() as display: destroy_listener = Listener(lambda l, d: print("Display destroying")) # display.add_destroy_listener(destroy_listener) # real usage display.add_socket() ``` ``` -------------------------------- ### Low-level CFFI List Traversal Helpers Source: https://context7.com/flacjacket/pywayland/llms.txt Use wl_container_of and wl_list_for_each for low-level manipulation of CFFI objects, mirroring C macros for walking wl_list-linked structures. ```python from pywayland.utils import wl_container_of, wl_list_for_each from pywayland import ffi, lib # wl_container_of: recover the enclosing struct from a member pointer # Equivalent to the C macro: wl_container_of(ptr, sample, member) # # Example: given a wl_listener pointer inside a wl_listener_container, # recover the container: container = ffi.new("struct wl_listener_container *") listener_ptr = ffi.addressof(container.destroy_listener) recovered = wl_container_of(listener_ptr, "struct wl_listener_container *", "destroy_listener") assert recovered == container # wl_list_for_each: iterate over a wl_list of structs # Equivalent to: wl_list_for_each(pos, head, member) # # Example: iterate over a wl_list of wl_listener_container objects head = ffi.new("struct wl_list *") lib.wl_list_init(head) # (In real usage the list would be populated by libwayland) for item in wl_list_for_each("struct wl_listener_container *", head, "destroy_listener"): print(item) # each item is a wl_listener_container cdata pointer ``` -------------------------------- ### Process Incoming Events with Display.dispatch() Source: https://context7.com/flacjacket/pywayland/llms.txt Handles event dispatching from the Wayland server. `block=True` waits for events, while `block=False` processes only queued events. Allows targeting a specific `EventQueue` for thread-safe operations. ```python from pywayland.client import Display with Display() as display: registry = display.get_registry() # Create a dedicated event queue for thread-safe handling my_queue = display.create_queue() registry.set_queue(my_queue) registry.dispatcher["global"] = lambda reg, id_, iface, ver: print(iface) # Block until events arrive on the default queue dispatched = display.dispatch(block=True) print(f"Dispatched {dispatched} events on default queue") # Non-blocking dispatch on custom queue display.dispatch(block=False, queue=my_queue) ``` -------------------------------- ### Display.roundtrip() — Synchronize with the server Source: https://context7.com/flacjacket/pywayland/llms.txt The `roundtrip()` method sends a synchronization request to the Wayland server and blocks until the server acknowledges it. This ensures all preceding requests have been processed and is useful for populating initial global objects. ```APIDOC ## Display.roundtrip() ### Description Sends a sync request and blocks until the server acknowledges it, ensuring all previously issued requests have been processed. Returns the number of events dispatched. ### Usage ```python from pywayland.client import Display from pywayland.protocol.wayland import WlOutput outputs = [] def registry_handler(registry, id_, interface, version): if interface == "wl_output": output = registry.bind(id_, WlOutput, version) outputs.append(output) with Display() as display: registry = display.get_registry() registry.dispatcher["global"] = registry_handler # After roundtrip, all globals are populated display.roundtrip() print(f"Found {len(outputs)} output(s)") # Second roundtrip to let output events (geometry, mode) arrive display.roundtrip() ``` ``` -------------------------------- ### Server EventLoop Management Source: https://context7.com/flacjacket/pywayland/llms.txt Integrates file descriptors, signals, timers, and idle callbacks into the compositor's main loop. Use this to manage asynchronous events in your Wayland server. ```python import signal as posix_signal from pywayland.server import Display def on_readable(fd, mask, data): print(f"fd {fd} is readable (mask={mask}), data={data}") return 1 def on_signal(signal_number, data): print(f"Received signal {signal_number}") return 1 def on_timer(data): print(f"Timer fired, data={data}") return 1 def on_idle(data): print(f"Idle callback, data={data}") with Display() as display: display.add_socket() loop = display.get_event_loop() # Watch a file descriptor import sys fd_source = loop.add_fd(sys.stdin.fileno(), on_readable, data="stdin") # React to SIGINT sig_source = loop.add_signal(posix_signal.SIGINT, on_signal, data=None) # One-shot timer (arm it with timer_update) timer_source = loop.add_timer(on_timer, data="tick") timer_source.timer_update(500) # fire after 500 ms # Idle callback runs when the loop has no other work idle_source = loop.add_idle(on_idle, data="idle") # Dispatch with a 100 ms timeout loop.dispatch(100) loop.dispatch_idle() # Clean up sources fd_source.remove() sig_source.remove() timer_source.remove() ``` -------------------------------- ### pywayland.scanner.Protocol Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/scanner/protocol.rst The Protocol class provides functionality for scanning and interacting with Wayland protocols. The `:members:` directive indicates that all public members of this class are documented. ```APIDOC ## Class: pywayland.scanner.Protocol This class is part of the pywayland scanner module and is used to represent and interact with Wayland protocols. ### Members The following members are available for the `Protocol` class: * `__init__` * `add_interface` * `find_interface` * `get_interface` * `interfaces` * `load_xml` * `name` * `parse` * `version` (Note: Specific details for each member are not provided in the source text, only their existence is indicated by `:members:`.) ``` -------------------------------- ### Listener Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/server.rst An object used to listen for and handle specific Wayland events. ```APIDOC ## Listener ### Description An object used to listen for and handle specific Wayland events. ### Members (Details of Listener members would be listed here if available in the source) ``` -------------------------------- ### Display Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/server.rst The main display object for a Wayland server. It manages connections and global objects. ```APIDOC ## Display ### Description The main display object for a Wayland server. It manages connections and global objects. ### Members (Details of display members would be listed here if available in the source) ``` -------------------------------- ### EventLoop - Server-side event loop Source: https://context7.com/flacjacket/pywayland/llms.txt The server EventLoop integrates file descriptors, signals, timers, and idle callbacks into the compositor's main loop. It allows for asynchronous event handling. ```APIDOC ## EventLoop ### Description The server `EventLoop` integrates file descriptors, signals, timers, and idle callbacks into the compositor's main loop. ### Usage ```python import signal as posix_signal from pywayland.server import Display def on_readable(fd, mask, data): print(f"fd {fd} is readable (mask={mask}), data={data}") return 1 def on_signal(signal_number, data): print(f"Received signal {signal_number}") return 1 def on_timer(data): print(f"Timer fired, data={data}") return 1 def on_idle(data): print(f"Idle callback, data={data}") with Display() as display: display.add_socket() loop = display.get_event_loop() # Watch a file descriptor import sys fd_source = loop.add_fd(sys.stdin.fileno(), on_readable, data="stdin") # React to SIGINT sig_source = loop.add_signal(posix_signal.SIGINT, on_signal, data=None) # One-shot timer (arm it with timer_update) timer_source = loop.add_timer(on_timer, data="tick") timer_source.timer_update(500) # fire after 500 ms # Idle callback runs when the loop has no other work idle_source = loop.add_idle(on_idle, data="idle") # Dispatch with a 100 ms timeout loop.dispatch(100) loop.dispatch_idle() # Clean up sources fd_source.remove() sig_source.remove() timer_source.remove() ``` ``` -------------------------------- ### Display.read() Source: https://context7.com/flacjacket/pywayland/llms.txt Reads raw events from the Wayland display file descriptor into per-proxy queues without dispatching them. This method is designed for multi-threaded applications where one thread is responsible for reading events and another for dispatching them. ```APIDOC ## `Display.read()` — Read events from the display file descriptor Reads raw events from the display fd into per-proxy queues without dispatching them. Designed for multi-threaded applications where one thread reads events and another dispatches. ### Method `read()` ``` -------------------------------- ### Display.dispatch() — Process incoming events Source: https://context7.com/flacjacket/pywayland/llms.txt The `dispatch()` method processes incoming events from the Wayland server. It can block until events are received or operate non-blockingly. It also supports dispatching events to a specific `EventQueue`. ```APIDOC ## Display.dispatch() ### Description Dispatches events from the server. When `block=True` it reads from the display fd and blocks until at least one event arrives; with `block=False` it only flushes the already-queued events without blocking. An optional `queue` argument targets a non-default `EventQueue`. ### Usage ```python from pywayland.client import Display with Display() as display: registry = display.get_registry() # Create a dedicated event queue for thread-safe handling my_queue = display.create_queue() registry.set_queue(my_queue) registry.dispatcher["global"] = lambda reg, id_, iface, ver: print(iface) # Block until events arrive on the default queue dispatched = display.dispatch(block=True) print(f"Dispatched {dispatched} events on default queue") # Non-blocking dispatch on custom queue display.dispatch(block=False, queue=my_queue) ``` ``` -------------------------------- ### Thread-Safe Event Queue for Wayland Events Source: https://context7.com/flacjacket/pywayland/llms.txt Enables dispatching events for selected proxies independently of the default queue, facilitating safe multi-threaded Wayland event handling. Events can be routed to a specific queue using `set_queue()`. ```python from pywayland.client import Display from pywayland.protocol.wayland import WlOutput with Display() as display: # Create a custom event queue output_queue = display.create_queue() registry = display.get_registry() output = None def registry_handler(registry, id_, interface, version): nonlocal output if interface == "wl_output": output = registry.bind(id_, WlOutput, version) # Route all output events through our dedicated queue output.set_queue(output_queue) registry.dispatcher["global"] = registry_handler display.roundtrip() if output: output.dispatcher["geometry"] = lambda o, x, y, pw, ph, sub, make, model, t: \ print(f"Output: {make} {model} at ({x},{y})") # Dispatch only events in the output queue display.dispatch(block=True, queue=output_queue) # Destroy the queue explicitly when done output_queue.destroy() print(f"Queue destroyed: {output_queue.destroyed}") ``` -------------------------------- ### Display.flush() Source: https://context7.com/flacjacket/pywayland/llms.txt Sends buffered client-side requests to the Wayland server immediately. This is useful for ensuring requests are sent before blocking operations, such as waiting for events in a custom event loop. ```APIDOC ## `Display.flush()` — Send buffered requests to the server Writes all pending client-side requests to the socket immediately. Returns the number of bytes written or `-1` on EAGAIN. Call before blocking on the display fd in a custom event loop. ### Method `flush()` ### Returns - `int`: The number of bytes written, or -1 on EAGAIN. ``` -------------------------------- ### Display Object Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/client.rst The Display object is a core component for Wayland clients, representing the connection to the Wayland server. Users should directly create instances of this class. ```APIDOC ## Display ### Description Represents the Wayland display connection. Users should directly create instances of this class. ### Members (Members are documented via autoclass directive in the source, specific methods are not listed here but are available through the Display object.) ``` -------------------------------- ### Observer Pattern for Wayland Signals Source: https://context7.com/flacjacket/pywayland/llms.txt Attaches a Python callable to a Wayland signal and emits events to registered listeners. Use this to implement the observer pattern for custom events within your compositor. ```python from pywayland.server import Display, Listener from pywayland.server.listener import Signal def on_destroy(listener, data): print(f"Object destroyed, data={data}") # Create a custom signal sig = Signal() # Register a listener listener = Listener(on_destroy) sig.add(listener) # Emit the signal with arbitrary Python data sig.emit(data={"reason": "cleanup"}) # Remove all listeners (e.g. before destroying the owning object) sig.remove_listeners() # Typical server usage: listen for client destruction with Display() as display: destroy_listener = Listener(lambda l, d: print("Display destroying")) # display.add_destroy_listener(destroy_listener) # real usage display.add_socket() ``` -------------------------------- ### EventLoop Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/server.rst Handles the event loop for the Wayland server, processing events from clients and other sources. ```APIDOC ## EventLoop ### Description Handles the event loop for the Wayland server, processing events from clients and other sources. ### Members (Details of EventLoop members would be listed here if available in the source) ``` -------------------------------- ### EventQueue Source: https://context7.com/flacjacket/pywayland/llms.txt Provides a thread-safe mechanism for managing Wayland events. An `EventQueue` allows events for specific proxies to be dispatched independently of the default queue, facilitating safe multi-threaded event handling. ```APIDOC ## `EventQueue` — Thread-safe event queue An `EventQueue` allows events for selected proxies to be dispatched independently of the default queue, enabling safe multi-threaded Wayland event handling. ### Methods - `create_queue()`: Creates a new, dedicated event queue. - `set_queue(queue)`: Assigns a proxy to a specific event queue. - `destroy()`: Destroys the event queue. ### Usage Example ```python from pywayland.client import Display from pywayland.protocol.wayland import WlOutput with Display() as display: output_queue = display.create_queue() registry = display.get_registry() output = None def registry_handler(registry, id_, interface, version): nonlocal output if interface == "wl_output": output = registry.bind(id_, WlOutput, version) output.set_queue(output_queue) registry.dispatcher["global"] = registry_handler display.roundtrip() if output: output.dispatcher["geometry"] = lambda o, x, y, pw, ph, sub, make, model, t: print(f"Output: {make} {model} at ({x},{y})") display.dispatch(block=True, queue=output_queue) output_queue.destroy() print(f"Queue destroyed: {output_queue.destroyed}") ``` ``` -------------------------------- ### Server-side Client Representation Source: https://context7.com/flacjacket/pywayland/llms.txt Represents a connected Wayland client on the compositor side. Provides credential inspection, resource lookup, and event flushing. Use this to manage client connections and their associated resources. ```python from pywayland.server import Client, Display, Listener client_connected = [] def handle_client_created(listener, client_ptr): client = Client(ptr=client_ptr) pid, uid, gid = client.get_credentials() print(f"Client connected: pid={pid} uid={uid} gid={gid}") # Attach a destroy listener destroy_listener = Listener(lambda l, d: print("Client disconnected")) client.add_destroy_listener(destroy_listener) client_connected.append(client) with Display() as display: socket_name = display.add_socket() # Listen for new client connections via a Listener on the display client_listener = Listener(handle_client_created) # In a real compositor: display.add_client_created_listener(client_listener) # Flush all pending events to every connected client display.flush_clients() display.terminate() ``` -------------------------------- ### AnonymousFile Class Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/utils.rst The AnonymousFile class provides an interface for anonymous file operations. ```APIDOC ## AnonymousFile Class ### Description Provides an interface for anonymous file operations. ### Methods (Members are documented in the source class) ``` -------------------------------- ### Client Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/server.rst Represents a connected Wayland client. The members of this class are the primary interface for interacting with a client. ```APIDOC ## Client ### Description Represents a connected Wayland client. The members of this class are the primary interface for interacting with a client. ### Members (Details of client members would be listed here if available in the source) ``` -------------------------------- ### EventQueue Object Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/client.rst The EventQueue object manages the event queue for a Wayland client, allowing for asynchronous event handling. Users should directly create instances of this class. ```APIDOC ## EventQueue ### Description Manages the event queue for a Wayland client. Users should directly create instances of this class. ### Members (Members are documented via autoclass directive in the source, specific methods are not listed here but are available through the EventQueue object.) ``` -------------------------------- ### Client - Server-side client representation Source: https://context7.com/flacjacket/pywayland/llms.txt Represents a connected Wayland client on the compositor side. Provides credential inspection, resource lookup, and event flushing. ```APIDOC ## Client ### Description Represents a connected Wayland client on the compositor side. Provides credential inspection, resource lookup, and event flushing. ### Usage ```python from pywayland.server import Client, Display, Listener client_connected = [] def handle_client_created(listener, client_ptr): client = Client(ptr=client_ptr) pid, uid, gid = client.get_credentials() print(f"Client connected: pid={pid} uid={uid} gid={gid}") # Attach a destroy listener destroy_listener = Listener(lambda l, d: print("Client disconnected")) client.add_destroy_listener(destroy_listener) client_connected.append(client) with Display() as display: socket_name = display.add_socket() # Listen for new client connections via a Listener on the display client_listener = Listener(handle_client_created) # In a real compositor: display.add_client_created_listener(client_listener) # Flush all pending events to every connected client display.flush_clients() display.terminate() ``` ``` -------------------------------- ### Read Display Events in a Separate Thread Source: https://context7.com/flacjacket/pywayland/llms.txt Reads raw Wayland events into per-proxy queues without dispatching them. Designed for multi-threaded applications where one thread reads events and another dispatches. Ensures thread-safe event reading. ```python import threading from pywayland.client import Display def reader_thread(display, stop_event): while not stop_event.is_set(): display.read() # reads into queues, thread-safe with Display() as display: stop = threading.Event() t = threading.Thread(target=reader_thread, args=(display, stop), daemon=True) t.start() display.roundtrip() stop.set() t.join() ``` -------------------------------- ### Printer Module Members Source: https://github.com/flacjacket/pywayland/blob/main/doc/module/scanner/printer.rst The Printer module contains various members that can be used for printing operations. The specific functions and classes available are detailed below. ```APIDOC ## Printer Module This module provides functionality related to printing. ### Members - `Printer` (class) - `print_data` (function) - `format_output` (function) Refer to the specific documentation for each member for detailed usage instructions. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.