mirror of
https://github.com/0intro/wmii
synced 2024-11-22 05:42:05 +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"
|
||||
pkgver=2637
|
||||
pkgver=2647
|
||||
pkgrel=1
|
||||
pkgdesc="The latest hg pull of wmii, a lightweight, dynamic window manager for X11"
|
||||
url="http://wmii.suckless.org"
|
||||
@ -16,8 +16,6 @@ provides=("wmii")
|
||||
conflicts=("wmii")
|
||||
source=()
|
||||
|
||||
test -d src || mkdir src
|
||||
ln -snf .. src/wmii
|
||||
FORCE_VER=$(hg tip --template {rev})
|
||||
#_hgroot="http://hg.suckless.org/"
|
||||
#_hgrepo="wmii"
|
||||
@ -32,7 +30,7 @@ build()
|
||||
make "${flags[@]}" || 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
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@ wmiir.c: $(ROOT)/mk/wmii.mk
|
||||
|
||||
DIRS = wmii \
|
||||
menu \
|
||||
strut
|
||||
strut \
|
||||
tray
|
||||
TARG = wihack \
|
||||
wmii.rc \
|
||||
wmii.sh \
|
||||
|
@ -12,7 +12,7 @@ bindings.c: keys.txt Makefile
|
||||
TARG = wimenu
|
||||
HFILES= dat.h fns.h
|
||||
|
||||
PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama
|
||||
PACKAGES += $(X11PACKAGES)
|
||||
|
||||
LIBS += -lm $(LIBS9) $(LIBIXP)
|
||||
CFLAGS += -DIXP_NEEDAPI=86
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ixp.h>
|
||||
#include <stuff/x.h>
|
||||
#include <stuff/util.h>
|
||||
#include <ixp.h>
|
||||
|
||||
#define BLOCK(x) do { x; }while(0)
|
||||
|
||||
|
@ -171,20 +171,6 @@ update_filter(bool print) {
|
||||
update_input();
|
||||
}
|
||||
|
||||
static void
|
||||
end(IxpConn *c) {
|
||||
|
||||
USED(c);
|
||||
srv.running = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
preselect(IxpServer *s) {
|
||||
|
||||
USED(s);
|
||||
event_check();
|
||||
}
|
||||
|
||||
enum { PointerScreen = -1 };
|
||||
|
||||
void
|
||||
@ -224,7 +210,6 @@ main(int argc, char *argv[]) {
|
||||
|
||||
quotefmtinstall();
|
||||
fmtinstall('r', errfmt);
|
||||
address = getenv("WMII_ADDRESS");
|
||||
screen_hint = PointerScreen;
|
||||
|
||||
find = strstr;
|
||||
@ -283,17 +268,18 @@ main(int argc, char *argv[]) {
|
||||
|
||||
client_init(address);
|
||||
|
||||
srv.preselect = preselect;
|
||||
ixp_listen(&srv, ConnectionNumber(display), nil, (void (*)(IxpConn*))preselect, end);
|
||||
srv.preselect = event_preselect;
|
||||
ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
|
||||
|
||||
ontop = !strcmp(readctl("bar on "), "top");
|
||||
loadcolor(&cnorm, readctl("normcolors "));
|
||||
loadcolor(&csel, readctl("focuscolors "));
|
||||
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)
|
||||
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);
|
||||
items = populate_list(cmplbuf, false);
|
||||
|
@ -255,7 +255,7 @@ menu_show(void) {
|
||||
}
|
||||
|
||||
static void
|
||||
kdown_event(Window *w, XKeyEvent *e) {
|
||||
kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||
char **action, **p;
|
||||
char *key;
|
||||
char buf[32];
|
||||
@ -331,7 +331,7 @@ kdown_event(Window *w, XKeyEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
expose_event(Window *w, XExposeEvent *e) {
|
||||
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||
|
||||
USED(w);
|
||||
menu_draw();
|
||||
|
@ -7,9 +7,8 @@ main.c: $(ROOT)/mk/wmii.mk
|
||||
TARG = wistrut
|
||||
HFILES= dat.h fns.h
|
||||
|
||||
PACKAGES += $(X11PACKAGES) xext xrandr xinerama
|
||||
PACKAGES += $(X11PACKAGES)
|
||||
|
||||
LIB = $(LIBIXP)
|
||||
LIBS += -lm $(LIBS9)
|
||||
CFLAGS += -DIXP_NEEDAPI=86
|
||||
OBJ = main \
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <unistd.h>
|
||||
#include <stuff/x.h>
|
||||
#include <stuff/util.h>
|
||||
#include <ixp.h>
|
||||
|
||||
#ifndef 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 ewmh_getstrut(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);
|
||||
}
|
||||
|
||||
static int
|
||||
errfmt(Fmt *f) {
|
||||
return fmtstrcpy(f, ixp_errbuf());
|
||||
}
|
||||
|
||||
static void
|
||||
search_wins(char *pattern) {
|
||||
ulong *wins;
|
||||
@ -135,7 +130,6 @@ main(int argc, char *argv[]) {
|
||||
ulong win;
|
||||
char *s;
|
||||
|
||||
fmtinstall('r', errfmt);
|
||||
fmtinstall('E', fmtevent);
|
||||
|
||||
ARGBEGIN{
|
||||
|
@ -80,22 +80,23 @@ restrut(Window *frame) {
|
||||
}
|
||||
|
||||
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),
|
||||
Pt(ev->x+ev->border_width, ev->y+ev->border_width));
|
||||
frame->r = rectaddpt(Rect(ev->x, ev->y, ev->width, ev->height),
|
||||
Pt(ev->border_width, ev->border_width));
|
||||
restrut(frame);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy(Window *w, XDestroyWindowEvent *ev) {
|
||||
USED(w, ev);
|
||||
destroy_event(Window *w, void *aux, XDestroyWindowEvent *ev) {
|
||||
|
||||
USED(ev);
|
||||
sethandler(w, nil);
|
||||
event_looprunning = windowmap.nmemb > 0;
|
||||
}
|
||||
|
||||
Handlers handlers = {
|
||||
.config = config,
|
||||
.destroy = destroy,
|
||||
.config = config_event,
|
||||
.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
|
||||
OBJ = area \
|
||||
bar \
|
||||
backtrace \
|
||||
client \
|
||||
column \
|
||||
div \
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include <bio.h>
|
||||
#include <plan9.h>
|
||||
#undef nelem
|
||||
#include <debug.h>
|
||||
#include "util.h"
|
||||
#include <stuff/util.h>
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef __linux__
|
||||
# define PROGTXT "exe"
|
@ -246,7 +246,7 @@ findbar(WMScreen *s, Point p) {
|
||||
}
|
||||
|
||||
static void
|
||||
bdown_event(Window *w, XButtonPressedEvent *e) {
|
||||
bdown_event(Window *w, void *aux, XButtonPressedEvent *e) {
|
||||
WMScreen *s;
|
||||
Bar *b;
|
||||
|
||||
@ -254,29 +254,29 @@ bdown_event(Window *w, XButtonPressedEvent *e) {
|
||||
XUngrabPointer(display, e->time);
|
||||
sync();
|
||||
|
||||
s = w->aux;
|
||||
s = aux;
|
||||
b = findbar(s, Pt(e->x, e->y));
|
||||
if(b)
|
||||
event("%sBarMouseDown %d %s\n", barside[b->bar], e->button, b->name);
|
||||
}
|
||||
|
||||
static void
|
||||
bup_event(Window *w, XButtonPressedEvent *e) {
|
||||
bup_event(Window *w, void *aux, XButtonPressedEvent *e) {
|
||||
WMScreen *s;
|
||||
Bar *b;
|
||||
|
||||
s = w->aux;
|
||||
s = aux;
|
||||
b = findbar(s, Pt(e->x, e->y));
|
||||
if(b)
|
||||
event("%sBarClick %d %s\n", barside[b->bar], e->button, b->name);
|
||||
}
|
||||
|
||||
static Rectangle
|
||||
dndmotion_event(Window *w, Point p) {
|
||||
dndmotion_event(Window *w, void *aux, Point p) {
|
||||
WMScreen *s;
|
||||
Bar *b;
|
||||
|
||||
s = w->aux;
|
||||
s = aux;
|
||||
b = findbar(s, p);
|
||||
if(b) {
|
||||
event("%sBarDND 1 %s\n", barside[b->bar], b->name);
|
||||
@ -286,9 +286,9 @@ dndmotion_event(Window *w, Point p) {
|
||||
}
|
||||
|
||||
static void
|
||||
expose_event(Window *w, XExposeEvent *e) {
|
||||
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||
USED(w, e);
|
||||
bar_draw(w->aux);
|
||||
bar_draw(aux);
|
||||
}
|
||||
|
||||
static Handlers handlers = {
|
||||
|
@ -101,9 +101,8 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
||||
c->fullscreen = -1;
|
||||
c->border = wa->border_width;
|
||||
|
||||
c->r.min = Pt(wa->x, wa->y);
|
||||
c->r.max = addpt(c->r.min,
|
||||
Pt(wa->width, wa->height));
|
||||
c->r = rectsetorigin(Rect(0, 0, wa->width, wa->height),
|
||||
Pt(wa->x, wa->y));
|
||||
|
||||
c->w.type = WWindow;
|
||||
c->w.xid = w;
|
||||
@ -115,7 +114,7 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
||||
c->ibuf = &ibuf;
|
||||
if(render_argb_p(wa->visual)) {
|
||||
depth = 32;
|
||||
vis = render_visual;
|
||||
vis = scr.visual32;
|
||||
c->ibuf = &ibuf32;
|
||||
}
|
||||
|
||||
@ -589,7 +588,7 @@ client_configure(Client *c) {
|
||||
e.height = Dy(r);
|
||||
e.border_width = c->border;
|
||||
|
||||
sendevent(&c->w, false, StructureNotifyMask, (XEvent*)&e);
|
||||
sendevent(&c->w, false, StructureNotifyMask, &e);
|
||||
}
|
||||
|
||||
void
|
||||
@ -809,7 +808,7 @@ client_prop(Client *c, Atom a) {
|
||||
memset(&h, 0, sizeof h);
|
||||
if(c->w.hints)
|
||||
bcopy(c->w.hints, &h, sizeof h);
|
||||
sethints(&c->w);
|
||||
gethints(&c->w);
|
||||
if(c->w.hints)
|
||||
c->fixedsize = eqpt(c->w.hints->min, c->w.hints->max);
|
||||
if(memcmp(&h, c->w.hints, sizeof h))
|
||||
@ -841,11 +840,11 @@ client_prop(Client *c, Atom a) {
|
||||
|
||||
/* Handlers */
|
||||
static void
|
||||
configreq_event(Window *w, XConfigureRequestEvent *e) {
|
||||
configreq_event(Window *w, void *aux, XConfigureRequestEvent *e) {
|
||||
Rectangle r, cr;
|
||||
Client *c;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
|
||||
r = client_grav(c, ZR);
|
||||
r.max = subpt(r.max, r.min);
|
||||
@ -875,17 +874,17 @@ configreq_event(Window *w, XConfigureRequestEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_event(Window *w, XDestroyWindowEvent *e) {
|
||||
destroy_event(Window *w, void *aux, XDestroyWindowEvent *e) {
|
||||
USED(w, e);
|
||||
|
||||
client_destroy(w->aux);
|
||||
client_destroy(aux);
|
||||
}
|
||||
|
||||
static void
|
||||
enter_event(Window *w, XCrossingEvent *e) {
|
||||
enter_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||
Client *c;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
if(e->detail != NotifyInferior) {
|
||||
if(e->detail != NotifyVirtual)
|
||||
if(e->serial != ignoreenter && disp.focus != c) {
|
||||
@ -898,10 +897,10 @@ enter_event(Window *w, XCrossingEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
focusin_event(Window *w, XFocusChangeEvent *e) {
|
||||
focusin_event(Window *w, void *aux, XFocusChangeEvent *e) {
|
||||
Client *c, *old;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
|
||||
print_focus("focusin_event", c, c->name);
|
||||
|
||||
@ -918,10 +917,10 @@ focusin_event(Window *w, XFocusChangeEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
focusout_event(Window *w, XFocusChangeEvent *e) {
|
||||
focusout_event(Window *w, void *aux, XFocusChangeEvent *e) {
|
||||
Client *c;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
if((e->mode == NotifyWhileGrabbed) && (disp.hasgrab != &c_root)) {
|
||||
if(disp.focus)
|
||||
disp.hasgrab = disp.focus;
|
||||
@ -934,34 +933,34 @@ focusout_event(Window *w, XFocusChangeEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_event(Window *w, XUnmapEvent *e) {
|
||||
unmap_event(Window *w, void *aux, XUnmapEvent *e) {
|
||||
Client *c;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
if(!e->send_event)
|
||||
c->unmapped--;
|
||||
client_destroy(c);
|
||||
}
|
||||
|
||||
static void
|
||||
map_event(Window *w, XMapEvent *e) {
|
||||
map_event(Window *w, void *aux, XMapEvent *e) {
|
||||
Client *c;
|
||||
|
||||
USED(e);
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
if(c == selclient())
|
||||
client_focus(c);
|
||||
}
|
||||
|
||||
static void
|
||||
property_event(Window *w, XPropertyEvent *e) {
|
||||
property_event(Window *w, void *aux, XPropertyEvent *e) {
|
||||
Client *c;
|
||||
|
||||
if(e->state == PropertyDelete) /* FIXME */
|
||||
return;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
client_prop(c, e->atom);
|
||||
}
|
||||
|
||||
@ -1002,6 +1001,7 @@ client_setviews(Client *c, char **tags) {
|
||||
if(*tags) {
|
||||
if(!*fp || cmp > 0) {
|
||||
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)
|
||||
c->sel = f;
|
||||
kludge = c; /* FIXME */
|
||||
|
@ -12,10 +12,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <utf.h>
|
||||
#include <ixp.h>
|
||||
#include <stuff/x.h>
|
||||
#include <stuff/util.h>
|
||||
#include <debug.h>
|
||||
#include <ixp.h>
|
||||
#include "debug.h"
|
||||
|
||||
#define FONT "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*"
|
||||
#define FOCUSCOLORS "#ffffff #335577 #447799"
|
||||
|
@ -1,5 +1,16 @@
|
||||
#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 Dprint(x, ...) BLOCK( if((debugflag|debugfile)&(x)) debug(x, __VA_ARGS__) )
|
||||
|
@ -164,22 +164,22 @@ div_update_all(void) {
|
||||
|
||||
/* Div Handlers */
|
||||
static void
|
||||
bdown_event(Window *w, XButtonEvent *e) {
|
||||
bdown_event(Window *w, void *aux, XButtonEvent *e) {
|
||||
Divide *d;
|
||||
|
||||
USED(e);
|
||||
|
||||
d = w->aux;
|
||||
d = aux;
|
||||
mouse_resizecol(d);
|
||||
}
|
||||
|
||||
static void
|
||||
expose_event(Window *w, XExposeEvent *e) {
|
||||
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||
Divide *d;
|
||||
|
||||
USED(e);
|
||||
|
||||
d = w->aux;
|
||||
d = aux;
|
||||
drawdiv(d);
|
||||
}
|
||||
|
||||
|
@ -10,15 +10,12 @@ debug_event(XEvent *e) {
|
||||
Dprint(DEvent, "%E\n", e);
|
||||
}
|
||||
|
||||
#define handle(w, fn, ev) \
|
||||
BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev))
|
||||
|
||||
void
|
||||
event_buttonpress(XButtonPressedEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, bdown, ev);
|
||||
event_handle(w, bdown, ev);
|
||||
else
|
||||
XAllowEvents(display, ReplayPointer, ev->time);
|
||||
}
|
||||
@ -29,7 +26,7 @@ event_configurenotify(XConfigureEvent *ev) {
|
||||
|
||||
ignoreenter = ev->serial;
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, config, ev);
|
||||
event_handle(w, config, ev);
|
||||
}
|
||||
|
||||
void
|
||||
@ -47,7 +44,7 @@ event_destroynotify(XDestroyWindowEvent *ev) {
|
||||
Client *c;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, destroy, ev);
|
||||
event_handle(w, destroy, ev);
|
||||
else if((c = win2client(ev->window)))
|
||||
fprint(2, "Badness: Unhandled DestroyNotify: Client: %p, Window: %W, Name: %s\n",
|
||||
c, &c->w, c->name);
|
||||
@ -87,7 +84,7 @@ event_focusin(XFocusChangeEvent *ev) {
|
||||
disp.focus = nil;
|
||||
}
|
||||
else if((w = findwin(ev->window)))
|
||||
handle(w, focusin, ev);
|
||||
event_handle(w, focusin, ev);
|
||||
else if(ev->mode == NotifyGrab) {
|
||||
/* Some unmanaged window has grabbed focus */
|
||||
if((c = disp.focus)) {
|
||||
@ -117,7 +114,7 @@ event_focusout(XFocusChangeEvent *ev) {
|
||||
&& XCheckMaskEvent(display, KeyPressMask, &me))
|
||||
event_dispatch(&me);
|
||||
else if((w = findwin(ev->window)))
|
||||
handle(w, focusout, ev);
|
||||
event_handle(w, focusout, ev);
|
||||
}
|
||||
|
||||
void
|
||||
@ -126,7 +123,7 @@ event_mapnotify(XMapEvent *ev) {
|
||||
|
||||
ignoreenter = ev->serial;
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, map, ev);
|
||||
event_handle(w, map, ev);
|
||||
}
|
||||
|
||||
void
|
||||
@ -137,7 +134,7 @@ event_unmapnotify(XUnmapEvent *ev) {
|
||||
if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) {
|
||||
w->mapped = false;
|
||||
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) {
|
||||
f->floatr = c->sel->floatr;
|
||||
f->r = c->sel->r;
|
||||
}else if(c->sel) {
|
||||
f->floatr = c->frame->floatr;
|
||||
f->r = c->frame->r;
|
||||
}else {
|
||||
f->r = client_grav(c, c->r);
|
||||
f->floatr = f->r;
|
||||
@ -140,20 +143,20 @@ frame_restack(Frame *f, Frame *above) {
|
||||
|
||||
/* Handlers */
|
||||
static void
|
||||
bup_event(Window *w, XButtonEvent *e) {
|
||||
bup_event(Window *w, void *aux, XButtonEvent *e) {
|
||||
if((e->state & def.mod) != def.mod)
|
||||
XAllowEvents(display, ReplayPointer, e->time);
|
||||
else
|
||||
XUngrabPointer(display, e->time);
|
||||
event("ClientClick %#C %d\n", w->aux, e->button);
|
||||
event("ClientClick %#C %d\n", aux, e->button);
|
||||
}
|
||||
|
||||
static void
|
||||
bdown_event(Window *w, XButtonEvent *e) {
|
||||
bdown_event(Window *w, void *aux, XButtonEvent *e) {
|
||||
Frame *f;
|
||||
Client *c;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
f = c->sel;
|
||||
|
||||
if((e->state & def.mod) == def.mod) {
|
||||
@ -200,17 +203,17 @@ bdown_event(Window *w, XButtonEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
config_event(Window *w, XConfigureEvent *e) {
|
||||
config_event(Window *w, void *aux, XConfigureEvent *e) {
|
||||
|
||||
USED(w, e);
|
||||
}
|
||||
|
||||
static void
|
||||
enter_event(Window *w, XCrossingEvent *e) {
|
||||
enter_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||
Client *c;
|
||||
Frame *f;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
f = c->sel;
|
||||
if(disp.focus != c || selclient() != c) {
|
||||
Dprint(DFocus, "enter_notify(f) => [%#C]%s%s\n",
|
||||
@ -225,12 +228,12 @@ enter_event(Window *w, XCrossingEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
expose_event(Window *w, XExposeEvent *e) {
|
||||
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||
Client *c;
|
||||
|
||||
USED(e);
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
if(c->sel)
|
||||
frame_draw(c->sel);
|
||||
else
|
||||
@ -239,10 +242,10 @@ expose_event(Window *w, XExposeEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
motion_event(Window *w, XMotionEvent *e) {
|
||||
motion_event(Window *w, void *aux, XMotionEvent *e) {
|
||||
Client *c;
|
||||
|
||||
c = w->aux;
|
||||
c = aux;
|
||||
mouse_checkresize(c->sel, Pt(e->x, e->y), false);
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ framedestroy(Framewin *f) {
|
||||
}
|
||||
|
||||
static void
|
||||
expose_event(Window *w, XExposeEvent *e) {
|
||||
expose_event(Window *w, void *aux, XExposeEvent *e) {
|
||||
Rectangle r;
|
||||
Framewin *f;
|
||||
Image *buf;
|
||||
@ -107,7 +107,7 @@ expose_event(Window *w, XExposeEvent *e) {
|
||||
|
||||
USED(e);
|
||||
|
||||
f = w->aux;
|
||||
f = aux;
|
||||
c = &def.focuscolor;
|
||||
buf = disp.ibuf;
|
||||
|
||||
|
@ -317,13 +317,6 @@ spawn_command(const char *cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_preselect(IxpServer *s) {
|
||||
USED(s);
|
||||
|
||||
event_check();
|
||||
}
|
||||
|
||||
static void
|
||||
closedisplay(IxpConn *c) {
|
||||
USED(c);
|
||||
@ -412,9 +405,9 @@ extern int fmtevent(Fmt*);
|
||||
|
||||
event_debug = debug_event;
|
||||
|
||||
srv.preselect = check_preselect;
|
||||
srv.preselect = event_preselect;
|
||||
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.colmode = Colstack;
|
||||
|
@ -29,7 +29,7 @@ quad_cursor(Align align) {
|
||||
}
|
||||
|
||||
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, w->r, def.focuscolor.bg);
|
||||
|
@ -24,13 +24,13 @@ root_init(void) {
|
||||
}
|
||||
|
||||
static void
|
||||
enter_event(Window *w, XCrossingEvent *e) {
|
||||
enter_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||
disp.sel = true;
|
||||
frame_draw_all();
|
||||
}
|
||||
|
||||
static void
|
||||
leave_event(Window *w, XCrossingEvent *e) {
|
||||
leave_event(Window *w, void *aux, XCrossingEvent *e) {
|
||||
if(!e->same_screen) {
|
||||
disp.sel = false;
|
||||
frame_draw_all();
|
||||
@ -38,13 +38,13 @@ leave_event(Window *w, XCrossingEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
focusin_event(Window *w, XFocusChangeEvent *e) {
|
||||
focusin_event(Window *w, void *aux, XFocusChangeEvent *e) {
|
||||
if(e->mode == NotifyGrab)
|
||||
disp.hasgrab = &c_root;
|
||||
}
|
||||
|
||||
static void
|
||||
mapreq_event(Window *w, XMapRequestEvent *e) {
|
||||
mapreq_event(Window *w, void *aux, XMapRequestEvent *e) {
|
||||
XWindowAttributes wa;
|
||||
|
||||
if(!XGetWindowAttributes(display, e->window, &wa))
|
||||
@ -62,7 +62,7 @@ mapreq_event(Window *w, XMapRequestEvent *e) {
|
||||
}
|
||||
|
||||
static void
|
||||
motion_event(Window *w, XMotionEvent *e) {
|
||||
motion_event(Window *w, void *aux, XMotionEvent *e) {
|
||||
Rectangle r, r2;
|
||||
|
||||
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
|
||||
kdown_event(Window *w, XKeyEvent *e) {
|
||||
kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||
|
||||
e->state &= valid_mask;
|
||||
kpress(w->xid, e->state, (KeyCode)e->keycode);
|
||||
|
@ -71,7 +71,7 @@ xdnd_clientmessage(XClientMessageEvent *e) {
|
||||
Dprint(DDnd, "\tp: %P\n", p);
|
||||
if(eqrect(dnd->r, ZR) || !rect_haspoint_p(p, dnd->r))
|
||||
if(w->handler->dndmotion)
|
||||
dnd->r = w->handler->dndmotion(w, p);
|
||||
dnd->r = w->handler->dndmotion(w, w->aux, p);
|
||||
r = dnd->r;
|
||||
if(!eqrect(r, ZR))
|
||||
r = rectaddpt(r, w->r.min);
|
||||
|
@ -26,7 +26,7 @@ LD = cc
|
||||
# Archiver
|
||||
AR = ar crs
|
||||
|
||||
X11PACKAGES = x11 xinerama xrender
|
||||
X11PACKAGES = x11 xinerama xrender xrandr
|
||||
INCX11 = $$(pkg-config --cflags $(X11PACKAGES))
|
||||
LIBIXP = $(LIBDIR)/libixp.a
|
||||
|
||||
|
@ -1,18 +1,25 @@
|
||||
#pragma once
|
||||
#define _XOPEN_SOURCE 600
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef nil
|
||||
#define nil ((void*)0)
|
||||
# define nil ((void*)0)
|
||||
#endif
|
||||
|
||||
#ifndef nelem
|
||||
#define nelem(ary) (sizeof(ary) / sizeof(*ary))
|
||||
# define nelem(ary) (sizeof(ary) / sizeof(*ary))
|
||||
#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 ushort
|
||||
#undef uint
|
||||
|
@ -22,16 +22,7 @@ enum {
|
||||
CCenter = 1<<1,
|
||||
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 {
|
||||
GInvert = 1<<0,
|
||||
};
|
||||
|
@ -16,11 +16,21 @@ void xext_event(XEvent*);
|
||||
void xext_init(void);
|
||||
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_dispatch(XEvent*);
|
||||
uint event_flush(long, bool dispatch);
|
||||
uint event_flushenter(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_buttonpress(XButtonPressedEvent*);
|
||||
@ -36,10 +46,14 @@ void event_focusout(XFocusChangeEvent*);
|
||||
void event_keypress(XKeyEvent*);
|
||||
void event_leavenotify(XCrossingEvent*);
|
||||
void event_mapnotify(XMapEvent*);
|
||||
void event_maprequest(XMapRequestEvent*);
|
||||
void event_mappingnotify(XMappingEvent*);
|
||||
void event_maprequest(XMapRequestEvent*);
|
||||
void event_motionnotify(XMotionEvent*);
|
||||
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*);
|
||||
|
||||
extern long event_xtime;
|
||||
|
@ -33,12 +33,14 @@ typedef enum WindowType WindowType;
|
||||
|
||||
typedef XSetWindowAttributes WinAttr;
|
||||
|
||||
typedef union ClientMessageData ClientMessageData;
|
||||
typedef struct Color Color;
|
||||
typedef struct CTuple CTuple;
|
||||
typedef struct ErrorCode ErrorCode;
|
||||
typedef struct Ewmh Ewmh;
|
||||
typedef struct Font Font;
|
||||
typedef struct Handlers Handlers;
|
||||
typedef struct HandlersLink HandlersLink;
|
||||
typedef struct Screen Screen;
|
||||
typedef struct WinHints WinHints;
|
||||
typedef struct Window Image;
|
||||
@ -48,6 +50,12 @@ typedef struct XftColor XftColor;
|
||||
typedef void XftDraw;
|
||||
typedef struct XftFont XftFont;
|
||||
|
||||
union ClientMessageData {
|
||||
char b[20];
|
||||
short s[10];
|
||||
long l[5];
|
||||
};
|
||||
|
||||
struct Color {
|
||||
ulong pixel;
|
||||
XRenderColor render;
|
||||
@ -86,24 +94,35 @@ struct Font {
|
||||
};
|
||||
|
||||
struct Handlers {
|
||||
Rectangle (*dndmotion)(Window*, Point);
|
||||
void (*bdown)(Window*, XButtonEvent*);
|
||||
void (*bup)(Window*, XButtonEvent*);
|
||||
void (*config)(Window*, XConfigureEvent*);
|
||||
void (*configreq)(Window*, XConfigureRequestEvent*);
|
||||
void (*destroy)(Window*, XDestroyWindowEvent*);
|
||||
void (*enter)(Window*, XCrossingEvent*);
|
||||
void (*expose)(Window*, XExposeEvent*);
|
||||
void (*focusin)(Window*, XFocusChangeEvent*);
|
||||
void (*focusout)(Window*, XFocusChangeEvent*);
|
||||
void (*kdown)(Window*, XKeyEvent*);
|
||||
void (*kup)(Window*, XKeyEvent*);
|
||||
void (*leave)(Window*, XCrossingEvent*);
|
||||
void (*map)(Window*, XMapEvent*);
|
||||
void (*mapreq)(Window*, XMapRequestEvent*);
|
||||
void (*motion)(Window*, XMotionEvent*);
|
||||
void (*property)(Window*, XPropertyEvent*);
|
||||
void (*unmap)(Window*, XUnmapEvent*);
|
||||
Rectangle (*dndmotion)(Window*, void*, Point);
|
||||
void (*bdown)(Window*, void*, XButtonEvent*);
|
||||
void (*bup)(Window*, void*, XButtonEvent*);
|
||||
void (*config)(Window*, void*, XConfigureEvent*);
|
||||
void (*configreq)(Window*, void*, XConfigureRequestEvent*);
|
||||
void (*destroy)(Window*, void*, XDestroyWindowEvent*);
|
||||
void (*enter)(Window*, void*, XCrossingEvent*);
|
||||
void (*expose)(Window*, void*, XExposeEvent*);
|
||||
void (*focusin)(Window*, void*, XFocusChangeEvent*);
|
||||
void (*focusout)(Window*, void*, XFocusChangeEvent*);
|
||||
void (*kdown)(Window*, void*, XKeyEvent*);
|
||||
void (*kup)(Window*, void*, XKeyEvent*);
|
||||
void (*leave)(Window*, void*, XCrossingEvent*);
|
||||
void (*map)(Window*, void*, XMapEvent*);
|
||||
void (*mapreq)(Window*, void*, XMapRequestEvent*);
|
||||
void (*message)(Window*, void*, XClientMessageEvent*);
|
||||
void (*motion)(Window*, void*, XMotionEvent*);
|
||||
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 {
|
||||
@ -132,8 +151,10 @@ struct Window {
|
||||
Window* next;
|
||||
Window* prev;
|
||||
Handlers* handler;
|
||||
HandlersLink* handler_link;
|
||||
WinHints* hints;
|
||||
Ewmh ewmh;
|
||||
long eventmask;
|
||||
void* dnd;
|
||||
void* aux;
|
||||
bool mapped;
|
||||
@ -193,6 +214,7 @@ extern struct Map windowmap;
|
||||
extern struct Map atommap;
|
||||
extern const Point ZP;
|
||||
extern const Rectangle ZR;
|
||||
extern const WinHints ZWinHints;
|
||||
extern Window* pointerwin;
|
||||
extern Xft* xft;
|
||||
|
||||
@ -204,6 +226,7 @@ XRectangle XRect(Rectangle r);
|
||||
(uchar*)(data), n)
|
||||
|
||||
/* x11.c */
|
||||
XRectangle XRect(Rectangle);
|
||||
Image* allocimage(int w, int h, int depth);
|
||||
void border(Image *dst, Rectangle, int w, Color);
|
||||
void changeprop_char(Window*, char*, char*, char[], int);
|
||||
@ -213,9 +236,10 @@ void changeprop_string(Window*, char*, char*);
|
||||
void changeprop_textlist(Window*, char*, char*, char*[]);
|
||||
void changeprop_ulong(Window*, char*, char*, ulong[], int);
|
||||
void changeproperty(Window*, char*, char*, int width, uchar*, int);
|
||||
void clientmessage(Window*, char*, long, int, ClientMessageData);
|
||||
void copyimage(Image*, Rectangle, Image*, Point);
|
||||
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);
|
||||
void delproperty(Window*, char*);
|
||||
void destroywindow(Window*);
|
||||
void drawline(Image*, Point, Point, int cap, int w, Color);
|
||||
@ -228,11 +252,13 @@ void freefont(Font*);
|
||||
void freeimage(Image *);
|
||||
void freestringlist(char**);
|
||||
XWindow getfocus(void);
|
||||
void gethints(Window*);
|
||||
ulong getprop_long(Window*, char*, char*, ulong, long**, ulong);
|
||||
char* getprop_string(Window*, char*);
|
||||
int getprop_textlist(Window *w, char *name, char **ret[]);
|
||||
ulong getprop_ulong(Window*, char*, char*, ulong, ulong**, ulong);
|
||||
ulong getproperty(Window*, char *prop, char *type, Atom *actual, ulong offset, uchar **ret, ulong length);
|
||||
Rectangle getwinrect(Window*);
|
||||
int grabkeyboard(Window*);
|
||||
int grabpointer(Window*, Window *confine, Cursor, int mask);
|
||||
bool havexft(void);
|
||||
@ -247,24 +273,29 @@ void movewin(Window*, Point);
|
||||
bool namedcolor(char *name, Color*);
|
||||
bool parsekey(char*, int*, char**);
|
||||
int pointerscreen(void);
|
||||
bool pophandler(Window*, Handlers*);
|
||||
void pushhandler(Window*, Handlers*, void*);
|
||||
Point querypointer(Window*);
|
||||
void raisewin(Window*);
|
||||
void reparentwindow(Window*, Window*, Point);
|
||||
void reshapewin(Window*, Rectangle);
|
||||
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 setfocus(Window*, int mode);
|
||||
void sethints(Window*);
|
||||
Handlers* sethandler(Window*, Handlers*);
|
||||
void sethints(Window*, WinHints*);
|
||||
void setshapemask(Window *dst, Image *src, Point);
|
||||
void setwinattr(Window*, WinAttr*, int valmask);
|
||||
Rectangle sizehint(WinHints*, Rectangle);
|
||||
char** strlistdup(char**);
|
||||
void sync(void);
|
||||
Rectangle textextents_l(Font*, char*, uint, int*);
|
||||
uint textwidth(Font*, char*);
|
||||
uint textwidth_l(Font*, char*, uint len);
|
||||
Rectangle textextents_l(Font*, char*, uint, int*);
|
||||
int traperrors(bool);
|
||||
Point translate(Window*, Window*, Point);
|
||||
int traperrors(bool);
|
||||
void ungrabkeyboard(void);
|
||||
void ungrabpointer(void);
|
||||
int unmapwin(Window*);
|
||||
@ -273,9 +304,4 @@ Window* window(XWindow);
|
||||
char* windowname(Window*);
|
||||
long winprotocols(Window*);
|
||||
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/focusin \
|
||||
event/focusout \
|
||||
event/ixp \
|
||||
event/keypress \
|
||||
event/leavenotify \
|
||||
event/mapnotify \
|
||||
@ -26,6 +27,10 @@ OBJ=\
|
||||
event/mappingnotify \
|
||||
event/motionnotify \
|
||||
event/propertynotify \
|
||||
event/reparentnotify \
|
||||
event/selection \
|
||||
event/selectionclear \
|
||||
event/selectionrequest \
|
||||
event/unmapnotify \
|
||||
event/xtime \
|
||||
geom/get_sticky \
|
||||
@ -38,7 +43,6 @@ OBJ=\
|
||||
map \
|
||||
printevent \
|
||||
util/_die \
|
||||
util/backtrace \
|
||||
util/closeexec \
|
||||
util/comm \
|
||||
util/doublefork \
|
||||
@ -114,6 +118,7 @@ OBJ=\
|
||||
x11/images/freeimage \
|
||||
x11/images/xftdrawable \
|
||||
x11/insanity/gravitate \
|
||||
x11/insanity/gethints \
|
||||
x11/insanity/sethints \
|
||||
x11/insanity/sizehint \
|
||||
x11/keyboard/grabkeyboard \
|
||||
|
@ -1,6 +1,7 @@
|
||||
#define IXP_NO_P9_
|
||||
#define IXP_P9_STRUCTS
|
||||
#define CLIENTEXTERN
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ixp.h>
|
||||
#include <stuff/clientutil.h>
|
||||
@ -40,11 +41,13 @@ readctl(char *key) {
|
||||
|
||||
void
|
||||
client_init(char* address) {
|
||||
if(address == nil)
|
||||
address = getenv("WMII_ADDRESS");
|
||||
if(address && *address)
|
||||
client = ixp_mount(address);
|
||||
else
|
||||
client = ixp_nsmount("wmii");
|
||||
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;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, bdown, ev);
|
||||
event_handle(w, bdown, ev);
|
||||
else
|
||||
XAllowEvents(display, ReplayPointer, ev->time);
|
||||
}
|
||||
|
@ -8,5 +8,5 @@ event_buttonrelease(XButtonPressedEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, bup, ev);
|
||||
event_handle(w, bup, ev);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
void
|
||||
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;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, config, ev);
|
||||
event_handle(w, config, ev);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ event_configurerequest(XConfigureRequestEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, configreq, ev);
|
||||
event_handle(w, configreq, ev);
|
||||
else{
|
||||
wc.x = ev->x;
|
||||
wc.y = ev->y;
|
||||
|
@ -8,5 +8,5 @@ event_destroynotify(XDestroyWindowEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, destroy, ev);
|
||||
event_handle(w, destroy, ev);
|
||||
}
|
||||
|
@ -7,10 +7,11 @@ void
|
||||
event_enternotify(XCrossingEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
event_xtime = ev->time;
|
||||
if(!ev->send_event)
|
||||
event_xtime = ev->time;
|
||||
if(ev->mode != NotifyNormal)
|
||||
return;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, enter, ev);
|
||||
event_handle(w, enter, ev);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
#include "event.h"
|
||||
|
||||
typedef void (*Handler)(Window*, void*, XEvent*);
|
||||
void (*event_debug)(XEvent*);
|
||||
long event_xtime;
|
||||
bool event_looprunning;
|
||||
@ -25,9 +26,29 @@ EventHandler event_handler[LASTEvent] = {
|
||||
[MappingNotify] = (EventHandler)event_mappingnotify,
|
||||
[MotionNotify] = (EventHandler)event_motionnotify,
|
||||
[PropertyNotify] = (EventHandler)event_propertynotify,
|
||||
[ReparentNotify] = (EventHandler)event_reparentnotify,
|
||||
[SelectionClear] = (EventHandler)event_selectionclear,
|
||||
[SelectionNotify] = (EventHandler)event_selection,
|
||||
[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
|
||||
event_dispatch(XEvent *e) {
|
||||
if(event_debug)
|
||||
|
@ -8,5 +8,5 @@ event_expose(XExposeEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
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;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, focusin, ev);
|
||||
event_handle(w, focusin, ev);
|
||||
}
|
||||
|
@ -15,5 +15,5 @@ event_focusout(XFocusChangeEvent *ev) {
|
||||
return;
|
||||
|
||||
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) {
|
||||
Window *w;
|
||||
|
||||
event_xtime = ev->time;
|
||||
if(!ev->send_event)
|
||||
event_xtime = ev->time;
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, kdown, ev);
|
||||
event_handle(w, kdown, ev);
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ void
|
||||
event_leavenotify(XCrossingEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
event_xtime = ev->time;
|
||||
if(!ev->send_event)
|
||||
event_xtime = ev->time;
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, leave, ev);
|
||||
event_handle(w, leave, ev);
|
||||
}
|
||||
|
@ -8,5 +8,5 @@ event_mapnotify(XMapEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, map, ev);
|
||||
event_handle(w, map, ev);
|
||||
}
|
||||
|
@ -8,5 +8,5 @@ event_maprequest(XMapRequestEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
if((w = findwin(ev->parent)))
|
||||
handle(w, mapreq, ev);
|
||||
event_handle(w, mapreq, ev);
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ void
|
||||
event_motionnotify(XMotionEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
event_xtime = ev->time;
|
||||
if(!ev->send_event)
|
||||
event_xtime = ev->time;
|
||||
if((w = findwin(ev->window)))
|
||||
handle(w, motion, ev);
|
||||
event_handle(w, motion, ev);
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ void
|
||||
event_propertynotify(XPropertyEvent *ev) {
|
||||
Window *w;
|
||||
|
||||
event_xtime = ev->time;
|
||||
if(!ev->send_event)
|
||||
event_xtime = ev->time;
|
||||
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)) {
|
||||
w->mapped = false;
|
||||
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);
|
||||
|
||||
if(_trap_errors)
|
||||
if(_trap_errors) {
|
||||
nerrors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
e = ignored_xerrors;
|
||||
if(e)
|
||||
|
@ -44,6 +44,8 @@ Wfmt(Fmt *f) {
|
||||
Window *w;
|
||||
|
||||
w = va_arg(f->args, Window*);
|
||||
if(w == nil)
|
||||
return fmtstrcpy(f, "<nil>");
|
||||
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>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include <string.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
|
||||
sethints(Window *w) {
|
||||
XSizeHints xs;
|
||||
XWMHints *wmh;
|
||||
WinHints *h;
|
||||
Point p;
|
||||
long size;
|
||||
sethints(Window *w, WinHints *h) {
|
||||
XSizeHints xhints = { 0, };
|
||||
int i;
|
||||
|
||||
/* TODO: Group hint */
|
||||
|
||||
if(w->hints == nil)
|
||||
w->hints = emalloc(sizeof *h);
|
||||
|
||||
h = w->hints;
|
||||
memset(h, 0, sizeof *h);
|
||||
*w->hints = *h;
|
||||
|
||||
h->max = Pt(INT_MAX, INT_MAX);
|
||||
h->inc = Pt(1,1);
|
||||
|
||||
wmh = XGetWMHints(display, w->xid);
|
||||
if(wmh) {
|
||||
if(wmh->flags & WindowGroupHint)
|
||||
h->group = wmh->window_group;
|
||||
free(wmh);
|
||||
if(!eqpt(h->min, ZP)) {
|
||||
xhints.flags |= PMinSize;
|
||||
xhints.min_width = h->min.x;
|
||||
xhints.min_height = h->min.y;
|
||||
}
|
||||
if(!eqpt(h->max, Pt(INT_MAX, INT_MAX))) {
|
||||
xhints.flags |= PMaxSize;
|
||||
xhints.max_width = h->max.x;
|
||||
xhints.max_height = h->max.y;
|
||||
}
|
||||
|
||||
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;
|
||||
if(!eqpt(h->base, ZP)) {
|
||||
xhints.flags |= PBaseSize;
|
||||
xhints.base_width = h->baspect.x;
|
||||
xhints.base_height = h->baspect.y;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
if(!eqrect(h->aspect, ZR)) {
|
||||
xhints.flags |= PAspect;
|
||||
|
||||
h->base = h->min;
|
||||
if(xs.flags & PBaseSize) {
|
||||
p.x = xs.base_width;
|
||||
p.y = xs.base_height;
|
||||
h->base = p;
|
||||
h->baspect = p;
|
||||
xhints.base_width = h->baspect.x;
|
||||
xhints.base_height = h->baspect.y;
|
||||
|
||||
xhints.min_aspect.x = h->aspect.min.x;
|
||||
xhints.min_aspect.y = h->aspect.min.y;
|
||||
|
||||
xhints.max_aspect.x = h->aspect.max.x;
|
||||
xhints.max_aspect.y = h->aspect.max.y;
|
||||
}
|
||||
|
||||
if(xs.flags & PResizeInc) {
|
||||
h->inc.x = max(xs.width_inc, 1);
|
||||
h->inc.y = max(xs.height_inc, 1);
|
||||
if(!eqpt(h->inc, Pt(1, 1))) {
|
||||
xhints.flags |= PResizeInc;
|
||||
xhints.width_inc = h->inc.x;
|
||||
xhints.height_inc = h->inc.y;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/* USPosition is probably an evil assumption, but it holds in our use cases. */
|
||||
if(h->position)
|
||||
xhints.flags |= USPosition | PPosition;
|
||||
|
||||
h->position = (xs.flags & (USPosition|PPosition)) != 0;
|
||||
xhints.flags |= PWinGravity;
|
||||
if(h->gravstatic)
|
||||
xhints.win_gravity = StaticGravity;
|
||||
else
|
||||
for(i=0; i < nelem(gravity_map); i++)
|
||||
if(h->grav.x == gravity_map[i].point.x &&
|
||||
h->grav.y == gravity_map[i].point.y) {
|
||||
xhints.win_gravity = gravity_map[i].gravity;
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
XSetWMNormalHints(display, w->xid, &xhints);
|
||||
}
|
||||
|
@ -19,6 +19,6 @@ changeprop_textlist(Window *w, char *prop, char *type, char *data[]) {
|
||||
memcpy(t, *p, n);
|
||||
t += n;
|
||||
}
|
||||
changeprop_char(w, prop, type, s, len);
|
||||
changeprop_char(w, prop, type, s, len - 1);
|
||||
free(s);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "x11.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2,19 +2,23 @@
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "x11.h"
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
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;
|
||||
|
||||
e.type = ClientMessage;
|
||||
e.window = w->xid;
|
||||
e.message_type = xatom(name);
|
||||
e.format = 32;
|
||||
e.data.l[0] = l0;
|
||||
e.data.l[1] = l1;
|
||||
e.data.l[2] = l2;
|
||||
e.data.l[3] = l3;
|
||||
e.data.l[4] = l4;
|
||||
sendevent(w, false, NoEventMask, (XEvent*)&e);
|
||||
e.format = format;
|
||||
bcopy(&data, &e.data, sizeof(data));
|
||||
sendevent(w, false, mask, (XEvent*)&e);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,10 @@
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "../x11.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static char hostname[HOST_NAME_MAX + 1];
|
||||
|
||||
Window*
|
||||
createwindow_visual(Window *parent, Rectangle r,
|
||||
@ -21,6 +25,8 @@ createwindow_visual(Window *parent, Rectangle r,
|
||||
w->parent = parent;
|
||||
if(valmask & CWColormap)
|
||||
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),
|
||||
0 /* border */, depth, class, vis, valmask, wa);
|
||||
@ -31,6 +37,12 @@ createwindow_visual(Window *parent, Rectangle r,
|
||||
if(class != InputOnly)
|
||||
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->depth = depth;
|
||||
return w;
|
||||
|
@ -7,6 +7,8 @@ void
|
||||
destroywindow(Window *w) {
|
||||
assert(w->type == WWindow);
|
||||
sethandler(w, nil);
|
||||
while(w->handler_link)
|
||||
pophandler(w, w->handler_link->handler);
|
||||
if(w->xft)
|
||||
xft->drawdestroy(w->xft);
|
||||
if(w->gc)
|
||||
|
@ -5,5 +5,6 @@
|
||||
|
||||
void
|
||||
selectinput(Window *w, long mask) {
|
||||
w->eventmask = mask;
|
||||
XSelectInput(display, w->xid, mask);
|
||||
}
|
||||
|
@ -3,21 +3,72 @@
|
||||
*/
|
||||
#include "../x11.h"
|
||||
|
||||
Handlers*
|
||||
sethandler(Window *w, Handlers *new) {
|
||||
Handlers *old;
|
||||
static void
|
||||
updatemap(Window *w) {
|
||||
void **e;
|
||||
|
||||
assert(w->type == WWindow);
|
||||
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);
|
||||
else {
|
||||
e = map_get(&windowmap, (ulong)w->xid, true);
|
||||
*e = w;
|
||||
}
|
||||
}
|
||||
|
||||
Handlers*
|
||||
sethandler(Window *w, Handlers *new) {
|
||||
Handlers *old;
|
||||
|
||||
old = w->handler;
|
||||
w->handler = new;
|
||||
|
||||
updatemap(w);
|
||||
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
|
||||
#include <stuff/x.h>
|
||||
#include <stuff/util.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
|
||||
|
@ -7,7 +7,8 @@ TARG = wmii.1 \
|
||||
wmii9menu.1\
|
||||
wihack.1 \
|
||||
wimenu.1 \
|
||||
wistrut.1
|
||||
wistrut.1 \
|
||||
witray.1
|
||||
|
||||
$(TARG): Makefile $(ROOT)/mk/wmii.mk header.t2t
|
||||
|
||||
|
@ -193,7 +193,7 @@ provided.
|
||||
|
||||
.SH SEE ALSO
|
||||
.P
|
||||
wmii(1), wmiir(1), wmii9menu(1), dmenu(1)
|
||||
wmii(1), wmiir(1), wistrug(1), wmii9menu(1), dmenu(1)
|
||||
|
||||
.P
|
||||
\fI[1]\fR http://www.suckless.org/wiki/wmii/tips/9p_tips
|
||||
|
@ -168,7 +168,7 @@ most shells.
|
||||
provided.
|
||||
:
|
||||
= 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,4 +1,4 @@
|
||||
.TH "WIMENU" 1 "May, 2010" "wmii-@VERSION@"
|
||||
.TH "WISTRUT" 1 "May, 2010" "wmii-@VERSION@"
|
||||
|
||||
.SH NAME
|
||||
.P
|
||||
|
@ -1,4 +1,4 @@
|
||||
WIMENU
|
||||
WISTRUT
|
||||
wmii-@VERSION@
|
||||
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 $@
|
||||
eval '$CC -o $outfile '"$CFLAGS"' $@ >$xtmp 2>&1'
|
||||
status=$?
|
||||
[ $? -eq 0 ] || echo $CC -o $outfile $CFLAGS $@ >&2
|
||||
[ $status -eq 0 ] || echo $CC -o $outfile $CFLAGS $@ >&2
|
||||
|
||||
base=$(echo $BASE | sed 's/,/\\,/g')
|
||||
re='\([^[:space:]/][^[:space:]]*\..:[0-9]\)'
|
||||
|
Loading…
Reference in New Issue
Block a user