mirror of
https://github.com/0intro/wmii
synced 2024-11-24 22:59:45 +03:00
[witray] Replace currently running system tray at startup.
This commit is contained in:
parent
ec26a17464
commit
6724357027
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user