wmii

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

commit ab2d1760f8777601daf1d5a7d1e4ef193702ec8c
parent 3550e7afef4e2fd2d8a38453ccfd2b1d5f49236d
Author: Kris Maglione <kris@suckless.org>
Date:   Fri, 21 May 2010 22:52:47 -0400

Factor out common code into library.

Diffstat:
.hgignore | 4++--
Makefile | 1+
cmd/Makefile | 7+------
cmd/click/Makefile | 8++------
cmd/click/dat.h | 14++------------
cmd/click/fns.h | 3---
cmd/click/main.c | 4++--
cmd/clientutil.c | 50--------------------------------------------------
cmd/menu/Makefile | 13++-----------
cmd/menu/dat.h | 14++------------
cmd/menu/event.c | 334-------------------------------------------------------------------------------
cmd/menu/fns.h | 1-
cmd/menu/main.c | 20++++++++------------
cmd/strut/Makefile | 9+--------
cmd/strut/_util.c | 77-----------------------------------------------------------------------------
cmd/strut/dat.h | 21+++------------------
cmd/strut/event.c | 309-------------------------------------------------------------------------------
cmd/strut/fns.h | 3---
cmd/strut/main.c | 7+++----
cmd/strut/printevent_kludge.c | 12------------
cmd/strut/win.c | 2+-
cmd/util.c | 272-------------------------------------------------------------------------------
cmd/wmii/Makefile | 9+--------
cmd/wmii/_util.c | 378-------------------------------------------------------------------------------
cmd/wmii/client.c | 8++++----
cmd/wmii/dat.h | 97+++++++++++--------------------------------------------------------------------
cmd/wmii/event.c | 264++++++++-----------------------------------------------------------------------
cmd/wmii/fns.h | 50++------------------------------------------------
cmd/wmii/geom.c | 94-------------------------------------------------------------------------------
cmd/wmii/key.c | 2+-
cmd/wmii/main.c | 6++++--
cmd/wmii/map.c | 126-------------------------------------------------------------------------------
cmd/wmii/message.c | 91-------------------------------------------------------------------------------
cmd/wmii/mouse.c | 19+++++++++++++++++--
cmd/wmii/printevent.c | 994-------------------------------------------------------------------------------
cmd/wmii/printevent.h | 248-------------------------------------------------------------------------------
cmd/wmii/x11.c | 1317-------------------------------------------------------------------------------
cmd/wmii/xext.c | 160-------------------------------------------------------------------------------
cmd/wmii9menu.c | 11++++-------
cmd/wmiir.c | 2+-
doc/wmii.tex | 1+
include/clientutil.h | 9---------
include/debug.h | 13+++++++++++++
include/stuff/clientutil.h | 13+++++++++++++
include/stuff/geom.h | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/stuff/util.h | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/stuff/x.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
include/stuff/x11.h | 249+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/util.h | 91-------------------------------------------------------------------------------
include/x11.h | 292-------------------------------------------------------------------------------
libstuff/Makefile | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/buffer.c | 8++++++++
libstuff/clientutil.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/event/buttonpress.c | 14++++++++++++++
libstuff/event/buttonrelease.c | 12++++++++++++
libstuff/event/clientmessage.c | 10++++++++++
libstuff/event/configurenotify.c | 12++++++++++++
libstuff/event/configurerequest.c | 24++++++++++++++++++++++++
libstuff/event/destroynotify.c | 12++++++++++++
libstuff/event/enternotify.c | 16++++++++++++++++
libstuff/event/event.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/event/event.h | 9+++++++++
libstuff/event/expose.c | 12++++++++++++
libstuff/event/focusin.c | 27+++++++++++++++++++++++++++
libstuff/event/focusout.c | 19+++++++++++++++++++
libstuff/event/keypress.c | 13+++++++++++++
libstuff/event/leavenotify.c | 13+++++++++++++
libstuff/event/mapnotify.c | 12++++++++++++
libstuff/event/mappingnotify.c | 11+++++++++++
libstuff/event/maprequest.c | 12++++++++++++
libstuff/event/motionnotify.c | 13+++++++++++++
libstuff/event/propertynotify.c | 13+++++++++++++
libstuff/event/unmapnotify.c | 15+++++++++++++++
libstuff/event/xtime.c | 33+++++++++++++++++++++++++++++++++
libstuff/geom/get_sticky.c | 24++++++++++++++++++++++++
libstuff/geom/quadrant.c | 23+++++++++++++++++++++++
libstuff/geom/rect_contains_p.c | 12++++++++++++
libstuff/geom/rect_haspoint_p.c | 10++++++++++
libstuff/geom/rect_intersect_p.c | 12++++++++++++
libstuff/geom/rect_intersection.c | 17+++++++++++++++++
libstuff/init_screens.c | 9+++++++++
libstuff/map.c | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/printevent.c | 994+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/printevent.h | 248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/util/_die.c | 27+++++++++++++++++++++++++++
libstuff/util/backtrace.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/util/closeexec.c | 12++++++++++++
libstuff/util/comm.c | 42++++++++++++++++++++++++++++++++++++++++++
libstuff/util/doublefork.c | 31+++++++++++++++++++++++++++++++
libstuff/util/emalloc.c | 12++++++++++++
libstuff/util/emallocz.c | 11+++++++++++
libstuff/util/erealloc.c | 12++++++++++++
libstuff/util/estrdup.c | 12++++++++++++
libstuff/util/estrndup.c | 15+++++++++++++++
libstuff/util/fatal.c | 40++++++++++++++++++++++++++++++++++++++++
libstuff/util/freelater.c | 16++++++++++++++++
libstuff/util/getbase.c | 43+++++++++++++++++++++++++++++++++++++++++++
libstuff/util/getint.c | 14++++++++++++++
libstuff/util/getlong.c | 24++++++++++++++++++++++++
libstuff/util/getulong.c | 24++++++++++++++++++++++++
libstuff/util/grep.c | 22++++++++++++++++++++++
libstuff/util/join.c | 23+++++++++++++++++++++++
libstuff/util/max.c | 10++++++++++
libstuff/util/mfatal.c | 34++++++++++++++++++++++++++++++++++
libstuff/util/min.c | 10++++++++++
libstuff/util/pathsearch.c | 33+++++++++++++++++++++++++++++++++
libstuff/util/refree.c | 14++++++++++++++
libstuff/util/reinit.c | 16++++++++++++++++
libstuff/util/spawn3.c | 44++++++++++++++++++++++++++++++++++++++++++++
libstuff/util/spawn3l.c | 29+++++++++++++++++++++++++++++
libstuff/util/stokenize.c | 22++++++++++++++++++++++
libstuff/util/strcasestr.c | 25+++++++++++++++++++++++++
libstuff/util/strend.c | 13+++++++++++++
libstuff/util/strlcat.c | 26++++++++++++++++++++++++++
libstuff/util/strlcatprint.c | 19+++++++++++++++++++
libstuff/util/sxprint.c | 14++++++++++++++
libstuff/util/tokenize.c | 21+++++++++++++++++++++
libstuff/util/uniq.c | 18++++++++++++++++++
libstuff/util/unquote.c | 38++++++++++++++++++++++++++++++++++++++
libstuff/util/utflcpy.c | 11+++++++++++
libstuff/util/util.h | 5+++++
libstuff/util/vector.c | 34++++++++++++++++++++++++++++++++++
libstuff/util/vsxprint.c | 13+++++++++++++
libstuff/x11/colors/loadcolor.c | 17+++++++++++++++++
libstuff/x11/colors/namedcolor.c | 22++++++++++++++++++++++
libstuff/x11/colors/xftcolor.c | 19+++++++++++++++++++
libstuff/x11/convpts.c | 17+++++++++++++++++
libstuff/x11/drawing/border.c | 19+++++++++++++++++++
libstuff/x11/drawing/drawline.c | 11+++++++++++
libstuff/x11/drawing/drawpoly.c | 15+++++++++++++++
libstuff/x11/drawing/drawstring.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/x11/drawing/fill.c | 11+++++++++++
libstuff/x11/drawing/fillpoly.c | 14++++++++++++++
libstuff/x11/errors.c | 40++++++++++++++++++++++++++++++++++++++++
libstuff/x11/focus/getfocus.c | 13+++++++++++++
libstuff/x11/focus/setfocus.c | 9+++++++++
libstuff/x11/freestringlist.c | 9+++++++++
libstuff/x11/geometry/XRect.c | 15+++++++++++++++
libstuff/x11/geometry/addpt.c | 11+++++++++++
libstuff/x11/geometry/divpt.c | 11+++++++++++
libstuff/x11/geometry/eqpt.c | 9+++++++++
libstuff/x11/geometry/eqrect.c | 10++++++++++
libstuff/x11/geometry/insetrect.c | 13+++++++++++++
libstuff/x11/geometry/mulpt.c | 11+++++++++++
libstuff/x11/geometry/rectaddpt.c | 13+++++++++++++
libstuff/x11/geometry/rectsetorigin.c | 15+++++++++++++++
libstuff/x11/geometry/rectsubpt.c | 13+++++++++++++
libstuff/x11/geometry/subpt.c | 11+++++++++++
libstuff/x11/ignored_xerrors.c | 9+++++++++
libstuff/x11/images/allocimage.c | 21+++++++++++++++++++++
libstuff/x11/images/copyimage.c | 13+++++++++++++
libstuff/x11/images/freeimage.c | 18++++++++++++++++++
libstuff/x11/images/xftdrawable.c | 11+++++++++++
libstuff/x11/initdisplay.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/x11/insanity/gravitate.c | 19+++++++++++++++++++
libstuff/x11/insanity/sethints.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/x11/insanity/sizehint.c | 42++++++++++++++++++++++++++++++++++++++++++
libstuff/x11/keyboard/grabkeyboard.c | 12++++++++++++
libstuff/x11/keyboard/ungrabkeyboard.c | 9+++++++++
libstuff/x11/keys/keycode.c | 9+++++++++
libstuff/x11/keys/parsekey.c | 46++++++++++++++++++++++++++++++++++++++++++++++
libstuff/x11/mouse/grabpointer.c | 16++++++++++++++++
libstuff/x11/mouse/pointerscreen.c | 15+++++++++++++++
libstuff/x11/mouse/querypointer.c | 15+++++++++++++++
libstuff/x11/mouse/translate.c | 14++++++++++++++
libstuff/x11/mouse/ungrabpointer.c | 9+++++++++
libstuff/x11/mouse/warppointer.c | 23+++++++++++++++++++++++
libstuff/x11/properties/changeprop_char.c | 9+++++++++
libstuff/x11/properties/changeprop_long.c | 9+++++++++
libstuff/x11/properties/changeprop_short.c | 9+++++++++
libstuff/x11/properties/changeprop_string.c | 9+++++++++
libstuff/x11/properties/changeprop_textlist.c | 23+++++++++++++++++++++++
libstuff/x11/properties/changeprop_ulong.c | 9+++++++++
libstuff/x11/properties/changeproperty.c | 11+++++++++++
libstuff/x11/properties/delproperty.c | 9+++++++++
libstuff/x11/properties/getprop.c | 28++++++++++++++++++++++++++++
libstuff/x11/properties/getprop_long.c | 19+++++++++++++++++++
libstuff/x11/properties/getprop_string.c | 19+++++++++++++++++++
libstuff/x11/properties/getprop_textlist.c | 22++++++++++++++++++++++
libstuff/x11/properties/getprop_ulong.c | 10++++++++++
libstuff/x11/properties/getproperty.c | 12++++++++++++
libstuff/x11/properties/strlistdup.c | 28++++++++++++++++++++++++++++
libstuff/x11/sendevent.c | 9+++++++++
libstuff/x11/sendmessage.c | 20++++++++++++++++++++
libstuff/x11/setgccol.c | 9+++++++++
libstuff/x11/shape/setshapemask.c | 11+++++++++++
libstuff/x11/sync.c | 9+++++++++
libstuff/x11/text/freefont.c | 23+++++++++++++++++++++++
libstuff/x11/text/labelh.c | 9+++++++++
libstuff/x11/text/loadfont.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libstuff/x11/text/textextents_l.c | 34++++++++++++++++++++++++++++++++++
libstuff/x11/text/textwidth.c | 9+++++++++
libstuff/x11/text/textwidth_l.c | 12++++++++++++
libstuff/x11/windows/configwin.c | 22++++++++++++++++++++++
libstuff/x11/windows/createwindow.c | 9+++++++++
libstuff/x11/windows/createwindow_visual.c | 33+++++++++++++++++++++++++++++++++
libstuff/x11/windows/destroywindow.c | 16++++++++++++++++
libstuff/x11/windows/findwin.c | 14++++++++++++++
libstuff/x11/windows/getwinrect.c | 15+++++++++++++++
libstuff/x11/windows/lowerwin.c | 10++++++++++
libstuff/x11/windows/mapwin.c | 15+++++++++++++++
libstuff/x11/windows/movewin.c | 13+++++++++++++
libstuff/x11/windows/raisewin.c | 10++++++++++
libstuff/x11/windows/reparentwindow.c | 13+++++++++++++
libstuff/x11/windows/reshapewin.c | 12++++++++++++
libstuff/x11/windows/selectinput.c | 9+++++++++
libstuff/x11/windows/setborder.c | 14++++++++++++++
libstuff/x11/windows/sethandler.c | 23+++++++++++++++++++++++
libstuff/x11/windows/setwinattr.c | 10++++++++++
libstuff/x11/windows/unmapwin.c | 16++++++++++++++++
libstuff/x11/windows/window.c | 14++++++++++++++
libstuff/x11/x11.c | 12++++++++++++
libstuff/x11/x11.h | 31+++++++++++++++++++++++++++++++
libstuff/x11/xatom.c | 14++++++++++++++
libstuff/xext.c | 161+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libwmii_hack/Makefile | 10++++++----
libwmii_hack/hack.h | 6+++---
libwmii_hack/util.c | 58----------------------------------------------------------
libwmii_hack/x11.c | 1+
mk/gcc.mk | 2+-
mk/hdr.mk | 9+++++----
mk/wmii.mk | 2+-
test/grav.c | 4++--
223 files changed, 5522 insertions(+), 5425 deletions(-)

