From 945fdd46463e8f5b31a1a83f4432d4af6c283f94 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 24 Oct 2015 12:32:55 +0200 Subject: [PATCH 1/2] Don't steal the _NET_WM_CM_Sn selection (#301) Before becoming the selection owner for _NET_WM_CM_Sn, compton will now check if that selection is already owned (which means that another composite manager is already running). If this check fails, startup will be refused. This behaviour is required by EWMH / ICCCM. Because this should catch all composite managers, the error message that was used before when another manager is already running is reworded to mention that the other manager does not follow EWMH. Signed-off-by: Uli Schlachter --- src/compton.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/compton.c b/src/compton.c index 92d08dc5..a3e2b1cf 100644 --- a/src/compton.c +++ b/src/compton.c @@ -3320,7 +3320,8 @@ xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) { if (ev->request_code == ps->composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows) { - fprintf(stderr, "Another composite manager is already running\n"); + fprintf(stderr, "Another composite manager is already running " + "(and does not handle _NET_WM_CM_Sn correctly)\n"); exit(1); } @@ -4892,6 +4893,7 @@ register_cm(session_t *ps) { if (!ps->o.no_x_selection) { unsigned len = strlen(REGISTER_PROP) + 2; int s = ps->scr; + Atom atom; while (s >= 10) { ++len; @@ -4901,7 +4903,13 @@ register_cm(session_t *ps) { char *buf = malloc(len); snprintf(buf, len, REGISTER_PROP "%d", ps->scr); buf[len - 1] = '\0'; - XSetSelectionOwner(ps->dpy, get_atom(ps, buf), ps->reg_win, 0); + atom = get_atom(ps, buf); + + if (XGetSelectionOwner(ps->dpy, atom) != None) { + fprintf(stderr, "Another composite manager is already running\n"); + return false; + } + XSetSelectionOwner(ps->dpy, atom, ps->reg_win, 0); free(buf); } From 091482159f21c6f3095f438eb8b2c8ae3131fda3 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 24 Oct 2015 12:42:16 +0200 Subject: [PATCH 2/2] Exit when compton loses the _NET_WM_CM_Sn selection Again, this behaviour is required by ICCCM. Signed-off-by: Uli Schlachter --- src/compton.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/compton.c b/src/compton.c index a3e2b1cf..7f9b879f 100644 --- a/src/compton.c +++ b/src/compton.c @@ -4349,6 +4349,16 @@ ev_screen_change_notify(session_t *ps, } } +inline static void +ev_selection_clear(session_t *ps, + XSelectionClearEvent __attribute__((unused)) *ev) { + // The only selection we own is the _NET_WM_CM_Sn selection. + // If we lose that one, we should exit. + fprintf(stderr, "Another composite manager started and " + "took the _NET_WM_CM_Sn selection.\n"); + exit(1); +} + #if defined(DEBUG_EVENTS) || defined(DEBUG_RESTACK) /** * Get a window's name from window ID. @@ -4441,6 +4451,9 @@ ev_handle(session_t *ps, XEvent *ev) { case PropertyNotify: ev_property_notify(ps, (XPropertyEvent *)ev); break; + case SelectionClear: + ev_selection_clear(ps, (XSelectionClearEvent *)ev); + break; default: if (ps->shape_exists && ev->type == ps->shape_event) { ev_shape_notify(ps, (XShapeEvent *) ev);