bind C-g for the rset key
[dana/openbox.git] / plugins / keyboard / keyboard.c
1 #include "../../kernel/focus.h"
2 #include "../../kernel/dispatch.h"
3 #include "../../kernel/openbox.h"
4 #include "../../kernel/grab.h"
5 #include "../../kernel/action.h"
6 #include "tree.h"
7 #include "keyboard.h"
8 #include "keysrc.h"
9 #include <glib.h>
10
11 void plugin_setup_config()
12 {
13 }
14
15 KeyBindingTree *firstnode;
16
17 static KeyBindingTree *curpos;
18 static guint reset_key, reset_state;
19 static gboolean grabbed;
20
21 static void grab_keys(gboolean grab)
22 {
23     if (!grab) {
24         ungrab_all_keys();
25     } else {
26         KeyBindingTree *p = firstnode;
27         while (p) {
28             grab_key(p->key, p->state, GrabModeSync);
29             p = p->next_sibling;
30         }
31     }
32 }
33
34 static void reset_chains()
35 {
36     /* XXX kill timer */
37     curpos = NULL;
38     if (grabbed) {
39         grabbed = FALSE;
40         grab_keyboard(FALSE);
41     }
42 }
43
44 gboolean kbind(GList *keylist, Action *action)
45 {
46     KeyBindingTree *tree, *t;
47     gboolean conflict;
48
49     g_assert(keylist != NULL);
50     g_assert(action != NULL);
51
52     if (!(tree = tree_build(keylist)))
53         return FALSE;
54     if ((t = tree_find(tree, &conflict)) != NULL) {
55         /* already bound to something */
56         g_warning("keychain is already bound");
57         tree_destroy(tree);
58         return FALSE;
59     }
60     if (conflict) {
61         g_warning("conflict with binding");
62         tree_destroy(tree);
63         return FALSE;
64     }
65
66     /* grab the server here to make sure no key presses go missed */
67     grab_server(TRUE);
68     grab_keys(FALSE);
69
70     /* set the action */
71     t = tree;
72     while (t->first_child) t = t->first_child;
73     t->action = action;
74     /* assimilate this built tree into the main tree. assimilation
75        destroys/uses the tree */
76     tree_assimilate(tree);
77
78     grab_keys(TRUE); 
79     grab_server(FALSE);
80
81     return TRUE;
82 }
83
84 static void press(ObEvent *e, void *foo)
85 {
86     if (e->data.x.e->xkey.keycode == reset_key &&
87         e->data.x.e->xkey.state == reset_state) {
88         reset_chains();
89     } else {
90         KeyBindingTree *p;
91         if (curpos == NULL)
92             p = firstnode;
93         else
94             p = curpos->first_child;
95         while (p) {
96             if (p->key == e->data.x.e->xkey.keycode &&
97                 p->state == e->data.x.e->xkey.state) {
98                 if (p->first_child != NULL) { /* part of a chain */
99                     /* XXX TIMER */
100                     if (!grabbed) {
101                         grab_keyboard(TRUE);
102                         grabbed = TRUE;
103                     }
104                     curpos = p;
105                 } else {
106                     if (p->action->func != NULL) {
107                         p->action->data.any.c = focus_client;
108
109                         g_assert(!(p->action->func == action_move ||
110                                    p->action->func == action_resize));
111
112                         p->action->func(&p->action->data);
113                     }
114
115                     reset_chains();
116                 }
117                 break;
118             }
119             p = p->next_sibling;
120         }
121     }
122     XAllowEvents(ob_display, AsyncKeyboard, e->data.x.e->xkey.time);
123 }
124
125 void plugin_startup()
126 {
127     dispatch_register(Event_X_KeyPress, (EventHandler)press, NULL);
128
129     translate_key("C-g", &reset_state, &reset_key);
130
131     keysrc_parse();
132 }
133
134 void plugin_shutdown()
135 {
136     dispatch_register(0, (EventHandler)press, NULL);
137
138     grab_keys(FALSE);
139     tree_destroy(firstnode);
140     firstnode = NULL;
141     grab_keys(TRUE);
142 }
143