New event processing model.

This commit is contained in:
Kris Maglione 2007-04-16 19:54:31 -04:00
parent b67d9d3848
commit d8a7ede21f
9 changed files with 395 additions and 212 deletions

View File

@ -8,7 +8,32 @@
#include "dat.h"
#include "fns.h"
Bar *free_bars = nil;
static Handlers handlers;
static Bar *free_bars;
void
initbar(WMScreen *s) {
WinAttr wa;
s->brect = s->rect;
s->brect.min.y = s->brect.max.y - labelh(def.font);
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask =
ExposureMask
| ButtonReleaseMask
| FocusChangeMask
| SubstructureRedirectMask
| SubstructureNotifyMask;
s->barwin = createwindow(&scr.root, s->brect, scr.depth, InputOutput, &wa,
CWOverrideRedirect
| CWBackPixmap
| CWEventMask);
sethandler(s->barwin, &handlers);
mapwin(s->barwin);
}
Bar *
create_bar(Bar **bp, char *name) {
@ -147,3 +172,29 @@ bar_of_name(Bar *bp, const char *name) {
break;
return b;
}
static void
bup_event(Window *w, XButtonPressedEvent *e) {
Bar *b;
for(b=screen->bar[BarLeft]; b; b=b->next)
if(ptinrect(Pt(e->x, e->y), b->r)) {
write_event("LeftBarClick %d %s\n", e->button, b->name);
return;
}
for(b=screen->bar[BarRight]; b; b=b->next)
if(ptinrect(Pt(e->x, e->y), b->r)) {
write_event("RightBarClick %d %s\n", e->button, b->name);
return;
}
}
static void
expose_event(Window *w, XExposeEvent *e) {
draw_bar(screen);
}
static Handlers handlers = {
.bup = bup_event,
.expose = expose_event,
};

View File

@ -11,6 +11,7 @@
#include "fns.h"
static void update_client_name(Client *c);
static Handlers handlers;
static char Ebadcmd[] = "bad command",
Ebadvalue[] = "bad value";
@ -64,7 +65,10 @@ create_client(XWindow w, XWindowAttributes *wa) {
| CWEventMask
| CWBackPixmap
| CWBackingStore);
XSync(display, False);
c->framewin->aux = c;
c->win.aux = c;
sethandler(c->framewin, &framehandler);
sethandler(&c->win, &handlers);
for(t=&client ;; t=&(*t)->next)
if(!*t) {
@ -106,8 +110,9 @@ destroy_client(Client *c) {
reparent_client(c, &scr.root, c->rect.min);
destroywindow(c->framewin);
XSync(display, False);
sethandler(&c->win, nil);
XSync(display, False);
XSetErrorHandler(wmii_error_handler);
XUngrabServer(display);
flushevents(EnterWindowMask, False);
@ -150,6 +155,146 @@ manage_client(Client *c) {
flushevents(EnterWindowMask, False);
}
/* Handlers */
static void
configreq_event(Window *w, XConfigureRequestEvent *e) {
Rectangle *frect;
Frame *f;
Client *c;
c = w->aux;
f = c->sel;
gravitate_client(c, True);
if(e->value_mask & CWX)
c->rect.min.x = e->x;
if(e->value_mask & CWY)
c->rect.min.y = e->y;
if(e->value_mask & CWWidth)
c->rect.max.x = c->rect.min.x + e->width;
if(e->value_mask & CWHeight)
c->rect.max.y = c->rect.min.y + e->height;
if(e->value_mask & CWBorderWidth)
c->border = e->border_width;
gravitate_client(c, False);
if((Dx(c->rect) == Dx(screen->rect))
&& (Dy(c->rect) == Dy(screen->rect))) {
c->fullscreen = True;
if(c->sel) {
if(!c->sel->area->floating)
send_to_area(c->sel->view->area, c->sel);
focus_client(c);
restack_view(c->sel->view);
}
}
if(c->sel->area->floating)
frect=&c->sel->rect;
else
frect=&c->sel->revert;
*frect = insetrect(c->rect, -def.border);
frect->min.y -= labelh(def.font);
if(c->sel->area->floating || c->fullscreen)
resize_client(c, frect);
else
configure_client(c);
}
static void
destroy_event(Window *w, XDestroyWindowEvent *e) {
destroy_client(w->aux);
}
static void
enter_event(Window *w, XCrossingEvent *e) {
Client *c;
c = w->aux;
if(e->detail != NotifyInferior) {
if(screen->focus != c) {
if(verbose) fprintf(stderr, "enter_notify(c) => %s\n", c->name);
focus(c, False);
}
set_cursor(c, cursor[CurNormal]);
}else if(verbose) fprintf(stderr, "enter_notify(c[NotifyInferior]) => %s\n", c->name);
}
static void
focusin_event(Window *w, XFocusChangeEvent *e) {
Client *c, *old;
c = w->aux;
//print_focus(c, c->name);
if(e->mode == NotifyGrab)
screen->hasgrab = c;
old = screen->focus;
screen->focus = c;
if(c != old) {
update_client_grab(c);
if(c->sel)
draw_frame(c->sel);
if(old && old->sel)
draw_frame(old->sel);
}
}
static void
focusout_event(Window *w, XFocusChangeEvent *e) {
Client *c;
c = w->aux;
if((e->mode == NotifyWhileGrabbed) && (screen->hasgrab != &c_root)) {
if((screen->focus)
&& (screen->hasgrab != screen->focus))
screen->hasgrab = screen->focus;
if(screen->hasgrab == c)
return;
}else if(e->mode != NotifyGrab) {
if(screen->focus == c) {
//print_focus(&c_magic, "<magic>");
screen->focus = &c_magic;
}
update_client_grab(c);
if(c->sel)
draw_frame(c->sel);
}
}
static void
unmap_event(Window *w, XUnmapEvent *e) {
Client *c;
c = w->aux;
if(!e->send_event)
c->unmapped--;
destroy_client(c);
}
static void
map_event(Window *w, XMapEvent *e) {
Client *c;
c = w->aux;
if(c == selclient())
focus_client(c);
}
static Handlers handlers = {
.configreq = configreq_event,
.destroy = destroy_event,
.enter = enter_event,
.focusin = focusin_event,
.focusout = focusout_event,
.map = map_event,
.unmap = unmap_event,
};
Client *
selclient() {
if(screen->sel && screen->sel->sel->sel)

View File

@ -12,6 +12,7 @@
static Image *divimg, *divmask;
static CTuple divc;
static Handlers divhandler;
char *modes[] = {
[Coldefault] = "default",
@ -56,9 +57,11 @@ get_div(Divide **dp) {
| ButtonPressMask
| ButtonReleaseMask;
d->w = createwindow(&scr.root, Rect(0, 0, 1, 1), scr.depth, InputOutput, &wa,
CWOverrideRedirect
| CWEventMask
| CWCursor);
CWOverrideRedirect
| CWEventMask
| CWCursor);
d->w->aux = d;
sethandler(d->w, &divhandler);
*dp = d;
return d;
@ -159,6 +162,28 @@ draw_div(Divide *d) {
setshapemask(d->w, divmask, ZP);
}
/* Div Handlers */
static void
bdown_event(Window *w, XButtonEvent *e) {
Divide *d;
d = w->aux;
mouse_resizecol(d);
}
static void
expose_event(Window *w, XExposeEvent *e) {
Divide *d;
d = w->aux;
draw_div(d);
}
static Handlers divhandler = {
.bdown = bdown_event,
.expose = expose_event,
};
Area *
new_column(View *v, Area *pos, uint w) {
Area *a;

View File

@ -211,6 +211,8 @@ Divide *divs;
Client c_magic;
Client c_root;
Handlers framehandler;
char buffer[8092];
/* IXP */

View File

@ -31,79 +31,24 @@ flushevents(long event_mask, Bool dispatch) {
static void
buttonrelease(XEvent *e) {
XButtonPressedEvent *ev;
Frame *f;
Bar *b;
Window *w;
ev = &e->xbutton;
if(ev->window == screen->barwin->w) {
for(b=screen->bar[BarLeft]; b; b=b->next)
if(ptinrect(Pt(ev->x, ev->y), b->r)) {
write_event("LeftBarClick %d %s\n", ev->button, b->name);
return;
}
for(b=screen->bar[BarRight]; b; b=b->next)
if(ptinrect(Pt(ev->x, ev->y), b->r)) {
write_event("RightBarClick %d %s\n", ev->button, b->name);
return;
}
}
else if((f = win2frame(ev->window)))
write_event("ClientClick 0x%x %d\n", f->client->win.w, ev->button);
if((w = findwin(e->xany.window)))
if(w->handler->bup)
w->handler->bup(w, ev);
}
static void
buttonpress(XEvent *e) {
XButtonPressedEvent *ev;
Divide *d;
Frame *f;
Window *w;
ev = &e->xbutton;
if((f = win2frame(ev->window))) {
if((ev->state & def.mod) == def.mod) {
switch(ev->button) {
case Button1:
do_mouse_resize(f->client, False, CENTER);
focus(f->client, True);
frame_to_top(f);
focus(f->client, True);
break;
case Button3:
do_mouse_resize(f->client, False,
quadrant(f->rect, Pt(ev->x_root, ev->y_root)));
frame_to_top(f);
focus(f->client, True);
break;
default: break;
XAllowEvents(display, ReplayPointer, ev->time);
}
}else{
if(ev->button == Button1) {
if(frame_to_top(f))
restack_view(f->view);
else if(ptinrect(Pt(ev->x, ev->y), f->grabbox))
do_mouse_resize(f->client, True, CENTER);
else if(f->area->floating)
if(!ev->subwindow && !ptinrect(Pt(ev->x, ev->y), f->titlebar))
do_mouse_resize(f->client, False,
quadrant(f->rect, Pt(ev->x_root, ev->y_root)));
if(f->client != selclient())
focus(f->client, True);
}
if(ev->subwindow)
XAllowEvents(display, ReplayPointer, ev->time);
else {
/* Ungrab so a menu can receive events before the button is released */
XUngrabPointer(display, ev->time);
XSync(display, False);
write_event("ClientMouseDown 0x%x %d\n", f->client->win.w, ev->button);
}
}
if((w = findwin(e->xany.window))) {
if(w->handler->bdown)
w->handler->bdown(w, ev);
}
else if((d = win2div(ev->window)))
mouse_resizecol(d);
else
XAllowEvents(display, ReplayPointer, ev->time);
}
@ -111,51 +56,13 @@ buttonpress(XEvent *e) {
static void
configurerequest(XEvent *e) {
XConfigureRequestEvent *ev;
Window *w;
XWindowChanges wc;
Rectangle *frect;
Client *c;
Frame *f;
ev = &e->xconfigurerequest;
c = win2client(ev->window);
if(c) {
f = c->sel;
gravitate_client(c, True);
if(ev->value_mask & CWX)
c->rect.min.x = ev->x;
if(ev->value_mask & CWY)
c->rect.min.y = ev->y;
if(ev->value_mask & CWWidth)
c->rect.max.x = c->rect.min.x + ev->width;
if(ev->value_mask & CWHeight)
c->rect.max.y = c->rect.min.y + ev->height;
if(ev->value_mask & CWBorderWidth)
c->border = ev->border_width;
gravitate_client(c, False);
if((Dx(c->rect) == Dx(screen->rect))
&& (Dy(c->rect) == Dy(screen->rect))) {
c->fullscreen = True;
if(c->sel) {
if(!c->sel->area->floating)
send_to_area(c->sel->view->area, c->sel);
focus_client(c);
restack_view(c->sel->view);
}
}
if(c->sel->area->floating)
frect=&c->sel->rect;
else
frect=&c->sel->revert;
*frect = insetrect(c->rect, -def.border);
frect->min.y -= labelh(def.font);
if(c->sel->area->floating || c->fullscreen)
resize_client(c, frect);
else
configure_client(c);
if((w = findwin(e->xany.window))) {
if(w->handler->configreq)
w->handler->configreq(w, ev);
}else{
wc.x = ev->x;
wc.y = ev->y;
@ -173,39 +80,27 @@ configurerequest(XEvent *e) {
static void
destroynotify(XEvent *e) {
XDestroyWindowEvent *ev;
Client *c;
Window *w;
ev = &e->xdestroywindow;
if((c = win2client(ev->window)))
destroy_client(c);
if((w = findwin(e->xany.window))) {
if(w->handler->destroy)
w->handler->destroy(w, ev);
}
}
static void
enternotify(XEvent *e) {
XCrossingEvent *ev;
Client *c;
Frame *f;
Window *w;
ev = &e->xcrossing;
if(ev->mode != NotifyNormal)
return;
if((c = win2client(ev->window))) {
if(ev->detail != NotifyInferior) {
if(screen->focus != c) {
if(verbose) fprintf(stderr, "enter_notify(c) => %s\n", c->name);
focus(c, False);
}
set_cursor(c, cursor[CurNormal]);
}else if(verbose) fprintf(stderr, "enter_notify(c[NotifyInferior]) => %s\n", c->name);
}
else if((f = win2frame(ev->window))) {
if(screen->focus != c) {
if(verbose) fprintf(stderr, "enter_notify(f) => %s\n", f->client->name);
if(f->area->floating || !f->collapsed)
focus(f->client, False);
}
set_frame_cursor(f, Pt(ev->x, ev->y));
if((w = findwin(e->xany.window))) {
if(w->handler->enter)
w->handler->enter(w, ev);
}
else if(ev->window == scr.root.w) {
sel_screen = True;
@ -216,8 +111,10 @@ enternotify(XEvent *e) {
static void
leavenotify(XEvent *e) {
XCrossingEvent *ev;
Window *w;
ev = &e->xcrossing;
w = findwin(e->xany.window);
if((ev->window == scr.root.w) && !ev->same_screen) {
sel_screen = True;
draw_frames();
@ -238,7 +135,8 @@ print_focus(Client *c, char *to) {
static void
focusin(XEvent *e) {
XFocusChangeEvent *ev;
Client *c, *old;
Window *w;
Client *c;
XEvent me;
ev = &e->xfocus;
@ -258,24 +156,15 @@ focusin(XEvent *e) {
&& (screen->hasgrab != &c_root))
return;
old = screen->focus;
c = win2client(ev->window);
if(c) {
print_focus(c, c->name);
if(ev->mode == NotifyGrab)
screen->hasgrab = c;
screen->focus = c;
if(c != old) {
update_client_grab(c);
if(c->sel)
draw_frame(c->sel);
if(old && old->sel)
draw_frame(old->sel);
}
}else if(ev->window == screen->barwin->w) {
if((w = findwin(e->xany.window))) {
if(w->handler->focusin)
w->handler->focusin(w, ev);
}
else if(ev->window == screen->barwin->w) {
print_focus(nil, "<nil>");
screen->focus = nil;
}else if(ev->mode == NotifyGrab) {
}
else if(ev->mode == NotifyGrab) {
if(ev->window == scr.root.w)
if(XCheckMaskEvent(display, KeyPressMask, &me)) {
/* wmii has grabbed focus */
@ -296,7 +185,7 @@ focusin(XEvent *e) {
static void
focusout(XEvent *e) {
XFocusChangeEvent *ev;
Client *c;
Window *w;
ev = &e->xfocus;
if(!((ev->detail == NotifyNonlinear)
@ -305,49 +194,33 @@ focusout(XEvent *e) {
if(ev->mode == NotifyUngrab)
screen->hasgrab = nil;
c = win2client(ev->window);
if(c) {
if((ev->mode == NotifyWhileGrabbed)
&& (screen->hasgrab != &c_root)) {
if((screen->focus)
&& (screen->hasgrab != screen->focus))
screen->hasgrab = screen->focus;
if(screen->hasgrab == c)
return;
}else if(ev->mode != NotifyGrab) {
if(screen->focus == c) {
print_focus(&c_magic, "<magic>");
screen->focus = &c_magic;
}
update_client_grab(c);
if(c->sel)
draw_frame(c->sel);
}
if((w = findwin(e->xany.window))) {
if(w->handler->focusout)
w->handler->focusout(w, ev);
}
}
static void
expose(XEvent *e) {
XExposeEvent *ev;
Divide *d;
Frame *f;
Window *w;
ev = &e->xexpose;
if(ev->count == 0) {
if(ev->window == screen->barwin->w)
draw_bar(screen);
else if((f = win2frame(ev->window)))
draw_frame(f);
else if((d = win2div(ev->window)))
draw_div(d);
if((w = findwin(e->xany.window))) {
if(w->handler->expose)
w->handler->expose(w, ev);
}
}
}
static void
keypress(XEvent *e) {
XKeyEvent *ev;
Window *w;
ev = &e->xkey;
w = findwin(e->xany.window);
ev->state &= valid_mask;
if(ev->window == scr.root.w)
kpress(scr.root.w, ev->state, (KeyCode) ev->keycode);
@ -366,9 +239,11 @@ mappingnotify(XEvent *e) {
static void
maprequest(XEvent *e) {
XMapRequestEvent *ev;
static XWindowAttributes wa;
Window *w;
XWindowAttributes wa;
ev = &e->xmaprequest;
w = findwin(e->xany.window);
if(!XGetWindowAttributes(display, ev->window, &wa))
return;
if(wa.override_redirect) {
@ -383,19 +258,23 @@ maprequest(XEvent *e) {
static void
motionnotify(XEvent *e) {
XMotionEvent *ev;
Frame *f;
Window *w;
ev = &e->xmotion;
if((f = win2frame(ev->window)))
set_frame_cursor(f, Pt(ev->x, ev->y));
if((w = findwin(e->xany.window))) {
if(w->handler->motion)
w->handler->motion(w, ev);
}
}
static void
propertynotify(XEvent *e) {
XPropertyEvent *ev;
Window *w;
Client *c;
ev = &e->xproperty;
w = findwin(e->xany.window);
if(ev->state == PropertyDelete)
return; /* ignore */
if((c = win2client(ev->window)))
@ -405,23 +284,26 @@ propertynotify(XEvent *e) {
static void
mapnotify(XEvent *e) {
XMapEvent *ev;
Client *c;
Window *w;
ev = &e->xmap;
if((c = win2client(ev->window)))
if(c == selclient())
focus_client(c);
if((w = findwin(e->xany.window))) {
if(w->handler->map)
w->handler->map(w, ev);
}
}
static void
unmapnotify(XEvent *e) {
XUnmapEvent *ev;
Client *c;
Window *w;
ev = &e->xunmap;
if((c = win2client(ev->window)))
if(ev->send_event || (c->unmapped-- == 0))
destroy_client(c);
if((w = findwin(e->xany.window))) {
if(ev->send_event || w->unmapped-- == 0)
if(w->handler->unmap)
w->handler->unmap(w, ev);
}
}
void (*handler[LASTEvent]) (XEvent *) = {
@ -441,7 +323,6 @@ void (*handler[LASTEvent]) (XEvent *) = {
[MotionNotify] = motionnotify,
[PropertyNotify]= propertynotify,
[UnmapNotify] = unmapnotify,
};
void

View File

@ -17,6 +17,7 @@ void detach_from_area(Frame*);
Client *area_selclient(Area*);
/* bar.c */
void initbar(WMScreen *s);
Bar *create_bar(Bar **b_link, char *name);
void destroy_bar(Bar **b_link, Bar*);
void draw_bar(WMScreen *s);
@ -165,6 +166,8 @@ void reshapewin(Window *w, Rectangle r);
void movewin(Window *w, Point pt);
int mapwin(Window *w);
int unmapwin(Window *w);
Handlers* sethandler(Window*, Handlers*);
Window* findwin(XWindow w);
uint winprotocols(Window *w);
void setshapemask(Window *dst, Image *src, Point pt);
void border(Image *dst, Rectangle r, int w, ulong col);

View File

@ -102,6 +102,101 @@ client2frame(Frame *f, Rectangle r) {
return r;
}
/* Handlers */
static void
bup_event(Window *w, XButtonEvent *e) {
write_event("ClientClick 0x%x %d\n", (uint)w->w, e->button);
}
static void
bdown_event(Window *w, XButtonEvent *e) {
Frame *f;
Client *c;
c = w->aux;
f = c->sel;
if((e->state & def.mod) == def.mod) {
switch(e->button) {
case Button1:
do_mouse_resize(c, False, CENTER);
focus(c, True);
frame_to_top(f);
focus(c, True);
break;
case Button3:
do_mouse_resize(c, False, quadrant(f->rect, Pt(e->x_root, e->y_root)));
frame_to_top(f);
focus(c, True);
break;
default: break;
XAllowEvents(display, ReplayPointer, e->time);
}
}else{
if(e->button == Button1) {
if(frame_to_top(f))
restack_view(f->view);
else if(ptinrect(Pt(e->x, e->y), f->grabbox))
do_mouse_resize(c, True, CENTER);
else if(f->area->floating)
if(!e->subwindow && !ptinrect(Pt(e->x, e->y), f->titlebar))
do_mouse_resize(c, False, quadrant(f->rect, Pt(e->x_root, e->y_root)));
if(f->client != selclient())
focus(c, True);
}
if(e->subwindow)
XAllowEvents(display, ReplayPointer, e->time);
else {
/* Ungrab so a menu can receive events before the button is released */
XUngrabPointer(display, e->time);
XSync(display, False);
write_event("ClientMouseDown 0x%x %d\n", f->client->win.w, e->button);
}
}
}
static void
enter_event(Window *w, XCrossingEvent *e) {
Client *c;
Frame *f;
c = w->aux;
f = c->sel;
if(screen->focus != c) {
if(verbose) fprintf(stderr, "enter_notify(f) => %s\n", f->client->name);
if(f->area->floating || !f->collapsed)
focus(f->client, False);
}
set_frame_cursor(f, Pt(e->x, e->y));
}
static void
expose_event(Window *w, XExposeEvent *e) {
Client *c;
c = w->aux;
draw_frame(c->sel);
}
static void
motion_event(Window *w, XMotionEvent *e) {
Client *c;
c = w->aux;
set_frame_cursor(c->sel, Pt(e->x, e->y));
}
Handlers framehandler = {
.bup = bup_event,
.bdown = bdown_event,
.enter = enter_event,
.expose = expose_event,
.motion = motion_event,
};
void
resize_frame(Frame *f, Rectangle r) {
Align stickycorner;
@ -115,7 +210,8 @@ resize_frame(Frame *f, Rectangle r) {
apply_sizehints(c, &f->crect, f->area->floating, True, stickycorner);
if(Dx(r) <= 0 || Dy(r) <= 0)
asm("int $3");
fprintf(stderr, "Badness: Frame rect: %d,%d %dx%d\n",
r.min.x, r.min.y, Dx(r), Dy(r));
if(f->area->floating)
f->rect = f->crect;

View File

@ -472,27 +472,7 @@ main(int argc, char *argv[]) {
setwinattr(&scr.root, &wa,
CWEventMask
| CWCursor);
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask =
ExposureMask
| ButtonReleaseMask
| FocusChangeMask
| SubstructureRedirectMask
| SubstructureNotifyMask;
s->brect = s->rect;
s->brect.min.y = s->brect.max.y - labelh(def.font);
s->barwin = createwindow(&scr.root, s->brect, scr.depth, InputOutput, &wa,
CWOverrideRedirect
| CWBackPixmap
| CWEventMask);
XSync(display, False);
draw_bar(s);
XMapRaised(display, s->barwin->w);
initbar(s);
}
screen = &screens[0];

View File

@ -215,7 +215,7 @@ restack_view(View *v) {
for(f=v->area->stack; f; f=f->snext)
wins[n++] = f->client->framewin->w;
for(d = divs; d && d->mapped; d = d->next)
for(d = divs; d && d->w->mapped; d = d->next)
wins[n++] = d->w->w;
for(a=v->area->next; a; a=a->next)