[witray] Replace currently running system tray at startup.

This commit is contained in:
Kris Maglione 2010-06-05 04:31:46 -04:00
parent ec26a17464
commit 6724357027
5 changed files with 69 additions and 10 deletions

View File

@ -51,6 +51,8 @@ struct Selection {
void (*cleanup)(Selection*); void (*cleanup)(Selection*);
void (*message)(Selection*, XClientMessageEvent*); void (*message)(Selection*, XClientMessageEvent*);
void (*request)(Selection*, XSelectionRequestEvent*); void (*request)(Selection*, XSelectionRequestEvent*);
long timer;
ulong oldowner;
}; };
struct XEmbed { struct XEmbed {

View File

@ -69,6 +69,8 @@ cleanup(Selection *s) {
while(tray.clients) while(tray.clients)
client_disown(tray.clients); client_disown(tray.clients);
tray.selection = nil;
srv.running = false;
} }
void void
@ -181,6 +183,8 @@ main(int argc, char *argv[]) {
event_xtime, message, cleanup); event_xtime, message, cleanup);
if(tray.selection == nil) if(tray.selection == nil)
fatal("Another system tray is already running."); fatal("Another system tray is already running.");
if(tray.selection->oldowner)
print("Replacing currently running system tray.\n");
xext_init(); xext_init();
tray_init(); tray_init();
@ -198,7 +202,8 @@ main(int argc, char *argv[]) {
srv.running = true; srv.running = true;
ixp_serverloop(&srv); ixp_serverloop(&srv);
selection_release(tray.selection); if(tray.selection)
selection_release(tray.selection);
XCloseDisplay(display); XCloseDisplay(display);

View File

@ -5,6 +5,7 @@
#include "fns.h" #include "fns.h"
static Handlers selection_handlers; static Handlers selection_handlers;
static Handlers steal_handlers;
Selection* Selection*
selection_create(char *selection, ulong time, selection_create(char *selection, ulong time,
@ -47,20 +48,51 @@ selection_create(char *selection, ulong time,
return s; return s;
} }
static void
_selection_manage(Selection *s) {
Dprint("[selection] Notifying.\n");
clientmessage(&scr.root, "MANAGER", SubstructureNotifyMask|StructureNotifyMask, 32,
(ClientMessageData){ .l = {s->time_start, xatom(s->selection), s->owner->xid} });
}
static void
timeout(long timer, void *v) {
Selection *s;
s = v;
Dprint("[selection] Done waiting. Killing 0x%ulx.\n", s->oldowner);
s->timer = 0;
XKillClient(display, s->oldowner);
sync();
}
Selection* Selection*
selection_manage(char *selection, ulong time, selection_manage(char *selection, ulong time,
void (*message)(Selection*, XClientMessageEvent*), void (*message)(Selection*, XClientMessageEvent*),
void (*cleanup)(Selection*)) { void (*cleanup)(Selection*)) {
Selection *s; Selection *s;
Window *w;
XWindow old;
if(XGetSelectionOwner(display, xatom(selection)) != None) if((old = XGetSelectionOwner(display, xatom(selection)))) {
return nil; w = emallocz(sizeof *w);
w->type = WWindow;
w->xid = old;
selectinput(w, StructureNotifyMask);
}
s = selection_create(selection, time, nil, cleanup); s = selection_create(selection, time, nil, cleanup);
if(s) { if(s) {
s->message = message; s->message = message;
clientmessage(&scr.root, "MANAGER", SubstructureNotifyMask|StructureNotifyMask, 32, s->oldowner = old;
(ClientMessageData){ .l = {time, xatom(selection), s->owner->xid} }); if(!old)
_selection_manage(s);
else {
Dprint("[selection] Waiting for old owner %W to die...\n", w);
pushhandler(w, &steal_handlers, s);
s->timer = ixp_settimer(&srv, 2000, timeout, s);
}
} }
return s; return s;
@ -70,9 +102,9 @@ void
selection_release(Selection *s) { selection_release(Selection *s) {
if(!s->time_end) if(!s->time_end)
XSetSelectionOwner(display, xatom(s->selection), None, s->time_start); XSetSelectionOwner(display, xatom(s->selection), None, s->time_start);
destroywindow(s->owner);
if(s->cleanup) if(s->cleanup)
s->cleanup(s); s->cleanup(s);
destroywindow(s->owner);
free(s->selection); free(s->selection);
free(s); free(s);
} }
@ -106,6 +138,7 @@ selectionclear_event(Window *w, void *aux, XSelectionClearEvent *ev) {
Selection *s; Selection *s;
USED(w, ev); USED(w, ev);
Dprint("[selection] Lost selection\n");
s = aux; s = aux;
s->time_end = ev->time; s->time_end = ev->time;
selection_release(s); selection_release(s);
@ -120,6 +153,7 @@ selectionrequest_event(Window *w, void *aux, XSelectionRequestEvent *ev) {
if(ev->property == None) if(ev->property == None)
ev->property = ev->target; /* Per ICCCM §2.2. */ ev->property = ev->target; /* Per ICCCM §2.2. */
Dprint("[selection] Request: %A\n", ev->target);
if(ev->target == xatom("TIMESTAMP")) { if(ev->target == xatom("TIMESTAMP")) {
/* Per ICCCM §2.6.2. */ /* Per ICCCM §2.6.2. */
changeprop_ulong(window(ev->requestor), changeprop_ulong(window(ev->requestor),
@ -142,3 +176,21 @@ static Handlers selection_handlers = {
.selectionrequest = selectionrequest_event, .selectionrequest = selectionrequest_event,
}; };
static bool
destroy_event(Window *w, void *aux, XDestroyWindowEvent *e) {
Selection *s;
Dprint("[selection] Old owner is dead.\n");
s = aux;
if(s->timer)
ixp_unsettimer(&srv, s->timer);
s->timer = 0;
s->oldowner = 0;
_selection_manage(s);
return false;
}
static Handlers steal_handlers = {
.destroy = destroy_event,
};

View File

@ -348,8 +348,8 @@ frame_resize(Frame *f, Rectangle r) {
|| Dy(r) == 0 && (!f->area->max || resizing) || Dy(r) == 0 && (!f->area->max || resizing)
&& !f->collapsed)) { && !f->collapsed)) {
fprint(2, "Frame rect: %R\n", r); fprint(2, "Frame rect: %R\n", r);
r.max.x = min(r.min.x+1, r.max.x); r.max.x = max(r.min.x+1, r.max.x);
r.max.y = min(r.min.y+1, r.max.y); r.max.y = max(r.min.y+1, r.max.y);
} }
c = f->client; c = f->client;

View File

@ -129,7 +129,7 @@ next_keystroke(ulong *mod, KeyCode *code) {
do { do {
XMaskEvent(display, KeyPressMask, &e); XMaskEvent(display, KeyPressMask, &e);
*mod |= e.xkey.state & valid_mask; *mod |= e.xkey.state & valid_mask;
*code = (KeyCode) e.xkey.keycode; *code = (KeyCode)e.xkey.keycode;
sym = XKeycodeToKeysym(display, e.xkey.keycode, 0); sym = XKeycodeToKeysym(display, e.xkey.keycode, 0);
} while(IsModifierKey(sym)); } while(IsModifierKey(sym));
} }
@ -143,7 +143,7 @@ fake_keypress(ulong mod, KeyCode key) {
if(c == nil || c->w.xid == 0) if(c == nil || c->w.xid == 0)
return; return;
e.time = CurrentTime; e.time = event_xtime;
e.window = c->w.xid; e.window = c->w.xid;
e.state = mod; e.state = mod;
e.keycode = key; e.keycode = key;