mirror of https://github.com/0intro/wmii
Add wistrut. Undocumented, not built by default.
This commit is contained in:
parent
86059e16d2
commit
a95494a9f7
|
@ -0,0 +1,26 @@
|
|||
ROOT= ../..
|
||||
include ${ROOT}/mk/hdr.mk
|
||||
include ${ROOT}/mk/wmii.mk
|
||||
|
||||
main.c: ${ROOT}/mk/wmii.mk
|
||||
|
||||
TARG = wistrut
|
||||
HFILES= dat.h fns.h
|
||||
|
||||
LIB = ${LIBIXP}
|
||||
LDFLAGS += -lm ${LIBX11} -lXext -lXrandr -lregexp9 -lbio -lfmt -lutf
|
||||
CFLAGS += ${INCX11} -DVERSION=\"${VERSION}\" \
|
||||
-DIXP_NEEDAPI=86
|
||||
OBJ = main \
|
||||
event \
|
||||
ewmh \
|
||||
win \
|
||||
_util \
|
||||
../wmii/map \
|
||||
../wmii/printevent \
|
||||
printevent_kludge \
|
||||
../wmii/x11 \
|
||||
../util
|
||||
|
||||
include ${ROOT}/mk/one.mk
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/* Copyright ©2008 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);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include <fmt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <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 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__)
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
/* Copyright ©2006-2008 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) {
|
||||
/* printevent(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->w) {
|
||||
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->w, 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->w)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/* Copyright ©2007-2008 Kris Maglione <fbsdaemon@gmail.com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "dat.h"
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "fns.h"
|
||||
|
||||
#define Net(x) ("_NET_" x)
|
||||
#define Action(x) ("_NET_WM_ACTION_" x)
|
||||
#define State(x) ("_NET_WM_STATE_" x)
|
||||
#define Type(x) ("_NET_WM_WINDOW_TYPE_" x)
|
||||
#define NET(x) xatom(Net(x))
|
||||
#define ACTION(x) xatom(Action(x))
|
||||
#define STATE(x) xatom(State(x))
|
||||
#define TYPE(x) xatom(Type(x))
|
||||
|
||||
enum {
|
||||
Left, Right, Top, Bottom,
|
||||
LeftMin, LeftMax,
|
||||
RightMin, RightMax,
|
||||
TopMin, TopMax,
|
||||
BottomMin, BottomMax,
|
||||
Last
|
||||
};
|
||||
|
||||
void
|
||||
ewmh_getstrut(Window *w, Rectangle struts[4]) {
|
||||
long *strut;
|
||||
ulong n;
|
||||
|
||||
memset(struts, 0, sizeof struts);
|
||||
|
||||
n = getprop_long(w, Net("WM_STRUT_PARTIAL"), "CARDINAL",
|
||||
0L, &strut, Last);
|
||||
if(n != Last) {
|
||||
free(strut);
|
||||
n = getprop_long(w, Net("WM_STRUT"), "CARDINAL",
|
||||
0L, &strut, 4L);
|
||||
if(n != 4) {
|
||||
free(strut);
|
||||
return;
|
||||
}
|
||||
strut = erealloc(strut, Last * sizeof *strut);
|
||||
strut[LeftMin] = strut[RightMin] = 0;
|
||||
strut[LeftMax] = strut[RightMax] = INT_MAX;
|
||||
strut[TopMin] = strut[BottomMin] = 0;
|
||||
strut[TopMax] = strut[BottomMax] = INT_MAX;
|
||||
}
|
||||
struts[Left] = Rect(0, strut[LeftMin], strut[Left], strut[LeftMax]);
|
||||
struts[Right] = Rect(-strut[Right], strut[RightMin], 0, strut[RightMax]);
|
||||
struts[Top] = Rect(strut[TopMin], 0, strut[TopMax], strut[Top]);
|
||||
struts[Bottom] = Rect(strut[BottomMin], -strut[Bottom], strut[BottomMax], 0);
|
||||
free(strut);
|
||||
}
|
||||
|
||||
void
|
||||
ewmh_setstrut(Window *w, Rectangle struts[4]) {
|
||||
long strut[Last];
|
||||
int i;
|
||||
|
||||
strut[LeftMin] = struts[Left].min.y;
|
||||
strut[Left] = struts[Left].max.x;
|
||||
strut[LeftMax] = struts[Left].max.y;
|
||||
|
||||
strut[RightMin] = struts[Right].min.y;
|
||||
strut[Right] = -struts[Right].min.x;
|
||||
strut[RightMax] = struts[Right].max.y;
|
||||
|
||||
strut[TopMin] = struts[Top].min.x;
|
||||
strut[Top] = struts[Top].max.y;
|
||||
strut[TopMax] = struts[Top].max.x;
|
||||
|
||||
strut[BottomMin] = struts[Bottom].min.x;
|
||||
strut[Bottom] = -struts[Bottom].min.y;
|
||||
strut[BottomMax] = struts[Bottom].max.x;
|
||||
|
||||
for(i=0; i<Last; i++)
|
||||
if(strut[i] < 0)
|
||||
strut[i] = 0;
|
||||
|
||||
changeprop_long(w, Net("WM_STRUT_PARTIAL"), "CARDINAL", strut, nelem(strut));
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
void debug(int, const char*, ...);
|
||||
void dispatch_event(XEvent*);
|
||||
uint flushevents(long, bool);
|
||||
uint flushenterevents(void);
|
||||
void xevent_loop(void);
|
||||
void xtime_kludge(void);
|
||||
|
||||
void restrut(void);
|
||||
|
||||
bool getlong(const char*, long*);
|
||||
bool getulong(const char*, ulong*);
|
||||
|
||||
void ewmh_getstrut(Window*, Rectangle[4]);
|
||||
void ewmh_setstrut(Window*, Rectangle[4]);
|
||||
|
||||
void printevent(XEvent *e);
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/* Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#define EXTERN
|
||||
#include "dat.h"
|
||||
#include <X11/Xproto.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include "fns.h"
|
||||
|
||||
static const char version[] = "witray-"VERSION", ©2007 Kris Maglione\n";
|
||||
|
||||
static int (*xlib_errorhandler) (Display*, XErrorEvent*);
|
||||
|
||||
static void
|
||||
usage(void) {
|
||||
fatal("usage: %s <window>\n", argv0);
|
||||
}
|
||||
|
||||
static int
|
||||
errfmt(Fmt *f) {
|
||||
return fmtstrcpy(f, ixp_errbuf());
|
||||
}
|
||||
|
||||
void
|
||||
debug(int flag, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
USED(flag);
|
||||
va_start(ap, fmt);
|
||||
vfprint(2, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* There's no way to check accesses to destroyed windows, thus
|
||||
* those cases are ignored (especially on UnmapNotifies).
|
||||
* Other types of errors call Xlib's default error handler, which
|
||||
* calls exit().
|
||||
*/
|
||||
struct {
|
||||
uchar rcode;
|
||||
uchar ecode;
|
||||
} itab[] = {
|
||||
{ 0, BadWindow },
|
||||
{ X_SetInputFocus, BadMatch },
|
||||
{ X_PolyText8, BadDrawable },
|
||||
{ X_PolyFillRectangle, BadDrawable },
|
||||
{ X_PolySegment, BadDrawable },
|
||||
{ X_ConfigureWindow, BadMatch },
|
||||
{ X_GrabKey, BadAccess },
|
||||
{ X_GetAtomName, BadAtom },
|
||||
};
|
||||
|
||||
static int
|
||||
errorhandler(Display *dpy, XErrorEvent *error) {
|
||||
int i;
|
||||
|
||||
USED(dpy);
|
||||
|
||||
if(error->request_code == X_QueryTree
|
||||
&& error->error_code == BadWindow
|
||||
&& error->resourceid == win.w)
|
||||
fatal("%W: window does not exist", &win);
|
||||
|
||||
for(i = 0; i < nelem(itab); i++)
|
||||
if((itab[i].rcode == 0 || itab[i].rcode == error->request_code)
|
||||
&& (itab[i].ecode == 0 || itab[i].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() */
|
||||
}
|
||||
|
||||
static Window
|
||||
findframe(Window *w) {
|
||||
XWindow *children;
|
||||
XWindow xw, par, root;
|
||||
Window ret = {0, };
|
||||
uint n;
|
||||
|
||||
for(par=w->w; par != scr.root.w; ) {
|
||||
xw = par;
|
||||
XQueryTree(display, xw, &root, &par, &children, &n);
|
||||
XFree(children);
|
||||
}
|
||||
ret.w = xw;
|
||||
ret.parent = &scr.root;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
getwinsize(Window *win) {
|
||||
int x, y;
|
||||
uint w, h;
|
||||
/* ignored */
|
||||
XWindow root;
|
||||
uint border, depth;
|
||||
|
||||
XGetGeometry(display, win->w, &root,
|
||||
&x, &y, &w, &h,
|
||||
&border, &depth);
|
||||
win->r = rectaddpt(Rect(0, 0, w, h),
|
||||
Pt(x, y));
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
char *s;
|
||||
|
||||
fmtinstall('r', errfmt);
|
||||
|
||||
ARGBEGIN{
|
||||
default:
|
||||
usage();
|
||||
}ARGEND;
|
||||
|
||||
s = EARGF(usage());
|
||||
if(!getulong(s, &win.w))
|
||||
usage();
|
||||
|
||||
if(argc)
|
||||
usage();
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
initdisplay();
|
||||
xlib_errorhandler = XSetErrorHandler(errorhandler);
|
||||
|
||||
frame = findframe(&win);
|
||||
getwinsize(&frame);
|
||||
restrut();
|
||||
sethandler(&frame, &handlers);
|
||||
selectinput(&frame, StructureNotifyMask);
|
||||
|
||||
running = true;
|
||||
xevent_loop();
|
||||
|
||||
XCloseDisplay(display);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/* Copyright ©2008 Kris Maglione <fbsdaemon@gmail.com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "dat.h"
|
||||
#include <string.h>
|
||||
#include "fns.h"
|
||||
|
||||
void
|
||||
restrut(void) {
|
||||
enum { Left, Right, Top, Bottom };
|
||||
Rectangle strut[4];
|
||||
Rectangle r;
|
||||
|
||||
r = frame.r;
|
||||
memset(strut, 0, sizeof strut);
|
||||
if(Dx(r) < Dx(scr.rect)/2) {
|
||||
if(r.min.x <= scr.rect.min.x) {
|
||||
strut[Left] = r;
|
||||
strut[Left].min.x = 0;
|
||||
strut[Left].max.x -= scr.rect.min.x;
|
||||
}
|
||||
if(r.max.x >= scr.rect.max.x) {
|
||||
strut[Right] = r;
|
||||
strut[Right].min.x -= scr.rect.max.x;
|
||||
strut[Right].max.x = 0;
|
||||
}
|
||||
}
|
||||
if(Dy(r) < Dy(scr.rect)/2) {
|
||||
if(r.min.y <= scr.rect.min.y) {
|
||||
strut[Top] = r;
|
||||
strut[Top].min.y = 0;
|
||||
strut[Top].max.y -= scr.rect.min.y;
|
||||
}
|
||||
if(r.max.y >= scr.rect.max.y) {
|
||||
strut[Bottom] = r;
|
||||
strut[Bottom].min.y -= scr.rect.max.y;
|
||||
strut[Bottom].max.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define pstrut(name) \
|
||||
if(!eqrect(strut[name], ZR)) \
|
||||
fprint(2, "strut["#name"] = %R\n", strut[name])
|
||||
/* Choose the struts which take up the least space.
|
||||
* Not ideal.
|
||||
*/
|
||||
if(Dy(strut[Top])) {
|
||||
if(strut[Top].min.x <= scr.rect.min.x)
|
||||
if(Dy(strut[Top]) < Dx(strut[Left]))
|
||||
strut[Left] = ZR;
|
||||
else
|
||||
strut[Top] = ZR;
|
||||
if(strut[Top].max.x >= scr.rect.max.x)
|
||||
if(Dy(strut[Top]) < Dx(strut[Right]))
|
||||
strut[Right] = ZR;
|
||||
else
|
||||
strut[Top] = ZR;
|
||||
}
|
||||
if(Dy(strut[Bottom])) {
|
||||
if(strut[Bottom].min.x <= scr.rect.min.x)
|
||||
if(Dy(strut[Bottom]) < Dx(strut[Left]))
|
||||
strut[Left] = ZR;
|
||||
else
|
||||
strut[Bottom] = ZR;
|
||||
if(strut[Bottom].max.x >= scr.rect.max.x)
|
||||
if(Dy(strut[Bottom]) < Dx(strut[Right]))
|
||||
strut[Right] = ZR;
|
||||
else
|
||||
strut[Bottom] = ZR;
|
||||
}
|
||||
|
||||
#if 0
|
||||
pstrut(Left);
|
||||
pstrut(Right);
|
||||
pstrut(Top);
|
||||
pstrut(Bottom);
|
||||
#endif
|
||||
|
||||
ewmh_setstrut(&win, strut);
|
||||
}
|
||||
|
||||
static void
|
||||
config(Window *w, XConfigureEvent *ev) {
|
||||
|
||||
USED(w);
|
||||
|
||||
frame.r = rectaddpt(Rect(0, 0, ev->width, ev->height),
|
||||
Pt(ev->x, ev->y));
|
||||
restrut();
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
destroy(Window *w, XDestroyWindowEvent *ev) {
|
||||
USED(w, ev);
|
||||
running = false;
|
||||
}
|
||||
|
||||
Handlers handlers = {
|
||||
.config = config,
|
||||
.destroy = destroy,
|
||||
};
|
||||
|
|
@ -152,7 +152,7 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
|||
sethandler(c->framewin, &framehandler);
|
||||
sethandler(&c->w, &handlers);
|
||||
|
||||
XSelectInput(display, c->w.w, ClientMask);
|
||||
selectinput(&c->w, ClientMask);
|
||||
|
||||
p.x = def.border;
|
||||
p.y = labelh(def.font);
|
||||
|
|
|
@ -328,9 +328,8 @@ main(int argc, char *argv[]) {
|
|||
xlib_errorhandler = XSetErrorHandler(errorhandler);
|
||||
|
||||
check_other_wm = true;
|
||||
XSelectInput(display, scr.root.w,
|
||||
SubstructureRedirectMask
|
||||
| EnterWindowMask);
|
||||
selectinput(&scr.root, SubstructureRedirectMask
|
||||
| EnterWindowMask);
|
||||
sync();
|
||||
|
||||
check_other_wm = false;
|
||||
|
|
|
@ -278,6 +278,11 @@ setwinattr(Window *w, WinAttr *wa, int valmask) {
|
|||
XChangeWindowAttributes(display, w->w, valmask, wa);
|
||||
}
|
||||
|
||||
void
|
||||
selectinput(Window *w, long mask) {
|
||||
XSelectInput(display, w->w, mask);
|
||||
}
|
||||
|
||||
void
|
||||
setborder(Window *w, int width, long pixel) {
|
||||
Rectangle r;
|
||||
|
|
|
@ -82,6 +82,7 @@ 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*);
|
||||
|
@ -221,6 +222,7 @@ 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, long);
|
||||
void setfocus(Window*, int mode);
|
||||
|
|
Loading…
Reference in New Issue