mirror of
https://github.com/0intro/wmii
synced 2024-11-22 13:52:17 +03:00
335 lines
6.4 KiB
C
335 lines
6.4 KiB
C
/* 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);
|
|
}
|
|
|