linsomniac

Untitled

Jul 19th, 2025
1,334
0
4 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.73 KB | None | 0 0
  1. ● TL;DR
  2.  
  3. To find the wl_surface backing an Xwayland X11 Window, you need to:
  4.  
  5. 1. Legacy method: Listen for WL_SURFACE_ID ClientMessage on X11 windows (requires SubstructureRedirect on root
  6. window), extract the surface ID from data.l[0], but beware of race conditions.
  7. 2. Modern method: Use the xwayland-shell-v1 Wayland protocol with WL_SURFACE_SERIAL ClientMessage to establish a
  8. robust, race-free association.
  9.  
  10. For xscreensaver, this requires becoming a hybrid X11/Wayland compositor to properly map screensaver windows, which
  11. is a significant architectural change.
  12.  
  13. ---
  14. Detailed Solution
  15.  
  16. The Problem
  17.  
  18. Xscreensaver currently creates X11 windows that are managed by Xwayland, but these windows have no direct
  19. connection to Wayland surfaces. Under Wayland, the compositor needs to know which wl_surface corresponds to each
  20. X11 window to properly manage and display them.
  21.  
  22. Method 1: Legacy WL_SURFACE_ID Approach
  23.  
  24. When Xwayland creates a wl_surface for an X11 window, it sends a ClientMessage with the WL_SURFACE_ID atom:
  25.  
  26. // In xscreensaver-gfx.c or similar
  27. static void setup_xwayland_surface_tracking(Display *dpy, Window root) {
  28. // Intern the WL_SURFACE_ID atom
  29. Atom wl_surface_id_atom = XInternAtom(dpy, "WL_SURFACE_ID", False);
  30.  
  31. // Select SubstructureRedirect to receive ClientMessages
  32. XSetWindowAttributes attrs;
  33. attrs.event_mask = SubstructureRedirectMask | SubstructureNotifyMask;
  34. XChangeWindowAttributes(dpy, root, CWEventMask, &attrs);
  35. }
  36.  
  37. // In event loop
  38. static void handle_wl_surface_id(XClientMessageEvent *event,
  39. Atom wl_surface_id_atom) {
  40. if (event->message_type == wl_surface_id_atom) {
  41. Window x11_window = event->window;
  42. uint32_t surface_id = event->data.l[0];
  43.  
  44. // Store mapping - but beware of race conditions!
  45. // The surface might already be destroyed
  46. store_window_surface_mapping(x11_window, surface_id);
  47. }
  48. }
  49.  
  50. Problems: Race conditions - the wl_surface might be destroyed before the X11 event is processed.
  51.  
  52. Method 2: Modern xwayland-shell-v1 Protocol
  53.  
  54. This requires xscreensaver to act as a Wayland client and use the xwayland-shell-v1 protocol:
  55.  
  56. // New file: wayland-xwayland.c
  57. #include <wayland-client.h>
  58. #include "xwayland-shell-v1-client-protocol.h"
  59.  
  60. struct xwayland_mapping {
  61. struct wl_surface *surface;
  62. Window x11_window;
  63. uint64_t serial;
  64. };
  65.  
  66. static void handle_wl_surface_serial(XClientMessageEvent *event,
  67. Atom wl_surface_serial_atom,
  68. struct xwayland_shell_v1 *xwayland_shell) {
  69. if (event->message_type == wl_surface_serial_atom) {
  70. Window x11_window = event->window;
  71. uint32_t serial_lo = event->data.l[0];
  72. uint32_t serial_hi = event->data.l[1];
  73.  
  74. // Create xwayland surface association
  75. struct wl_surface *surface = find_surface_for_window(x11_window);
  76. if (surface && xwayland_shell) {
  77. struct xwayland_surface_v1 *xwl_surface =
  78. xwayland_shell_v1_get_xwayland_surface(xwayland_shell, surface);
  79.  
  80. xwayland_surface_v1_set_serial(xwl_surface, serial_lo, serial_hi);
  81. wl_surface_commit(surface);
  82. }
  83. }
  84. }
  85.  
  86. Proposed Implementation for xscreensaver
  87.  
  88. 1. Detect Xwayland vs regular X11:
  89. static Bool is_xwayland(Display *dpy) {
  90. // Check for Xwayland-specific atoms or properties
  91. Atom xwayland_atom = XInternAtom(dpy, "_XWAYLAND_SIGNATURE", True);
  92. return (xwayland_atom != None);
  93. }
  94.  
  95. 2. Create hybrid X11/Wayland connection:
  96. // In driver/wayland-xwayland.c
  97. struct xwayland_context {
  98. struct wl_display *wl_display;
  99. struct xwayland_shell_v1 *xwayland_shell;
  100. Display *x11_display;
  101.  
  102. // Mapping tables
  103. GHashTable *window_to_surface;
  104. GHashTable *surface_to_window;
  105. };
  106.  
  107. static struct xwayland_context *
  108. init_xwayland_context(Display *dpy) {
  109. struct xwayland_context *ctx = calloc(1, sizeof(*ctx));
  110.  
  111. // Connect to Wayland
  112. ctx->wl_display = wl_display_connect(NULL);
  113. ctx->x11_display = dpy;
  114.  
  115. // Bind xwayland-shell protocol
  116. // ... registry handling code ...
  117.  
  118. return ctx;
  119. }
  120.  
  121. 3. Modify window creation in driver/windows.c:
  122. // Add after creating X11 window
  123. if (si->xwayland_context) {
  124. // Create corresponding Wayland surface
  125. struct wl_surface *surface =
  126. wl_compositor_create_surface(si->wayland_compositor);
  127.  
  128. // Wait for WL_SURFACE_SERIAL ClientMessage
  129. // Then associate using xwayland-shell-v1
  130. }
  131.  
  132. Architecture Changes Required
  133.  
  134. 1. Dual Protocol Support: xscreensaver needs to connect to both X11 and Wayland simultaneously
  135. 2. Event Loop Integration: Merge X11 and Wayland event handling
  136. 3. Surface Management: Track X11 window to wl_surface mappings
  137. 4. Compositor Role: Act as a minimal Wayland compositor for screensaver surfaces
  138.  
  139. Challenges
  140.  
  141. 1. Complexity: This essentially makes xscreensaver a hybrid X11/Wayland compositor
  142. 2. Compatibility: Need to maintain pure X11 mode for non-Wayland systems
  143. 3. Security: Wayland's security model prevents screen locking without compositor support
  144. 4. Performance: Double event loop processing might impact responsiveness
  145.  
  146. Alternative Approach
  147.  
  148. Instead of mapping X11 windows to wl_surface, consider creating native Wayland screensavers:
  149. - Port screenhacks to use Wayland directly
  150. - Use wl_shell or xdg_shell for window management
  151. - Implement screen locking via compositor protocols
  152.  
  153. This would be cleaner but requires rewriting all screensaver modules.
Advertisement
Add Comment
Please, Sign In to add comment