diff --git a/.hgignore b/.hgignore @@ -1,7 +1,7 @@ syntax: regexp (^|/)\.((.*\.)?sw.|depend|hgignore)$ -(^|/)(tags|mkfile)$ -\.([oa]|out|o_pic|so|pyc|pyo)$ +(^|/)(tags|mkfile|diff)$ +\.([oa]|out|o_pic|so|pyc|pyo|diff)$ \.(diff|orig|rej|bak)$ \.(aux|idx|ilg|ind|log|toc)$ ^cmd/(stfo|osd|wiwarp|setfocus)(/|$) diff --git a/Makefile b/Makefile @@ -11,6 +11,7 @@ PDIRS = \ alternative_wmiircs DIRS = \ + libstuff \ libbio \ libfmt \ libregexp \ diff --git a/cmd/Makefile b/cmd/Makefile @@ -12,8 +12,6 @@ TARG = wihack \ wmii9menu \ wmiir -OFILES = util.o - LIBS += $(LIBS9) CFLAGS += $(INCX11) @@ -24,10 +22,7 @@ OWMIIR=wmiir.o $(OFILES) $(LIBIXP) wmiir.out: $(OWMIIR) $(LINK) $@ $(STATIC) $(OWMIIR) -wmii/x11.o wmii/xext.o wmii/geom.o wmii/map.o: dall - true - -O9MENU=wmii9menu.o clientutil.o wmii/x11.o wmii/xext.o wmii/geom.o wmii/map.o $(OFILES) $(LIBIXP) +O9MENU=wmii9menu.o $(ROOT)/lib/libstuff.a $(LIBIXP) wmii9menu.out: $(O9MENU) $(LINK) $@ $(O9MENU) $$(pkg-config --libs $(X11PACKAGES) xrandr xinerama) -lXext diff --git a/cmd/click/Makefile b/cmd/click/Makefile @@ -11,12 +11,8 @@ PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama LIB = $(LIBIXP) LIBS += -lm -lXtst $(LIBS9) -CFLAGS += -DVERSION=\"$(VERSION)\" -DIXP_NEEDAPI=86 -OBJ = main \ - _util \ - ../wmii/map \ - ../wmii/x11 \ - ../util +CFLAGS += -DIXP_NEEDAPI=86 +OBJ = main include ${ROOT}/mk/one.mk diff --git a/cmd/click/dat.h b/cmd/click/dat.h @@ -3,9 +3,9 @@ #include <stdbool.h> #include <stdlib.h> #include <unistd.h> -#include <util.h> +#include <stuff/x.h> +#include <stuff/util.h> #include <ixp.h> -#include <x11.h> #define BLOCK(x) do { x; }while(0) @@ -15,13 +15,3 @@ EXTERN Window win; -EXTERN char buffer[8092]; -EXTERN char* _buffer; - -static char* const _buf_end = buffer + sizeof buffer; - -#define bufclear() \ - BLOCK( _buffer = buffer; _buffer[0] = '\0' ) -#define bufprint(...) \ - _buffer = seprint(_buffer, _buf_end, __VA_ARGS__) - diff --git a/cmd/click/fns.h b/cmd/click/fns.h @@ -1,4 +1 @@ -bool getlong(const char*, long*); -bool getulong(const char*, ulong*); - diff --git a/cmd/click/main.c b/cmd/click/main.c @@ -46,10 +46,10 @@ main(int argc, char *argv[]) { initdisplay(); s = ARGF(); - if(s && !getulong(s, &win.w)) + if(s && !getulong(s, &win.xid)) usage(); if (!s) - win.w = getfocus(); + win.xid = getfocus(); if(argc) usage(); diff --git a/cmd/clientutil.c b/cmd/clientutil.c @@ -1,50 +0,0 @@ -#define IXP_NO_P9_ -#define IXP_P9_STRUCTS -#define CLIENTEXTERN -#include <string.h> -#include <ixp.h> -#include <clientutil.h> -#include <util.h> - -static IxpCFid* ctlfid; -static char ctl[1024]; -static char* ectl; - -char* -readctl(char *key) { - char *s, *p; - int nkey, n; - - if(ctlfid == nil) { - ctlfid = ixp_open(client, "ctl", OREAD); - n = ixp_read(ctlfid, ctl, 1023); - ectl = ctl + n; - ixp_close(ctlfid); - } - - nkey = strlen(key); - p = ctl - 1; - do { - p++; - if(!strncmp(p, key, nkey)) { - p += nkey; - s = strchr(p, '\n'); - n = (s ? s : ectl) - p; - s = freelater(emalloc(n + 1)); - s[n] = '\0'; - return strncpy(s, p, n); - } - } while((p = strchr(p, '\n'))); - return ""; -} - -void -client_init(char* address) { - if(address && *address) - client = ixp_mount(address); - else - client = ixp_nsmount("wmii"); - if(client == nil) - fatal("can't mount: %r\n"); -} - diff --git a/cmd/menu/Makefile b/cmd/menu/Makefile @@ -14,23 +14,14 @@ HFILES= dat.h fns.h PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama -LIB = $(LIBIXP) -LIBS += -lm $(LIBS9) +LIBS += -lm $(LIBS9) $(LIBIXP) CFLAGS += -DIXP_NEEDAPI=86 OBJ = main \ caret \ history \ - event \ menu \ keys \ - bindings \ - ../wmii/geom \ - ../wmii/map \ - ../wmii/printevent \ - ../wmii/x11 \ - ../wmii/xext \ - ../clientutil \ - ../util + bindings include $(ROOT)/mk/one.mk diff --git a/cmd/menu/dat.h b/cmd/menu/dat.h @@ -7,9 +7,9 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <util.h> +#include <stuff/x.h> +#include <stuff/util.h> #include <ixp.h> -#include <x11.h> #define BLOCK(x) do { x; }while(0) @@ -104,13 +104,3 @@ EXTERN int (*compare)(const char*, const char*, size_t); EXTERN char* prompt; EXTERN int promptw; -EXTERN char buffer[8092]; -EXTERN char* _buffer; - -static char* const _buf_end = buffer + sizeof buffer; - -#define bufclear() \ - BLOCK( _buffer = buffer; _buffer[0] = '\0' ) -#define bufprint(...) \ - _buffer = seprint(_buffer, _buf_end, __VA_ARGS__) - diff --git a/cmd/menu/event.c b/cmd/menu/event.c @@ -1,334 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <fbsdaemon@gmail.com> - * See LICENSE file for license details. - */ -#include "dat.h" -#include "fns.h" - -typedef void (*EvHandler)(XEvent*); -static EvHandler handler[LASTEvent]; - -void -dispatch_event(XEvent *e) { - if(e->type < nelem(handler)) { - if(handler[e->type]) - handler[e->type](e); - }else - xext_event(e); -} - -#define handle(w, fn, ev) \ - BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev)) - -static int -findtime(Display *d, XEvent *e, XPointer v) { - Window *w; - - w = (Window*)v; - if(e->type == PropertyNotify && e->xproperty.window == w->xid) { - xtime = e->xproperty.time; - return true; - } - return false; -} - -void -xtime_kludge(void) { - /* Round trip. */ - static Window *w; - WinAttr wa; - XEvent e; - long l; - - if(w == nil) { - w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0); - selectinput(w, PropertyChangeMask); - } - changeprop_long(w, "ATOM", "ATOM", &l, 0); - sync(); - XIfEvent(display, &e, findtime, (void*)w); -} - -uint -flushevents(long event_mask, bool dispatch) { - XEvent ev; - uint n = 0; - - while(XCheckMaskEvent(display, event_mask, &ev)) { - if(dispatch) - dispatch_event(&ev); - n++; - } - return n; -} - -static int -findenter(Display *d, XEvent *e, XPointer v) { - long *l; - - USED(d); - l = (long*)v; - if(*l) - return false; - if(e->type == EnterNotify) - return true; - if(e->type == MotionNotify) - (*l)++; - return false; -} - -/* This isn't perfect. If there were motion events in the queue - * before this was called, then it flushes nothing. If we don't - * check for them, we might lose a legitamate enter event. - */ -uint -flushenterevents(void) { - XEvent e; - long l; - int n; - - l = 0; - n = 0; - while(XCheckIfEvent(display, &e, findenter, (void*)&l)) - n++; - return n; -} - -static void -buttonrelease(XButtonPressedEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, bup, ev); -} - -static void -buttonpress(XButtonPressedEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, bdown, ev); - else - XAllowEvents(display, ReplayPointer, ev->time); -} - -static void -configurerequest(XConfigureRequestEvent *ev) { - XWindowChanges wc; - Window *w; - - if((w = findwin(ev->window))) - handle(w, configreq, ev); - else{ - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(display, ev->window, ev->value_mask, &wc); - } -} - -static void -configurenotify(XConfigureEvent *ev) { - Window *w; - - USED(ev); - if((w = findwin(ev->window))) - handle(w, config, ev); -} - -static void -clientmessage(XClientMessageEvent *ev) { - - USED(ev); -} - -static void -destroynotify(XDestroyWindowEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, destroy, ev); -} - -static void -enternotify(XCrossingEvent *ev) { - Window *w; - static int sel_screen; - - xtime = ev->time; - if(ev->mode != NotifyNormal) - return; - - if((w = findwin(ev->window))) - handle(w, enter, ev); - else if(ev->window == scr.root.xid) - sel_screen = true; -} - -static void -leavenotify(XCrossingEvent *ev) { - - xtime = ev->time; -#if 0 - if((ev->window == scr.root.xid) && !ev->same_screen) - sel_screen = true; -#endif -} - -static void -focusin(XFocusChangeEvent *ev) { - Window *w; - - /* Yes, we're focusing in on nothing, here. */ - if(ev->detail == NotifyDetailNone) { - /* FIXME: Do something. */ - return; - } - - if(!((ev->detail == NotifyNonlinear) - ||(ev->detail == NotifyNonlinearVirtual) - ||(ev->detail == NotifyVirtual) - ||(ev->detail == NotifyInferior) - ||(ev->detail == NotifyAncestor))) - return; - if((ev->mode == NotifyWhileGrabbed)) /* && (screen->hasgrab != &c_root)) */ - return; - - if((w = findwin(ev->window))) - handle(w, focusin, ev); -#if 0 - else if(ev->mode == NotifyGrab) { - if(ev->window == scr.root.xid) - screen->hasgrab = &c_root; - /* Some unmanaged window has grabbed focus */ - else if((c = screen->focus)) { - print_focus("focusin", &c_magic, "<magic>"); - screen->focus = &c_magic; - if(c->sel) - frame_draw(c->sel); - } - } -#endif -} - -static void -focusout(XFocusChangeEvent *ev) { - Window *w; - - if(!((ev->detail == NotifyNonlinear) - ||(ev->detail == NotifyNonlinearVirtual) - ||(ev->detail == NotifyVirtual) - ||(ev->detail == NotifyInferior) - ||(ev->detail == NotifyAncestor))) - return; -#if 0 - if(ev->mode == NotifyUngrab) - screen->hasgrab = nil; -#endif - - if((w = findwin(ev->window))) - handle(w, focusout, ev); -} - -static void -expose(XExposeEvent *ev) { - Window *w; - - if(ev->count == 0) { - if((w = findwin(ev->window))) - handle(w, expose, ev); - } -} - -static void -keypress(XKeyEvent *ev) { - Window *w; - - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, kdown, ev); -} - -static void -mappingnotify(XMappingEvent *ev) { - - /* Why do you need me to tell you this? */ - XRefreshKeyboardMapping(ev); -} - -static void -maprequest(XMapRequestEvent *ev) { - - USED(ev); -} - -static void -motionnotify(XMotionEvent *ev) { - Window *w; - - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, motion, ev); -} - -static void -propertynotify(XPropertyEvent *ev) { - Window *w; - - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, property, ev); -} - -static void -mapnotify(XMapEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, map, ev); -} - -static void -unmapnotify(XUnmapEvent *ev) { - Window *w; - - if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) { - w->mapped = false; - if(ev->send_event || w->unmapped-- == 0) - handle(w, unmap, ev); - } -} - -static EvHandler handler[LASTEvent] = { - [ButtonPress] = (EvHandler)buttonpress, - [ButtonRelease] = (EvHandler)buttonrelease, - [ConfigureRequest] = (EvHandler)configurerequest, - [ConfigureNotify] = (EvHandler)configurenotify, - [ClientMessage] = (EvHandler)clientmessage, - [DestroyNotify] = (EvHandler)destroynotify, - [EnterNotify] = (EvHandler)enternotify, - [Expose] = (EvHandler)expose, - [FocusIn] = (EvHandler)focusin, - [FocusOut] = (EvHandler)focusout, - [KeyPress] = (EvHandler)keypress, - [LeaveNotify] = (EvHandler)leavenotify, - [MapNotify] = (EvHandler)mapnotify, - [MapRequest] = (EvHandler)maprequest, - [MappingNotify] = (EvHandler)mappingnotify, - [MotionNotify] = (EvHandler)motionnotify, - [PropertyNotify] = (EvHandler)propertynotify, - [UnmapNotify] = (EvHandler)unmapnotify, -}; - -void -check_x_event(IxpConn *c) { - XEvent ev; - - USED(c); - while(XCheckMaskEvent(display, ~0, &ev)) - dispatch_event(&ev); -} - diff --git a/cmd/menu/fns.h b/cmd/menu/fns.h @@ -19,7 +19,6 @@ char* history_search(int, char*, int); /* main.c */ void debug(int, const char*, ...); Item* filter_list(Item*, char*); -void init_screens(int); void update_filter(bool); void update_input(void); diff --git a/cmd/menu/main.c b/cmd/menu/main.c @@ -10,7 +10,7 @@ #include <strings.h> #include <unistd.h> #include <bio.h> -#include <clientutil.h> +#include <stuff/clientutil.h> #include "fns.h" #define link _link @@ -19,6 +19,7 @@ static Biobuf* cmplbuf; static Biobuf* inbuf; static bool alwaysprint; static char* cmdsep; +static int screen_hint; static void usage(void) { @@ -169,10 +170,6 @@ update_filter(bool print) { update_input(); } -ErrorCode ignored_xerrors[] = { - { 0, } -}; - static void end(IxpConn *c) { @@ -184,13 +181,13 @@ static void preselect(IxpServer *s) { USED(s); - check_x_event(nil); + event_check(); } enum { PointerScreen = -1 }; void -init_screens(int screen_hint) { +init_screens(void) { Rectangle *rects; Point p; int i, n; @@ -223,12 +220,11 @@ main(int argc, char *argv[]) { static bool nokeys; int i; long ndump; - int screen; quotefmtinstall(); fmtinstall('r', errfmt); address = getenv("WMII_ADDRESS"); - screen = PointerScreen; + screen_hint = PointerScreen; find = strstr; compare = strncmp; @@ -261,7 +257,7 @@ main(int argc, char *argv[]) { prompt = EARGF(usage()); break; case 's': - screen = strtol(EARGF(usage()), nil, 10); + screen_hint = strtol(EARGF(usage()), nil, 10); break; case 'S': cmdsep = EARGF(usage()); @@ -287,7 +283,7 @@ main(int argc, char *argv[]) { client_init(address); srv.preselect = preselect; - ixp_listen(&srv, ConnectionNumber(display), nil, check_x_event, end); + ixp_listen(&srv, ConnectionNumber(display), nil, (void (*)(IxpConn*))preselect, end); ontop = !strcmp(readctl("bar on "), "top"); loadcolor(&cnorm, readctl("normcolors ")); @@ -331,7 +327,7 @@ main(int argc, char *argv[]) { if(barwin == nil) menu_init(); - init_screens(screen); + init_screens(); i = ixp_serverloop(&srv); if(i) diff --git a/cmd/strut/Makefile b/cmd/strut/Makefile @@ -13,15 +13,8 @@ LIB = $(LIBIXP) LIBS += -lm $(LIBS9) CFLAGS += -DIXP_NEEDAPI=86 OBJ = main \ - event \ ewmh \ - win \ - _util \ - ../wmii/map \ - ../wmii/printevent \ - printevent_kludge \ - ../wmii/x11 \ - ../util + win include ${ROOT}/mk/one.mk diff --git a/cmd/strut/_util.c b/cmd/strut/_util.c @@ -1,77 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <fbsdaemon@gmail.com> - * See LICENSE file for license details. - */ -#include "dat.h" -#include <ctype.h> -#include <string.h> -#include "fns.h" - -#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1)) -static int -getbase(const char **s, long *sign) { - const char *p; - int ret; - - ret = 10; - *sign = 1; - if(**s == '-') { - *sign = -1; - *s += 1; - }else if(**s == '+') - *s += 1; - - p = *s; - if(!strbcmp(p, "0x")) { - *s += 2; - ret = 16; - } - else if(isdigit(p[0])) { - if(p[1] == 'r') { - *s += 2; - ret = p[0] - '0'; - } - else if(isdigit(p[1]) && p[2] == 'r') { - *s += 3; - ret = 10*(p[0]-'0') + (p[1]-'0'); - } - } - else if(p[0] == '0') { - ret = 8; - } - if(ret != 10 && (**s == '-' || **s == '+')) - *sign = 0; - return ret; -} - -bool -getlong(const char *s, long *ret) { - const char *end; - char *rend; - int base; - long sign; - - end = s+strlen(s); - base = getbase(&s, &sign); - if(sign == 0) - return false; - - *ret = sign * strtol(s, &rend, base); - return (end == rend); -} - -bool -getulong(const char *s, ulong *ret) { - const char *end; - char *rend; - int base; - long sign; - - end = s+strlen(s); - base = getbase(&s, &sign); - if(sign < 1) - return false; - - *ret = strtoul(s, &rend, base); - return (end == rend); -} - diff --git a/cmd/strut/dat.h b/cmd/strut/dat.h @@ -3,31 +3,16 @@ #include <stdbool.h> #include <stdlib.h> #include <unistd.h> -#include <util.h> +#include <stuff/x.h> +#include <stuff/util.h> #include <ixp.h> -#include <x11.h> - -#define BLOCK(x) do { x; }while(0) #ifndef EXTERN # define EXTERN extern #endif -extern Handlers handlers; - -EXTERN bool running; +EXTERN Handlers handlers; EXTERN Window win; EXTERN Window frame; -EXTERN long xtime; - -EXTERN char buffer[8092]; -EXTERN char* _buffer; - -static char* const _buf_end = buffer + sizeof buffer; - -#define bufclear() \ - BLOCK( _buffer = buffer; _buffer[0] = '\0' ) -#define bufprint(...) \ - _buffer = seprint(_buffer, _buf_end, __VA_ARGS__) diff --git a/cmd/strut/event.c b/cmd/strut/event.c @@ -1,309 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <fbsdaemon@gmail.com> - * See LICENSE file for license details. - */ -#include "dat.h" -#include "fns.h" - -static void (*handler[LASTEvent])(XEvent*); - -void -dispatch_event(XEvent *e) { - /* print("%E\n", e); */ - if(e->type < nelem(handler) && handler[e->type]) - handler[e->type](e); -} - -#define handle(w, fn, ev) \ - BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev)) - -#ifdef notdef -uint -flushevents(long event_mask, bool dispatch) { - XEvent ev; - uint n = 0; - - while(XCheckMaskEvent(display, event_mask, &ev)) { - if(dispatch) - dispatch_event(&ev); - n++; - } - return n; -} - -static int -findenter(Display *d, XEvent *e, XPointer v) { - long *l; - - USED(d); - l = (long*)v; - if(*l) - return false; - if(e->type == EnterNotify) - return true; - if(e->type == MotionNotify) - (*l)++; - return false; -} - -/* This isn't perfect. If there were motion events in the queue - * before this was called, then it flushes nothing. If we don't - * check for them, we might lose a legitamate enter event. - */ -uint -flushenterevents(void) { - XEvent e; - long l; - int n; - - l = 0; - n = 0; - while(XCheckIfEvent(display, &e, findenter, (void*)&l)) - n++; - return n; -} -#endif - -static int -findtime(Display *d, XEvent *e, XPointer v) { - Window *w; - - w = (Window*)v; - if(e->type == PropertyNotify && e->xproperty.window == w->xid) { - xtime = e->xproperty.time; - return true; - } - return false; -} - -void -xtime_kludge(void) { - Window *w; - WinAttr wa; - XEvent e; - long l; - - w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0); - - XSelectInput(display, w->xid, PropertyChangeMask); - changeprop_long(w, "ATOM", "ATOM", &l, 0); - XIfEvent(display, &e, findtime, (void*)w); - - destroywindow(w); -} - -static void -buttonrelease(XEvent *e) { - XButtonPressedEvent *ev; - Window *w; - - ev = &e->xbutton; - if((w = findwin(ev->window))) - handle(w, bup, ev); -} - -static void -buttonpress(XEvent *e) { - XButtonPressedEvent *ev; - Window *w; - - ev = &e->xbutton; - if((w = findwin(ev->window))) - handle(w, bdown, ev); - else - XAllowEvents(display, ReplayPointer, ev->time); -} - -static void -clientmessage(XEvent *e) { - XClientMessageEvent *ev; - - ev = &e->xclient; - USED(ev); -} - -static void -configurenotify(XEvent *e) { - XConfigureEvent *ev; - Window *w; - - ev = &e->xconfigure; - if((w = findwin(ev->window))) - handle(w, config, ev); -} - -static void -destroynotify(XEvent *e) { - XDestroyWindowEvent *ev; - Window *w; - - ev = &e->xdestroywindow; - if((w = findwin(ev->window))) - handle(w, destroy, ev); -} - -static void -enternotify(XEvent *e) { - XCrossingEvent *ev; - Window *w; - - ev = &e->xcrossing; - xtime = ev->time; - if(ev->mode != NotifyNormal) - return; - - if((w = findwin(ev->window))) - handle(w, enter, ev); -} - -static void -leavenotify(XEvent *e) { - XCrossingEvent *ev; - - ev = &e->xcrossing; - xtime = ev->time; -} - -static void -focusin(XEvent *e) { - XFocusChangeEvent *ev; - Window *w; - - ev = &e->xfocus; - /* Yes, we're focusing in on nothing, here. */ - if(ev->detail == NotifyDetailNone) { - /* FIXME: Do something. */ - return; - } - - if(!((ev->detail == NotifyNonlinear) - ||(ev->detail == NotifyNonlinearVirtual) - ||(ev->detail == NotifyVirtual) - ||(ev->detail == NotifyInferior) - ||(ev->detail == NotifyAncestor))) - return; - if((ev->mode == NotifyWhileGrabbed)) - return; - - if((w = findwin(ev->window))) - handle(w, focusin, ev); -} - -static void -focusout(XEvent *e) { - XFocusChangeEvent *ev; - Window *w; - - ev = &e->xfocus; - if(!((ev->detail == NotifyNonlinear) - ||(ev->detail == NotifyNonlinearVirtual) - ||(ev->detail == NotifyVirtual) - ||(ev->detail == NotifyInferior) - ||(ev->detail == NotifyAncestor))) - return; - - if((w = findwin(ev->window))) - handle(w, focusout, ev); -} - -static void -expose(XEvent *e) { - XExposeEvent *ev; - Window *w; - - ev = &e->xexpose; - if(ev->count == 0) { - if((w = findwin(ev->window))) - handle(w, expose, ev); - } -} - -static void -keypress(XEvent *e) { - XKeyEvent *ev; - - ev = &e->xkey; - xtime = ev->time; -} - -static void -mappingnotify(XEvent *e) { - XMappingEvent *ev; - - ev = &e->xmapping; - /* Why do you need me to tell you this? */ - XRefreshKeyboardMapping(ev); -} - -static void -motionnotify(XEvent *e) { - XMotionEvent *ev; - Window *w; - - ev = &e->xmotion; - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, motion, ev); -} - -static void -propertynotify(XEvent *e) { - XPropertyEvent *ev; - Window *w; - - ev = &e->xproperty; - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, property, ev); -} - -static void -mapnotify(XEvent *e) { - XMapEvent *ev; - Window *w; - - ev = &e->xmap; - if((w = findwin(ev->window))) - handle(w, map, ev); -} - -static void -unmapnotify(XEvent *e) { - XUnmapEvent *ev; - Window *w; - - ev = &e->xunmap; - if((w = findwin(ev->window)) && w->parent && (ev->event == w->parent->xid)) { - if(ev->send_event || w->unmapped-- == 0) - handle(w, unmap, ev); - } -} - -static void (*handler[LASTEvent])(XEvent*) = { - [ButtonPress] = buttonpress, - [ButtonRelease] = buttonrelease, - [ClientMessage] = clientmessage, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [FocusOut] = focusout, - [KeyPress] = keypress, - [LeaveNotify] = leavenotify, - [MapNotify] = mapnotify, - [MappingNotify] = mappingnotify, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify, -}; - -void -xevent_loop(void) { - XEvent ev; - - while(running) { - XNextEvent(display, &ev); - dispatch_event(&ev); - } -} - diff --git a/cmd/strut/fns.h b/cmd/strut/fns.h @@ -8,9 +8,6 @@ void xtime_kludge(void); void restrut(void); -bool getlong(const char*, long*); -bool getulong(const char*, ulong*); - void ewmh_getstrut(Window*, Rectangle[4]); void ewmh_setstrut(Window*, Rectangle[4]); diff --git a/cmd/strut/main.c b/cmd/strut/main.c @@ -30,8 +30,6 @@ debug(int flag, const char *fmt, ...) { va_end(ap); } -ErrorCode ignored_xerrors[] = { {0,} }; - static Window findframe(Window *w) { XWindow *children; @@ -39,6 +37,7 @@ findframe(Window *w) { Window ret = {0, }; uint n; + xw = w->xid; for(par=w->xid; par != scr.root.xid; ) { xw = par; XQueryTree(display, xw, &root, &par, &children, &n); @@ -93,8 +92,8 @@ extern int fmtevent(Fmt*); sethandler(&frame, &handlers); selectinput(&frame, StructureNotifyMask); - running = true; - xevent_loop(); + event_looprunning = true; + event_loop(); XCloseDisplay(display); return 0; diff --git a/cmd/strut/printevent_kludge.c b/cmd/strut/printevent_kludge.c @@ -1,12 +0,0 @@ -#include "dat.h" - -void dprint(const char *fmt, ...); -void -dprint(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprint(2, fmt, ap); - va_end(ap); -} - diff --git a/cmd/strut/win.c b/cmd/strut/win.c @@ -92,7 +92,7 @@ config(Window *w, XConfigureEvent *ev) { static void destroy(Window *w, XDestroyWindowEvent *ev) { USED(w, ev); - running = false; + event_looprunning = false; } Handlers handlers = { diff --git a/cmd/util.c b/cmd/util.c @@ -1,272 +0,0 @@ -/* Written by Kris Maglione <fbsdaemon at gmail dot com> */ -/* Public domain */ -#include <ctype.h> -#include <errno.h> -#include <sys/types.h> -#include <signal.h> -#include <stdarg.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> -#include <util.h> -#include <fmt.h> - -typedef struct VFmt VFmt; -struct VFmt { - const char *fmt; - va_list args; -}; - -#ifdef VARARGCK -# pragma varargck type "V" VFmt* -#endif - -static int -Vfmt(Fmt *f) { - VFmt *vf; - int i; - - vf = va_arg(f->args, VFmt*); - i = fmtvprint(f, vf->fmt, vf->args); - return i; -} - -void -fatal(const char *fmt, ...) { - VFmt fp; - - fmtinstall('V', Vfmt); - fmtinstall('\001', Vfmt); - - fp.fmt = fmt; - va_start(fp.args, fmt); - fprint(2, "%s: fatal: %V\n", argv0, &fp); - va_end(fp.args); - - exit(1); -} - -void* -freelater(void *p) { - static char* obj[16]; - static long nobj; - int id; - - id = nobj++ % nelem(obj); - free(obj[id]); - obj[id] = p; - return p; -} - -char* -vsxprint(const char *fmt, va_list ap) { - char *s; - - s = vsmprint(fmt, ap); - freelater(s); - return s; -} - -char* -sxprint(const char *fmt, ...) { - va_list ap; - char *ret; - - va_start(ap, fmt); - ret = vsxprint(fmt, ap); - va_end(ap); - return ret; -} - -void -_die(char *file, int line, char *msg, ...) { - va_list ap; - - va_start(ap, msg); - fprint(2, "%s: dieing at %s:%d: %s\n", - argv0, file, line, - vsxprint(msg, ap)); - va_end(ap); - - kill(getpid(), SIGABRT); - abort(); /* Adds too many frames: - * _die() - * abort() - * raise(SIGABRT) - * kill(getpid(), SIGABRT) - */ -} - -/* Can't malloc */ -static void -mfatal(char *name, uint size) { - const char - couldnot[] = ": fatal: Could not ", - paren[] = "() ", - bytes[] = " bytes\n"; - char buf[1024]; - char sizestr[8]; - int i; - - i = sizeof sizestr; - do { - sizestr[--i] = '0' + (size%10); - size /= 10; - } while(size > 0); - - strlcat(buf, argv0, sizeof buf); - strlcat(buf, couldnot, sizeof buf); - strlcat(buf, name, sizeof buf); - strlcat(buf, paren, sizeof buf); - strlcat(buf, sizestr+i, sizeof buf); - strlcat(buf, bytes, sizeof buf); - write(2, buf, strlen(buf)); - - exit(1); -} - -void * -emalloc(uint size) { - void *ret = malloc(size); - if(!ret) - mfatal("malloc", size); - return ret; -} - -void * -emallocz(uint size) { - void *ret = emalloc(size); - memset(ret, 0, size); - return ret; -} - -void * -erealloc(void *ptr, uint size) { - void *ret = realloc(ptr, size); - if(!ret) - mfatal("realloc", size); - return ret; -} - -char* -estrdup(const char *str) { - void *ret = strdup(str); - if(!ret) - mfatal("strdup", strlen(str)); - return ret; -} - -char* -estrndup(const char *str, uint len) { - char *ret; - - len = min(len, strlen(str)); - ret = emalloc(len + 1); - memcpy(ret, str, len); - ret[len] = '\0'; - return ret; -} - - -uint -tokenize(char *res[], uint reslen, char *str, char delim) { - char *s; - uint i; - - i = 0; - s = str; - while(i < reslen && *s) { - while(*s == delim) - *(s++) = '\0'; - if(*s) - res[i++] = s; - while(*s && *s != delim) - s++; - } - return i; -} - -uint -stokenize(char *res[], uint reslen, char *str, char *delim) { - char *s; - uint i; - - i = 0; - s = str; - while(i < reslen && *s) { - while(strchr(delim, *s)) - *(s++) = '\0'; - if(*s) - res[i++] = s; - while(*s && !strchr(delim, *s)) - s++; - } - return i; -} - -int -max(int a, int b) { - if(a > b) - return a; - return b; -} - -int -min(int a, int b) { - if(a < b) - return a; - return b; -} - -int -utflcpy(char *to, const char *from, int l) { - char *p; - - p = utfecpy(to, to+l, from); - return p-to; -} - -uint -strlcat(char *dst, const char *src, uint size) { - const char *s; - char *d; - int n, len; - - d = dst; - s = src; - n = size; - while(n-- > 0 && *d != '\0') - d++; - len = n; - - while(*s != '\0') { - if(n-- > 0) - *d++ = *s; - s++; - } - if(len > 0) - *d = '\0'; - return size - n - 1; -} - -/* TODO: Make this UTF-8 compliant. */ -char* -strcasestr(const char *dst, const char *src) { - int dc, sc; - int len; - - len = strlen(src) - 1; - for(; (sc = *src) && *dst; src++) { - sc = tolower(dc); - for(; (dc = *dst); dst++) { - dc = tolower(dc); - if(sc == dc && !strncasecmp(dst+1, src+1, len)) - return (char*)(uintptr_t)dst; - } - } - return nil; -} - diff --git a/cmd/wmii/Makefile b/cmd/wmii/Makefile @@ -24,25 +24,18 @@ OBJ = area \ float \ frame \ fs \ - geom \ key \ layout \ main \ - map \ message \ mouse \ print \ root \ rule \ - printevent\ screen \ utf \ - _util \ view \ - xdnd \ - x11 \ - xext \ - ../util + xdnd include $(ROOT)/mk/one.mk diff --git a/cmd/wmii/_util.c b/cmd/wmii/_util.c @@ -1,378 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "dat.h" -#include <errno.h> -#include <fcntl.h> -#include <stdarg.h> -#include <sys/signal.h> -#include <sys/wait.h> -#include <unistd.h> -#include <bio.h> -#include "fns.h" - -/* Blech. */ -#define VECTOR(type, nam, c) \ -void \ -vector_##c##init(Vector_##nam *v) { \ - memset(v, 0, sizeof *v); \ -} \ - \ -void \ -vector_##c##free(Vector_##nam *v) { \ - free(v->ary); \ - memset(v, 0, sizeof *v); \ -} \ - \ -void \ -vector_##c##push(Vector_##nam *v, type val) { \ - if(v->n == v->size) { \ - if(v->size == 0) \ - v->size = 2; \ - v->size <<= 2; \ - v->ary = erealloc(v->ary, v->size * sizeof *v->ary); \ - } \ - v->ary[v->n++] = val; \ -} \ - -VECTOR(long, long, l) -VECTOR(Rectangle, rect, r) -VECTOR(void*, ptr, p) - -int -doublefork(void) { - pid_t pid; - int status; - - switch(pid=fork()) { - case -1: - fatal("Can't fork(): %r"); - case 0: - switch(pid=fork()) { - case -1: - fatal("Can't fork(): %r"); - case 0: - return 0; - default: - exit(0); - } - default: - waitpid(pid, &status, 0); - return pid; - } - /* NOTREACHED */ -} - -void -closeexec(int fd) { - if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - fatal("can't set %d close on exec: %r", fd); -} - -int -spawn3(int fd[3], const char *file, char *argv[]) { - /* Some ideas from Russ Cox's libthread port. */ - int p[2]; - int pid; - - if(pipe(p) < 0) - return -1; - closeexec(p[1]); - - switch(pid = doublefork()) { - case 0: - dup2(fd[0], 0); - dup2(fd[1], 1); - dup2(fd[2], 2); - - execvp(file, argv); - write(p[1], &errno, sizeof errno); - exit(1); - break; - default: - close(p[1]); - if(read(p[0], &errno, sizeof errno) == sizeof errno) - pid = -1; - close(p[0]); - break; - case -1: /* can't happen */ - break; - } - - close(fd[0]); - /* These could fail if any of these was also a previous fd. */ - close(fd[1]); - close(fd[2]); - return pid; -} - -int -spawn3l(int fd[3], const char *file, ...) { - va_list ap; - char **argv; - int i, n; - - va_start(ap, file); - for(n=0; va_arg(ap, char*); n++) - ; - va_end(ap); - - argv = emalloc((n+1) * sizeof *argv); - va_start(ap, file); - quotefmtinstall(); - for(i=0; i <= n; i++) - argv[i] = va_arg(ap, char*); - va_end(ap); - - i = spawn3(fd, file, argv); - free(argv); - return i; -} - -#ifdef __linux__ -# define PROGTXT "exe" -#else -# define PROGTXT "file" -#endif - -static void -_backtrace(int pid, char *btarg) { - char *proc, *spid, *gdbcmd; - int fd[3], p[2]; - int status, cmdfd; - - gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX"); - if(pipe(p) < 0) - goto done; - closeexec(p[0]); - - cmdfd = mkstemp(gdbcmd); - if(cmdfd < 0) - goto done; - - fprint(cmdfd, "bt %s\n", btarg); - fprint(cmdfd, "detach\n"); - close(cmdfd); - - fd[0] = open("/dev/null", O_RDONLY); - fd[1] = p[1]; - fd[2] = dup(2); - - proc = sxprint("/proc/%d/" PROGTXT, pid); - spid = sxprint("%d", pid); - if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) { - unlink(gdbcmd); - goto done; - } - - Biobuf bp; - char *s; - - Binit(&bp, p[0], OREAD); - while((s = Brdstr(&bp, '\n', 1))) { - Dprint(DStack, "%s\n", s); - free(s); - } - unlink(gdbcmd); - -done: - free(gdbcmd); - kill(pid, SIGKILL); - waitpid(pid, &status, 0); -} - -void -backtrace(char *btarg) { - int pid; - - /* Fork so we can backtrace the child. Keep this stack - * frame minimal, so the trace is fairly clean. - */ - Debug(DStack) - switch(pid = fork()) { - case -1: - return; - case 0: - kill(getpid(), SIGSTOP); - _exit(0); - default: - _backtrace(pid, btarg); - break; - } - -} - -void -reinit(Regex *r, char *regx) { - - refree(r); - - if(regx[0] != '\0') { - r->regex = estrdup(regx); - r->regc = regcomp(regx); - } -} - -void -refree(Regex *r) { - - free(r->regex); - free(r->regc); - r->regex = nil; - r->regc = nil; -} - -void -uniq(char **toks) { - char **p, **q; - - q = toks; - if(*q == nil) - return; - for(p=q+1; *p; p++) - if(strcmp(*q, *p)) - *++q = *p; - *++q = nil; -} - -char** -comm(int cols, char **toka, char **tokb) { - Vector_ptr vec; - char **ret; - int cmp; - - vector_pinit(&vec); - while(*toka || *tokb) { - if(!*toka) - cmp = 1; - else if(!*tokb) - cmp = -1; - else - cmp = strcmp(*toka, *tokb); - if(cmp < 0) { - if(cols & CLeft) - vector_ppush(&vec, *toka); - toka++; - }else if(cmp > 0) { - if(cols & CRight) - vector_ppush(&vec, *tokb); - tokb++; - }else { - if(cols & CCenter) - vector_ppush(&vec, *toka); - toka++; - tokb++; - } - } - vector_ppush(&vec, nil); - ret = strlistdup((char**)vec.ary); - free(vec.ary); - return ret; -} - -void -grep(char **list, Reprog *re, int flags) { - char **p, **q; - int res; - - q = list; - for(p=q; *p; p++) { - res = 0; - if(re) - res = regexec(re, *p, nil, 0); - if(res && !(flags & GInvert) - || !res && (flags & GInvert)) - *q++ = *p; - } - *q = nil; -} - -char* -join(char **list, char *sep) { - Fmt f; - char **p; - - if(fmtstrinit(&f) < 0) - abort(); - - for(p=list; *p; p++) { - if(p != list) - fmtstrcpy(&f, sep); - fmtstrcpy(&f, *p); - } - - return fmtstrflush(&f); -} - -int -strlcatprint(char *buf, int len, const char *fmt, ...) { - va_list ap; - int buflen; - int ret; - - va_start(ap, fmt); - buflen = strlen(buf); - ret = vsnprint(buf+buflen, len-buflen, fmt, ap); - va_end(ap); - return ret; -} - -char* -pathsearch(const char *path, const char *file, bool slashok) { - char *orig, *p, *s; - - if(!slashok && strchr(file, '/') > file) - file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file); - else if(!strncmp(file, "./", 2)) - file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file+2); - if(file[0] == '/') { - if(access(file, X_OK)) - return strdup(file); - return nil; - } - - orig = estrdup(path ? path : getenv("PATH")); - for(p=orig; (s=strtok(p, ":")); p=nil) { - s = smprint("%s/%s", s, file); - if(!access(s, X_OK)) - break; - free(s); - } - free(orig); - return s; -} - -int -unquote(char *buf, char *toks[], int ntoks) { - char *s, *t; - bool inquote; - int n; - - n = 0; - s = buf; - while(*s && n < ntoks) { - while(*s && utfrune(" \t\r\n", *s)) - s++; - inquote = false; - toks[n] = s; - t = s; - while(*s && (inquote || !utfrune(" \t\r\n", *s))) { - if(*s == '\'') { - if(inquote && s[1] == '\'') - *t++ = *s++; - else - inquote = !inquote; - } - else - *t++ = *s; - s++; - } - if(*s) - s++; - *t = '\0'; - if(s != toks[n]) - n++; - } - return n; -} - diff --git a/cmd/wmii/client.c b/cmd/wmii/client.c @@ -314,7 +314,7 @@ client_destroy(Client *c) { if(starting > -1) event("DestroyClient %C\n", c); - flushevents(FocusChangeMask, true); + event_flush(FocusChangeMask, true); free(c->w.hints); free(c); } @@ -503,7 +503,7 @@ client_focus(Client *c) { c->group->client = c; sync(); - flushevents(FocusChangeMask, true); + event_flush(FocusChangeMask, true); Dprint(DFocus, "client_focus([%C]%s)\n", c, clientname(c)); Dprint(DFocus, "\t[%C]%s\n\t=> [%C]%s\n", @@ -514,14 +514,14 @@ client_focus(Client *c) { if(!c->noinput) setfocus(&c->w, RevertToParent); else if(c->proto & ProtoTakeFocus) { - xtime_kludge(); + event_updatextime(); client_message(c, "WM_TAKE_FOCUS", 0); } }else setfocus(screen->barwin, RevertToParent); sync(); - flushevents(FocusChangeMask, true); + event_flush(FocusChangeMask, true); } } diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h @@ -11,11 +11,11 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <ixp.h> -#include <util.h> #include <utf.h> -#include <fmt.h> -#include <x11.h> +#include <stuff/x.h> +#include <stuff/util.h> +#include <debug.h> +#include <ixp.h> #define FONT "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*" #define FOCUSCOLORS "#ffffff #335577 #447799" @@ -25,12 +25,6 @@ enum { PingTime = 10000, }; -enum { - CLeft = 1<<0, - CCenter = 1<<1, - CRight = 1<<2, -}; - enum IncMode { IIgnore, IShow, @@ -38,10 +32,6 @@ enum IncMode { }; enum { - GInvert = 1<<0, -}; - -enum { UrgManager, UrgClient, }; @@ -80,15 +70,6 @@ enum Barpos { }; enum { - CurNormal, - CurNECorner, CurNWCorner, CurSECorner, CurSWCorner, - CurDHArrow, CurDVArrow, CurMove, CurInput, CurSizing, - CurTCross, CurIcon, - CurNone, - CurLast, -}; - -enum { NCOL = 16, }; @@ -98,16 +79,16 @@ enum Protocols { ProtoPing = 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 { + CurNormal, + CurNECorner, CurNWCorner, CurSECorner, CurSWCorner, + CurDHArrow, CurDVArrow, CurMove, CurInput, CurSizing, + CurTCross, CurIcon, + CurNone, + CurLast, }; +Cursor cursor[CurLast]; + /* Data Structures */ typedef struct Area Area; @@ -117,9 +98,6 @@ typedef struct Divide Divide; typedef struct Frame Frame; typedef struct Group Group; typedef struct Key Key; -typedef struct Map Map; -typedef struct MapEnt MapEnt; -typedef struct Regex Regex; typedef struct Rule Rule; typedef struct Ruleset Ruleset; typedef struct Strut Strut; @@ -156,11 +134,6 @@ struct Bar { WMScreen* screen; }; -struct Regex { - char* regex; - Reprog* regc; -}; - struct Client { Client* next; Frame* frame; @@ -243,11 +216,6 @@ struct Key { KeyCode key; }; -struct Map { - MapEnt**bucket; - uint nhash; -}; - struct Rule { Rule* next; Reprog* regex; @@ -286,23 +254,6 @@ struct View { Rectangle *pad; }; -/* Yuck. */ -#define VECTOR(type, nam, c) \ -typedef struct Vector_##nam Vector_##nam; \ -struct Vector_##nam { \ - type* ary; \ - long n; \ - long size; \ -}; \ -void vector_##c##free(Vector_##nam*); \ -void vector_##c##init(Vector_##nam*); \ -void vector_##c##push(Vector_##nam*, type); \ - -VECTOR(long, long, l) -VECTOR(Rectangle, rect, r) -VECTOR(void*, ptr, p) -#undef VECTOR - #ifndef EXTERN # define EXTERN extern #endif @@ -328,8 +279,6 @@ enum { BLeft, BRight }; -#define BLOCK(x) do { x; }while(0) - EXTERN struct WMScreen { Bar* bar[2]; Window* barwin; @@ -360,15 +309,6 @@ EXTERN Client c_root; EXTERN Handlers framehandler; -EXTERN char buffer[8092]; -EXTERN char* _buffer; -static char* const _buf_end = buffer + sizeof buffer; - -#define bufclear() \ - BLOCK( _buffer = buffer; _buffer[0] = '\0' ) -#define bufprint(...) \ - _buffer = seprint(_buffer, _buf_end, __VA_ARGS__) - /* IXP */ EXTERN IxpServer srv; EXTERN Ixp9Srv p9srv; @@ -379,26 +319,15 @@ EXTERN uint numlock_mask; EXTERN Image* ibuf; EXTERN Image* ibuf32; -EXTERN Cursor cursor[CurLast]; - -typedef void (*XHandler)(XEvent*); -EXTERN XHandler handler[LASTEvent]; - /* Misc */ EXTERN int starting; EXTERN bool resizing; EXTERN long ignoreenter; EXTERN char* user; EXTERN char* execstr; -EXTERN int debugflag; -EXTERN int debugfile; EXTERN long xtime; -EXTERN Visual* render_visual; EXTERN Client* kludge; extern char* debugtab[]; -#define Debug(x) if(((debugflag|debugfile)&(x)) && setdebug(x)) -#define Dprint(x, ...) BLOCK( if((debugflag|debugfile)&(x)) debug(x, __VA_ARGS__) ) - diff --git a/cmd/wmii/event.c b/cmd/wmii/event.c @@ -5,105 +5,16 @@ #include <X11/keysym.h> #include "fns.h" -typedef void (*EvHandler)(XEvent*); - void -dispatch_event(XEvent *e) { +debug_event(XEvent *e) { Dprint(DEvent, "%E\n", e); - if(e->type < nelem(handler)) { - if(handler[e->type]) - handler[e->type](e); - }else - xext_event(e); } #define handle(w, fn, ev) \ BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev)) -static int -findtime(Display *d, XEvent *e, XPointer v) { - Window *w; - - w = (Window*)v; - if(e->type == PropertyNotify && e->xproperty.window == w->xid) { - xtime = e->xproperty.time; - return true; - } - return false; -} - void -xtime_kludge(void) { - /* Round trip. */ - static Window *w; - WinAttr wa; - XEvent e; - long l; - - if(w == nil) { - w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0); - selectinput(w, PropertyChangeMask); - } - changeprop_long(w, "ATOM", "ATOM", &l, 0); - sync(); - XIfEvent(display, &e, findtime, (void*)w); -} - -uint -flushevents(long event_mask, bool dispatch) { - XEvent ev; - uint n = 0; - - while(XCheckMaskEvent(display, event_mask, &ev)) { - if(dispatch) - dispatch_event(&ev); - n++; - } - return n; -} - -static Bool -findenter(Display *d, XEvent *e, XPointer v) { - long *l; - - USED(d); - l = (long*)v; - if(*l) - return false; - if(e->type == EnterNotify) - return true; - if(e->type == MotionNotify) - (*l)++; - return false; -} - -/* This isn't perfect. If there were motion events in the queue - * before this was called, then it flushes nothing. If we don't - * check for them, we might lose a legitamate enter event. - */ -uint -flushenterevents(void) { - XEvent e; - long l; - int n; - - l = 0; - n = 0; - while(XCheckIfEvent(display, &e, findenter, (void*)&l)) - n++; - return n; -} - -static void -buttonrelease(XButtonPressedEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, bup, ev); -} - -static void -buttonpress(XButtonPressedEvent *ev) { +event_buttonpress(XButtonPressedEvent *ev) { Window *w; if((w = findwin(ev->window))) @@ -112,27 +23,8 @@ buttonpress(XButtonPressedEvent *ev) { XAllowEvents(display, ReplayPointer, ev->time); } -static void -configurerequest(XConfigureRequestEvent *ev) { - XWindowChanges wc; - Window *w; - - if((w = findwin(ev->window))) - handle(w, configreq, ev); - else{ - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(display, ev->window, ev->value_mask, &wc); - } -} - -static void -configurenotify(XConfigureEvent *ev) { +void +event_configurenotify(XConfigureEvent *ev) { Window *w; ignoreenter = ev->serial; @@ -140,8 +32,8 @@ configurenotify(XConfigureEvent *ev) { handle(w, config, ev); } -static void -clientmessage(XClientMessageEvent *ev) { +void +event_clientmessage(XClientMessageEvent *ev) { if(ewmh_clientmessage(ev)) return; @@ -149,40 +41,16 @@ clientmessage(XClientMessageEvent *ev) { return; } -static void -destroynotify(XDestroyWindowEvent *ev) { +void +event_destroynotify(XDestroyWindowEvent *ev) { Window *w; Client *c; if((w = findwin(ev->window))) 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); - } -} - -static void -enternotify(XCrossingEvent *ev) { - Window *w; - - xtime = ev->time; - if(ev->mode != NotifyNormal) - return; - - if((w = findwin(ev->window))) - handle(w, enter, ev); -} - -static void -leavenotify(XCrossingEvent *ev) { - Window *w; - - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, leave, ev); + else if((c = win2client(ev->window))) + fprint(2, "Badness: Unhandled DestroyNotify: Client: %p, Window: %W, Name: %s\n", + c, &c->w, c->name); } void @@ -192,8 +60,8 @@ print_focus(const char *fn, Client *c, const char *to) { Dprint(DFocus, "\t%s => %s\n", clientname(disp.focus), to); } -static void -focusin(XFocusChangeEvent *ev) { +void +event_focusin(XFocusChangeEvent *ev) { Window *w; Client *c; @@ -231,8 +99,8 @@ focusin(XFocusChangeEvent *ev) { } } -static void -focusout(XFocusChangeEvent *ev) { +void +event_focusout(XFocusChangeEvent *ev) { XEvent me; Window *w; @@ -247,74 +115,22 @@ focusout(XFocusChangeEvent *ev) { if((ev->mode == NotifyGrab) && XCheckMaskEvent(display, KeyPressMask, &me)) - dispatch_event(&me); + event_dispatch(&me); else if((w = findwin(ev->window))) handle(w, focusout, ev); } -static void -expose(XExposeEvent *ev) { - Window *w; - - if(ev->count == 0) - if((w = findwin(ev->window))) - handle(w, expose, ev); -} - -static void -keypress(XKeyEvent *ev) { - Window *w; - - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, kdown, ev); -} - -static void -mappingnotify(XMappingEvent *ev) { - - XRefreshKeyboardMapping(ev); - if(ev->request == MappingKeyboard) - update_keys(); -} - -static void -maprequest(XMapRequestEvent *ev) { - Window *w; - - if((w = findwin(ev->parent))) - handle(w, mapreq, ev); -} - -static void -motionnotify(XMotionEvent *ev) { - Window *w; - - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, motion, ev); -} - -static void -propertynotify(XPropertyEvent *ev) { - Window *w; - - xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, property, ev); -} - -static void -mapnotify(XMapEvent *ev) { - Window *w; +void +event_mapnotify(XMapEvent *ev) { + Window *w; - ignoreenter = ev->serial; - if((w = findwin(ev->window))) - handle(w, map, ev); + ignoreenter = ev->serial; + if((w = findwin(ev->window))) + handle(w, map, ev); } -static void -unmapnotify(XUnmapEvent *ev) { +void +event_unmapnotify(XUnmapEvent *ev) { Window *w; ignoreenter = ev->serial; @@ -325,35 +141,3 @@ unmapnotify(XUnmapEvent *ev) { } } -EvHandler handler[LASTEvent] = { - [ButtonPress] = (EvHandler)buttonpress, - [ButtonRelease] = (EvHandler)buttonrelease, - [ConfigureRequest] = (EvHandler)configurerequest, - [ConfigureNotify] = (EvHandler)configurenotify, - [ClientMessage] = (EvHandler)clientmessage, - [DestroyNotify] = (EvHandler)destroynotify, - [EnterNotify] = (EvHandler)enternotify, - [Expose] = (EvHandler)expose, - [FocusIn] = (EvHandler)focusin, - [FocusOut] = (EvHandler)focusout, - [KeyPress] = (EvHandler)keypress, - [LeaveNotify] = (EvHandler)leavenotify, - [MapNotify] = (EvHandler)mapnotify, - [MapRequest] = (EvHandler)maprequest, - [MappingNotify] = (EvHandler)mappingnotify, - [MotionNotify] = (EvHandler)motionnotify, - [PropertyNotify] = (EvHandler)propertynotify, - [UnmapNotify] = (EvHandler)unmapnotify, -}; - -void -check_x_event(IxpConn *c) { - XEvent ev; - - USED(c); - while(XPending(display)) { - XNextEvent(display, &ev); - dispatch_event(&ev); - } -} - diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h @@ -129,12 +129,8 @@ void poperror(void); jmp_buf* pusherror(void); /* event.c */ -void check_x_event(IxpConn*); -void dispatch_event(XEvent*); -uint flushenterevents(void); -uint flushevents(long, bool dispatch); +void debug_event(XEvent*); void print_focus(const char*, Client*, const char*); -void xtime_kludge(void); /* ewmh.c */ int ewmh_clientmessage(XClientMessageEvent*); @@ -197,15 +193,6 @@ void fs_walk(Ixp9Req*); void fs_write(Ixp9Req*); void event(const char*, ...); -/* geom.c */ -Align get_sticky(Rectangle src, Rectangle dst); -Cursor quad_cursor(Align); -Align quadrant(Rectangle, Point); -bool rect_contains_p(Rectangle, Rectangle); -bool rect_haspoint_p(Point, Rectangle); -bool rect_intersect_p(Rectangle, Rectangle); -Rectangle rect_intersection(Rectangle, Rectangle); - /* key.c */ void init_lock_keys(void); void kpress(XWindow, ulong mod, KeyCode); @@ -215,15 +202,7 @@ void update_keys(void); void init_screens(void); void spawn_command(const char*); -/* map.c */ -void** hash_get(Map*, const char*, bool create); -void* hash_rm(Map*, const char*); -void** map_get(Map*, ulong, bool create); -void* map_rm(Map*, ulong); - /* message.c */ -bool getlong(const char*, long*); -bool getulong(const char*, ulong*); char* message_client(Client*, IxpMsg*); char* message_root(void*, IxpMsg*); char* message_view(View*, IxpMsg*); @@ -237,6 +216,7 @@ char* readctl_root(void); char* readctl_view(View*); Area* strarea(View*, ulong, const char*); void warning(const char*, ...); + /* debug */ void debug(int, const char*, ...); void dprint(const char*, ...); @@ -259,9 +239,6 @@ Align snap_rect(const Rectangle *rects, int num, Rectangle *current, Align *mask /* print.c */ int Ffmt(Fmt*); -/* printevent.c */ -void printevent(XEvent*); - /* root.c */ void root_init(void); @@ -295,22 +272,6 @@ void view_update_all(void); void view_update_rect(View*); Rectangle* view_rects(View*, uint *num, Frame *ignore); -/* _util.c */ -void backtrace(char*); -void closeexec(int); -char** comm(int, char**, char**); -int doublefork(void); -void grep(char**, Reprog*, int); -char* join(char**, char*); -char* pathsearch(const char*, const char*, bool); -void refree(Regex*); -void reinit(Regex*, char*); -int strlcatprint(char*, int, const char*, ...); -int spawn3(int[3], const char*, char*[]); -int spawn3l(int[3], const char*, ...); -void uniq(char**); -int unquote(char*, char*[], int); - /* utf.c */ char* toutf8(const char*); char* toutf8n(const char*, size_t); @@ -319,10 +280,3 @@ char* toutf8n(const char*, size_t); int xdnd_clientmessage(XClientMessageEvent*); void xdnd_initwindow(Window*); -/* xext.c */ -void randr_event(XEvent*); -bool render_argb_p(Visual*); -void xext_event(XEvent*); -void xext_init(void); -Rectangle* xinerama_screens(int*); - diff --git a/cmd/wmii/geom.c b/cmd/wmii/geom.c @@ -1,94 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "dat.h" -#include "fns.h" - -bool -rect_haspoint_p(Point pt, Rectangle r) { - return (pt.x >= r.min.x) && (pt.x < r.max.x) - && (pt.y >= r.min.y) && (pt.y < r.max.y); -} - -bool -rect_intersect_p(Rectangle r, Rectangle r2) { - return r.min.x <= r2.max.x - && r.max.x >= r2.min.x - && r.min.y <= r2.max.y - && r.max.y >= r2.min.y; -} - -Rectangle -rect_intersection(Rectangle r, Rectangle r2) { - Rectangle ret; - - /* ret != canonrect(ret) ≡ no intersection. */ - ret.min.x = max(r.min.x, r2.min.x); - ret.max.x = min(r.max.x, r2.max.x); - ret.min.y = max(r.min.y, r2.min.y); - ret.max.y = min(r.max.y, r2.max.y); - return ret; -} - -bool -rect_contains_p(Rectangle r, Rectangle r2) { - return r2.min.x >= r.min.x - && r2.max.x <= r.max.x - && r2.min.y >= r.min.y - && r2.max.y <= r.max.y; -} - -Align -quadrant(Rectangle r, Point pt) { - Align ret; - - pt = subpt(pt, r.min); - ret = 0; - - if(pt.x >= Dx(r) * .5) - ret |= East; - if(pt.x <= Dx(r) * .5) - ret |= West; - if(pt.y <= Dy(r) * .5) - ret |= North; - if(pt.y >= Dy(r) * .5) - ret |= South; - - return ret; -} - -Cursor -quad_cursor(Align align) { - switch(align) { - case NEast: return cursor[CurNECorner]; - case NWest: return cursor[CurNWCorner]; - case SEast: return cursor[CurSECorner]; - case SWest: return cursor[CurSWCorner]; - case South: - case North: return cursor[CurDVArrow]; - case East: - case West: return cursor[CurDHArrow]; - default: return cursor[CurMove]; - } -} - -Align -get_sticky(Rectangle src, Rectangle dst) { - Align corner; - - corner = 0; - if(src.min.x != dst.min.x - && src.max.x == dst.max.x) - corner |= East; - else - corner |= West; - - if(src.min.y != dst.min.y - && src.max.y == dst.max.y) - corner |= South; - else - corner |= North; - - return corner; -} - diff --git a/cmd/wmii/key.c b/cmd/wmii/key.c @@ -208,7 +208,7 @@ kpress(XWindow w, ulong mod, KeyCode keycode) { event("Key %s\n", found->name); else { XGrabKeyboard(display, w, true, GrabModeAsync, GrabModeAsync, CurrentTime); - flushevents(FocusChangeMask, true); + event_flush(FocusChangeMask, true); kpress_seq(w, found); XUngrabKeyboard(display, CurrentTime); } diff --git a/cmd/wmii/main.c b/cmd/wmii/main.c @@ -323,7 +323,7 @@ static void check_preselect(IxpServer *s) { USED(s); - check_x_event(nil); + event_check(); } static void @@ -412,9 +412,11 @@ extern int fmtevent(Fmt*); ewmh_init(); xext_init(); + event_debug = debug_event; + srv.preselect = check_preselect; ixp_listen(&srv, sock, &p9srv, serve_9pcon, nil); - ixp_listen(&srv, ConnectionNumber(display), nil, check_x_event, closedisplay); + ixp_listen(&srv, ConnectionNumber(display), nil, (void (*)(IxpConn*))check_preselect, closedisplay); def.border = 1; def.colmode = Colstack; diff --git a/cmd/wmii/map.c b/cmd/wmii/map.c @@ -1,126 +0,0 @@ -/* Written by Kris Maglione */ -/* Public domain */ -#include "dat.h" -#include "fns.h" - -/* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */ - -struct MapEnt { - ulong hash; - const char* key; - void* val; - MapEnt* next; -}; - -MapEnt *NM; - -/* By Dan Bernstein. Public domain. */ -static ulong -hash(const char *str) { - ulong h; - - h = 5381; - while (*str != '\0') { - h += h << 5; /* h *= 33 */ - h ^= *str++; - } - return h; -} - -static void -insert(MapEnt **e, ulong val, const char *key) { - MapEnt *te; - - te = emallocz(sizeof *te); - te->hash = val; - te->key = key; - te->next = *e; - *e = te; -} - -static MapEnt** -map_getp(Map *map, ulong val, int create) { - MapEnt **e; - - e = &map->bucket[val%map->nhash]; - for(; *e; e = &(*e)->next) - if((*e)->hash >= val) break; - if(*e == nil || (*e)->hash != val) { - if(create) - insert(e, val, nil); - else - e = &NM; - } - return e; -} - -static MapEnt** -hash_getp(Map *map, const char *str, int create) { - MapEnt **e; - ulong h; - int cmp; - - h = hash(str); - e = map_getp(map, h, create); - if(*e && (*e)->key == nil) - (*e)->key = str; - else { - SET(cmp); - for(; *e; e = &(*e)->next) - if((*e)->hash > h || (cmp = strcmp((*e)->key, str)) >= 0) - break; - if(*e == nil || (*e)->hash > h || cmp > 0) - if(create) - insert(e, h, str); - } - return e; -} - -void** -map_get(Map *map, ulong val, bool create) { - MapEnt *e; - - e = *map_getp(map, val, create); - return e ? &e->val : nil; -} - -void** -hash_get(Map *map, const char *str, bool create) { - MapEnt *e; - - e = *hash_getp(map, str, create); - return e ? &e->val : nil; -} - -void* -map_rm(Map *map, ulong val) { - MapEnt **e, *te; - void *ret; - - ret = nil; - e = map_getp(map, val, 0); - if(*e) { - te = *e; - ret = te->val; - *e = te->next; - free(te); - } - return ret; -} - -void* -hash_rm(Map *map, const char *str) { - MapEnt **e, *te; - void *ret; - - ret = nil; - e = hash_getp(map, str, 0); - if(*e) { - te = *e; - ret = te->val; - *e = te->next; - free(te); - } - return ret; -} - diff --git a/cmd/wmii/message.c b/cmd/wmii/message.c @@ -231,97 +231,6 @@ msg_getword(IxpMsg *m) { return ret; } -#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1)) -static int -getbase(const char **s, long *sign) { - const char *p; - int ret; - - ret = 10; - *sign = 1; - if(**s == '-') { - *sign = -1; - *s += 1; - }else if(**s == '+') - *s += 1; - - p = *s; - if(!strbcmp(p, "0x")) { - *s += 2; - ret = 16; - } - else if(isdigit(p[0])) { - if(p[1] == 'r') { - *s += 2; - ret = p[0] - '0'; - } - else if(isdigit(p[1]) && p[2] == 'r') { - *s += 3; - ret = 10*(p[0]-'0') + (p[1]-'0'); - } - } - else if(p[0] == '0') { - ret = 8; - } - if(ret != 10 && (**s == '-' || **s == '+')) - *sign = 0; - return ret; -} - -static bool -getint(const char *s, int *ret) { - long l; - bool res; - - res = getlong(s, &l); - *ret = l; - return res; -} - -bool -getlong(const char *s, long *ret) { - const char *end; - char *rend; - int base; - long sign; - - if(s == nil) - return false; - end = s+strlen(s); - base = getbase(&s, &sign); - if(sign == 0) - return false; - - *ret = sign * strtol(s, &rend, base); - return (end == rend); -} - -bool -getulong(const char *s, ulong *ret) { - const char *end; - char *rend; - int base; - long sign; - - if(s == nil) - return false; - end = s+strlen(s); - base = getbase(&s, &sign); - if(sign < 1) - return false; - - *ret = strtoul(s, &rend, base); - return (end == rend); -} - -static char* -strend(char *s, int n) { - int len; - - len = strlen(s); - return s + max(0, len - n); -} - static Client* strclient(View *v, char *s) { ulong id; diff --git a/cmd/wmii/mouse.c b/cmd/wmii/mouse.c @@ -13,6 +13,21 @@ enum { ButtonMask | PointerMotionMask }; +static Cursor +quad_cursor(Align align) { + switch(align) { + case NEast: return cursor[CurNECorner]; + case NWest: return cursor[CurNWCorner]; + case SEast: return cursor[CurSECorner]; + case SWest: return cursor[CurSWCorner]; + case South: + case North: return cursor[CurDVArrow]; + case East: + case West: return cursor[CurDHArrow]; + default: return cursor[CurMove]; + } +} + static void cwin_expose(Window *w, XExposeEvent *e) { @@ -176,7 +191,7 @@ readmouse(Point *p, uint *button) { case Expose: case NoExpose: case PropertyNotify: - dispatch_event(&ev); + event_dispatch(&ev); default: Dprint(DEvent, "readmouse(): ignored: %E\n", &ev); continue; @@ -428,7 +443,7 @@ mouse_resize(Client *c, Align align, bool grabmod) { warppointer(d); } sync(); - flushevents(PointerMotionMask, false); + event_flush(PointerMotionMask, false); while(readmotion(&d)) { if(align == Center) { diff --git a/cmd/wmii/printevent.c b/cmd/wmii/printevent.c @@ -1,994 +0,0 @@ -/* - * Original code posted to comp.sources.x - * Modifications by Russ Cox <rsc@swtch.com>. - * Further modifications by Kris Maglione <maglione.k at Gmail> - */ - -/* - * Path: uunet!wyse!mikew From: mikew@wyse.wyse.com (Mike Wexler) Newsgroups: - * comp.sources.x Subject: v02i056: subroutine to print events in human - * readable form, Part01/01 Message-ID: <1935@wyse.wyse.com> Date: 22 Dec 88 - * 19:28:25 GMT Organization: Wyse Technology, San Jose Lines: 1093 Approved: - * mikew@wyse.com - * - * Submitted-by: richsun!darkstar!ken Posting-number: Volume 2, Issue 56 - * Archive-name: showevent/part01 - * - * - * There are times during debugging when it would be real useful to be able to - * print the fields of an event in a human readable form. Too many times I - * found myself scrounging around in section 8 of the Xlib manual looking for - * the valid fields for the events I wanted to see, then adding printf's to - * display the numeric values of the fields, and then scanning through X.h - * trying to decode the cryptic detail and state fields. After playing with - * xev, I decided to write a couple of standard functions that I could keep - * in a library and call on whenever I needed a little debugging verbosity. - * The first function, GetType(), is useful for returning the string - * representation of the type of an event. The second function, ShowEvent(), - * is used to display all the fields of an event in a readable format. The - * functions are not complicated, in fact, they are mind-numbingly boring - - * but that's just the point nobody wants to spend the time writing functions - * like this, they just want to have them when they need them. - * - * A simple, sample program is included which does little else but to - * demonstrate the use of these two functions. These functions have saved me - * many an hour during debugging and I hope you find some benefit to these. - * If you have any comments, suggestions, improvements, or if you find any - * blithering errors you can get it touch with me at the following location: - * - * ken@richsun.UUCP - */ - -#include "dat.h" -#include <stdarg.h> -#include <bio.h> -//#include "fns.h" -#include "printevent.h" -#define Window XWindow - -#define nil ((void*)0) - -typedef struct Pair Pair; - -struct Pair { - int key; - char *val; -}; - -static char* sep = " "; - -static char * -search(Pair *lst, int key, char *(*def)(int)) { - for(; lst->val; lst++) - if(lst->key == key) - return lst->val; - return def(key); -} - -static char* -unmask(Pair *list, uint val) -{ - Pair *p; - char *s, *end; - int n; - - buffer[0] = '\0'; - end = buffer + sizeof buffer; - s = buffer; - - n = 0; - s = utfecpy(s, end, "("); - for (p = list; p->val; p++) - if (val & p->key) { - if(n++) - s = utfecpy(s, end, "|"); - s = utfecpy(s, end, p->val); - } - utfecpy(s, end, ")"); - - return buffer; -} - -static char * -strhex(int key) { - sprint(buffer, "0x%x", key); - return buffer; -} - -static char * -strdec(int key) { - sprint(buffer, "%d", key); - return buffer; -} - -static char * -strign(int key) { - USED(key); - - return "?"; -} - -/******************************************************************************/ -/**** Miscellaneous routines to convert values to their string equivalents ****/ -/******************************************************************************/ - -static void -TInt(Fmt *b, va_list *ap) { - fmtprint(b, "%d", va_arg(*ap, int)); -} - -static void -TWindow(Fmt *b, va_list *ap) { - Window w; - - w = va_arg(*ap, Window); - fmtprint(b, "0x%ux", (uint)w); -} - -static void -TData(Fmt *b, va_list *ap) { - long *l; - int i; - - l = va_arg(*ap, long*); - fmtprint(b, "{"); - for (i = 0; i < 5; i++) { - if(i > 0) - fmtprint(b, ", "); - fmtprint(b, "0x%08lx", l[i]); - } - fmtprint(b, "}"); -} - -/* Returns the string equivalent of a timestamp */ -static void -TTime(Fmt *b, va_list *ap) { - ldiv_t d; - ulong msec; - ulong sec; - ulong min; - ulong hr; - ulong day; - Time time; - - time = va_arg(*ap, Time); - - msec = time/1000; - d = ldiv(msec, 60); - msec = time-msec*1000; - - sec = d.rem; - d = ldiv(d.quot, 60); - min = d.rem; - d = ldiv(d.quot, 24); - hr = d.rem; - day = d.quot; - -#ifdef notdef - sprintf(buffer, "%lu day%s %02lu:%02lu:%02lu.%03lu", - day, day == 1 ? "" : "(s)", hr, min, sec, msec); -#endif - - fmtprint(b, "%ludd_%ludh_%ludm_%lud.%03luds", day, hr, min, sec, msec); -} - -/* Returns the string equivalent of a boolean parameter */ -static void -TBool(Fmt *b, va_list *ap) { - static Pair list[] = { - {True, "True"}, - {False, "False"}, - {0, nil}, - }; - Bool key; - - key = va_arg(*ap, Bool); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a property notify state */ -static void -TPropState(Fmt *b, va_list *ap) { - static Pair list[] = { - {PropertyNewValue, "PropertyNewValue"}, - {PropertyDelete, "PropertyDelete"}, - {0, nil}, - }; - uint key; - - key = va_arg(*ap, uint); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a visibility notify state */ -static void -TVis(Fmt *b, va_list *ap) { - static Pair list[] = { - {VisibilityUnobscured, "VisibilityUnobscured"}, - {VisibilityPartiallyObscured, "VisibilityPartiallyObscured"}, - {VisibilityFullyObscured, "VisibilityFullyObscured"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a mask of buttons and/or modifier keys */ -static void -TModState(Fmt *b, va_list *ap) { - static Pair list[] = { - {Button1Mask, "Button1Mask"}, - {Button2Mask, "Button2Mask"}, - {Button3Mask, "Button3Mask"}, - {Button4Mask, "Button4Mask"}, - {Button5Mask, "Button5Mask"}, - {ShiftMask, "ShiftMask"}, - {LockMask, "LockMask"}, - {ControlMask, "ControlMask"}, - {Mod1Mask, "Mod1Mask"}, - {Mod2Mask, "Mod2Mask"}, - {Mod3Mask, "Mod3Mask"}, - {Mod4Mask, "Mod4Mask"}, - {Mod5Mask, "Mod5Mask"}, - {0, nil}, - }; - uint state; - - state = va_arg(*ap, uint); - fmtprint(b, "%s", unmask(list, state)); -} - -/* Returns the string equivalent of a mask of configure window values */ -static void -TConfMask(Fmt *b, va_list *ap) { - static Pair list[] = { - {CWX, "CWX"}, - {CWY, "CWY"}, - {CWWidth, "CWWidth"}, - {CWHeight, "CWHeight"}, - {CWBorderWidth, "CWBorderWidth"}, - {CWSibling, "CWSibling"}, - {CWStackMode, "CWStackMode"}, - {0, nil}, - }; - uint valuemask; - - valuemask = va_arg(*ap, uint); - fmtprint(b, "%s", unmask(list, valuemask)); -} - -/* Returns the string equivalent of a motion hint */ -#if 0 -static void -IsHint(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyNormal, "NotifyNormal"}, - {NotifyHint, "NotifyHint"}, - {0, nil}, - }; - char key; - - key = va_arg(*ap, char); - fmtprint(b, "%s", search(list, key, strign)); -} -#endif - -/* Returns the string equivalent of an id or the value "None" */ -static void -TIntNone(Fmt *b, va_list *ap) { - static Pair list[] = { - {None, "None"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strhex)); -} - -/* Returns the string equivalent of a colormap state */ -static void -TColMap(Fmt *b, va_list *ap) { - static Pair list[] = { - {ColormapInstalled, "ColormapInstalled"}, - {ColormapUninstalled, "ColormapUninstalled"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a crossing detail */ -static void -TXing(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyAncestor, "NotifyAncestor"}, - {NotifyInferior, "NotifyInferior"}, - {NotifyVirtual, "NotifyVirtual"}, - {NotifyNonlinear, "NotifyNonlinear"}, - {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a focus change detail */ -static void -TFocus(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyAncestor, "NotifyAncestor"}, - {NotifyInferior, "NotifyInferior"}, - {NotifyVirtual, "NotifyVirtual"}, - {NotifyNonlinear, "NotifyNonlinear"}, - {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, - {NotifyPointer, "NotifyPointer"}, - {NotifyPointerRoot, "NotifyPointerRoot"}, - {NotifyDetailNone, "NotifyDetailNone"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a configure detail */ -static void -TConfDetail(Fmt *b, va_list *ap) { - static Pair list[] = { - {Above, "Above"}, - {Below, "Below"}, - {TopIf, "TopIf"}, - {BottomIf, "BottomIf"}, - {Opposite, "Opposite"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a grab mode */ -static void -TGrabMode(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyNormal, "NotifyNormal"}, - {NotifyGrab, "NotifyGrab"}, - {NotifyUngrab, "NotifyUngrab"}, - {NotifyWhileGrabbed, "NotifyWhileGrabbed"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a mapping request */ -static void -TMapping(Fmt *b, va_list *ap) { - static Pair list[] = { - {MappingModifier, "MappingModifier"}, - {MappingKeyboard, "MappingKeyboard"}, - {MappingPointer, "MappingPointer"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a stacking order place */ -static void -TPlace(Fmt *b, va_list *ap) { - static Pair list[] = { - {PlaceOnTop, "PlaceOnTop"}, - {PlaceOnBottom, "PlaceOnBottom"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a major code */ -static void -TMajor(Fmt *b, va_list *ap) { - static char *list[] = { XMajors }; - char *s; - uint key; - - key = va_arg(*ap, uint); - s = "<nil>"; - if(key < nelem(list)) - s = list[key]; - fmtprint(b, "%s", s); -} - -static char* -eventtype(int key) { - static Pair list[] = { - {ButtonPress, "ButtonPress"}, - {ButtonRelease, "ButtonRelease"}, - {CirculateNotify, "CirculateNotify"}, - {CirculateRequest, "CirculateRequest"}, - {ClientMessage, "ClientMessage"}, - {ColormapNotify, "ColormapNotify"}, - {ConfigureNotify, "ConfigureNotify"}, - {ConfigureRequest, "ConfigureRequest"}, - {CreateNotify, "CreateNotify"}, - {DestroyNotify, "DestroyNotify"}, - {EnterNotify, "EnterNotify"}, - {Expose, "Expose"}, - {FocusIn, "FocusIn"}, - {FocusOut, "FocusOut"}, - {GraphicsExpose, "GraphicsExpose"}, - {GravityNotify, "GravityNotify"}, - {KeyPress, "KeyPress"}, - {KeyRelease, "KeyRelease"}, - {KeymapNotify, "KeymapNotify"}, - {LeaveNotify, "LeaveNotify"}, - {MapNotify, "MapNotify"}, - {MapRequest, "MapRequest"}, - {MappingNotify, "MappingNotify"}, - {MotionNotify, "MotionNotify"}, - {NoExpose, "NoExpose"}, - {PropertyNotify, "PropertyNotify"}, - {ReparentNotify, "ReparentNotify"}, - {ResizeRequest, "ResizeRequest"}, - {SelectionClear, "SelectionClear"}, - {SelectionNotify, "SelectionNotify"}, - {SelectionRequest, "SelectionRequest"}, - {UnmapNotify, "UnmapNotify"}, - {VisibilityNotify, "VisibilityNotify"}, - {0, nil}, - }; - return search(list, key, strdec); -} -/* Returns the string equivalent the keycode contained in the key event */ -static void -TKeycode(Fmt *b, va_list *ap) { - KeySym keysym_str; - XKeyEvent *ev; - char *keysym_name; - - ev = va_arg(*ap, XKeyEvent*); - - XLookupString(ev, buffer, sizeof buffer, &keysym_str, nil); - - if (keysym_str == NoSymbol) - keysym_name = "NoSymbol"; - else - keysym_name = XKeysymToString(keysym_str); - if(keysym_name == nil) - keysym_name = "(no name)"; - - fmtprint(b, "%ud (keysym 0x%x \"%s\")", (int)ev->keycode, - (int)keysym_str, keysym_name); -} - -/* Returns the string equivalent of an atom or "None" */ -static void -TAtom(Fmt *b, va_list *ap) { - char *atom_name; - Atom atom; - - atom = va_arg(*ap, Atom); - atom_name = XGetAtomName(display, atom); - fmtprint(b, "%s", atom_name); - XFree(atom_name); -} - -#define _(m) #m, ev->m -#define TEnd nil -typedef void (*Tfn)(Fmt*, va_list*); - -static int -pevent(Fmt *fmt, void *e, ...) { - va_list ap; - Tfn fn; - XAnyEvent *ev; - char *key; - int n; - - ev = e; - fmtprint(fmt, "%3ld %-20s ", ev->serial, eventtype(ev->type)); - if(ev->send_event) - fmtstrcpy(fmt, "(sendevent) "); - - n = 0; - va_start(ap, e); - for(;;) { - fn = va_arg(ap, Tfn); - if(fn == TEnd) - break; - - if(n++ != 0) - fmtprint(fmt, "%s", sep); - - key = va_arg(ap, char*); - fmtprint(fmt, "%s=", key); - fn(fmt, &ap); - } - va_end(ap); - return 0; -} - -/*****************************************************************************/ -/*** Routines to print out readable values for the field of various events ***/ -/*****************************************************************************/ - -static int -VerbMotion(Fmt *fmt, XEvent *e) { - XMotionEvent *ev = &e->xmotion; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TModState, _(state), - TBool, _(same_screen), - TEnd - ); - //fprintf(stderr, "is_hint=%s%s", IsHint(ev->is_hint), sep); -} - -static int -VerbButton(Fmt *fmt, XEvent *e) { - XButtonEvent *ev = &e->xbutton; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TModState, _(state), - TModState, _(button), - TBool, _(same_screen), - TEnd - ); -} - -static int -VerbColormap(Fmt *fmt, XEvent *e) { - XColormapEvent *ev = &e->xcolormap; - - return pevent(fmt, ev, - TWindow, _(window), - TIntNone, _(colormap), - TBool, _(new), - TColMap, _(state), - TEnd - ); -} - -static int -VerbCrossing(Fmt *fmt, XEvent *e) { - XCrossingEvent *ev = &e->xcrossing; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TGrabMode, _(mode), - TXing, _(detail), - TBool, _(same_screen), - TBool, _(focus), - TModState, _(state), - TEnd - ); -} - -static int -VerbExpose(Fmt *fmt, XEvent *e) { - XExposeEvent *ev = &e->xexpose; - - return pevent(fmt, ev, - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(count), - TEnd - ); -} - -static int -VerbGraphicsExpose(Fmt *fmt, XEvent *e) { - XGraphicsExposeEvent *ev = &e->xgraphicsexpose; - - return pevent(fmt, ev, - TWindow, _(drawable), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TMajor, _(major_code), - TInt, _(minor_code), - TEnd - ); -} - -static int -VerbNoExpose(Fmt *fmt, XEvent *e) { - XNoExposeEvent *ev = &e->xnoexpose; - - return pevent(fmt, ev, - TWindow, _(drawable), - TMajor, _(major_code), - TInt, _(minor_code), - TEnd - ); -} - -static int -VerbFocus(Fmt *fmt, XEvent *e) { - XFocusChangeEvent *ev = &e->xfocus; - - return pevent(fmt, ev, - TWindow, _(window), - TGrabMode, _(mode), - TFocus, _(detail), - TEnd - ); -} - -static int -VerbKeymap(Fmt *fmt, XEvent *e) { - XKeymapEvent *ev = &e->xkeymap; - int i; - - fmtprint(fmt, "window=0x%x%s", (int)ev->window, sep); - fmtprint(fmt, "key_vector="); - for (i = 0; i < 32; i++) - fmtprint(fmt, "%02x", ev->key_vector[i]); - fmtprint(fmt, "\n"); - return 0; -} - -static int -VerbKey(Fmt *fmt, XEvent *e) { - XKeyEvent *ev = &e->xkey; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TModState, _(state), - TKeycode, "keycode", ev, - TBool, _(same_screen), - TEnd - ); -} - -static int -VerbProperty(Fmt *fmt, XEvent *e) { - XPropertyEvent *ev = &e->xproperty; - - return pevent(fmt, ev, - TWindow, _(window), - TAtom, _(atom), - TTime, _(time), - TPropState, _(state), - TEnd - ); -} - -static int -VerbResizeRequest(Fmt *fmt, XEvent *e) { - XResizeRequestEvent *ev = &e->xresizerequest; - - return pevent(fmt, ev, - TWindow, _(window), - TInt, _(width), TInt, _(height), - TEnd - ); -} - -static int -VerbCirculate(Fmt *fmt, XEvent *e) { - XCirculateEvent *ev = &e->xcirculate; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TPlace, _(place), - TEnd - ); -} - -static int -VerbConfigure(Fmt *fmt, XEvent *e) { - XConfigureEvent *ev = &e->xconfigure; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(border_width), - TIntNone, _(above), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbCreateWindow(Fmt *fmt, XEvent *e) { - XCreateWindowEvent *ev = &e->xcreatewindow; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(border_width), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbDestroyWindow(Fmt *fmt, XEvent *e) { - XDestroyWindowEvent *ev = &e->xdestroywindow; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TEnd - ); -} - -static int -VerbGravity(Fmt *fmt, XEvent *e) { - XGravityEvent *ev = &e->xgravity; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TEnd - ); -} - -static int -VerbMap(Fmt *fmt, XEvent *e) { - XMapEvent *ev = &e->xmap; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbReparent(Fmt *fmt, XEvent *e) { - XReparentEvent *ev = &e->xreparent; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TWindow, _(parent), - TInt, _(x), TInt, _(y), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbUnmap(Fmt *fmt, XEvent *e) { - XUnmapEvent *ev = &e->xunmap; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TBool, _(from_configure), - TEnd - ); -} - -static int -VerbCirculateRequest(Fmt *fmt, XEvent *e) { - XCirculateRequestEvent *ev = &e->xcirculaterequest; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TPlace, _(place), - TEnd - ); -} - -static int -VerbConfigureRequest(Fmt *fmt, XEvent *e) { - XConfigureRequestEvent *ev = &e->xconfigurerequest; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(border_width), - TIntNone, _(above), - TConfDetail, _(detail), - TConfMask, _(value_mask), - TEnd - ); -} - -static int -VerbMapRequest(Fmt *fmt, XEvent *e) { - XMapRequestEvent *ev = &e->xmaprequest; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TEnd - ); -} - -static int -VerbClient(Fmt *fmt, XEvent *e) { - XClientMessageEvent *ev = &e->xclient; - - return pevent(fmt, ev, - TWindow, _(window), - TAtom, _(message_type), - TInt, _(format), - TData, "data (as longs)", &ev->data, - TEnd - ); -} - -static int -VerbMapping(Fmt *fmt, XEvent *e) { - XMappingEvent *ev = &e->xmapping; - - return pevent(fmt, ev, - TWindow, _(window), - TMapping, _(request), - TWindow, _(first_keycode), - TWindow, _(count), - TEnd - ); -} - -static int -VerbSelectionClear(Fmt *fmt, XEvent *e) { - XSelectionClearEvent *ev = &e->xselectionclear; - - return pevent(fmt, ev, - TWindow, _(window), - TAtom, _(selection), - TTime, _(time), - TEnd - ); -} - -static int -VerbSelection(Fmt *fmt, XEvent *e) { - XSelectionEvent *ev = &e->xselection; - - return pevent(fmt, ev, - TWindow, _(requestor), - TAtom, _(selection), - TAtom, _(target), - TAtom, _(property), - TTime, _(time), - TEnd - ); -} - -static int -VerbSelectionRequest(Fmt *fmt, XEvent *e) { - XSelectionRequestEvent *ev = &e->xselectionrequest; - - return pevent(fmt, ev, - TWindow, _(owner), - TWindow, _(requestor), - TAtom, _(selection), - TAtom, _(target), - TAtom, _(property), - TTime, _(time), - TEnd - ); -} - -static int -VerbVisibility(Fmt *fmt, XEvent *e) { - XVisibilityEvent *ev = &e->xvisibility; - - return pevent(fmt, ev, - TWindow, _(window), - TVis, _(state), - TEnd - ); -} - -/******************************************************************************/ -/**************** Print the values of all fields for any event ****************/ -/******************************************************************************/ - -typedef struct Handler Handler; -struct Handler { - int key; - int (*fn)(Fmt*, XEvent*); -}; - -int -fmtevent(Fmt *fmt) { - XEvent *e; - XAnyEvent *ev; - /* - fprintf(stderr, "type=%s%s", eventtype(e->xany.type), sep); - fprintf(stderr, "serial=%lu%s", ev->serial, sep); - fprintf(stderr, "send_event=%s%s", TorF(ev->send_event), sep); - fprintf(stderr, "display=0x%p%s", ev->display, sep); - */ - static Handler fns[] = { - {MotionNotify, VerbMotion}, - {ButtonPress, VerbButton}, - {ButtonRelease, VerbButton}, - {ColormapNotify, VerbColormap}, - {EnterNotify, VerbCrossing}, - {LeaveNotify, VerbCrossing}, - {Expose, VerbExpose}, - {GraphicsExpose, VerbGraphicsExpose}, - {NoExpose, VerbNoExpose}, - {FocusIn, VerbFocus}, - {FocusOut, VerbFocus}, - {KeymapNotify, VerbKeymap}, - {KeyPress, VerbKey}, - {KeyRelease, VerbKey}, - {PropertyNotify, VerbProperty}, - {ResizeRequest, VerbResizeRequest}, - {CirculateNotify, VerbCirculate}, - {ConfigureNotify, VerbConfigure}, - {CreateNotify, VerbCreateWindow}, - {DestroyNotify, VerbDestroyWindow}, - {GravityNotify, VerbGravity}, - {MapNotify, VerbMap}, - {ReparentNotify, VerbReparent}, - {UnmapNotify, VerbUnmap}, - {CirculateRequest, VerbCirculateRequest}, - {ConfigureRequest, VerbConfigureRequest}, - {MapRequest, VerbMapRequest}, - {ClientMessage, VerbClient}, - {MappingNotify, VerbMapping}, - {SelectionClear, VerbSelectionClear}, - {SelectionNotify, VerbSelection}, - {SelectionRequest, VerbSelectionRequest}, - {VisibilityNotify, VerbVisibility}, - {0, nil}, - }; - Handler *p; - - e = va_arg(fmt->args, XEvent*); - ev = &e->xany; - - for (p = fns; p->fn; p++) - if (p->key == ev->type) - return p->fn(fmt, e); - return 1; -} - diff --git a/cmd/wmii/printevent.h b/cmd/wmii/printevent.h @@ -1,248 +0,0 @@ -int fmtevent(Fmt *fmt); - -enum { - X_CreateWindow = 1, - X_ChangeWindowAttributes, - X_GetWindowAttributes, - X_DestroyWindow, - X_DestroySubwindows, - X_ChangeSaveSet, - X_ReparentWindow, - X_MapWindow, - X_MapSubwindows, - X_UnmapWindow, - X_UnmapSubwindows, - X_ConfigureWindow, - X_CirculateWindow, - X_GetGeometry, - X_QueryTree, - X_InternAtom, - X_GetAtomName, - X_ChangeProperty, - X_DeleteProperty, - X_GetProperty, - X_ListProperties, - X_SetSelectionOwner, - X_GetSelectionOwner, - X_ConvertSelection, - X_SendEvent, - X_GrabPointer, - X_UngrabPointer, - X_GrabButton, - X_UngrabButton, - X_ChangeActivePointerGrab, - X_GrabKeyboard, - X_UngrabKeyboard, - X_GrabKey, - X_UngrabKey, - X_AllowEvents, - X_GrabServer, - X_UngrabServer, - X_QueryPointer, - X_GetMotionEvents, - X_TranslateCoords, - X_WarpPointer, - X_SetInputFocus, - X_GetInputFocus, - X_QueryKeymap, - X_OpenFont, - X_CloseFont, - X_QueryFont, - X_QueryTextExtents, - X_ListFonts, - X_ListFontsWithInfo, - X_SetFontPath, - X_GetFontPath, - X_CreatePixmap, - X_FreePixmap, - X_CreateGC, - X_ChangeGC, - X_CopyGC, - X_SetDashes, - X_SetClipRectangles, - X_FreeGC, - X_ClearArea, - X_CopyArea, - X_CopyPlane, - X_PolyPoint, - X_PolyLine, - X_PolySegment, - X_PolyRectangle, - X_PolyArc, - X_FillPoly, - X_PolyFillRectangle, - X_PolyFillArc, - X_PutImage, - X_GetImage, - X_PolyText8, - X_PolyText16, - X_ImageText8, - X_ImageText16, - X_CreateColormap, - X_FreeColormap, - X_CopyColormapAndFree, - X_InstallColormap, - X_UninstallColormap, - X_ListInstalledColormaps, - X_AllocColor, - X_AllocNamedColor, - X_AllocColorCells, - X_AllocColorPlanes, - X_FreeColors, - X_StoreColors, - X_StoreNamedColor, - X_QueryColors, - X_LookupColor, - X_CreateCursor, - X_CreateGlyphCursor, - X_FreeCursor, - X_RecolorCursor, - X_QueryBestSize, - X_QueryExtension, - X_ListExtensions, - X_ChangeKeyboardMapping, - X_GetKeyboardMapping, - X_ChangeKeyboardControl, - X_GetKeyboardControl, - X_Bell, - X_ChangePointerControl, - X_GetPointerControl, - X_SetScreenSaver, - X_GetScreenSaver, - X_ChangeHosts, - X_ListHosts, - X_SetAccessControl, - X_SetCloseDownMode, - X_KillClient, - X_RotateProperties, - X_ForceScreenSaver, - X_SetPointerMapping, - X_GetPointerMapping, - X_SetModifierMapping, - X_GetModifierMapping, - X_NoOperation, -}; - -#define XMajors \ - "<nil>",\ - "CreateWindow",\ - "ChangeWindowAttributes",\ - "GetWindowAttributes",\ - "DestroyWindow",\ - "DestroySubwindows",\ - "ChangeSaveSet",\ - "ReparentWindow",\ - "MapWindow",\ - "MapSubwindows",\ - "UnmapWindow",\ - "UnmapSubwindows",\ - "ConfigureWindow",\ - "CirculateWindow",\ - "GetGeometry",\ - "QueryTree",\ - "InternAtom",\ - "GetAtomName",\ - "ChangeProperty",\ - "DeleteProperty",\ - "GetProperty",\ - "ListProperties",\ - "SetSelectionOwner",\ - "GetSelectionOwner",\ - "ConvertSelection",\ - "SendEvent",\ - "GrabPointer",\ - "UngrabPointer",\ - "GrabButton",\ - "UngrabButton",\ - "ChangeActivePointerGrab",\ - "GrabKeyboard",\ - "UngrabKeyboard",\ - "GrabKey",\ - "UngrabKey",\ - "AllowEvents",\ - "GrabServer",\ - "UngrabServer",\ - "QueryPointer",\ - "GetMotionEvents",\ - "TranslateCoords",\ - "WarpPointer",\ - "SetInputFocus",\ - "GetInputFocus",\ - "QueryKeymap",\ - "OpenFont",\ - "CloseFont",\ - "QueryFont",\ - "QueryTextExtents",\ - "ListFonts",\ - "ListFontsWithInfo",\ - "SetFontPath",\ - "GetFontPath",\ - "CreatePixmap",\ - "FreePixmap",\ - "CreateGC",\ - "ChangeGC",\ - "CopyGC",\ - "SetDashes",\ - "SetClipRectangles",\ - "FreeGC",\ - "ClearArea",\ - "CopyArea",\ - "CopyPlane",\ - "PolyPoint",\ - "PolyLine",\ - "PolySegment",\ - "PolyRectangle",\ - "PolyArc",\ - "FillPoly",\ - "PolyFillRectangle",\ - "PolyFillArc",\ - "PutImage",\ - "GetImage",\ - "PolyText8",\ - "PolyText16",\ - "ImageText8",\ - "ImageText16",\ - "CreateColormap",\ - "FreeColormap",\ - "CopyColormapAndFree",\ - "InstallColormap",\ - "UninstallColormap",\ - "ListInstalledColormaps",\ - "AllocColor",\ - "AllocNamedColor",\ - "AllocColorCells",\ - "AllocColorPlanes",\ - "FreeColors",\ - "StoreColors",\ - "StoreNamedColor",\ - "QueryColors",\ - "LookupColor",\ - "CreateCursor",\ - "CreateGlyphCursor",\ - "FreeCursor",\ - "RecolorCursor",\ - "QueryBestSize",\ - "QueryExtension",\ - "ListExtensions",\ - "ChangeKeyboardMapping",\ - "GetKeyboardMapping",\ - "ChangeKeyboardControl",\ - "GetKeyboardControl",\ - "Bell",\ - "ChangePointerControl",\ - "GetPointerControl",\ - "SetScreenSaver",\ - "GetScreenSaver",\ - "ChangeHosts",\ - "ListHosts",\ - "SetAccessControl",\ - "SetCloseDownMode",\ - "KillClient",\ - "RotateProperties",\ - "ForceScreenSaver",\ - "SetPointerMapping",\ - "GetPointerMapping",\ - "SetModifierMapping",\ - "GetModifierMapping",\ - "NoOperation",\ - diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c @@ -1,1317 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#define _X11_VISIBLE -#define pointerwin __pointerwin -#include "dat.h" -#include <limits.h> -#include <math.h> -#include <strings.h> -#include <unistd.h> -#include <bio.h> -#include "fns.h" -#undef pointerwin - -const Point ZP = {0, 0}; -const Rectangle ZR = {{0, 0}, {0, 0}}; - -const Window _pointerwin = { .xid = PointerRoot }; -Window* const pointerwin = (Window*)&_pointerwin; - -static Map windowmap; -static Map atommap; -static MapEnt* wbucket[137]; -static MapEnt* abucket[137]; - -static int errorhandler(Display*, XErrorEvent*); -static int (*xlib_errorhandler) (Display*, XErrorEvent*); - -static XftColor* xftcolor(Color); - - -/* Rectangles/Points */ -XRectangle -XRect(Rectangle r) { - XRectangle xr; - - xr.x = r.min.x; - xr.y = r.min.y; - xr.width = Dx(r); - xr.height = Dy(r); - return xr; -} - -int -eqrect(Rectangle a, Rectangle b) { - return a.min.x==b.min.x && a.max.x==b.max.x - && a.min.y==b.min.y && a.max.y==b.max.y; -} - -int -eqpt(Point p, Point q) { - return p.x==q.x && p.y==q.y; -} - -Point -addpt(Point p, Point q) { - p.x += q.x; - p.y += q.y; - return p; -} - -Point -subpt(Point p, Point q) { - p.x -= q.x; - p.y -= q.y; - return p; -} - -Point -mulpt(Point p, Point q) { - p.x *= q.x; - p.y *= q.y; - return p; -} - -Point -divpt(Point p, Point q) { - p.x /= q.x; - p.y /= q.y; - return p; -} - -Rectangle -insetrect(Rectangle r, int n) { - r.min.x += n; - r.min.y += n; - r.max.x -= n; - r.max.y -= n; - return r; -} - -Rectangle -rectaddpt(Rectangle r, Point p) { - r.min.x += p.x; - r.max.x += p.x; - r.min.y += p.y; - r.max.y += p.y; - return r; -} - -Rectangle -rectsubpt(Rectangle r, Point p) { - r.min.x -= p.x; - r.max.x -= p.x; - r.min.y -= p.y; - r.max.y -= p.y; - return r; -} - -Rectangle -rectsetorigin(Rectangle r, Point p) { - Rectangle ret; - - ret.min.x = p.x; - ret.min.y = p.y; - ret.max.x = p.x + Dx(r); - ret.max.y = p.y + Dy(r); - return ret; -} - -/* Formatters */ -static int -Afmt(Fmt *f) { - Atom a; - char *s; - int i; - - a = va_arg(f->args, Atom); - s = XGetAtomName(display, a); - i = fmtprint(f, "%s", s); - free(s); - return i; -} - -static int -Rfmt(Fmt *f) { - Rectangle r; - - r = va_arg(f->args, Rectangle); - return fmtprint(f, "%P+%dx%d", r.min, Dx(r), Dy(r)); -} - -static int -Pfmt(Fmt *f) { - Point p; - - p = va_arg(f->args, Point); - return fmtprint(f, "(%d,%d)", p.x, p.y); -} - -static int -Wfmt(Fmt *f) { - Window *w; - - w = va_arg(f->args, Window*); - return fmtprint(f, "0x%ulx", w->xid); -} - -/* Init */ -void -initdisplay(void) { - display = XOpenDisplay(nil); - if(display == nil) - fatal("Can't open display"); - scr.screen = DefaultScreen(display); - scr.colormap = DefaultColormap(display, scr.screen); - scr.visual = DefaultVisual(display, scr.screen); - scr.visual32 = DefaultVisual(display, scr.screen); - scr.gc = DefaultGC(display, scr.screen); - scr.depth = DefaultDepth(display, scr.screen); - - scr.white = WhitePixel(display, scr.screen); - scr.black = BlackPixel(display, scr.screen); - - scr.root.xid = RootWindow(display, scr.screen); - scr.root.r = Rect(0, 0, - DisplayWidth(display, scr.screen), - DisplayHeight(display, scr.screen)); - scr.rect = scr.root.r; - - scr.root.parent = &scr.root; - - windowmap.bucket = wbucket; - windowmap.nhash = nelem(wbucket); - atommap.bucket = abucket; - atommap.nhash = nelem(abucket); - - fmtinstall('A', Afmt); - fmtinstall('R', Rfmt); - fmtinstall('P', Pfmt); - fmtinstall('W', Wfmt); - - xlib_errorhandler = XSetErrorHandler(errorhandler); -} - -/* Error handling */ - -extern ErrorCode ignored_xerrors[]; -static bool _trap_errors; -static long nerrors; - -static int -errorhandler(Display *dpy, XErrorEvent *error) { - ErrorCode *e; - - USED(dpy); - - if(_trap_errors) - nerrors++; - - e = ignored_xerrors; - if(e) - for(; e->rcode || e->ecode; e++) - if((e->rcode == 0 || e->rcode == error->request_code) - && (e->ecode == 0 || e->ecode == error->error_code)) - return 0; - - fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n", - argv0, error->request_code, error->error_code); - return xlib_errorhandler(display, error); /* calls exit() */ -} - -int -traperrors(bool enable) { - - sync(); - _trap_errors = enable; - if (enable) - nerrors = 0; - return nerrors; - -} - -/* Images */ -Image* -allocimage(int w, int h, int depth) { - Image *img; - - img = emallocz(sizeof *img); - img->type = WImage; - img->xid = XCreatePixmap(display, scr.root.xid, w, h, depth); - img->gc = XCreateGC(display, img->xid, 0, nil); - img->colormap = scr.colormap; - img->visual = scr.visual; - if(depth == 32) - img->visual = scr.visual32; - img->depth = depth; - img->r = Rect(0, 0, w, h); - return img; -} - -void -freeimage(Image *img) { - if(img == nil) - return; - - assert(img->type == WImage); - - if(img->xft) - XftDrawDestroy(img->xft); - XFreePixmap(display, img->xid); - XFreeGC(display, img->gc); - free(img); -} - -static XftDraw* -xftdrawable(Image *img) { - if(img->xft == nil) - img->xft = XftDrawCreate(display, img->xid, img->visual, img->colormap); - return img->xft; -} - -/* Windows */ -Window* -createwindow_visual(Window *parent, Rectangle r, - int depth, Visual *vis, uint class, - WinAttr *wa, int valmask) { - Window *w; - - assert(parent->type == WWindow); - - w = emallocz(sizeof *w); - w->visual = vis; - w->type = WWindow; - w->parent = parent; - if(valmask & CWColormap) - w->colormap = wa->colormap; - - w->xid = XCreateWindow(display, parent->xid, r.min.x, r.min.y, Dx(r), Dy(r), - 0 /* border */, depth, class, vis, valmask, wa); -#if 0 - print("createwindow_visual(%W, %R, %d, %p, %ud, %p, %x) = %W\n", - parent, r, depth, vis, class, wa, valmask, w); -#endif - if(class != InputOnly) - w->gc = XCreateGC(display, w->xid, 0, nil); - - w->r = r; - w->depth = depth; - return w; -} - -Window* -createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, int valmask) { - return createwindow_visual(parent, r, depth, scr.visual, class, wa, valmask); -} - -Window* -window(XWindow xw) { - Window *w; - - w = malloc(sizeof *w); - w->type = WWindow; - w->xid = xw; - return freelater(w); -} - -void -reparentwindow(Window *w, Window *par, Point p) { - assert(w->type == WWindow); - XReparentWindow(display, w->xid, par->xid, p.x, p.y); - w->parent = par; - w->r = rectsubpt(w->r, w->r.min); - w->r = rectaddpt(w->r, p); -} - -void -destroywindow(Window *w) { - assert(w->type == WWindow); - sethandler(w, nil); - if(w->xft) - XftDrawDestroy(w->xft); - if(w->gc) - XFreeGC(display, w->gc); - XDestroyWindow(display, w->xid); - free(w); -} - -void -setwinattr(Window *w, WinAttr *wa, int valmask) { - assert(w->type == WWindow); - XChangeWindowAttributes(display, w->xid, valmask, wa); -} - -void -selectinput(Window *w, long mask) { - XSelectInput(display, w->xid, mask); -} - -static void -configwin(Window *w, Rectangle r, int border) { - XWindowChanges wc; - - if(eqrect(r, w->r) && border == w->border) - return; - - wc.x = r.min.x - border; - wc.y = r.min.y - border; - wc.width = Dx(r); - wc.height = Dy(r); - wc.border_width = border; - XConfigureWindow(display, w->xid, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - - w->r = r; - w->border = border; -} - -void -setborder(Window *w, int width, Color col) { - - assert(w->type == WWindow); - if(width) - XSetWindowBorder(display, w->xid, col.pixel); - if(width != w->border) - configwin(w, w->r, width); -} - -void -reshapewin(Window *w, Rectangle r) { - assert(w->type == WWindow); - assert(Dx(r) > 0 && Dy(r) > 0); /* Rather than an X error. */ - - configwin(w, r, w->border); -} - -void -movewin(Window *w, Point pt) { - Rectangle r; - - assert(w->type == WWindow); - r = rectsetorigin(w->r, pt); - reshapewin(w, r); -} - -int -mapwin(Window *w) { - assert(w->type == WWindow); - if(!w->mapped) { - XMapWindow(display, w->xid); - w->mapped = 1; - return 1; - } - return 0; -} - -int -unmapwin(Window *w) { - assert(w->type == WWindow); - if(w->mapped) { - XUnmapWindow(display, w->xid); - w->mapped = 0; - w->unmapped++; - return 1; - } - return 0; -} - -void -raisewin(Window *w) { - assert(w->type == WWindow); - XRaiseWindow(display, w->xid); -} - -void -lowerwin(Window *w) { - assert(w->type == WWindow); - XLowerWindow(display, w->xid); -} - -Handlers* -sethandler(Window *w, Handlers *new) { - Handlers *old; - void **e; - - assert(w->type == WWindow); - assert((w->prev != nil && w->next != nil) || w->next == w->prev); - - if(new == nil) - map_rm(&windowmap, (ulong)w->xid); - else { - e = map_get(&windowmap, (ulong)w->xid, true); - *e = w; - } - old = w->handler; - w->handler = new; - return old; -} - -Window* -findwin(XWindow w) { - void **e; - - e = map_get(&windowmap, (ulong)w, false); - if(e) - return *e; - return nil; -} - -/* Shape */ -void -setshapemask(Window *dst, Image *src, Point pt) { - /* Assumes that we have the shape extension... */ - XShapeCombineMask (display, dst->xid, - ShapeBounding, pt.x, pt.y, src->xid, ShapeSet); -} - -static void -setgccol(Image *dst, Color col) { - XSetForeground(display, dst->gc, col.pixel); -} - -/* Drawing */ -void -border(Image *dst, Rectangle r, int w, Color col) { - if(w == 0) - return; - - r = insetrect(r, w/2); - r.max.x -= w%2; - r.max.y -= w%2; - - XSetLineAttributes(display, dst->gc, w, LineSolid, CapButt, JoinMiter); - setgccol(dst, col); - XDrawRectangle(display, dst->xid, dst->gc, - r.min.x, r.min.y, Dx(r), Dy(r)); -} - -void -fill(Image *dst, Rectangle r, Color col) { - setgccol(dst, col); - XFillRectangle(display, dst->xid, dst->gc, - r.min.x, r.min.y, Dx(r), Dy(r)); -} - -static XPoint* -convpts(Point *pt, int np) { - XPoint *rp; - int i; - - rp = emalloc(np * sizeof *rp); - for(i = 0; i < np; i++) { - rp[i].x = pt[i].x; - rp[i].y = pt[i].y; - } - return rp; -} - -void -drawpoly(Image *dst, Point *pt, int np, int cap, int w, Color col) { - XPoint *xp; - - xp = convpts(pt, np); - XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); - setgccol(dst, col); - XDrawLines(display, dst->xid, dst->gc, xp, np, CoordModeOrigin); - free(xp); -} - -void -fillpoly(Image *dst, Point *pt, int np, Color col) { - XPoint *xp; - - xp = convpts(pt, np); - setgccol(dst, col); - XFillPolygon(display, dst->xid, dst->gc, xp, np, Complex, CoordModeOrigin); - free(xp); -} - -void -drawline(Image *dst, Point p1, Point p2, int cap, int w, Color col) { - XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); - setgccol(dst, col); - XDrawLine(display, dst->xid, dst->gc, p1.x, p1.y, p2.x, p2.y); -} - -uint -drawstring(Image *dst, Font *font, - Rectangle r, Align align, - char *text, Color col) { - Rectangle tr; - char *buf; - uint x, y, width, height, len; - int shortened; - - shortened = 0; - - len = strlen(text); - buf = emalloc(len+1); - memcpy(buf, text, len+1); - - r.max.y -= font->pad.min.y; - r.min.y += font->pad.max.y; - - height = font->ascent + font->descent; - y = r.min.y + Dy(r) / 2 - height / 2 + font->ascent; - - width = Dx(r) - font->pad.min.x - font->pad.max.x - (font->height & ~1); - - r.min.x += font->pad.min.x; - r.max.x -= font->pad.max.x; - - /* shorten text if necessary */ - tr = ZR; - while(len > 0) { - tr = textextents_l(font, buf, len + min(shortened, 3), nil); - if(Dx(tr) <= width) - break; - while(len > 0 && (buf[--len]&0xC0) == 0x80) - buf[len] = '.'; - buf[len] = '.'; - shortened++; - } - - if(len == 0 || Dx(tr) > width) - goto done; - - /* mark shortened info in the string */ - if(shortened) - len += min(shortened, 3); - - switch (align) { - case East: - x = r.max.x - (tr.max.x + (font->height / 2)); - break; - case Center: - x = r.min.x + (Dx(r) - Dx(tr)) / 2 - tr.min.x; - break; - default: - x = r.min.x + (font->height / 2) - tr.min.x; - break; - } - - setgccol(dst, col); - switch(font->type) { - case FFontSet: - Xutf8DrawString(display, dst->xid, - font->font.set, dst->gc, - x, y, - buf, len); - break; - case FXft: - XftDrawStringUtf8(xftdrawable(dst), xftcolor(col), - font->font.xft, - x, y, (uchar*)buf, len); - break; - case FX11: - XSetFont(display, dst->gc, font->font.x11->fid); - XDrawString(display, dst->xid, dst->gc, - x, y, buf, len); - break; - default: - die("Invalid font type."); - } - -done: - free(buf); - return Dx(tr); -} - -void -copyimage(Image *dst, Rectangle r, Image *src, Point p) { - XCopyArea(display, - src->xid, dst->xid, - dst->gc, - r.min.x, r.min.y, Dx(r), Dy(r), - p.x, p.y); -} - -/* Colors */ -bool -namedcolor(char *name, Color *ret) { - XColor c, c2; - - if(XAllocNamedColor(display, scr.colormap, name, &c, &c2)) { - *ret = (Color) { - c.pixel, { - c.red, - c.green, - c.blue, - 0xffff - }, - }; - return true; - } - return false; -} - -bool -loadcolor(CTuple *c, char *str) { - char buf[24]; - - utflcpy(buf, str, sizeof buf); - memcpy(c->colstr, str, sizeof c->colstr); - - buf[7] = buf[15] = buf[23] = '\0'; - return namedcolor(buf, &c->fg) - && namedcolor(buf+8, &c->bg) - && namedcolor(buf+16, &c->border); -} - -static XftColor* -xftcolor(Color col) { - XftColor *c; - - c = emallocz(sizeof *c); - *c = (XftColor) { - ((col.render.alpha&0xff00) << 24) - | ((col.render.red&0xff00) << 8) - | ((col.render.green&0xff00) << 0) - | ((col.render.blue&0xff00) >> 8), - col.render - }; - return freelater(c); -} - -/* Fonts */ -Font* -loadfont(char *name) { - XFontStruct **xfonts; - char **missing, **font_names; - Biobuf *b; - Font *f; - int n, i; - - missing = nil; - f = emallocz(sizeof *f); - f->name = estrdup(name); - if(!strncmp(f->name, "xft:", 4)) { - f->type = FXft; - - f->font.xft = XftFontOpenXlfd(display, scr.screen, f->name + 4); - if(!f->font.xft) - f->font.xft = XftFontOpenName(display, scr.screen, f->name + 4); - if(!f->font.xft) - goto error; - - f->ascent = f->font.xft->ascent; - f->descent = f->font.xft->descent; - }else { - f->font.set = XCreateFontSet(display, name, &missing, &n, nil); - if(missing) { - if(false) { - b = Bfdopen(dup(2), O_WRONLY); - Bprint(b, "%s: note: missing fontset%s for '%s':", argv0, - (n > 1 ? "s" : ""), name); - for(i = 0; i < n; i++) - Bprint(b, "%s %s", (i ? "," : ""), missing[i]); - Bprint(b, "\n"); - Bterm(b); - } - freestringlist(missing); - } - - if(f->font.set) { - f->type = FFontSet; - XFontsOfFontSet(f->font.set, &xfonts, &font_names); - f->ascent = xfonts[0]->ascent; - f->descent = xfonts[0]->descent; - }else { - f->type = FX11; - f->font.x11 = XLoadQueryFont(display, name); - if(!f->font.x11) - goto error; - - f->ascent = f->font.x11->ascent; - f->descent = f->font.x11->descent; - } - } - f->height = f->ascent + f->descent; - return f; - -error: - fprint(2, "%s: cannot load font: %s\n", argv0, name); - f->type = 0; - freefont(f); - return nil; -} - -void -freefont(Font *f) { - switch(f->type) { - case FFontSet: - XFreeFontSet(display, f->font.set); - break; - case FXft: - XftFontClose(display, f->font.xft); - break; - case FX11: - XFreeFont(display, f->font.x11); - break; - default: - break; - } - free(f->name); - free(f); -} - -Rectangle -textextents_l(Font *font, char *text, uint len, int *offset) { - Rectangle rect; - XRectangle r; - XGlyphInfo i; - int unused; - - if(!offset) - offset = &unused; - - switch(font->type) { - case FFontSet: - *offset = Xutf8TextExtents(font->font.set, text, len, &r, nil); - return Rect(r.x, -r.y - r.height, r.x + r.width, -r.y); - case FXft: - XftTextExtentsUtf8(display, font->font.xft, (uchar*)text, len, &i); - *offset = i.xOff; - return Rect(-i.x, i.y - i.height, -i.x + i.width, i.y); - case FX11: - rect = ZR; - rect.max.x = XTextWidth(font->font.x11, text, len); - rect.max.y = font->ascent; - *offset = rect.max.x; - return rect; - default: - die("Invalid font type"); - return ZR; /* shut up ken */ - } -} - -uint -textwidth_l(Font *font, char *text, uint len) { - Rectangle r; - - r = textextents_l(font, text, len, nil); - return Dx(r); -} - -uint -textwidth(Font *font, char *text) { - return textwidth_l(font, text, strlen(text)); -} - -uint -labelh(Font *font) { - return max(font->height + font->descent + font->pad.min.y + font->pad.max.y, 1); -} - -/* Misc */ -Atom -xatom(char *name) { - void **e; - - e = hash_get(&atommap, name, true); - if(*e == nil) - *e = (void*)XInternAtom(display, name, false); - return (Atom)*e; -} - -void -sendmessage(Window *w, char *name, long l0, long l1, long l2, long l3, long l4) { - 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); -} - -void -sendevent(Window *w, bool propegate, long mask, XEvent *e) { - XSendEvent(display, w->xid, propegate, mask, e); -} - -KeyCode -keycode(char *name) { - return XKeysymToKeycode(display, XStringToKeysym(name)); -} - -typedef struct KMask KMask; - -static struct KMask { - int mask; - const char* name; -} masks[] = { - {ShiftMask, "Shift"}, - {ControlMask, "Control"}, - {Mod1Mask, "Mod1"}, - {Mod2Mask, "Mod2"}, - {Mod3Mask, "Mod3"}, - {Mod4Mask, "Mod4"}, - {Mod5Mask, "Mod5"}, - {0,} -}; - -bool -parsekey(char *str, int *mask, char **key) { - static char *keys[16]; - KMask *m; - int i, nkeys; - - *mask = 0; - nkeys = tokenize(keys, nelem(keys), str, '-'); - for(i=0; i < nkeys; i++) { - for(m=masks; m->mask; m++) - if(!strcasecmp(m->name, keys[i])) { - *mask |= m->mask; - goto next; - } - break; - next: continue; - } - if(key) { - if(nkeys) - *key = keys[i]; - return i == nkeys - 1; - } - else - return i == nkeys; -} - -void -sync(void) { - XSync(display, false); -} - -/* Properties */ -void -delproperty(Window *w, char *prop) { - XDeleteProperty(display, w->xid, xatom(prop)); -} - -void -changeproperty(Window *w, char *prop, char *type, - int width, uchar data[], int n) { - XChangeProperty(display, w->xid, xatom(prop), xatom(type), width, - PropModeReplace, data, n); -} - -void -changeprop_string(Window *w, char *prop, char *string) { - changeprop_char(w, prop, "UTF8_STRING", string, strlen(string)); -} - -void -changeprop_char(Window *w, char *prop, char *type, char data[], int len) { - changeproperty(w, prop, type, 8, (uchar*)data, len); -} - -void -changeprop_short(Window *w, char *prop, char *type, short data[], int len) { - changeproperty(w, prop, type, 16, (uchar*)data, len); -} - -void -changeprop_long(Window *w, char *prop, char *type, long data[], int len) { - changeproperty(w, prop, type, 32, (uchar*)data, len); -} - -void -changeprop_ulong(Window *w, char *prop, char *type, ulong data[], int len) { - changeproperty(w, prop, type, 32, (uchar*)data, len); -} - -void -changeprop_textlist(Window *w, char *prop, char *type, char *data[]) { - char **p, *s, *t; - int len, n; - - len = 0; - for(p=data; *p; p++) - len += strlen(*p) + 1; - s = emalloc(len); - t = s; - for(p=data; *p; p++) { - n = strlen(*p) + 1; - memcpy(t, *p, n); - t += n; - } - changeprop_char(w, prop, type, s, len); - free(s); -} - -void -freestringlist(char *list[]) { - XFreeStringList(list); -} - -static ulong -getprop(Window *w, char *prop, char *type, Atom *actual, int *format, - ulong offset, uchar **ret, ulong length) { - Atom typea; - ulong n, extra; - int status; - - typea = (type ? xatom(type) : 0L); - - status = XGetWindowProperty(display, w->xid, - xatom(prop), offset, length, false /* delete */, - typea, actual, format, &n, &extra, ret); - - if(status != Success) { - *ret = nil; - return 0; - } - if(n == 0) { - free(*ret); - *ret = nil; - } - return n; -} - -ulong -getproperty(Window *w, char *prop, char *type, Atom *actual, - ulong offset, uchar **ret, ulong length) { - int format; - - return getprop(w, prop, type, actual, &format, offset, ret, length); -} - -ulong -getprop_long(Window *w, char *prop, char *type, - ulong offset, long **ret, ulong length) { - Atom actual; - ulong n; - int format; - - n = getprop(w, prop, type, &actual, &format, offset, (uchar**)ret, length); - if(n == 0 || format == 32 && xatom(type) == actual) - return n; - free(*ret); - *ret = 0; - return 0; -} - -ulong -getprop_ulong(Window *w, char *prop, char *type, - ulong offset, ulong **ret, ulong length) { - return getprop_long(w, prop, type, offset, (long**)ret, length); -} - -char** -strlistdup(char *list[]) { - char **p; - char *q; - int i, m, n; - - n = 0; - m = 0; - for(p=list; *p; p++, n++) - m += strlen(*p) + 1; - - p = malloc((n+1) * sizeof(*p) + m); - q = (char*)&p[n+1]; - - for(i=0; i < n; i++) { - p[i] = q; - m = strlen(list[i]) + 1; - memcpy(q, list[i], m); - q += m; - } - p[n] = nil; - return p; -} - -int -getprop_textlist(Window *w, char *name, char **ret[]) { - XTextProperty prop; - char **list; - int n; - - *ret = nil; - n = 0; - - XGetTextProperty(display, w->xid, &prop, xatom(name)); - if(prop.nitems > 0) { - if(Xutf8TextPropertyToTextList(display, &prop, &list, &n) == Success) - *ret = list; - XFree(prop.value); - } - return n; -} - -char* -getprop_string(Window *w, char *name) { - char **list, *str; - int n; - - str = nil; - - n = getprop_textlist(w, name, &list); - if(n > 0) - str = estrdup(*list); - freestringlist(list); - - return str; -} - -Rectangle -getwinrect(Window *w) { - XWindowAttributes wa; - Point p; - - if(!XGetWindowAttributes(display, w->xid, &wa)) - return ZR; - p = translate(w, &scr.root, ZP); - return rectaddpt(Rect(0, 0, wa.width, wa.height), p); -} - -void -setfocus(Window *w, int mode) { - XSetInputFocus(display, w->xid, mode, CurrentTime); -} - -XWindow -getfocus(void) { - XWindow ret; - int revert; - - XGetInputFocus(display, &ret, &revert); - return ret; -} - -/* Mouse */ -Point -querypointer(Window *w) { - XWindow win; - Point pt; - uint ui; - int i; - - XQueryPointer(display, w->xid, &win, &win, &i, &i, &pt.x, &pt.y, &ui); - return pt; -} - -int -pointerscreen(void) { - XWindow win; - Point pt; - uint ui; - int i; - - return XQueryPointer(display, scr.root.xid, &win, &win, &i, &i, - &pt.x, &pt.y, &ui); -} - -void -warppointer(Point pt) { - /* Nasty kludge for xephyr, xnest. */ - static int havereal = -1; - static char* real; - - if(havereal == -1) { - real = getenv("REALDISPLAY"); - havereal = real != nil; - } - if(havereal) - system(sxprint("DISPLAY=%s wiwarp %d %d", real, pt.x, pt.y)); - - XWarpPointer(display, - /* src, dest w */ None, scr.root.xid, - /* src_rect */ 0, 0, 0, 0, - /* target */ pt.x, pt.y); -} - -Point -translate(Window *src, Window *dst, Point sp) { - Point pt; - XWindow w; - - XTranslateCoordinates(display, src->xid, dst->xid, sp.x, sp.y, - &pt.x, &pt.y, &w); - return pt; -} - -int -grabpointer(Window *w, Window *confine, Cursor cur, int mask) { - XWindow cw; - - cw = None; - if(confine) - cw = confine->xid; - return XGrabPointer(display, w->xid, false /* owner events */, mask, - GrabModeAsync, GrabModeAsync, cw, cur, CurrentTime - ) == GrabSuccess; -} - -void -ungrabpointer(void) { - XUngrabPointer(display, CurrentTime); -} - -int -grabkeyboard(Window *w) { - - return XGrabKeyboard(display, w->xid, true /* owner events */, - GrabModeAsync, GrabModeAsync, CurrentTime - ) == GrabSuccess; -} - -void -ungrabkeyboard(void) { - XUngrabKeyboard(display, CurrentTime); -} - -/* Insanity */ -void -sethints(Window *w) { - XSizeHints xs; - XWMHints *wmh; - WinHints *h; - Point p; - long size; - - if(w->hints == nil) - w->hints = emalloc(sizeof *h); - - h = w->hints; - memset(h, 0, sizeof *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(!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); -} - -Rectangle -sizehint(WinHints *h, Rectangle r) { - Point p, aspect, origin; - - if(h == nil) - return r; - - origin = r.min; - r = rectsubpt(r, origin); - - /* Min/max */ - r.max.x = max(r.max.x, h->min.x); - r.max.y = max(r.max.y, h->min.y); - r.max.x = min(r.max.x, h->max.x); - r.max.y = min(r.max.y, h->max.y); - - /* Increment */ - p = subpt(r.max, h->base); - r.max.x -= p.x % h->inc.x; - r.max.y -= p.y % h->inc.y; - - /* Aspect */ - p = subpt(r.max, h->baspect); - p.y = max(p.y, 1); - - aspect = h->aspect.min; - if(p.x * aspect.y / p.y < aspect.x) - r.max.y = h->baspect.y - + p.x * aspect.y / aspect.x; - - aspect = h->aspect.max; - if(p.x * aspect.y / p.y > aspect.x) - r.max.x = h->baspect.x - + p.y * aspect.x / aspect.y; - - return rectaddpt(r, origin); -} - -Rectangle -gravitate(Rectangle rc, Rectangle rf, Point grav) { - Point d; - - /* Get delta between frame and client rectangles */ - d = subpt(subpt(rf.max, rf.min), - subpt(rc.max, rc.min)); - - /* Divide by 2 and apply gravity */ - d = divpt(d, Pt(2, 2)); - d = mulpt(d, grav); - - return rectsubpt(rc, d); -} - diff --git a/cmd/wmii/xext.c b/cmd/wmii/xext.c @@ -1,160 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#define _X11_VISIBLE -#include "dat.h" -#include <X11/extensions/Xrender.h> -#include <X11/extensions/Xinerama.h> -#include "fns.h" - -#if RANDR_MAJOR < 1 -# error XRandR versions less than 1.0 are not supported -#endif - -static void randr_screenchange(XRRScreenChangeNotifyEvent*); -static bool randr_event_p(XEvent *e); -static void randr_init(void); -static void render_init(void); -static void xinerama_init(void); - -typedef void (*EvHandler)(XEvent*); -static EvHandler randr_handlers[RRNumberEvents]; - -bool have_RandR; -bool have_render; -bool have_xinerama; -int randr_eventbase; - -static void -handle(XEvent *e, EvHandler h[], int base) { - - if(h[e->type-base]) - h[e->type-base](e); -} - -void -xext_init(void) { - randr_init(); - render_init(); - xinerama_init(); -} - -void -xext_event(XEvent *e) { - - if(randr_event_p(e)) - handle(e, randr_handlers, randr_eventbase); -} - -static void -randr_init(void) { - int errorbase, major, minor; - - have_RandR = XRRQueryExtension(display, &randr_eventbase, &errorbase); - if(have_RandR) - if(XRRQueryVersion(display, &major, &minor) && major < 1) - have_RandR = false; - if(have_RandR) - XRRSelectInput(display, scr.root.xid, RRScreenChangeNotifyMask); -} - -static bool -randr_event_p(XEvent *e) { - return have_RandR - && (uint)e->type - randr_eventbase < RRNumberEvents; -} - -static void -randr_screenchange(XRRScreenChangeNotifyEvent *ev) { - - XRRUpdateConfiguration((XEvent*)ev); - if(ev->rotation*90 % 180) - scr.rect = Rect(0, 0, ev->width, ev->height); - else - scr.rect = Rect(0, 0, ev->height, ev->width); - init_screens(); -} - -static EvHandler randr_handlers[] = { - [RRScreenChangeNotify] = (EvHandler)randr_screenchange, -}; - -/* Ripped most graciously from ecore_x. XRender documentation - * is sparse. - */ -static void -render_init(void) { - XVisualInfo *vip; - XVisualInfo vi; - int base, i, n; - - have_render = XRenderQueryExtension(display, &base, &base); - if(!have_render) - return; - - vi.class = TrueColor; - vi.depth = 32; - vi.screen = scr.screen; - vip = XGetVisualInfo(display, VisualClassMask - | VisualDepthMask - | VisualScreenMask, - &vi, &n); - for(i=0; i < n; i++) - if(render_argb_p(vip[i].visual)) { - render_visual = vip[i].visual; - scr.visual32 = render_visual; - break; - } - XFree(vip); -} - -bool -render_argb_p(Visual *v) { - XRenderPictFormat *f; - - if(!have_render) - return false; - f = XRenderFindVisualFormat(display, v); - return f - && f->type == PictTypeDirect - && f->direct.alphaMask; -} - -static void -xinerama_init(void) { - int base; - - have_xinerama = XineramaQueryExtension(display, &base, &base); -} - -static bool -xinerama_active(void) { - return have_xinerama && XineramaIsActive(display); -} - -Rectangle* -xinerama_screens(int *np) { - static Rectangle *rects; - XineramaScreenInfo *res; - int i, n; - - if(!xinerama_active()) { - *np = 1; - return &scr.rect; - } - - free(rects); - res = XineramaQueryScreens(display, &n); - rects = emalloc(n * sizeof *rects); - for(i=0; i < n; i++) { - rects[i].min.x = res[i].x_org; - rects[i].min.y = res[i].y_org; - rects[i].max.x = res[i].x_org + res[i].width; - rects[i].max.y = res[i].y_org + res[i].height; - } - XFree(res); - - *np = n; - return rects; -} - diff --git a/cmd/wmii9menu.c b/cmd/wmii9menu.c @@ -44,9 +44,10 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <clientutil.h> -#include <util.h> -#include <x11.h> + +#include <stuff/clientutil.h> +#include <stuff/util.h> +#include <stuff/x11.h> char version[] = "wmii9menu-" VERSION " ©2010 Kris Maglione, ©1994 David Hogan, Arnold Robbins"; @@ -81,10 +82,6 @@ void warpmouse(int, int); void memory(void); int args(void); -ErrorCode ignored_xerrors[] = { - { 0, } -}; - /* xext.c */ void xext_init(void); Rectangle* xinerama_screens(int*); diff --git a/cmd/wmiir.c b/cmd/wmiir.c @@ -9,7 +9,7 @@ #include <time.h> #include <unistd.h> #include <ixp.h> -#include <util.h> +#include <stuff/util.h> #include <fmt.h> static IxpClient *client; diff --git a/doc/wmii.tex b/doc/wmii.tex @@ -45,6 +45,7 @@ \DefineShortVerb{\|} \makeatletter +\let\idx@@heading\chapter \let\:=: \catcode`\:=\active \def:{\@ifnextchar:{\coloncoloneq}{\:}} diff --git a/include/clientutil.h b/include/clientutil.h @@ -1,9 +0,0 @@ -#ifndef CLIENTEXTERN -# define CLIENTEXTERN extern -#endif - -char* readctl(char*); -void client_init(char*); - -CLIENTEXTERN IxpClient* client; - diff --git a/include/debug.h b/include/debug.h @@ -0,0 +1,13 @@ +#include <stdbool.h> + +#define Debug(x) if(((debugflag|debugfile)&(x)) && setdebug(x)) +#define Dprint(x, ...) BLOCK( if((debugflag|debugfile)&(x)) debug(x, __VA_ARGS__) ) + +void debug(int, const char*, ...); +void dprint(const char*, ...); +void dwrite(int, void*, int, bool); +bool setdebug(int); +void vdebug(int, const char*, va_list); + +int debugflag; +int debugfile; diff --git a/include/stuff/clientutil.h b/include/stuff/clientutil.h @@ -0,0 +1,13 @@ +/* Copyright ©2009-2010 Kris Maglione <fbsdaemon@gmail.com> + * See LICENSE file for license details. + */ + +#ifndef CLIENTEXTERN +# define CLIENTEXTERN extern +#endif + +char* readctl(char*); +void client_init(char*); + +CLIENTEXTERN IxpClient* client; + diff --git a/include/stuff/geom.h b/include/stuff/geom.h @@ -0,0 +1,54 @@ +#pragma once + +#include <stuff/base.h> + +typedef struct Point Point; +typedef struct Rectangle Rectangle; + +struct Point { + int x, y; +}; + +struct Rectangle { + Point min, max; +}; + +enum Align { + North = 0x01, + East = 0x02, + South = 0x04, + West = 0x08, + NEast = North | East, + NWest = North | West, + SEast = South | East, + SWest = South | West, + Center = NEast | SWest, +}; + +typedef enum Align Align; + +#define Dx(r) ((r).max.x - (r).min.x) +#define Dy(r) ((r).max.y - (r).min.y) +#define Pt(x, y) ((Point){(x), (y)}) +#define Rpt(p, q) ((Rectangle){p, q}) +#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)}) + +Point addpt(Point, Point); +Point divpt(Point, Point); +int eqpt(Point, Point); +int eqrect(Rectangle, Rectangle); +Rectangle gravitate(Rectangle dst, Rectangle src, Point grav); +Rectangle insetrect(Rectangle, int); +Point mulpt(Point p, Point q); +Rectangle rectaddpt(Rectangle, Point); +Rectangle rectsetorigin(Rectangle, Point); +Rectangle rectsubpt(Rectangle, Point); +Point subpt(Point, Point); + +Align get_sticky(Rectangle src, Rectangle dst); +Align quadrant(Rectangle, Point); +bool rect_contains_p(Rectangle, Rectangle); +bool rect_haspoint_p(Point, Rectangle); +bool rect_intersect_p(Rectangle, Rectangle); +Rectangle rect_intersection(Rectangle, Rectangle); + diff --git a/include/stuff/util.h b/include/stuff/util.h @@ -0,0 +1,150 @@ +/* Copyright ©2007-2010 Kris Maglione <fbsdaemon@gmail.com> + * See LICENSE file for license details. + */ + +#include <stuff/geom.h> + +#include <stdarg.h> + +#include <regexp9.h> + +/* Types */ + +typedef struct Regex Regex; + +struct Regex { + char* regex; + Reprog* regc; +}; + +enum { + CLeft = 1<<0, + 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, +}; + +#ifdef VARARGCK +# pragma varargck argpos _die 3 +# pragma varargck argpos fatal 1 +# pragma varargck argpos sxprint 1 +#endif + +#define strlcat stuff_strlcat +#define strcasestr stuff_strcasestr + +void _die(char*, int, char*, ...); +void backtrace(char*); +void closeexec(int); +char** comm(int, char**, char**); +int doublefork(void); +void* emalloc(uint); +void* emallocz(uint); +void* erealloc(void*, uint); +char* estrdup(const char*); +char* estrndup(const char*, uint); +void fatal(const char*, ...); +void* freelater(void*); +int getbase(const char**, long*); +bool getint(const char*, int*); +bool getlong(const char*, long*); +bool getulong(const char*, ulong*); +void grep(char**, Reprog*, int); +char* join(char**, char*); +int max(int, int); +int min(int, int); +char* pathsearch(const char*, const char*, bool); +void refree(Regex*); +void reinit(Regex*, char*); +int spawn3(int[3], const char*, char*[]); +int spawn3l(int[3], const char*, ...); +uint stokenize(char**, uint, char*, char*); +char* strcasestr(const char*, const char*); +char* strend(char*, int); +uint strlcat(char*, const char*, uint); +int strlcatprint(char*, int, const char*, ...); +char* sxprint(const char*, ...); +uint tokenize(char**, uint, char*, char); +void uniq(char**); +int unquote(char*, char*[], int); +int utflcpy(char*, const char*, int); +char* vsxprint(const char*, va_list); + +extern char buffer[8092]; +extern char* _buffer; +extern char* const _buf_end; + +#define bufclear() \ + BLOCK( _buffer = buffer; _buffer[0] = '\0' ) +#define bufprint(...) \ + _buffer = seprint(_buffer, _buf_end, __VA_ARGS__) + +#define die(...) \ + _die(__FILE__, __LINE__, __VA_ARGS__) + +char *argv0; +#undef ARGBEGIN +#undef ARGEND +#undef ARGF +#undef EARGF +#define ARGBEGIN \ + int _argtmp=0, _inargv; char *_argv=nil; \ + if(!argv0) argv0=*argv; argv++, argc--; \ + _inargv=1; USED(_inargv); \ + while(argc && argv[0][0] == '-') { \ + _argv=&argv[0][1]; argv++; argc--; \ + if(_argv[0] == '-' && _argv[1] == '\0') \ + break; \ + while(*_argv) switch(*_argv++) +#define ARGEND }_inargv=0;USED(_argtmp, _argv, _inargv) + +#define EARGF(f) ((_inargv && *_argv) ? \ + (_argtmp=strlen(_argv), _argv+=_argtmp, _argv-_argtmp) \ + : ((argc > 0) ? \ + (--argc, ++argv, _used(argc), *(argv-1)) \ + : ((f), (char*)0))) +#define ARGF() EARGF(_used(0)) + +/* map.c */ +typedef struct Map Map; +typedef struct MapEnt MapEnt; + +struct Map { + MapEnt**bucket; + uint nhash; +}; + +void** hash_get(Map*, const char*, bool create); +void* hash_rm(Map*, const char*); +void** map_get(Map*, ulong, bool create); +void* map_rm(Map*, ulong); + +/* Yuck. */ +#define VECTOR(type, nam, c) \ +typedef struct Vector_##nam Vector_##nam; \ +struct Vector_##nam { \ + type* ary; \ + long n; \ + long size; \ +}; \ +void vector_##c##free(Vector_##nam*); \ +void vector_##c##init(Vector_##nam*); \ +void vector_##c##push(Vector_##nam*, type); \ + +VECTOR(long, long, l) +VECTOR(Rectangle, rect, r) +VECTOR(void*, ptr, p) +#undef VECTOR + diff --git a/include/stuff/x.h b/include/stuff/x.h @@ -0,0 +1,48 @@ +#include <stuff/base.h> +#include <stuff/x11.h> +#include <fmt.h> + +extern Visual* render_visual; + +extern void init_screens(void); + +/* printevent.c */ +int fmtevent(Fmt*); + +/* xext.c */ +void randr_event(XEvent*); +bool render_argb_p(Visual*); +void xext_event(XEvent*); +void xext_init(void); +Rectangle* xinerama_screens(int*); + +void event_check(void); +void event_dispatch(XEvent*); +uint event_flush(long, bool dispatch); +uint event_flushenter(void); +void event_loop(void); +void event_updatextime(void); + +void event_buttonpress(XButtonPressedEvent*); +void event_buttonrelease(XButtonPressedEvent*); +void event_clientmessage(XClientMessageEvent*); +void event_configurenotify(XConfigureEvent*); +void event_configurerequest(XConfigureRequestEvent*); +void event_destroynotify(XDestroyWindowEvent*); +void event_enternotify(XCrossingEvent*); +void event_expose(XExposeEvent*); +void event_focusin(XFocusChangeEvent*); +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_motionnotify(XMotionEvent*); +void event_propertynotify(XPropertyEvent*); +void event_unmapnotify(XUnmapEvent*); + +extern long event_xtime; +extern bool event_looprunning; +extern void (*event_debug)(XEvent*); + diff --git a/include/stuff/x11.h b/include/stuff/x11.h @@ -0,0 +1,249 @@ +/* Copyright ©2007-2010 Kris Maglione <fbsdaemon@gmail.com> + * See LICENSE file for license details. + */ +#define Window XWindow +#define Font XFont +#define Screen XScreen +#include <stuff/geom.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xft/Xft.h> +#include <X11/extensions/Xrender.h> +#ifdef _X11_VISIBLE +# include <X11/Xatom.h> +# include <X11/extensions/shape.h> +# include <X11/extensions/Xrandr.h> +#endif +#undef Window +#undef Font +#undef Screen + +enum FontType { + FX11 = 1, + FFontSet, + FXft, +}; + +enum WindowType { + WWindow, + WImage, +}; + +typedef enum FontType FontType; +typedef enum WindowType WindowType; + +typedef XSetWindowAttributes WinAttr; + +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 Screen Screen; +typedef struct WinHints WinHints; +typedef struct Window Image; +typedef struct Window Window; + +struct Color { + ulong pixel; + XRenderColor render; +}; + +struct CTuple { + Color bg; + Color fg; + Color border; + char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */ +}; + +struct ErrorCode { + uchar rcode; + uchar ecode; +}; + +struct Ewmh { + long type; + long ping; + long timer; +}; + +struct Font { + int type; + union { + XFontStruct* x11; + XFontSet set; + XftFont* xft; + } font; + Rectangle pad; + int ascent; + int descent; + uint height; + char* name; +}; + +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*); +}; + +struct WinHints { + Point min; + Point max; + Point base; + Point baspect; + Point inc; + Point grav; + Rectangle aspect; + XWindow group; + bool gravstatic; + bool position; +}; + +struct Window { + int type; + XID xid; + GC gc; + Visual* visual; + Colormap colormap; + XftDraw* xft; + Rectangle r; + int border; + Window* parent; + Window* next; + Window* prev; + Handlers* handler; + WinHints* hints; + Ewmh ewmh; + void* dnd; + void* aux; + bool mapped; + int unmapped; + int depth; +}; + +struct Screen { + int screen; + Window root; + GC gc; + Colormap colormap; + Visual* visual; + Visual* visual32; + Rectangle rect; + int depth; + int fd; + ulong black; + ulong white; +}; + +#ifdef VARARGCK +# pragma varargck type "A" Atom +# pragma varargck type "P" Point +# pragma varargck type "R" Rectangle +# pragma varargck type "W" Window* +#endif + +Display *display; +Screen scr; + +extern const Point ZP; +extern const Rectangle ZR; +extern Window* pointerwin; + +XRectangle XRect(Rectangle r); + +#define changeprop(w, prop, type, data, n) \ + changeproperty(w, prop, type, \ + ((sizeof(*(data)) == 8 ? 4 : sizeof(*(data))) * 8), \ + (uchar*)(data), n) + +/* x11.c */ +Image* allocimage(int w, int h, int depth); +void border(Image *dst, Rectangle, int w, Color); +void changeprop_char(Window*, char*, char*, char[], int); +void changeprop_long(Window*, char*, char*, long[], int); +void changeprop_short(Window*, char*, char*, short[], int); +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 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); +void delproperty(Window*, char*); +void destroywindow(Window*); +void drawline(Image*, Point, Point, int cap, int w, Color); +void drawpoly(Image*, Point*, int, int cap, int w, Color); +uint drawstring(Image*, Font*, Rectangle, Align, char*, Color); +void fill(Image*, Rectangle, Color); +void fillpoly(Image*, Point*, int, Color); +Window* findwin(XWindow); +void freefont(Font*); +void freeimage(Image *); +void freestringlist(char**); +XWindow getfocus(void); +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); +int grabkeyboard(Window*); +int grabpointer(Window*, Window *confine, Cursor, int mask); +void initdisplay(void); +KeyCode keycode(char*); +uint labelh(Font*); +bool loadcolor(CTuple*, char*); +Font* loadfont(char*); +void lowerwin(Window*); +int mapwin(Window*); +void movewin(Window*, Point); +bool namedcolor(char *name, Color*); +bool parsekey(char*, int*, char**); +int pointerscreen(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 setborder(Window*, int, Color); +void setfocus(Window*, int mode); +void sethints(Window*); +void setshapemask(Window *dst, Image *src, Point); +void setwinattr(Window*, WinAttr*, int valmask); +char** strlistdup(char**); +void sync(void); +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); +void ungrabkeyboard(void); +void ungrabpointer(void); +int unmapwin(Window*); +void warppointer(Point); +Window* window(XWindow); +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); + diff --git a/include/util.h b/include/util.h @@ -1,91 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <fbsdaemon@gmail.com> - * See LICENSE file for license details. - */ -#define nil ((void*)0) -#define nelem(ary) (sizeof(ary) / sizeof(*ary)) - -/* Types */ -#undef uchar -#undef ushort -#undef uint -#undef ulong -#undef uvlong -#undef vlong -#define uchar _x_uchar -#define ushort _x_ushort -#define uint _x_uint -#define ulong _x_ulong -#define uvlong _x_uvlong -#define vlong _x_vlong - -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long long uvlong; -typedef long long vlong; - -#ifdef VARARGCK -# pragma varargck argpos _die 3 -# pragma varargck argpos fatal 1 -# pragma varargck argpos sxprint 1 -#endif - -#define strlcat wmii_strlcat -#define strcasestr wmii_strcasestr -/* util.c */ -void _die(char*, int, char*, ...); -void* emalloc(uint); -void* emallocz(uint); -void* erealloc(void*, uint); -char* estrdup(const char*); -char* estrndup(const char*, uint); -void fatal(const char*, ...); -void* freelater(void*); -int max(int, int); -int min(int, int); -uint strlcat(char*, const char*, uint); -char* strcasestr(const char*, const char*); -char* sxprint(const char*, ...); -uint tokenize(char**, uint, char*, char); -uint stokenize(char**, uint, char*, char*); -int utflcpy(char*, const char*, int); -char* vsxprint(const char*, va_list); - -#define die(...) \ - _die(__FILE__, __LINE__, __VA_ARGS__) - -char *argv0; -#undef ARGBEGIN -#undef ARGEND -#undef ARGF -#undef EARGF -#define ARGBEGIN \ - int _argtmp=0, _inargv; char *_argv=nil; \ - if(!argv0) argv0=*argv; argv++, argc--; \ - _inargv=1; USED(_inargv); \ - while(argc && argv[0][0] == '-') { \ - _argv=&argv[0][1]; argv++; argc--; \ - if(_argv[0] == '-' && _argv[1] == '\0') \ - break; \ - while(*_argv) switch(*_argv++) -#define ARGEND }_inargv=0;USED(_argtmp, _argv, _inargv) - -#define EARGF(f) ((_inargv && *_argv) ? \ - (_argtmp=strlen(_argv), _argv+=_argtmp, _argv-_argtmp) \ - : ((argc > 0) ? \ - (--argc, ++argv, _used(argc), *(argv-1)) \ - : ((f), (char*)0))) -#define ARGF() EARGF(_used(0)) - -static inline void -_used(long a, ...) { - if(a){} -} -#ifndef KENC -# undef USED -# undef SET -# define USED(...) _used((long)__VA_ARGS__) -# define SET(x) (x = 0) -/* # define SET(x) USED(&x) GCC 4 is 'too smart' for this. */ -#endif diff --git a/include/x11.h b/include/x11.h @@ -1,292 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <fbsdaemon@gmail.com> - * See LICENSE file for license details. - */ -#define Window XWindow -#define Font XFont -#define Screen XScreen -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xft/Xft.h> -#include <X11/extensions/Xrender.h> -#ifdef _X11_VISIBLE -# include <X11/Xatom.h> -# include <X11/extensions/shape.h> -# include <X11/extensions/Xrandr.h> -#endif -#undef Window -#undef Font -#undef Screen - -enum Align { - North = 0x01, - East = 0x02, - South = 0x04, - West = 0x08, - NEast = North | East, - NWest = North | West, - SEast = South | East, - SWest = South | West, - Center = NEast | SWest, -}; - -enum FontType { - FX11 = 1, - FFontSet, - FXft, -}; - -enum WindowType { - WWindow, - WImage, -}; - -typedef enum Align Align; -typedef enum FontType FontType; -typedef enum WindowType WindowType; - -typedef XSetWindowAttributes WinAttr; - -typedef struct Point Point; -typedef struct Rectangle Rectangle; - -struct Point { - int x, y; -}; - -struct Rectangle { - Point min, max; -}; - -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 Screen Screen; -typedef struct WinHints WinHints; -typedef struct Window Image; -typedef struct Window Window; - -struct Color { - ulong pixel; - XRenderColor render; -}; - -struct CTuple { - Color bg; - Color fg; - Color border; - char colstr[24]; /* #RRGGBB #RRGGBB #RRGGBB */ -}; - -struct ErrorCode { - uchar rcode; - uchar ecode; -}; - -struct Ewmh { - long type; - long ping; - long timer; -}; - -struct Font { - int type; - union { - XFontStruct* x11; - XFontSet set; - XftFont* xft; - } font; - Rectangle pad; - int ascent; - int descent; - uint height; - char* name; -}; - -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*); -}; - -struct WinHints { - Point min; - Point max; - Point base; - Point baspect; - Point inc; - Point grav; - Rectangle aspect; - XWindow group; - bool gravstatic; - bool position; -}; - -struct Window { - int type; - XID xid; - GC gc; - Visual* visual; - Colormap colormap; - XftDraw* xft; - Rectangle r; - int border; - Window* parent; - Window* next; - Window* prev; - Handlers* handler; - WinHints* hints; - Ewmh ewmh; - void* dnd; - void* aux; - bool mapped; - int unmapped; - int depth; -}; - -struct Screen { - int screen; - Window root; - GC gc; - Colormap colormap; - Visual* visual; - Visual* visual32; - Rectangle rect; - int depth; - int fd; - ulong black; - ulong white; -}; - -#ifdef VARARGCK -# pragma varargck type "A" Atom -# pragma varargck type "P" Point -# pragma varargck type "R" Rectangle -# pragma varargck type "W" Window* -#endif - -Display *display; -Screen scr; - -extern const Point ZP; -extern const Rectangle ZR; -extern Window* pointerwin; - -Point Pt(int x, int y); -Rectangle Rect(int x0, int y0, int x1, int y1); -Rectangle Rpt(Point min, Point max); - -XRectangle XRect(Rectangle r); - -#define Dx(r) ((r).max.x - (r).min.x) -#define Dy(r) ((r).max.y - (r).min.y) -#define Pt(x, y) ((Point){(x), (y)}) -#define Rpt(p, q) ((Rectangle){p, q}) -#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)}) -#define changeprop(w, prop, type, data, n) \ - changeproperty(w, prop, type, \ - ((sizeof(*(data)) == 8 ? 4 : sizeof(*(data))) * 8), \ - (uchar*)(data), n) - -/* x11.c */ -Point addpt(Point, Point); -Image* allocimage(int w, int h, int depth); -void border(Image *dst, Rectangle, int w, Color); -void changeprop_char(Window*, char*, char*, char[], int); -void changeprop_long(Window*, char*, char*, long[], int); -void changeprop_short(Window*, char*, char*, short[], int); -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 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); -void delproperty(Window*, char*); -void destroywindow(Window*); -Point divpt(Point, Point); -void drawline(Image*, Point, Point, int cap, int w, Color); -void drawpoly(Image*, Point*, int, int cap, int w, Color); -uint drawstring(Image*, Font*, Rectangle, Align, char*, Color); -int eqpt(Point, Point); -int eqrect(Rectangle, Rectangle); -void fill(Image*, Rectangle, Color); -void fillpoly(Image*, Point*, int, Color); -Window* findwin(XWindow); -void freefont(Font*); -void freeimage(Image *); -void freestringlist(char**); -XWindow getfocus(void); -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); -int grabkeyboard(Window*); -int grabpointer(Window*, Window *confine, Cursor, int mask); -void initdisplay(void); -KeyCode keycode(char*); -uint labelh(Font*); -bool loadcolor(CTuple*, char*); -Font* loadfont(char*); -void lowerwin(Window*); -int mapwin(Window*); -void movewin(Window*, Point); -Point mulpt(Point p, Point q); -bool namedcolor(char *name, Color*); -bool parsekey(char*, int*, char**); -int pointerscreen(void); -Point querypointer(Window*); -void raisewin(Window*); -void reparentwindow(Window*, Window*, Point); -void reshapewin(Window*, Rectangle); -void selectinput(Window*, long); -void sendevent(Window*, bool propegate, long mask, XEvent*); -void setborder(Window*, int, Color); -void setfocus(Window*, int mode); -void sethints(Window*); -void setshapemask(Window *dst, Image *src, Point); -void setwinattr(Window*, WinAttr*, int valmask); -char** strlistdup(char**); -Point subpt(Point, Point); -void sync(void); -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); -void ungrabkeyboard(void); -void ungrabpointer(void); -int unmapwin(Window*); -void warppointer(Point); -Window* window(XWindow); -long winprotocols(Window*); -Atom xatom(char*); -void sendmessage(Window*, char*, long, long, long, long, long); -XRectangle XRect(Rectangle); -Rectangle getwinrect(Window*); -Rectangle gravitate(Rectangle dst, Rectangle src, Point grav); -Rectangle insetrect(Rectangle, int); -Rectangle rectaddpt(Rectangle, Point); -Rectangle rectsetorigin(Rectangle, Point); -Rectangle rectsubpt(Rectangle, Point); -Handlers* sethandler(Window*, Handlers*); -Rectangle sizehint(WinHints*, Rectangle); - diff --git a/libstuff/Makefile b/libstuff/Makefile @@ -0,0 +1,171 @@ +ROOT= .. +include ${ROOT}/mk/hdr.mk + +TARG=libstuff + +PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama + +OBJ=\ + buffer \ + clientutil \ + event/buttonpress \ + event/buttonrelease \ + event/clientmessage \ + event/configurenotify \ + event/configurerequest \ + event/destroynotify \ + event/enternotify \ + event/event \ + event/expose \ + event/focusin \ + event/focusout \ + event/keypress \ + event/leavenotify \ + event/mapnotify \ + event/maprequest \ + event/mappingnotify \ + event/motionnotify \ + event/propertynotify \ + event/unmapnotify \ + event/xtime \ + geom/get_sticky \ + geom/quadrant \ + geom/rect_contains_p \ + geom/rect_haspoint_p \ + geom/rect_intersect_p \ + geom/rect_intersection \ + init_screens \ + map \ + printevent \ + util/_die \ + util/backtrace \ + util/closeexec \ + util/comm \ + util/doublefork \ + util/emalloc \ + util/emallocz \ + util/erealloc \ + util/estrdup \ + util/estrndup \ + util/fatal \ + util/freelater \ + util/getbase \ + util/getint \ + util/getlong \ + util/getulong \ + util/grep \ + util/join \ + util/max \ + util/mfatal \ + util/min \ + util/pathsearch \ + util/refree \ + util/reinit \ + util/spawn3 \ + util/spawn3l \ + util/stokenize \ + util/strcasestr \ + util/strend \ + util/strlcat \ + util/strlcatprint \ + util/sxprint \ + util/tokenize \ + util/uniq \ + util/unquote \ + util/utflcpy \ + util/vector \ + util/vsxprint \ + x11/convpts \ + x11/errors \ + x11/ignored_xerrors \ + x11/freestringlist \ + x11/initdisplay \ + x11/sendevent \ + x11/sendmessage \ + x11/setgccol \ + x11/sync \ + x11/x11 \ + x11/xatom \ + x11/colors/loadcolor \ + x11/colors/namedcolor \ + x11/colors/xftcolor \ + x11/drawing/border \ + x11/drawing/drawline \ + x11/drawing/drawpoly \ + x11/drawing/drawstring \ + x11/drawing/fill \ + x11/drawing/fillpoly \ + x11/focus/getfocus \ + x11/focus/setfocus \ + x11/geometry/XRect \ + x11/geometry/addpt \ + x11/geometry/divpt \ + x11/geometry/eqpt \ + x11/geometry/eqrect \ + x11/geometry/insetrect \ + x11/geometry/mulpt \ + x11/geometry/rectaddpt \ + x11/geometry/rectsetorigin \ + x11/geometry/rectsubpt \ + x11/geometry/subpt \ + x11/images/allocimage \ + x11/images/copyimage \ + x11/images/freeimage \ + x11/images/xftdrawable \ + x11/insanity/gravitate \ + x11/insanity/sethints \ + x11/insanity/sizehint \ + x11/keyboard/grabkeyboard \ + x11/keyboard/ungrabkeyboard \ + x11/keys/keycode \ + x11/keys/parsekey \ + x11/mouse/grabpointer \ + x11/mouse/pointerscreen \ + x11/mouse/querypointer \ + x11/mouse/translate \ + x11/mouse/ungrabpointer \ + x11/mouse/warppointer \ + x11/properties/changeprop_char \ + x11/properties/changeprop_long \ + x11/properties/changeprop_short \ + x11/properties/changeprop_string \ + x11/properties/changeprop_textlist \ + x11/properties/changeprop_ulong \ + x11/properties/changeproperty \ + x11/properties/delproperty \ + x11/properties/getprop \ + x11/properties/getprop_long \ + x11/properties/getprop_string \ + x11/properties/getprop_textlist \ + x11/properties/getprop_ulong \ + x11/properties/getproperty \ + x11/properties/strlistdup \ + x11/shape/setshapemask \ + x11/text/freefont \ + x11/text/labelh \ + x11/text/loadfont \ + x11/text/textextents_l \ + x11/text/textwidth \ + x11/text/textwidth_l \ + x11/windows/configwin \ + x11/windows/createwindow \ + x11/windows/createwindow_visual \ + x11/windows/destroywindow \ + x11/windows/findwin \ + x11/windows/getwinrect \ + x11/windows/lowerwin \ + x11/windows/mapwin \ + x11/windows/movewin \ + x11/windows/raisewin \ + x11/windows/reparentwindow \ + x11/windows/reshapewin \ + x11/windows/selectinput \ + x11/windows/setborder \ + x11/windows/sethandler \ + x11/windows/setwinattr \ + x11/windows/unmapwin \ + x11/windows/window \ + xext + +include ${ROOT}/mk/lib.mk + diff --git a/libstuff/buffer.c b/libstuff/buffer.c @@ -0,0 +1,8 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ + +char buffer[8092]; +char* _buffer; +char* const _buf_end = buffer + sizeof buffer; + diff --git a/libstuff/clientutil.c b/libstuff/clientutil.c @@ -0,0 +1,50 @@ +#define IXP_NO_P9_ +#define IXP_P9_STRUCTS +#define CLIENTEXTERN +#include <string.h> +#include <ixp.h> +#include <stuff/clientutil.h> +#include <stuff/util.h> + +static IxpCFid* ctlfid; +static char ctl[1024]; +static char* ectl; + +char* +readctl(char *key) { + char *s, *p; + int nkey, n; + + if(ctlfid == nil) { + ctlfid = ixp_open(client, "ctl", OREAD); + n = ixp_read(ctlfid, ctl, 1023); + ectl = ctl + n; + ixp_close(ctlfid); + } + + nkey = strlen(key); + p = ctl - 1; + do { + p++; + if(!strncmp(p, key, nkey)) { + p += nkey; + s = strchr(p, '\n'); + n = (s ? s : ectl) - p; + s = freelater(emalloc(n + 1)); + s[n] = '\0'; + return strncpy(s, p, n); + } + } while((p = strchr(p, '\n'))); + return ""; +} + +void +client_init(char* address) { + if(address && *address) + client = ixp_mount(address); + else + client = ixp_nsmount("wmii"); + if(client == nil) + fatal("can't mount: %r\n"); +} + diff --git a/libstuff/event/buttonpress.c b/libstuff/event/buttonpress.c @@ -0,0 +1,14 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_buttonpress(XButtonPressedEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, bdown, ev); + else + XAllowEvents(display, ReplayPointer, ev->time); +} diff --git a/libstuff/event/buttonrelease.c b/libstuff/event/buttonrelease.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_buttonrelease(XButtonPressedEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, bup, ev); +} diff --git a/libstuff/event/clientmessage.c b/libstuff/event/clientmessage.c @@ -0,0 +1,10 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_clientmessage(XClientMessageEvent *ev) { + + USED(ev); +} diff --git a/libstuff/event/configurenotify.c b/libstuff/event/configurenotify.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_configurenotify(XConfigureEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, config, ev); +} diff --git a/libstuff/event/configurerequest.c b/libstuff/event/configurerequest.c @@ -0,0 +1,24 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_configurerequest(XConfigureRequestEvent *ev) { + XWindowChanges wc; + Window *w; + + if((w = findwin(ev->window))) + handle(w, configreq, ev); + else{ + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(display, ev->window, ev->value_mask, &wc); + } +} + diff --git a/libstuff/event/destroynotify.c b/libstuff/event/destroynotify.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_destroynotify(XDestroyWindowEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, destroy, ev); +} diff --git a/libstuff/event/enternotify.c b/libstuff/event/enternotify.c @@ -0,0 +1,16 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_enternotify(XCrossingEvent *ev) { + Window *w; + + event_xtime = ev->time; + if(ev->mode != NotifyNormal) + return; + + if((w = findwin(ev->window))) + handle(w, enter, ev); +} diff --git a/libstuff/event/event.c b/libstuff/event/event.c @@ -0,0 +1,107 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void (*event_debug)(XEvent*); +long event_xtime; +bool event_looprunning; + +EventHandler event_handler[LASTEvent] = { + [ButtonPress] = (EventHandler)event_buttonpress, + [ButtonRelease] = (EventHandler)event_buttonrelease, + [ClientMessage] = (EventHandler)event_clientmessage, + [ConfigureNotify] = (EventHandler)event_configurenotify, + [ConfigureRequest] = (EventHandler)event_configurerequest, + [DestroyNotify] = (EventHandler)event_destroynotify, + [EnterNotify] = (EventHandler)event_enternotify, + [Expose] = (EventHandler)event_expose, + [FocusIn] = (EventHandler)event_focusin, + [FocusOut] = (EventHandler)event_focusout, + [KeyPress] = (EventHandler)event_keypress, + [LeaveNotify] = (EventHandler)event_leavenotify, + [MapNotify] = (EventHandler)event_mapnotify, + [MapRequest] = (EventHandler)event_maprequest, + [MappingNotify] = (EventHandler)event_mappingnotify, + [MotionNotify] = (EventHandler)event_motionnotify, + [PropertyNotify] = (EventHandler)event_propertynotify, + [UnmapNotify] = (EventHandler)event_unmapnotify, +}; + +void +event_dispatch(XEvent *e) { + if(event_debug) + event_debug(e); + + if(e->type < nelem(event_handler)) { + if(event_handler[e->type]) + event_handler[e->type](e); + }else + xext_event(e); +} + +void +event_check(void) { + XEvent ev; + + while(XPending(display)) { + XNextEvent(display, &ev); + event_dispatch(&ev); + } +} + +void +event_loop(void) { + XEvent ev; + + while(event_looprunning) { + XNextEvent(display, &ev); + event_dispatch(&ev); + } +} + +uint +event_flush(long event_mask, bool dispatch) { + XEvent ev; + uint n = 0; + + while(XCheckMaskEvent(display, event_mask, &ev)) { + if(dispatch) + event_dispatch(&ev); + n++; + } + return n; +} + +static int +findenter(Display *d, XEvent *e, XPointer v) { + long *l; + + USED(d); + l = (long*)v; + if(*l) + return false; + if(e->type == EnterNotify) + return true; + if(e->type == MotionNotify) + (*l)++; + return false; +} + +/* This isn't perfect. If there were motion events in the queue + * before this was called, then it flushes nothing. If we don't + * check for them, we might lose a legitamate enter event. + */ +uint +event_flushenter(void) { + XEvent e; + long l; + int n; + + l = 0; + n = 0; + while(XCheckIfEvent(display, &e, findenter, (void*)&l)) + n++; + return n; +} + diff --git a/libstuff/event/event.h b/libstuff/event/event.h @@ -0,0 +1,9 @@ +#include <stuff/x.h> + +typedef void (*EventHandler)(XEvent*); + +#define handle(w, fn, ev) \ + BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev)) + +extern EventHandler event_handler[LASTEvent]; + diff --git a/libstuff/event/expose.c b/libstuff/event/expose.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_expose(XExposeEvent *ev) { + Window *w; + + if(ev->count == 0 && (w = findwin(ev->window))) + handle(w, expose, ev); +} diff --git a/libstuff/event/focusin.c b/libstuff/event/focusin.c @@ -0,0 +1,27 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_focusin(XFocusChangeEvent *ev) { + Window *w; + + /* Yes, we're focusing in on nothing, here. */ + if(ev->detail == NotifyDetailNone) { + /* FIXME: Do something. */ + return; + } + + if(!((ev->detail == NotifyNonlinear) + ||(ev->detail == NotifyNonlinearVirtual) + ||(ev->detail == NotifyVirtual) + ||(ev->detail == NotifyInferior) + ||(ev->detail == NotifyAncestor))) + return; + if((ev->mode == NotifyWhileGrabbed)) + return; + + if((w = findwin(ev->window))) + handle(w, focusin, ev); +} diff --git a/libstuff/event/focusout.c b/libstuff/event/focusout.c @@ -0,0 +1,19 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_focusout(XFocusChangeEvent *ev) { + Window *w; + + if(!((ev->detail == NotifyNonlinear) + ||(ev->detail == NotifyNonlinearVirtual) + ||(ev->detail == NotifyVirtual) + ||(ev->detail == NotifyInferior) + ||(ev->detail == NotifyAncestor))) + return; + + if((w = findwin(ev->window))) + handle(w, focusout, ev); +} diff --git a/libstuff/event/keypress.c b/libstuff/event/keypress.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_keypress(XKeyEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, kdown, ev); +} diff --git a/libstuff/event/leavenotify.c b/libstuff/event/leavenotify.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_leavenotify(XCrossingEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, leave, ev); +} diff --git a/libstuff/event/mapnotify.c b/libstuff/event/mapnotify.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_mapnotify(XMapEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, map, ev); +} diff --git a/libstuff/event/mappingnotify.c b/libstuff/event/mappingnotify.c @@ -0,0 +1,11 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_mappingnotify(XMappingEvent *ev) { + + /* Why do you need me to tell you this? */ + XRefreshKeyboardMapping(ev); +} diff --git a/libstuff/event/maprequest.c b/libstuff/event/maprequest.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_maprequest(XMapRequestEvent *ev) { + Window *w; + + if((w = findwin(ev->parent))) + handle(w, mapreq, ev); +} diff --git a/libstuff/event/motionnotify.c b/libstuff/event/motionnotify.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_motionnotify(XMotionEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, motion, ev); +} diff --git a/libstuff/event/propertynotify.c b/libstuff/event/propertynotify.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_propertynotify(XPropertyEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, property, ev); +} diff --git a/libstuff/event/unmapnotify.c b/libstuff/event/unmapnotify.c @@ -0,0 +1,15 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_unmapnotify(XUnmapEvent *ev) { + Window *w; + + 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); + } +} diff --git a/libstuff/event/xtime.c b/libstuff/event/xtime.c @@ -0,0 +1,33 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/x.h> + +static int +findtime(Display *d, XEvent *e, XPointer v) { + Window *w; + + w = (Window*)v; + if(e->type == PropertyNotify && e->xproperty.window == w->xid) { + event_xtime = e->xproperty.time; + return true; + } + return false; +} + +void +event_updatextime(void) { + Window *w; + WinAttr wa; + XEvent e; + long l; + + w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0); + + XSelectInput(display, w->xid, PropertyChangeMask); + changeprop_long(w, "ATOM", "ATOM", &l, 0); + XIfEvent(display, &e, findtime, (void*)w); + + destroywindow(w); +} + diff --git a/libstuff/geom/get_sticky.c b/libstuff/geom/get_sticky.c @@ -0,0 +1,24 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +Align +get_sticky(Rectangle src, Rectangle dst) { + Align corner; + + corner = 0; + if(src.min.x != dst.min.x + && src.max.x == dst.max.x) + corner |= East; + else + corner |= West; + + if(src.min.y != dst.min.y + && src.max.y == dst.max.y) + corner |= South; + else + corner |= North; + + return corner; +} diff --git a/libstuff/geom/quadrant.c b/libstuff/geom/quadrant.c @@ -0,0 +1,23 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +Align +quadrant(Rectangle r, Point pt) { + Align ret; + + pt = subpt(pt, r.min); + ret = 0; + + if(pt.x >= Dx(r) * .5) + ret |= East; + if(pt.x <= Dx(r) * .5) + ret |= West; + if(pt.y <= Dy(r) * .5) + ret |= North; + if(pt.y >= Dy(r) * .5) + ret |= South; + + return ret; +} diff --git a/libstuff/geom/rect_contains_p.c b/libstuff/geom/rect_contains_p.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +bool +rect_contains_p(Rectangle r, Rectangle r2) { + return r2.min.x >= r.min.x + && r2.max.x <= r.max.x + && r2.min.y >= r.min.y + && r2.max.y <= r.max.y; +} diff --git a/libstuff/geom/rect_haspoint_p.c b/libstuff/geom/rect_haspoint_p.c @@ -0,0 +1,10 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +bool +rect_haspoint_p(Point pt, Rectangle r) { + return (pt.x >= r.min.x) && (pt.x < r.max.x) + && (pt.y >= r.min.y) && (pt.y < r.max.y); +} diff --git a/libstuff/geom/rect_intersect_p.c b/libstuff/geom/rect_intersect_p.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +bool +rect_intersect_p(Rectangle r, Rectangle r2) { + return r.min.x <= r2.max.x + && r.max.x >= r2.min.x + && r.min.y <= r2.max.y + && r.max.y >= r2.min.y; +} diff --git a/libstuff/geom/rect_intersection.c b/libstuff/geom/rect_intersection.c @@ -0,0 +1,17 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> +#include <stuff/util.h> + +Rectangle +rect_intersection(Rectangle r, Rectangle r2) { + Rectangle ret; + + /* ret != canonrect(ret) ≡ no intersection. */ + ret.min.x = max(r.min.x, r2.min.x); + ret.max.x = min(r.max.x, r2.max.x); + ret.min.y = max(r.min.y, r2.min.y); + ret.max.y = min(r.max.y, r2.max.y); + return ret; +} diff --git a/libstuff/init_screens.c b/libstuff/init_screens.c @@ -0,0 +1,9 @@ +/* Copyright ©2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ + +void init_screens(void); +void +init_screens(void) { +} + diff --git a/libstuff/map.c b/libstuff/map.c @@ -0,0 +1,127 @@ +/* Written by Kris Maglione */ +/* Public domain */ +#include <stdlib.h> +#include <string.h> +#include <stuff/util.h> + +/* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */ + +struct MapEnt { + ulong hash; + const char* key; + void* val; + MapEnt* next; +}; + +MapEnt *NM; + +/* By Dan Bernstein. Public domain. */ +static ulong +hash(const char *str) { + ulong h; + + h = 5381; + while (*str != '\0') { + h += h << 5; /* h *= 33 */ + h ^= *str++; + } + return h; +} + +static void +insert(MapEnt **e, ulong val, const char *key) { + MapEnt *te; + + te = emallocz(sizeof *te); + te->hash = val; + te->key = key; + te->next = *e; + *e = te; +} + +static MapEnt** +map_getp(Map *map, ulong val, int create) { + MapEnt **e; + + e = &map->bucket[val%map->nhash]; + for(; *e; e = &(*e)->next) + if((*e)->hash >= val) break; + if(*e == nil || (*e)->hash != val) { + if(create) + insert(e, val, nil); + else + e = &NM; + } + return e; +} + +static MapEnt** +hash_getp(Map *map, const char *str, int create) { + MapEnt **e; + ulong h; + int cmp; + + h = hash(str); + e = map_getp(map, h, create); + if(*e && (*e)->key == nil) + (*e)->key = str; + else { + SET(cmp); + for(; *e; e = &(*e)->next) + if((*e)->hash > h || (cmp = strcmp((*e)->key, str)) >= 0) + break; + if(*e == nil || (*e)->hash > h || cmp > 0) + if(create) + insert(e, h, str); + } + return e; +} + +void** +map_get(Map *map, ulong val, bool create) { + MapEnt *e; + + e = *map_getp(map, val, create); + return e ? &e->val : nil; +} + +void** +hash_get(Map *map, const char *str, bool create) { + MapEnt *e; + + e = *hash_getp(map, str, create); + return e ? &e->val : nil; +} + +void* +map_rm(Map *map, ulong val) { + MapEnt **e, *te; + void *ret; + + ret = nil; + e = map_getp(map, val, 0); + if(*e) { + te = *e; + ret = te->val; + *e = te->next; + free(te); + } + return ret; +} + +void* +hash_rm(Map *map, const char *str) { + MapEnt **e, *te; + void *ret; + + ret = nil; + e = hash_getp(map, str, 0); + if(*e) { + te = *e; + ret = te->val; + *e = te->next; + free(te); + } + return ret; +} + diff --git a/libstuff/printevent.c b/libstuff/printevent.c @@ -0,0 +1,994 @@ +/* + * Original code posted to comp.sources.x + * Modifications by Russ Cox <rsc@swtch.com>. + * Further modifications by Kris Maglione <maglione.k at Gmail> + */ + +/* + * Path: uunet!wyse!mikew From: mikew@wyse.wyse.com (Mike Wexler) Newsgroups: + * comp.sources.x Subject: v02i056: subroutine to print events in human + * readable form, Part01/01 Message-ID: <1935@wyse.wyse.com> Date: 22 Dec 88 + * 19:28:25 GMT Organization: Wyse Technology, San Jose Lines: 1093 Approved: + * mikew@wyse.com + * + * Submitted-by: richsun!darkstar!ken Posting-number: Volume 2, Issue 56 + * Archive-name: showevent/part01 + * + * + * There are times during debugging when it would be real useful to be able to + * print the fields of an event in a human readable form. Too many times I + * found myself scrounging around in section 8 of the Xlib manual looking for + * the valid fields for the events I wanted to see, then adding printf's to + * display the numeric values of the fields, and then scanning through X.h + * trying to decode the cryptic detail and state fields. After playing with + * xev, I decided to write a couple of standard functions that I could keep + * in a library and call on whenever I needed a little debugging verbosity. + * The first function, GetType(), is useful for returning the string + * representation of the type of an event. The second function, ShowEvent(), + * is used to display all the fields of an event in a readable format. The + * functions are not complicated, in fact, they are mind-numbingly boring - + * but that's just the point nobody wants to spend the time writing functions + * like this, they just want to have them when they need them. + * + * A simple, sample program is included which does little else but to + * demonstrate the use of these two functions. These functions have saved me + * many an hour during debugging and I hope you find some benefit to these. + * If you have any comments, suggestions, improvements, or if you find any + * blithering errors you can get it touch with me at the following location: + * + * ken@richsun.UUCP + */ + +#include <stdarg.h> +#include <bio.h> +#include <stuff/x.h> +#include <stuff/util.h> +#include "printevent.h" +#define Window XWindow + +#define nil ((void*)0) + +typedef struct Pair Pair; + +struct Pair { + int key; + char *val; +}; + +static char* sep = " "; + +static char * +search(Pair *lst, int key, char *(*def)(int)) { + for(; lst->val; lst++) + if(lst->key == key) + return lst->val; + return def(key); +} + +static char* +unmask(Pair *list, uint val) +{ + Pair *p; + char *s, *end; + int n; + + buffer[0] = '\0'; + end = buffer + sizeof buffer; + s = buffer; + + n = 0; + s = utfecpy(s, end, "("); + for (p = list; p->val; p++) + if (val & p->key) { + if(n++) + s = utfecpy(s, end, "|"); + s = utfecpy(s, end, p->val); + } + utfecpy(s, end, ")"); + + return buffer; +} + +static char * +strhex(int key) { + sprint(buffer, "0x%x", key); + return buffer; +} + +static char * +strdec(int key) { + sprint(buffer, "%d", key); + return buffer; +} + +static char * +strign(int key) { + USED(key); + + return "?"; +} + +/******************************************************************************/ +/**** Miscellaneous routines to convert values to their string equivalents ****/ +/******************************************************************************/ + +static void +TInt(Fmt *b, va_list *ap) { + fmtprint(b, "%d", va_arg(*ap, int)); +} + +static void +TWindow(Fmt *b, va_list *ap) { + Window w; + + w = va_arg(*ap, Window); + fmtprint(b, "0x%ux", (uint)w); +} + +static void +TData(Fmt *b, va_list *ap) { + long *l; + int i; + + l = va_arg(*ap, long*); + fmtprint(b, "{"); + for (i = 0; i < 5; i++) { + if(i > 0) + fmtprint(b, ", "); + fmtprint(b, "0x%08lx", l[i]); + } + fmtprint(b, "}"); +} + +/* Returns the string equivalent of a timestamp */ +static void +TTime(Fmt *b, va_list *ap) { + ldiv_t d; + ulong msec; + ulong sec; + ulong min; + ulong hr; + ulong day; + Time time; + + time = va_arg(*ap, Time); + + msec = time/1000; + d = ldiv(msec, 60); + msec = time-msec*1000; + + sec = d.rem; + d = ldiv(d.quot, 60); + min = d.rem; + d = ldiv(d.quot, 24); + hr = d.rem; + day = d.quot; + +#ifdef notdef + sprintf(buffer, "%lu day%s %02lu:%02lu:%02lu.%03lu", + day, day == 1 ? "" : "(s)", hr, min, sec, msec); +#endif + + fmtprint(b, "%ludd_%ludh_%ludm_%lud.%03luds", day, hr, min, sec, msec); +} + +/* Returns the string equivalent of a boolean parameter */ +static void +TBool(Fmt *b, va_list *ap) { + static Pair list[] = { + {True, "True"}, + {False, "False"}, + {0, nil}, + }; + Bool key; + + key = va_arg(*ap, Bool); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a property notify state */ +static void +TPropState(Fmt *b, va_list *ap) { + static Pair list[] = { + {PropertyNewValue, "PropertyNewValue"}, + {PropertyDelete, "PropertyDelete"}, + {0, nil}, + }; + uint key; + + key = va_arg(*ap, uint); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a visibility notify state */ +static void +TVis(Fmt *b, va_list *ap) { + static Pair list[] = { + {VisibilityUnobscured, "VisibilityUnobscured"}, + {VisibilityPartiallyObscured, "VisibilityPartiallyObscured"}, + {VisibilityFullyObscured, "VisibilityFullyObscured"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a mask of buttons and/or modifier keys */ +static void +TModState(Fmt *b, va_list *ap) { + static Pair list[] = { + {Button1Mask, "Button1Mask"}, + {Button2Mask, "Button2Mask"}, + {Button3Mask, "Button3Mask"}, + {Button4Mask, "Button4Mask"}, + {Button5Mask, "Button5Mask"}, + {ShiftMask, "ShiftMask"}, + {LockMask, "LockMask"}, + {ControlMask, "ControlMask"}, + {Mod1Mask, "Mod1Mask"}, + {Mod2Mask, "Mod2Mask"}, + {Mod3Mask, "Mod3Mask"}, + {Mod4Mask, "Mod4Mask"}, + {Mod5Mask, "Mod5Mask"}, + {0, nil}, + }; + uint state; + + state = va_arg(*ap, uint); + fmtprint(b, "%s", unmask(list, state)); +} + +/* Returns the string equivalent of a mask of configure window values */ +static void +TConfMask(Fmt *b, va_list *ap) { + static Pair list[] = { + {CWX, "CWX"}, + {CWY, "CWY"}, + {CWWidth, "CWWidth"}, + {CWHeight, "CWHeight"}, + {CWBorderWidth, "CWBorderWidth"}, + {CWSibling, "CWSibling"}, + {CWStackMode, "CWStackMode"}, + {0, nil}, + }; + uint valuemask; + + valuemask = va_arg(*ap, uint); + fmtprint(b, "%s", unmask(list, valuemask)); +} + +/* Returns the string equivalent of a motion hint */ +#if 0 +static void +IsHint(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyNormal, "NotifyNormal"}, + {NotifyHint, "NotifyHint"}, + {0, nil}, + }; + char key; + + key = va_arg(*ap, char); + fmtprint(b, "%s", search(list, key, strign)); +} +#endif + +/* Returns the string equivalent of an id or the value "None" */ +static void +TIntNone(Fmt *b, va_list *ap) { + static Pair list[] = { + {None, "None"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strhex)); +} + +/* Returns the string equivalent of a colormap state */ +static void +TColMap(Fmt *b, va_list *ap) { + static Pair list[] = { + {ColormapInstalled, "ColormapInstalled"}, + {ColormapUninstalled, "ColormapUninstalled"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a crossing detail */ +static void +TXing(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyAncestor, "NotifyAncestor"}, + {NotifyInferior, "NotifyInferior"}, + {NotifyVirtual, "NotifyVirtual"}, + {NotifyNonlinear, "NotifyNonlinear"}, + {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a focus change detail */ +static void +TFocus(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyAncestor, "NotifyAncestor"}, + {NotifyInferior, "NotifyInferior"}, + {NotifyVirtual, "NotifyVirtual"}, + {NotifyNonlinear, "NotifyNonlinear"}, + {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, + {NotifyPointer, "NotifyPointer"}, + {NotifyPointerRoot, "NotifyPointerRoot"}, + {NotifyDetailNone, "NotifyDetailNone"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a configure detail */ +static void +TConfDetail(Fmt *b, va_list *ap) { + static Pair list[] = { + {Above, "Above"}, + {Below, "Below"}, + {TopIf, "TopIf"}, + {BottomIf, "BottomIf"}, + {Opposite, "Opposite"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a grab mode */ +static void +TGrabMode(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyNormal, "NotifyNormal"}, + {NotifyGrab, "NotifyGrab"}, + {NotifyUngrab, "NotifyUngrab"}, + {NotifyWhileGrabbed, "NotifyWhileGrabbed"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a mapping request */ +static void +TMapping(Fmt *b, va_list *ap) { + static Pair list[] = { + {MappingModifier, "MappingModifier"}, + {MappingKeyboard, "MappingKeyboard"}, + {MappingPointer, "MappingPointer"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a stacking order place */ +static void +TPlace(Fmt *b, va_list *ap) { + static Pair list[] = { + {PlaceOnTop, "PlaceOnTop"}, + {PlaceOnBottom, "PlaceOnBottom"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a major code */ +static void +TMajor(Fmt *b, va_list *ap) { + static char *list[] = { XMajors }; + char *s; + uint key; + + key = va_arg(*ap, uint); + s = "<nil>"; + if(key < nelem(list)) + s = list[key]; + fmtprint(b, "%s", s); +} + +static char* +eventtype(int key) { + static Pair list[] = { + {ButtonPress, "ButtonPress"}, + {ButtonRelease, "ButtonRelease"}, + {CirculateNotify, "CirculateNotify"}, + {CirculateRequest, "CirculateRequest"}, + {ClientMessage, "ClientMessage"}, + {ColormapNotify, "ColormapNotify"}, + {ConfigureNotify, "ConfigureNotify"}, + {ConfigureRequest, "ConfigureRequest"}, + {CreateNotify, "CreateNotify"}, + {DestroyNotify, "DestroyNotify"}, + {EnterNotify, "EnterNotify"}, + {Expose, "Expose"}, + {FocusIn, "FocusIn"}, + {FocusOut, "FocusOut"}, + {GraphicsExpose, "GraphicsExpose"}, + {GravityNotify, "GravityNotify"}, + {KeyPress, "KeyPress"}, + {KeyRelease, "KeyRelease"}, + {KeymapNotify, "KeymapNotify"}, + {LeaveNotify, "LeaveNotify"}, + {MapNotify, "MapNotify"}, + {MapRequest, "MapRequest"}, + {MappingNotify, "MappingNotify"}, + {MotionNotify, "MotionNotify"}, + {NoExpose, "NoExpose"}, + {PropertyNotify, "PropertyNotify"}, + {ReparentNotify, "ReparentNotify"}, + {ResizeRequest, "ResizeRequest"}, + {SelectionClear, "SelectionClear"}, + {SelectionNotify, "SelectionNotify"}, + {SelectionRequest, "SelectionRequest"}, + {UnmapNotify, "UnmapNotify"}, + {VisibilityNotify, "VisibilityNotify"}, + {0, nil}, + }; + return search(list, key, strdec); +} +/* Returns the string equivalent the keycode contained in the key event */ +static void +TKeycode(Fmt *b, va_list *ap) { + KeySym keysym_str; + XKeyEvent *ev; + char *keysym_name; + + ev = va_arg(*ap, XKeyEvent*); + + XLookupString(ev, buffer, sizeof buffer, &keysym_str, nil); + + if (keysym_str == NoSymbol) + keysym_name = "NoSymbol"; + else + keysym_name = XKeysymToString(keysym_str); + if(keysym_name == nil) + keysym_name = "(no name)"; + + fmtprint(b, "%ud (keysym 0x%x \"%s\")", (int)ev->keycode, + (int)keysym_str, keysym_name); +} + +/* Returns the string equivalent of an atom or "None" */ +static void +TAtom(Fmt *b, va_list *ap) { + char *atom_name; + Atom atom; + + atom = va_arg(*ap, Atom); + atom_name = XGetAtomName(display, atom); + fmtprint(b, "%s", atom_name); + XFree(atom_name); +} + +#define _(m) #m, ev->m +#define TEnd nil +typedef void (*Tfn)(Fmt*, va_list*); + +static int +pevent(Fmt *fmt, void *e, ...) { + va_list ap; + Tfn fn; + XAnyEvent *ev; + char *key; + int n; + + ev = e; + fmtprint(fmt, "%3ld %-20s ", ev->serial, eventtype(ev->type)); + if(ev->send_event) + fmtstrcpy(fmt, "(sendevent) "); + + n = 0; + va_start(ap, e); + for(;;) { + fn = va_arg(ap, Tfn); + if(fn == TEnd) + break; + + if(n++ != 0) + fmtprint(fmt, "%s", sep); + + key = va_arg(ap, char*); + fmtprint(fmt, "%s=", key); + fn(fmt, &ap); + } + va_end(ap); + return 0; +} + +/*****************************************************************************/ +/*** Routines to print out readable values for the field of various events ***/ +/*****************************************************************************/ + +static int +VerbMotion(Fmt *fmt, XEvent *e) { + XMotionEvent *ev = &e->xmotion; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TModState, _(state), + TBool, _(same_screen), + TEnd + ); + //fprintf(stderr, "is_hint=%s%s", IsHint(ev->is_hint), sep); +} + +static int +VerbButton(Fmt *fmt, XEvent *e) { + XButtonEvent *ev = &e->xbutton; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TModState, _(state), + TModState, _(button), + TBool, _(same_screen), + TEnd + ); +} + +static int +VerbColormap(Fmt *fmt, XEvent *e) { + XColormapEvent *ev = &e->xcolormap; + + return pevent(fmt, ev, + TWindow, _(window), + TIntNone, _(colormap), + TBool, _(new), + TColMap, _(state), + TEnd + ); +} + +static int +VerbCrossing(Fmt *fmt, XEvent *e) { + XCrossingEvent *ev = &e->xcrossing; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TGrabMode, _(mode), + TXing, _(detail), + TBool, _(same_screen), + TBool, _(focus), + TModState, _(state), + TEnd + ); +} + +static int +VerbExpose(Fmt *fmt, XEvent *e) { + XExposeEvent *ev = &e->xexpose; + + return pevent(fmt, ev, + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(count), + TEnd + ); +} + +static int +VerbGraphicsExpose(Fmt *fmt, XEvent *e) { + XGraphicsExposeEvent *ev = &e->xgraphicsexpose; + + return pevent(fmt, ev, + TWindow, _(drawable), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TMajor, _(major_code), + TInt, _(minor_code), + TEnd + ); +} + +static int +VerbNoExpose(Fmt *fmt, XEvent *e) { + XNoExposeEvent *ev = &e->xnoexpose; + + return pevent(fmt, ev, + TWindow, _(drawable), + TMajor, _(major_code), + TInt, _(minor_code), + TEnd + ); +} + +static int +VerbFocus(Fmt *fmt, XEvent *e) { + XFocusChangeEvent *ev = &e->xfocus; + + return pevent(fmt, ev, + TWindow, _(window), + TGrabMode, _(mode), + TFocus, _(detail), + TEnd + ); +} + +static int +VerbKeymap(Fmt *fmt, XEvent *e) { + XKeymapEvent *ev = &e->xkeymap; + int i; + + fmtprint(fmt, "window=0x%x%s", (int)ev->window, sep); + fmtprint(fmt, "key_vector="); + for (i = 0; i < 32; i++) + fmtprint(fmt, "%02x", ev->key_vector[i]); + fmtprint(fmt, "\n"); + return 0; +} + +static int +VerbKey(Fmt *fmt, XEvent *e) { + XKeyEvent *ev = &e->xkey; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TModState, _(state), + TKeycode, "keycode", ev, + TBool, _(same_screen), + TEnd + ); +} + +static int +VerbProperty(Fmt *fmt, XEvent *e) { + XPropertyEvent *ev = &e->xproperty; + + return pevent(fmt, ev, + TWindow, _(window), + TAtom, _(atom), + TTime, _(time), + TPropState, _(state), + TEnd + ); +} + +static int +VerbResizeRequest(Fmt *fmt, XEvent *e) { + XResizeRequestEvent *ev = &e->xresizerequest; + + return pevent(fmt, ev, + TWindow, _(window), + TInt, _(width), TInt, _(height), + TEnd + ); +} + +static int +VerbCirculate(Fmt *fmt, XEvent *e) { + XCirculateEvent *ev = &e->xcirculate; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TPlace, _(place), + TEnd + ); +} + +static int +VerbConfigure(Fmt *fmt, XEvent *e) { + XConfigureEvent *ev = &e->xconfigure; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(border_width), + TIntNone, _(above), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbCreateWindow(Fmt *fmt, XEvent *e) { + XCreateWindowEvent *ev = &e->xcreatewindow; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(border_width), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbDestroyWindow(Fmt *fmt, XEvent *e) { + XDestroyWindowEvent *ev = &e->xdestroywindow; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TEnd + ); +} + +static int +VerbGravity(Fmt *fmt, XEvent *e) { + XGravityEvent *ev = &e->xgravity; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TEnd + ); +} + +static int +VerbMap(Fmt *fmt, XEvent *e) { + XMapEvent *ev = &e->xmap; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbReparent(Fmt *fmt, XEvent *e) { + XReparentEvent *ev = &e->xreparent; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TWindow, _(parent), + TInt, _(x), TInt, _(y), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbUnmap(Fmt *fmt, XEvent *e) { + XUnmapEvent *ev = &e->xunmap; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TBool, _(from_configure), + TEnd + ); +} + +static int +VerbCirculateRequest(Fmt *fmt, XEvent *e) { + XCirculateRequestEvent *ev = &e->xcirculaterequest; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TPlace, _(place), + TEnd + ); +} + +static int +VerbConfigureRequest(Fmt *fmt, XEvent *e) { + XConfigureRequestEvent *ev = &e->xconfigurerequest; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(border_width), + TIntNone, _(above), + TConfDetail, _(detail), + TConfMask, _(value_mask), + TEnd + ); +} + +static int +VerbMapRequest(Fmt *fmt, XEvent *e) { + XMapRequestEvent *ev = &e->xmaprequest; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TEnd + ); +} + +static int +VerbClient(Fmt *fmt, XEvent *e) { + XClientMessageEvent *ev = &e->xclient; + + return pevent(fmt, ev, + TWindow, _(window), + TAtom, _(message_type), + TInt, _(format), + TData, "data (as longs)", &ev->data, + TEnd + ); +} + +static int +VerbMapping(Fmt *fmt, XEvent *e) { + XMappingEvent *ev = &e->xmapping; + + return pevent(fmt, ev, + TWindow, _(window), + TMapping, _(request), + TWindow, _(first_keycode), + TWindow, _(count), + TEnd + ); +} + +static int +VerbSelectionClear(Fmt *fmt, XEvent *e) { + XSelectionClearEvent *ev = &e->xselectionclear; + + return pevent(fmt, ev, + TWindow, _(window), + TAtom, _(selection), + TTime, _(time), + TEnd + ); +} + +static int +VerbSelection(Fmt *fmt, XEvent *e) { + XSelectionEvent *ev = &e->xselection; + + return pevent(fmt, ev, + TWindow, _(requestor), + TAtom, _(selection), + TAtom, _(target), + TAtom, _(property), + TTime, _(time), + TEnd + ); +} + +static int +VerbSelectionRequest(Fmt *fmt, XEvent *e) { + XSelectionRequestEvent *ev = &e->xselectionrequest; + + return pevent(fmt, ev, + TWindow, _(owner), + TWindow, _(requestor), + TAtom, _(selection), + TAtom, _(target), + TAtom, _(property), + TTime, _(time), + TEnd + ); +} + +static int +VerbVisibility(Fmt *fmt, XEvent *e) { + XVisibilityEvent *ev = &e->xvisibility; + + return pevent(fmt, ev, + TWindow, _(window), + TVis, _(state), + TEnd + ); +} + +/******************************************************************************/ +/**************** Print the values of all fields for any event ****************/ +/******************************************************************************/ + +typedef struct Handler Handler; +struct Handler { + int key; + int (*fn)(Fmt*, XEvent*); +}; + +int +fmtevent(Fmt *fmt) { + XEvent *e; + XAnyEvent *ev; + /* + fprintf(stderr, "type=%s%s", eventtype(e->xany.type), sep); + fprintf(stderr, "serial=%lu%s", ev->serial, sep); + fprintf(stderr, "send_event=%s%s", TorF(ev->send_event), sep); + fprintf(stderr, "display=0x%p%s", ev->display, sep); + */ + static Handler fns[] = { + {MotionNotify, VerbMotion}, + {ButtonPress, VerbButton}, + {ButtonRelease, VerbButton}, + {ColormapNotify, VerbColormap}, + {EnterNotify, VerbCrossing}, + {LeaveNotify, VerbCrossing}, + {Expose, VerbExpose}, + {GraphicsExpose, VerbGraphicsExpose}, + {NoExpose, VerbNoExpose}, + {FocusIn, VerbFocus}, + {FocusOut, VerbFocus}, + {KeymapNotify, VerbKeymap}, + {KeyPress, VerbKey}, + {KeyRelease, VerbKey}, + {PropertyNotify, VerbProperty}, + {ResizeRequest, VerbResizeRequest}, + {CirculateNotify, VerbCirculate}, + {ConfigureNotify, VerbConfigure}, + {CreateNotify, VerbCreateWindow}, + {DestroyNotify, VerbDestroyWindow}, + {GravityNotify, VerbGravity}, + {MapNotify, VerbMap}, + {ReparentNotify, VerbReparent}, + {UnmapNotify, VerbUnmap}, + {CirculateRequest, VerbCirculateRequest}, + {ConfigureRequest, VerbConfigureRequest}, + {MapRequest, VerbMapRequest}, + {ClientMessage, VerbClient}, + {MappingNotify, VerbMapping}, + {SelectionClear, VerbSelectionClear}, + {SelectionNotify, VerbSelection}, + {SelectionRequest, VerbSelectionRequest}, + {VisibilityNotify, VerbVisibility}, + {0, nil}, + }; + Handler *p; + + e = va_arg(fmt->args, XEvent*); + ev = &e->xany; + + for (p = fns; p->fn; p++) + if (p->key == ev->type) + return p->fn(fmt, e); + return 1; +} + diff --git a/libstuff/printevent.h b/libstuff/printevent.h @@ -0,0 +1,248 @@ +int fmtevent(Fmt *fmt); + +enum { + X_CreateWindow = 1, + X_ChangeWindowAttributes, + X_GetWindowAttributes, + X_DestroyWindow, + X_DestroySubwindows, + X_ChangeSaveSet, + X_ReparentWindow, + X_MapWindow, + X_MapSubwindows, + X_UnmapWindow, + X_UnmapSubwindows, + X_ConfigureWindow, + X_CirculateWindow, + X_GetGeometry, + X_QueryTree, + X_InternAtom, + X_GetAtomName, + X_ChangeProperty, + X_DeleteProperty, + X_GetProperty, + X_ListProperties, + X_SetSelectionOwner, + X_GetSelectionOwner, + X_ConvertSelection, + X_SendEvent, + X_GrabPointer, + X_UngrabPointer, + X_GrabButton, + X_UngrabButton, + X_ChangeActivePointerGrab, + X_GrabKeyboard, + X_UngrabKeyboard, + X_GrabKey, + X_UngrabKey, + X_AllowEvents, + X_GrabServer, + X_UngrabServer, + X_QueryPointer, + X_GetMotionEvents, + X_TranslateCoords, + X_WarpPointer, + X_SetInputFocus, + X_GetInputFocus, + X_QueryKeymap, + X_OpenFont, + X_CloseFont, + X_QueryFont, + X_QueryTextExtents, + X_ListFonts, + X_ListFontsWithInfo, + X_SetFontPath, + X_GetFontPath, + X_CreatePixmap, + X_FreePixmap, + X_CreateGC, + X_ChangeGC, + X_CopyGC, + X_SetDashes, + X_SetClipRectangles, + X_FreeGC, + X_ClearArea, + X_CopyArea, + X_CopyPlane, + X_PolyPoint, + X_PolyLine, + X_PolySegment, + X_PolyRectangle, + X_PolyArc, + X_FillPoly, + X_PolyFillRectangle, + X_PolyFillArc, + X_PutImage, + X_GetImage, + X_PolyText8, + X_PolyText16, + X_ImageText8, + X_ImageText16, + X_CreateColormap, + X_FreeColormap, + X_CopyColormapAndFree, + X_InstallColormap, + X_UninstallColormap, + X_ListInstalledColormaps, + X_AllocColor, + X_AllocNamedColor, + X_AllocColorCells, + X_AllocColorPlanes, + X_FreeColors, + X_StoreColors, + X_StoreNamedColor, + X_QueryColors, + X_LookupColor, + X_CreateCursor, + X_CreateGlyphCursor, + X_FreeCursor, + X_RecolorCursor, + X_QueryBestSize, + X_QueryExtension, + X_ListExtensions, + X_ChangeKeyboardMapping, + X_GetKeyboardMapping, + X_ChangeKeyboardControl, + X_GetKeyboardControl, + X_Bell, + X_ChangePointerControl, + X_GetPointerControl, + X_SetScreenSaver, + X_GetScreenSaver, + X_ChangeHosts, + X_ListHosts, + X_SetAccessControl, + X_SetCloseDownMode, + X_KillClient, + X_RotateProperties, + X_ForceScreenSaver, + X_SetPointerMapping, + X_GetPointerMapping, + X_SetModifierMapping, + X_GetModifierMapping, + X_NoOperation, +}; + +#define XMajors \ + "<nil>",\ + "CreateWindow",\ + "ChangeWindowAttributes",\ + "GetWindowAttributes",\ + "DestroyWindow",\ + "DestroySubwindows",\ + "ChangeSaveSet",\ + "ReparentWindow",\ + "MapWindow",\ + "MapSubwindows",\ + "UnmapWindow",\ + "UnmapSubwindows",\ + "ConfigureWindow",\ + "CirculateWindow",\ + "GetGeometry",\ + "QueryTree",\ + "InternAtom",\ + "GetAtomName",\ + "ChangeProperty",\ + "DeleteProperty",\ + "GetProperty",\ + "ListProperties",\ + "SetSelectionOwner",\ + "GetSelectionOwner",\ + "ConvertSelection",\ + "SendEvent",\ + "GrabPointer",\ + "UngrabPointer",\ + "GrabButton",\ + "UngrabButton",\ + "ChangeActivePointerGrab",\ + "GrabKeyboard",\ + "UngrabKeyboard",\ + "GrabKey",\ + "UngrabKey",\ + "AllowEvents",\ + "GrabServer",\ + "UngrabServer",\ + "QueryPointer",\ + "GetMotionEvents",\ + "TranslateCoords",\ + "WarpPointer",\ + "SetInputFocus",\ + "GetInputFocus",\ + "QueryKeymap",\ + "OpenFont",\ + "CloseFont",\ + "QueryFont",\ + "QueryTextExtents",\ + "ListFonts",\ + "ListFontsWithInfo",\ + "SetFontPath",\ + "GetFontPath",\ + "CreatePixmap",\ + "FreePixmap",\ + "CreateGC",\ + "ChangeGC",\ + "CopyGC",\ + "SetDashes",\ + "SetClipRectangles",\ + "FreeGC",\ + "ClearArea",\ + "CopyArea",\ + "CopyPlane",\ + "PolyPoint",\ + "PolyLine",\ + "PolySegment",\ + "PolyRectangle",\ + "PolyArc",\ + "FillPoly",\ + "PolyFillRectangle",\ + "PolyFillArc",\ + "PutImage",\ + "GetImage",\ + "PolyText8",\ + "PolyText16",\ + "ImageText8",\ + "ImageText16",\ + "CreateColormap",\ + "FreeColormap",\ + "CopyColormapAndFree",\ + "InstallColormap",\ + "UninstallColormap",\ + "ListInstalledColormaps",\ + "AllocColor",\ + "AllocNamedColor",\ + "AllocColorCells",\ + "AllocColorPlanes",\ + "FreeColors",\ + "StoreColors",\ + "StoreNamedColor",\ + "QueryColors",\ + "LookupColor",\ + "CreateCursor",\ + "CreateGlyphCursor",\ + "FreeCursor",\ + "RecolorCursor",\ + "QueryBestSize",\ + "QueryExtension",\ + "ListExtensions",\ + "ChangeKeyboardMapping",\ + "GetKeyboardMapping",\ + "ChangeKeyboardControl",\ + "GetKeyboardControl",\ + "Bell",\ + "ChangePointerControl",\ + "GetPointerControl",\ + "SetScreenSaver",\ + "GetScreenSaver",\ + "ChangeHosts",\ + "ListHosts",\ + "SetAccessControl",\ + "SetCloseDownMode",\ + "KillClient",\ + "RotateProperties",\ + "ForceScreenSaver",\ + "SetPointerMapping",\ + "GetPointerMapping",\ + "SetModifierMapping",\ + "GetModifierMapping",\ + "NoOperation",\ + diff --git a/libstuff/util/_die.c b/libstuff/util/_die.c @@ -0,0 +1,27 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <sys/types.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> +#include <fmt.h> +#include "util.h" + +void +_die(char *file, int line, char *msg, ...) { + va_list ap; + + va_start(ap, msg); + fprint(2, "%s: dieing at %s:%d: %s\n", + argv0, file, line, + vsxprint(msg, ap)); + va_end(ap); + + kill(getpid(), SIGABRT); + abort(); /* Adds too many frames: + * _die() + * abort() + * raise(SIGABRT) + * kill(getpid(), SIGABRT) + */ +} diff --git a/libstuff/util/backtrace.c b/libstuff/util/backtrace.c @@ -0,0 +1,88 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <signal.h> +#include <stdlib.h> + +#include <bio.h> +#include <plan9.h> +#undef nelem +#include <debug.h> +#include "util.h" + +#ifdef __linux__ +# define PROGTXT "exe" +#else +# define PROGTXT "file" +#endif + +static void +_backtrace(int pid, char *btarg) { + char *proc, *spid, *gdbcmd; + int fd[3], p[2]; + int status, cmdfd; + + gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX"); + if(pipe(p) < 0) + goto done; + closeexec(p[0]); + + cmdfd = mkstemp(gdbcmd); + if(cmdfd < 0) + goto done; + + fprint(cmdfd, "bt %s\n", btarg); + fprint(cmdfd, "detach\n"); + close(cmdfd); + + fd[0] = open("/dev/null", O_RDONLY); + fd[1] = p[1]; + fd[2] = dup(2); + + proc = sxprint("/proc/%d/" PROGTXT, pid); + spid = sxprint("%d", pid); + if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) { + unlink(gdbcmd); + goto done; + } + + Biobuf bp; + char *s; + + Binit(&bp, p[0], OREAD); + while((s = Brdstr(&bp, '\n', 1))) { + Dprint(DStack, "%s\n", s); + free(s); + } + unlink(gdbcmd); + +done: + free(gdbcmd); + kill(pid, SIGKILL); + waitpid(pid, &status, 0); +} + +void +backtrace(char *btarg) { + int pid; + + /* Fork so we can backtrace the child. Keep this stack + * frame minimal, so the trace is fairly clean. + */ + Debug(DStack) + switch(pid = fork()) { + case -1: + return; + case 0: + kill(getpid(), SIGSTOP); + _exit(0); + default: + _backtrace(pid, btarg); + break; + } + +} diff --git a/libstuff/util/closeexec.c b/libstuff/util/closeexec.c @@ -0,0 +1,12 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <unistd.h> +#include <fcntl.h> +#include "util.h" + +void +closeexec(int fd) { + if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + fatal("can't set %d close on exec: %r", fd); +} diff --git a/libstuff/util/comm.c b/libstuff/util/comm.c @@ -0,0 +1,42 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "util.h" +#include <stuff/x11.h> + + +char** +comm(int cols, char **toka, char **tokb) { + Vector_ptr vec; + char **ret; + int cmp; + + vector_pinit(&vec); + while(*toka || *tokb) { + if(!*toka) + cmp = 1; + else if(!*tokb) + cmp = -1; + else + cmp = strcmp(*toka, *tokb); + if(cmp < 0) { + if(cols & CLeft) + vector_ppush(&vec, *toka); + toka++; + }else if(cmp > 0) { + if(cols & CRight) + vector_ppush(&vec, *tokb); + tokb++; + }else { + if(cols & CCenter) + vector_ppush(&vec, *toka); + toka++; + tokb++; + } + } + vector_ppush(&vec, nil); + ret = strlistdup((char**)vec.ary); + free(vec.ary); + return ret; +} diff --git a/libstuff/util/doublefork.c b/libstuff/util/doublefork.c @@ -0,0 +1,31 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <sys/wait.h> +#include <stdlib.h> +#include <unistd.h> +#include "util.h" + +int +doublefork(void) { + pid_t pid; + int status; + + switch(pid=fork()) { + case -1: + fatal("Can't fork(): %r"); + case 0: + switch(pid=fork()) { + case -1: + fatal("Can't fork(): %r"); + case 0: + return 0; + default: + exit(0); + } + default: + waitpid(pid, &status, 0); + return pid; + } + /* NOTREACHED */ +} diff --git a/libstuff/util/emalloc.c b/libstuff/util/emalloc.c @@ -0,0 +1,12 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <stdlib.h> +#include "util.h" + +void * +emalloc(uint size) { + void *ret = malloc(size); + if(!ret) + mfatal("malloc", size); + return ret; +} diff --git a/libstuff/util/emallocz.c b/libstuff/util/emallocz.c @@ -0,0 +1,11 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +void* +emallocz(uint size) { + void *ret = emalloc(size); + memset(ret, 0, size); + return ret; +} diff --git a/libstuff/util/erealloc.c b/libstuff/util/erealloc.c @@ -0,0 +1,12 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <stdlib.h> +#include "util.h" + +void * +erealloc(void *ptr, uint size) { + void *ret = realloc(ptr, size); + if(!ret) + mfatal("realloc", size); + return ret; +} diff --git a/libstuff/util/estrdup.c b/libstuff/util/estrdup.c @@ -0,0 +1,12 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +char* +estrdup(const char *str) { + void *ret = strdup(str); + if(!ret) + mfatal("strdup", strlen(str)); + return ret; +} diff --git a/libstuff/util/estrndup.c b/libstuff/util/estrndup.c @@ -0,0 +1,15 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +char* +estrndup(const char *str, uint len) { + char *ret; + + len = min(len, strlen(str)); + ret = emalloc(len + 1); + memcpy(ret, str, len); + ret[len] = '\0'; + return ret; +} diff --git a/libstuff/util/fatal.c b/libstuff/util/fatal.c @@ -0,0 +1,40 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <stdlib.h> +#include <fmt.h> +#include "util.h" + +typedef struct VFmt VFmt; +struct VFmt { + const char *fmt; + va_list args; +}; + +#ifdef VARARGCK +# pragma varargck type "V" VFmt* +#endif + +static int +Vfmt(Fmt *f) { + VFmt *vf; + int i; + + vf = va_arg(f->args, VFmt*); + i = fmtvprint(f, vf->fmt, vf->args); + return i; +} + +void +fatal(const char *fmt, ...) { + VFmt fp; + + fmtinstall('V', Vfmt); + fmtinstall('', Vfmt); + + fp.fmt = fmt; + va_start(fp.args, fmt); + fprint(2, "%s: fatal: %V\n", argv0, &fp); + va_end(fp.args); + + exit(1); +} diff --git a/libstuff/util/freelater.c b/libstuff/util/freelater.c @@ -0,0 +1,16 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <stdlib.h> +#include "util.h" + +void* +freelater(void *p) { + static char* obj[16]; + static long nobj; + int id; + + id = nobj++ % nelem(obj); + free(obj[id]); + obj[id] = p; + return p; +} diff --git a/libstuff/util/getbase.c b/libstuff/util/getbase.c @@ -0,0 +1,43 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <ctype.h> +#include <string.h> +#include <stuff/util.h> + +#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1)) +int +getbase(const char **s, long *sign) { + const char *p; + int ret; + + ret = 10; + *sign = 1; + if(**s == '-') { + *sign = -1; + *s += 1; + }else if(**s == '+') + *s += 1; + + p = *s; + if(!strbcmp(p, "0x")) { + *s += 2; + ret = 16; + } + else if(isdigit(p[0])) { + if(p[1] == 'r') { + *s += 2; + ret = p[0] - '0'; + } + else if(isdigit(p[1]) && p[2] == 'r') { + *s += 3; + ret = 10*(p[0]-'0') + (p[1]-'0'); + } + } + else if(p[0] == '0') { + ret = 8; + } + if(ret != 10 && (**s == '-' || **s == '+')) + *sign = 0; + return ret; +} diff --git a/libstuff/util/getint.c b/libstuff/util/getint.c @@ -0,0 +1,14 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/util.h> + +bool +getint(const char *s, int *ret) { + long l; + bool res; + + res = getlong(s, &l); + *ret = l; + return res; +} diff --git a/libstuff/util/getlong.c b/libstuff/util/getlong.c @@ -0,0 +1,24 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stdlib.h> +#include <string.h> +#include <stuff/util.h> + +bool +getlong(const char *s, long *ret) { + const char *end; + char *rend; + int base; + long sign; + + if(s == nil) + return false; + end = s+strlen(s); + base = getbase(&s, &sign); + if(sign == 0) + return false; + + *ret = sign * strtol(s, &rend, base); + return (end == rend); +} diff --git a/libstuff/util/getulong.c b/libstuff/util/getulong.c @@ -0,0 +1,24 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stdlib.h> +#include <string.h> +#include <stuff/util.h> + +bool +getulong(const char *s, ulong *ret) { + const char *end; + char *rend; + int base; + long sign; + + if(s == nil) + return false; + end = s+strlen(s); + base = getbase(&s, &sign); + if(sign < 1) + return false; + + *ret = strtoul(s, &rend, base); + return (end == rend); +} diff --git a/libstuff/util/grep.c b/libstuff/util/grep.c @@ -0,0 +1,22 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "util.h" + + +void +grep(char **list, Reprog *re, int flags) { + char **p, **q; + int res; + + q = list; + for(p=q; *p; p++) { + res = 0; + if(re) + res = regexec(re, *p, nil, 0); + if(res && !(flags & GInvert) + || !res && (flags & GInvert)) + *q++ = *p; + } + *q = nil; +} diff --git a/libstuff/util/join.c b/libstuff/util/join.c @@ -0,0 +1,23 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stdlib.h> +#include <fmt.h> +#include "util.h" + +char* +join(char **list, char *sep) { + Fmt f; + char **p; + + if(fmtstrinit(&f) < 0) + abort(); + + for(p=list; *p; p++) { + if(p != list) + fmtstrcpy(&f, sep); + fmtstrcpy(&f, *p); + } + + return fmtstrflush(&f); +} diff --git a/libstuff/util/max.c b/libstuff/util/max.c @@ -0,0 +1,10 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +int +max(int a, int b) { + if(a > b) + return a; + return b; +} diff --git a/libstuff/util/mfatal.c b/libstuff/util/mfatal.c @@ -0,0 +1,34 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "util.h" + +/* Can't malloc */ +void +mfatal(char *name, uint size) { + const char + couldnot[] = ": fatal: Could not ", + paren[] = "() ", + bytes[] = " bytes\n"; + char buf[1024]; + char sizestr[8]; + int i; + + i = sizeof sizestr; + do { + sizestr[--i] = '0' + (size%10); + size /= 10; + } while(size > 0); + + strlcat(buf, argv0, sizeof buf); + strlcat(buf, couldnot, sizeof buf); + strlcat(buf, name, sizeof buf); + strlcat(buf, paren, sizeof buf); + strlcat(buf, sizestr+i, sizeof buf); + strlcat(buf, bytes, sizeof buf); + write(2, buf, strlen(buf)); + + exit(1); +} diff --git a/libstuff/util/min.c b/libstuff/util/min.c @@ -0,0 +1,10 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +int +min(int a, int b) { + if(a < b) + return a; + return b; +} diff --git a/libstuff/util/pathsearch.c b/libstuff/util/pathsearch.c @@ -0,0 +1,33 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fmt.h> +#include "util.h" + +char* +pathsearch(const char *path, const char *file, bool slashok) { + char *orig, *p, *s; + + if(!slashok && strchr(file, '/') > file) + file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file); + else if(!strncmp(file, "./", 2)) + file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file+2); + if(file[0] == '/') { + if(access(file, X_OK)) + return strdup(file); + return nil; + } + + orig = estrdup(path ? path : getenv("PATH")); + for(p=orig; (s=strtok(p, ":")); p=nil) { + s = smprint("%s/%s", s, file); + if(!access(s, X_OK)) + break; + free(s); + } + free(orig); + return s; +} diff --git a/libstuff/util/refree.c b/libstuff/util/refree.c @@ -0,0 +1,14 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stdlib.h> +#include "util.h" + +void +refree(Regex *r) { + + free(r->regex); + free(r->regc); + r->regex = nil; + r->regc = nil; +} diff --git a/libstuff/util/reinit.c b/libstuff/util/reinit.c @@ -0,0 +1,16 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "util.h" + + +void +reinit(Regex *r, char *regx) { + + refree(r); + + if(regx[0] != '\0') { + r->regex = estrdup(regx); + r->regc = regcomp(regx); + } +} diff --git a/libstuff/util/spawn3.c b/libstuff/util/spawn3.c @@ -0,0 +1,44 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include "util.h" + +int +spawn3(int fd[3], const char *file, char *argv[]) { + /* Some ideas from Russ Cox's libthread port. */ + int p[2]; + int pid; + + if(pipe(p) < 0) + return -1; + closeexec(p[1]); + + switch(pid = doublefork()) { + case 0: + dup2(fd[0], 0); + dup2(fd[1], 1); + dup2(fd[2], 2); + + execvp(file, argv); + write(p[1], &errno, sizeof errno); + exit(1); + break; + default: + close(p[1]); + if(read(p[0], &errno, sizeof errno) == sizeof errno) + pid = -1; + close(p[0]); + break; + case -1: /* can't happen */ + break; + } + + close(fd[0]); + /* These could fail if any of these was also a previous fd. */ + close(fd[1]); + close(fd[2]); + return pid; +} diff --git a/libstuff/util/spawn3l.c b/libstuff/util/spawn3l.c @@ -0,0 +1,29 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stdlib.h> +#include <fmt.h> +#include "util.h" + +int +spawn3l(int fd[3], const char *file, ...) { + va_list ap; + char **argv; + int i, n; + + va_start(ap, file); + for(n=0; va_arg(ap, char*); n++) + ; + va_end(ap); + + argv = emalloc((n+1) * sizeof *argv); + va_start(ap, file); + quotefmtinstall(); + for(i=0; i <= n; i++) + argv[i] = va_arg(ap, char*); + va_end(ap); + + i = spawn3(fd, file, argv); + free(argv); + return i; +} diff --git a/libstuff/util/stokenize.c b/libstuff/util/stokenize.c @@ -0,0 +1,22 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +uint +stokenize(char *res[], uint reslen, char *str, char *delim) { + char *s; + uint i; + + i = 0; + s = str; + while(i < reslen && *s) { + while(strchr(delim, *s)) + *(s++) = '\0'; + if(*s) + res[i++] = s; + while(*s && !strchr(delim, *s)) + s++; + } + return i; +} diff --git a/libstuff/util/strcasestr.c b/libstuff/util/strcasestr.c @@ -0,0 +1,25 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <ctype.h> +#include <stdint.h> +#include <string.h> +#include <strings.h> +#include "util.h" + +/* TODO: Make this UTF-8 compliant. */ +char* +strcasestr(const char *dst, const char *src) { + int dc, sc; + int len; + + len = strlen(src) - 1; + for(; (sc = *src) && *dst; src++) { + sc = tolower(dc); + for(; (dc = *dst); dst++) { + dc = tolower(dc); + if(sc == dc && !strncasecmp(dst+1, src+1, len)) + return (char*)(uintptr_t)dst; + } + } + return nil; +} diff --git a/libstuff/util/strend.c b/libstuff/util/strend.c @@ -0,0 +1,13 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include <stuff/util.h> + +char* +strend(char *s, int n) { + int len; + + len = strlen(s); + return s + max(0, len - n); +} diff --git a/libstuff/util/strlcat.c b/libstuff/util/strlcat.c @@ -0,0 +1,26 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +uint +strlcat(char *dst, const char *src, uint size) { + const char *s; + char *d; + int n, len; + + d = dst; + s = src; + n = size; + while(n-- > 0 && *d != '\0') + d++; + len = n; + + while(*s != '\0') { + if(n-- > 0) + *d++ = *s; + s++; + } + if(len > 0) + *d = '\0'; + return size - n - 1; +} diff --git a/libstuff/util/strlcatprint.c b/libstuff/util/strlcatprint.c @@ -0,0 +1,19 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include <fmt.h> +#include "util.h" + +int +strlcatprint(char *buf, int len, const char *fmt, ...) { + va_list ap; + int buflen; + int ret; + + va_start(ap, fmt); + buflen = strlen(buf); + ret = vsnprint(buf+buflen, len-buflen, fmt, ap); + va_end(ap); + return ret; +} diff --git a/libstuff/util/sxprint.c b/libstuff/util/sxprint.c @@ -0,0 +1,14 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +char* +sxprint(const char *fmt, ...) { + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = vsxprint(fmt, ap); + va_end(ap); + return ret; +} diff --git a/libstuff/util/tokenize.c b/libstuff/util/tokenize.c @@ -0,0 +1,21 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +uint +tokenize(char *res[], uint reslen, char *str, char delim) { + char *s; + uint i; + + i = 0; + s = str; + while(i < reslen && *s) { + while(*s == delim) + *(s++) = '\0'; + if(*s) + res[i++] = s; + while(*s && *s != delim) + s++; + } + return i; +} diff --git a/libstuff/util/uniq.c b/libstuff/util/uniq.c @@ -0,0 +1,18 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "util.h" + +void +uniq(char **toks) { + char **p, **q; + + q = toks; + if(*q == nil) + return; + for(p=q+1; *p; p++) + if(strcmp(*q, *p)) + *++q = *p; + *++q = nil; +} diff --git a/libstuff/util/unquote.c b/libstuff/util/unquote.c @@ -0,0 +1,38 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "util.h" + +int +unquote(char *buf, char *toks[], int ntoks) { + char *s, *t; + bool inquote; + int n; + + n = 0; + s = buf; + while(*s && n < ntoks) { + while(*s && utfrune(" \t\r\n", *s)) + s++; + inquote = false; + toks[n] = s; + t = s; + while(*s && (inquote || !utfrune(" \t\r\n", *s))) { + if(*s == '\'') { + if(inquote && s[1] == '\'') + *t++ = *s++; + else + inquote = !inquote; + } + else + *t++ = *s; + s++; + } + if(*s) + s++; + *t = '\0'; + if(s != toks[n]) + n++; + } + return n; +} diff --git a/libstuff/util/utflcpy.c b/libstuff/util/utflcpy.c @@ -0,0 +1,11 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +int +utflcpy(char *to, const char *from, int l) { + char *p; + + p = utfecpy(to, to+l, from); + return p-to; +} diff --git a/libstuff/util/util.h b/libstuff/util/util.h @@ -0,0 +1,5 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <stuff/util.h> + +void mfatal(char*, uint); diff --git a/libstuff/util/vector.c b/libstuff/util/vector.c @@ -0,0 +1,34 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stdlib.h> +#include <string.h> +#include "util.h" + +/* Blech. */ +#define VECTOR(type, nam, c) \ +void \ +vector_##c##init(Vector_##nam *v) { \ + memset(v, 0, sizeof *v); \ +} \ + \ +void \ +vector_##c##free(Vector_##nam *v) { \ + free(v->ary); \ + memset(v, 0, sizeof *v); \ +} \ + \ +void \ +vector_##c##push(Vector_##nam *v, type val) { \ + if(v->n == v->size) { \ + if(v->size == 0) \ + v->size = 2; \ + v->size <<= 2; \ + v->ary = erealloc(v->ary, v->size * sizeof *v->ary); \ + } \ + v->ary[v->n++] = val; \ +} \ + +VECTOR(long, long, l) +VECTOR(Rectangle, rect, r) +VECTOR(void*, ptr, p) diff --git a/libstuff/util/vsxprint.c b/libstuff/util/vsxprint.c @@ -0,0 +1,13 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <fmt.h> +#include "util.h" + +char* +vsxprint(const char *fmt, va_list ap) { + char *s; + + s = vsmprint(fmt, ap); + freelater(s); + return s; +} diff --git a/libstuff/x11/colors/loadcolor.c b/libstuff/x11/colors/loadcolor.c @@ -0,0 +1,17 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +bool +loadcolor(CTuple *c, char *str) { + char buf[24]; + + utflcpy(buf, str, sizeof buf); + memcpy(c->colstr, str, sizeof c->colstr); + + buf[7] = buf[15] = buf[23] = '\0'; + return namedcolor(buf, &c->fg) + && namedcolor(buf+8, &c->bg) + && namedcolor(buf+16, &c->border); +} diff --git a/libstuff/x11/colors/namedcolor.c b/libstuff/x11/colors/namedcolor.c @@ -0,0 +1,22 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +bool +namedcolor(char *name, Color *ret) { + XColor c, c2; + + if(XAllocNamedColor(display, scr.colormap, name, &c, &c2)) { + *ret = (Color) { + c.pixel, { + c.red, + c.green, + c.blue, + 0xffff + }, + }; + return true; + } + return false; +} diff --git a/libstuff/x11/colors/xftcolor.c b/libstuff/x11/colors/xftcolor.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XftColor* +xftcolor(Color col) { + XftColor *c; + + c = emallocz(sizeof *c); + *c = (XftColor) { + ((col.render.alpha&0xff00) << 24) + | ((col.render.red&0xff00) << 8) + | ((col.render.green&0xff00) << 0) + | ((col.render.blue&0xff00) >> 8), + col.render + }; + return freelater(c); +} diff --git a/libstuff/x11/convpts.c b/libstuff/x11/convpts.c @@ -0,0 +1,17 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +XPoint* +convpts(Point *pt, int np) { + XPoint *rp; + int i; + + rp = emalloc(np * sizeof *rp); + for(i = 0; i < np; i++) { + rp[i].x = pt[i].x; + rp[i].y = pt[i].y; + } + return rp; +} diff --git a/libstuff/x11/drawing/border.c b/libstuff/x11/drawing/border.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +border(Image *dst, Rectangle r, int w, Color col) { + if(w == 0) + return; + + r = insetrect(r, w/2); + r.max.x -= w%2; + r.max.y -= w%2; + + XSetLineAttributes(display, dst->gc, w, LineSolid, CapButt, JoinMiter); + setgccol(dst, col); + XDrawRectangle(display, dst->xid, dst->gc, + r.min.x, r.min.y, Dx(r), Dy(r)); +} diff --git a/libstuff/x11/drawing/drawline.c b/libstuff/x11/drawing/drawline.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +drawline(Image *dst, Point p1, Point p2, int cap, int w, Color col) { + XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); + setgccol(dst, col); + XDrawLine(display, dst->xid, dst->gc, p1.x, p1.y, p2.x, p2.y); +} diff --git a/libstuff/x11/drawing/drawpoly.c b/libstuff/x11/drawing/drawpoly.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +drawpoly(Image *dst, Point *pt, int np, int cap, int w, Color col) { + XPoint *xp; + + xp = convpts(pt, np); + XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); + setgccol(dst, col); + XDrawLines(display, dst->xid, dst->gc, xp, np, CoordModeOrigin); + free(xp); +} diff --git a/libstuff/x11/drawing/drawstring.c b/libstuff/x11/drawing/drawstring.c @@ -0,0 +1,88 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +uint +drawstring(Image *dst, Font *font, + Rectangle r, Align align, + char *text, Color col) { + Rectangle tr; + char *buf; + uint x, y, width, height, len; + int shortened; + + shortened = 0; + + len = strlen(text); + buf = emalloc(len+1); + memcpy(buf, text, len+1); + + r.max.y -= font->pad.min.y; + r.min.y += font->pad.max.y; + + height = font->ascent + font->descent; + y = r.min.y + Dy(r) / 2 - height / 2 + font->ascent; + + width = Dx(r) - font->pad.min.x - font->pad.max.x - (font->height & ~1); + + r.min.x += font->pad.min.x; + r.max.x -= font->pad.max.x; + + /* shorten text if necessary */ + tr = ZR; + while(len > 0) { + tr = textextents_l(font, buf, len + min(shortened, 3), nil); + if(Dx(tr) <= width) + break; + while(len > 0 && (buf[--len]&0xC0) == 0x80) + buf[len] = '.'; + buf[len] = '.'; + shortened++; + } + + if(len == 0 || Dx(tr) > width) + goto done; + + /* mark shortened info in the string */ + if(shortened) + len += min(shortened, 3); + + switch (align) { + case East: + x = r.max.x - (tr.max.x + (font->height / 2)); + break; + case Center: + x = r.min.x + (Dx(r) - Dx(tr)) / 2 - tr.min.x; + break; + default: + x = r.min.x + (font->height / 2) - tr.min.x; + break; + } + + setgccol(dst, col); + switch(font->type) { + case FFontSet: + Xutf8DrawString(display, dst->xid, + font->font.set, dst->gc, + x, y, + buf, len); + break; + case FXft: + XftDrawStringUtf8(xftdrawable(dst), xftcolor(col), + font->font.xft, + x, y, (uchar*)buf, len); + break; + case FX11: + XSetFont(display, dst->gc, font->font.x11->fid); + XDrawString(display, dst->xid, dst->gc, + x, y, buf, len); + break; + default: + die("Invalid font type."); + } + +done: + free(buf); + return Dx(tr); +} diff --git a/libstuff/x11/drawing/fill.c b/libstuff/x11/drawing/fill.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +fill(Image *dst, Rectangle r, Color col) { + setgccol(dst, col); + XFillRectangle(display, dst->xid, dst->gc, + r.min.x, r.min.y, Dx(r), Dy(r)); +} diff --git a/libstuff/x11/drawing/fillpoly.c b/libstuff/x11/drawing/fillpoly.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +fillpoly(Image *dst, Point *pt, int np, Color col) { + XPoint *xp; + + xp = convpts(pt, np); + setgccol(dst, col); + XFillPolygon(display, dst->xid, dst->gc, xp, np, Complex, CoordModeOrigin); + free(xp); +} diff --git a/libstuff/x11/errors.c b/libstuff/x11/errors.c @@ -0,0 +1,40 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +extern ErrorCode ignored_xerrors[]; +static bool _trap_errors; +static long nerrors; + +int +errorhandler(Display *dpy, XErrorEvent *error) { + ErrorCode *e; + + USED(dpy); + + if(_trap_errors) + nerrors++; + + e = ignored_xerrors; + if(e) + for(; e->rcode || e->ecode; e++) + if((e->rcode == 0 || e->rcode == error->request_code) + && (e->ecode == 0 || e->ecode == error->error_code)) + return 0; + + fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n", + argv0, error->request_code, error->error_code); + return xlib_errorhandler(display, error); /* calls exit() */ +} + +int +traperrors(bool enable) { + + sync(); + _trap_errors = enable; + if (enable) + nerrors = 0; + return nerrors; + +} diff --git a/libstuff/x11/focus/getfocus.c b/libstuff/x11/focus/getfocus.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XWindow +getfocus(void) { + XWindow ret; + int revert; + + XGetInputFocus(display, &ret, &revert); + return ret; +} diff --git a/libstuff/x11/focus/setfocus.c b/libstuff/x11/focus/setfocus.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setfocus(Window *w, int mode) { + XSetInputFocus(display, w->xid, mode, CurrentTime); +} diff --git a/libstuff/x11/freestringlist.c b/libstuff/x11/freestringlist.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +freestringlist(char *list[]) { + XFreeStringList(list); +} diff --git a/libstuff/x11/geometry/XRect.c b/libstuff/x11/geometry/XRect.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XRectangle +XRect(Rectangle r) { + XRectangle xr; + + xr.x = r.min.x; + xr.y = r.min.y; + xr.width = Dx(r); + xr.height = Dy(r); + return xr; +} diff --git a/libstuff/x11/geometry/addpt.c b/libstuff/x11/geometry/addpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +addpt(Point p, Point q) { + p.x += q.x; + p.y += q.y; + return p; +} diff --git a/libstuff/x11/geometry/divpt.c b/libstuff/x11/geometry/divpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +divpt(Point p, Point q) { + p.x /= q.x; + p.y /= q.y; + return p; +} diff --git a/libstuff/x11/geometry/eqpt.c b/libstuff/x11/geometry/eqpt.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +eqpt(Point p, Point q) { + return p.x==q.x && p.y==q.y; +} diff --git a/libstuff/x11/geometry/eqrect.c b/libstuff/x11/geometry/eqrect.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +eqrect(Rectangle a, Rectangle b) { + return a.min.x==b.min.x && a.max.x==b.max.x + && a.min.y==b.min.y && a.max.y==b.max.y; +} diff --git a/libstuff/x11/geometry/insetrect.c b/libstuff/x11/geometry/insetrect.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +insetrect(Rectangle r, int n) { + r.min.x += n; + r.min.y += n; + r.max.x -= n; + r.max.y -= n; + return r; +} diff --git a/libstuff/x11/geometry/mulpt.c b/libstuff/x11/geometry/mulpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +mulpt(Point p, Point q) { + p.x *= q.x; + p.y *= q.y; + return p; +} diff --git a/libstuff/x11/geometry/rectaddpt.c b/libstuff/x11/geometry/rectaddpt.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +rectaddpt(Rectangle r, Point p) { + r.min.x += p.x; + r.max.x += p.x; + r.min.y += p.y; + r.max.y += p.y; + return r; +} diff --git a/libstuff/x11/geometry/rectsetorigin.c b/libstuff/x11/geometry/rectsetorigin.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +rectsetorigin(Rectangle r, Point p) { + Rectangle ret; + + ret.min.x = p.x; + ret.min.y = p.y; + ret.max.x = p.x + Dx(r); + ret.max.y = p.y + Dy(r); + return ret; +} diff --git a/libstuff/x11/geometry/rectsubpt.c b/libstuff/x11/geometry/rectsubpt.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +rectsubpt(Rectangle r, Point p) { + r.min.x -= p.x; + r.max.x -= p.x; + r.min.y -= p.y; + r.max.y -= p.y; + return r; +} diff --git a/libstuff/x11/geometry/subpt.c b/libstuff/x11/geometry/subpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +subpt(Point p, Point q) { + p.x -= q.x; + p.y -= q.y; + return p; +} diff --git a/libstuff/x11/ignored_xerrors.c b/libstuff/x11/ignored_xerrors.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +ErrorCode ignored_xerrors[] = { + { 0, }, +}; + diff --git a/libstuff/x11/images/allocimage.c b/libstuff/x11/images/allocimage.c @@ -0,0 +1,21 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Image* +allocimage(int w, int h, int depth) { + Image *img; + + img = emallocz(sizeof *img); + img->type = WImage; + img->xid = XCreatePixmap(display, scr.root.xid, w, h, depth); + img->gc = XCreateGC(display, img->xid, 0, nil); + img->colormap = scr.colormap; + img->visual = scr.visual; + if(depth == 32) + img->visual = scr.visual32; + img->depth = depth; + img->r = Rect(0, 0, w, h); + return img; +} diff --git a/libstuff/x11/images/copyimage.c b/libstuff/x11/images/copyimage.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +copyimage(Image *dst, Rectangle r, Image *src, Point p) { + XCopyArea(display, + src->xid, dst->xid, + dst->gc, + r.min.x, r.min.y, Dx(r), Dy(r), + p.x, p.y); +} diff --git a/libstuff/x11/images/freeimage.c b/libstuff/x11/images/freeimage.c @@ -0,0 +1,18 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +freeimage(Image *img) { + if(img == nil) + return; + + assert(img->type == WImage); + + if(img->xft) + XftDrawDestroy(img->xft); + XFreePixmap(display, img->xid); + XFreeGC(display, img->gc); + free(img); +} diff --git a/libstuff/x11/images/xftdrawable.c b/libstuff/x11/images/xftdrawable.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XftDraw* +xftdrawable(Image *img) { + if(img->xft == nil) + img->xft = XftDrawCreate(display, img->xid, img->visual, img->colormap); + return img->xft; +} diff --git a/libstuff/x11/initdisplay.c b/libstuff/x11/initdisplay.c @@ -0,0 +1,84 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +int (*xlib_errorhandler) (Display*, XErrorEvent*); + +Map windowmap; +Map atommap; +MapEnt* wbucket[137]; +MapEnt* abucket[137]; + +static int +Afmt(Fmt *f) { + Atom a; + char *s; + int i; + + a = va_arg(f->args, Atom); + s = XGetAtomName(display, a); + i = fmtprint(f, "%s", s); + free(s); + return i; +} + +static int +Pfmt(Fmt *f) { + Point p; + + p = va_arg(f->args, Point); + return fmtprint(f, "(%d,%d)", p.x, p.y); +} + +static int +Rfmt(Fmt *f) { + Rectangle r; + + r = va_arg(f->args, Rectangle); + return fmtprint(f, "%P+%dx%d", r.min, Dx(r), Dy(r)); +} + +static int +Wfmt(Fmt *f) { + Window *w; + + w = va_arg(f->args, Window*); + return fmtprint(f, "0x%ulx", w->xid); +} + +void +initdisplay(void) { + display = XOpenDisplay(nil); + if(display == nil) + fatal("Can't open display"); + scr.screen = DefaultScreen(display); + scr.colormap = DefaultColormap(display, scr.screen); + scr.visual = DefaultVisual(display, scr.screen); + scr.visual32 = DefaultVisual(display, scr.screen); + scr.gc = DefaultGC(display, scr.screen); + scr.depth = DefaultDepth(display, scr.screen); + + scr.white = WhitePixel(display, scr.screen); + scr.black = BlackPixel(display, scr.screen); + + scr.root.xid = RootWindow(display, scr.screen); + scr.root.r = Rect(0, 0, + DisplayWidth(display, scr.screen), + DisplayHeight(display, scr.screen)); + scr.rect = scr.root.r; + + scr.root.parent = &scr.root; + + windowmap.bucket = wbucket; + windowmap.nhash = nelem(wbucket); + atommap.bucket = abucket; + atommap.nhash = nelem(abucket); + + fmtinstall('A', Afmt); + fmtinstall('R', Rfmt); + fmtinstall('P', Pfmt); + fmtinstall('W', Wfmt); + + xlib_errorhandler = XSetErrorHandler(errorhandler); +} diff --git a/libstuff/x11/insanity/gravitate.c b/libstuff/x11/insanity/gravitate.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +gravitate(Rectangle rc, Rectangle rf, Point grav) { + Point d; + + /* Get delta between frame and client rectangles */ + d = subpt(subpt(rf.max, rf.min), + subpt(rc.max, rc.min)); + + /* Divide by 2 and apply gravity */ + d = divpt(d, Pt(2, 2)); + d = mulpt(d, grav); + + return rectsubpt(rc, d); +} diff --git a/libstuff/x11/insanity/sethints.c b/libstuff/x11/insanity/sethints.c @@ -0,0 +1,99 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +sethints(Window *w) { + XSizeHints xs; + XWMHints *wmh; + WinHints *h; + Point p; + long size; + + if(w->hints == nil) + w->hints = emalloc(sizeof *h); + + h = w->hints; + memset(h, 0, sizeof *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(!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); +} diff --git a/libstuff/x11/insanity/sizehint.c b/libstuff/x11/insanity/sizehint.c @@ -0,0 +1,42 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +sizehint(WinHints *h, Rectangle r) { + Point p, aspect, origin; + + if(h == nil) + return r; + + origin = r.min; + r = rectsubpt(r, origin); + + /* Min/max */ + r.max.x = max(r.max.x, h->min.x); + r.max.y = max(r.max.y, h->min.y); + r.max.x = min(r.max.x, h->max.x); + r.max.y = min(r.max.y, h->max.y); + + /* Increment */ + p = subpt(r.max, h->base); + r.max.x -= p.x % h->inc.x; + r.max.y -= p.y % h->inc.y; + + /* Aspect */ + p = subpt(r.max, h->baspect); + p.y = max(p.y, 1); + + aspect = h->aspect.min; + if(p.x * aspect.y / p.y < aspect.x) + r.max.y = h->baspect.y + + p.x * aspect.y / aspect.x; + + aspect = h->aspect.max; + if(p.x * aspect.y / p.y > aspect.x) + r.max.x = h->baspect.x + + p.y * aspect.x / aspect.y; + + return rectaddpt(r, origin); +} diff --git a/libstuff/x11/keyboard/grabkeyboard.c b/libstuff/x11/keyboard/grabkeyboard.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +grabkeyboard(Window *w) { + + return XGrabKeyboard(display, w->xid, true /* owner events */, + GrabModeAsync, GrabModeAsync, CurrentTime + ) == GrabSuccess; +} diff --git a/libstuff/x11/keyboard/ungrabkeyboard.c b/libstuff/x11/keyboard/ungrabkeyboard.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +ungrabkeyboard(void) { + XUngrabKeyboard(display, CurrentTime); +} diff --git a/libstuff/x11/keys/keycode.c b/libstuff/x11/keys/keycode.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +KeyCode +keycode(char *name) { + return XKeysymToKeycode(display, XStringToKeysym(name)); +} diff --git a/libstuff/x11/keys/parsekey.c b/libstuff/x11/keys/parsekey.c @@ -0,0 +1,46 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +typedef struct KMask KMask; + +static struct KMask { + int mask; + const char* name; +} masks[] = { + {ShiftMask, "Shift"}, + {ControlMask, "Control"}, + {Mod1Mask, "Mod1"}, + {Mod2Mask, "Mod2"}, + {Mod3Mask, "Mod3"}, + {Mod4Mask, "Mod4"}, + {Mod5Mask, "Mod5"}, + {0,} +}; + +bool +parsekey(char *str, int *mask, char **key) { + static char *keys[16]; + KMask *m; + int i, nkeys; + + *mask = 0; + nkeys = tokenize(keys, nelem(keys), str, '-'); + for(i=0; i < nkeys; i++) { + for(m=masks; m->mask; m++) + if(!strcasecmp(m->name, keys[i])) { + *mask |= m->mask; + goto next; + } + break; + next: continue; + } + if(key) { + if(nkeys) + *key = keys[i]; + return i == nkeys - 1; + } + else + return i == nkeys; +} diff --git a/libstuff/x11/mouse/grabpointer.c b/libstuff/x11/mouse/grabpointer.c @@ -0,0 +1,16 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +grabpointer(Window *w, Window *confine, Cursor cur, int mask) { + XWindow cw; + + cw = None; + if(confine) + cw = confine->xid; + return XGrabPointer(display, w->xid, false /* owner events */, mask, + GrabModeAsync, GrabModeAsync, cw, cur, CurrentTime + ) == GrabSuccess; +} diff --git a/libstuff/x11/mouse/pointerscreen.c b/libstuff/x11/mouse/pointerscreen.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +pointerscreen(void) { + XWindow win; + Point pt; + uint ui; + int i; + + return XQueryPointer(display, scr.root.xid, &win, &win, &i, &i, + &pt.x, &pt.y, &ui); +} diff --git a/libstuff/x11/mouse/querypointer.c b/libstuff/x11/mouse/querypointer.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +querypointer(Window *w) { + XWindow win; + Point pt; + uint ui; + int i; + + XQueryPointer(display, w->xid, &win, &win, &i, &i, &pt.x, &pt.y, &ui); + return pt; +} diff --git a/libstuff/x11/mouse/translate.c b/libstuff/x11/mouse/translate.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +translate(Window *src, Window *dst, Point sp) { + Point pt; + XWindow w; + + XTranslateCoordinates(display, src->xid, dst->xid, sp.x, sp.y, + &pt.x, &pt.y, &w); + return pt; +} diff --git a/libstuff/x11/mouse/ungrabpointer.c b/libstuff/x11/mouse/ungrabpointer.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +ungrabpointer(void) { + XUngrabPointer(display, CurrentTime); +} diff --git a/libstuff/x11/mouse/warppointer.c b/libstuff/x11/mouse/warppointer.c @@ -0,0 +1,23 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +warppointer(Point pt) { + /* Nasty kludge for xephyr, xnest. */ + static int havereal = -1; + static char* real; + + if(havereal == -1) { + real = getenv("REALDISPLAY"); + havereal = real != nil; + } + if(havereal) + system(sxprint("DISPLAY=%s wiwarp %d %d", real, pt.x, pt.y)); + + XWarpPointer(display, + /* src, dest w */ None, scr.root.xid, + /* src_rect */ 0, 0, 0, 0, + /* target */ pt.x, pt.y); +} diff --git a/libstuff/x11/properties/changeprop_char.c b/libstuff/x11/properties/changeprop_char.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_char(Window *w, char *prop, char *type, char data[], int len) { + changeproperty(w, prop, type, 8, (uchar*)data, len); +} diff --git a/libstuff/x11/properties/changeprop_long.c b/libstuff/x11/properties/changeprop_long.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_long(Window *w, char *prop, char *type, long data[], int len) { + changeproperty(w, prop, type, 32, (uchar*)data, len); +} diff --git a/libstuff/x11/properties/changeprop_short.c b/libstuff/x11/properties/changeprop_short.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_short(Window *w, char *prop, char *type, short data[], int len) { + changeproperty(w, prop, type, 16, (uchar*)data, len); +} diff --git a/libstuff/x11/properties/changeprop_string.c b/libstuff/x11/properties/changeprop_string.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_string(Window *w, char *prop, char *string) { + changeprop_char(w, prop, "UTF8_STRING", string, strlen(string)); +} diff --git a/libstuff/x11/properties/changeprop_textlist.c b/libstuff/x11/properties/changeprop_textlist.c @@ -0,0 +1,23 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_textlist(Window *w, char *prop, char *type, char *data[]) { + char **p, *s, *t; + int len, n; + + len = 0; + for(p=data; *p; p++) + len += strlen(*p) + 1; + s = emalloc(len); + t = s; + for(p=data; *p; p++) { + n = strlen(*p) + 1; + memcpy(t, *p, n); + t += n; + } + changeprop_char(w, prop, type, s, len); + free(s); +} diff --git a/libstuff/x11/properties/changeprop_ulong.c b/libstuff/x11/properties/changeprop_ulong.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_ulong(Window *w, char *prop, char *type, ulong data[], int len) { + changeproperty(w, prop, type, 32, (uchar*)data, len); +} diff --git a/libstuff/x11/properties/changeproperty.c b/libstuff/x11/properties/changeproperty.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeproperty(Window *w, char *prop, char *type, + int width, uchar data[], int n) { + XChangeProperty(display, w->xid, xatom(prop), xatom(type), width, + PropModeReplace, data, n); +} diff --git a/libstuff/x11/properties/delproperty.c b/libstuff/x11/properties/delproperty.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +delproperty(Window *w, char *prop) { + XDeleteProperty(display, w->xid, xatom(prop)); +} diff --git a/libstuff/x11/properties/getprop.c b/libstuff/x11/properties/getprop.c @@ -0,0 +1,28 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getprop(Window *w, char *prop, char *type, Atom *actual, int *format, + ulong offset, uchar **ret, ulong length) { + Atom typea; + ulong n, extra; + int status; + + typea = (type ? xatom(type) : 0L); + + status = XGetWindowProperty(display, w->xid, + xatom(prop), offset, length, false /* delete */, + typea, actual, format, &n, &extra, ret); + + if(status != Success) { + *ret = nil; + return 0; + } + if(n == 0) { + free(*ret); + *ret = nil; + } + return n; +} diff --git a/libstuff/x11/properties/getprop_long.c b/libstuff/x11/properties/getprop_long.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getprop_long(Window *w, char *prop, char *type, + ulong offset, long **ret, ulong length) { + Atom actual; + ulong n; + int format; + + n = getprop(w, prop, type, &actual, &format, offset, (uchar**)ret, length); + if(n == 0 || format == 32 && xatom(type) == actual) + return n; + free(*ret); + *ret = 0; + return 0; +} diff --git a/libstuff/x11/properties/getprop_string.c b/libstuff/x11/properties/getprop_string.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +char* +getprop_string(Window *w, char *name) { + char **list, *str; + int n; + + str = nil; + + n = getprop_textlist(w, name, &list); + if(n > 0) + str = estrdup(*list); + freestringlist(list); + + return str; +} diff --git a/libstuff/x11/properties/getprop_textlist.c b/libstuff/x11/properties/getprop_textlist.c @@ -0,0 +1,22 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +getprop_textlist(Window *w, char *name, char **ret[]) { + XTextProperty prop; + char **list; + int n; + + *ret = nil; + n = 0; + + XGetTextProperty(display, w->xid, &prop, xatom(name)); + if(prop.nitems > 0) { + if(Xutf8TextPropertyToTextList(display, &prop, &list, &n) == Success) + *ret = list; + XFree(prop.value); + } + return n; +} diff --git a/libstuff/x11/properties/getprop_ulong.c b/libstuff/x11/properties/getprop_ulong.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getprop_ulong(Window *w, char *prop, char *type, + ulong offset, ulong **ret, ulong length) { + return getprop_long(w, prop, type, offset, (long**)ret, length); +} diff --git a/libstuff/x11/properties/getproperty.c b/libstuff/x11/properties/getproperty.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getproperty(Window *w, char *prop, char *type, Atom *actual, + ulong offset, uchar **ret, ulong length) { + int format; + + return getprop(w, prop, type, actual, &format, offset, ret, length); +} diff --git a/libstuff/x11/properties/strlistdup.c b/libstuff/x11/properties/strlistdup.c @@ -0,0 +1,28 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +char** +strlistdup(char *list[]) { + char **p; + char *q; + int i, m, n; + + n = 0; + m = 0; + for(p=list; *p; p++, n++) + m += strlen(*p) + 1; + + p = malloc((n+1) * sizeof(*p) + m); + q = (char*)&p[n+1]; + + for(i=0; i < n; i++) { + p[i] = q; + m = strlen(list[i]) + 1; + memcpy(q, list[i], m); + q += m; + } + p[n] = nil; + return p; +} diff --git a/libstuff/x11/sendevent.c b/libstuff/x11/sendevent.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +sendevent(Window *w, bool propegate, long mask, XEvent *e) { + XSendEvent(display, w->xid, propegate, mask, e); +} diff --git a/libstuff/x11/sendmessage.c b/libstuff/x11/sendmessage.c @@ -0,0 +1,20 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +sendmessage(Window *w, char *name, long l0, long l1, long l2, long l3, long l4) { + 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); +} diff --git a/libstuff/x11/setgccol.c b/libstuff/x11/setgccol.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +setgccol(Image *dst, Color col) { + XSetForeground(display, dst->gc, col.pixel); +} diff --git a/libstuff/x11/shape/setshapemask.c b/libstuff/x11/shape/setshapemask.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setshapemask(Window *dst, Image *src, Point pt) { + /* Assumes that we have the shape extension... */ + XShapeCombineMask (display, dst->xid, + ShapeBounding, pt.x, pt.y, src->xid, ShapeSet); +} diff --git a/libstuff/x11/sync.c b/libstuff/x11/sync.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +sync(void) { + XSync(display, false); +} diff --git a/libstuff/x11/text/freefont.c b/libstuff/x11/text/freefont.c @@ -0,0 +1,23 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +freefont(Font *f) { + switch(f->type) { + case FFontSet: + XFreeFontSet(display, f->font.set); + break; + case FXft: + XftFontClose(display, f->font.xft); + break; + case FX11: + XFreeFont(display, f->font.x11); + break; + default: + break; + } + free(f->name); + free(f); +} diff --git a/libstuff/x11/text/labelh.c b/libstuff/x11/text/labelh.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +uint +labelh(Font *font) { + return max(font->height + font->descent + font->pad.min.y + font->pad.max.y, 1); +} diff --git a/libstuff/x11/text/loadfont.c b/libstuff/x11/text/loadfont.c @@ -0,0 +1,66 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Font* +loadfont(char *name) { + XFontStruct **xfonts; + char **missing, **font_names; + Biobuf *b; + Font *f; + int n, i; + + missing = nil; + f = emallocz(sizeof *f); + f->name = estrdup(name); + if(!strncmp(f->name, "xft:", 4)) { + f->type = FXft; + + f->font.xft = XftFontOpenXlfd(display, scr.screen, f->name + 4); + if(!f->font.xft) + f->font.xft = XftFontOpenName(display, scr.screen, f->name + 4); + if(!f->font.xft) + goto error; + + f->ascent = f->font.xft->ascent; + f->descent = f->font.xft->descent; + }else { + f->font.set = XCreateFontSet(display, name, &missing, &n, nil); + if(missing) { + if(false) { + b = Bfdopen(dup(2), O_WRONLY); + Bprint(b, "%s: note: missing fontset%s for '%s':", argv0, + (n > 1 ? "s" : ""), name); + for(i = 0; i < n; i++) + Bprint(b, "%s %s", (i ? "," : ""), missing[i]); + Bprint(b, "\n"); + Bterm(b); + } + freestringlist(missing); + } + + if(f->font.set) { + f->type = FFontSet; + XFontsOfFontSet(f->font.set, &xfonts, &font_names); + f->ascent = xfonts[0]->ascent; + f->descent = xfonts[0]->descent; + }else { + f->type = FX11; + f->font.x11 = XLoadQueryFont(display, name); + if(!f->font.x11) + goto error; + + f->ascent = f->font.x11->ascent; + f->descent = f->font.x11->descent; + } + } + f->height = f->ascent + f->descent; + return f; + +error: + fprint(2, "%s: cannot load font: %s\n", argv0, name); + f->type = 0; + freefont(f); + return nil; +} diff --git a/libstuff/x11/text/textextents_l.c b/libstuff/x11/text/textextents_l.c @@ -0,0 +1,34 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +textextents_l(Font *font, char *text, uint len, int *offset) { + Rectangle rect; + XRectangle r; + XGlyphInfo i; + int unused; + + if(!offset) + offset = &unused; + + switch(font->type) { + case FFontSet: + *offset = Xutf8TextExtents(font->font.set, text, len, &r, nil); + return Rect(r.x, -r.y - r.height, r.x + r.width, -r.y); + case FXft: + XftTextExtentsUtf8(display, font->font.xft, (uchar*)text, len, &i); + *offset = i.xOff; + return Rect(-i.x, i.y - i.height, -i.x + i.width, i.y); + case FX11: + rect = ZR; + rect.max.x = XTextWidth(font->font.x11, text, len); + rect.max.y = font->ascent; + *offset = rect.max.x; + return rect; + default: + die("Invalid font type"); + return ZR; /* shut up ken */ + } +} diff --git a/libstuff/x11/text/textwidth.c b/libstuff/x11/text/textwidth.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +uint +textwidth(Font *font, char *text) { + return textwidth_l(font, text, strlen(text)); +} diff --git a/libstuff/x11/text/textwidth_l.c b/libstuff/x11/text/textwidth_l.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +uint +textwidth_l(Font *font, char *text, uint len) { + Rectangle r; + + r = textextents_l(font, text, len, nil); + return Dx(r); +} diff --git a/libstuff/x11/windows/configwin.c b/libstuff/x11/windows/configwin.c @@ -0,0 +1,22 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +configwin(Window *w, Rectangle r, int border) { + XWindowChanges wc; + + if(eqrect(r, w->r) && border == w->border) + return; + + wc.x = r.min.x - border; + wc.y = r.min.y - border; + wc.width = Dx(r); + wc.height = Dy(r); + wc.border_width = border; + XConfigureWindow(display, w->xid, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + + w->r = r; + w->border = border; +} diff --git a/libstuff/x11/windows/createwindow.c b/libstuff/x11/windows/createwindow.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, int valmask) { + return createwindow_visual(parent, r, depth, scr.visual, class, wa, valmask); +} diff --git a/libstuff/x11/windows/createwindow_visual.c b/libstuff/x11/windows/createwindow_visual.c @@ -0,0 +1,33 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +createwindow_visual(Window *parent, Rectangle r, + int depth, Visual *vis, uint class, + WinAttr *wa, int valmask) { + Window *w; + + assert(parent->type == WWindow); + + w = emallocz(sizeof *w); + w->visual = vis; + w->type = WWindow; + w->parent = parent; + if(valmask & CWColormap) + w->colormap = wa->colormap; + + w->xid = XCreateWindow(display, parent->xid, r.min.x, r.min.y, Dx(r), Dy(r), + 0 /* border */, depth, class, vis, valmask, wa); +#if 0 + print("createwindow_visual(%W, %R, %d, %p, %ud, %p, %x) = %W\n", + parent, r, depth, vis, class, wa, valmask, w); +#endif + if(class != InputOnly) + w->gc = XCreateGC(display, w->xid, 0, nil); + + w->r = r; + w->depth = depth; + return w; +} diff --git a/libstuff/x11/windows/destroywindow.c b/libstuff/x11/windows/destroywindow.c @@ -0,0 +1,16 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +destroywindow(Window *w) { + assert(w->type == WWindow); + sethandler(w, nil); + if(w->xft) + XftDrawDestroy(w->xft); + if(w->gc) + XFreeGC(display, w->gc); + XDestroyWindow(display, w->xid); + free(w); +} diff --git a/libstuff/x11/windows/findwin.c b/libstuff/x11/windows/findwin.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +findwin(XWindow w) { + void **e; + + e = map_get(&windowmap, (ulong)w, false); + if(e) + return *e; + return nil; +} diff --git a/libstuff/x11/windows/getwinrect.c b/libstuff/x11/windows/getwinrect.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +getwinrect(Window *w) { + XWindowAttributes wa; + Point p; + + if(!XGetWindowAttributes(display, w->xid, &wa)) + return ZR; + p = translate(w, &scr.root, ZP); + return rectaddpt(Rect(0, 0, wa.width, wa.height), p); +} diff --git a/libstuff/x11/windows/lowerwin.c b/libstuff/x11/windows/lowerwin.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +lowerwin(Window *w) { + assert(w->type == WWindow); + XLowerWindow(display, w->xid); +} diff --git a/libstuff/x11/windows/mapwin.c b/libstuff/x11/windows/mapwin.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +mapwin(Window *w) { + assert(w->type == WWindow); + if(!w->mapped) { + XMapWindow(display, w->xid); + w->mapped = 1; + return 1; + } + return 0; +} diff --git a/libstuff/x11/windows/movewin.c b/libstuff/x11/windows/movewin.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +movewin(Window *w, Point pt) { + Rectangle r; + + assert(w->type == WWindow); + r = rectsetorigin(w->r, pt); + reshapewin(w, r); +} diff --git a/libstuff/x11/windows/raisewin.c b/libstuff/x11/windows/raisewin.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +raisewin(Window *w) { + assert(w->type == WWindow); + XRaiseWindow(display, w->xid); +} diff --git a/libstuff/x11/windows/reparentwindow.c b/libstuff/x11/windows/reparentwindow.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +reparentwindow(Window *w, Window *par, Point p) { + assert(w->type == WWindow); + XReparentWindow(display, w->xid, par->xid, p.x, p.y); + w->parent = par; + w->r = rectsubpt(w->r, w->r.min); + w->r = rectaddpt(w->r, p); +} diff --git a/libstuff/x11/windows/reshapewin.c b/libstuff/x11/windows/reshapewin.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +reshapewin(Window *w, Rectangle r) { + assert(w->type == WWindow); + assert(Dx(r) > 0 && Dy(r) > 0); /* Rather than an X error. */ + + configwin(w, r, w->border); +} diff --git a/libstuff/x11/windows/selectinput.c b/libstuff/x11/windows/selectinput.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +selectinput(Window *w, long mask) { + XSelectInput(display, w->xid, mask); +} diff --git a/libstuff/x11/windows/setborder.c b/libstuff/x11/windows/setborder.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setborder(Window *w, int width, Color col) { + + assert(w->type == WWindow); + if(width) + XSetWindowBorder(display, w->xid, col.pixel); + if(width != w->border) + configwin(w, w->r, width); +} diff --git a/libstuff/x11/windows/sethandler.c b/libstuff/x11/windows/sethandler.c @@ -0,0 +1,23 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Handlers* +sethandler(Window *w, Handlers *new) { + Handlers *old; + void **e; + + assert(w->type == WWindow); + assert((w->prev != nil && w->next != nil) || w->next == w->prev); + + if(new == nil) + map_rm(&windowmap, (ulong)w->xid); + else { + e = map_get(&windowmap, (ulong)w->xid, true); + *e = w; + } + old = w->handler; + w->handler = new; + return old; +} diff --git a/libstuff/x11/windows/setwinattr.c b/libstuff/x11/windows/setwinattr.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setwinattr(Window *w, WinAttr *wa, int valmask) { + assert(w->type == WWindow); + XChangeWindowAttributes(display, w->xid, valmask, wa); +} diff --git a/libstuff/x11/windows/unmapwin.c b/libstuff/x11/windows/unmapwin.c @@ -0,0 +1,16 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +unmapwin(Window *w) { + assert(w->type == WWindow); + if(w->mapped) { + XUnmapWindow(display, w->xid); + w->mapped = 0; + w->unmapped++; + return 1; + } + return 0; +} diff --git a/libstuff/x11/windows/window.c b/libstuff/x11/windows/window.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +window(XWindow xw) { + Window *w; + + w = malloc(sizeof *w); + w->type = WWindow; + w->xid = xw; + return freelater(w); +} diff --git a/libstuff/x11/x11.c b/libstuff/x11/x11.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +const Point ZP = {0, 0}; +const Rectangle ZR = {{0, 0}, {0, 0}}; + +const Window _pointerwin = { .xid = PointerRoot }; +Window* const pointerwin = (Window*)&_pointerwin; + + diff --git a/libstuff/x11/x11.h b/libstuff/x11/x11.h @@ -0,0 +1,31 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ + +#define _X11_VISIBLE +#define pointerwin __pointerwin +#include <assert.h> +#include <limits.h> +#include <math.h> +#include <strings.h> +#include <unistd.h> +#include <bio.h> +#include <stuff/x.h> +#include <stuff/util.h> +#undef pointerwin + +extern Map windowmap; +extern Map atommap; +extern MapEnt* wbucket[137]; +extern MapEnt* abucket[137]; + +extern int (*xlib_errorhandler) (Display*, XErrorEvent*); + +void configwin(Window*, Rectangle, int); +XPoint* convpts(Point*, int); +int errorhandler(Display*, XErrorEvent*); +ulong getprop(Window*, char*, char*, Atom*, int*, ulong, uchar**, ulong); +void setgccol(Image*, Color); +XftColor* xftcolor(Color); +XftDraw* xftdrawable(Image*); + diff --git a/libstuff/x11/xatom.c b/libstuff/x11/xatom.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +Atom +xatom(char *name) { + void **e; + + e = hash_get(&atommap, name, true); + if(*e == nil) + *e = (void*)XInternAtom(display, name, false); + return (Atom)*e; +} diff --git a/libstuff/xext.c b/libstuff/xext.c @@ -0,0 +1,161 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#define _X11_VISIBLE +#include <stuff/x.h> +#include <stuff/util.h> +#include <X11/extensions/Xrender.h> +#include <X11/extensions/Xinerama.h> + +#if RANDR_MAJOR < 1 +# error XRandR versions less than 1.0 are not supported +#endif + +static void randr_screenchange(XRRScreenChangeNotifyEvent*); +static bool randr_event_p(XEvent *e); +static void randr_init(void); +static void render_init(void); +static void xinerama_init(void); + +typedef void (*EvHandler)(XEvent*); +static EvHandler randr_handlers[RRNumberEvents]; + +bool have_RandR; +bool have_render; +bool have_xinerama; +int randr_eventbase; +Visual* render_visual; + +static void +handle(XEvent *e, EvHandler h[], int base) { + + if(h[e->type-base]) + h[e->type-base](e); +} + +void +xext_init(void) { + randr_init(); + render_init(); + xinerama_init(); +} + +void +xext_event(XEvent *e) { + + if(randr_event_p(e)) + handle(e, randr_handlers, randr_eventbase); +} + +static void +randr_init(void) { + int errorbase, major, minor; + + have_RandR = XRRQueryExtension(display, &randr_eventbase, &errorbase); + if(have_RandR) + if(XRRQueryVersion(display, &major, &minor) && major < 1) + have_RandR = false; + if(have_RandR) + XRRSelectInput(display, scr.root.xid, RRScreenChangeNotifyMask); +} + +static bool +randr_event_p(XEvent *e) { + return have_RandR + && (uint)e->type - randr_eventbase < RRNumberEvents; +} + +static void +randr_screenchange(XRRScreenChangeNotifyEvent *ev) { + + XRRUpdateConfiguration((XEvent*)ev); + if(ev->rotation*90 % 180) + scr.rect = Rect(0, 0, ev->width, ev->height); + else + scr.rect = Rect(0, 0, ev->height, ev->width); + init_screens(); +} + +static EvHandler randr_handlers[] = { + [RRScreenChangeNotify] = (EvHandler)randr_screenchange, +}; + +/* Ripped most graciously from ecore_x. XRender documentation + * is sparse. + */ +static void +render_init(void) { + XVisualInfo *vip; + XVisualInfo vi; + int base, i, n; + + have_render = XRenderQueryExtension(display, &base, &base); + if(!have_render) + return; + + vi.class = TrueColor; + vi.depth = 32; + vi.screen = scr.screen; + vip = XGetVisualInfo(display, VisualClassMask + | VisualDepthMask + | VisualScreenMask, + &vi, &n); + for(i=0; i < n; i++) + if(render_argb_p(vip[i].visual)) { + render_visual = vip[i].visual; + scr.visual32 = render_visual; + break; + } + XFree(vip); +} + +bool +render_argb_p(Visual *v) { + XRenderPictFormat *f; + + if(!have_render) + return false; + f = XRenderFindVisualFormat(display, v); + return f + && f->type == PictTypeDirect + && f->direct.alphaMask; +} + +static void +xinerama_init(void) { + int base; + + have_xinerama = XineramaQueryExtension(display, &base, &base); +} + +static bool +xinerama_active(void) { + return have_xinerama && XineramaIsActive(display); +} + +Rectangle* +xinerama_screens(int *np) { + static Rectangle *rects; + XineramaScreenInfo *res; + int i, n; + + if(!xinerama_active()) { + *np = 1; + return &scr.rect; + } + + free(rects); + res = XineramaQueryScreens(display, &n); + rects = emalloc(n * sizeof *rects); + for(i=0; i < n; i++) { + rects[i].min.x = res[i].x_org; + rects[i].min.y = res[i].y_org; + rects[i].max.x = res[i].x_org + res[i].width; + rects[i].max.y = res[i].y_org + res[i].height; + } + XFree(res); + + *np = n; + return rects; +} + diff --git a/libwmii_hack/Makefile b/libwmii_hack/Makefile @@ -1,15 +1,17 @@ ROOT= .. include ${ROOT}/mk/hdr.mk -hack.o hack.o_pic: util.c x11.c hack.h x11.h +hack.o hack.o_pic: util.c hack.h x11.h CFLAGS += $(INCX11) SOLDFLAGS += $(LIBX11) TARG = libwmii_hack -OBJ = hack -# util \ -# x11 +# Can't just link libstuff here. We need PIC objects. +OBJ = hack \ + ../libstuff/util/getbase \ + ../libstuff/util/getlong \ + ../libstuff/util/tokenize include ${ROOT}/mk/so.mk diff --git a/libwmii_hack/hack.h b/libwmii_hack/hack.h @@ -12,13 +12,13 @@ typedef unsigned char uchar; #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <x11.h> +#include <stuff/util.h> #include <X11/Xlib.h> #define strdup my_strdup +#define smprint my_smprint +#define vsmprint my_vsmprint -static int getlong(const char*, long*); -static uint tokenize(char*[], uint, char*, char); static char* smprint(const char*, ...); static char* vsmprint(const char*, va_list); static char* strdup(const char*); diff --git a/libwmii_hack/util.c b/libwmii_hack/util.c @@ -2,64 +2,6 @@ #include <stdio.h> #include <string.h> -#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1)) -static int -getbase(const char **s) { - const char *p; - - p = *s; - if(!strbcmp(p, "0x")) { - *s += 2; - return 16; - } - if(isdigit(p[0])) { - if(p[1] == 'r') { - *s += 2; - return p[0] - '0'; - } - if(isdigit(p[1]) && p[2] == 'r') { - *s += 3; - return 10*(p[0]-'0') + (p[1]-'0'); - } - } - if(p[0] == '0') { - *s += 1; - return 8; - } - return 10; -} - -static int -getlong(const char *s, long *ret) { - const char *end; - char *rend; - int base; - - end = s+strlen(s); - base = getbase(&s); - - *ret = strtol(s, &rend, base); - return (end == rend); -} - -static uint -tokenize(char *res[], uint reslen, char *str, char delim) { - char *s; - uint i; - - i = 0; - s = str; - while(i < reslen && *s) { - while(*s == delim) - *(s++) = '\0'; - if(*s) - res[i++] = s; - while(*s && *s != delim) - s++; - } - return i; -} - static char* vsmprint(const char *fmt, va_list ap) { va_list al; diff --git a/libwmii_hack/x11.c b/libwmii_hack/x11.c @@ -2,6 +2,7 @@ * See LICENSE file for license details. */ #include <assert.h> +#include "x11.h" /* Misc */ static Atom diff --git a/mk/gcc.mk b/mk/gcc.mk @@ -8,7 +8,7 @@ DEBUGCFLAGS = \ -fno-unroll-loops CFLAGS += \ -std=c99 \ - -pedantic \ + -pedantic-errors \ -pipe \ -fno-strict-aliasing \ -Wall \ diff --git a/mk/hdr.mk b/mk/hdr.mk @@ -22,8 +22,9 @@ FILTER = cat EXCFLAGS = $(INCLUDES) -D_XOPEN_SOURCE=600 -COMPILE = $(ROOT)/util/compile "$(CC)" "$(EXCFLAGS) $(CFLAGS) $$(pkg-config --cflags $(PACKAGES))" -COMPILEPIC = $(ROOT)/util/compile "$(CC)" "$(EXCFLAGS) $(CFLAGS) $$(pkg-config --cflags $(PACKAGES)) $(SOCFLAGS)" +COMPILE_FLAGS = $(EXCFLAGS) $(CFLAGS) $$(pkg-config --cflags $(PACKAGES)) +COMPILE = $(ROOT)/util/compile "$(CC)" "$(COMPILE_FLAGS)" +COMPILEPIC = $(ROOT)/util/compile "$(CC)" "$(COMPILE_FLAGS) $(SOCFLAGS)" LINK = $(ROOT)/util/link "$(LD)" "$$(pkg-config --libs $(PACKAGES)) $(LDFLAGS) $(LIBS)" LINKSO = $(ROOT)/util/link "$(LD)" "$$(pkg-config --libs $(PACKAGES)) $(SOLDFLAGS) $(LIBS) $(SHARED)" @@ -61,8 +62,8 @@ all: MAKEFILES=.depend .c.depend: echo MKDEP $< - [ -n "${noisycc}" ] && echo $(MKDEP) $(EXCFLAGS) $(CFLAGS) $$(pkg-config --cflags $(PACKAGES)) $< || true - $(MKDEP) $(EXCFLAGS) $(CFLAGS) $$(pkg-config --cflags $(PACKAGES)) $< >>.depend + [ -n "${noisycc}" ] && echo $(MKDEP) $(COMPILE_FLAGS) $< || true + eval "$(MKDEP) $(COMPILE_FLAGS)" $< >>.depend .sh.depend .rc.depend .1.depend .awk.depend: : diff --git a/mk/wmii.mk b/mk/wmii.mk @@ -13,7 +13,7 @@ COPYRIGHT = ©2010 Kris Maglione .MAKE.EXPORTED += WMII_HGVERSION SUBMAKE_EXPORT = WMII_HGVERSION=$(WMII_HGVERSION) -LIBS9 = $(ROOT)/lib/libregexp9.a $(ROOT)/lib/libbio.a $(ROOT)/lib/libfmt.a $(ROOT)/lib/libutf.a +LIBS9 = $(ROOT)/lib/libstuff.a $(ROOT)/lib/libregexp9.a $(ROOT)/lib/libbio.a $(ROOT)/lib/libfmt.a $(ROOT)/lib/libutf.a CFLAGS += '-DVERSION=\"$(VERSION)\"' '-DCOPYRIGHT=\"$(COPYRIGHT)\"' \ '-DCONFVERSION=\"$(CONFVERSION)\"' '-DCONFPREFIX=\"$(ETC)\"' diff --git a/test/grav.c b/test/grav.c @@ -21,8 +21,8 @@ #include <stdarg.h> #include <stdbool.h> #include <unistd.h> -#include <util.h> -#include <x11.h> +#include <stuff/util.h> +#include <stuff/x11.h> char buffer[8196]; void debug() {}