From 6aad540b889c752dec030d3d455b1dac67984a1e Mon Sep 17 00:00:00 2001 From: Christophe CURIS Date: Thu, 14 May 2015 18:55:34 +0200 Subject: [PATCH] wmaker: support providing ICCCM version, for compliance with the standard The standard specify that the pseudo-selection which is used to cooperatively replace window managers should actually contain the version of the ICCCM standard which is supported. As this could be handy for compatibility checks in the future, let Window Maker comply. Signed-off-by: Christophe CURIS --- src/event.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/event.c b/src/event.c index 71450fce..a6a54026 100644 --- a/src/event.c +++ b/src/event.c @@ -37,6 +37,7 @@ #include #include +#include #ifdef USE_XSHAPE # include #endif @@ -103,6 +104,7 @@ static void handleFocusIn(XEvent *event); static void handleMotionNotify(XEvent *event); static void handleVisibilityNotify(XEvent *event); static void handle_inotify_events(void); +static void handle_selection_request(XSelectionRequestEvent *event); static void handle_selection_clear(XSelectionClearEvent *event); static void wdelete_death_handler(WMagicNumber id); @@ -275,6 +277,10 @@ void DispatchEvent(XEvent * event) #endif break; + case SelectionRequest: + handle_selection_request(&event->xselectionrequest); + break; + case SelectionClear: handle_selection_clear(&event->xselectionclear); break; @@ -1892,6 +1898,79 @@ static void handleVisibilityNotify(XEvent * event) wwin->flags.obscured = (event->xvisibility.state == VisibilityFullyObscured); } +static void handle_selection_request(XSelectionRequestEvent *event) +{ +#ifdef USE_ICCCM_WMREPLACE + static Atom atom_version = None; + WScreen *scr; + XSelectionEvent notify; + + /* + * 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, + XA_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 */ + XSendEvent(dpy, event->requestor, False, 0L, (XEvent *) ¬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