4 * Copyright (c) Lukas Schroeder 2002
5 * See the included file LICENSE for details.
13 #include "clientwin.h"
25 #include "selection.h"
36 static bool commandmode_keyboard_handler(WThing
*thing
, XEvent
*ev
);
40 /* {{{ Definitions and friends */
42 static bool commandmode_active
=FALSE
;
44 WBindmap commandmode_bindmap
;
48 /*{{{ auxiliary functions */
50 static WThing
*get_current_from_thing(WThing
*thing
)
54 return (WThing
*)find_current(scr
->current_workspace
);
60 /*{{{ init/deinit,enter/leave */
62 void commandmode_enter(WThing
*thing
)
67 if(commandmode_active
==TRUE
){
68 fprintf(stderr
, "%s() commandmode already active!\n", __FUNCTION__
);
72 if(wglobal
.input_mode
!=INPUT_NORMAL
){
73 fprintf(stderr
, "%s() can only enter commandmode from normal input mode!\n", __FUNCTION__
);
77 if(!WTHING_IS(thing
, WWindow
)){
79 wwin
=(WThing
*)find_current(scr
->current_workspace
);
83 commandmode_active
=TRUE
;
84 grab_establish(thing
, commandmode_keyboard_handler
, FocusChangeMask
);
86 wglobal
.input_mode
=INPUT_NORMAL
;
89 void commandmode_leave(WThing
*thing
)
91 if(commandmode_active
){
92 commandmode_active
=FALSE
;
93 grab_remove(commandmode_keyboard_handler
);
100 /*{{{ event handling */
102 static void commandmode_keypress_handler(WThing
*thing
, XKeyEvent
*ev
)
105 WBinding
*binding
=NULL
;
110 if(ev
->type
==KeyRelease
)
114 * when holding a grab ev->window will be the window holding the pointer
115 * (X's PointerRoot focus mode); this can either be a window
116 * handled by the window manager or a Window of an application, and "thing"
117 * will just be too old an information if e.g. the focus changed while
118 * holding the command-mode grab
119 * so, to get the right context for call_binding() we'll do a lookup to find
120 * the current WWindow...
123 thing
=get_current_from_thing(thing
);
124 if(!thing
|| !WTHING_IS(thing
, WWindow
))
127 bindptr
=&(((WWindow
*)thing
)->bindmap
);
128 toplvl
=WTHING_IS(thing
, WFrame
);
130 if(!thing
|| !WTHING_IS(thing
, WEdln
))
131 binding
=lookup_binding(&commandmode_bindmap
, ACT_KEYPRESS
, ev
->state
, ev
->keycode
);
133 binding
=lookup_binding(*bindptr
, ACT_KEYPRESS
, ev
->state
, ev
->keycode
);
136 if(ismod(ev
->keycode
))
140 if(bindptr
&& *bindptr
){
141 while((*bindptr
)->parent
!=NULL
){
143 *bindptr
=(*bindptr
)->parent
;
147 if(binding
!=NULL
&& binding
->submap
!=NULL
){
149 /* we dont allow submap grabs in commandmode; (yet?) */
150 *bindptr
=binding
->submap
;
151 if(toplvl
&& wglobal
.input_mode
==INPUT_NORMAL
){
153 change_grab_cursor(CURSOR_WAITKEY
);
154 wglobal
.input_mode
=INPUT_SUBMAPGRAB
;
161 /* Get the screen now for waitrel grab - the thing might
162 * have been destroyed when call_binding returns.
164 scr
=SCREEN_OF(thing
);
165 call_binding(binding
, thing
);
167 if(topmap
&& WTHING_IS(thing
, WEdln
))
168 adhoc_insstr((WEdln
*)thing
, ev
);
172 static Bool
commandmode_event_scanner(Display
*dpy
, XEvent
*ev
, char *args
)
177 return (ev
->xfocus
.mode
==NotifyUngrab
);
180 return (ev
->xcrossing
.mode
==NotifyUngrab
);
188 static bool commandmode_keyboard_handler(WThing
*thing
, XEvent
*ev
)
190 /* we get called with commandmode_active==TRUE, if there was
191 another GrabHandler active at commandmode_leave() time */
192 if(commandmode_active
==FALSE
)
195 if(ev
->type
==KeyPress
)
196 commandmode_keypress_handler(thing
, &ev
->xkey
);
198 if(!commandmode_active
){
199 /* prevent FocusIn, FocusOut, EnterNotify events at command-mode-leave time;
200 * not doing so would result in flipping the focus to the window containing
201 * the pointer (X's PointerRoot mode, when grab's are held).
204 XSync(wglobal
.dpy
, False
);
205 while(XCheckIfEvent(wglobal
.dpy
, &tmp
, commandmode_event_scanner
, NULL
));
207 /* enforce refocus on the "current thing"; this is necessary to get
208 * the focussing of WClientWin's right when the commandmode was used to
209 * "switch_tab" only and the clients received their FocusOut.
211 thing
=get_current_from_thing(thing
);
212 if(thing
&& WTHING_IS(thing
, WWindow
))
215 return !commandmode_active
;