changeset: 2807:746394dc7615
tag: tip
user: Kris Maglione <kris_AT_suckless.org>
date: Tue Sep 20 02:49:06 2011 -0400
files: cmd/tray/selection.c
description:
[tray] Add a horrible workaround for broken Qt systray icon implementation. Closes issue #228.
diff -r 1d200a866939 -r 746394dc7615 cmd/tray/selection.c
--- a/cmd/tray/selection.c Mon Sep 19 23:45:42 2011 -0400
+++ b/cmd/tray/selection.c Tue Sep 20 02:49:06 2011 -0400
@@ -7,10 +7,11 @@
static Handlers selection_handlers;
static Handlers steal_handlers;
-Selection*
-selection_create(char *selection, ulong time,
+static Selection*
+_selection_create(char *selection, ulong time,
void (*request)(Selection*, XSelectionRequestEvent*),
- void (*cleanup)(Selection*)) {
+ void (*cleanup)(Selection*),
+ bool lazy) {
Selection *s;
if(time == 0)
@@ -26,31 +27,49 @@
sethandler(s->owner, &selection_handlers);
- XSetSelectionOwner(display, xatom(selection), s->owner->xid, time);
+ if (!lazy) {
+ XSetSelectionOwner(display, xatom(selection), s->owner->xid, time);
- /*
- * There is a race here that ICCCM doesn't mention. It's
- * possible that we've gained and lost the selection in this
- * time, and a client's sent us a selection request. We're
- * required to reply to it, but since we're destroying the
- * window, we'll never hear about it. Since ICCCM doesn't
- * mention it, we assume that other clients behave likewise,
- * and therefore clients must be prepared to deal with such
- * behavior regardless.
- */
- if(XGetSelectionOwner(display, xatom(selection)) != s->owner->xid) {
- destroywindow(s->owner);
- free(s);
- return nil;
+ /*
+ * There is a race here that ICCCM doesn't mention. It's
+ * possible that we've gained and lost the selection in this
+ * time, and a client's sent us a selection request. We're
+ * required to reply to it, but since we're destroying the
+ * window, we'll never hear about it. Since ICCCM doesn't
+ * mention it, we assume that other clients behave likewise,
+ * and therefore clients must be prepared to deal with such
+ * behavior regardless.
+ */
+ if(XGetSelectionOwner(display, xatom(selection)) != s->owner->xid) {
+ destroywindow(s->owner);
+ free(s);
+ return nil;
+ }
}
s->selection = estrdup(selection);
return s;
}
+Selection*
+selection_create(char *selection, ulong time,
+ void (*request)(Selection*, XSelectionRequestEvent*),
+ void (*cleanup)(Selection*)) {
+ return _selection_create(selection, time, request, cleanup, false);
+}
+
static void
_selection_manage(Selection *s) {
+ if (s->oldowner) {
+ Dprint("[selection] Grabbing.\n");
+ XSetSelectionOwner(display, xatom(s->selection), s->owner->xid, s->time_start);
+ if(XGetSelectionOwner(display, xatom(s->selection)) != s->owner->xid) {
+ selection_release(s);
+ return;
+ }
+ }
+
Dprint("[selection] Notifying.\n");
clientmessage(&scr.root, "MANAGER", SubstructureNotifyMask|StructureNotifyMask, 32,
(ClientMessageData){ .l = {s->time_start, xatom(s->selection), s->owner->xid} });
@@ -84,9 +103,18 @@
w->type = WWindow;
w->xid = old;
selectinput(w, StructureNotifyMask);
+
+ /* Hack for broken Qt systray implementation. If it
+ * finds a new system tray running when the old one
+ * dies, it never selects the StructureNotify mask
+ * on it, and therefore never disassociates from it,
+ * and completely ignores any future MANAGER
+ * messages it receives.
+ */
+ XSetSelectionOwner(display, xatom(selection), 0, time);
}
- s = selection_create(selection, time, nil, cleanup);
+ s = _selection_create(selection, time, nil, cleanup, old);
if(s) {
s->message = message;
s->oldowner = old;
@@ -189,8 +217,9 @@
if(s->timer)
ixp_unsettimer(&srv, s->timer);
s->timer = 0;
+
+ _selection_manage(s);
s->oldowner = 0;
- _selection_manage(s);
return false;
}
Received on Tue Sep 20 2011 - 08:49:09 CEST
This archive was generated by hypermail 2.2.0 : Tue Sep 20 2011 - 09:00:08 CEST