diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/Makefile ion-20020120-test2/src/Makefile --- ion-20020120-pristine/src/Makefile Fri Nov 9 19:14:08 2001 +++ ion-20020120-test2/src/Makefile Sun Jan 27 00:57:38 2002 @@ -20,7 +20,8 @@ frameid.o function.o key.o listing.o main.o obj.o pointer.o \ property.o query.o readconfig.o resize.o screen.o selection.o \ signal.o sizehint.o split.o thing.o wedln.o window.o winprops.o \ - workspace.o xic.o input.o wmessage.o splitmisc.o modules.o + workspace.o xic.o input.o wmessage.o splitmisc.o modules.o \ + command.o shortcut.o grab.o TARGETS=ion diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/client.c ion-20020120-test2/src/client.c --- ion-20020120-pristine/src/client.c Sun Mar 4 13:14:00 2001 +++ ion-20020120-test2/src/client.c Sun Jan 27 00:57:38 2002 @@ -379,7 +379,7 @@ } -static bool goto_window(WWindow *wwin) +bool goto_window(WWindow *wwin) { WWorkspace *ws; diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/client.h ion-20020120-test2/src/client.h --- ion-20020120-pristine/src/client.h Fri Mar 2 05:18:00 2001 +++ ion-20020120-test2/src/client.h Sun Jan 27 00:57:38 2002 @@ -31,6 +31,7 @@ int flags; char *label; + int shortcut; /* valid values: '0'-'9','A'-'z' */ int label_inst; WClient *label_next, *label_prev; @@ -64,6 +65,7 @@ extern void client_toggle_tagged(WClient *client); extern void clear_tags(); +extern bool goto_window(WWindow *window); extern void goto_client(WClient *client); extern void goto_previous(); extern bool goto_client_name(const char *cname); diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/clientwin.c ion-20020120-test2/src/clientwin.c --- ion-20020120-pristine/src/clientwin.c Mon Nov 12 08:39:27 2001 +++ ion-20020120-test2/src/clientwin.c Sun Jan 27 01:00:21 2002 @@ -529,7 +529,7 @@ void focus_clientwin(WClientWin *cwin) { - SET_FOCUS(cwin->win); + set_input_focus(cwin->win); if(cwin->flags&CWIN_P_WM_TAKE_FOCUS) send_clientmsg(cwin->win, wglobal.atom_wm_take_focus); diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/command.c ion-20020120-test2/src/command.c --- ion-20020120-pristine/src/command.c Thu Jan 1 01:00:00 1970 +++ ion-20020120-test2/src/command.c Sun Jan 27 21:27:04 2002 @@ -0,0 +1,218 @@ +/* + * ion/command.c + * + * Copyright (c) Lukas Schroeder 2002 + * See the included file LICENSE for details. + */ + +#include +#include + +#include "common.h" +#include "event.h" +#include "clientwin.h" +#include "screen.h" +#include "frame.h" +#include "property.h" +#include "pointer.h" +#include "key.h" +#include "focus.h" +#include "cursor.h" +#include "signal.h" +#include "global.h" +#include "draw.h" +#include "input.h" +#include "selection.h" +#include "thing.h" +#include "sizehint.h" +#include "readfds.h" +#include "wedln.h" +#include "window.h" +#include "objp.h" +#include "grab.h" + +/*{{{ Prototypes */ + +static bool commandmode_keyboard_handler(WThing *thing, XEvent *ev); + +/*}}}*/ + +/* {{{ Definitions and friends */ + +static bool commandmode_active=FALSE; + +WBindmap commandmode_bindmap; + +/*}}}*/ + +/*{{{ auxiliary functions */ + +static WThing *get_current_from_thing(WThing *thing) +{ + WScreen *scr; + scr=SCREEN_OF(thing); + return (WThing*)find_current(scr->current_workspace); +} + +/*}}}*/ + + +/*{{{ init/deinit,enter/leave */ + +void commandmode_enter(WThing *thing) +{ + WScreen *scr; + WThing *wwin; + + if(commandmode_active==TRUE){ + fprintf(stderr, "%s() commandmode already active!\n", __FUNCTION__); + return; + } + + if(wglobal.input_mode!=INPUT_NORMAL){ + fprintf(stderr, "%s() can only enter commandmode from normal input mode!\n", __FUNCTION__); + return; + } + + if(!WTHING_IS(thing, WWindow)){ + scr=SCREEN_OF(thing); + wwin=(WThing*)find_current(scr->current_workspace); + thing=wwin; + } + + commandmode_active=TRUE; + grab_establish(thing, commandmode_keyboard_handler, FocusChangeMask); + + wglobal.input_mode=INPUT_NORMAL; +} + +void commandmode_leave(WThing *thing) +{ + if(commandmode_active){ + commandmode_active=FALSE; + grab_remove(commandmode_keyboard_handler); + } +} + +/*}}}*/ + + +/*{{{ event handling */ + +static void commandmode_keypress_handler(WThing *thing, XKeyEvent *ev) +{ + WScreen *scr; + WBinding *binding=NULL; + WBindmap **bindptr; + bool topmap=TRUE; + bool toplvl=FALSE; + + if(ev->type==KeyRelease) + return; + + /* + * when holding a grab ev->window will be the window holding the pointer + * (X's PointerRoot focus mode); this can either be a window + * handled by the window manager or a Window of an application, and "thing" + * will just be too old an information if e.g. the focus changed while + * holding the command-mode grab + * so, to get the right context for call_binding() we'll do a lookup to find + * the current WWindow... + */ + + thing=get_current_from_thing(thing); + if(!thing || !WTHING_IS(thing, WWindow)) + return; + + bindptr=&(((WWindow*)thing)->bindmap); + toplvl=WTHING_IS(thing, WFrame); + + if(!thing || !WTHING_IS(thing, WEdln)) + binding=lookup_binding(&commandmode_bindmap, ACT_KEYPRESS, ev->state, ev->keycode); + else + binding=lookup_binding(*bindptr, ACT_KEYPRESS, ev->state, ev->keycode); + + if(!binding){ + if(ismod(ev->keycode)) + return; + } + + if(bindptr && *bindptr){ + while((*bindptr)->parent!=NULL){ + topmap=FALSE; + *bindptr=(*bindptr)->parent; + } + } + + if(binding!=NULL && binding->submap!=NULL){ +#if 0 +/* we dont allow submap grabs in commandmode; (yet?) */ + *bindptr=binding->submap; + if(toplvl && wglobal.input_mode==INPUT_NORMAL){ + grab_kb_ptr(thing); + change_grab_cursor(CURSOR_WAITKEY); + wglobal.input_mode=INPUT_SUBMAPGRAB; + } +#endif + return; + } + + if(binding!=NULL){ + /* Get the screen now for waitrel grab - the thing might + * have been destroyed when call_binding returns. + */ + scr=SCREEN_OF(thing); + call_binding(binding, thing); + }else{ + if(topmap && WTHING_IS(thing, WEdln)) + adhoc_insstr((WEdln*)thing, ev); + } +} + +static Bool commandmode_event_scanner(Display *dpy, XEvent *ev, char *args) +{ + switch(ev->type){ + case FocusIn: + case FocusOut: + return (ev->xfocus.mode==NotifyUngrab); + break; + case EnterNotify: + return (ev->xcrossing.mode==NotifyUngrab); + break; + default: + break; + } + return False; +} + +static bool commandmode_keyboard_handler(WThing *thing, XEvent *ev) +{ + /* we get called with commandmode_active==TRUE, if there was + another GrabHandler active at commandmode_leave() time */ + if(commandmode_active==FALSE) + return TRUE; + + if(ev->type==KeyPress) + commandmode_keypress_handler(thing, &ev->xkey); + + if(!commandmode_active){ + /* prevent FocusIn, FocusOut, EnterNotify events at command-mode-leave time; + * not doing so would result in flipping the focus to the window containing + * the pointer (X's PointerRoot mode, when grab's are held). + */ + XEvent tmp; + XSync(wglobal.dpy, False); + while(XCheckIfEvent(wglobal.dpy, &tmp, commandmode_event_scanner, NULL)); + + /* enforce refocus on the "current thing"; this is necessary to get + * the focussing of WClientWin's right when the commandmode was used to + * "switch_tab" only and the clients received their FocusOut. + */ + thing=get_current_from_thing(thing); + if(thing && WTHING_IS(thing, WWindow)) + set_focus(thing); + } + return !commandmode_active; +} + +/*}}}*/ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/draw.c ion-20020120-test2/src/draw.c --- ion-20020120-pristine/src/draw.c Wed Oct 17 13:17:03 2001 +++ ion-20020120-test2/src/draw.c Sun Jan 27 00:57:38 2002 @@ -161,6 +161,27 @@ draw_frame_bar(frame, !grdata->bar_inside_frame); } +static char *get_shortcut_label(char shortcut) +{ + static char buffer[10]; + + snprintf(buffer, 10, "%c", shortcut); + return buffer; +} + +static void draw_shortcut_tab(const WFrame *frame, DrawInfo *dinfo, WGRData *grdata) +{ + if(frame->shortcut!=0){ + if(IS_ACTIVE_FRAME(frame)) + COLORS=&(grdata->act_tab_shortcut_colors); + else + COLORS=&(grdata->tab_shortcut_colors); + dinfo->geom.w=FRAME_SHORTCUT_W; + draw_textbox(dinfo, get_shortcut_label(frame->shortcut), CF_TAB_TEXT_ALIGN, TRUE); + X+=FRAME_SHORTCUT_W+grdata->spacing; + dinfo->geom.w=frame->tab_w; + } +} void draw_frame_bar(const WFrame *frame, bool complete) { @@ -194,14 +215,26 @@ } } + /* draw shortcut tab in top-left corner? */ + if(!grdata->shortcut_corner) + draw_shortcut_tab(frame, dinfo, grdata); + client=FIRST_THING(frame, WClient); if(client==NULL){ + if(frame->shortcut) + W=bg.w-FRAME_SHORTCUT_W; + if(IS_ACTIVE_FRAME(frame)) COLORS=&(grdata->act_tab_sel_colors); else COLORS=&(grdata->tab_sel_colors); draw_textbox(dinfo, "", CF_TAB_TEXT_ALIGN, TRUE); + + /* draw shortcut tab in top-right corner? */ + X+=frame->tab_w+grdata->spacing; + if(grdata->shortcut_corner) + draw_shortcut_tab(frame, dinfo, grdata); return; } @@ -210,8 +243,12 @@ for(; client!=NULL; client=next){ next=NEXT_THING(client, WClient); - if(next==NULL) - W=bg.w-(X-bg.x); + if(next==NULL){ + int d=0; + if(frame->shortcut && grdata->shortcut_corner) + d=FRAME_SHORTCUT_W+grdata->spacing; + W=bg.w-(X-bg.x)-d; + } if(IS_ACTIVE_FRAME(frame)){ if(client==frame->current_client) @@ -249,6 +286,11 @@ X+=frame->tab_w+grdata->spacing; } + + /* draw shortcut tab in top-right corner? */ + X-=grdata->spacing; + if(grdata->shortcut_corner) + draw_shortcut_tab(frame, dinfo, grdata); } @@ -591,6 +633,7 @@ grdata->bar_inside_frame=FALSE; grdata->spacing=1; + grdata->shortcut_corner=0; grdata->font=NULL; grdata->tab_font=NULL; } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/event.c ion-20020120-test2/src/event.c --- ion-20020120-pristine/src/event.c Sun Jan 27 01:14:16 2002 +++ ion-20020120-test2/src/event.c Sun Jan 27 21:28:42 2002 @@ -27,6 +27,8 @@ #include "thing.h" #include "sizehint.h" #include "readfds.h" +#include "grab.h" +#include "objp.h" /*{{{ Prototypes */ @@ -42,15 +44,26 @@ static void handle_focus_out(const XFocusChangeEvent *ev); static void handle_property(const XPropertyEvent *ev); static void handle_colormap_notify(const XColormapEvent *ev); -static void pointer_handler(XEvent *ev); -static void keyboard_handler(XEvent *ev); - /*}}}*/ +InputHandler default_input_handler={ + default_keyboard_handler, + default_pointer_handler +}; -/*{{{ Event-reading, mainloop */ +void set_input_handler(InputHandler *handler, InputHandlerContext *context) +{ + context->oldhandler=wglobal.input_handler; + wglobal.input_handler=handler; +} +void restore_input_handler(InputHandlerContext *context) +{ + wglobal.input_handler=context->oldhandler; +} + +/*{{{ Event-reading, mainloop */ void get_event(XEvent *ev) { @@ -112,8 +125,11 @@ /* fprintf(stderr, "[%#lx] %s\n", ev->xany.window, #X);*/ -#define SKIP_FOCUSENTER_EVENTS(EV) while(XCheckMaskEvent(wglobal.dpy, \ - EnterWindowMask|FocusChangeMask, EV)) /*nothing */; +void kill_focusenter_events() +{ + XEvent ev; + while(XCheckMaskEvent(wglobal.dpy, EnterWindowMask|FocusChangeMask, &ev)) /*nothing */; +} /* * Workspace switching and focusing with CF_WARP. @@ -124,7 +140,7 @@ * window that is really wanted to have the focus. */ -static void skip_focusenter() +void skip_focusenter() { XEvent ev; XEvent tmp; @@ -194,18 +210,19 @@ handle_expose(&(ev->xexpose)); break; CASE_EVENT(KeyPress) - if(wglobal.input_mode!=INPUT_WAITRELEASE) - keyboard_handler(ev); + assert(wglobal.input_handler!=NULL); + assert(wglobal.input_handler->keyboard!=NULL); + wglobal.input_handler->keyboard(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(); - } + assert(wglobal.input_handler!=NULL); + assert(wglobal.input_handler->keyboard!=NULL); + wglobal.input_handler->keyboard(ev); break; CASE_EVENT(ButtonPress) - pointer_handler(ev); + assert(wglobal.input_handler!=NULL); + if(wglobal.input_handler->pointer!=NULL) + wglobal.input_handler->pointer(ev); break; CASE_EVENT(ColormapNotify) handle_colormap_notify(&(ev->xcolormap)); @@ -238,7 +255,7 @@ XSync(wglobal.dpy, False); if(wglobal.focus_next!=NULL){ - SKIP_FOCUSENTER_EVENTS(&ev); + kill_focusenter_events(); do_set_focus(wglobal.focus_next); wglobal.focus_next=NULL; } @@ -504,13 +521,29 @@ /*{{{ Enter window, focus */ - static void handle_enter_window(XEvent *ev) { XEnterWindowEvent *eev=&(ev->xcrossing); WThing *thing=NULL; bool inf=TRUE; +#if 0 + /* when enabling this check you can't change focus by moving the pointer when in command mode */ + if(grab_held()) + return; +#endif + + if(eev->mode==NotifyGrab) + return; + + /* + * mode==NotifyUngrab events are generated en masse on XUngrab*() + * and are generally ignored; unfortunately a refocussing + * ButtonRelease usually happens in this mode too. argh. + */ + if(eev->mode==NotifyUngrab) + return; + do{ if(eev->detail!=NotifyInferior)/* && !eev->send_event)*/ inf=FALSE; @@ -524,6 +557,7 @@ return; } + thing=FIND_WINDOW_T(eev->window, WThing); if(thing==NULL) @@ -574,7 +608,7 @@ WScreen *scr; Colormap cmap=None; - if(ev->mode==NotifyGrab) + if(ev->mode==NotifyGrab || ev->detail > NotifyNonlinearVirtual) return; thing=FIND_WINDOW_T(ev->window, WThing); @@ -592,6 +626,12 @@ return; } + if(ev->mode==NotifyUngrab){ + if(WTHING_IS(thing, WFrame) && !IS_ACTIVE_FRAME(thing)) + restore_focus(scr); + return; + } + /* Handle colormap */ if(WTHING_IS(thing, WClientWin)) cmap=((WClientWin*)thing)->cmap; @@ -617,10 +657,10 @@ activate(wwin); } - static void handle_focus_out(const XFocusChangeEvent *ev) { WWindow *wwin; + WScreen *scr; /*if(ev->window==SCREEN->root.win){ SCREEN->active=FALSE; @@ -630,11 +670,18 @@ return; }*/ + if(ev->mode==NotifyGrab || ev->mode==NotifyUngrab || ev->detail>NotifyNonlinearVirtual) + return; + wwin=FIND_WINDOW_T(ev->window, WWindow); if(wwin==NULL) return; + scr=SCREEN_OF(wwin); + if(ev->window==scr->root.win) + return; + if(wwin->xic!=NULL) XUnsetICFocus(wwin->xic); } @@ -646,12 +693,12 @@ /*{{{ Pointer, keyboard */ -void do_grab_kb_ptr(Window win, WThing *thing) +void do_grab_kb_ptr(Window win, WThing *thing, long eventmask) { wglobal.grab_holder=thing; - wglobal.input_mode=INPUT_GRAB; + wglobal.input_mode=INPUT_NORMAL; - 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); @@ -663,7 +710,7 @@ void grab_kb_ptr(WThing *thing) { - do_grab_kb_ptr(ROOT_OF(thing), thing); + do_grab_kb_ptr(ROOT_OF(thing), thing, FocusChangeMask); } @@ -681,21 +728,49 @@ KeyPressMask|KeyReleaseMask| \ EnterWindowMask|FocusChangeMask) -static void pointer_handler(XEvent *ev) +void default_pointer_handler(XEvent *ev) { + XEvent tmp; + Window win_pressed; WThing *t; + bool mouse_grab_held=FALSE; + bool refocus=FALSE; + + if(grab_held()) + return; - if(!handle_button_press(&(ev->xbutton))) + win_pressed=ev->xbutton.window; + 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_EVENT(ButtonRelease) - if(handle_button_release(&(ev->xbutton))) + 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); + if(XCheckTypedWindowEvent(wglobal.dpy, win_pressed, EnterNotify, &tmp)){ + t=(WThing*)FIND_WINDOW_T(win_pressed, WWindow); + if(t){ + set_focus(t); + } + } + } break; CASE_EVENT(MotionNotify) handle_pointer_motion(&(ev->xmotion)); @@ -708,27 +783,15 @@ } -static void keyboard_handler(XEvent *ev) +void default_keyboard_handler(XEvent *ev) { - handle_keypress(&(ev->xkey)); - - while(wglobal.input_mode!=INPUT_NORMAL && - wglobal.input_mode!=INPUT_WAITRELEASE){ - XFlush(wglobal.dpy); - get_event_mask(ev, GRAB_EV_MASK); + if(call_grab_handler(ev)) + return; - switch(ev->type){ - CASE_EVENT(Expose) - handle_expose(&(ev->xexpose)); - break; - CASE_EVENT(KeyPress) + if(ev->type==KeyPress) handle_keypress(&(ev->xkey)); - break; - } - } skip_focusenter(); } - /*}}}*/ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/event.h ion-20020120-test2/src/event.h --- ion-20020120-pristine/src/event.h Fri Mar 2 06:24:25 2001 +++ ion-20020120-test2/src/event.h Sun Jan 27 00:57:38 2002 @@ -8,6 +8,7 @@ #ifndef INCLUDED_EVENT_H #define INCLUDED_EVENT_H +#include "global.h" /* for InputHandler and InputHandlerContext */ #include "common.h" #include "thing.h" @@ -39,8 +40,17 @@ extern void get_event_mask(XEvent *ev, long mask); extern void handle_event(XEvent *ev); -extern void do_grab_kb_ptr(Window win, WThing *thing); +extern void do_grab_kb_ptr(Window win, WThing *thing, long eventmask); extern void grab_kb_ptr(WThing *thing); extern void ungrab_kb_ptr(); + +extern void default_pointer_handler(XEvent *ev); +extern void default_keyboard_handler(XEvent *ev); + +extern void kill_focusenter_events(); +extern void skip_focusenter(); + +extern void set_input_handler(InputHandler *handler, InputHandlerContext *context); +extern void restore_input_handler(InputHandlerContext *context); #endif /* INCLUDED_EVENT_H */ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/focus.c ion-20020120-test2/src/focus.c --- ion-20020120-pristine/src/focus.c Tue Jan 16 21:04:18 2001 +++ ion-20020120-test2/src/focus.c Sun Jan 27 01:01:11 2002 @@ -73,6 +73,10 @@ /*{{{ set_focus, warp */ +void set_input_focus(Window win) +{ + XSetInputFocus(wglobal.dpy, win, RevertToParent, CurrentTime); +} void do_set_focus(WThing *thing) { diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/focus.h ion-20020120-test2/src/focus.h --- ion-20020120-pristine/src/focus.h Tue Jan 16 21:04:18 2001 +++ ion-20020120-test2/src/focus.h Sun Jan 27 00:57:38 2002 @@ -8,13 +8,13 @@ #ifndef INCLUDED_FOCUS_H #define INCLUDED_FOCUS_H +#include "global.h" #include "common.h" #include "thing.h" #include "window.h" -#define SET_FOCUS(WIN) \ - XSetInputFocus(wglobal.dpy, WIN, RevertToParent, CurrentTime); - +extern void skip_focusenter(); +extern void set_input_focus(Window win); extern void do_set_focus(WThing *thing); extern void set_focus(WThing *thing); extern void warp(WWindow *thing); diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/frame.c ion-20020120-test2/src/frame.c --- ion-20020120-pristine/src/frame.c Mon Oct 1 16:39:12 2001 +++ ion-20020120-test2/src/frame.c Sun Jan 27 01:18:05 2002 @@ -25,6 +25,7 @@ #include "input.h" #include "query.h" #include "splitmisc.h" +#include "shortcut.h" #define FRAME_MIN_H(SCR) \ @@ -117,6 +118,8 @@ void deinit_frame(WFrame *frame) { deinit_window((WWindow*)frame); + if (shortcut_is_valid(frame->shortcut)) + shortcut_remove(frame->shortcut); free_frame_id(frame->frame_id); } @@ -463,6 +466,9 @@ int textw; WClient *client; + if(shortcut_is_valid(frame->shortcut)) + bar_w-=FRAME_SHORTCUT_W+scr->grdata.spacing; + if(frame->client_count==0){ frame->tab_w=bar_w; draw_frame_bar(frame, TRUE); @@ -598,7 +604,6 @@ /*}}}*/ - /*{{{ Misc */ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/frame.h ion-20020120-test2/src/frame.h --- ion-20020120-pristine/src/frame.h Mon Jan 15 22:29:11 2001 +++ ion-20020120-test2/src/frame.h Sun Jan 27 00:57:38 2002 @@ -24,6 +24,8 @@ #define WFRAME_NO_BAR 0x0008 #define WFRAME_MAX_BOTH (WFRAME_MAX_VERT|WFRAME_MAX_HORIZ) +#define FRAME_SHORTCUT_W 23 + #define FRAME_GEOM(FRAME) ((FRAME)->win.geom) #define FRAME_X(FRAME) ((FRAME)->win.geom.x) #define FRAME_Y(FRAME) ((FRAME)->win.geom.y) @@ -43,6 +45,7 @@ int tab_w; int client_count; + int shortcut; /* valid values: '0'-'9','A'-'z' */ WClient *current_client; WInput *current_input; }; @@ -80,6 +83,8 @@ extern void frame_bar_geom(const WFrame *frame, WRectangle *geom); extern void frame_client_geom(const WFrame *frame, WRectangle *geom); + +extern void frame_set_shortcut(WFrame *frame, int shortcut); /* */ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/function.c ion-20020120-test2/src/function.c --- ion-20020120-pristine/src/function.c Sat Jan 19 20:39:18 2002 +++ ion-20020120-test2/src/function.c Sun Jan 27 01:01:24 2002 @@ -22,6 +22,7 @@ #include "modules.h" #include "complete.h" #include "key.h" +#include "shortcut.h" /*{{{ Definitions and stuff */ @@ -30,6 +31,9 @@ extern WDragHandler p_tabdrag_handler; extern WDragHandler p_resize_handler; +extern void commandmode_enter(); +extern void commandmode_leave(); + /*}}}*/ @@ -48,7 +52,6 @@ /*{{{ Function table */ - static WFunction funcs[]={ /* frame */ FN(l, generic, WFrame, "switch_nth", frame_switch_nth), @@ -59,6 +62,8 @@ FN_VOID(generic, WFrame, "destroy_frame", destroy_frame), FN_VOID(generic, WFrame, "closedestroy", closedestroy), FN_VOID(generic, WFrame, "attach_tagged", frame_attach_tagged), + FN_VOID(generic, WFrame, "set_shortcut", set_shortcut), + FN_VOID(generic, WFrame, "goto_shortcut", goto_shortcut), FN(ss, generic, WFrame, "query_runfile", query_runfile), FN(ss, generic, WFrame, "query_runwith", query_runwith), @@ -112,6 +117,9 @@ FN(s, generic, WThing, "command_sequence", command_sequence), + FN_VOID(generic, WFrame, "enter_command_mode", commandmode_enter), + FN_VOID(generic, WFrame, "leave_command_mode", commandmode_leave), + {NULL, NULL, NULL, NULL, NULL} }; @@ -261,6 +269,7 @@ { typedef void Func(WThing*); thing=find_parent(thing, func->objdescr); + if(thing!=NULL) ((Func*)func->fn)(thing); } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/global.h ion-20020120-test2/src/global.h --- ion-20020120-pristine/src/global.h Thu Nov 8 22:40:55 2001 +++ ion-20020120-test2/src/global.h Sun Jan 27 00:57:38 2002 @@ -31,6 +31,17 @@ OPMODE_DEINIT }; +typedef void xInputEventHandler(XEvent *ev); +typedef struct input_event_handler{ + xInputEventHandler *keyboard; + xInputEventHandler *pointer; +}InputHandler; + +typedef struct input_handler_context{ + struct input_handler_context *prev, *next; + InputHandler *oldhandler; +}InputHandlerContext; + INTRSTRUCT(WGlobal) DECLSTRUCT(WGlobal){ @@ -73,13 +84,17 @@ Time dblclick_delay; bool opaque_resize; + WThing *shortcuts[127]; /* WFrame's and WClients apply for a shortcut */ WClient *client_list; WBindmap main_bindmap, tab_bindmap, moveres_bindmap, input_bindmap; + + InputHandler *input_handler; }; extern WGlobal wglobal; extern void deinit(); + #endif /* INCLUDED_GLOBAL_H */ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/grab.c ion-20020120-test2/src/grab.c --- ion-20020120-pristine/src/grab.c Thu Jan 1 01:00:00 1970 +++ ion-20020120-test2/src/grab.c Sun Jan 27 21:32:58 2002 @@ -0,0 +1,158 @@ +/* + * 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{ + WThing *holder; + GrabHandler *handler; + 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 do_grab_install(GrabStatus *grab) +{ + 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) + 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&KeyRelease)) + allow=TRUE; + else if(!allow && ev->type==KeyPress && current_grab->events&KeyPress) + allow=TRUE; + else + allow=FALSE; + + 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(WThing *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(); + } +} + +WThing *grab_get_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-20020120-pristine/src/grab.h ion-20020120-test2/src/grab.h --- ion-20020120-pristine/src/grab.h Thu Jan 1 01:00:00 1970 +++ ion-20020120-test2/src/grab.h Sun Jan 27 21:38:21 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(WThing *thing, XEvent *ev); + +extern void set_input_handler(InputHandler *handler, InputHandlerContext *context); +extern void restore_input_handler(InputHandlerContext *context); +extern bool call_grab_handler(XEvent *ev); + +extern void grab_establish(WThing *thing, GrabHandler *func, long eventmask); +extern void grab_remove(GrabHandler *func); +extern WThing *grab_get_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-20020120-pristine/src/grdata.h ion-20020120-test2/src/grdata.h --- ion-20020120-pristine/src/grdata.h Tue Jan 2 15:19:47 2001 +++ ion-20020120-test2/src/grdata.h Sun Jan 27 00:57:38 2002 @@ -35,10 +35,12 @@ /* configurable data */ bool bar_inside_frame; int spacing; + int shortcut_corner; /* 0=left; 1=right; */ WColorGroup act_frame_colors, frame_colors; WColorGroup act_tab_colors, tab_colors; WColorGroup act_tab_sel_colors, tab_sel_colors; + WColorGroup act_tab_shortcut_colors, tab_shortcut_colors; WColorGroup input_colors; Pixel bgcolor, selection_bgcolor, selection_fgcolor; diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/key.c ion-20020120-test2/src/key.c --- ion-20020120-pristine/src/key.c Fri Nov 9 19:12:27 2001 +++ ion-20020120-test2/src/key.c Sun Jan 27 12:03:59 2002 @@ -8,16 +8,21 @@ #include #include "common.h" -#include "key.h" #include "binding.h" #include "global.h" -#include "wedln.h" +#include "key.h" #include "event.h" #include "cursor.h" -#include "objp.h" +#include "client.h" +#include "grab.h" + +/*{{{ prototypes */ +static void waitrelease(WScreen *screen); -static void adhoc_insstr(WEdln *wedln, XKeyEvent *ev) +/*}}}*/ + +void adhoc_insstr(WEdln *wedln, XKeyEvent *ev) { static XComposeStatus cs={NULL, 0}; char buf[16]={0,}; @@ -39,8 +44,62 @@ edln_insstr(&(wedln->edln), buf); } +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(WThing *thing, 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(thing); + call_binding(binding, thing); + 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 void send_key(XEvent *ev, WClientWin *cwin) +{ + Window win=cwin->win; + ev->xkey.window=win; + ev->xkey.subwindow=None; + XSendEvent(wglobal.dpy, win, False, KeyPressMask, ev); +} -static bool quote_next_flag=FALSE; + +static bool quote_next_handler(WThing *thing, XEvent *xev) +{ + XKeyEvent *ev=&xev->xkey; + if(ev->type==KeyRelease) + return TRUE; + if(ismod(ev->keycode)) + return FALSE; + assert(WTHING_IS(thing, WClientWin)); + send_key(xev, (WClientWin*)thing); + return TRUE; /* remove the grab */ +} void quote_next(WClient *client) { @@ -49,21 +108,42 @@ if(cwin==NULL) return; - quote_next_flag=TRUE; - grab_kb_ptr((WThing*)cwin); - change_grab_cursor(CURSOR_WAITKEY); - wglobal.input_mode=INPUT_SUBMAPGRAB; + grab_establish((WThing*)cwin, quote_next_handler, FocusChangeMask); } +static bool waitrelease_handler(WThing *thing, XEvent *ev) +{ + if(!unmod(ev->xkey.state, ev->xkey.keycode)) + return TRUE; + return FALSE; +} -static void send_key(XEvent *ev, WClientWin *cwin) +static void waitrelease(WScreen *screen) { - Window win=cwin->win; - ev->xkey.window=win; - ev->xkey.subwindow=None; - XSendEvent(wglobal.dpy, win, False, KeyPressMask, ev); + grab_establish((WThing *)screen, waitrelease_handler, FocusChangeMask); } +static bool submapgrab_handler(WThing *thing, XEvent *ev) +{ + WBinding *binding; + + if(ev->type==KeyRelease) + return TRUE; + + binding=lookup_binding_from_event((WWindow*)thing, &ev->xkey); + + if(binding==NULL) + if(ismod(ev->xkey.keycode)){ + return FALSE; + } + + return dispatch_binding(thing, binding, &ev->xkey); +} + +static void submapgrab(WThing *thing) +{ + grab_establish(thing, submapgrab_handler, FocusChangeMask); +} void handle_keypress(XKeyEvent *ev) { @@ -74,67 +154,37 @@ bool topmap=TRUE; bool toplvl=FALSE; - if(wglobal.input_mode!=INPUT_NORMAL){ - thing=wglobal.grab_holder; - if(quote_next_flag){ - if(ismod(ev->keycode)) - return; - assert(WTHING_IS(thing, WClientWin)); - quote_next_flag=FALSE; - ungrab_kb_ptr(); - send_key((XEvent*)ev, (WClientWin*)thing); - return; - } - }else{ - thing=FIND_WINDOW(ev->window); - } - - quote_next_flag=FALSE; + /* this function gets called with grab_holder==NULL */ + thing=FIND_WINDOW(ev->window); if(thing==NULL || !WTHING_IS(thing, WWindow)) return; - bindptr=&(((WWindow*)thing)->bindmap); toplvl=WTHING_IS(thing, WFrame); - - binding=lookup_binding(*bindptr, ACT_KEYPRESS, ev->state, ev->keycode); - - if(binding==NULL && wglobal.input_mode==INPUT_SUBMAPGRAB){ - if(ismod(ev->keycode)) - return; - } + bindptr=&(((WWindow*)thing)->bindmap); while((*bindptr)->parent!=NULL){ topmap=FALSE; *bindptr=(*bindptr)->parent; } + binding=lookup_binding_from_event((WWindow*)thing, ev); + + if(binding!=NULL && binding->submap!=NULL){ *bindptr=binding->submap; - if(toplvl && wglobal.input_mode==INPUT_NORMAL){ - grab_kb_ptr(thing); - change_grab_cursor(CURSOR_WAITKEY); - wglobal.input_mode=INPUT_SUBMAPGRAB; + if(toplvl){ + submapgrab(thing); } return; } - if(wglobal.input_mode==INPUT_SUBMAPGRAB) - ungrab_kb_ptr(); - - if(binding!=NULL){ - /* Get the screen now for waitrel grab - the thing might - * have been destroyed when call_binding returns. - */ - scr=SCREEN_OF(thing); - call_binding(binding, thing); - if(ev->state!=0 && binding->waitrel){ - grab_kb_ptr((WThing*)scr); - wglobal.input_mode=INPUT_WAITRELEASE; - } - }else{ + if(binding!=NULL) + dispatch_binding(thing, binding, ev); + else{ if(topmap && WTHING_IS(thing, WEdln)) adhoc_insstr((WEdln*)thing, ev); } } + diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/key.h ion-20020120-test2/src/key.h --- ion-20020120-pristine/src/key.h Thu Nov 1 09:44:16 2001 +++ ion-20020120-test2/src/key.h Sun Jan 27 00:57:38 2002 @@ -11,9 +11,12 @@ #include #include "function.h" #include "client.h" +#include "wedln.h" extern void handle_keypress(XKeyEvent *ev); extern void quote_next(WClient *cwin); +void adhoc_insstr(WEdln *wedln, XKeyEvent *ev); + #endif /* INCLUDED_KEY_H */ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/main.c ion-20020120-test2/src/main.c --- ion-20020120-pristine/src/main.c Sat Jan 19 20:05:39 2002 +++ ion-20020120-test2/src/main.c Sun Jan 27 01:20:37 2002 @@ -78,6 +78,7 @@ static bool initialize(const char *display, const char *cfgfile, bool onescreen); +extern InputHandler default_input_handler; int main(int argc, char*argv[]) { @@ -104,6 +105,8 @@ wglobal.previous_protect=0; wglobal.client_id=NULL; wglobal.state_file=NULL; + wglobal.input_handler=&default_input_handler; + memset(wglobal.shortcuts, 0, sizeof(wglobal.shortcuts)); /* The rest don't need to be initialized here */ @@ -150,6 +153,7 @@ return EXIT_SUCCESS; } +extern void debug_dump_thing(WThing *thing); static bool load_initial_workspaces() { WScreen *scr; diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/pointer.c ion-20020120-test2/src/pointer.c --- ion-20020120-pristine/src/pointer.c Fri Mar 2 06:24:25 2001 +++ ion-20020120-test2/src/pointer.c Sun Jan 27 01:29:27 2002 @@ -18,6 +18,7 @@ #include "split.h" #include "resize.h" #include "focus.h" +#include "grab.h" /*{{{ Variables */ @@ -264,15 +265,16 @@ return FALSE; } - do_grab_kb_ptr(ev->root, thing); + do_grab_kb_ptr(ev->root, thing, FocusChangeMask); if(p_clickcnt==1 && time_in_treshold(ev->time) && p_button==button && p_state==state && thing==p_dbltmp && p_bindmap==bindmap){ pressbind=lookup_binding(bindmap, ACT_BUTTONDBLCLICK, state, button); } - if(pressbind==NULL) + if(pressbind==NULL){ pressbind=lookup_binding(bindmap, ACT_BUTTONPRESS, state, button); + } end: p_dbltmp=thing; diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/query.c ion-20020120-test2/src/query.c --- ion-20020120-pristine/src/query.c Sun Jan 20 00:16:08 2002 +++ ion-20020120-test2/src/query.c Sun Jan 27 01:01:48 2002 @@ -34,7 +34,7 @@ { frame->current_input=input; if(IS_ACTIVE_FRAME(frame)) - focus_window((WWindow*)input); + set_focus((WThing*)input); } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/readconfig.c ion-20020120-test2/src/readconfig.c --- ion-20020120-pristine/src/readconfig.c Mon Mar 5 17:16:06 2001 +++ ion-20020120-test2/src/readconfig.c Sun Jan 27 00:57:38 2002 @@ -312,6 +312,14 @@ return TRUE; } +extern WBindmap commandmode_bindmap; +static bool opt_commandmode_bindings(Tokenizer *tokz, int n, Token *toks) +{ + tmp_bindmap=&commandmode_bindmap; + tmp_funtab=FUNTAB_MAIN; + return TRUE; +} + static bool end_bindings(Tokenizer *tokz, int n, Token *toks) { @@ -450,6 +458,8 @@ CGHAND(act_tab_colors) CGHAND(act_tab_sel_colors) CGHAND(input_colors) +CGHAND(act_tab_shortcut_colors) +CGHAND(tab_shortcut_colors) #undef CGHAND @@ -522,6 +532,28 @@ return TRUE; } +static bool opt_screen_shortcut_corner(Tokenizer *tokz, int n, Token *toks) +{ + WScreen *scr; + char *data=TOK_STRING_VAL(&(toks[1])); + int val=0; + + if(!strncasecmp(data, "right", 5)) + val=1; + else if(!strncasecmp(data, "left", 4)) + val=0; + else{ + tokz_warn(tokz, toks[1].line, + "Invalid value `%s' given to shortcut_corner.", data); + } + + FOR_ALL_SELECTED_SCREENS(scr){ + scr->grdata.shortcut_corner=val; + } + + return TRUE; +} + /* Begin/end */ @@ -729,8 +761,10 @@ {"act_tab_colors", "ssss", opt_screen_act_tab_colors, NULL}, {"act_tab_sel_colors", "ssss", opt_screen_act_tab_sel_colors, NULL}, {"act_frame_colors", "ssss", opt_screen_act_frame_colors, NULL}, + {"act_tab_shortcut_colors", "ssss", opt_screen_act_tab_shortcut_colors, NULL}, {"tab_colors", "ssss", opt_screen_tab_colors, NULL}, {"tab_sel_colors", "ssss", opt_screen_tab_sel_colors, NULL}, + {"tab_shortcut_colors", "ssss", opt_screen_tab_shortcut_colors, NULL}, {"frame_colors", "ssss", opt_screen_frame_colors, NULL}, {"input_colors", "ssss", opt_screen_input_colors, NULL}, {"background_color", "s", opt_screen_background_color, NULL}, @@ -738,6 +772,7 @@ {"spacing", "l", opt_screen_spacing, NULL}, {"bar_inside_frame", "b", opt_screen_bar_inside_frame, NULL}, + {"shortcut_corner", "s", opt_screen_shortcut_corner, NULL}, {"#end", NULL, end_screen, NULL}, {"#cancel", NULL, end_screen, NULL}, @@ -788,6 +823,7 @@ {"tab_bindings", NULL, opt_tab_bindings, bindings_opts}, {"input_bindings", NULL, opt_input_bindings, bindings_opts}, {"moveres_bindings", NULL, opt_moveres_bindings, bindings_opts}, + {"commandmode_bindings", NULL, opt_commandmode_bindings, bindings_opts}, /* window props */ {"winprop" , "s", begin_winprop, winprop_opts}, diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/resize.c ion-20020120-test2/src/resize.c --- ion-20020120-pristine/src/resize.c Fri Mar 2 03:03:53 2001 +++ ion-20020120-test2/src/resize.c Sun Jan 27 21:47:36 2002 @@ -14,10 +14,12 @@ #include "cursor.h" #include "sizehint.h" #include "draw.h" +#include "grab.h" #define XOR_RESIZE (!wglobal.opaque_resize) +static bool resize_handler(WThing *thing, XEvent *ev); static bool resize_mode=FALSE; static int tmpsize; @@ -28,13 +30,14 @@ static void tmr_end_resize(WTimer *unused) { + WThing *holder; if(!resize_mode){ return; } - assert(wglobal.grab_holder!=NULL && - WTHING_IS(wglobal.grab_holder, WWindow)); + holder=grab_get_holder(resize_handler); + assert(holder && WTHING_IS(holder, WWindow)); - end_resize((WWindow*)wglobal.grab_holder); + end_resize((WWindow*)holder); } static WTimer resize_timer=INIT_TIMER(tmr_end_resize); @@ -198,8 +201,10 @@ { WScreen *scr=SCREEN_OF(wwin); + if(!resize_mode) + return; + resize_mode=FALSE; - wwin->bindmap=&(wglobal.main_bindmap); reset_timer(&resize_timer); @@ -208,7 +213,6 @@ resize_tmp(&rtmp); XUngrabServer(wglobal.dpy); } - ungrab_kb_ptr(); XUnmapWindow(wglobal.dpy, scr->grdata.moveres_win); } @@ -217,8 +221,10 @@ { WScreen *scr=SCREEN_OF(wwin); + if(!resize_mode) + return; + resize_mode=FALSE; - wwin->bindmap=&(wglobal.main_bindmap); reset_timer(&resize_timer); @@ -226,7 +232,6 @@ res_draw_rubberband(scr, wwin->geom); XUngrabServer(wglobal.dpy); } - ungrab_kb_ptr(); XUnmapWindow(wglobal.dpy, scr->grdata.moveres_win); } @@ -236,15 +241,45 @@ /*{{{ Keyboard resize */ +static bool resize_handler(WThing *thing, XEvent *xev) +{ + XKeyEvent *ev=&xev->xkey; + WScreen *scr; + WBinding *binding=NULL; + WBindmap **bindptr; + + if(!resize_mode){ + return TRUE; + } + + if(ev->type==KeyRelease) + return FALSE; + + assert(thing && WTHING_IS(thing, WWindow)); + binding=lookup_binding(&wglobal.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, thing); + } + + return !resize_mode; +} static void begin_keyresize(WWindow *wwin, int dir) { - begin_resize(wwin, dir, ANY); + if(resize_mode) + return; - if(wglobal.input_mode==INPUT_NORMAL) - grab_kb_ptr((WThing*)wwin); + begin_resize(wwin, dir, ANY); - wwin->bindmap=&(wglobal.moveres_bindmap); + grab_establish((WThing*)wwin, resize_handler, FocusChangeMask); change_grab_cursor(CURSOR_RESIZE); } diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/shortcut.c ion-20020120-test2/src/shortcut.c --- ion-20020120-pristine/src/shortcut.c Thu Jan 1 01:00:00 1970 +++ ion-20020120-test2/src/shortcut.c Sun Jan 27 01:08:58 2002 @@ -0,0 +1,136 @@ +/* + * ion/shortcut.c + * + * Copyright (c) Lukas Schroeder 2002 + * See the included file LICENSE for details. + */ + +#include + +#include "common.h" +#include "binding.h" +#include "global.h" +#include "key.h" +#include "event.h" +#include "cursor.h" +#include "client.h" +#include "shortcut.h" +#include "grab.h" + +bool shortcut_is_valid(int cut) +{ + return ((cut>='0' && cut<='9') || (cut>='A' && cut<='z')); +} + +void shortcut_remove(int cut) +{ + WThing *thing; + + if(!shortcut_is_valid(cut)) + return; + + thing=wglobal.shortcuts[cut]; + if(!thing) + return; + + if(WTHING_IS(thing, WFrame)){ + WFrame *frame=(WFrame*)thing; + frame->shortcut=0; + } + + wglobal.shortcuts[cut]=NULL; +} + +static void shortcut_remove_from_frame(WFrame *frame) +{ + shortcut_remove(frame->shortcut); + assert(frame->shortcut==0); + frame_recalc_bar(frame); +} + +void shortcut_set(WThing *thing, int cut) +{ + bool valid=shortcut_is_valid(cut); + + if(valid){ + WThing *oldthing=wglobal.shortcuts[cut]; + if(oldthing && WTHING_IS(thing, WFrame)) + shortcut_remove_from_frame((WFrame*)oldthing); + } + + if(WTHING_IS(thing, WFrame)) + shortcut_remove_from_frame((WFrame*)thing); + + if(!valid) + return; + + shortcut_remove(cut); + + wglobal.shortcuts[cut]=thing; + if(WTHING_IS(thing, WFrame)){ + WFrame *frame=(WFrame*)thing; + frame->shortcut=cut; + frame_recalc_bar(frame); + } +} + +static char *decode_keysym(XKeyEvent *ev) +{ + static char buffer[10]; + int len; + + len = XLookupString(ev, buffer, 10, NULL, NULL); + if(!len || !shortcut_is_valid((int)buffer[0])) + buffer[0]=0; + buffer[1]=0; + return buffer; +} + +static bool setshortcut_handler(WThing *thing, XEvent *ev) +{ + KeySym sym; + char *sc; + + if(ismod(ev->xkey.keycode)) + return FALSE; + + sc=decode_keysym(&ev->xkey); + shortcut_set(thing, (int)sc[0]); + return TRUE; +} + +static bool gotoshortcut_handler(WThing *thing, XEvent *ev) +{ + WThing *target; + char *sc; + + if(ismod(ev->xkey.keycode)) + return FALSE; + + sc=decode_keysym(&ev->xkey); + if(sc[0] && shortcut_is_valid((int)sc[0])){ + + target=wglobal.shortcuts[(int)sc[0]]; + if(!target) + return TRUE; + + if(WTHING_IS(target, WFrame)){ + goto_window((WWindow*)target); + }else if(WTHING_IS(target, WClient)) + goto_client((WClient*)target); + /* else: "Ooops. target is not a WFrame" */ + } + skip_focusenter(); + return TRUE; +} + +void set_shortcut(WFrame *frame) +{ + grab_establish((WThing*)frame, setshortcut_handler, FocusChangeMask); +} + +void goto_shortcut(WFrame *frame) +{ + grab_establish((WThing*)frame, gotoshortcut_handler, FocusChangeMask); +} + diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/shortcut.h ion-20020120-test2/src/shortcut.h --- ion-20020120-pristine/src/shortcut.h Thu Jan 1 01:00:00 1970 +++ ion-20020120-test2/src/shortcut.h Sun Jan 27 00:57:38 2002 @@ -0,0 +1,25 @@ +/* + * ion/shortcut.h + * + * Copyright (c) Lukas Schroeder 2002 + * See the included file LICENSE for details. + */ + +#ifndef INCLUDED_SHORTCUT_H +#define INCLUDED_SHORTCUT_H + +#include +#include "function.h" +#include "client.h" +#include "wedln.h" + + +extern bool shortcut_is_valid(int cut); +extern void shortcut_remove(int cut); +extern void shortcut_set(WThing *thing, int cut); + +extern void set_shortcut(WFrame *frame); +extern void goto_shortcut(WFrame *frame); + + +#endif /* INCLUDED_SHORTCUT_H */ diff -ubNr --exclude-from=/home/azzit/diffrc/ion.conf ion-20020120-pristine/src/window.c ion-20020120-test2/src/window.c --- ion-20020120-pristine/src/window.c Sat Mar 3 18:19:38 2001 +++ ion-20020120-test2/src/window.c Sun Jan 27 01:02:05 2002 @@ -177,7 +177,7 @@ void focus_window(WWindow *wwin) { - SET_FOCUS(wwin->win); + set_input_focus(wwin->win); }