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