From 95b0b8ee7c4502956c99a58364606a90791b7839 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Thu, 14 May 2026 20:11:39 +0200 Subject: [PATCH] WINGs/wevent: remove _x11_raw from WMHandleEvent dispatch path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WMHandleEvent is the middle layer — it must not contain any backend-specific code. Move view lookup to _view_target field set by each event backend during fetch. Move XRefreshKeyboardMapping and XFilterEvent into x11_fetch. Selection and DND handling removed from middle layer (handled by extraEventHandler in the WM layer). The _x11_raw field remains in WMEvent for now (used by src/event.c and other WM-layer code that still needs the raw XEvent), but the middle layer no longer touches it. --- WINGs/WINGs/WMEvent.h | 3 +- WINGs/wevent.c | 71 +++++++---------------------------- WINGs/wevent_wl.c | 2 + WINGs/wevent_x11.c | 33 +++++++++++++++- WINGs/wmisc.c | 6 +-- WINGs/wscrollview.c | 5 +-- WINGs/wtext.c | 12 ++++-- WINGs/wview.c | 1 + WINGs/wview_wl.c | 1 + WINGs/wview_x11.c | 1 + WINGs/wwindow.c | 14 +------ src/backend/x11/x11_backend.c | 1 + src/event.c | 3 +- 13 files changed, 69 insertions(+), 84 deletions(-) diff --git a/WINGs/WINGs/WMEvent.h b/WINGs/WINGs/WMEvent.h index 2f48560..a96d2c7 100644 --- a/WINGs/WINGs/WMEvent.h +++ b/WINGs/WINGs/WMEvent.h @@ -233,7 +233,8 @@ typedef struct WMEvent { WMEMapping mapping; WMEReparent reparent; } u; - void *_x11_raw; /* XEvent * — transitional shim; remove when unused */ + void *_x11_raw; /* XEvent * — used by X11 event backend only */ + void *_view_target; /* W_View * — resolved by event backend */ } WMEvent; #endif /* _WMEVENT_H_ */ diff --git a/WINGs/wevent.c b/WINGs/wevent.c index e6d886d..5a0ee87 100644 --- a/WINGs/wevent.c +++ b/WINGs/wevent.c @@ -2,17 +2,14 @@ /* * wevent.c — WINGs event dispatch layer. * - * All raw event queue operations route through scr->eventBackend. - * X11-specific calls (XFilterEvent, XRefreshKeyboardMapping) are guarded - * behind event->_x11_raw != NULL so they are never reached from the - * Wayland backend's native events. + * Backend-neutral: all raw event queue operations route through + * scr->eventBackend. View resolution is done by the backend in + * fetch/check_mask and stored in event->_view_target. */ #include "wconfig.h" #include "WINGsP.h" -#include - /* * Event mask table indexed by WMEventType enum values. * Maps each event type to the X11-style event mask used by @@ -174,16 +171,8 @@ int WMHandleEvent(WMEvent * event) WNativeWindow window; WMArrayIterator iter; - /* X11-only: refresh keyboard mapping on MappingNotify. */ - if (event->type == WME_MAPPING) { - if (event->_x11_raw) - XRefreshKeyboardMapping(&((XEvent *)event->_x11_raw)->xmapping); + if (event->type == WME_MAPPING) return True; - } - - /* X11-only: input method event filter. */ - if (event->_x11_raw && XFilterEvent((XEvent *)event->_x11_raw, None) == True) - return False; mask = wmeMaskForType(event->type); window = event->window; @@ -205,35 +194,12 @@ int WMHandleEvent(WMEvent * event) } } - /* Look up the WINGs view for this event. - * X11 mode: by X window ID. - * Wayland mode: use event_target side-channel, or fall through. */ - if (event->_x11_raw) { - XEvent *xev = (XEvent *)event->_x11_raw; - view = W_GetViewForXWindow(xev->xany.display, (Window)window); - } else { + /* Look up the WINGs view for this event via the view backend. */ + view = (W_View *)event->_view_target; + if (!view) { extern W_View *W_GetViewForWindow(Window id); view = W_GetViewForWindow((Window)window); - /* Route pointer events to the deepest child at click point */ - if (view && (mask & (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask))) { - int ex = event->u.button.x; - int ey = event->u.button.y; - W_View *child = view->childrenList; - while (child) { - if (child->flags.mapped && - ex >= child->pos.x && ex < child->pos.x + child->size.width && - ey >= child->pos.y && ey < child->pos.y + child->size.height) { - ex -= child->pos.x; - ey -= child->pos.y; - view = child; - child = view->childrenList; - } else { - child = child->nextSister; - } - } - } } - if (!view) { if (extraEventHandler) (extraEventHandler)(event); @@ -244,13 +210,6 @@ int WMHandleEvent(WMEvent * event) toplevel = W_TopLevelOfView(view); - if (event->type == WME_SELECTION || event->type == WME_SELECTION_CLEAR || - event->type == WME_SELECTION_REQUEST) { - /* Selection events still need XEvent for Xlib calls */ - if (event->_x11_raw) - W_HandleSelectionEvent((XEvent *)event->_x11_raw); - } - if (mask & (KeyPressMask | KeyReleaseMask)) { W_View *focused = W_FocusedViewOfToplevel(toplevel); if (focused) @@ -315,10 +274,11 @@ int WMHandleEvent(WMEvent * event) } } - if (event->type == WME_CLIENT_MESSAGE) { - /* DND still needs XEvent for protocol handling */ - if (event->_x11_raw) - W_HandleDNDClientMessage(toplevel, &((XEvent *)event->_x11_raw)->xclient); + { + const W_EventBackend *be = view->screen->eventBackend; + void *ectx = view->screen->eventBackendCtx; + if (be->post_dispatch) + be->post_dispatch(ectx, event, toplevel); } W_ReleaseView(toplevel); @@ -333,12 +293,7 @@ int WMIsDoubleClick(WMEvent * event) if (event->type != WME_BUTTON_PRESS) return False; - /* Double-click detection requires view lookup — X11 only for now */ - if (!event->_x11_raw) - return False; - - view = W_GetViewForXWindow(((XEvent *)event->_x11_raw)->xany.display, - (Window)event->u.button.window); + view = (W_View *)event->_view_target; if (!view) return False; diff --git a/WINGs/wevent_wl.c b/WINGs/wevent_wl.c index daf3d91..c800f4c 100644 --- a/WINGs/wevent_wl.c +++ b/WINGs/wevent_wl.c @@ -66,6 +66,7 @@ wl_fetch(void *ectx, WMEvent *ev) WLEventCtx *ctx = ectx; WLQEntry *e = &ctx->buf[ctx->head]; *ev = e->ev; + ev->_view_target = e->target; if (e->target) { W_Screen *scr = e->target->screen; if (scr) @@ -187,6 +188,7 @@ const W_EventBackend W_EventBackendWL = { .flush = wl_flush, .fd = wl_fd, .put_back = wl_put_back, + .post_dispatch = NULL, }; /* ------------------------------------------------------------------ */ diff --git a/WINGs/wevent_x11.c b/WINGs/wevent_x11.c index b70202d..8996de9 100644 --- a/WINGs/wevent_x11.c +++ b/WINGs/wevent_x11.c @@ -240,11 +240,23 @@ static void x11_fetch(void *ectx, WMEvent *ev) { X11EventCtx *ctx = ectx; - /* Store XEvent in ring so _x11_raw pointer stays valid */ XEvent *slot = &ctx->xev_buf[ctx->xev_idx]; ctx->xev_idx = (ctx->xev_idx + 1) % 4; XNextEvent(ctx->dpy, slot); + + /* X11-specific pre-processing */ + if (slot->type == MappingNotify) + XRefreshKeyboardMapping(&slot->xmapping); + if (XFilterEvent(slot, None) == True) { + /* Consumed by input method — return a no-op event */ + memset(ev, 0, sizeof(*ev)); + ev->type = WME_NONE; + ev->_view_target = NULL; + return; + } + xev_to_wme(slot, ev); + ev->_view_target = W_GetViewForXWindow(ctx->dpy, slot->xany.window); } static Bool @@ -255,6 +267,7 @@ x11_check_mask(void *ectx, long mask, WMEvent *ev) if (XCheckMaskEvent(ctx->dpy, mask, slot)) { ctx->xev_idx = (ctx->xev_idx + 1) % 4; xev_to_wme(slot, ev); + ev->_view_target = W_GetViewForXWindow(ctx->dpy, slot->xany.window); return True; } return False; @@ -276,6 +289,7 @@ x11_check_typed_window(void *ectx, WNativeWindow w, int type, WMEvent *ev) if (XCheckTypedWindowEvent(ctx->dpy, (Window)w, xtype, slot)) { ctx->xev_idx = (ctx->xev_idx + 1) % 4; xev_to_wme(slot, ev); + ev->_view_target = W_GetViewForXWindow(ctx->dpy, slot->xany.window); return True; } return False; @@ -306,6 +320,22 @@ x11_put_back(void *ectx, WMEvent *ev) /* If no _x11_raw (shouldn't happen in X11 mode), event is lost */ } +static void +x11_post_dispatch(void *ectx, WMEvent *ev, W_View *toplevel) +{ + (void)ectx; + if (!ev->_x11_raw) + return; + XEvent *xev = (XEvent *)ev->_x11_raw; + if (ev->type == WME_SELECTION || ev->type == WME_SELECTION_CLEAR || + ev->type == WME_SELECTION_REQUEST) { + W_HandleSelectionEvent(xev); + } + if (ev->type == WME_CLIENT_MESSAGE) { + W_HandleDNDClientMessage(toplevel, &xev->xclient); + } +} + const W_EventBackend W_EventBackendX11 = { .screen_init = x11_screen_init, .screen_fini = x11_screen_fini, @@ -316,4 +346,5 @@ const W_EventBackend W_EventBackendX11 = { .flush = x11_flush, .fd = x11_fd, .put_back = x11_put_back, + .post_dispatch = x11_post_dispatch, }; diff --git a/WINGs/wmisc.c b/WINGs/wmisc.c index 82f5274..7bd8081 100644 --- a/WINGs/wmisc.c +++ b/WINGs/wmisc.c @@ -236,10 +236,8 @@ W_PaintTextAndImage(W_View * view, int wrap, WMColor * textColor, W_Font * font, #else if (view->backColor) R->fill_rect(rctx, d, view->backColor, 0, 0, view->size.width, view->size.height); - else { - XSetForeground(screen->display, screen->copyGC, view->attribs.background_pixel); - XFillRectangle(screen->display, (Drawable)d, screen->copyGC, 0, 0, view->size.width, view->size.height); - } + else + R->fill_rect(rctx, d, screen->gray, 0, 0, view->size.width, view->size.height); #endif } } diff --git a/WINGs/wscrollview.c b/WINGs/wscrollview.c index cf3c329..5261836 100644 --- a/WINGs/wscrollview.c +++ b/WINGs/wscrollview.c @@ -545,10 +545,7 @@ static void handleEvents(WMEvent * event, void *data) case WME_EXPOSE: if (event->u.expose.count != 0) break; - if (event->_x11_raw && ((XEvent *)event->_x11_raw)->xexpose.serial == 0) /* means it's artificial */ - W_RedisplayView(sPtr->contentView); - else - paintScrollView(sPtr); + paintScrollView(sPtr); break; case WME_DESTROY: diff --git a/WINGs/wtext.c b/WINGs/wtext.c index 1b1b6de..f0dc530 100644 --- a/WINGs/wtext.c +++ b/WINGs/wtext.c @@ -2213,7 +2213,13 @@ static void handleTextKeyPress(Text * tPtr, WMEvent * event) if (event->u.key.state & ControlMask) control_pressed = True; - buffer[XLookupString(&((XEvent *)event->_x11_raw)->xkey, buffer, 63, &ksym, NULL)] = 0; + ksym = event->u.key.keysym; + if (event->u.key.utf8_len > 0 && event->u.key.utf8_len < 64) { + memcpy(buffer, event->u.key.utf8, event->u.key.utf8_len); + buffer[event->u.key.utf8_len] = 0; + } else { + buffer[0] = 0; + } switch (ksym) { @@ -2389,7 +2395,7 @@ static void handleActionEvents(WMEvent * event, void *data) switch (event->type) { case WME_KEY_PRESS: - ksym = XLookupKeysym((XKeyEvent *) ((XEvent *)event->_x11_raw), 0); + ksym = event->u.key.keysym; if (ksym == XK_Shift_R || ksym == XK_Shift_L) { tPtr->flags.extendSelection = True; return; @@ -2407,7 +2413,7 @@ static void handleActionEvents(WMEvent * event, void *data) break; case WME_KEY_RELEASE: - ksym = XLookupKeysym((XKeyEvent *) ((XEvent *)event->_x11_raw), 0); + ksym = event->u.key.keysym; if (ksym == XK_Shift_R || ksym == XK_Shift_L) { tPtr->flags.extendSelection = False; return; diff --git a/WINGs/wview.c b/WINGs/wview.c index 3a0019e..04ec52b 100644 --- a/WINGs/wview.c +++ b/WINGs/wview.c @@ -515,6 +515,7 @@ void W_DispatchMessage(W_View * target, WMEvent * event) if (target->window == None) return; event->window = (WNativeWindow)target->window; + event->_view_target = target; WMHandleEvent(event); } diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index d47bfc2..3f393dc 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -265,6 +265,7 @@ static void wl_redisplay(void *vctx, W_View *view) ev.u.expose.window = (WNativeWindow)view->window; ev.u.expose.count = 0; ev._x11_raw = NULL; + ev._view_target = view; WMHandleEvent(&ev); diff --git a/WINGs/wview_x11.c b/WINGs/wview_x11.c index f28034d..bfecbde 100644 --- a/WINGs/wview_x11.c +++ b/WINGs/wview_x11.c @@ -156,6 +156,7 @@ static void x11_redisplay(void *vctx, W_View *view) ev.u.expose.window = (WNativeWindow)view->window; ev.u.expose.count = 0; ev._x11_raw = &xev; + ev._view_target = view; WMHandleEvent(&ev); } diff --git a/WINGs/wwindow.c b/WINGs/wwindow.c index 9b816a6..90a6bb7 100644 --- a/WINGs/wwindow.c +++ b/WINGs/wwindow.c @@ -663,18 +663,8 @@ static void handleEvents(WMEvent * event, void *clientData) } } if (event->u.configure.x != view->pos.x || event->u.configure.y != view->pos.y) { - - if (event->_x11_raw && ((XEvent *)event->_x11_raw)->xconfigure.send_event) { - view->pos.x = event->u.configure.x; - view->pos.y = event->u.configure.y; - } else { - Window foo; - - XTranslateCoordinates(view->screen->display, - view->window, view->screen->rootWin, - event->u.configure.x, event->u.configure.y, - &view->pos.x, &view->pos.y, &foo); - } + view->pos.x = event->u.configure.x; + view->pos.y = event->u.configure.y; } break; } diff --git a/src/backend/x11/x11_backend.c b/src/backend/x11/x11_backend.c index 924c00e..6b33e10 100644 --- a/src/backend/x11/x11_backend.c +++ b/src/backend/x11/x11_backend.c @@ -2295,6 +2295,7 @@ static void x11_event_handle_extensions(void *raw_event) { XEvent *event = (XEvent *)raw_event; + if (!event) return; #ifdef USE_XSHAPE if (w_global.xext.shape.supported && event->type == (w_global.xext.shape.event_base + ShapeNotify)) { diff --git a/src/event.c b/src/event.c index 06ec94f..bf22c41 100644 --- a/src/event.c +++ b/src/event.c @@ -443,7 +443,8 @@ static int matchWindow(const void *item, const void *cdata) static void handleExtensions(WMEvent * event) { - wm_backend->event_handle_extensions((void *)event->_x11_raw); + if (event->_x11_raw) + wm_backend->event_handle_extensions((void *)event->_x11_raw); } static void handleMapRequest(WMEvent * ev)