4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
10 #ifndef CF_NO_LOCK_HACK
11 #define CF_HACK_IGNORE_EVIL_LOCKS
14 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
16 #include <X11/keysymdef.h>
30 static const uint modmasks
[N_MODS
]={
31 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
, Mod2Mask
, Mod3Mask
,
35 static XModifierKeymap
*modmap
=NULL
;
37 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
40 #define N_LOOKUPEVIL 2
42 static uint evillockmasks
[N_EVILLOCKS
]={
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
,
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
);
86 bool init_bindmap(WBindmap
*bindmap
)
89 bindmap
->bindings
=NULL
;
91 bindmap
->confdefmod
=0;
96 WBindmap
*create_bindmap()
98 SIMPLECREATESTRUCT_IMPL(WBindmap
, bindmap
, (p
));
102 void destroy_binding(WBinding
*binding
)
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
)
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
)
134 if(bindmap
==NULL
|| (b
->func
==NULL
&& b
->submap
==NULL
))
137 binding
=bindmap
->bindings
;
139 for(i
=0; i
<bindmap
->nbindings
; i
++){
140 switch(compare_bindings((void*)b
, (void*)(binding
+i
))){
144 destroy_binding(binding
+i
);
150 binding
=REALLOC_N(binding
, WBinding
, bindmap
->nbindings
,
151 bindmap
->nbindings
+1);
158 memmove(&(binding
[i
+1]), &(binding
[i
]),
159 sizeof(WBinding
)*(bindmap
->nbindings
-i
));
161 bindmap
->bindings
=binding
;
162 bindmap
->nbindings
++;
165 memcpy(&(binding
[i
]), b
, sizeof(WBinding
));
171 static void bind_simple(WBindmap
*bindmap
, int ftab
,
172 int state
, int key
, char *fn
)
176 binding
.func
=lookup_func(fn
, ftab
);
178 binding
.kcb
=XKeysymToKeycode(wglobal
.dpy
, key
);
179 binding
.act
=ACT_KEYPRESS
;
183 add_binding(bindmap
, &binding
);
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
210 XModifierKeymap
*nm
=XGetModifierMapping(wglobal
.dpy
);
213 XFreeModifiermap(modmap
);
222 void grab_bindings(WBindmap
*bindmap
, Window win
)
224 WBinding
*binding
=bindmap
->bindings
;
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
);
233 evil_grab_key(wglobal
.dpy
, binding
->kcb
, binding
->state
, win
, True
,
234 GrabModeAsync
, GrabModeAsync
);
238 if(binding
->act
!=ACT_BUTTONPRESS
&& binding
->act
!=ACT_BUTTONCLICK
&&
239 binding
->act
!=ACT_BUTTONDBLCLICK
&& binding
->act
!=ACT_BUTTONMOTION
)
242 if(binding
->state
==0)
245 #ifndef CF_HACK_IGNORE_EVIL_LOCKS
246 XGrabButton(wglobal
.dpy
, binding
->kcb
, binding
->state
, win
, True
,
247 GRAB_POINTER_MASK
, GrabModeAsync
, GrabModeAsync
,
250 evil_grab_button(wglobal
.dpy
, binding
->kcb
, binding
->state
, win
, True
,
251 GRAB_POINTER_MASK
, GrabModeAsync
, GrabModeAsync
,
262 static WBinding
*search_binding(WBindmap
*bindmap
, WBinding
*binding
)
264 if(bindmap
->bindings
==NULL
|| bindmap
->nbindings
==0)
267 return (WBinding
*)bsearch((void*)binding
, (void*)(bindmap
->bindings
),
268 bindmap
->nbindings
, sizeof(WBinding
),
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
;
285 binding
=search_binding(bindmap
, &tmp
);
288 tmp
.state
=AnyModifier
;
289 binding
=search_binding(bindmap
, &tmp
);
293 tmp
.kcb
=(act
==ACT_KEYPRESS
? AnyKey
: AnyButton
);
294 binding
=search_binding(bindmap
, &tmp
);
297 tmp
.state
=AnyModifier
;
298 binding
=search_binding(bindmap
, &tmp
);
307 void call_binding(WBinding
*binding
, WThing
*thing
)
309 if(binding
->func
==NULL
)
312 if(binding
->func
->callhnd
==NULL
)
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
)
329 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
330 state
&=~evilignoremask
;
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
];
342 bool ismod(int keycode
)
346 for(j
=0; j
<N_MODS
*modmap
->max_keypermod
; j
++){
347 if(modmap
->modifiermap
[j
]==keycode
)
355 #ifdef CF_HACK_IGNORE_EVIL_LOCKS
357 static void lookup_evil_locks()
359 uint keycodes
[N_LOOKUPEVIL
];
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
)
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
)
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)
392 for(j
=i
; j
<N_EVILLOCKS
; j
++){
393 if(evillockmasks
[j
]==0)
395 mods
|=evillockmasks
[j
];
396 XGrabKey(display
, keycode
, mods
,
397 grab_window
, owner_events
, pointer_mode
, keyboard_mode
);
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
,
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)
425 for(j
=i
; j
<N_EVILLOCKS
; j
++){
426 if(evillockmasks
[j
]==0)
428 mods
|=evillockmasks
[j
];
429 XGrabButton(display
, button
, mods
,
430 grab_window
, owner_events
, event_mask
, pointer_mode
,
431 keyboard_mode
, confine_to
, cursor
);
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 */