mirror of
https://github.com/0intro/wmii
synced 2024-11-25 23:30:24 +03:00
Add witray system tray program.
This commit is contained in:
parent
1dad368d9c
commit
88f0721673
6
PKGBUILD
6
PKGBUILD
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
pkgname="wmii-hg"
|
pkgname="wmii-hg"
|
||||||
pkgver=2637
|
pkgver=2647
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="The latest hg pull of wmii, a lightweight, dynamic window manager for X11"
|
pkgdesc="The latest hg pull of wmii, a lightweight, dynamic window manager for X11"
|
||||||
url="http://wmii.suckless.org"
|
url="http://wmii.suckless.org"
|
||||||
@ -16,8 +16,6 @@ provides=("wmii")
|
|||||||
conflicts=("wmii")
|
conflicts=("wmii")
|
||||||
source=()
|
source=()
|
||||||
|
|
||||||
test -d src || mkdir src
|
|
||||||
ln -snf .. src/wmii
|
|
||||||
FORCE_VER=$(hg tip --template {rev})
|
FORCE_VER=$(hg tip --template {rev})
|
||||||
#_hgroot="http://hg.suckless.org/"
|
#_hgroot="http://hg.suckless.org/"
|
||||||
#_hgrepo="wmii"
|
#_hgrepo="wmii"
|
||||||
@ -32,7 +30,7 @@ build()
|
|||||||
make "${flags[@]}" || return 1
|
make "${flags[@]}" || return 1
|
||||||
make "${flags[@]}" install || return 1
|
make "${flags[@]}" install || return 1
|
||||||
|
|
||||||
mkdir -p $startdir/pkg/etc/X11/sessions
|
install -m644 -D ./debian/file/wmii.desktop $startdir/pkg/etc/X11/sessions/wmii.desktop
|
||||||
install -m644 -D ./LICENSE $startdir/pkg/usr/share/licenses/wmii/LICENSE
|
install -m644 -D ./LICENSE $startdir/pkg/usr/share/licenses/wmii/LICENSE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@ wmiir.c: $(ROOT)/mk/wmii.mk
|
|||||||
|
|
||||||
DIRS = wmii \
|
DIRS = wmii \
|
||||||
menu \
|
menu \
|
||||||
strut
|
strut \
|
||||||
|
tray
|
||||||
TARG = wihack \
|
TARG = wihack \
|
||||||
wmii.rc \
|
wmii.rc \
|
||||||
wmii.sh \
|
wmii.sh \
|
||||||
|
@ -12,7 +12,7 @@ bindings.c: keys.txt Makefile
|
|||||||
TARG = wimenu
|
TARG = wimenu
|
||||||
HFILES= dat.h fns.h
|
HFILES= dat.h fns.h
|
||||||
|
|
||||||
PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama
|
PACKAGES += $(X11PACKAGES)
|
||||||
|
|
||||||
LIBS += -lm $(LIBS9) $(LIBIXP)
|
LIBS += -lm $(LIBS9) $(LIBIXP)
|
||||||
CFLAGS += -DIXP_NEEDAPI=86
|
CFLAGS += -DIXP_NEEDAPI=86
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <ixp.h>
|
||||||
#include <stuff/x.h>
|
#include <stuff/x.h>
|
||||||
#include <stuff/util.h>
|
#include <stuff/util.h>
|
||||||
#include <ixp.h>
|
|
||||||
|
|
||||||
#define BLOCK(x) do { x; }while(0)
|
#define BLOCK(x) do { x; }while(0)
|
||||||
|
|
||||||
|
@ -171,20 +171,6 @@ update_filter(bool print) {
|
|||||||
update_input();
|
update_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
end(IxpConn *c) {
|
|
||||||
|
|
||||||
USED(c);
|
|
||||||
srv.running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
preselect(IxpServer *s) {
|
|
||||||
|
|
||||||
USED(s);
|
|
||||||
event_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum { PointerScreen = -1 };
|
enum { PointerScreen = -1 };
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -224,7 +210,6 @@ main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
quotefmtinstall();
|
quotefmtinstall();
|
||||||
fmtinstall('r', errfmt);
|
fmtinstall('r', errfmt);
|
||||||
address = getenv("WMII_ADDRESS");
|
|
||||||
screen_hint = PointerScreen;
|
screen_hint = PointerScreen;
|
||||||
|
|
||||||
find = strstr;
|
find = strstr;
|
||||||
@ -283,17 +268,18 @@ main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
client_init(address);
|
client_init(address);
|
||||||
|
|
||||||
srv.preselect = preselect;
|
srv.preselect = event_preselect;
|
||||||
ixp_listen(&srv, ConnectionNumber(display), nil, (void (*)(IxpConn*))preselect, end);
|
ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
|
||||||
|
|
||||||
ontop = !strcmp(readctl("bar on "), "top");
|
ontop = !strcmp(readctl("bar on "), "top");
|
||||||
loadcolor(&cnorm, readctl("normcolors "));
|
loadcolor(&cnorm, readctl("normcolors "));
|
||||||
loadcolor(&csel, readctl("focuscolors "));
|
loadcolor(&csel, readctl("focuscolors "));
|
||||||
font = loadfont(readctl("font "));
|
font = loadfont(readctl("font "));
|
||||||
sscanf(readctl("fontpad "), "%d %d %d %d", &font->pad.min.x, &font->pad.max.x,
|
|
||||||
&font->pad.min.x, &font->pad.max.y);
|
|
||||||
if(!font)
|
if(!font)
|
||||||
fatal("Can't load font %q", readctl("font "));
|
fatal("Can't load font %q", readctl("font "));
|
||||||
|
sscanf(readctl("fontpad "), "%d %d %d %d",
|
||||||
|
&font->pad.min.x, &font->pad.max.x,
|
||||||
|
&font->pad.min.x, &font->pad.max.y);
|
||||||
|
|
||||||
cmplbuf = Bfdopen(0, OREAD);
|
cmplbuf = Bfdopen(0, OREAD);
|
||||||
items = populate_list(cmplbuf, false);
|
items = populate_list(cmplbuf, false);
|
||||||
|
@ -255,7 +255,7 @@ menu_show(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kdown_event(Window *w, XKeyEvent *e) {
|
kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||||
char **action, **p;
|
char **action, **p;
|
||||||
char *key;
|
char *key;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
@ -331,7 +331,7 @@ kdown_event(Window *w, XKeyEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expose_event(Window *w, XExposeEvent *e) {
|
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||||
|
|
||||||
USED(w);
|
USED(w);
|
||||||
menu_draw();
|
menu_draw();
|
||||||
|
@ -7,9 +7,8 @@ main.c: $(ROOT)/mk/wmii.mk
|
|||||||
TARG = wistrut
|
TARG = wistrut
|
||||||
HFILES= dat.h fns.h
|
HFILES= dat.h fns.h
|
||||||
|
|
||||||
PACKAGES += $(X11PACKAGES) xext xrandr xinerama
|
PACKAGES += $(X11PACKAGES)
|
||||||
|
|
||||||
LIB = $(LIBIXP)
|
|
||||||
LIBS += -lm $(LIBS9)
|
LIBS += -lm $(LIBS9)
|
||||||
CFLAGS += -DIXP_NEEDAPI=86
|
CFLAGS += -DIXP_NEEDAPI=86
|
||||||
OBJ = main \
|
OBJ = main \
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stuff/x.h>
|
#include <stuff/x.h>
|
||||||
#include <stuff/util.h>
|
#include <stuff/util.h>
|
||||||
#include <ixp.h>
|
|
||||||
|
|
||||||
#ifndef EXTERN
|
#ifndef EXTERN
|
||||||
# define EXTERN extern
|
# define EXTERN extern
|
||||||
|
@ -1,15 +1,6 @@
|
|||||||
|
|
||||||
void debug(int, const char*, ...);
|
|
||||||
void dispatch_event(XEvent*);
|
|
||||||
uint flushevents(long, bool);
|
|
||||||
uint flushenterevents(void);
|
|
||||||
void xevent_loop(void);
|
|
||||||
void xtime_kludge(void);
|
|
||||||
|
|
||||||
void restrut(Window*);
|
void restrut(Window*);
|
||||||
|
|
||||||
void ewmh_getstrut(Window*, Rectangle[4]);
|
void ewmh_getstrut(Window*, Rectangle[4]);
|
||||||
void ewmh_setstrut(Window*, Rectangle[4]);
|
void ewmh_setstrut(Window*, Rectangle[4]);
|
||||||
|
|
||||||
void printevent(XEvent *e);
|
|
||||||
|
|
||||||
|
@ -21,11 +21,6 @@ usage(void) {
|
|||||||
fatal("usage: %s [-HV] <window|class>...\n", argv0);
|
fatal("usage: %s [-HV] <window|class>...\n", argv0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
errfmt(Fmt *f) {
|
|
||||||
return fmtstrcpy(f, ixp_errbuf());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
search_wins(char *pattern) {
|
search_wins(char *pattern) {
|
||||||
ulong *wins;
|
ulong *wins;
|
||||||
@ -135,7 +130,6 @@ main(int argc, char *argv[]) {
|
|||||||
ulong win;
|
ulong win;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
fmtinstall('r', errfmt);
|
|
||||||
fmtinstall('E', fmtevent);
|
fmtinstall('E', fmtevent);
|
||||||
|
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
|
@ -80,22 +80,23 @@ restrut(Window *frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
config(Window *frame, XConfigureEvent *ev) {
|
config_event(Window *frame, void *aux, XConfigureEvent *ev) {
|
||||||
|
|
||||||
frame->r = rectaddpt(Rect(0, 0, ev->width, ev->height),
|
frame->r = rectaddpt(Rect(ev->x, ev->y, ev->width, ev->height),
|
||||||
Pt(ev->x+ev->border_width, ev->y+ev->border_width));
|
Pt(ev->border_width, ev->border_width));
|
||||||
restrut(frame);
|
restrut(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy(Window *w, XDestroyWindowEvent *ev) {
|
destroy_event(Window *w, void *aux, XDestroyWindowEvent *ev) {
|
||||||
USED(w, ev);
|
|
||||||
|
USED(ev);
|
||||||
sethandler(w, nil);
|
sethandler(w, nil);
|
||||||
event_looprunning = windowmap.nmemb > 0;
|
event_looprunning = windowmap.nmemb > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handlers handlers = {
|
Handlers handlers = {
|
||||||
.config = config,
|
.config = config_event,
|
||||||
.destroy = destroy,
|
.destroy = destroy_event,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
22
cmd/tray/Makefile
Normal file
22
cmd/tray/Makefile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
ROOT= ../..
|
||||||
|
include $(ROOT)/mk/hdr.mk
|
||||||
|
include $(ROOT)/mk/wmii.mk
|
||||||
|
|
||||||
|
main.c: $(ROOT)/mk/wmii.mk
|
||||||
|
|
||||||
|
TARG = witray
|
||||||
|
HFILES= dat.h fns.h
|
||||||
|
|
||||||
|
PACKAGES += $(X11PACKAGES)
|
||||||
|
|
||||||
|
LIBS += -lm $(LIBS9) $(LIBIXP)
|
||||||
|
OBJ = \
|
||||||
|
client \
|
||||||
|
ewmh \
|
||||||
|
main \
|
||||||
|
selection \
|
||||||
|
tray \
|
||||||
|
xembed
|
||||||
|
|
||||||
|
include $(ROOT)/mk/one.mk
|
||||||
|
|
190
cmd/tray/client.c
Normal file
190
cmd/tray/client.c
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fns.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static Handlers handlers;
|
||||||
|
|
||||||
|
static void client_cleanup(XEmbed*);
|
||||||
|
|
||||||
|
void
|
||||||
|
client_manage(XWindow w) {
|
||||||
|
Client **cp;
|
||||||
|
Client *c;
|
||||||
|
WinAttr wa;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
c = emallocz(sizeof *c);
|
||||||
|
c->w.type = WWindow;
|
||||||
|
c->w.xid = w;
|
||||||
|
c->w.aux = c;
|
||||||
|
|
||||||
|
Dprint("client_manage(%W)\n", &c->w);
|
||||||
|
|
||||||
|
traperrors(true);
|
||||||
|
XAddToSaveSet(display, w);
|
||||||
|
c->xembed = xembed_swallow(tray.win, &c->w, client_cleanup);
|
||||||
|
if(traperrors(false)) {
|
||||||
|
fprint(1, "client_manage(0x%ulx): Caught error.\n", w);
|
||||||
|
if(c->xembed)
|
||||||
|
xembed_disown(c->xembed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wa.background_pixel = tray.selcolors.bg.pixel;
|
||||||
|
size = max(tray.iconsize / 4, 4);
|
||||||
|
|
||||||
|
c->indicator = createwindow(tray.win, Rect(0, 0, size, size), scr.depth,
|
||||||
|
InputOutput, &wa, CWBackPixel);
|
||||||
|
setborder(c->indicator, 1, tray.selcolors.border);
|
||||||
|
|
||||||
|
sethandler(&c->w, &handlers);
|
||||||
|
|
||||||
|
for(cp=&tray.clients; *cp; cp=&(*cp)->next)
|
||||||
|
;
|
||||||
|
*cp = c;
|
||||||
|
|
||||||
|
tray_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_disown(Client *c) {
|
||||||
|
|
||||||
|
Dprint("client_disown(%W)\n", &c->w);
|
||||||
|
xembed_disown(c->xembed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
client_cleanup(XEmbed *e) {
|
||||||
|
Client **cp;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
c = e->w->aux;
|
||||||
|
destroywindow(c->indicator);
|
||||||
|
|
||||||
|
for(cp=&tray.clients; *cp; cp=&(*cp)->next)
|
||||||
|
if(*cp == c) {
|
||||||
|
*cp = c->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(c);
|
||||||
|
tray_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
Client*
|
||||||
|
client_find(Window *w) {
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
for(c=tray.clients; c; c=c->next)
|
||||||
|
if(&c->w == w)
|
||||||
|
return c;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
message_cancel(Client *c, long id) {
|
||||||
|
Message *m, **mp;
|
||||||
|
|
||||||
|
for(mp=&c->message; (m = *mp) && m->id != id; mp=&m->next)
|
||||||
|
;
|
||||||
|
|
||||||
|
if(m) {
|
||||||
|
*mp = m->next;
|
||||||
|
free(m->msg.data);
|
||||||
|
free(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
client_hasmessage(Client *c) {
|
||||||
|
Message *m;
|
||||||
|
|
||||||
|
for(m=c->message; m; m=m->next)
|
||||||
|
if(m->msg.pos == m->msg.end)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_opcode(Client *c, long message, long l1, long l2, long l3) {
|
||||||
|
Message *m, **mp;
|
||||||
|
|
||||||
|
Dprint("client_opcode(%p, %s, %lx, %lx, %lx)\n",
|
||||||
|
c,
|
||||||
|
message == TrayRequestDock ? "TrayRequestDock" :
|
||||||
|
message == TrayBeginMessage ? "TrayBeginMessage" :
|
||||||
|
message == TrayCancelMessage ? "TrayCancelMessage" :
|
||||||
|
sxprint("%lx", message),
|
||||||
|
l1, l2, l3);
|
||||||
|
|
||||||
|
if(message == TrayBeginMessage)
|
||||||
|
message_cancel(c, l1);
|
||||||
|
else if(message == TrayBeginMessage) {
|
||||||
|
if(l2 > 5 * 1024) /* Don't bother with absurdly large messages. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
m = emallocz(sizeof *m);
|
||||||
|
m->timeout = l1;
|
||||||
|
m->msg = ixp_message(emallocz(l2), l2, MsgPack);
|
||||||
|
m->id = l3;
|
||||||
|
|
||||||
|
/* Add the message to the end of the queue. */
|
||||||
|
for(mp=&c->message; *mp; mp=&(*mp)->next)
|
||||||
|
;
|
||||||
|
*mp = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_message(Client *c, long type, int format, ClientMessageData* data) {
|
||||||
|
Message *m;
|
||||||
|
|
||||||
|
if(format == 8 && type == NET("SYSTEM_TRAY_MESSAGE_DATA")) {
|
||||||
|
/* Append the data to the last incomplete message. */
|
||||||
|
for(m = c->message; m && m->msg.pos >= m->msg.end; m++)
|
||||||
|
;
|
||||||
|
if(m) {
|
||||||
|
memcpy(m->msg.pos, data, min(20, m->msg.end - m->msg.pos));
|
||||||
|
m->msg.pos += min(20, m->msg.end - m->msg.pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
config_event(Window *w, void *aux, XConfigureEvent *e) {
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
c = aux;
|
||||||
|
if(false)
|
||||||
|
movewin(c->indicator, addpt(w->r.min, Pt(1, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
configreq_event(Window *w, void *aux, XConfigureRequestEvent *e) {
|
||||||
|
|
||||||
|
Dprint("configreq_event(%W)\n", w);
|
||||||
|
/* This seems, sadly, to be necessary. */
|
||||||
|
tray_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
map_event(Window *w, void *aux, XMapEvent *e) {
|
||||||
|
|
||||||
|
tray_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unmap_event(Window *w, void *aux, XUnmapEvent *e) {
|
||||||
|
|
||||||
|
tray_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Handlers handlers = {
|
||||||
|
.config = config_event,
|
||||||
|
.configreq = configreq_event,
|
||||||
|
.map = map_event,
|
||||||
|
.unmap = unmap_event,
|
||||||
|
};
|
||||||
|
|
82
cmd/tray/dat.h
Normal file
82
cmd/tray/dat.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include <fmt.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ixp.h>
|
||||||
|
#include <stuff/x.h>
|
||||||
|
#include <stuff/util.h>
|
||||||
|
|
||||||
|
#ifndef EXTERN
|
||||||
|
# define EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { OAuto, OHorizontal, OVertical };
|
||||||
|
|
||||||
|
enum XEmbedFlags {
|
||||||
|
XEmbedMapped = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TrayOpcodes {
|
||||||
|
TrayRequestDock,
|
||||||
|
TrayBeginMessage,
|
||||||
|
TrayCancelMessage,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Client Client;
|
||||||
|
typedef struct Message Message;
|
||||||
|
typedef struct Selection Selection;
|
||||||
|
typedef struct XEmbed XEmbed;
|
||||||
|
|
||||||
|
struct Client {
|
||||||
|
Client* next;
|
||||||
|
XEmbed* xembed;
|
||||||
|
Window w;
|
||||||
|
Window* indicator;
|
||||||
|
Message* message;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message {
|
||||||
|
Message* next;
|
||||||
|
long id;
|
||||||
|
ulong timeout;
|
||||||
|
IxpMsg msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Selection {
|
||||||
|
Window* owner;
|
||||||
|
char* selection;
|
||||||
|
ulong time_start;
|
||||||
|
ulong time_end;
|
||||||
|
void (*cleanup)(Selection*);
|
||||||
|
void (*message)(Selection*, XClientMessageEvent*);
|
||||||
|
void (*request)(Selection*, XSelectionRequestEvent*);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XEmbed {
|
||||||
|
Window* w;
|
||||||
|
Window* owner;
|
||||||
|
void (*cleanup)(XEmbed*);
|
||||||
|
int version;
|
||||||
|
ulong flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
EXTERN IxpServer srv;
|
||||||
|
EXTERN char** program_args;
|
||||||
|
EXTERN int debug;
|
||||||
|
|
||||||
|
EXTERN struct {
|
||||||
|
Window* win;
|
||||||
|
Image* pixmap;
|
||||||
|
Client* clients;
|
||||||
|
Selection* selection;
|
||||||
|
char* tags;
|
||||||
|
ulong iconsize;
|
||||||
|
ulong padding;
|
||||||
|
long edge;
|
||||||
|
int orientation;
|
||||||
|
Font* font;
|
||||||
|
CTuple selcolors;
|
||||||
|
CTuple normcolors;
|
||||||
|
} tray;
|
||||||
|
|
45
cmd/tray/ewmh.c
Normal file
45
cmd/tray/ewmh.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "dat.h"
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "fns.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Left, Right, Top, Bottom,
|
||||||
|
LeftMin, LeftMax,
|
||||||
|
RightMin, RightMax,
|
||||||
|
TopMin, TopMax,
|
||||||
|
BottomMin, BottomMax,
|
||||||
|
Last
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
ewmh_setstrut(Window *w, Rectangle struts[4]) {
|
||||||
|
long strut[Last];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
strut[LeftMin] = struts[Left].min.y;
|
||||||
|
strut[Left] = struts[Left].max.x;
|
||||||
|
strut[LeftMax] = struts[Left].max.y;
|
||||||
|
|
||||||
|
strut[RightMin] = struts[Right].min.y;
|
||||||
|
strut[Right] = -struts[Right].min.x;
|
||||||
|
strut[RightMax] = struts[Right].max.y;
|
||||||
|
|
||||||
|
strut[TopMin] = struts[Top].min.x;
|
||||||
|
strut[Top] = struts[Top].max.y;
|
||||||
|
strut[TopMax] = struts[Top].max.x;
|
||||||
|
|
||||||
|
strut[BottomMin] = struts[Bottom].min.x;
|
||||||
|
strut[Bottom] = -struts[Bottom].min.y;
|
||||||
|
strut[BottomMax] = struts[Bottom].max.x;
|
||||||
|
|
||||||
|
for(i=0; i<Last; i++)
|
||||||
|
if(strut[i] < 0)
|
||||||
|
strut[i] = 0;
|
||||||
|
|
||||||
|
changeprop_long(w, Net("WM_STRUT_PARTIAL"), "CARDINAL", strut, nelem(strut));
|
||||||
|
}
|
||||||
|
|
34
cmd/tray/fns.h
Normal file
34
cmd/tray/fns.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
#define Net(x) ("_NET_" x)
|
||||||
|
#define Action(x) ("_NET_WM_ACTION_" x)
|
||||||
|
#define State(x) ("_NET_WM_STATE_" x)
|
||||||
|
#define Type(x) ("_NET_WM_WINDOW_TYPE_" x)
|
||||||
|
#define NET(x) xatom(Net(x))
|
||||||
|
#define ACTION(x) xatom(Action(x))
|
||||||
|
#define STATE(x) xatom(State(x))
|
||||||
|
#define TYPE(x) xatom(Type(x))
|
||||||
|
|
||||||
|
void cleanup(Selection*);
|
||||||
|
Client* client_find(Window*);
|
||||||
|
bool client_hasmessage(Client*);
|
||||||
|
void client_disown(Client*);
|
||||||
|
void client_manage(XWindow);
|
||||||
|
void client_message(Client*, long, int, ClientMessageData*);
|
||||||
|
void client_opcode(Client*, long, long, long, long);
|
||||||
|
void ewmh_setstrut(Window*, Rectangle[4]);
|
||||||
|
int main(int, char*[]);
|
||||||
|
void message(Selection*, XClientMessageEvent*);
|
||||||
|
void message_cancel(Client*, long);
|
||||||
|
void restrut(Window*, int);
|
||||||
|
Selection* selection_create(char*, ulong, void (*)(Selection*, XSelectionRequestEvent*), void (*)(Selection*));
|
||||||
|
Selection* selection_manage(char*, ulong, void (*)(Selection*, XClientMessageEvent*), void (*)(Selection*));
|
||||||
|
void selection_release(Selection*);
|
||||||
|
void tray_init(void);
|
||||||
|
void tray_resize(Rectangle);
|
||||||
|
void tray_update(void);
|
||||||
|
void xembed_disown(XEmbed*);
|
||||||
|
XEmbed* xembed_swallow(Window*, Window*, void (*)(XEmbed*));
|
||||||
|
|
||||||
|
#define Debug if(debug)
|
||||||
|
#define Dprint Debug print
|
||||||
|
|
216
cmd/tray/main.c
Normal file
216
cmd/tray/main.c
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#define EXTERN
|
||||||
|
#include "dat.h"
|
||||||
|
#include <X11/Xproto.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stuff/clientutil.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
#include "fns.h"
|
||||||
|
|
||||||
|
static const char version[] = "witray-"VERSION", "COPYRIGHT"\n";
|
||||||
|
|
||||||
|
static int exitsignal;
|
||||||
|
static struct sigaction sa;
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void) {
|
||||||
|
fprint(2, "usage: %s [-a <address>] [-NESW] [-HV] [-p <padding>] [-s <iconsize>] [-t tags]\n"
|
||||||
|
" %s -v\n", argv0, argv0);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
errfmt(Fmt *f) {
|
||||||
|
return fmtstrcpy(f, ixp_errbuf());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup_handler(int signal) {
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
sigaction(signal, &sa, nil);
|
||||||
|
|
||||||
|
srv.running = false;
|
||||||
|
|
||||||
|
switch(signal) {
|
||||||
|
case SIGTERM:
|
||||||
|
sa.sa_handler = cleanup_handler;
|
||||||
|
sigaction(SIGALRM, &sa, nil);
|
||||||
|
alarm(1);
|
||||||
|
default:
|
||||||
|
exitsignal = signal;
|
||||||
|
break;
|
||||||
|
case SIGALRM:
|
||||||
|
raise(SIGTERM);
|
||||||
|
case SIGINT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_traps(void) {
|
||||||
|
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sa.sa_handler = cleanup_handler;
|
||||||
|
sigaction(SIGINT, &sa, nil);
|
||||||
|
sigaction(SIGTERM, &sa, nil);
|
||||||
|
sigaction(SIGQUIT, &sa, nil);
|
||||||
|
sigaction(SIGHUP, &sa, nil);
|
||||||
|
sigaction(SIGUSR1, &sa, nil);
|
||||||
|
sigaction(SIGUSR2, &sa, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup(Selection *s) {
|
||||||
|
USED(s);
|
||||||
|
|
||||||
|
while(tray.clients)
|
||||||
|
client_disown(tray.clients);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
message(Selection *s, XClientMessageEvent *ev) {
|
||||||
|
Window *w;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
USED(s);
|
||||||
|
|
||||||
|
Dprint("message(%s) 0x%lx\n", XGetAtomName(display, ev->message_type), ev->window);
|
||||||
|
Dprint("\t0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n",
|
||||||
|
ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
|
||||||
|
|
||||||
|
w = findwin(ev->window);
|
||||||
|
if(w == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(w == tray.selection->owner) {
|
||||||
|
if(ev->message_type == NET("SYSTEM_TRAY_OPCODE") && ev->format == 32)
|
||||||
|
if(ev->data.l[1] == TrayRequestDock)
|
||||||
|
client_manage(ev->data.l[2]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((c = client_find(w))) {
|
||||||
|
if(ev->message_type == NET("SYSTEM_TRAY_OPCODE") && ev->format == 32)
|
||||||
|
client_opcode(w->aux, ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
|
||||||
|
else
|
||||||
|
client_message(w->aux, ev->message_type, ev->format, (ClientMessageData*)&ev->data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ignored_xerrors[] = {
|
||||||
|
{ 0, BadWindow },
|
||||||
|
{ X_GetAtomName, BadAtom },
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[]) {
|
||||||
|
static char* address;
|
||||||
|
|
||||||
|
program_args = argv;
|
||||||
|
|
||||||
|
setlocale(LC_CTYPE, "");
|
||||||
|
|
||||||
|
fmtinstall('r', errfmt);
|
||||||
|
fmtinstall('E', fmtevent);
|
||||||
|
|
||||||
|
tray.orientation = OHorizontal;
|
||||||
|
tray.tags = "/./";
|
||||||
|
tray.padding = 1;
|
||||||
|
|
||||||
|
ARGBEGIN{
|
||||||
|
case 'N':
|
||||||
|
tray.edge = (tray.edge & ~South) | North;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
tray.edge = (tray.edge & ~North) | South;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
tray.edge = (tray.edge & ~West) | East;
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
tray.edge = (tray.edge & ~East) | West;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
tray.orientation = OHorizontal;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
tray.orientation = OVertical;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if(!getulong(EARGF(usage()), &tray.padding))
|
||||||
|
usage();
|
||||||
|
tray.padding = max(1, min(10, (int)tray.padding));
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if(!getulong(EARGF(usage()), &tray.iconsize))
|
||||||
|
usage();
|
||||||
|
tray.iconsize = max(1, (int)tray.iconsize);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
tray.tags = EARGF(usage());
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
address = EARGF(usage());
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
debug++;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
print("%s", version);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
}ARGEND;
|
||||||
|
|
||||||
|
if(argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
init_traps();
|
||||||
|
initdisplay();
|
||||||
|
|
||||||
|
srv.preselect = event_preselect;
|
||||||
|
ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
|
||||||
|
|
||||||
|
event_updatextime();
|
||||||
|
tray.selection = selection_manage(sxprint(Net("SYSTEM_TRAY_S%d"), scr.screen),
|
||||||
|
event_xtime, message, cleanup);
|
||||||
|
if(tray.selection == nil)
|
||||||
|
fatal("Another system tray is already running.");
|
||||||
|
|
||||||
|
xext_init();
|
||||||
|
tray_init();
|
||||||
|
|
||||||
|
client_init(nil);
|
||||||
|
|
||||||
|
if(tray.edge == 0)
|
||||||
|
tray.edge = West | (!strcmp(readctl("bar on "), "top") ? North : South);
|
||||||
|
|
||||||
|
loadcolor(&tray.normcolors, readctl("normcolors "));
|
||||||
|
loadcolor(&tray.selcolors, readctl("focuscolors "));
|
||||||
|
tray.font = loadfont(readctl("font "));
|
||||||
|
if(!tray.font)
|
||||||
|
fatal("Can't load font %q", readctl("font "));
|
||||||
|
sscanf(readctl("fontpad "), "%d %d %d %d",
|
||||||
|
&tray.font->pad.min.x, &tray.font->pad.max.x,
|
||||||
|
&tray.font->pad.min.x, &tray.font->pad.max.y);
|
||||||
|
|
||||||
|
if(tray.iconsize == 0) /* Default to wmii's bar size. */
|
||||||
|
tray.iconsize = labelh(tray.font) - 2 * tray.padding;
|
||||||
|
|
||||||
|
srv.running = true;
|
||||||
|
ixp_serverloop(&srv);
|
||||||
|
|
||||||
|
selection_release(tray.selection);
|
||||||
|
|
||||||
|
XCloseDisplay(display);
|
||||||
|
|
||||||
|
if(exitsignal)
|
||||||
|
raise(exitsignal);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
144
cmd/tray/selection.c
Normal file
144
cmd/tray/selection.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fns.h"
|
||||||
|
|
||||||
|
static Handlers selection_handlers;
|
||||||
|
|
||||||
|
Selection*
|
||||||
|
selection_create(char *selection, ulong time,
|
||||||
|
void (*request)(Selection*, XSelectionRequestEvent*),
|
||||||
|
void (*cleanup)(Selection*)) {
|
||||||
|
Selection *s;
|
||||||
|
|
||||||
|
if(time == 0)
|
||||||
|
time = event_xtime;
|
||||||
|
|
||||||
|
s = emallocz(sizeof *s);
|
||||||
|
s->owner = createwindow(&scr.root, Rect(0, 0, 1, 1), 0,
|
||||||
|
InputOnly, nil, 0);
|
||||||
|
s->owner->aux = s;
|
||||||
|
s->request = request;
|
||||||
|
s->cleanup = cleanup;
|
||||||
|
s->time_start = time;
|
||||||
|
|
||||||
|
sethandler(s->owner, &selection_handlers);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->selection = estrdup(selection);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <X11/Xlib-xcb.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
Selection*
|
||||||
|
selection_manage(char *selection, ulong time,
|
||||||
|
void (*message)(Selection*, XClientMessageEvent*),
|
||||||
|
void (*cleanup)(Selection*)) {
|
||||||
|
Selection *s;
|
||||||
|
|
||||||
|
if(XGetSelectionOwner(display, xatom(selection)) != None)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
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} });
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
free(s->selection);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
selection_notify(Selection *s, XSelectionRequestEvent *ev, bool success) {
|
||||||
|
XSelectionEvent notify;
|
||||||
|
|
||||||
|
notify.type = SelectionNotify;
|
||||||
|
notify.requestor = ev->requestor;
|
||||||
|
notify.selection = ev->selection;
|
||||||
|
notify.target = ev->target;
|
||||||
|
notify.property = success ? ev->property : None;
|
||||||
|
notify.time = ev->time;
|
||||||
|
|
||||||
|
sendevent(window(ev->requestor), false, 0L, ¬ify);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
message_event(Window *w, void *aux, XClientMessageEvent *ev) {
|
||||||
|
Selection *s;
|
||||||
|
|
||||||
|
s = aux;
|
||||||
|
if(s->message)
|
||||||
|
s->message(s, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
selectionclear_event(Window *w, void *aux, XSelectionClearEvent *ev) {
|
||||||
|
Selection *s;
|
||||||
|
|
||||||
|
USED(w, ev);
|
||||||
|
s = aux;
|
||||||
|
s->time_end = ev->time;
|
||||||
|
selection_release(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
selectionrequest_event(Window *w, void *aux, XSelectionRequestEvent *ev) {
|
||||||
|
Selection *s;
|
||||||
|
|
||||||
|
s = aux;
|
||||||
|
if(ev->property == None)
|
||||||
|
ev->property = ev->target; /* Per ICCCM §2.2. */
|
||||||
|
|
||||||
|
if(ev->target == xatom("TIMESTAMP")) {
|
||||||
|
/* Per ICCCM §2.6.2. */
|
||||||
|
changeprop_ulong(window(ev->requestor),
|
||||||
|
XGetAtomName(display, ev->property), "TIMESTAMP",
|
||||||
|
&s->time_start, 1);
|
||||||
|
selection_notify(s, ev, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s->request)
|
||||||
|
s->request(s, ev);
|
||||||
|
else
|
||||||
|
selection_notify(s, ev, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Handlers selection_handlers = {
|
||||||
|
.message = message_event,
|
||||||
|
.selectionclear = selectionclear_event,
|
||||||
|
.selectionrequest = selectionrequest_event,
|
||||||
|
};
|
||||||
|
|
257
cmd/tray/tray.c
Normal file
257
cmd/tray/tray.c
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "dat.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "fns.h"
|
||||||
|
|
||||||
|
static Handlers handlers;
|
||||||
|
|
||||||
|
void
|
||||||
|
restrut(Window *w, int orientation) {
|
||||||
|
enum { Left, Right, Top, Bottom };
|
||||||
|
Rectangle strut[4];
|
||||||
|
Rectangle r;
|
||||||
|
|
||||||
|
r = w->r;
|
||||||
|
memset(strut, 0, sizeof strut);
|
||||||
|
if(Dx(r) < Dx(scr.rect)/2 && orientation != OHorizontal) {
|
||||||
|
if(r.min.x <= scr.rect.min.x) {
|
||||||
|
strut[Left] = r;
|
||||||
|
strut[Left].min.x = 0;
|
||||||
|
strut[Left].max.x -= scr.rect.min.x;
|
||||||
|
}
|
||||||
|
if(r.max.x >= scr.rect.max.x) {
|
||||||
|
strut[Right] = r;
|
||||||
|
strut[Right].min.x -= scr.rect.max.x;
|
||||||
|
strut[Right].max.x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Dy(r) < Dy(scr.rect)/2 && orientation != OVertical) {
|
||||||
|
if(r.min.y <= scr.rect.min.y) {
|
||||||
|
strut[Top] = r;
|
||||||
|
strut[Top].min.y = 0;
|
||||||
|
strut[Top].max.y -= scr.rect.min.y;
|
||||||
|
}
|
||||||
|
if(r.max.y >= scr.rect.max.y) {
|
||||||
|
strut[Bottom] = r;
|
||||||
|
strut[Bottom].min.y -= scr.rect.max.y;
|
||||||
|
strut[Bottom].max.y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define pstrut(name) \
|
||||||
|
if(!eqrect(strut[name], ZR)) \
|
||||||
|
fprint(2, "strut["#name"] = %R\n", strut[name])
|
||||||
|
pstrut(Left);
|
||||||
|
pstrut(Right);
|
||||||
|
pstrut(Top);
|
||||||
|
pstrut(Bottom);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ewmh_setstrut(w, strut);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tray_init(void) {
|
||||||
|
WinAttr wa;
|
||||||
|
XWMHints hints = { 0, };
|
||||||
|
|
||||||
|
wa.background_pixmap = None;
|
||||||
|
wa.bit_gravity = NorthEastGravity;
|
||||||
|
wa.border_pixel = 0;
|
||||||
|
wa.event_mask = ExposureMask
|
||||||
|
| ButtonPressMask
|
||||||
|
| ButtonReleaseMask
|
||||||
|
| StructureNotifyMask
|
||||||
|
| SubstructureNotifyMask
|
||||||
|
/* Disallow clients reconfiguring themselves. */
|
||||||
|
| SubstructureRedirectMask;
|
||||||
|
if(true)
|
||||||
|
tray.win = createwindow(&scr.root, Rect(0, 0, 1, 1), scr.depth, InputOutput,
|
||||||
|
&wa, CWBackPixmap
|
||||||
|
| CWBitGravity
|
||||||
|
| CWEventMask);
|
||||||
|
else {
|
||||||
|
wa.colormap = XCreateColormap(display, scr.root.xid, scr.visual32, AllocNone);
|
||||||
|
tray.win = createwindow_visual(&scr.root, Rect(0, 0, 1, 1), 32, scr.visual32, InputOutput,
|
||||||
|
&wa, CWBackPixmap
|
||||||
|
| CWBorderPixel
|
||||||
|
| CWColormap
|
||||||
|
| CWBitGravity
|
||||||
|
| CWEventMask);
|
||||||
|
XFreeColormap(display, wa.colormap);
|
||||||
|
}
|
||||||
|
sethandler(tray.win, &handlers);
|
||||||
|
|
||||||
|
changeprop_string(tray.win, "_WMII_TAGS", tray.tags);
|
||||||
|
|
||||||
|
changeprop_ulong(tray.selection->owner, Net("SYSTEM_TRAY_VISUAL"), "VISUALID",
|
||||||
|
&scr.visual->visualid, 1);
|
||||||
|
changeprop_long(tray.win, Net("WM_WINDOW_TYPE"), "ATOM",
|
||||||
|
(long[1]){ TYPE("DOCK") }, 1);
|
||||||
|
|
||||||
|
changeprop_string(tray.win, Net("WM_NAME"), "witray");
|
||||||
|
changeprop_textlist(tray.win, "WM_NAME", "STRING",
|
||||||
|
(char*[2]){ "witray", nil });
|
||||||
|
changeprop_textlist(tray.win, "WM_CLASS", "STRING",
|
||||||
|
(char*[3]){ "witray", "witray", nil });
|
||||||
|
changeprop_textlist(tray.win, "WM_COMMAND", "STRING", program_args);
|
||||||
|
|
||||||
|
hints.flags = InputHint;
|
||||||
|
hints.input = false;
|
||||||
|
XSetWMHints(display, tray.win->xid, &hints);
|
||||||
|
tray_resize(tray.win->r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tray_draw(Rectangle r) {
|
||||||
|
int borderwidth;
|
||||||
|
|
||||||
|
if(!tray.pixmap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
borderwidth = 1;
|
||||||
|
|
||||||
|
r = rectsetorigin(r, ZP);
|
||||||
|
border(tray.pixmap, r, borderwidth, tray.selcolors.border);
|
||||||
|
r = insetrect(r, borderwidth);
|
||||||
|
fill(tray.pixmap, r, tray.selcolors.bg);
|
||||||
|
XClearWindow(display, tray.win->xid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tray_resize(Rectangle r) {
|
||||||
|
WinHints hints;
|
||||||
|
Image *oldimage;
|
||||||
|
WinAttr wa;
|
||||||
|
|
||||||
|
hints = ZWinHints;
|
||||||
|
hints.position = true;
|
||||||
|
hints.min = hints.max = Pt(Dx(r), Dy(r));
|
||||||
|
hints.grav = Pt(tray.edge & East ? 0 :
|
||||||
|
tray.edge & West ? 2 : 1,
|
||||||
|
tray.edge & North ? 0 :
|
||||||
|
tray.edge & South ? 2 : 1);
|
||||||
|
/* Not necessary, since we specify fixed size, but... */
|
||||||
|
// hints.base = Pt(2, 2);
|
||||||
|
// hints.inc = Pt(tray.iconsize, tray.iconsize);
|
||||||
|
sethints(tray.win, &hints);
|
||||||
|
|
||||||
|
if(!eqrect(tray.win->r, r)) {
|
||||||
|
oldimage = tray.pixmap;
|
||||||
|
|
||||||
|
tray.pixmap = allocimage(Dx(r), Dy(r), tray.win->depth);
|
||||||
|
tray_draw(r);
|
||||||
|
wa.background_pixmap = tray.pixmap->xid;
|
||||||
|
setwinattr(tray.win, &wa, CWBackPixmap);
|
||||||
|
|
||||||
|
freeimage(oldimage);
|
||||||
|
}
|
||||||
|
|
||||||
|
reshapewin(tray.win, r);
|
||||||
|
restrut(tray.win, tray.orientation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tray_update(void) {
|
||||||
|
Rectangle r;
|
||||||
|
Point p, offset, padding;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
r = Rect(0, 0, tray.iconsize, tray.iconsize);
|
||||||
|
padding = Pt(tray.padding, tray.padding);
|
||||||
|
offset = padding;
|
||||||
|
Dprint("tray_update()\n");
|
||||||
|
for(c=tray.clients; c; c=c->next) {
|
||||||
|
if(c->w.mapped) {
|
||||||
|
reshapewin(&c->w, rectaddpt(r, offset));
|
||||||
|
/* This seems, sadly, to be necessary. */
|
||||||
|
sendevent(&c->w, false, StructureNotifyMask, &(XEvent){
|
||||||
|
.xconfigure = {
|
||||||
|
.type = ConfigureNotify,
|
||||||
|
.event = c->w.xid,
|
||||||
|
.window = c->w.xid,
|
||||||
|
.above = None,
|
||||||
|
.x = c->w.r.min.x,
|
||||||
|
.y = c->w.r.min.y,
|
||||||
|
.width = Dx(c->w.r),
|
||||||
|
.height = Dy(c->w.r),
|
||||||
|
.border_width = 0,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
movewin(c->indicator, addpt(offset, Pt(2, 2)));
|
||||||
|
if(tray.orientation == OHorizontal)
|
||||||
|
offset.x += tray.iconsize + tray.padding;
|
||||||
|
else
|
||||||
|
offset.y += tray.iconsize + tray.padding;
|
||||||
|
}
|
||||||
|
if(c->w.mapped && client_hasmessage(c))
|
||||||
|
mapwin(c->indicator);
|
||||||
|
else
|
||||||
|
unmapwin(c->indicator);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(eqpt(offset, padding))
|
||||||
|
unmapwin(tray.win);
|
||||||
|
else {
|
||||||
|
if(tray.orientation == OHorizontal)
|
||||||
|
offset.y += tray.iconsize + tray.padding;
|
||||||
|
else
|
||||||
|
offset.x += tray.iconsize + tray.padding;
|
||||||
|
|
||||||
|
r = Rpt(ZP, offset);
|
||||||
|
p = subpt(scr.rect.max, r.max);
|
||||||
|
if(tray.edge & East)
|
||||||
|
p.x = 0;
|
||||||
|
if(tray.edge & North)
|
||||||
|
p.y = 0;
|
||||||
|
tray_resize(rectaddpt(r, p));
|
||||||
|
mapwin(tray.win);
|
||||||
|
}
|
||||||
|
|
||||||
|
tray_draw(tray.win->r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
config_event(Window *w, void *aux, XConfigureEvent *ev) {
|
||||||
|
|
||||||
|
USED(aux);
|
||||||
|
if(ev->send_event) {
|
||||||
|
/*
|
||||||
|
* Per ICCCM §4.2.3, the window manager sends
|
||||||
|
* synthetic configure events in the root coordinate
|
||||||
|
* space when it changes the window configuration.
|
||||||
|
* This code assumes wmii's generous behavior of
|
||||||
|
* supplying all relevant members in every configure
|
||||||
|
* notify event.
|
||||||
|
*/
|
||||||
|
w->r = rectaddpt(rectsetorigin(Rect(0, 0, ev->width, ev->height),
|
||||||
|
Pt(ev->x, ev->y)),
|
||||||
|
Pt(ev->border_width, ev->border_width));
|
||||||
|
restrut(w, tray.orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
expose_event(Window *w, void *aux, XExposeEvent *ev) {
|
||||||
|
|
||||||
|
USED(w, aux, ev);
|
||||||
|
tray_draw(tray.win->r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
message_event(Window *w, void *aux, XClientMessageEvent *ev) {
|
||||||
|
|
||||||
|
Dprint("tray_message: %s\n", XGetAtomName(display, ev->message_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Handlers handlers = {
|
||||||
|
.message = message_event,
|
||||||
|
.config = config_event,
|
||||||
|
.expose = expose_event,
|
||||||
|
};
|
||||||
|
|
128
cmd/tray/xembed.c
Normal file
128
cmd/tray/xembed.c
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fns.h"
|
||||||
|
|
||||||
|
#define DEAD ~0UL
|
||||||
|
|
||||||
|
enum { XEmbedVersion = 0 };
|
||||||
|
|
||||||
|
enum XEmbedMessage {
|
||||||
|
XEmbedEmbeddedNotify,
|
||||||
|
XEmbedWindowActivate,
|
||||||
|
XEmbedWindowDeactivate,
|
||||||
|
XEmbedRequestFocus,
|
||||||
|
XEmbedFocusIn,
|
||||||
|
XEmbedFocusOut,
|
||||||
|
XEmbedFocusNext,
|
||||||
|
XEmbedFocusPrev,
|
||||||
|
XEmbedModalityOn = 10,
|
||||||
|
XEmbedModalityOff,
|
||||||
|
XEmbedRegisterAccelerator,
|
||||||
|
XEmbedUnregisterAccelerator,
|
||||||
|
XEmbedActivateAccelerator,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum XEmbedFocusDetail {
|
||||||
|
XEmbedFocusCurrent,
|
||||||
|
XEmbedFocusFirst,
|
||||||
|
XEmbedFocusLast,
|
||||||
|
};
|
||||||
|
|
||||||
|
static Handlers handlers;
|
||||||
|
|
||||||
|
static void xembed_updateinfo(XEmbed*);
|
||||||
|
static void xembed_sendmessage(XEmbed*, long, long, long, long);
|
||||||
|
|
||||||
|
XEmbed*
|
||||||
|
xembed_swallow(Window *parent, Window *client, void (*cleanup)(XEmbed*)) {
|
||||||
|
XEmbed *xembed;
|
||||||
|
|
||||||
|
xembed = emallocz(sizeof *xembed);
|
||||||
|
xembed->w = client;
|
||||||
|
xembed->owner = parent;
|
||||||
|
xembed->cleanup = cleanup;
|
||||||
|
selectinput(client, client->eventmask | PropertyChangeMask | StructureNotifyMask);
|
||||||
|
pushhandler(client, &handlers, xembed);
|
||||||
|
|
||||||
|
reparentwindow(client, parent, ZP);
|
||||||
|
xembed_updateinfo(xembed);
|
||||||
|
xembed_sendmessage(xembed, XEmbedEmbeddedNotify, 0, parent->xid, min(XEmbedVersion, xembed->version));
|
||||||
|
return xembed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xembed_disown(XEmbed *xembed) {
|
||||||
|
|
||||||
|
pophandler(xembed->w, &handlers);
|
||||||
|
if(xembed->flags != DEAD)
|
||||||
|
reparentwindow(xembed->w, &scr.root, ZP);
|
||||||
|
if(xembed->cleanup)
|
||||||
|
xembed->cleanup(xembed);
|
||||||
|
free(xembed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xembed_updateinfo(XEmbed *xembed) {
|
||||||
|
ulong *res;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = getprop_ulong(xembed->w, "_XEMBED_INFO", "_XEMBED_INFO", 0, &res, 2);
|
||||||
|
xembed->flags = 0UL;
|
||||||
|
if(n >= 2) {
|
||||||
|
xembed->version = res[0];
|
||||||
|
xembed->flags = res[1];
|
||||||
|
}
|
||||||
|
free(res);
|
||||||
|
|
||||||
|
if(xembed->flags & XEmbedMapped)
|
||||||
|
mapwin(xembed->w);
|
||||||
|
else
|
||||||
|
unmapwin(xembed->w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xembed_sendmessage(XEmbed *xembed, long message, long detail, long data1, long data2) {
|
||||||
|
|
||||||
|
traperrors(true);
|
||||||
|
sendmessage(xembed->w, "_XEMBED", event_xtime, message, detail, data1, data2);
|
||||||
|
traperrors(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_event(Window *w, void *aux, XDestroyWindowEvent *ev) {
|
||||||
|
XEmbed *xembed;
|
||||||
|
|
||||||
|
xembed = aux;
|
||||||
|
xembed->flags = DEAD;
|
||||||
|
xembed_disown(xembed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
property_event(Window *w, void *aux, XPropertyEvent *ev) {
|
||||||
|
XEmbed *xembed;
|
||||||
|
|
||||||
|
Dprint("property_event(%W, %p, %s)\n",
|
||||||
|
w, aux, XGetAtomName(display, ev->atom));
|
||||||
|
xembed = aux;
|
||||||
|
if(ev->atom == xatom("_XEMBED_INFO"))
|
||||||
|
xembed_updateinfo(xembed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reparent_event(Window *w, void *aux, XReparentEvent *ev) {
|
||||||
|
XEmbed *xembed;
|
||||||
|
|
||||||
|
xembed = aux;
|
||||||
|
if(ev->parent != xembed->owner->xid) {
|
||||||
|
xembed->flags = DEAD;
|
||||||
|
xembed_disown(xembed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Handlers handlers = {
|
||||||
|
.destroy = destroy_event,
|
||||||
|
.property = property_event,
|
||||||
|
.reparent = reparent_event,
|
||||||
|
};
|
@ -15,6 +15,7 @@ LIBS += -lm $(LIBS9)
|
|||||||
CFLAGS += $(INCICONV) -DIXP_NEEDAPI=97
|
CFLAGS += $(INCICONV) -DIXP_NEEDAPI=97
|
||||||
OBJ = area \
|
OBJ = area \
|
||||||
bar \
|
bar \
|
||||||
|
backtrace \
|
||||||
client \
|
client \
|
||||||
column \
|
column \
|
||||||
div \
|
div \
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
#include <bio.h>
|
#include <bio.h>
|
||||||
#include <plan9.h>
|
#include <plan9.h>
|
||||||
#undef nelem
|
#undef nelem
|
||||||
#include <debug.h>
|
#include <stuff/util.h>
|
||||||
#include "util.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# define PROGTXT "exe"
|
# define PROGTXT "exe"
|
@ -246,7 +246,7 @@ findbar(WMScreen *s, Point p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bdown_event(Window *w, XButtonPressedEvent *e) {
|
bdown_event(Window *w, void *aux, XButtonPressedEvent *e) {
|
||||||
WMScreen *s;
|
WMScreen *s;
|
||||||
Bar *b;
|
Bar *b;
|
||||||
|
|
||||||
@ -254,29 +254,29 @@ bdown_event(Window *w, XButtonPressedEvent *e) {
|
|||||||
XUngrabPointer(display, e->time);
|
XUngrabPointer(display, e->time);
|
||||||
sync();
|
sync();
|
||||||
|
|
||||||
s = w->aux;
|
s = aux;
|
||||||
b = findbar(s, Pt(e->x, e->y));
|
b = findbar(s, Pt(e->x, e->y));
|
||||||
if(b)
|
if(b)
|
||||||
event("%sBarMouseDown %d %s\n", barside[b->bar], e->button, b->name);
|
event("%sBarMouseDown %d %s\n", barside[b->bar], e->button, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bup_event(Window *w, XButtonPressedEvent *e) {
|
bup_event(Window *w, void *aux, XButtonPressedEvent *e) {
|
||||||
WMScreen *s;
|
WMScreen *s;
|
||||||
Bar *b;
|
Bar *b;
|
||||||
|
|
||||||
s = w->aux;
|
s = aux;
|
||||||
b = findbar(s, Pt(e->x, e->y));
|
b = findbar(s, Pt(e->x, e->y));
|
||||||
if(b)
|
if(b)
|
||||||
event("%sBarClick %d %s\n", barside[b->bar], e->button, b->name);
|
event("%sBarClick %d %s\n", barside[b->bar], e->button, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Rectangle
|
static Rectangle
|
||||||
dndmotion_event(Window *w, Point p) {
|
dndmotion_event(Window *w, void *aux, Point p) {
|
||||||
WMScreen *s;
|
WMScreen *s;
|
||||||
Bar *b;
|
Bar *b;
|
||||||
|
|
||||||
s = w->aux;
|
s = aux;
|
||||||
b = findbar(s, p);
|
b = findbar(s, p);
|
||||||
if(b) {
|
if(b) {
|
||||||
event("%sBarDND 1 %s\n", barside[b->bar], b->name);
|
event("%sBarDND 1 %s\n", barside[b->bar], b->name);
|
||||||
@ -286,9 +286,9 @@ dndmotion_event(Window *w, Point p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expose_event(Window *w, XExposeEvent *e) {
|
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||||
USED(w, e);
|
USED(w, e);
|
||||||
bar_draw(w->aux);
|
bar_draw(aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Handlers handlers = {
|
static Handlers handlers = {
|
||||||
|
@ -101,9 +101,8 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
|||||||
c->fullscreen = -1;
|
c->fullscreen = -1;
|
||||||
c->border = wa->border_width;
|
c->border = wa->border_width;
|
||||||
|
|
||||||
c->r.min = Pt(wa->x, wa->y);
|
c->r = rectsetorigin(Rect(0, 0, wa->width, wa->height),
|
||||||
c->r.max = addpt(c->r.min,
|
Pt(wa->x, wa->y));
|
||||||
Pt(wa->width, wa->height));
|
|
||||||
|
|
||||||
c->w.type = WWindow;
|
c->w.type = WWindow;
|
||||||
c->w.xid = w;
|
c->w.xid = w;
|
||||||
@ -115,7 +114,7 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
|||||||
c->ibuf = &ibuf;
|
c->ibuf = &ibuf;
|
||||||
if(render_argb_p(wa->visual)) {
|
if(render_argb_p(wa->visual)) {
|
||||||
depth = 32;
|
depth = 32;
|
||||||
vis = render_visual;
|
vis = scr.visual32;
|
||||||
c->ibuf = &ibuf32;
|
c->ibuf = &ibuf32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +588,7 @@ client_configure(Client *c) {
|
|||||||
e.height = Dy(r);
|
e.height = Dy(r);
|
||||||
e.border_width = c->border;
|
e.border_width = c->border;
|
||||||
|
|
||||||
sendevent(&c->w, false, StructureNotifyMask, (XEvent*)&e);
|
sendevent(&c->w, false, StructureNotifyMask, &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -809,7 +808,7 @@ client_prop(Client *c, Atom a) {
|
|||||||
memset(&h, 0, sizeof h);
|
memset(&h, 0, sizeof h);
|
||||||
if(c->w.hints)
|
if(c->w.hints)
|
||||||
bcopy(c->w.hints, &h, sizeof h);
|
bcopy(c->w.hints, &h, sizeof h);
|
||||||
sethints(&c->w);
|
gethints(&c->w);
|
||||||
if(c->w.hints)
|
if(c->w.hints)
|
||||||
c->fixedsize = eqpt(c->w.hints->min, c->w.hints->max);
|
c->fixedsize = eqpt(c->w.hints->min, c->w.hints->max);
|
||||||
if(memcmp(&h, c->w.hints, sizeof h))
|
if(memcmp(&h, c->w.hints, sizeof h))
|
||||||
@ -841,11 +840,11 @@ client_prop(Client *c, Atom a) {
|
|||||||
|
|
||||||
/* Handlers */
|
/* Handlers */
|
||||||
static void
|
static void
|
||||||
configreq_event(Window *w, XConfigureRequestEvent *e) {
|
configreq_event(Window *w, void *aux, XConfigureRequestEvent *e) {
|
||||||
Rectangle r, cr;
|
Rectangle r, cr;
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
|
|
||||||
r = client_grav(c, ZR);
|
r = client_grav(c, ZR);
|
||||||
r.max = subpt(r.max, r.min);
|
r.max = subpt(r.max, r.min);
|
||||||
@ -875,17 +874,17 @@ configreq_event(Window *w, XConfigureRequestEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_event(Window *w, XDestroyWindowEvent *e) {
|
destroy_event(Window *w, void *aux, XDestroyWindowEvent *e) {
|
||||||
USED(w, e);
|
USED(w, e);
|
||||||
|
|
||||||
client_destroy(w->aux);
|
client_destroy(aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enter_event(Window *w, XCrossingEvent *e) {
|
enter_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
if(e->detail != NotifyInferior) {
|
if(e->detail != NotifyInferior) {
|
||||||
if(e->detail != NotifyVirtual)
|
if(e->detail != NotifyVirtual)
|
||||||
if(e->serial != ignoreenter && disp.focus != c) {
|
if(e->serial != ignoreenter && disp.focus != c) {
|
||||||
@ -898,10 +897,10 @@ enter_event(Window *w, XCrossingEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
focusin_event(Window *w, XFocusChangeEvent *e) {
|
focusin_event(Window *w, void *aux, XFocusChangeEvent *e) {
|
||||||
Client *c, *old;
|
Client *c, *old;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
|
|
||||||
print_focus("focusin_event", c, c->name);
|
print_focus("focusin_event", c, c->name);
|
||||||
|
|
||||||
@ -918,10 +917,10 @@ focusin_event(Window *w, XFocusChangeEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
focusout_event(Window *w, XFocusChangeEvent *e) {
|
focusout_event(Window *w, void *aux, XFocusChangeEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
if((e->mode == NotifyWhileGrabbed) && (disp.hasgrab != &c_root)) {
|
if((e->mode == NotifyWhileGrabbed) && (disp.hasgrab != &c_root)) {
|
||||||
if(disp.focus)
|
if(disp.focus)
|
||||||
disp.hasgrab = disp.focus;
|
disp.hasgrab = disp.focus;
|
||||||
@ -934,34 +933,34 @@ focusout_event(Window *w, XFocusChangeEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unmap_event(Window *w, XUnmapEvent *e) {
|
unmap_event(Window *w, void *aux, XUnmapEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
if(!e->send_event)
|
if(!e->send_event)
|
||||||
c->unmapped--;
|
c->unmapped--;
|
||||||
client_destroy(c);
|
client_destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
map_event(Window *w, XMapEvent *e) {
|
map_event(Window *w, void *aux, XMapEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
USED(e);
|
USED(e);
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
if(c == selclient())
|
if(c == selclient())
|
||||||
client_focus(c);
|
client_focus(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
property_event(Window *w, XPropertyEvent *e) {
|
property_event(Window *w, void *aux, XPropertyEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
if(e->state == PropertyDelete) /* FIXME */
|
if(e->state == PropertyDelete) /* FIXME */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
client_prop(c, e->atom);
|
client_prop(c, e->atom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1002,6 +1001,7 @@ client_setviews(Client *c, char **tags) {
|
|||||||
if(*tags) {
|
if(*tags) {
|
||||||
if(!*fp || cmp > 0) {
|
if(!*fp || cmp > 0) {
|
||||||
f = frame_create(c, view_create(*tags));
|
f = frame_create(c, view_create(*tags));
|
||||||
|
Dprint(DGeneric, "%#C %p %R %R %R %C\n", c, c->sel, c->r, f->floatr, c->sel ? c->sel->floatr : ZR, c);
|
||||||
if(f->view == selview || !c->sel)
|
if(f->view == selview || !c->sel)
|
||||||
c->sel = f;
|
c->sel = f;
|
||||||
kludge = c; /* FIXME */
|
kludge = c; /* FIXME */
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <utf.h>
|
#include <utf.h>
|
||||||
|
#include <ixp.h>
|
||||||
#include <stuff/x.h>
|
#include <stuff/x.h>
|
||||||
#include <stuff/util.h>
|
#include <stuff/util.h>
|
||||||
#include <debug.h>
|
#include "debug.h"
|
||||||
#include <ixp.h>
|
|
||||||
|
|
||||||
#define FONT "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*"
|
#define FONT "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*"
|
||||||
#define FOCUSCOLORS "#ffffff #335577 #447799"
|
#define FOCUSCOLORS "#ffffff #335577 #447799"
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
enum DebugOpt {
|
||||||
|
D9p = 1<<0,
|
||||||
|
DDnd = 1<<1,
|
||||||
|
DEvent = 1<<2,
|
||||||
|
DEwmh = 1<<3,
|
||||||
|
DFocus = 1<<4,
|
||||||
|
DGeneric= 1<<5,
|
||||||
|
DStack = 1<<6,
|
||||||
|
NDebugOpt = 7,
|
||||||
|
};
|
||||||
|
|
||||||
#define Debug(x) if(((debugflag|debugfile)&(x)) && setdebug(x))
|
#define Debug(x) if(((debugflag|debugfile)&(x)) && setdebug(x))
|
||||||
#define Dprint(x, ...) BLOCK( if((debugflag|debugfile)&(x)) debug(x, __VA_ARGS__) )
|
#define Dprint(x, ...) BLOCK( if((debugflag|debugfile)&(x)) debug(x, __VA_ARGS__) )
|
||||||
|
|
@ -164,22 +164,22 @@ div_update_all(void) {
|
|||||||
|
|
||||||
/* Div Handlers */
|
/* Div Handlers */
|
||||||
static void
|
static void
|
||||||
bdown_event(Window *w, XButtonEvent *e) {
|
bdown_event(Window *w, void *aux, XButtonEvent *e) {
|
||||||
Divide *d;
|
Divide *d;
|
||||||
|
|
||||||
USED(e);
|
USED(e);
|
||||||
|
|
||||||
d = w->aux;
|
d = aux;
|
||||||
mouse_resizecol(d);
|
mouse_resizecol(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expose_event(Window *w, XExposeEvent *e) {
|
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||||
Divide *d;
|
Divide *d;
|
||||||
|
|
||||||
USED(e);
|
USED(e);
|
||||||
|
|
||||||
d = w->aux;
|
d = aux;
|
||||||
drawdiv(d);
|
drawdiv(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,15 +10,12 @@ debug_event(XEvent *e) {
|
|||||||
Dprint(DEvent, "%E\n", e);
|
Dprint(DEvent, "%E\n", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define handle(w, fn, ev) \
|
|
||||||
BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev))
|
|
||||||
|
|
||||||
void
|
void
|
||||||
event_buttonpress(XButtonPressedEvent *ev) {
|
event_buttonpress(XButtonPressedEvent *ev) {
|
||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, bdown, ev);
|
event_handle(w, bdown, ev);
|
||||||
else
|
else
|
||||||
XAllowEvents(display, ReplayPointer, ev->time);
|
XAllowEvents(display, ReplayPointer, ev->time);
|
||||||
}
|
}
|
||||||
@ -29,7 +26,7 @@ event_configurenotify(XConfigureEvent *ev) {
|
|||||||
|
|
||||||
ignoreenter = ev->serial;
|
ignoreenter = ev->serial;
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, config, ev);
|
event_handle(w, config, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -47,7 +44,7 @@ event_destroynotify(XDestroyWindowEvent *ev) {
|
|||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, destroy, ev);
|
event_handle(w, destroy, ev);
|
||||||
else if((c = win2client(ev->window)))
|
else if((c = win2client(ev->window)))
|
||||||
fprint(2, "Badness: Unhandled DestroyNotify: Client: %p, Window: %W, Name: %s\n",
|
fprint(2, "Badness: Unhandled DestroyNotify: Client: %p, Window: %W, Name: %s\n",
|
||||||
c, &c->w, c->name);
|
c, &c->w, c->name);
|
||||||
@ -87,7 +84,7 @@ event_focusin(XFocusChangeEvent *ev) {
|
|||||||
disp.focus = nil;
|
disp.focus = nil;
|
||||||
}
|
}
|
||||||
else if((w = findwin(ev->window)))
|
else if((w = findwin(ev->window)))
|
||||||
handle(w, focusin, ev);
|
event_handle(w, focusin, ev);
|
||||||
else if(ev->mode == NotifyGrab) {
|
else if(ev->mode == NotifyGrab) {
|
||||||
/* Some unmanaged window has grabbed focus */
|
/* Some unmanaged window has grabbed focus */
|
||||||
if((c = disp.focus)) {
|
if((c = disp.focus)) {
|
||||||
@ -117,7 +114,7 @@ event_focusout(XFocusChangeEvent *ev) {
|
|||||||
&& XCheckMaskEvent(display, KeyPressMask, &me))
|
&& XCheckMaskEvent(display, KeyPressMask, &me))
|
||||||
event_dispatch(&me);
|
event_dispatch(&me);
|
||||||
else if((w = findwin(ev->window)))
|
else if((w = findwin(ev->window)))
|
||||||
handle(w, focusout, ev);
|
event_handle(w, focusout, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -126,7 +123,7 @@ event_mapnotify(XMapEvent *ev) {
|
|||||||
|
|
||||||
ignoreenter = ev->serial;
|
ignoreenter = ev->serial;
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, map, ev);
|
event_handle(w, map, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -137,7 +134,7 @@ event_unmapnotify(XUnmapEvent *ev) {
|
|||||||
if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) {
|
if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) {
|
||||||
w->mapped = false;
|
w->mapped = false;
|
||||||
if(ev->send_event || w->unmapped-- == 0)
|
if(ev->send_event || w->unmapped-- == 0)
|
||||||
handle(w, unmap, ev);
|
event_handle(w, unmap, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,9 @@ frame_create(Client *c, View *v) {
|
|||||||
if(c->sel) {
|
if(c->sel) {
|
||||||
f->floatr = c->sel->floatr;
|
f->floatr = c->sel->floatr;
|
||||||
f->r = c->sel->r;
|
f->r = c->sel->r;
|
||||||
|
}else if(c->sel) {
|
||||||
|
f->floatr = c->frame->floatr;
|
||||||
|
f->r = c->frame->r;
|
||||||
}else {
|
}else {
|
||||||
f->r = client_grav(c, c->r);
|
f->r = client_grav(c, c->r);
|
||||||
f->floatr = f->r;
|
f->floatr = f->r;
|
||||||
@ -140,20 +143,20 @@ frame_restack(Frame *f, Frame *above) {
|
|||||||
|
|
||||||
/* Handlers */
|
/* Handlers */
|
||||||
static void
|
static void
|
||||||
bup_event(Window *w, XButtonEvent *e) {
|
bup_event(Window *w, void *aux, XButtonEvent *e) {
|
||||||
if((e->state & def.mod) != def.mod)
|
if((e->state & def.mod) != def.mod)
|
||||||
XAllowEvents(display, ReplayPointer, e->time);
|
XAllowEvents(display, ReplayPointer, e->time);
|
||||||
else
|
else
|
||||||
XUngrabPointer(display, e->time);
|
XUngrabPointer(display, e->time);
|
||||||
event("ClientClick %#C %d\n", w->aux, e->button);
|
event("ClientClick %#C %d\n", aux, e->button);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bdown_event(Window *w, XButtonEvent *e) {
|
bdown_event(Window *w, void *aux, XButtonEvent *e) {
|
||||||
Frame *f;
|
Frame *f;
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
f = c->sel;
|
f = c->sel;
|
||||||
|
|
||||||
if((e->state & def.mod) == def.mod) {
|
if((e->state & def.mod) == def.mod) {
|
||||||
@ -200,17 +203,17 @@ bdown_event(Window *w, XButtonEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
config_event(Window *w, XConfigureEvent *e) {
|
config_event(Window *w, void *aux, XConfigureEvent *e) {
|
||||||
|
|
||||||
USED(w, e);
|
USED(w, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enter_event(Window *w, XCrossingEvent *e) {
|
enter_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
Frame *f;
|
Frame *f;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
f = c->sel;
|
f = c->sel;
|
||||||
if(disp.focus != c || selclient() != c) {
|
if(disp.focus != c || selclient() != c) {
|
||||||
Dprint(DFocus, "enter_notify(f) => [%#C]%s%s\n",
|
Dprint(DFocus, "enter_notify(f) => [%#C]%s%s\n",
|
||||||
@ -225,12 +228,12 @@ enter_event(Window *w, XCrossingEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expose_event(Window *w, XExposeEvent *e) {
|
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
USED(e);
|
USED(e);
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
if(c->sel)
|
if(c->sel)
|
||||||
frame_draw(c->sel);
|
frame_draw(c->sel);
|
||||||
else
|
else
|
||||||
@ -239,10 +242,10 @@ expose_event(Window *w, XExposeEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
motion_event(Window *w, XMotionEvent *e) {
|
motion_event(Window *w, void *aux, XMotionEvent *e) {
|
||||||
Client *c;
|
Client *c;
|
||||||
|
|
||||||
c = w->aux;
|
c = aux;
|
||||||
mouse_checkresize(c->sel, Pt(e->x, e->y), false);
|
mouse_checkresize(c->sel, Pt(e->x, e->y), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ framedestroy(Framewin *f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expose_event(Window *w, XExposeEvent *e) {
|
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||||
Rectangle r;
|
Rectangle r;
|
||||||
Framewin *f;
|
Framewin *f;
|
||||||
Image *buf;
|
Image *buf;
|
||||||
@ -107,7 +107,7 @@ expose_event(Window *w, XExposeEvent *e) {
|
|||||||
|
|
||||||
USED(e);
|
USED(e);
|
||||||
|
|
||||||
f = w->aux;
|
f = aux;
|
||||||
c = &def.focuscolor;
|
c = &def.focuscolor;
|
||||||
buf = disp.ibuf;
|
buf = disp.ibuf;
|
||||||
|
|
||||||
|
@ -317,13 +317,6 @@ spawn_command(const char *cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
check_preselect(IxpServer *s) {
|
|
||||||
USED(s);
|
|
||||||
|
|
||||||
event_check();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
closedisplay(IxpConn *c) {
|
closedisplay(IxpConn *c) {
|
||||||
USED(c);
|
USED(c);
|
||||||
@ -412,9 +405,9 @@ extern int fmtevent(Fmt*);
|
|||||||
|
|
||||||
event_debug = debug_event;
|
event_debug = debug_event;
|
||||||
|
|
||||||
srv.preselect = check_preselect;
|
srv.preselect = event_preselect;
|
||||||
ixp_listen(&srv, sock, &p9srv, serve_9pcon, nil);
|
ixp_listen(&srv, sock, &p9srv, serve_9pcon, nil);
|
||||||
ixp_listen(&srv, ConnectionNumber(display), nil, (void (*)(IxpConn*))check_preselect, closedisplay);
|
ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, closedisplay);
|
||||||
|
|
||||||
def.border = 1;
|
def.border = 1;
|
||||||
def.colmode = Colstack;
|
def.colmode = Colstack;
|
||||||
|
@ -29,7 +29,7 @@ quad_cursor(Align align) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cwin_expose(Window *w, XExposeEvent *e) {
|
cwin_expose(Window *w, void *aux, XExposeEvent *e) {
|
||||||
|
|
||||||
fill(w, rectsubpt(w->r, w->r.min), def.focuscolor.bg);
|
fill(w, rectsubpt(w->r, w->r.min), def.focuscolor.bg);
|
||||||
fill(w, w->r, def.focuscolor.bg);
|
fill(w, w->r, def.focuscolor.bg);
|
||||||
|
@ -24,13 +24,13 @@ root_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enter_event(Window *w, XCrossingEvent *e) {
|
enter_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||||
disp.sel = true;
|
disp.sel = true;
|
||||||
frame_draw_all();
|
frame_draw_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
leave_event(Window *w, XCrossingEvent *e) {
|
leave_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||||
if(!e->same_screen) {
|
if(!e->same_screen) {
|
||||||
disp.sel = false;
|
disp.sel = false;
|
||||||
frame_draw_all();
|
frame_draw_all();
|
||||||
@ -38,13 +38,13 @@ leave_event(Window *w, XCrossingEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
focusin_event(Window *w, XFocusChangeEvent *e) {
|
focusin_event(Window *w, void *aux, XFocusChangeEvent *e) {
|
||||||
if(e->mode == NotifyGrab)
|
if(e->mode == NotifyGrab)
|
||||||
disp.hasgrab = &c_root;
|
disp.hasgrab = &c_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mapreq_event(Window *w, XMapRequestEvent *e) {
|
mapreq_event(Window *w, void *aux, XMapRequestEvent *e) {
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
|
|
||||||
if(!XGetWindowAttributes(display, e->window, &wa))
|
if(!XGetWindowAttributes(display, e->window, &wa))
|
||||||
@ -62,7 +62,7 @@ mapreq_event(Window *w, XMapRequestEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
motion_event(Window *w, XMotionEvent *e) {
|
motion_event(Window *w, void *aux, XMotionEvent *e) {
|
||||||
Rectangle r, r2;
|
Rectangle r, r2;
|
||||||
|
|
||||||
r = rectsetorigin(Rect(0, 0, 1, 1), Pt(e->x_root, e->y_root));
|
r = rectsetorigin(Rect(0, 0, 1, 1), Pt(e->x_root, e->y_root));
|
||||||
@ -72,7 +72,7 @@ motion_event(Window *w, XMotionEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kdown_event(Window *w, XKeyEvent *e) {
|
kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||||
|
|
||||||
e->state &= valid_mask;
|
e->state &= valid_mask;
|
||||||
kpress(w->xid, e->state, (KeyCode)e->keycode);
|
kpress(w->xid, e->state, (KeyCode)e->keycode);
|
||||||
|
@ -71,7 +71,7 @@ xdnd_clientmessage(XClientMessageEvent *e) {
|
|||||||
Dprint(DDnd, "\tp: %P\n", p);
|
Dprint(DDnd, "\tp: %P\n", p);
|
||||||
if(eqrect(dnd->r, ZR) || !rect_haspoint_p(p, dnd->r))
|
if(eqrect(dnd->r, ZR) || !rect_haspoint_p(p, dnd->r))
|
||||||
if(w->handler->dndmotion)
|
if(w->handler->dndmotion)
|
||||||
dnd->r = w->handler->dndmotion(w, p);
|
dnd->r = w->handler->dndmotion(w, w->aux, p);
|
||||||
r = dnd->r;
|
r = dnd->r;
|
||||||
if(!eqrect(r, ZR))
|
if(!eqrect(r, ZR))
|
||||||
r = rectaddpt(r, w->r.min);
|
r = rectaddpt(r, w->r.min);
|
||||||
|
@ -26,7 +26,7 @@ LD = cc
|
|||||||
# Archiver
|
# Archiver
|
||||||
AR = ar crs
|
AR = ar crs
|
||||||
|
|
||||||
X11PACKAGES = x11 xinerama xrender
|
X11PACKAGES = x11 xinerama xrender xrandr
|
||||||
INCX11 = $$(pkg-config --cflags $(X11PACKAGES))
|
INCX11 = $$(pkg-config --cflags $(X11PACKAGES))
|
||||||
LIBIXP = $(LIBDIR)/libixp.a
|
LIBIXP = $(LIBDIR)/libixp.a
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#define _XOPEN_SOURCE 600
|
#define _XOPEN_SOURCE 600
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -13,6 +14,12 @@
|
|||||||
# define nelem(ary) (sizeof(ary) / sizeof(*ary))
|
# define nelem(ary) (sizeof(ary) / sizeof(*ary))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
|
# define offsetof(type, member) ((size_t)&((type*)0)->member)
|
||||||
|
#endif
|
||||||
|
#define structmember(ptr, type, offset) \
|
||||||
|
(*(type*)((char*)(ptr) + (offset)))
|
||||||
|
|
||||||
#undef uchar
|
#undef uchar
|
||||||
#undef ushort
|
#undef ushort
|
||||||
#undef uint
|
#undef uint
|
||||||
|
@ -22,16 +22,7 @@ enum {
|
|||||||
CCenter = 1<<1,
|
CCenter = 1<<1,
|
||||||
CRight = 1<<2,
|
CRight = 1<<2,
|
||||||
};
|
};
|
||||||
enum DebugOpt {
|
|
||||||
D9p = 1<<0,
|
|
||||||
DDnd = 1<<1,
|
|
||||||
DEvent = 1<<2,
|
|
||||||
DEwmh = 1<<3,
|
|
||||||
DFocus = 1<<4,
|
|
||||||
DGeneric= 1<<5,
|
|
||||||
DStack = 1<<6,
|
|
||||||
NDebugOpt = 7,
|
|
||||||
};
|
|
||||||
enum {
|
enum {
|
||||||
GInvert = 1<<0,
|
GInvert = 1<<0,
|
||||||
};
|
};
|
||||||
|
@ -16,11 +16,21 @@ void xext_event(XEvent*);
|
|||||||
void xext_init(void);
|
void xext_init(void);
|
||||||
Rectangle* xinerama_screens(int*);
|
Rectangle* xinerama_screens(int*);
|
||||||
|
|
||||||
|
#define event_handle(w, fn, ev) \
|
||||||
|
_event_handle(w, offsetof(Handlers, fn), (XEvent*)ev)
|
||||||
|
|
||||||
|
void _event_handle(Window*, ulong, XEvent*);
|
||||||
|
|
||||||
void event_check(void);
|
void event_check(void);
|
||||||
void event_dispatch(XEvent*);
|
void event_dispatch(XEvent*);
|
||||||
uint event_flush(long, bool dispatch);
|
uint event_flush(long, bool dispatch);
|
||||||
uint event_flushenter(void);
|
uint event_flushenter(void);
|
||||||
void event_loop(void);
|
void event_loop(void);
|
||||||
|
#ifdef IXP_API /* Evil. */
|
||||||
|
void event_fdclosed(IxpConn*);
|
||||||
|
void event_fdready(IxpConn*);
|
||||||
|
void event_preselect(IxpServer*);
|
||||||
|
#endif
|
||||||
void event_updatextime(void);
|
void event_updatextime(void);
|
||||||
|
|
||||||
void event_buttonpress(XButtonPressedEvent*);
|
void event_buttonpress(XButtonPressedEvent*);
|
||||||
@ -36,10 +46,14 @@ void event_focusout(XFocusChangeEvent*);
|
|||||||
void event_keypress(XKeyEvent*);
|
void event_keypress(XKeyEvent*);
|
||||||
void event_leavenotify(XCrossingEvent*);
|
void event_leavenotify(XCrossingEvent*);
|
||||||
void event_mapnotify(XMapEvent*);
|
void event_mapnotify(XMapEvent*);
|
||||||
void event_maprequest(XMapRequestEvent*);
|
|
||||||
void event_mappingnotify(XMappingEvent*);
|
void event_mappingnotify(XMappingEvent*);
|
||||||
|
void event_maprequest(XMapRequestEvent*);
|
||||||
void event_motionnotify(XMotionEvent*);
|
void event_motionnotify(XMotionEvent*);
|
||||||
void event_propertynotify(XPropertyEvent*);
|
void event_propertynotify(XPropertyEvent*);
|
||||||
|
void event_reparentnotify(XReparentEvent *ev);
|
||||||
|
void event_selection(XSelectionEvent*);
|
||||||
|
void event_selectionclear(XSelectionClearEvent*);
|
||||||
|
void event_selectionrequest(XSelectionRequestEvent*);
|
||||||
void event_unmapnotify(XUnmapEvent*);
|
void event_unmapnotify(XUnmapEvent*);
|
||||||
|
|
||||||
extern long event_xtime;
|
extern long event_xtime;
|
||||||
|
@ -33,12 +33,14 @@ typedef enum WindowType WindowType;
|
|||||||
|
|
||||||
typedef XSetWindowAttributes WinAttr;
|
typedef XSetWindowAttributes WinAttr;
|
||||||
|
|
||||||
|
typedef union ClientMessageData ClientMessageData;
|
||||||
typedef struct Color Color;
|
typedef struct Color Color;
|
||||||
typedef struct CTuple CTuple;
|
typedef struct CTuple CTuple;
|
||||||
typedef struct ErrorCode ErrorCode;
|
typedef struct ErrorCode ErrorCode;
|
||||||
typedef struct Ewmh Ewmh;
|
typedef struct Ewmh Ewmh;
|
||||||
typedef struct Font Font;
|
typedef struct Font Font;
|
||||||
typedef struct Handlers Handlers;
|
typedef struct Handlers Handlers;
|
||||||
|
typedef struct HandlersLink HandlersLink;
|
||||||
typedef struct Screen Screen;
|
typedef struct Screen Screen;
|
||||||
typedef struct WinHints WinHints;
|
typedef struct WinHints WinHints;
|
||||||
typedef struct Window Image;
|
typedef struct Window Image;
|
||||||
@ -48,6 +50,12 @@ typedef struct XftColor XftColor;
|
|||||||
typedef void XftDraw;
|
typedef void XftDraw;
|
||||||
typedef struct XftFont XftFont;
|
typedef struct XftFont XftFont;
|
||||||
|
|
||||||
|
union ClientMessageData {
|
||||||
|
char b[20];
|
||||||
|
short s[10];
|
||||||
|
long l[5];
|
||||||
|
};
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
ulong pixel;
|
ulong pixel;
|
||||||
XRenderColor render;
|
XRenderColor render;
|
||||||
@ -86,24 +94,35 @@ struct Font {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Handlers {
|
struct Handlers {
|
||||||
Rectangle (*dndmotion)(Window*, Point);
|
Rectangle (*dndmotion)(Window*, void*, Point);
|
||||||
void (*bdown)(Window*, XButtonEvent*);
|
void (*bdown)(Window*, void*, XButtonEvent*);
|
||||||
void (*bup)(Window*, XButtonEvent*);
|
void (*bup)(Window*, void*, XButtonEvent*);
|
||||||
void (*config)(Window*, XConfigureEvent*);
|
void (*config)(Window*, void*, XConfigureEvent*);
|
||||||
void (*configreq)(Window*, XConfigureRequestEvent*);
|
void (*configreq)(Window*, void*, XConfigureRequestEvent*);
|
||||||
void (*destroy)(Window*, XDestroyWindowEvent*);
|
void (*destroy)(Window*, void*, XDestroyWindowEvent*);
|
||||||
void (*enter)(Window*, XCrossingEvent*);
|
void (*enter)(Window*, void*, XCrossingEvent*);
|
||||||
void (*expose)(Window*, XExposeEvent*);
|
void (*expose)(Window*, void*, XExposeEvent*);
|
||||||
void (*focusin)(Window*, XFocusChangeEvent*);
|
void (*focusin)(Window*, void*, XFocusChangeEvent*);
|
||||||
void (*focusout)(Window*, XFocusChangeEvent*);
|
void (*focusout)(Window*, void*, XFocusChangeEvent*);
|
||||||
void (*kdown)(Window*, XKeyEvent*);
|
void (*kdown)(Window*, void*, XKeyEvent*);
|
||||||
void (*kup)(Window*, XKeyEvent*);
|
void (*kup)(Window*, void*, XKeyEvent*);
|
||||||
void (*leave)(Window*, XCrossingEvent*);
|
void (*leave)(Window*, void*, XCrossingEvent*);
|
||||||
void (*map)(Window*, XMapEvent*);
|
void (*map)(Window*, void*, XMapEvent*);
|
||||||
void (*mapreq)(Window*, XMapRequestEvent*);
|
void (*mapreq)(Window*, void*, XMapRequestEvent*);
|
||||||
void (*motion)(Window*, XMotionEvent*);
|
void (*message)(Window*, void*, XClientMessageEvent*);
|
||||||
void (*property)(Window*, XPropertyEvent*);
|
void (*motion)(Window*, void*, XMotionEvent*);
|
||||||
void (*unmap)(Window*, XUnmapEvent*);
|
void (*property)(Window*, void*, XPropertyEvent*);
|
||||||
|
void (*reparent)(Window*, void*, XReparentEvent*);
|
||||||
|
void (*selection)(Window*, void*, XSelectionEvent*);
|
||||||
|
void (*selectionclear)(Window*, void*, XSelectionClearEvent*);
|
||||||
|
void (*selectionrequest)(Window*, void*, XSelectionRequestEvent*);
|
||||||
|
void (*unmap)(Window*, void*, XUnmapEvent*);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HandlersLink {
|
||||||
|
HandlersLink* next;
|
||||||
|
void* aux;
|
||||||
|
Handlers* handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WinHints {
|
struct WinHints {
|
||||||
@ -132,8 +151,10 @@ struct Window {
|
|||||||
Window* next;
|
Window* next;
|
||||||
Window* prev;
|
Window* prev;
|
||||||
Handlers* handler;
|
Handlers* handler;
|
||||||
|
HandlersLink* handler_link;
|
||||||
WinHints* hints;
|
WinHints* hints;
|
||||||
Ewmh ewmh;
|
Ewmh ewmh;
|
||||||
|
long eventmask;
|
||||||
void* dnd;
|
void* dnd;
|
||||||
void* aux;
|
void* aux;
|
||||||
bool mapped;
|
bool mapped;
|
||||||
@ -193,6 +214,7 @@ extern struct Map windowmap;
|
|||||||
extern struct Map atommap;
|
extern struct Map atommap;
|
||||||
extern const Point ZP;
|
extern const Point ZP;
|
||||||
extern const Rectangle ZR;
|
extern const Rectangle ZR;
|
||||||
|
extern const WinHints ZWinHints;
|
||||||
extern Window* pointerwin;
|
extern Window* pointerwin;
|
||||||
extern Xft* xft;
|
extern Xft* xft;
|
||||||
|
|
||||||
@ -204,6 +226,7 @@ XRectangle XRect(Rectangle r);
|
|||||||
(uchar*)(data), n)
|
(uchar*)(data), n)
|
||||||
|
|
||||||
/* x11.c */
|
/* x11.c */
|
||||||
|
XRectangle XRect(Rectangle);
|
||||||
Image* allocimage(int w, int h, int depth);
|
Image* allocimage(int w, int h, int depth);
|
||||||
void border(Image *dst, Rectangle, int w, Color);
|
void border(Image *dst, Rectangle, int w, Color);
|
||||||
void changeprop_char(Window*, char*, char*, char[], int);
|
void changeprop_char(Window*, char*, char*, char[], int);
|
||||||
@ -213,6 +236,7 @@ void changeprop_string(Window*, char*, char*);
|
|||||||
void changeprop_textlist(Window*, char*, char*, char*[]);
|
void changeprop_textlist(Window*, char*, char*, char*[]);
|
||||||
void changeprop_ulong(Window*, char*, char*, ulong[], int);
|
void changeprop_ulong(Window*, char*, char*, ulong[], int);
|
||||||
void changeproperty(Window*, char*, char*, int width, uchar*, int);
|
void changeproperty(Window*, char*, char*, int width, uchar*, int);
|
||||||
|
void clientmessage(Window*, char*, long, int, ClientMessageData);
|
||||||
void copyimage(Image*, Rectangle, Image*, Point);
|
void copyimage(Image*, Rectangle, Image*, Point);
|
||||||
Window* createwindow(Window*, Rectangle, int depth, uint class, WinAttr*, int valuemask);
|
Window* createwindow(Window*, Rectangle, int depth, uint class, WinAttr*, int valuemask);
|
||||||
Window* createwindow_visual(Window*, Rectangle, int depth, Visual*, uint class, WinAttr*, int);
|
Window* createwindow_visual(Window*, Rectangle, int depth, Visual*, uint class, WinAttr*, int);
|
||||||
@ -228,11 +252,13 @@ void freefont(Font*);
|
|||||||
void freeimage(Image *);
|
void freeimage(Image *);
|
||||||
void freestringlist(char**);
|
void freestringlist(char**);
|
||||||
XWindow getfocus(void);
|
XWindow getfocus(void);
|
||||||
|
void gethints(Window*);
|
||||||
ulong getprop_long(Window*, char*, char*, ulong, long**, ulong);
|
ulong getprop_long(Window*, char*, char*, ulong, long**, ulong);
|
||||||
char* getprop_string(Window*, char*);
|
char* getprop_string(Window*, char*);
|
||||||
int getprop_textlist(Window *w, char *name, char **ret[]);
|
int getprop_textlist(Window *w, char *name, char **ret[]);
|
||||||
ulong getprop_ulong(Window*, char*, char*, ulong, ulong**, ulong);
|
ulong getprop_ulong(Window*, char*, char*, ulong, ulong**, ulong);
|
||||||
ulong getproperty(Window*, char *prop, char *type, Atom *actual, ulong offset, uchar **ret, ulong length);
|
ulong getproperty(Window*, char *prop, char *type, Atom *actual, ulong offset, uchar **ret, ulong length);
|
||||||
|
Rectangle getwinrect(Window*);
|
||||||
int grabkeyboard(Window*);
|
int grabkeyboard(Window*);
|
||||||
int grabpointer(Window*, Window *confine, Cursor, int mask);
|
int grabpointer(Window*, Window *confine, Cursor, int mask);
|
||||||
bool havexft(void);
|
bool havexft(void);
|
||||||
@ -247,24 +273,29 @@ void movewin(Window*, Point);
|
|||||||
bool namedcolor(char *name, Color*);
|
bool namedcolor(char *name, Color*);
|
||||||
bool parsekey(char*, int*, char**);
|
bool parsekey(char*, int*, char**);
|
||||||
int pointerscreen(void);
|
int pointerscreen(void);
|
||||||
|
bool pophandler(Window*, Handlers*);
|
||||||
|
void pushhandler(Window*, Handlers*, void*);
|
||||||
Point querypointer(Window*);
|
Point querypointer(Window*);
|
||||||
void raisewin(Window*);
|
void raisewin(Window*);
|
||||||
void reparentwindow(Window*, Window*, Point);
|
void reparentwindow(Window*, Window*, Point);
|
||||||
void reshapewin(Window*, Rectangle);
|
void reshapewin(Window*, Rectangle);
|
||||||
void selectinput(Window*, long);
|
void selectinput(Window*, long);
|
||||||
void sendevent(Window*, bool propagate, long mask, XEvent*);
|
void sendevent(Window*, bool propagate, long mask, void*);
|
||||||
|
void sendmessage(Window*, char*, long, long, long, long, long);
|
||||||
void setborder(Window*, int, Color);
|
void setborder(Window*, int, Color);
|
||||||
void setfocus(Window*, int mode);
|
void setfocus(Window*, int mode);
|
||||||
void sethints(Window*);
|
Handlers* sethandler(Window*, Handlers*);
|
||||||
|
void sethints(Window*, WinHints*);
|
||||||
void setshapemask(Window *dst, Image *src, Point);
|
void setshapemask(Window *dst, Image *src, Point);
|
||||||
void setwinattr(Window*, WinAttr*, int valmask);
|
void setwinattr(Window*, WinAttr*, int valmask);
|
||||||
|
Rectangle sizehint(WinHints*, Rectangle);
|
||||||
char** strlistdup(char**);
|
char** strlistdup(char**);
|
||||||
void sync(void);
|
void sync(void);
|
||||||
|
Rectangle textextents_l(Font*, char*, uint, int*);
|
||||||
uint textwidth(Font*, char*);
|
uint textwidth(Font*, char*);
|
||||||
uint textwidth_l(Font*, char*, uint len);
|
uint textwidth_l(Font*, char*, uint len);
|
||||||
Rectangle textextents_l(Font*, char*, uint, int*);
|
|
||||||
int traperrors(bool);
|
|
||||||
Point translate(Window*, Window*, Point);
|
Point translate(Window*, Window*, Point);
|
||||||
|
int traperrors(bool);
|
||||||
void ungrabkeyboard(void);
|
void ungrabkeyboard(void);
|
||||||
void ungrabpointer(void);
|
void ungrabpointer(void);
|
||||||
int unmapwin(Window*);
|
int unmapwin(Window*);
|
||||||
@ -273,9 +304,4 @@ Window* window(XWindow);
|
|||||||
char* windowname(Window*);
|
char* windowname(Window*);
|
||||||
long winprotocols(Window*);
|
long winprotocols(Window*);
|
||||||
Atom xatom(char*);
|
Atom xatom(char*);
|
||||||
void sendmessage(Window*, char*, long, long, long, long, long);
|
|
||||||
XRectangle XRect(Rectangle);
|
|
||||||
Rectangle getwinrect(Window*);
|
|
||||||
Handlers* sethandler(Window*, Handlers*);
|
|
||||||
Rectangle sizehint(WinHints*, Rectangle);
|
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ OBJ=\
|
|||||||
event/expose \
|
event/expose \
|
||||||
event/focusin \
|
event/focusin \
|
||||||
event/focusout \
|
event/focusout \
|
||||||
|
event/ixp \
|
||||||
event/keypress \
|
event/keypress \
|
||||||
event/leavenotify \
|
event/leavenotify \
|
||||||
event/mapnotify \
|
event/mapnotify \
|
||||||
@ -26,6 +27,10 @@ OBJ=\
|
|||||||
event/mappingnotify \
|
event/mappingnotify \
|
||||||
event/motionnotify \
|
event/motionnotify \
|
||||||
event/propertynotify \
|
event/propertynotify \
|
||||||
|
event/reparentnotify \
|
||||||
|
event/selection \
|
||||||
|
event/selectionclear \
|
||||||
|
event/selectionrequest \
|
||||||
event/unmapnotify \
|
event/unmapnotify \
|
||||||
event/xtime \
|
event/xtime \
|
||||||
geom/get_sticky \
|
geom/get_sticky \
|
||||||
@ -38,7 +43,6 @@ OBJ=\
|
|||||||
map \
|
map \
|
||||||
printevent \
|
printevent \
|
||||||
util/_die \
|
util/_die \
|
||||||
util/backtrace \
|
|
||||||
util/closeexec \
|
util/closeexec \
|
||||||
util/comm \
|
util/comm \
|
||||||
util/doublefork \
|
util/doublefork \
|
||||||
@ -114,6 +118,7 @@ OBJ=\
|
|||||||
x11/images/freeimage \
|
x11/images/freeimage \
|
||||||
x11/images/xftdrawable \
|
x11/images/xftdrawable \
|
||||||
x11/insanity/gravitate \
|
x11/insanity/gravitate \
|
||||||
|
x11/insanity/gethints \
|
||||||
x11/insanity/sethints \
|
x11/insanity/sethints \
|
||||||
x11/insanity/sizehint \
|
x11/insanity/sizehint \
|
||||||
x11/keyboard/grabkeyboard \
|
x11/keyboard/grabkeyboard \
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#define IXP_NO_P9_
|
#define IXP_NO_P9_
|
||||||
#define IXP_P9_STRUCTS
|
#define IXP_P9_STRUCTS
|
||||||
#define CLIENTEXTERN
|
#define CLIENTEXTERN
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ixp.h>
|
#include <ixp.h>
|
||||||
#include <stuff/clientutil.h>
|
#include <stuff/clientutil.h>
|
||||||
@ -40,11 +41,13 @@ readctl(char *key) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
client_init(char* address) {
|
client_init(char* address) {
|
||||||
|
if(address == nil)
|
||||||
|
address = getenv("WMII_ADDRESS");
|
||||||
if(address && *address)
|
if(address && *address)
|
||||||
client = ixp_mount(address);
|
client = ixp_mount(address);
|
||||||
else
|
else
|
||||||
client = ixp_nsmount("wmii");
|
client = ixp_nsmount("wmii");
|
||||||
if(client == nil)
|
if(client == nil)
|
||||||
fatal("can't mount: %r\n");
|
fatal("can't mount wmii filesystem: %r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ event_buttonpress(XButtonPressedEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, bdown, ev);
|
event_handle(w, bdown, ev);
|
||||||
else
|
else
|
||||||
XAllowEvents(display, ReplayPointer, ev->time);
|
XAllowEvents(display, ReplayPointer, ev->time);
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ event_buttonrelease(XButtonPressedEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, bup, ev);
|
event_handle(w, bup, ev);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
void
|
void
|
||||||
event_clientmessage(XClientMessageEvent *ev) {
|
event_clientmessage(XClientMessageEvent *ev) {
|
||||||
|
Window *w;
|
||||||
|
|
||||||
USED(ev);
|
if((w = findwin(ev->window)))
|
||||||
|
event_handle(w, message, ev);
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ event_configurenotify(XConfigureEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, config, ev);
|
event_handle(w, config, ev);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ event_configurerequest(XConfigureRequestEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, configreq, ev);
|
event_handle(w, configreq, ev);
|
||||||
else{
|
else{
|
||||||
wc.x = ev->x;
|
wc.x = ev->x;
|
||||||
wc.y = ev->y;
|
wc.y = ev->y;
|
||||||
|
@ -8,5 +8,5 @@ event_destroynotify(XDestroyWindowEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, destroy, ev);
|
event_handle(w, destroy, ev);
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,11 @@ void
|
|||||||
event_enternotify(XCrossingEvent *ev) {
|
event_enternotify(XCrossingEvent *ev) {
|
||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
event_xtime = ev->time;
|
event_xtime = ev->time;
|
||||||
if(ev->mode != NotifyNormal)
|
if(ev->mode != NotifyNormal)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, enter, ev);
|
event_handle(w, enter, ev);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
|
||||||
|
typedef void (*Handler)(Window*, void*, XEvent*);
|
||||||
void (*event_debug)(XEvent*);
|
void (*event_debug)(XEvent*);
|
||||||
long event_xtime;
|
long event_xtime;
|
||||||
bool event_looprunning;
|
bool event_looprunning;
|
||||||
@ -25,9 +26,29 @@ EventHandler event_handler[LASTEvent] = {
|
|||||||
[MappingNotify] = (EventHandler)event_mappingnotify,
|
[MappingNotify] = (EventHandler)event_mappingnotify,
|
||||||
[MotionNotify] = (EventHandler)event_motionnotify,
|
[MotionNotify] = (EventHandler)event_motionnotify,
|
||||||
[PropertyNotify] = (EventHandler)event_propertynotify,
|
[PropertyNotify] = (EventHandler)event_propertynotify,
|
||||||
|
[ReparentNotify] = (EventHandler)event_reparentnotify,
|
||||||
|
[SelectionClear] = (EventHandler)event_selectionclear,
|
||||||
|
[SelectionNotify] = (EventHandler)event_selection,
|
||||||
[UnmapNotify] = (EventHandler)event_unmapnotify,
|
[UnmapNotify] = (EventHandler)event_unmapnotify,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
_event_handle(Window *w, ulong offset, XEvent *event) {
|
||||||
|
Handler f;
|
||||||
|
HandlersLink *l;
|
||||||
|
|
||||||
|
if(w->handler && (f = structmember(w->handler, Handler, offset))) {
|
||||||
|
f(w, w->aux, event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(l=w->handler_link; l; l=l->next) {
|
||||||
|
if(f = structmember(l->handler, Handler, offset)) {
|
||||||
|
f(w, l->aux, event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
event_dispatch(XEvent *e) {
|
event_dispatch(XEvent *e) {
|
||||||
if(event_debug)
|
if(event_debug)
|
||||||
|
@ -8,5 +8,5 @@ event_expose(XExposeEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if(ev->count == 0 && (w = findwin(ev->window)))
|
if(ev->count == 0 && (w = findwin(ev->window)))
|
||||||
handle(w, expose, ev);
|
event_handle(w, expose, ev);
|
||||||
}
|
}
|
||||||
|
@ -23,5 +23,5 @@ event_focusin(XFocusChangeEvent *ev) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, focusin, ev);
|
event_handle(w, focusin, ev);
|
||||||
}
|
}
|
||||||
|
@ -15,5 +15,5 @@ event_focusout(XFocusChangeEvent *ev) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, focusout, ev);
|
event_handle(w, focusout, ev);
|
||||||
}
|
}
|
||||||
|
23
lib/libstuff/event/ixp.c
Normal file
23
lib/libstuff/event/ixp.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include <ixp.h>
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
event_preselect(IxpServer *s) {
|
||||||
|
USED(s);
|
||||||
|
event_check();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
event_fdready(IxpConn *c) {
|
||||||
|
USED(c);
|
||||||
|
event_check();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
event_fdclosed(IxpConn *c) {
|
||||||
|
|
||||||
|
c->srv->running = false;
|
||||||
|
}
|
@ -7,7 +7,8 @@ void
|
|||||||
event_keypress(XKeyEvent *ev) {
|
event_keypress(XKeyEvent *ev) {
|
||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
event_xtime = ev->time;
|
event_xtime = ev->time;
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, kdown, ev);
|
event_handle(w, kdown, ev);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ void
|
|||||||
event_leavenotify(XCrossingEvent *ev) {
|
event_leavenotify(XCrossingEvent *ev) {
|
||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
event_xtime = ev->time;
|
event_xtime = ev->time;
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, leave, ev);
|
event_handle(w, leave, ev);
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ event_mapnotify(XMapEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, map, ev);
|
event_handle(w, map, ev);
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ event_maprequest(XMapRequestEvent *ev) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
if((w = findwin(ev->parent)))
|
if((w = findwin(ev->parent)))
|
||||||
handle(w, mapreq, ev);
|
event_handle(w, mapreq, ev);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ void
|
|||||||
event_motionnotify(XMotionEvent *ev) {
|
event_motionnotify(XMotionEvent *ev) {
|
||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
event_xtime = ev->time;
|
event_xtime = ev->time;
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, motion, ev);
|
event_handle(w, motion, ev);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ void
|
|||||||
event_propertynotify(XPropertyEvent *ev) {
|
event_propertynotify(XPropertyEvent *ev) {
|
||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
event_xtime = ev->time;
|
event_xtime = ev->time;
|
||||||
if((w = findwin(ev->window)))
|
if((w = findwin(ev->window)))
|
||||||
handle(w, property, ev);
|
event_handle(w, property, ev);
|
||||||
}
|
}
|
||||||
|
12
lib/libstuff/event/reparentnotify.c
Normal file
12
lib/libstuff/event/reparentnotify.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
event_reparentnotify(XReparentEvent *ev) {
|
||||||
|
Window *w;
|
||||||
|
|
||||||
|
if((w = findwin(ev->window)))
|
||||||
|
event_handle(w, reparent, ev);
|
||||||
|
}
|
15
lib/libstuff/event/selection.c
Normal file
15
lib/libstuff/event/selection.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
event_selection(XSelectionEvent *ev) {
|
||||||
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
|
event_xtime = ev->time;
|
||||||
|
if((w = findwin(ev->requestor)))
|
||||||
|
event_handle(w, selection, ev);
|
||||||
|
}
|
||||||
|
|
14
lib/libstuff/event/selectionclear.c
Normal file
14
lib/libstuff/event/selectionclear.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
event_selectionclear(XSelectionClearEvent *ev) {
|
||||||
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
|
event_xtime = ev->time;
|
||||||
|
if((w = findwin(ev->window)))
|
||||||
|
event_handle(w, selectionclear, ev);
|
||||||
|
}
|
15
lib/libstuff/event/selectionrequest.c
Normal file
15
lib/libstuff/event/selectionrequest.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
event_selectionrequest(XSelectionRequestEvent *ev) {
|
||||||
|
Window *w;
|
||||||
|
|
||||||
|
if(!ev->send_event)
|
||||||
|
event_xtime = ev->time;
|
||||||
|
if((w = findwin(ev->owner)))
|
||||||
|
event_handle(w, selectionrequest, ev);
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,6 @@ event_unmapnotify(XUnmapEvent *ev) {
|
|||||||
if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) {
|
if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) {
|
||||||
w->mapped = false;
|
w->mapped = false;
|
||||||
if(w->parent && (ev->send_event || w->unmapped-- == 0))
|
if(w->parent && (ev->send_event || w->unmapped-- == 0))
|
||||||
handle(w, unmap, ev);
|
event_handle(w, unmap, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,10 @@ errorhandler(Display *dpy, XErrorEvent *error) {
|
|||||||
|
|
||||||
USED(dpy);
|
USED(dpy);
|
||||||
|
|
||||||
if(_trap_errors)
|
if(_trap_errors) {
|
||||||
nerrors++;
|
nerrors++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
e = ignored_xerrors;
|
e = ignored_xerrors;
|
||||||
if(e)
|
if(e)
|
||||||
|
@ -44,6 +44,8 @@ Wfmt(Fmt *f) {
|
|||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
w = va_arg(f->args, Window*);
|
w = va_arg(f->args, Window*);
|
||||||
|
if(w == nil)
|
||||||
|
return fmtstrcpy(f, "<nil>");
|
||||||
return fmtprint(f, "0x%ulx", w->xid);
|
return fmtprint(f, "0x%ulx", w->xid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
97
lib/libstuff/x11/insanity/gethints.c
Normal file
97
lib/libstuff/x11/insanity/gethints.c
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail>
|
||||||
|
* See LICENSE file for license details.
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include "../x11.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
gethints(Window *w) {
|
||||||
|
XSizeHints xs;
|
||||||
|
XWMHints *wmh;
|
||||||
|
WinHints *h;
|
||||||
|
Point p;
|
||||||
|
long size;
|
||||||
|
|
||||||
|
if(w->hints == nil)
|
||||||
|
w->hints = emalloc(sizeof *h);
|
||||||
|
|
||||||
|
h = w->hints;
|
||||||
|
*h = ZWinHints;
|
||||||
|
|
||||||
|
wmh = XGetWMHints(display, w->xid);
|
||||||
|
if(wmh) {
|
||||||
|
if(wmh->flags & WindowGroupHint)
|
||||||
|
h->group = wmh->window_group;
|
||||||
|
free(wmh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!XGetWMNormalHints(display, w->xid, &xs, &size))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(xs.flags & PMinSize) {
|
||||||
|
h->min.x = xs.min_width;
|
||||||
|
h->min.y = xs.min_height;
|
||||||
|
}
|
||||||
|
if(xs.flags & PMaxSize) {
|
||||||
|
h->max.x = xs.max_width;
|
||||||
|
h->max.y = xs.max_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Goddamn buggy clients. */
|
||||||
|
if(h->max.x < h->min.x)
|
||||||
|
h->max.x = h->min.x;
|
||||||
|
if(h->max.y < h->min.y)
|
||||||
|
h->max.y = h->min.y;
|
||||||
|
|
||||||
|
h->base = h->min;
|
||||||
|
if(xs.flags & PBaseSize) {
|
||||||
|
p.x = xs.base_width;
|
||||||
|
p.y = xs.base_height;
|
||||||
|
h->base = p;
|
||||||
|
h->baspect = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(xs.flags & PResizeInc) {
|
||||||
|
h->inc.x = max(xs.width_inc, 1);
|
||||||
|
h->inc.y = max(xs.height_inc, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(xs.flags & PAspect) {
|
||||||
|
h->aspect.min.x = xs.min_aspect.x;
|
||||||
|
h->aspect.min.y = xs.min_aspect.y;
|
||||||
|
h->aspect.max.x = xs.max_aspect.x;
|
||||||
|
h->aspect.max.y = xs.max_aspect.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->position = (xs.flags & (USPosition|PPosition)) != 0;
|
||||||
|
|
||||||
|
if(!(xs.flags & PWinGravity))
|
||||||
|
xs.win_gravity = NorthWestGravity;
|
||||||
|
p = ZP;
|
||||||
|
switch (xs.win_gravity) {
|
||||||
|
case EastGravity:
|
||||||
|
case CenterGravity:
|
||||||
|
case WestGravity:
|
||||||
|
p.y = 1;
|
||||||
|
break;
|
||||||
|
case SouthEastGravity:
|
||||||
|
case SouthGravity:
|
||||||
|
case SouthWestGravity:
|
||||||
|
p.y = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (xs.win_gravity) {
|
||||||
|
case NorthGravity:
|
||||||
|
case CenterGravity:
|
||||||
|
case SouthGravity:
|
||||||
|
p.x = 1;
|
||||||
|
break;
|
||||||
|
case NorthEastGravity:
|
||||||
|
case EastGravity:
|
||||||
|
case SouthEastGravity:
|
||||||
|
p.x = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h->grav = p;
|
||||||
|
h->gravstatic = (xs.win_gravity == StaticGravity);
|
||||||
|
}
|
@ -1,100 +1,97 @@
|
|||||||
/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail>
|
/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail>
|
||||||
* See LICENSE file for license details.
|
* See LICENSE file for license details.
|
||||||
*/
|
*/
|
||||||
#include <string.h>
|
|
||||||
#include "../x11.h"
|
#include "../x11.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
const WinHints ZWinHints = {
|
||||||
|
.inc = {1, 1},
|
||||||
|
.max = {INT_MAX, INT_MAX},
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct GravityMap GravityMap;
|
||||||
|
|
||||||
|
struct GravityMap {
|
||||||
|
Point point;
|
||||||
|
int gravity;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GravityMap gravity_map[] = {
|
||||||
|
{ {0, 0}, NorthWestGravity },
|
||||||
|
{ {0, 1}, WestGravity },
|
||||||
|
{ {0, 2}, SouthWestGravity },
|
||||||
|
|
||||||
|
{ {1, 0}, NorthGravity },
|
||||||
|
{ {1, 1}, CenterGravity },
|
||||||
|
{ {1, 2}, SouthGravity },
|
||||||
|
|
||||||
|
{ {2, 0}, NorthEastGravity },
|
||||||
|
{ {2, 1}, EastGravity },
|
||||||
|
{ {2, 2}, SouthEastGravity },
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
sethints(Window *w) {
|
sethints(Window *w, WinHints *h) {
|
||||||
XSizeHints xs;
|
XSizeHints xhints = { 0, };
|
||||||
XWMHints *wmh;
|
int i;
|
||||||
WinHints *h;
|
|
||||||
Point p;
|
/* TODO: Group hint */
|
||||||
long size;
|
|
||||||
|
|
||||||
if(w->hints == nil)
|
if(w->hints == nil)
|
||||||
w->hints = emalloc(sizeof *h);
|
w->hints = emalloc(sizeof *h);
|
||||||
|
|
||||||
h = w->hints;
|
*w->hints = *h;
|
||||||
memset(h, 0, sizeof *h);
|
|
||||||
|
|
||||||
h->max = Pt(INT_MAX, INT_MAX);
|
if(!eqpt(h->min, ZP)) {
|
||||||
h->inc = Pt(1,1);
|
xhints.flags |= PMinSize;
|
||||||
|
xhints.min_width = h->min.x;
|
||||||
wmh = XGetWMHints(display, w->xid);
|
xhints.min_height = h->min.y;
|
||||||
if(wmh) {
|
}
|
||||||
if(wmh->flags & WindowGroupHint)
|
if(!eqpt(h->max, Pt(INT_MAX, INT_MAX))) {
|
||||||
h->group = wmh->window_group;
|
xhints.flags |= PMaxSize;
|
||||||
free(wmh);
|
xhints.max_width = h->max.x;
|
||||||
|
xhints.max_height = h->max.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!XGetWMNormalHints(display, w->xid, &xs, &size))
|
if(!eqpt(h->base, ZP)) {
|
||||||
return;
|
xhints.flags |= PBaseSize;
|
||||||
|
xhints.base_width = h->baspect.x;
|
||||||
if(xs.flags & PMinSize) {
|
xhints.base_height = h->baspect.y;
|
||||||
h->min.x = xs.min_width;
|
|
||||||
h->min.y = xs.min_height;
|
|
||||||
}
|
|
||||||
if(xs.flags & PMaxSize) {
|
|
||||||
h->max.x = xs.max_width;
|
|
||||||
h->max.y = xs.max_height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Goddamn buggy clients. */
|
if(!eqrect(h->aspect, ZR)) {
|
||||||
if(h->max.x < h->min.x)
|
xhints.flags |= PAspect;
|
||||||
h->max.x = h->min.x;
|
|
||||||
if(h->max.y < h->min.y)
|
|
||||||
h->max.y = h->min.y;
|
|
||||||
|
|
||||||
h->base = h->min;
|
xhints.base_width = h->baspect.x;
|
||||||
if(xs.flags & PBaseSize) {
|
xhints.base_height = h->baspect.y;
|
||||||
p.x = xs.base_width;
|
|
||||||
p.y = xs.base_height;
|
xhints.min_aspect.x = h->aspect.min.x;
|
||||||
h->base = p;
|
xhints.min_aspect.y = h->aspect.min.y;
|
||||||
h->baspect = p;
|
|
||||||
|
xhints.max_aspect.x = h->aspect.max.x;
|
||||||
|
xhints.max_aspect.y = h->aspect.max.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xs.flags & PResizeInc) {
|
if(!eqpt(h->inc, Pt(1, 1))) {
|
||||||
h->inc.x = max(xs.width_inc, 1);
|
xhints.flags |= PResizeInc;
|
||||||
h->inc.y = max(xs.height_inc, 1);
|
xhints.width_inc = h->inc.x;
|
||||||
|
xhints.height_inc = h->inc.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xs.flags & PAspect) {
|
/* USPosition is probably an evil assumption, but it holds in our use cases. */
|
||||||
h->aspect.min.x = xs.min_aspect.x;
|
if(h->position)
|
||||||
h->aspect.min.y = xs.min_aspect.y;
|
xhints.flags |= USPosition | PPosition;
|
||||||
h->aspect.max.x = xs.max_aspect.x;
|
|
||||||
h->aspect.max.y = xs.max_aspect.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
h->position = (xs.flags & (USPosition|PPosition)) != 0;
|
xhints.flags |= PWinGravity;
|
||||||
|
if(h->gravstatic)
|
||||||
if(!(xs.flags & PWinGravity))
|
xhints.win_gravity = StaticGravity;
|
||||||
xs.win_gravity = NorthWestGravity;
|
else
|
||||||
p = ZP;
|
for(i=0; i < nelem(gravity_map); i++)
|
||||||
switch (xs.win_gravity) {
|
if(h->grav.x == gravity_map[i].point.x &&
|
||||||
case EastGravity:
|
h->grav.y == gravity_map[i].point.y) {
|
||||||
case CenterGravity:
|
xhints.win_gravity = gravity_map[i].gravity;
|
||||||
case WestGravity:
|
|
||||||
p.y = 1;
|
|
||||||
break;
|
|
||||||
case SouthEastGravity:
|
|
||||||
case SouthGravity:
|
|
||||||
case SouthWestGravity:
|
|
||||||
p.y = 2;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (xs.win_gravity) {
|
|
||||||
case NorthGravity:
|
XSetWMNormalHints(display, w->xid, &xhints);
|
||||||
case CenterGravity:
|
|
||||||
case SouthGravity:
|
|
||||||
p.x = 1;
|
|
||||||
break;
|
|
||||||
case NorthEastGravity:
|
|
||||||
case EastGravity:
|
|
||||||
case SouthEastGravity:
|
|
||||||
p.x = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
h->grav = p;
|
|
||||||
h->gravstatic = (xs.win_gravity == StaticGravity);
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,6 @@ changeprop_textlist(Window *w, char *prop, char *type, char *data[]) {
|
|||||||
memcpy(t, *p, n);
|
memcpy(t, *p, n);
|
||||||
t += n;
|
t += n;
|
||||||
}
|
}
|
||||||
changeprop_char(w, prop, type, s, len);
|
changeprop_char(w, prop, type, s, len - 1);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "x11.h"
|
#include "x11.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
sendevent(Window *w, bool propegate, long mask, XEvent *e) {
|
sendevent(Window *w, bool propegate, long mask, void *e) {
|
||||||
XSendEvent(display, w->xid, propegate, mask, e);
|
XSendEvent(display, w->xid, propegate, mask, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,19 +2,23 @@
|
|||||||
* See LICENSE file for license details.
|
* See LICENSE file for license details.
|
||||||
*/
|
*/
|
||||||
#include "x11.h"
|
#include "x11.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
sendmessage(Window *w, char *name, long l0, long l1, long l2, long l3, long l4) {
|
sendmessage(Window *w, char *name, long l0, long l1, long l2, long l3, long l4) {
|
||||||
|
|
||||||
|
clientmessage(w, name, NoEventMask, 32, (ClientMessageData){ .l = { l0, l1, l2, l3, l4 } });
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clientmessage(Window *w, char *name, long mask, int format, ClientMessageData data) {
|
||||||
XClientMessageEvent e;
|
XClientMessageEvent e;
|
||||||
|
|
||||||
e.type = ClientMessage;
|
e.type = ClientMessage;
|
||||||
e.window = w->xid;
|
e.window = w->xid;
|
||||||
e.message_type = xatom(name);
|
e.message_type = xatom(name);
|
||||||
e.format = 32;
|
e.format = format;
|
||||||
e.data.l[0] = l0;
|
bcopy(&data, &e.data, sizeof(data));
|
||||||
e.data.l[1] = l1;
|
sendevent(w, false, mask, (XEvent*)&e);
|
||||||
e.data.l[2] = l2;
|
|
||||||
e.data.l[3] = l3;
|
|
||||||
e.data.l[4] = l4;
|
|
||||||
sendevent(w, false, NoEventMask, (XEvent*)&e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
* See LICENSE file for license details.
|
* See LICENSE file for license details.
|
||||||
*/
|
*/
|
||||||
#include "../x11.h"
|
#include "../x11.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static char hostname[HOST_NAME_MAX + 1];
|
||||||
|
|
||||||
Window*
|
Window*
|
||||||
createwindow_visual(Window *parent, Rectangle r,
|
createwindow_visual(Window *parent, Rectangle r,
|
||||||
@ -21,6 +25,8 @@ createwindow_visual(Window *parent, Rectangle r,
|
|||||||
w->parent = parent;
|
w->parent = parent;
|
||||||
if(valmask & CWColormap)
|
if(valmask & CWColormap)
|
||||||
w->colormap = wa->colormap;
|
w->colormap = wa->colormap;
|
||||||
|
if(valmask & CWEventMask)
|
||||||
|
w->eventmask = wa->event_mask;
|
||||||
|
|
||||||
w->xid = XCreateWindow(display, parent->xid, r.min.x, r.min.y, Dx(r), Dy(r),
|
w->xid = XCreateWindow(display, parent->xid, r.min.x, r.min.y, Dx(r), Dy(r),
|
||||||
0 /* border */, depth, class, vis, valmask, wa);
|
0 /* border */, depth, class, vis, valmask, wa);
|
||||||
@ -31,6 +37,12 @@ createwindow_visual(Window *parent, Rectangle r,
|
|||||||
if(class != InputOnly)
|
if(class != InputOnly)
|
||||||
w->gc = XCreateGC(display, w->xid, 0, nil);
|
w->gc = XCreateGC(display, w->xid, 0, nil);
|
||||||
|
|
||||||
|
changeprop_ulong(w, "_NET_WM_PID", "CARDINAL", (ulong[1]){ getpid() }, 1);
|
||||||
|
if(!hostname[0])
|
||||||
|
gethostname(hostname, sizeof(hostname) - 1);
|
||||||
|
if(hostname[0])
|
||||||
|
changeprop_char(w, "WM_CLIENT_MACHINE", "STRING", hostname, strlen(hostname));
|
||||||
|
|
||||||
w->r = r;
|
w->r = r;
|
||||||
w->depth = depth;
|
w->depth = depth;
|
||||||
return w;
|
return w;
|
||||||
|
@ -7,6 +7,8 @@ void
|
|||||||
destroywindow(Window *w) {
|
destroywindow(Window *w) {
|
||||||
assert(w->type == WWindow);
|
assert(w->type == WWindow);
|
||||||
sethandler(w, nil);
|
sethandler(w, nil);
|
||||||
|
while(w->handler_link)
|
||||||
|
pophandler(w, w->handler_link->handler);
|
||||||
if(w->xft)
|
if(w->xft)
|
||||||
xft->drawdestroy(w->xft);
|
xft->drawdestroy(w->xft);
|
||||||
if(w->gc)
|
if(w->gc)
|
||||||
|
@ -5,5 +5,6 @@
|
|||||||
|
|
||||||
void
|
void
|
||||||
selectinput(Window *w, long mask) {
|
selectinput(Window *w, long mask) {
|
||||||
|
w->eventmask = mask;
|
||||||
XSelectInput(display, w->xid, mask);
|
XSelectInput(display, w->xid, mask);
|
||||||
}
|
}
|
||||||
|
@ -3,21 +3,72 @@
|
|||||||
*/
|
*/
|
||||||
#include "../x11.h"
|
#include "../x11.h"
|
||||||
|
|
||||||
Handlers*
|
static void
|
||||||
sethandler(Window *w, Handlers *new) {
|
updatemap(Window *w) {
|
||||||
Handlers *old;
|
|
||||||
void **e;
|
void **e;
|
||||||
|
|
||||||
assert(w->type == WWindow);
|
assert(w->type == WWindow);
|
||||||
assert((w->prev != nil && w->next != nil) || w->next == w->prev);
|
assert((w->prev != nil && w->next != nil) || w->next == w->prev);
|
||||||
|
|
||||||
if(new == nil)
|
if(w->handler == nil && w->handler_link == nil)
|
||||||
map_rm(&windowmap, (ulong)w->xid);
|
map_rm(&windowmap, (ulong)w->xid);
|
||||||
else {
|
else {
|
||||||
e = map_get(&windowmap, (ulong)w->xid, true);
|
e = map_get(&windowmap, (ulong)w->xid, true);
|
||||||
*e = w;
|
*e = w;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Handlers*
|
||||||
|
sethandler(Window *w, Handlers *new) {
|
||||||
|
Handlers *old;
|
||||||
|
|
||||||
old = w->handler;
|
old = w->handler;
|
||||||
w->handler = new;
|
w->handler = new;
|
||||||
|
|
||||||
|
updatemap(w);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HandlersLink* free_link;
|
||||||
|
|
||||||
|
void
|
||||||
|
pushhandler(Window *w, Handlers *new, void *aux) {
|
||||||
|
HandlersLink *l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(free_link == nil) {
|
||||||
|
l = emalloc(16 * sizeof *l);
|
||||||
|
for(i=0; i < 16; i++) {
|
||||||
|
l[i].next = free_link;
|
||||||
|
free_link = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l = free_link;
|
||||||
|
free_link = l->next;
|
||||||
|
|
||||||
|
/* TODO: Maybe: pophandler(w, new); */
|
||||||
|
|
||||||
|
l->next = w->handler_link;
|
||||||
|
l->handler = new;
|
||||||
|
l->aux = aux;
|
||||||
|
w->handler_link = l;
|
||||||
|
|
||||||
|
updatemap(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pophandler(Window *w, Handlers *old) {
|
||||||
|
HandlersLink **lp;
|
||||||
|
HandlersLink *l;
|
||||||
|
|
||||||
|
for(lp=&w->handler_link; (l=*lp); lp=&l->next)
|
||||||
|
if(l->handler == old) {
|
||||||
|
*lp = l->next;
|
||||||
|
l->next = free_link;
|
||||||
|
free_link = l;
|
||||||
|
updatemap(w);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#define _X11_VISIBLE
|
#define _X11_VISIBLE
|
||||||
#include <stuff/x.h>
|
#include <stuff/x.h>
|
||||||
#include <stuff/util.h>
|
#include <stuff/util.h>
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include <X11/extensions/Xrender.h>
|
#include <X11/extensions/Xrender.h>
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@ TARG = wmii.1 \
|
|||||||
wmii9menu.1\
|
wmii9menu.1\
|
||||||
wihack.1 \
|
wihack.1 \
|
||||||
wimenu.1 \
|
wimenu.1 \
|
||||||
wistrut.1
|
wistrut.1 \
|
||||||
|
witray.1
|
||||||
|
|
||||||
$(TARG): Makefile $(ROOT)/mk/wmii.mk header.t2t
|
$(TARG): Makefile $(ROOT)/mk/wmii.mk header.t2t
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ provided.
|
|||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.P
|
.P
|
||||||
wmii(1), wmiir(1), wmii9menu(1), dmenu(1)
|
wmii(1), wmiir(1), wistrug(1), wmii9menu(1), dmenu(1)
|
||||||
|
|
||||||
.P
|
.P
|
||||||
\fI[1]\fR http://www.suckless.org/wiki/wmii/tips/9p_tips
|
\fI[1]\fR http://www.suckless.org/wiki/wmii/tips/9p_tips
|
||||||
|
@ -168,7 +168,7 @@ most shells.
|
|||||||
provided.
|
provided.
|
||||||
:
|
:
|
||||||
= SEE ALSO =
|
= SEE ALSO =
|
||||||
wmii(1), wmiir(1), wmii9menu(1), dmenu(1)
|
wmii(1), wmiir(1), wistrug(1), wmii9menu(1), dmenu(1)
|
||||||
|
|
||||||
[1] http://www.suckless.org/wiki/wmii/tips/9p_tips
|
[1] http://www.suckless.org/wiki/wmii/tips/9p_tips
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH "WIMENU" 1 "May, 2010" "wmii-@VERSION@"
|
.TH "WISTRUT" 1 "May, 2010" "wmii-@VERSION@"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.P
|
.P
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
WIMENU
|
WISTRUT
|
||||||
wmii-@VERSION@
|
wmii-@VERSION@
|
||||||
May, 2010
|
May, 2010
|
||||||
|
|
||||||
|
85
man/witray.1
Normal file
85
man/witray.1
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
.TH "WITRAY" 1 "May, 2010" "wmii-@VERSION@"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
.P
|
||||||
|
witray \- The wmii system tray
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.P
|
||||||
|
witray \fI[\-a \fI<address>\fR]\fR \fI[\-NESW]\fR \fI[\-HV]\fR \fI[\-p \fI<padding>\fR]\fR \fI[\-s \fI<iconsize>\fR]\fR \-t (tags)
|
||||||
|
.P
|
||||||
|
witray \-v
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.P
|
||||||
|
\fBwitray\fR is a simple system tray program meant to be used with wmii.
|
||||||
|
It supports the Freedesktop System Tray Protocol Specification
|
||||||
|
common among all newer applications and desktop environments. The
|
||||||
|
tray is only visible when applications require it. While there are
|
||||||
|
many standalone system tray applications, this one is explicitly
|
||||||
|
tailored to wmii. It's simple, stays out of the user's way, is easy
|
||||||
|
to configure, and generally Just Works.
|
||||||
|
|
||||||
|
.SH ARGUMENTS
|
||||||
|
.TP
|
||||||
|
\-a
|
||||||
|
The address at which to connect to \fBwmii\fR.
|
||||||
|
.TP
|
||||||
|
\-N \-E \-S \-W
|
||||||
|
|
||||||
|
.RS
|
||||||
|
Sets the screen edge where \fBwitray\fR is to appear to the
|
||||||
|
\fINorth\fR, \fISouth\fR, \fIEast\fR, or \fIWest\fR edge, respectively.
|
||||||
|
Options may be combined, for instance *\-NE* gives the _North
|
||||||
|
East_ corner of the screen. If no options are given,
|
||||||
|
\fBwitray\fR opens to the West of whichever part of the screen
|
||||||
|
the wmii bar occupies.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
\-H \-V
|
||||||
|
|
||||||
|
.RS
|
||||||
|
Specifies whether icons are to be aligned horizontally or
|
||||||
|
vertically, respectively. Also determines from which edge of
|
||||||
|
the screen windows are shunted to make room for the tray.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
\-p \fI<padding>\fR
|
||||||
|
|
||||||
|
.RS
|
||||||
|
Sets the padding between icons and around the edge of the
|
||||||
|
tray. In pixels.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
\-s \fI<iconsize>\fR
|
||||||
|
|
||||||
|
.RS
|
||||||
|
Sets the size of the icons, in pixels. If not provided,
|
||||||
|
icons are sized so that the tray is the same height as the
|
||||||
|
\fBwmii\fR bar.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
\-t \fI<tags>\fR
|
||||||
|
|
||||||
|
.RS
|
||||||
|
The tags on which to open. Default: \fI/./\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
\-v
|
||||||
|
|
||||||
|
.RS
|
||||||
|
Display version information.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH CAVEATS
|
||||||
|
.P
|
||||||
|
\fBwitray\fR is not XRandR aware.
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.P
|
||||||
|
wmii(1), wimenu(1)
|
||||||
|
|
||||||
|
|
||||||
|
.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net)
|
||||||
|
.\" cmdline: txt2tags -o- witray.man1
|
||||||
|
|
60
man/witray.man1
Normal file
60
man/witray.man1
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
WITRAY
|
||||||
|
wmii-@VERSION@
|
||||||
|
May, 2010
|
||||||
|
|
||||||
|
%!includeconf: header.t2t
|
||||||
|
|
||||||
|
= NAME =
|
||||||
|
|
||||||
|
witray - The wmii system tray
|
||||||
|
|
||||||
|
= SYNOPSIS =
|
||||||
|
|
||||||
|
witray [-a <address>] [-NESW] [-HV] [-p <padding>] [-s <iconsize>] [-t tags] +
|
||||||
|
witray -v
|
||||||
|
|
||||||
|
= DESCRIPTION =
|
||||||
|
|
||||||
|
`witray` is a simple system tray program meant to be used with wmii.
|
||||||
|
It supports the Freedesktop System Tray Protocol Specification
|
||||||
|
common among all newer applications and desktop environments. The
|
||||||
|
tray is only visible when applications require it. While there are
|
||||||
|
many standalone system tray applications, this one is explicitly
|
||||||
|
tailored to wmii. It's simple, stays out of the user's way, is easy
|
||||||
|
to configure, and generally Just Works.
|
||||||
|
|
||||||
|
= ARGUMENTS =
|
||||||
|
|
||||||
|
: -a
|
||||||
|
The address at which to connect to `wmii`.
|
||||||
|
: -N -E -S -W
|
||||||
|
Sets the screen edge where `witray` is to appear to the
|
||||||
|
_North_, _South_, _East_, or _West_ edge, respectively.
|
||||||
|
Options may be combined, for instance *-NE* gives the _North
|
||||||
|
East_ corner of the screen. If no options are given,
|
||||||
|
`witray` opens to the West of whichever part of the screen
|
||||||
|
the wmii bar occupies.
|
||||||
|
: -H -V
|
||||||
|
Specifies whether icons are to be aligned horizontally or
|
||||||
|
vertically, respectively. Also determines from which edge of
|
||||||
|
the screen windows are shunted to make room for the tray.
|
||||||
|
: -p <padding>
|
||||||
|
Sets the padding between icons and around the edge of the
|
||||||
|
tray. In pixels.
|
||||||
|
: -s <iconsize>
|
||||||
|
Sets the size of the icons, in pixels. If not provided,
|
||||||
|
icons are sized so that the tray is the same height as the
|
||||||
|
`wmii` bar.
|
||||||
|
: -t <tags>
|
||||||
|
The tags on which to open. Default: _/./_
|
||||||
|
: -v
|
||||||
|
Display version information.
|
||||||
|
|
||||||
|
= CAVEATS =
|
||||||
|
|
||||||
|
`witray` is not XRandR aware.
|
||||||
|
|
||||||
|
= SEE ALSO =
|
||||||
|
|
||||||
|
wmii(1), wimenu(1)
|
||||||
|
|
@ -14,7 +14,7 @@ echo CC $($bin/cleanname ${BASE}$outfile)
|
|||||||
[ -n "$noisycc" ] && echo $CC -o $outfile $CFLAGS $@
|
[ -n "$noisycc" ] && echo $CC -o $outfile $CFLAGS $@
|
||||||
eval '$CC -o $outfile '"$CFLAGS"' $@ >$xtmp 2>&1'
|
eval '$CC -o $outfile '"$CFLAGS"' $@ >$xtmp 2>&1'
|
||||||
status=$?
|
status=$?
|
||||||
[ $? -eq 0 ] || echo $CC -o $outfile $CFLAGS $@ >&2
|
[ $status -eq 0 ] || echo $CC -o $outfile $CFLAGS $@ >&2
|
||||||
|
|
||||||
base=$(echo $BASE | sed 's/,/\\,/g')
|
base=$(echo $BASE | sed 's/,/\\,/g')
|
||||||
re='\([^[:space:]/][^[:space:]]*\..:[0-9]\)'
|
re='\([^[:space:]/][^[:space:]]*\..:[0-9]\)'
|
||||||
|
Loading…
Reference in New Issue
Block a user