diff --git a/src/compton.c b/src/compton.c index 92d08dc5..7f9b879f 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); } @@ -4348,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. @@ -4440,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); @@ -4892,6 +4906,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 +4916,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); }