Selkies

display_utils

Display plumbing shared by the WebSocket and WebRTC transports.

Covers X11 RandR display management (resolution modes, extended-desktop logical monitors, framebuffer sizing), per-desktop-environment DPI application, Wayland output-id mapping, pixelflux CaptureSettings population, and cursor payload/cache-handle helpers.

Every RandR operation runs natively on a retained python-xlib connection; the xrandr/cvt/gtf subprocess each one degrades to when the native call fails lives in display_utils_xrandr. Blocking X work runs on executor threads (asyncio.to_thread) under _x11_lock so the event loop never waits on the X server. A helper drops the cached connection on any failure other than an X protocol error: an XError leaves the connection healthy, while a broken connection also frees this session's RandR modes. RandR request failures arrive through the connection's asynchronous error handler -- printed, never raised -- so every mutation reads its result back before claiming success.

An extended desktop is laid out one of two ways, decided by what the server offers (apply_extended_layout). Where it has pluggable outputs -- spare RandR outputs carrying a Connected property, each with a CRTC of its own, which the Xvfb the images build provides -- every display is a real output: a secondary is plugged in, given its exact mode and a position, and unplugged when its client leaves, so window managers and toolkits meet what hardware would show them and need no knowledge of the framebuffer (_sync_apply_output_layout). A layout that both adds a display and moves the primary publishes the move first (output_layout_stage). Anywhere else the server has one CRTC covering the framebuffer and each display is a RandR 1.5 logical monitor over it, which consumers that build their screens from CRTCs do not follow; that layout, the window-manager restart it needs, and the subprocess fallbacks are display_utils_xrandr, which this module imports only at the point it falls back.

Either way RandR moves a screen and leaves every window at its root coordinates: the primary moves back to the origin when the display on its left leaves, or aside when one is added there, and takes none of its windows along, so they end up beyond the screen or on the other display. Openbox and xfwm4 carry an unmaximized window along with its monitor by themselves; Marco, Metacity, and KWin leave it where it was, and xfwm4 maximizes a window again on the monitor its restored geometry falls on. Every layout change therefore reads the manager's client list before it moves anything and asks the manager afterwards, through _NET_MOVERESIZE_WINDOW, to move each window by its own display's move and each window of a display that is gone onto the primary (window_moves, _sync_follow_display_moves), once the framebuffer holds the layout, since a manager constrains a move against the screen it has; the desktop window and panels place themselves and are left alone, except that a desktop window its manager left reaching past the screen is asked back to the origin (_sync_seat_desktop_windows).

DPI handling here is X11-only by design: on the Wayland backend a DPI is an output scale on the session compositor (applied in-process through wlr-output-management), never Xft resources — XWayland runs in the compositor's logical space and is scaled with it, so Xft resources merged there would scale applications twice. On X11 a density or cursor size reaches only the session on this display: the daemons told to reload and the settings stores written through a session bus are found by the DISPLAY their processes run with (_pids_on_display, _session_env), never through whatever bus Selkies inherited, since another display's session may share the home and would apply the change live.

attributelogger_app_resize
= logging.getLogger('display')
attributeRect
= Tuple[int, int, int, int]
attributeWAYLAND_SCREEN_OUTPUT_ID
= 0
attributeFIRST_FRAME_WAIT_S
= 5.0
attributeLOST_FRAME_MEMORY
= 64
attributeFRAME_NUM_WRAP
= 16
attributeFRAME_ANCHOR
= 8

On this page

No Headings
Edit on GitHub