diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/src/resize.c ion-devel-20020130/src/resize.c --- ion-devel-20020130-pristine/src/resize.c Sun Jan 27 14:49:47 2002 +++ ion-devel-20020130/src/resize.c Wed Feb 6 10:52:58 2002 @@ -10,6 +10,40 @@ #include #include "resize.h" #include "split.h" +#include "bindmaps.h" + + +/*{{{ keyboard handling */ + +static bool resize_handler(WRegion *thing, XEvent *xev) +{ + XKeyEvent *ev=&xev->xkey; + WScreen *scr; + WBinding *binding=NULL; + WBindmap **bindptr; + + if(ev->type==KeyRelease) + return FALSE; + + assert(thing && WTHING_IS(thing, WWindow)); + binding=lookup_binding(&ion_moveres_bindmap, ACT_KEYPRESS, ev->state, ev->keycode); + + if(!binding) + return FALSE; + + if(binding){ + /* Get the screen now for waitrel grab - the thing might + * have been destroyed when call_binding returns. + */ + scr=SCREEN_OF(thing); + call_binding(binding, (WThing *)thing); + } + + return !is_resizing(); +} + + +/*}}}*/ /*{{{ Keyboard resize */ @@ -17,19 +51,20 @@ static int tmpdir=0; +static void end_keyresize() +{ + grab_remove(resize_handler); +} + static void begin_keyresize(WRegion *reg, int dir) { XSizeHints hints; uint relw, relh; -#warning TODO: set up bindings - - return; + grab_establish((WThing *)reg, resize_handler, FocusChangeMask|KeyReleaseMask); tmpdir=dir; - begin_resize(reg, NULL); - - /*((WWindow*)reg)->bindmap=&(ion_moveres_bindmap);*/ + begin_resize_atexit(reg, NULL, end_keyresize); } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/Makefile ion-devel-20020130/wmcore/Makefile --- ion-devel-20020130-pristine/wmcore/Makefile Wed Jan 30 22:49:28 2002 +++ ion-devel-20020130/wmcore/Makefile Wed Feb 6 09:34:56 2002 @@ -20,7 +20,7 @@ sizehint.o thing.o window.o wmcore.o xic.o selection.o \ completehelp.o symlist.o clientwin.o colormap.o region.o \ eventh.o winpropsgen.o targetid.o attach.o resize.o close.o \ - defer.o + defer.o grab.o TARGETS=wmcore.a diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/event.c ion-devel-20020130/wmcore/event.c --- ion-devel-20020130-pristine/wmcore/event.c Sat Dec 29 20:04:38 2001 +++ ion-devel-20020130/wmcore/event.c Wed Feb 6 12:09:55 2002 @@ -77,12 +77,12 @@ /*{{{ Grab */ -void do_grab_kb_ptr(Window win, WRegion *reg) +void do_grab_kb_ptr(Window win, WRegion *reg, long eventmask) { wglobal.grab_holder=reg; wglobal.input_mode=INPUT_GRAB; - XSelectInput(wglobal.dpy, win, ROOT_MASK&~FocusChangeMask); + XSelectInput(wglobal.dpy, win, ROOT_MASK&~eventmask); XGrabPointer(wglobal.dpy, win, True, GRAB_POINTER_MASK, GrabModeAsync, GrabModeAsync, win, x_cursor(CURSOR_DEFAULT), CurrentTime); @@ -94,7 +94,7 @@ void grab_kb_ptr(WRegion *reg) { - do_grab_kb_ptr(ROOT_OF(reg), reg); + do_grab_kb_ptr(ROOT_OF(reg), reg, FocusChangeMask); } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/event.h ion-devel-20020130/wmcore/event.h --- ion-devel-20020130-pristine/wmcore/event.h Sat Dec 29 20:04:38 2001 +++ ion-devel-20020130/wmcore/event.h Wed Feb 6 12:17:21 2002 @@ -35,7 +35,7 @@ extern void get_event(XEvent *ev); extern void get_event_mask(XEvent *ev, long mask); -extern void do_grab_kb_ptr(Window win, WRegion *reg); +extern void do_grab_kb_ptr(Window win, WRegion *reg, long eventmask); extern void grab_kb_ptr(WRegion *reg); extern void ungrab_kb_ptr(); diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/eventh.c ion-devel-20020130/wmcore/eventh.c --- ion-devel-20020130-pristine/wmcore/eventh.c Wed Jan 30 03:34:30 2002 +++ ion-devel-20020130/wmcore/eventh.c Wed Feb 6 16:41:37 2002 @@ -162,15 +162,10 @@ handle_expose(&(ev->xexpose)); break; CASE_EVENT(KeyPress) - if(wglobal.input_mode!=INPUT_WAITRELEASE) keyboard_handler(ev); break; CASE_EVENT(KeyRelease) - if(wglobal.input_mode==INPUT_WAITRELEASE){ - if(unmod(ev->xkey.state, ev->xkey.keycode)==0) - ungrab_kb_ptr(); - /*skip_focusenter();*/ - } + keyboard_handler(ev); break; CASE_EVENT(ButtonPress) pointer_handler(ev); @@ -553,23 +548,55 @@ static void pointer_handler(XEvent *ev) { - do_grab_kb_ptr(ev->xbutton.root, NULL); + XEvent tmp; + Window win_pressed; + WThing *t; + bool mouse_grab_held=FALSE; + bool refocus=FALSE; + bool justeat; + + if(grab_held()) + return; + + win_pressed=ev->xbutton.window; - handle_button_press(&(ev->xbutton)); + if(!handle_button_press(&(ev->xbutton))) + return; - while(wglobal.input_mode!=INPUT_NORMAL){ + mouse_grab_held=TRUE; + + while(mouse_grab_held){ XFlush(wglobal.dpy); get_event_mask(ev, GRAB_EV_MASK); switch(ev->type){ - case ButtonRelease: - if(handle_button_release(&(ev->xbutton))) + CASE_EVENT(ButtonRelease) + if(handle_button_release(&ev->xbutton)){ ungrab_kb_ptr(); + mouse_grab_held=FALSE; + + /* + * XUngrab*() generate events carrying mode==NotifyUngrab (see + * handle_enter_window() for more info). + * we'll try to catch the offending ButtonPress-triggered + * EnterNotify and use set_focus() to generate deferred + * FocusChange/EnterNotify events which do not carry mode=NotifyUngrab + * anymore and get interpreted just fine. argh. + */ + /*XSync(wglobal.dpy, False); + justeat=(wglobal.focus_next!=NULL); + if(XCheckTypedWindowEvent(wglobal.dpy, win_pressed, EnterNotify, &tmp)){ + t=(WThing*)FIND_WINDOW_T(win_pressed, WWindow); + if(t && !justeat){ + set_focus(t); + } + }*/ + } break; - case MotionNotify: - handle_pointer_motion(&(ev->xmotion)); + CASE_EVENT(MotionNotify) + handle_pointer_motion(&ev->xmotion); break; - case Expose: + CASE_EVENT(Expose) handle_expose(&(ev->xexpose)); break; } @@ -579,8 +606,12 @@ static void keyboard_handler(XEvent *ev) { - handle_keypress(&(ev->xkey)); + if(call_grab_handler(ev)) + return; + if(ev->type==KeyPress) + handle_keypress(&(ev->xkey)); +#if 0 while(wglobal.input_mode!=INPUT_NORMAL && wglobal.input_mode!=INPUT_WAITRELEASE){ XFlush(wglobal.dpy); @@ -595,6 +626,7 @@ break; } } +#endif /*if(wglobal.focus_next==NULL) skip_focusenter();*/ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/grab.c ion-devel-20020130/wmcore/grab.c --- ion-devel-20020130-pristine/wmcore/grab.c Thu Jan 1 01:00:00 1970 +++ ion-devel-20020130/wmcore/grab.c Wed Feb 6 15:02:52 2002 @@ -0,0 +1,185 @@ +/* + * ion/grab.c + * + * Copyright (c) Lukas Schroeder 2002. + * See the included file LICENSE for details. + */ + +#include +#include +#include + +#include "common.h" +#include "global.h" +#include "event.h" +#include "thing.h" +#include "screen.h" +#include "cursor.h" +#include "grab.h" + +/* {{{ definitions */ + +typedef struct _grab_status{ + WRegion *holder; + GrabHandler *handler; + WWatch watch; + long events; + long flags; + + bool remove; /* TRUE, if entry marked for removal by do_grab_remove() */ + int suspended; +}GrabStatus; + +#define MAX_GRABS 10 +static GrabStatus grabs[MAX_GRABS]; +static GrabStatus *current_grab; +static int idx_grab=0; + +/*}}}*/ + + +static void grab_watch_handler(WWatch *w, WThing *t) +{ + grab_holder_remove((WRegion *)t); + /*warn("Thing destroyed while it's a grab->holder!");*/ +} + +static void do_grab_install(GrabStatus *grab) +{ + setup_watch(&grab->watch, (WThing*)grab->holder, grab_watch_handler); + do_grab_kb_ptr(ROOT_OF(grab->holder), grab->holder, ~grab->events); + current_grab=grab; + change_grab_cursor(CURSOR_WAITKEY); +} + +static void do_grab_remove() +{ + current_grab=NULL; + ungrab_kb_ptr(); + + while(idx_grab>0 && grabs[idx_grab-1].remove==TRUE){ + reset_watch(&grabs[idx_grab-1].watch); + idx_grab--; + } + + assert(idx_grab>=0); + + if(idx_grab>0 && !grabs[idx_grab-1].suspended){ + current_grab=&grabs[idx_grab-1]; + do_grab_install(current_grab); + } +} + +bool call_grab_handler(XEvent *ev) +{ + if(current_grab && current_grab->remove){ + do_grab_remove(); + return FALSE; + } + + if(current_grab!=NULL + && current_grab->holder!=NULL + && current_grab->handler!=NULL){ + + bool allow; + bool remove=FALSE; + GrabStatus *tmp_grab=current_grab; + + /* here we also catch luser's that tried to grab without + KeyPressMask|KeyReleaseMask */ + allow=!(current_grab->events&(KeyPressMask|KeyReleaseMask)); + if(!allow && ev->type==KeyRelease && current_grab->events&KeyReleaseMask) + allow=TRUE; + else if(!allow && ev->type==KeyPress && current_grab->events&KeyPressMask) + allow=TRUE; + + if(allow){ + remove=current_grab->handler(current_grab->holder, ev); + if(remove) + grab_remove(tmp_grab->handler); + } + return TRUE; + } + return FALSE; +} + +bool grab_held() +{ + return (idx_grab>0 && !grabs[idx_grab-1].suspended); +} + +void grab_establish(WRegion *thing, GrabHandler *func, long eventmask) +{ + if(idx_grabholder=thing; + current_grab->handler=func; + current_grab->events=~eventmask; + current_grab->remove=FALSE; + current_grab->suspended=0; + + do_grab_install(current_grab); + } +} + +void grab_remove(GrabHandler *func) +{ + int i; + for(i=idx_grab-1; i>=0; i--){ + if(grabs[i].handler==func){ + grabs[i].remove=TRUE; + break; + } + } + + if(grabs[idx_grab-1].remove){ + do_grab_remove(); + } +} + +void grab_holder_remove(WRegion *holder) +{ + int i; + for(i=idx_grab-1; i>=0; i--){ + if(grabs[i].holder==holder) + grabs[i].remove=TRUE; + } + + if(grabs[idx_grab-1].remove) + do_grab_remove(); +} + +WRegion *grab_get_holder() +{ + if (grab_held()) + return grabs[idx_grab-1].holder; + return NULL; +} + +WRegion *grab_get_my_holder(GrabHandler *func) +{ + int i; + for(i=idx_grab-1; i>=0; i--) + if(grabs[i].handler==func) + return grabs[i].holder; + return NULL; +} + +void grab_suspend() +{ + if(idx_grab>0){ + if(!grabs[idx_grab-1].suspended) + ungrab_kb_ptr(); + grabs[idx_grab-1].suspended++; + } +} + +void grab_resume() +{ + if(idx_grab>0 && grabs[idx_grab-1].suspended){ + current_grab=&grabs[idx_grab-1]; + current_grab->suspended--; + do_grab_install(current_grab); + } +} + diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/grab.h ion-devel-20020130/wmcore/grab.h --- ion-devel-20020130-pristine/wmcore/grab.h Thu Jan 1 01:00:00 1970 +++ ion-devel-20020130/wmcore/grab.h Wed Feb 6 11:42:41 2002 @@ -0,0 +1,37 @@ +/* + * ion/grab.h + * + * Copyright (c) Lukas Schroeder 2002. + * See the included file LICENSE for details. + */ + +#ifndef INCLUDED_GRAB_H +#define INCLUDED_GRAB_H + +#include "global.h" /* for InputHandler and InputHandlerContext */ +#include "common.h" +#include "thing.h" + +/* GrabHandler: + the default_keyboard_handler now simplifies access to subsequent keypresses + when you establish a grab using grab_establish(). + + if your GrabHandler returns TRUE, your grab will be removed, otherwise it's + kept active and you get more grabbed events passed to your handler. + */ +typedef bool GrabHandler(WRegion *thing, XEvent *ev); + +extern bool call_grab_handler(XEvent *ev); + +extern void grab_establish(WRegion *thing, GrabHandler *func, long eventmask); +extern void grab_remove(GrabHandler *func); +extern void grab_holder_remove(WRegion *holder); +extern WRegion *grab_get_holder(); +extern WRegion *grab_get_my_holder(GrabHandler *func); +extern void grab_suspend(); +extern void grab_resume(); +extern bool grab_held(); + + +#endif /* INCLUDED_GRAB_H */ + diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/key.c ion-devel-20020130/wmcore/key.c --- ion-devel-20020130-pristine/wmcore/key.c Sat Jan 26 21:18:58 2002 +++ ion-devel-20020130/wmcore/key.c Wed Feb 6 15:01:54 2002 @@ -15,6 +15,8 @@ #include "cursor.h" #include "objp.h" +static void waitrelease(WScreen *screen); + static void insstr(WWindow *wwin, XKeyEvent *ev) { @@ -38,6 +40,78 @@ window_insstr(wwin, buf, n); } +static WBinding *lookup_binding_from_event(WWindow *thing, XKeyEvent *ev) +{ + WBinding *binding; + WBindmap **bindptr; + + bindptr=&thing->bindmap; + assert(*bindptr!=NULL); + + binding=lookup_binding(*bindptr, ACT_KEYPRESS, ev->state, ev->keycode); + return binding; +} + +/* dispatch_binding + * the return values are those expected by GrabHandler's, i.e. + * you can just pass through the retval obtained from this function + */ +static bool dispatch_binding(WRegion *reg, WBinding *binding, XKeyEvent *ev) +{ + WScreen *scr; + + if(binding){ + /* Get the screen now for waitrel grab - the thing might + * have been destroyed when call_binding returns. + */ + scr=SCREEN_OF(reg); + call_binding(binding, (WThing *)reg); + if(ev->state!=0 && binding->waitrel){ + waitrelease(scr); + /* return FALSE here to prevent uninstalling the waitrelease handler + immediately after establishing it */ + return FALSE; + } + } + return TRUE; +} + +static bool waitrelease_handler(WRegion *thing, XEvent *ev) +{ + if(!unmod(ev->xkey.state, ev->xkey.keycode)) + return TRUE; + return FALSE; +} + +static void waitrelease(WScreen *screen) +{ + grab_establish((WThing *)screen, waitrelease_handler, FocusChangeMask|KeyPressMask); +} + +static bool submapgrab_handler(WRegion *reg, XEvent *ev) +{ + WBinding *binding; + + if(ev->type==KeyRelease) + return FALSE; + + binding=lookup_binding_from_event((WWindow*)reg, &ev->xkey); + + /* if it is just a modifier, then return + */ + if(binding==NULL) + if(ismod(ev->xkey.keycode)){ + return FALSE; + } + + return dispatch_binding(reg, binding, &ev->xkey); +} + +static void submapgrab(WRegion *reg) +{ + grab_establish(reg, submapgrab_handler, FocusChangeMask|KeyReleaseMask); +} + void handle_keypress(XKeyEvent *ev) { @@ -51,9 +125,9 @@ /* Lookup the object that should receive the event and * the action. */ - if(wglobal.input_mode!=INPUT_NORMAL) - reg=wglobal.grab_holder; - else + /* this function gets called with grab_holder==NULL + */ + reg=(WRegion*)FIND_WINDOW(ev->window); if(reg==NULL || !WTHING_IS(reg, WWindow)) @@ -66,16 +140,6 @@ toplvl=((WWindow*)reg)->flags&WWINDOW_CLIENTCONT; - binding=lookup_binding(*bindptr, ACT_KEYPRESS, ev->state, ev->keycode); - - /* If we are in submap grap mode, and the pressed key is a modifier, - * return without doing anything. - */ - if(binding==NULL && wglobal.input_mode==INPUT_SUBMAPGRAB){ - if(ismod(ev->keycode)) - return; - } - /* Restore object's bindmap pointer to the its toplevel bindmap * (if in submap mode). */ @@ -84,34 +148,22 @@ *bindptr=(*bindptr)->parent; } - /* Is it a submap? Then grab all input and return. + binding=lookup_binding_from_event((WWindow*)reg, ev); + + /* Is it a submap? Then handle it accordingly... */ if(binding!=NULL && binding->submap!=NULL){ *bindptr=binding->submap; - if(toplvl && wglobal.input_mode==INPUT_NORMAL){ - grab_kb_ptr(reg); - change_grab_cursor(CURSOR_WAITKEY); - wglobal.input_mode=INPUT_SUBMAPGRAB; - } + if(toplvl) + submapgrab(reg); return; } - if(wglobal.input_mode==INPUT_SUBMAPGRAB) - ungrab_kb_ptr(); - /* Call the handler. */ - if(binding!=NULL){ - /* We must get the screen now for waitrel grab - the thing - * might have been destroyed when call_binding returns. - */ - scr=SCREEN_OF(reg); - call_binding(binding, (WThing*)reg); - if(ev->state!=0 && binding->waitrel){ - grab_kb_ptr((WRegion*)scr); - wglobal.input_mode=INPUT_WAITRELEASE; - } - }else if(topmap){ + if(binding!=NULL) + dispatch_binding(reg, binding, ev); + else if(topmap){ insstr((WWindow*)reg, ev); } } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/pointer.c ion-devel-20020130/wmcore/pointer.c --- ion-devel-20020130-pristine/wmcore/pointer.c Sat Dec 29 20:04:39 2001 +++ ion-devel-20020130/wmcore/pointer.c Wed Feb 6 16:50:35 2002 @@ -159,7 +159,7 @@ /*{{{ handle_button_press/release/motion */ -void handle_button_press(XButtonEvent *ev) +bool handle_button_press(XButtonEvent *ev) { WBinding *pressbind=NULL; WRegion *reg=NULL; @@ -175,8 +175,9 @@ reg=(WRegion*)FIND_WINDOW_T(ev->window, WWindow); if(reg==NULL) - return; + return FALSE; + do_grab_kb_ptr(ev->root, reg, FocusChangeMask); bindmap=((WWindow*)reg)->bindmap; area=window_press((WWindow*)reg, ev, ®); @@ -208,6 +209,7 @@ p_area=area; call_button(pressbind, ev); + return TRUE; } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/pointer.h ion-devel-20020130/wmcore/pointer.h --- ion-devel-20020130-pristine/wmcore/pointer.h Sat Dec 29 20:04:39 2001 +++ ion-devel-20020130/wmcore/pointer.h Wed Feb 6 16:50:49 2002 @@ -22,7 +22,7 @@ WButtonHandler *end; }; -extern void handle_button_press(XButtonEvent *ev); +extern bool handle_button_press(XButtonEvent *ev); extern bool handle_button_release(XButtonEvent *ev); extern void handle_pointer_motion(XMotionEvent *ev); diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/resize.c ion-devel-20020130/wmcore/resize.c --- ion-devel-20020130-pristine/wmcore/resize.c Wed Jan 30 03:34:30 2002 +++ ion-devel-20020130/wmcore/resize.c Wed Feb 6 15:44:10 2002 @@ -15,7 +15,6 @@ #include "cursor.h" #include "objp.h" - #define XOR_RESIZE (!wglobal.opaque_resize) static bool resize_mode=FALSE; @@ -27,7 +26,7 @@ static WRectangle tmpgeom; static WRegion *tmpreg=NULL; static WDrawRubberbandFn *tmprubfn=NULL; - +static void (*resize_atexit)(); /*{{{ Dynfuns */ @@ -116,6 +115,10 @@ /*{{{ Resize */ +bool is_resizing() +{ + return resize_mode; +} bool may_resize(WRegion *reg) { @@ -161,14 +164,19 @@ if(XOR_RESIZE) res_draw_rubberband(scr); - if(wglobal.input_mode==INPUT_NORMAL) - grab_kb_ptr(reg); - change_grab_cursor(CURSOR_RESIZE); return TRUE; } +bool begin_resize_atexit(WRegion *reg, WDrawRubberbandFn *rubfn, void (*exitfn)()) +{ + if(begin_resize(reg, rubfn)){ + resize_atexit=exitfn; + return TRUE; + } + return FALSE; +} void delta_resize(WRegion *reg, int dx1, int dx2, int dy1, int dy2, WRectangle *rret) @@ -238,9 +246,12 @@ XUngrabServer(wglobal.dpy); } - ungrab_kb_ptr(); - XUnmapWindow(wglobal.dpy, scr->grdata.moveres_win); + + if(resize_atexit){ + resize_atexit(); + resize_atexit=NULL; + } } @@ -260,9 +271,12 @@ XUngrabServer(wglobal.dpy); } - ungrab_kb_ptr(); - XUnmapWindow(wglobal.dpy, scr->grdata.moveres_win); + + if(resize_atexit){ + resize_atexit(); + resize_atexit=NULL; + } } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-devel-20020130-pristine/wmcore/resize.h ion-devel-20020130/wmcore/resize.h --- ion-devel-20020130-pristine/wmcore/resize.h Sat Dec 29 20:04:39 2001 +++ ion-devel-20020130/wmcore/resize.h Wed Feb 6 10:10:37 2002 @@ -14,6 +14,7 @@ typedef void WDrawRubberbandFn(WScreen *scr, WRectangle geom); extern bool begin_resize(WRegion *reg, WDrawRubberbandFn *rubfn); +extern bool begin_resize_atexit(WRegion *reg, WDrawRubberbandFn *rubfn, void (*exitfn)()); /* dx1/dx2/dy1/dy2: left/right/top/bottom difference to previous values. * left/top negative, bottom/right positive increases size. */ @@ -23,6 +24,7 @@ extern void cancel_resize(WRegion *reg); extern void set_resize_timer(WRegion *reg, uint timeout); +extern bool is_resizing(); extern bool may_resize(WRegion *reg); DYNFUN void region_resize_hints(WRegion *reg, XSizeHints *hints_ret,