Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / command.c
blob5a412593a3d86690d2134344ae22d7ff9c5e72d0
1 /*
2 * ion/command.c
4 * Copyright (c) Lukas Schroeder 2002
5 * See the included file LICENSE for details.
6 */
8 #include <stdlib.h>
9 #include <unistd.h>
11 #include "common.h"
12 #include "event.h"
13 #include "clientwin.h"
14 #include "screen.h"
15 #include "frame.h"
16 #include "property.h"
17 #include "pointer.h"
18 #include "key.h"
19 #include "focus.h"
20 #include "cursor.h"
21 #include "signal.h"
22 #include "global.h"
23 #include "draw.h"
24 #include "input.h"
25 #include "selection.h"
26 #include "thing.h"
27 #include "sizehint.h"
28 #include "readfds.h"
29 #include "wedln.h"
30 #include "window.h"
31 #include "objp.h"
32 #include "grab.h"
34 /*{{{ Prototypes */
36 static bool commandmode_keyboard_handler(WThing *thing, XEvent *ev);
38 /*}}}*/
40 /* {{{ Definitions and friends */
42 static bool commandmode_active=FALSE;
44 WBindmap commandmode_bindmap;
46 /*}}}*/
48 /*{{{ auxiliary functions */
50 static WThing *get_current_from_thing(WThing *thing)
52 WScreen *scr;
53 scr=SCREEN_OF(thing);
54 return (WThing*)find_current(scr->current_workspace);
57 /*}}}*/
60 /*{{{ init/deinit,enter/leave */
62 void commandmode_enter(WThing *thing)
64 WScreen *scr;
65 WThing *wwin;
67 if(commandmode_active==TRUE){
68 fprintf(stderr, "%s() commandmode already active!\n", __FUNCTION__);
69 return;
72 if(wglobal.input_mode!=INPUT_NORMAL){
73 fprintf(stderr, "%s() can only enter commandmode from normal input mode!\n", __FUNCTION__);
74 return;
77 if(!WTHING_IS(thing, WWindow)){
78 scr=SCREEN_OF(thing);
79 wwin=(WThing*)find_current(scr->current_workspace);
80 thing=wwin;
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);
97 /*}}}*/
100 /*{{{ event handling */
102 static void commandmode_keypress_handler(WThing *thing, XKeyEvent *ev)
104 WScreen *scr;
105 WBinding *binding=NULL;
106 WBindmap **bindptr;
107 bool topmap=TRUE;
108 bool toplvl=FALSE;
110 if(ev->type==KeyRelease)
111 return;
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))
125 return;
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);
132 else
133 binding=lookup_binding(*bindptr, ACT_KEYPRESS, ev->state, ev->keycode);
135 if(!binding){
136 if(ismod(ev->keycode))
137 return;
140 if(bindptr && *bindptr){
141 while((*bindptr)->parent!=NULL){
142 topmap=FALSE;
143 *bindptr=(*bindptr)->parent;
147 if(binding!=NULL && binding->submap!=NULL){
148 #if 0
149 /* we dont allow submap grabs in commandmode; (yet?) */
150 *bindptr=binding->submap;
151 if(toplvl && wglobal.input_mode==INPUT_NORMAL){
152 grab_kb_ptr(thing);
153 change_grab_cursor(CURSOR_WAITKEY);
154 wglobal.input_mode=INPUT_SUBMAPGRAB;
156 #endif
157 return;
160 if(binding!=NULL){
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);
166 }else{
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)
174 switch(ev->type){
175 case FocusIn:
176 case FocusOut:
177 return (ev->xfocus.mode==NotifyUngrab);
178 break;
179 case EnterNotify:
180 return (ev->xcrossing.mode==NotifyUngrab);
181 break;
182 default:
183 break;
185 return False;
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)
193 return TRUE;
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).
203 XEvent tmp;
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))
213 set_focus(thing);
215 return !commandmode_active;
218 /*}}}*/