Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / binding.c
blobb57e253a50e02842fed5bc777f3edda8b31cf29b
1 /*
2 * ion/binding.c
4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
6 */
8 #include <string.h>
10 #ifndef CF_NO_LOCK_HACK
11 #define CF_HACK_IGNORE_EVIL_LOCKS
12 #endif
14 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
15 #define XK_MISCELLANY
16 #include <X11/keysymdef.h>
17 #endif
19 #include "common.h"
20 #include "event.h"
21 #include "binding.h"
22 #include "global.h"
23 #include "objp.h"
26 /* */
28 #define N_MODS 8
30 static const uint modmasks[N_MODS]={
31 ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask,
32 Mod4Mask, Mod5Mask
35 static XModifierKeymap *modmap=NULL;
37 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
39 #define N_EVILLOCKS 3
40 #define N_LOOKUPEVIL 2
42 static uint evillockmasks[N_EVILLOCKS]={
43 0, 0, LockMask
46 static const KeySym evillocks[N_LOOKUPEVIL]={
47 XK_Num_Lock, XK_Scroll_Lock
50 static uint evilignoremask=LockMask;
52 static void lookup_evil_locks();
54 static void evil_grab_key(Display *display, uint keycode, uint modifiers,
55 Window grab_window, bool owner_events,
56 int pointer_mode, int keyboard_mode);
58 static void evil_grab_button(Display *display, uint button, uint modifiers,
59 Window grab_window, bool owner_events,
60 uint event_mask, int pointer_mode,
61 int keyboard_mode, Window confine_to,
62 Cursor cursor);
64 #endif
67 #define CVAL(A, B, V) ( A->V < B->V ? -1 : (A->V > B->V ? 1 : 0))
69 static int compare_bindings(const void *a_, const void *b_)
71 const WBinding *a=(WBinding*)a_, *b=(WBinding*)b_;
72 int r=CVAL(a, b, act);
73 if(r==0){
74 r=CVAL(a, b, kcb);
75 if(r==0){
76 r=CVAL(a, b, state);
79 return r;
82 #undef CVAL
86 bool init_bindmap(WBindmap *bindmap)
88 bindmap->nbindings=0;
89 bindmap->bindings=NULL;
90 bindmap->parent=NULL;
91 bindmap->confdefmod=0;
92 return TRUE;
96 WBindmap *create_bindmap()
98 SIMPLECREATESTRUCT_IMPL(WBindmap, bindmap, (p));
102 void destroy_binding(WBinding *binding)
104 int i;
106 if(binding->submap!=NULL){
107 destroy_bindmap(binding->submap);
108 free(binding->submap);
111 for(i=1; i<binding->nargs; i++)
112 tok_free(binding->args+i);
116 void destroy_bindmap(WBindmap *bindmap)
118 int i;
119 WBinding *binding=bindmap->bindings;
121 for(i=0; i<bindmap->nbindings; i++, binding++)
122 destroy_binding(binding);
124 free(bindmap->bindings);
129 bool add_binding(WBindmap *bindmap, const WBinding *b)
131 WBinding *binding;
132 int i, j;
134 if(bindmap==NULL || (b->func==NULL && b->submap==NULL))
135 return FALSE;
137 binding=bindmap->bindings;
139 for(i=0; i<bindmap->nbindings; i++){
140 switch(compare_bindings((void*)b, (void*)(binding+i))){
141 case 1:
142 continue;
143 case 0:
144 destroy_binding(binding+i);
145 goto subst;
147 break;
150 binding=REALLOC_N(binding, WBinding, bindmap->nbindings,
151 bindmap->nbindings+1);
153 if(binding==NULL){
154 warn_err();
155 return FALSE;
158 memmove(&(binding[i+1]), &(binding[i]),
159 sizeof(WBinding)*(bindmap->nbindings-i));
161 bindmap->bindings=binding;
162 bindmap->nbindings++;
164 subst:
165 memcpy(&(binding[i]), b, sizeof(WBinding));
167 return TRUE;
171 static void bind_simple(WBindmap *bindmap, int ftab,
172 int state, int key, char *fn)
174 WBinding binding;
176 binding.func=lookup_func(fn, ftab);
177 binding.state=state;
178 binding.kcb=XKeysymToKeycode(wglobal.dpy, key);
179 binding.act=ACT_KEYPRESS;
180 binding.nargs=0;
181 binding.submap=NULL;
183 add_binding(bindmap, &binding);
187 void init_bindings()
189 modmap=XGetModifierMapping(wglobal.dpy);
191 assert(modmap!=NULL);
193 init_bindmap(&(wglobal.main_bindmap));
194 init_bindmap(&(wglobal.tab_bindmap));
195 init_bindmap(&(wglobal.input_bindmap));
196 init_bindmap(&(wglobal.moveres_bindmap));
198 /* There must be a way to get out of resize mode */
199 bind_simple(&(wglobal.moveres_bindmap), FUNTAB_MOVERES,
200 0, XK_Escape, "cancel_resize");
202 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
203 lookup_evil_locks();
204 #endif
208 void update_modmap()
210 XModifierKeymap *nm=XGetModifierMapping(wglobal.dpy);
212 if(nm!=NULL){
213 XFreeModifiermap(modmap);
214 modmap=nm;
219 /* */
222 void grab_bindings(WBindmap *bindmap, Window win)
224 WBinding *binding=bindmap->bindings;
225 int i;
227 for(i=0; i<bindmap->nbindings; i++, binding++){
228 if(binding->act==ACT_KEYPRESS){
229 #ifndef CF_HACK_IGNORE_EVIL_LOCKS
230 XGrabKey(wglobal.dpy, binding->kcb, binding->state, win, True,
231 GrabModeAsync, GrabModeAsync);
232 #else
233 evil_grab_key(wglobal.dpy, binding->kcb, binding->state, win, True,
234 GrabModeAsync, GrabModeAsync);
235 #endif
238 if(binding->act!=ACT_BUTTONPRESS && binding->act!=ACT_BUTTONCLICK &&
239 binding->act!=ACT_BUTTONDBLCLICK && binding->act!=ACT_BUTTONMOTION)
240 continue;
242 if(binding->state==0)
243 continue;
245 #ifndef CF_HACK_IGNORE_EVIL_LOCKS
246 XGrabButton(wglobal.dpy, binding->kcb, binding->state, win, True,
247 GRAB_POINTER_MASK, GrabModeAsync, GrabModeAsync,
248 None, None);
249 #else
250 evil_grab_button(wglobal.dpy, binding->kcb, binding->state, win, True,
251 GRAB_POINTER_MASK, GrabModeAsync, GrabModeAsync,
252 None, None);
253 #endif
259 /* */
262 static WBinding *search_binding(WBindmap *bindmap, WBinding *binding)
264 if(bindmap->bindings==NULL || bindmap->nbindings==0)
265 return NULL;
267 return (WBinding*)bsearch((void*)binding, (void*)(bindmap->bindings),
268 bindmap->nbindings, sizeof(WBinding),
269 compare_bindings);
273 WBinding *lookup_binding(WBindmap *bindmap, int act, uint state, uint kcb)
275 WBinding *binding, tmp;
277 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
278 state&=~evilignoremask;
279 #endif
281 tmp.act=act;
282 tmp.kcb=kcb;
283 tmp.state=state;
285 binding=search_binding(bindmap, &tmp);
287 if(binding==NULL){
288 tmp.state=AnyModifier;
289 binding=search_binding(bindmap, &tmp);
291 if(binding==NULL){
292 tmp.state=state;
293 tmp.kcb=(act==ACT_KEYPRESS ? AnyKey : AnyButton);
294 binding=search_binding(bindmap, &tmp);
296 if(binding==NULL){
297 tmp.state=AnyModifier;
298 binding=search_binding(bindmap, &tmp);
303 return binding;
307 void call_binding(WBinding *binding, WThing *thing)
309 if(binding->func==NULL)
310 return;
312 if(binding->func->callhnd==NULL)
313 return;
315 binding->func->callhnd(thing, binding->func,
316 binding->nargs, binding->args);
321 * A dirty hack to deal with (==ignore) evil locking modifier keys.
325 int unmod(int state, int keycode)
327 int j;
329 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
330 state&=~evilignoremask;
331 #endif
333 for(j=0; j<N_MODS*modmap->max_keypermod; j++){
334 if(modmap->modifiermap[j]==keycode)
335 return state&~modmasks[j/modmap->max_keypermod];
338 return state;
342 bool ismod(int keycode)
344 int j;
346 for(j=0; j<N_MODS*modmap->max_keypermod; j++){
347 if(modmap->modifiermap[j]==keycode)
348 return TRUE;
351 return FALSE;
355 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
357 static void lookup_evil_locks()
359 uint keycodes[N_LOOKUPEVIL];
360 int i, j;
362 for(i=0; i<N_LOOKUPEVIL; i++)
363 keycodes[i]=XKeysymToKeycode(wglobal.dpy, evillocks[i]);
365 for(j=0; j<N_MODS*modmap->max_keypermod; j++){
366 for(i=0; i<N_LOOKUPEVIL; i++){
367 if(keycodes[i]==None)
368 continue;
369 if(modmap->modifiermap[j]==keycodes[i]){
370 evillockmasks[i]=modmasks[j/modmap->max_keypermod];
371 evilignoremask|=evillockmasks[i];
378 static void evil_grab_key(Display *display, uint keycode, uint modifiers,
379 Window grab_window, bool owner_events,
380 int pointer_mode, int keyboard_mode)
382 uint mods;
383 int i, j;
385 XGrabKey(display, keycode, modifiers, grab_window, owner_events,
386 pointer_mode, keyboard_mode);
388 for(i=0; i<N_EVILLOCKS; i++){
389 if(evillockmasks[i]==0)
390 continue;
391 mods=modifiers;
392 for(j=i; j<N_EVILLOCKS; j++){
393 if(evillockmasks[j]==0)
394 continue;
395 mods|=evillockmasks[j];
396 XGrabKey(display, keycode, mods,
397 grab_window, owner_events, pointer_mode, keyboard_mode);
398 if(i==j)
399 continue;
400 XGrabKey(display, keycode,
401 modifiers|evillockmasks[i]|evillockmasks[j],
402 grab_window, owner_events, pointer_mode, keyboard_mode);
408 static void evil_grab_button(Display *display, uint button, uint modifiers,
409 Window grab_window, bool owner_events,
410 uint event_mask, int pointer_mode,
411 int keyboard_mode, Window confine_to,
412 Cursor cursor)
414 uint mods;
415 int i, j;
417 XGrabButton(display, button, modifiers,
418 grab_window, owner_events, event_mask, pointer_mode,
419 keyboard_mode, confine_to, cursor);
421 for(i=0; i<N_EVILLOCKS; i++){
422 if(evillockmasks[i]==0)
423 continue;
424 mods=modifiers;
425 for(j=i; j<N_EVILLOCKS; j++){
426 if(evillockmasks[j]==0)
427 continue;
428 mods|=evillockmasks[j];
429 XGrabButton(display, button, mods,
430 grab_window, owner_events, event_mask, pointer_mode,
431 keyboard_mode, confine_to, cursor);
432 if(i==j)
433 continue;
434 XGrabButton(display, button,
435 modifiers|evillockmasks[i]|evillockmasks[j],
436 grab_window, owner_events, event_mask, pointer_mode,
437 keyboard_mode, confine_to, cursor);
442 #endif /* CF_HACK_IGNORE_EVIL_LOCKS */