arch: eliminate _x11_raw escapes from event.c
Five _x11_raw accesses in shared event.c (the worst architectural leak)
removed by widening vtable signatures and moving X11-only logic into
the X11 backend:
WME_SELECTION_REQUEST / WME_SELECTION_CLEAR
* handle_selection_request/clear functions deleted from event.c
* Reimplemented in x11_backend.c as x11_handle_selection_request/clear
where they read _x11_raw internally and call XChangeProperty etc.
* New vtable slots handle_selection_request / handle_selection_clear
(WMEvent*). Wayland: no-ops (wmaker UI does not own a WM_Sn
selection on the X server).
WME_CONFIGURE
* event_randr_update vtable widened to (WMEvent*).
* Root-window check (DefaultRootWindow) moved into x11 impl.
WME_MAPPING
* Dropped the if (xev) guard — keyboard_mapping_refresh already
took WMEvent*.
WME_SELECTION
* xdnd_process_selection vtable widened to (WMEvent*).
Net: event.c is X11-free except for DefaultRootWindow uses elsewhere
that will be cleaned up in subsequent tasks.
This commit is contained in:
parent
f2e49a8b67
commit
1c1f261fb2
|
|
@ -85,3 +85,4 @@ WindowMaker/menu.*
|
|||
WindowMaker/plmenu
|
||||
WindowMaker/plmenu.*
|
||||
WindowMaker/wmmacros
|
||||
core.*
|
||||
|
|
|
|||
|
|
@ -1215,7 +1215,7 @@ typedef struct WMBackend {
|
|||
* Called from the ConfigureNotify case in the main event switch.
|
||||
* No-op if USE_RANDR is not compiled in (or equivalent).
|
||||
*/
|
||||
void (*event_randr_update)(void *event);
|
||||
void (*event_randr_update)(WMEvent *event);
|
||||
|
||||
/*
|
||||
* Return the current XKB keyboard group (layout index, 0-based).
|
||||
|
|
@ -1807,9 +1807,25 @@ typedef struct WMBackend {
|
|||
/* NETWM/XDND mechanism (Phase 80s) */
|
||||
int (*netwm_process_client_message)(void *xevent);
|
||||
int (*xdnd_process_client_message)(void *xevent);
|
||||
void (*xdnd_process_selection)(void *xevent);
|
||||
void (*xdnd_process_selection)(WMEvent *event);
|
||||
void (*xdnd_make_awareness)(WNativeWindow win);
|
||||
void (*netwm_check_client_hint_change)(WWindow *wwin, void *event);
|
||||
|
||||
/*
|
||||
* ICCCM WM-replacement SelectionRequest / SelectionClear handling.
|
||||
*
|
||||
* The X server delivers SelectionRequest/SelectionClear events for
|
||||
* the WM_Sn selection that wmaker holds when running under X11.
|
||||
* Both handlers need access to the X display, atom interning, and
|
||||
* XChangeProperty — all X11-only. They live in the X11 backend.
|
||||
*
|
||||
* Wayland: the Wayland backend's wmaker UI does not own a WM_Sn
|
||||
* selection on the X server, so these are no-ops. XWayland clients
|
||||
* still receive their own selections via wlroots' data device path
|
||||
* and never reach these slots.
|
||||
*/
|
||||
void (*handle_selection_request)(WMEvent *event);
|
||||
void (*handle_selection_clear)(WMEvent *event);
|
||||
void (*netwm_position_splash)(WWindow *wwin, int *x, int *y, int width, int height);
|
||||
void (*netwm_check_initial_frame_state)(WWindow *wwin);
|
||||
|
||||
|
|
|
|||
|
|
@ -6253,7 +6253,7 @@ static int wl_event_pending(void) { return 0; }
|
|||
static void wl_event_drain_motion(void) {}
|
||||
static void wl_event_discard_enter_leave_until(unsigned long timestamp) { (void)timestamp; }
|
||||
static void wl_event_handle_extensions(void *event) { (void)event; }
|
||||
static void wl_event_randr_update(void *event) { (void)event; }
|
||||
static void wl_event_randr_update(WMEvent *event) { (void)event; }
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Properties */
|
||||
|
|
@ -8876,8 +8876,10 @@ static const char *wl_noop_keysym_to_string(unsigned long ks) { (void)ks; return
|
|||
static int wl_noop_window_get_command(WNativeWindow win, char ***a, int *c) { (void)win; (void)a; *c=0; return 0; }
|
||||
static int wl_noop_netwm_process_client_message(void *x) { (void)x; return 0; }
|
||||
static int wl_noop_xdnd_process_client_message(void *x) { (void)x; return 0; }
|
||||
static void wl_noop_xdnd_process_selection(void *x) { (void)x; }
|
||||
static void wl_noop_xdnd_process_selection(WMEvent *e) { (void)e; }
|
||||
static void wl_noop_xdnd_make_awareness(WNativeWindow w) { (void)w; }
|
||||
static void wl_noop_handle_selection_request(WMEvent *e) { (void)e; }
|
||||
static void wl_noop_handle_selection_clear(WMEvent *e) { (void)e; }
|
||||
static void wl_noop_netwm_check_client_hint_change(WWindow *w, void *e) { (void)w; (void)e; }
|
||||
static void wl_noop_netwm_position_splash(WWindow *w, int *x, int *y, int ww, int h) { (void)w;(void)x;(void)y;(void)ww;(void)h; }
|
||||
static void wl_noop_netwm_check_initial_frame_state(WWindow *w) { (void)w; }
|
||||
|
|
@ -9152,9 +9154,10 @@ const WMBackend wl_backend = {
|
|||
.netwm_process_client_message = wl_noop_netwm_process_client_message,
|
||||
.xdnd_process_client_message = wl_noop_xdnd_process_client_message,
|
||||
.xdnd_process_selection = wl_noop_xdnd_process_selection,
|
||||
.xdnd_make_awareness = wl_noop_xdnd_make_awareness,
|
||||
.netwm_check_client_hint_change = wl_noop_netwm_check_client_hint_change,
|
||||
.xdnd_make_awareness = wl_noop_xdnd_make_awareness, .netwm_check_client_hint_change = wl_noop_netwm_check_client_hint_change,
|
||||
.netwm_position_splash = wl_noop_netwm_position_splash,
|
||||
.netwm_check_initial_frame_state = wl_noop_netwm_check_initial_frame_state,
|
||||
.handle_selection_request = wl_noop_handle_selection_request,
|
||||
.handle_selection_clear = wl_noop_handle_selection_clear,
|
||||
.create_rcontext = wl_create_rcontext,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2339,12 +2339,19 @@ x11_event_handle_extensions(void *raw_event)
|
|||
}
|
||||
|
||||
static void
|
||||
x11_event_randr_update(void *raw_event)
|
||||
x11_event_randr_update(WMEvent *event)
|
||||
{
|
||||
#ifdef USE_RANDR
|
||||
XRRUpdateConfiguration((XEvent *)raw_event);
|
||||
if (!event)
|
||||
return;
|
||||
/* RandR root events only — ignore configure events on regular windows. */
|
||||
if (event->u.configure.window != DefaultRootWindow(dpy))
|
||||
return;
|
||||
XEvent *xev = (XEvent *)event->_x11_raw;
|
||||
if (xev)
|
||||
XRRUpdateConfiguration(xev);
|
||||
#else
|
||||
(void) raw_event;
|
||||
(void) event;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -3553,9 +3560,86 @@ static int x11_xdnd_process_client_message(void *xevent)
|
|||
{
|
||||
return wXDNDProcessClientMessage(&((XEvent *)xevent)->xclient);
|
||||
}
|
||||
static void x11_xdnd_process_selection(void *xevent)
|
||||
static void x11_xdnd_process_selection(WMEvent *event)
|
||||
{
|
||||
wXDNDProcessSelection((XEvent *)xevent);
|
||||
XEvent *xev = event ? (XEvent *)event->_x11_raw : NULL;
|
||||
if (xev)
|
||||
wXDNDProcessSelection(xev);
|
||||
}
|
||||
|
||||
static void x11_handle_selection_request(WMEvent *event)
|
||||
{
|
||||
XEvent *xev = event ? (XEvent *)event->_x11_raw : NULL;
|
||||
if (!xev) return;
|
||||
XSelectionRequestEvent *xsr = &xev->xselectionrequest;
|
||||
#ifdef USE_ICCCM_WMREPLACE
|
||||
static Atom atom_version = None;
|
||||
WScreen *scr;
|
||||
XSelectionEvent notify;
|
||||
|
||||
/* Default reply: 'no selection'. */
|
||||
notify.type = SelectionNotify;
|
||||
notify.display = dpy;
|
||||
notify.requestor = xsr->requestor;
|
||||
notify.selection = xsr->selection;
|
||||
notify.target = xsr->target;
|
||||
notify.property = None;
|
||||
notify.time = xsr->time;
|
||||
|
||||
scr = wScreenForWindow(xsr->owner);
|
||||
if (!scr)
|
||||
goto not_our_selection;
|
||||
if (xsr->owner != scr->info_window)
|
||||
goto not_our_selection;
|
||||
if (xsr->selection != scr->sn_atom)
|
||||
goto not_our_selection;
|
||||
|
||||
if (atom_version == None)
|
||||
atom_version = XInternAtom(dpy, "VERSION", False);
|
||||
|
||||
if (xsr->target == atom_version) {
|
||||
static const long icccm_version[] = { 2, 0 };
|
||||
|
||||
/* ICCCM 2.0: "Communication with the Window Manager by Means of
|
||||
* Selections". Setting the property means the content of the
|
||||
* selection is available. Old clients may pass property=None. */
|
||||
notify.property = (xsr->property == None) ? xsr->target : xsr->property;
|
||||
XChangeProperty(dpy, xsr->requestor, notify.property,
|
||||
WA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *)icccm_version, wlengthof(icccm_version));
|
||||
}
|
||||
|
||||
not_our_selection:
|
||||
if (notify.property == None)
|
||||
wwarning("received SelectionRequest(%s) for target=\"%s\" from "
|
||||
"requestor 0x%lX but we have no answer",
|
||||
XGetAtomName(dpy, xsr->selection),
|
||||
XGetAtomName(dpy, xsr->target),
|
||||
(long)xsr->requestor);
|
||||
|
||||
/* Send the answer to the requestor */
|
||||
wm_backend->client_send_event((WNativeWindow)xsr->requestor, (void *)¬ify);
|
||||
#else
|
||||
(void)xsr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void x11_handle_selection_clear(WMEvent *event)
|
||||
{
|
||||
XEvent *xev = event ? (XEvent *)event->_x11_raw : NULL;
|
||||
if (!xev) return;
|
||||
#ifdef USE_ICCCM_WMREPLACE
|
||||
XSelectionClearEvent *xsc = &xev->xselectionclear;
|
||||
WScreen *scr = wScreenForWindow(xsc->window);
|
||||
if (!scr)
|
||||
return;
|
||||
if (xsc->selection != scr->sn_atom)
|
||||
return;
|
||||
wmessage(_("another window manager is replacing us!"));
|
||||
Shutdown(WSExitMode);
|
||||
#else
|
||||
(void)xev;
|
||||
#endif
|
||||
}
|
||||
static void x11_xdnd_make_awareness(WNativeWindow win)
|
||||
{
|
||||
|
|
@ -4470,6 +4554,8 @@ const WMBackend x11_backend = {
|
|||
.xdnd_process_selection = x11_xdnd_process_selection,
|
||||
.xdnd_make_awareness = x11_xdnd_make_awareness,
|
||||
.netwm_check_client_hint_change = x11_netwm_check_client_hint_change,
|
||||
.handle_selection_request = x11_handle_selection_request,
|
||||
.handle_selection_clear = x11_handle_selection_clear,
|
||||
.netwm_position_splash = x11_netwm_position_splash,
|
||||
.netwm_check_initial_frame_state = x11_netwm_check_initial_frame_state,
|
||||
.create_rcontext = x11_create_rcontext,
|
||||
|
|
|
|||
122
src/event.c
122
src/event.c
|
|
@ -91,8 +91,6 @@ static void handleFocusIn(WMEvent *event);
|
|||
static void handleMotionNotify(WMEvent *event);
|
||||
static void handleVisibilityNotify(WMEvent *event);
|
||||
/* inotify handling moved to x11_backend.c (x11_event_loop_run) */
|
||||
static void handle_selection_request(XSelectionRequestEvent *event);
|
||||
static void handle_selection_clear(XSelectionClearEvent *event);
|
||||
static void wdelete_death_handler(WMagicNumber id);
|
||||
|
||||
|
||||
|
|
@ -245,10 +243,8 @@ void DispatchEvent(WMEvent * event)
|
|||
break;
|
||||
|
||||
case WME_MAPPING:
|
||||
if (event->u.mapping.request == MappingKeyboard || event->u.mapping.request == MappingModifier) {
|
||||
XEvent *xev = (XEvent *)event->_x11_raw;
|
||||
if (xev) wm_backend->keyboard_mapping_refresh(event);
|
||||
}
|
||||
if (event->u.mapping.request == MappingKeyboard || event->u.mapping.request == MappingModifier)
|
||||
wm_backend->keyboard_mapping_refresh(event);
|
||||
break;
|
||||
|
||||
case WME_FOCUS_IN:
|
||||
|
|
@ -260,22 +256,15 @@ void DispatchEvent(WMEvent * event)
|
|||
break;
|
||||
|
||||
case WME_CONFIGURE:
|
||||
if (event->u.configure.window == DefaultRootWindow(dpy))
|
||||
wm_backend->event_randr_update((void *)event->_x11_raw);
|
||||
wm_backend->event_randr_update(event);
|
||||
break;
|
||||
|
||||
case WME_SELECTION_REQUEST:
|
||||
{
|
||||
XEvent *xev = (XEvent *)event->_x11_raw;
|
||||
if (xev) handle_selection_request(&xev->xselectionrequest);
|
||||
}
|
||||
wm_backend->handle_selection_request(event);
|
||||
break;
|
||||
|
||||
case WME_SELECTION_CLEAR:
|
||||
{
|
||||
XEvent *xev = (XEvent *)event->_x11_raw;
|
||||
if (xev) handle_selection_clear(&xev->xselectionclear);
|
||||
}
|
||||
wm_backend->handle_selection_clear(event);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -427,10 +416,8 @@ static void saveTimestamp(WMEvent * event)
|
|||
case WME_SELECTION:
|
||||
w_global.timestamp.last_event = event->u.selection.time;
|
||||
#ifdef USE_DOCK_XDND
|
||||
if (event->type == WME_SELECTION) {
|
||||
XEvent *xev = (XEvent *)event->_x11_raw;
|
||||
if (xev) wm_backend->xdnd_process_selection(xev);
|
||||
}
|
||||
if (event->type == WME_SELECTION)
|
||||
wm_backend->xdnd_process_selection(event);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1973,97 +1960,6 @@ static void handleVisibilityNotify(WMEvent * event)
|
|||
wwin->flags.obscured = (event->u.visibility.state == VisibilityFullyObscured);
|
||||
}
|
||||
|
||||
static void handle_selection_request(XSelectionRequestEvent *event)
|
||||
{
|
||||
#ifdef USE_ICCCM_WMREPLACE
|
||||
static Atom atom_version = None;
|
||||
WScreen *scr;
|
||||
XSelectionEvent notify;
|
||||
/* Selection request/clear handling moved to backend
|
||||
* (X11 backend: x11_handle_selection_request/clear; Wayland: no-op) */
|
||||
|
||||
/*
|
||||
* This event must be sent to the slection requester to not block him
|
||||
*
|
||||
* We create it with the answer 'there is no selection' by default
|
||||
*/
|
||||
notify.type = SelectionNotify;
|
||||
notify.display = dpy;
|
||||
notify.requestor = event->requestor;
|
||||
notify.selection = event->selection;
|
||||
notify.target = event->target;
|
||||
notify.property = None; /* This says that there is no selection */
|
||||
notify.time = event->time;
|
||||
|
||||
scr = wScreenForWindow(event->owner);
|
||||
if (!scr)
|
||||
goto not_our_selection;
|
||||
|
||||
if (event->owner != scr->info_window)
|
||||
goto not_our_selection;
|
||||
|
||||
if (event->selection != scr->sn_atom)
|
||||
goto not_our_selection;
|
||||
|
||||
if (atom_version == None)
|
||||
atom_version = XInternAtom(dpy, "VERSION", False);
|
||||
|
||||
if (event->target == atom_version) {
|
||||
static const long icccm_version[] = { 2, 0 };
|
||||
|
||||
/*
|
||||
* This protocol is defined in ICCCM 2.0:
|
||||
* http://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html
|
||||
* "Communication with the Window Manager by Means of Selections"
|
||||
*/
|
||||
|
||||
/*
|
||||
* Setting the property means the content of the selection is available
|
||||
* According to the ICCCM spec, we need to support being asked for a property
|
||||
* set to 'None' for compatibility with old clients
|
||||
*/
|
||||
notify.property = (event->property == None)?(event->target):(event->property);
|
||||
|
||||
XChangeProperty(dpy, event->requestor, notify.property,
|
||||
WA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) icccm_version, wlengthof(icccm_version));
|
||||
}
|
||||
|
||||
not_our_selection:
|
||||
if (notify.property == None)
|
||||
wwarning("received SelectionRequest(%s) for target=\"%s\" from requestor 0x%lX but we have no answer",
|
||||
XGetAtomName(dpy, event->selection), XGetAtomName(dpy, event->target), (long) event->requestor);
|
||||
|
||||
/* Send the answer to the requestor */
|
||||
wm_backend->client_send_event((WNativeWindow)event->requestor, (void *)¬ify);
|
||||
|
||||
#else
|
||||
/*
|
||||
* If the support for ICCCM window manager replacement was not enabled, we should not receive
|
||||
* this kind of event, so we just ignore it (Conceptually, we should reply with 'SelectionNotify'
|
||||
* event with property set to 'None' to tell that we don't have this selection, but that is a bit
|
||||
* costly for an event that shall never happen).
|
||||
*/
|
||||
(void) event;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void handle_selection_clear(XSelectionClearEvent *event)
|
||||
{
|
||||
#ifdef USE_ICCCM_WMREPLACE
|
||||
WScreen *scr = wScreenForWindow(event->window);
|
||||
|
||||
if (!scr)
|
||||
return;
|
||||
|
||||
if (event->selection != scr->sn_atom)
|
||||
return;
|
||||
|
||||
wmessage(_("another window manager is replacing us!"));
|
||||
Shutdown(WSExitMode);
|
||||
#else
|
||||
/*
|
||||
* If the support for ICCCM window manager replacement was not enabled, we should not receive
|
||||
* this kind of event, so we simply do nothing.
|
||||
*/
|
||||
(void) event;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue