decompose wl_backend.c: extract wl_extensions.c
This commit is contained in:
parent
c60c20bf49
commit
a9a3f0ff1d
|
|
@ -171,7 +171,8 @@ wmaker_SOURCES += \
|
|||
backend/wayland/wl_signalfd.c \
|
||||
backend/wayland/wl_xkb.c \
|
||||
backend/wayland/wl_badge.c \
|
||||
backend/wayland/wl_fakeleader.c
|
||||
backend/wayland/wl_fakeleader.c \
|
||||
backend/wayland/wl_extensions.c
|
||||
endif
|
||||
|
||||
if USE_NESTED_FUNC
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ frame_timer_cb(void *data)
|
|||
((struct wl_toplevel_view *)((char *)(ptr) - offsetof(struct wl_toplevel_view, field)))
|
||||
|
||||
/* X error handler — defined near the vtable at the bottom of this file. */
|
||||
static int wl_catch_xwayland_error(Display *edpy, XErrorEvent *error);
|
||||
int wl_catch_xwayland_error(Display *edpy, XErrorEvent *error);
|
||||
|
||||
/* Phase 43: forward declaration — defined in the focus section below. */
|
||||
static void wl_focus_set(WNativeWindow win, int revert_to, unsigned long timestamp);
|
||||
|
|
@ -3111,7 +3111,7 @@ wl_display_default_screen(void)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
wl_event_loop_run(void)
|
||||
{
|
||||
if (!wl_state.display)
|
||||
|
|
@ -3303,7 +3303,7 @@ wl_event_loop_run(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
wl_event_loop_terminate(void)
|
||||
{
|
||||
/* Write a byte to the self-pipe. write(2) is async-signal-safe, so this
|
||||
|
|
@ -6065,166 +6065,6 @@ static void wl_monitors_select_events(WScreen *scr) { (void)scr; }
|
|||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Extensions / cursors / error handlers */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void wl_extensions_init(void) {}
|
||||
static void wl_cursors_init(void) {}
|
||||
static WNativeWindow wl_cursor_create_named(const char *name) { (void)name; return WNATIVE_NONE; }
|
||||
static void
|
||||
wl_shape_combine_mask(WNativeWindow win, WNativeWindow mask)
|
||||
{
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (!fb) return;
|
||||
|
||||
pixman_image_t *mask_img = (pixman_image_t *)mask;
|
||||
if (!mask_img) {
|
||||
/* No mask: clear opaque region (accept all input) */
|
||||
wlr_scene_buffer_set_opaque_region(fb->scene_buf, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build a pixman region from the mask image (non-transparent pixels) */
|
||||
int w = pixman_image_get_width(mask_img);
|
||||
int h = pixman_image_get_height(mask_img);
|
||||
uint32_t *data = (uint32_t *)pixman_image_get_data(mask_img);
|
||||
int stride = pixman_image_get_stride(mask_img) / 4;
|
||||
|
||||
pixman_region32_t region;
|
||||
pixman_region32_init(®ion);
|
||||
|
||||
for (int y = 0; y < h; y++) {
|
||||
int run_start = -1;
|
||||
for (int x = 0; x < w; x++) {
|
||||
uint32_t pixel = data[y * stride + x];
|
||||
uint8_t alpha = (pixel >> 24) & 0xFF;
|
||||
if (alpha > 0) {
|
||||
if (run_start < 0) run_start = x;
|
||||
} else {
|
||||
if (run_start >= 0) {
|
||||
pixman_region32_union_rect(®ion, ®ion, run_start, y, x - run_start, 1);
|
||||
run_start = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (run_start >= 0) {
|
||||
pixman_region32_union_rect(®ion, ®ion, run_start, y, w - run_start, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set opaque region for the scene buffer */
|
||||
wlr_scene_buffer_set_opaque_region(fb->scene_buf, ®ion);
|
||||
|
||||
pixman_region32_fini(®ion);
|
||||
}
|
||||
static int
|
||||
wl_catch_xwayland_error(Display *edpy, XErrorEvent *error)
|
||||
{
|
||||
(void)edpy;
|
||||
/* BadMatch on X_SetInputFocus is benign: the target window may not be
|
||||
* viewable yet (e.g. during XWayland startup or between map/unmap).
|
||||
* Silence it so it does not reach Xlib's default handler. */
|
||||
if (error->error_code == BadMatch &&
|
||||
error->request_code == X_SetInputFocus)
|
||||
return 0;
|
||||
/* BadWindow is also common during window teardown; ignore silently. */
|
||||
if (error->error_code == BadWindow)
|
||||
return 0;
|
||||
/* Everything else: print via wwarning and continue. */
|
||||
char buf[256];
|
||||
XGetErrorText(edpy, error->error_code, buf, sizeof(buf));
|
||||
wwarning("wl_backend: X error from XWayland: %s (request %d, resource 0x%lx)",
|
||||
buf, (int)error->request_code, (unsigned long)error->resourceid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* _XDefaultError interposition -----------------------------------------------
|
||||
* libX11's _XDefaultError (called when no user error handler is installed, or
|
||||
* when the user handler IS _XDefaultError itself) calls exit(1) after printing.
|
||||
* In the XWayland bridge the error handler can be temporarily displaced by
|
||||
* WINGs/wrlib save-restore code (selection.c, dragcommon.c, texture.c) between
|
||||
* the time a request is sent and the time its BadMatch reply is received.
|
||||
*
|
||||
* Because libX11 calls _XDefaultError via PLT (confirmed with objdump — it is
|
||||
* a GLOBAL DEFAULT symbol with no version tag), our definition in the wmaker
|
||||
* binary takes precedence over the library version via ELF symbol interposition.
|
||||
* This is the last-resort safety net: even if _XErrorFunction is reset to
|
||||
* _XDefaultError, we never exit on a recoverable X protocol error while the
|
||||
* XWayland connection is open.
|
||||
*/
|
||||
int _XDefaultError(Display *dpy, XErrorEvent *event)
|
||||
{
|
||||
/* Only intercept errors on our XWayland Xlib connection. */
|
||||
if (wl_state.x_display != NULL) {
|
||||
char buf[256] = "unknown";
|
||||
XGetErrorText(dpy, event->error_code, buf, sizeof(buf));
|
||||
wwarning("wl_backend: X error reached _XDefaultError: "
|
||||
"%s (request %d, resource 0x%lx) — suppressing exit",
|
||||
buf, (int)event->request_code,
|
||||
(unsigned long)event->resourceid);
|
||||
return 0;
|
||||
}
|
||||
/* Pure X11 mode (no XWayland connection): behave as libX11 normally would.
|
||||
* x11_backend installs x11_catch_error so _XDefaultError is only reached
|
||||
* for truly unexpected errors — exiting here is the right thing. */
|
||||
fprintf(stderr, "X Error of failed request: error_code=%d request_code=%d\n",
|
||||
(int)event->error_code, (int)event->request_code);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
wl_catch_xwayland_io_error(Display *edpy)
|
||||
{
|
||||
(void)edpy;
|
||||
/* XIO error = the X server closed the connection (e.g. XWayland crashed or
|
||||
* its XWM connection died and it shut down). The default handler calls
|
||||
* exit(1), which then makes XWayland print "(EE) failed to read Wayland
|
||||
* events: Broken pipe" — our exit closes the Wayland socket that XWayland's
|
||||
* client side reads. Intercept it so we can shut down gracefully. */
|
||||
wwarning("wl_backend: X IO error — XWayland connection lost, terminating");
|
||||
/* Trigger graceful shutdown via the event loop. */
|
||||
wl_event_loop_terminate();
|
||||
/* XIO error handlers must not return; call exit directly. */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_register_error_handlers(void)
|
||||
{
|
||||
/* Install a permissive X error handler for the XWayland connection.
|
||||
* The _XDefaultError interposition above provides a last-resort safety
|
||||
* net if any code temporarily displaces this handler. */
|
||||
XSetErrorHandler(wl_catch_xwayland_error);
|
||||
/* Install an XIO error handler so we get a proper log message instead of
|
||||
* the silent exit(1) from Xlib's default handler when XWayland disconnects. */
|
||||
XSetIOErrorHandler(wl_catch_xwayland_io_error);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_texture_alloc_color(WScreen *scr, WMColorRGB *color)
|
||||
{
|
||||
(void) scr; (void) color;
|
||||
}
|
||||
|
||||
static void
|
||||
wl_texture_free_colors(WScreen *scr, unsigned long *pixels, int count)
|
||||
{
|
||||
(void) scr; (void) pixels; (void) count;
|
||||
}
|
||||
|
||||
static GC
|
||||
wl_texture_create_gc(WScreen *scr, unsigned long pixel)
|
||||
{
|
||||
(void) scr; (void) pixel;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
wl_texture_free_gc(GC gc)
|
||||
{
|
||||
(void) gc;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Phase 80: no-op stubs for X11-only operations */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <pixman.h>
|
||||
#include "../../screen.h"
|
||||
#include "wl_types.h"
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Extensions / cursors / error handlers */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
void wl_extensions_init(void) {}
|
||||
void wl_cursors_init(void) {}
|
||||
WNativeWindow wl_cursor_create_named(const char *name) { (void)name; return WNATIVE_NONE; }
|
||||
void
|
||||
wl_shape_combine_mask(WNativeWindow win, WNativeWindow mask)
|
||||
{
|
||||
struct wl_frame_buf *fb = frame_buf_find(win);
|
||||
if (!fb) return;
|
||||
|
||||
pixman_image_t *mask_img = (pixman_image_t *)mask;
|
||||
if (!mask_img) {
|
||||
/* No mask: clear opaque region (accept all input) */
|
||||
wlr_scene_buffer_set_opaque_region(fb->scene_buf, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build a pixman region from the mask image (non-transparent pixels) */
|
||||
int w = pixman_image_get_width(mask_img);
|
||||
int h = pixman_image_get_height(mask_img);
|
||||
uint32_t *data = (uint32_t *)pixman_image_get_data(mask_img);
|
||||
int stride = pixman_image_get_stride(mask_img) / 4;
|
||||
|
||||
pixman_region32_t region;
|
||||
pixman_region32_init(®ion);
|
||||
|
||||
for (int y = 0; y < h; y++) {
|
||||
int run_start = -1;
|
||||
for (int x = 0; x < w; x++) {
|
||||
uint32_t pixel = data[y * stride + x];
|
||||
uint8_t alpha = (pixel >> 24) & 0xFF;
|
||||
if (alpha > 0) {
|
||||
if (run_start < 0) run_start = x;
|
||||
} else {
|
||||
if (run_start >= 0) {
|
||||
pixman_region32_union_rect(®ion, ®ion, run_start, y, x - run_start, 1);
|
||||
run_start = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (run_start >= 0) {
|
||||
pixman_region32_union_rect(®ion, ®ion, run_start, y, w - run_start, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set opaque region for the scene buffer */
|
||||
wlr_scene_buffer_set_opaque_region(fb->scene_buf, ®ion);
|
||||
|
||||
pixman_region32_fini(®ion);
|
||||
}
|
||||
int
|
||||
wl_catch_xwayland_error(Display *edpy, XErrorEvent *error)
|
||||
{
|
||||
(void)edpy;
|
||||
/* BadMatch on X_SetInputFocus is benign: the target window may not be
|
||||
* viewable yet (e.g. during XWayland startup or between map/unmap).
|
||||
* Silence it so it does not reach Xlib's default handler. */
|
||||
if (error->error_code == BadMatch &&
|
||||
error->request_code == X_SetInputFocus)
|
||||
return 0;
|
||||
/* BadWindow is also common during window teardown; ignore silently. */
|
||||
if (error->error_code == BadWindow)
|
||||
return 0;
|
||||
/* Everything else: print via wwarning and continue. */
|
||||
char buf[256];
|
||||
XGetErrorText(edpy, error->error_code, buf, sizeof(buf));
|
||||
wwarning("wl_backend: X error from XWayland: %s (request %d, resource 0x%lx)",
|
||||
buf, (int)error->request_code, (unsigned long)error->resourceid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* _XDefaultError interposition -----------------------------------------------
|
||||
* libX11's _XDefaultError (called when no user error handler is installed, or
|
||||
* when the user handler IS _XDefaultError itself) calls exit(1) after printing.
|
||||
* In the XWayland bridge the error handler can be temporarily displaced by
|
||||
* WINGs/wrlib save-restore code (selection.c, dragcommon.c, texture.c) between
|
||||
* the time a request is sent and the time its BadMatch reply is received.
|
||||
*
|
||||
* Because libX11 calls _XDefaultError via PLT (confirmed with objdump — it is
|
||||
* a GLOBAL DEFAULT symbol with no version tag), our definition in the wmaker
|
||||
* binary takes precedence over the library version via ELF symbol interposition.
|
||||
* This is the last-resort safety net: even if _XErrorFunction is reset to
|
||||
* _XDefaultError, we never exit on a recoverable X protocol error while the
|
||||
* XWayland connection is open.
|
||||
*/
|
||||
int _XDefaultError(Display *dpy, XErrorEvent *event)
|
||||
{
|
||||
/* Only intercept errors on our XWayland Xlib connection. */
|
||||
if (wl_state.x_display != NULL) {
|
||||
char buf[256] = "unknown";
|
||||
XGetErrorText(dpy, event->error_code, buf, sizeof(buf));
|
||||
wwarning("wl_backend: X error reached _XDefaultError: "
|
||||
"%s (request %d, resource 0x%lx) — suppressing exit",
|
||||
buf, (int)event->request_code,
|
||||
(unsigned long)event->resourceid);
|
||||
return 0;
|
||||
}
|
||||
/* Pure X11 mode (no XWayland connection): behave as libX11 normally would.
|
||||
* x11_backend installs x11_catch_error so _XDefaultError is only reached
|
||||
* for truly unexpected errors — exiting here is the right thing. */
|
||||
fprintf(stderr, "X Error of failed request: error_code=%d request_code=%d\n",
|
||||
(int)event->error_code, (int)event->request_code);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
wl_catch_xwayland_io_error(Display *edpy)
|
||||
{
|
||||
(void)edpy;
|
||||
/* XIO error = the X server closed the connection (e.g. XWayland crashed or
|
||||
* its XWM connection died and it shut down). The default handler calls
|
||||
* exit(1), which then makes XWayland print "(EE) failed to read Wayland
|
||||
* events: Broken pipe" — our exit closes the Wayland socket that XWayland's
|
||||
* client side reads. Intercept it so we can shut down gracefully. */
|
||||
wwarning("wl_backend: X IO error — XWayland connection lost, terminating");
|
||||
/* Trigger graceful shutdown via the event loop. */
|
||||
wl_event_loop_terminate();
|
||||
/* XIO error handlers must not return; call exit directly. */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
wl_register_error_handlers(void)
|
||||
{
|
||||
/* Install a permissive X error handler for the XWayland connection.
|
||||
* The _XDefaultError interposition above provides a last-resort safety
|
||||
* net if any code temporarily displaces this handler. */
|
||||
XSetErrorHandler(wl_catch_xwayland_error);
|
||||
/* Install an XIO error handler so we get a proper log message instead of
|
||||
* the silent exit(1) from Xlib's default handler when XWayland disconnects. */
|
||||
XSetIOErrorHandler(wl_catch_xwayland_io_error);
|
||||
}
|
||||
|
||||
void
|
||||
wl_texture_alloc_color(WScreen *scr, WMColorRGB *color)
|
||||
{
|
||||
(void) scr; (void) color;
|
||||
}
|
||||
|
||||
void
|
||||
wl_texture_free_colors(WScreen *scr, unsigned long *pixels, int count)
|
||||
{
|
||||
(void) scr; (void) pixels; (void) count;
|
||||
}
|
||||
|
||||
GC
|
||||
wl_texture_create_gc(WScreen *scr, unsigned long pixel)
|
||||
{
|
||||
(void) scr; (void) pixel;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wl_texture_free_gc(GC gc)
|
||||
{
|
||||
(void) gc;
|
||||
}
|
||||
|
|
@ -518,3 +518,22 @@ void wl_workspace_badge_update(WScreen *scr, WNativeWindow badge_win, RImage *im
|
|||
/* Fake leader declarations (extracted to wl_fakeleader.c) */
|
||||
WNativeWindow wl_fake_leader_create(WScreen *scr);
|
||||
void wl_fake_leader_destroy(WNativeWindow win);
|
||||
|
||||
/* Extensions/cursors/error handlers (extracted to wl_extensions.c) */
|
||||
void wl_extensions_init(void);
|
||||
void wl_cursors_init(void);
|
||||
WNativeWindow wl_cursor_create_named(const char *name);
|
||||
void wl_shape_combine_mask(WNativeWindow win, WNativeWindow mask);
|
||||
int wl_catch_xwayland_error(Display *edpy, XErrorEvent *error);
|
||||
int wl_catch_xwayland_io_error(Display *edpy);
|
||||
void wl_register_error_handlers(void);
|
||||
void wl_texture_alloc_color(WScreen *scr, WMColorRGB *color);
|
||||
void wl_texture_free_colors(WScreen *scr, unsigned long *pixels, int count);
|
||||
GC wl_texture_create_gc(WScreen *scr, unsigned long pixel);
|
||||
void wl_texture_free_gc(GC gc);
|
||||
|
||||
/* Signalfd module (extracted to wl_signalfd.c) */
|
||||
int wl_signalfd_handler(int fd, uint32_t mask, void *data);
|
||||
void wl_handle_inotify_events(void);
|
||||
void wl_event_loop_run(void);
|
||||
void wl_event_loop_terminate(void);
|
||||
|
|
|
|||
Loading…
Reference in New Issue