wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit 67243570270ce12a70883bda00b869d7d98ba58c
parent ec26a17464bda3aa901df6658c0d1d8e5b222c0d
Author: Kris Maglione <kris@suckless.org>
Date:   Sat,  5 Jun 2010 04:31:46 -0400

[witray] Replace currently running system tray at startup.

Diffstat:
cmd/tray/dat.h | 2++
cmd/tray/main.c | 7++++++-
cmd/tray/selection.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
cmd/wmii/frame.c | 4++--
cmd/wmii/key.c | 4++--
5 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/cmd/tray/dat.h b/cmd/tray/dat.h @@ -51,6 +51,8 @@ struct Selection { void (*cleanup)(Selection*); void (*message)(Selection*, XClientMessageEvent*); void (*request)(Selection*, XSelectionRequestEvent*); + long timer; + ulong oldowner; }; struct XEmbed { diff --git a/cmd/tray/main.c b/cmd/tray/main.c @@ -69,6 +69,8 @@ cleanup(Selection *s) { while(tray.clients) client_disown(tray.clients); + tray.selection = nil; + srv.running = false; } void @@ -181,6 +183,8 @@ main(int argc, char *argv[]) { event_xtime, message, cleanup); if(tray.selection == nil) fatal("Another system tray is already running."); + if(tray.selection->oldowner) + print("Replacing currently running system tray.\n"); xext_init(); tray_init(); @@ -198,7 +202,8 @@ main(int argc, char *argv[]) { srv.running = true; ixp_serverloop(&srv); - selection_release(tray.selection); + if(tray.selection) + selection_release(tray.selection); XCloseDisplay(display); diff --git a/cmd/tray/selection.c b/cmd/tray/selection.c @@ -5,6 +5,7 @@ #include "fns.h" static Handlers selection_handlers; +static Handlers steal_handlers; Selection* selection_create(char *selection, ulong time, @@ -47,20 +48,51 @@ selection_create(char *selection, ulong time, 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_manage(char *selection, ulong time, void (*message)(Selection*, XClientMessageEvent*), void (*cleanup)(Selection*)) { Selection *s; - - if(XGetSelectionOwner(display, xatom(selection)) != None) - return nil; + Window *w; + XWindow old; + + if((old = XGetSelectionOwner(display, xatom(selection)))) { + w = emallocz(sizeof *w); + w->type = WWindow; + w->xid = old; + selectinput(w, StructureNotifyMask); + } s = selection_create(selection, time, nil, cleanup); if(s) { s->message = message; - clientmessage(&scr.root, "MANAGER", SubstructureNotifyMask|StructureNotifyMask, 32, - (ClientMessageData){ .l = {time, xatom(selection), s->owner->xid} }); + s->oldowner = old; + 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; @@ -70,9 +102,9 @@ void selection_release(Selection *s) { if(!s->time_end) XSetSelectionOwner(display, xatom(s->selection), None, s->time_start); - destroywindow(s->owner); if(s->cleanup) s->cleanup(s); + destroywindow(s->owner); free(s->selection); free(s); } @@ -106,6 +138,7 @@ selectionclear_event(Window *w, void *aux, XSelectionClearEvent *ev) { Selection *s; USED(w, ev); + Dprint("[selection] Lost selection\n"); s = aux; s->time_end = ev->time; selection_release(s); @@ -120,6 +153,7 @@ selectionrequest_event(Window *w, void *aux, XSelectionRequestEvent *ev) { if(ev->property == None) ev->property = ev->target; /* Per ICCCM §2.2. */ + Dprint("[selection] Request: %A\n", ev->target); if(ev->target == xatom("TIMESTAMP")) { /* Per ICCCM §2.6.2. */ changeprop_ulong(window(ev->requestor), @@ -142,3 +176,21 @@ static Handlers selection_handlers = { .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, +}; + diff --git a/cmd/wmii/frame.c b/cmd/wmii/frame.c @@ -348,8 +348,8 @@ frame_resize(Frame *f, Rectangle r) { || Dy(r) == 0 && (!f->area->max || resizing) && !f->collapsed)) { fprint(2, "Frame rect: %R\n", r); - r.max.x = min(r.min.x+1, r.max.x); - r.max.y = min(r.min.y+1, r.max.y); + r.max.x = max(r.min.x+1, r.max.x); + r.max.y = max(r.min.y+1, r.max.y); } c = f->client; diff --git a/cmd/wmii/key.c b/cmd/wmii/key.c @@ -129,7 +129,7 @@ next_keystroke(ulong *mod, KeyCode *code) { do { XMaskEvent(display, KeyPressMask, &e); *mod |= e.xkey.state & valid_mask; - *code = (KeyCode) e.xkey.keycode; + *code = (KeyCode)e.xkey.keycode; sym = XKeycodeToKeysym(display, e.xkey.keycode, 0); } while(IsModifierKey(sym)); } @@ -143,7 +143,7 @@ fake_keypress(ulong mod, KeyCode key) { if(c == nil || c->w.xid == 0) return; - e.time = CurrentTime; + e.time = event_xtime; e.window = c->w.xid; e.state = mod; e.keycode = key;