]> Dogcows Code - chaz/openbox/blob - plugins/keyboard/keyboard.c
keyboard bindings are functional
[chaz/openbox] / plugins / keyboard / keyboard.c
1 #include "../../kernel/focus.h"
2 #include "../../kernel/dispatch.h"
3 #include "../../kernel/openbox.h"
4 #include "../../kernel/action.h"
5 #include "tree.h"
6 #include "keyboard.h"
7 #include "keyaction.h"
8 #include <glib.h>
9
10 KeyBindingTree *firstnode;
11
12 static KeyBindingTree *curpos;
13 static guint reset_key, reset_state;
14 static gboolean grabbed;
15
16 static void grab_keys(gboolean grab)
17 {
18 if (!grab) {
19 XUngrabKey(ob_display, AnyKey, AnyModifier, ob_root);
20 } else {
21 KeyBindingTree *p = firstnode;
22 while (p) {
23 XGrabKey(ob_display, p->key, p->state, ob_root, FALSE,
24 GrabModeAsync, GrabModeSync);
25 p = p->next_sibling;
26 }
27 }
28 }
29
30 static void reset_chains()
31 {
32 /* XXX kill timer */
33 curpos = NULL;
34 if (grabbed) {
35 grabbed = FALSE;
36 XUngrabKeyboard(ob_display, CurrentTime);
37 }
38 }
39
40 static void clearall()
41 {
42 grab_keys(FALSE);
43 tree_destroy(firstnode);
44 firstnode = NULL;
45 grab_keys(TRUE);
46 }
47
48 static gboolean bind(GList *keylist, KeyAction *action)
49 {
50 KeyBindingTree *tree, *t;
51 gboolean conflict;
52
53 if (!(tree = tree_build(keylist))) {
54 g_warning("invalid binding");
55 return FALSE;
56 }
57
58 t = tree_find(tree, &conflict);
59 if (conflict) {
60 g_warning("conflict with binding");
61 tree_destroy(tree);
62 return FALSE;
63 }
64 if (t != NULL) {
65 /* already bound to something */
66 g_warning("keychain is already bound");
67 tree_destroy(tree);
68 return FALSE;
69 }
70
71 /* grab the server here to make sure no key pressed go missed */
72 XGrabServer(ob_display);
73 XSync(ob_display, FALSE);
74
75 grab_keys(FALSE);
76
77 /* set the function */
78 t = tree;
79 while (t->first_child) t = t->first_child;
80 t->action.action = action->action;
81 t->action.type[0] = action->type[0];
82 t->action.type[1] = action->type[1];
83 t->action.data[0] = action->data[0];
84 t->action.data[1] = action->data[1];
85
86 /* assimilate this built tree into the main tree */
87 tree_assimilate(tree); /* assimilation destroys/uses the tree */
88
89 grab_keys(TRUE);
90
91 XUngrabServer(ob_display);
92 XFlush(ob_display);
93
94 return TRUE;
95 }
96
97 static void press(ObEvent *e, void *foo)
98 {
99 if (e->data.x.e->xkey.keycode == reset_key &&
100 e->data.x.e->xkey.state == reset_state) {
101 reset_chains();
102 XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
103 } else {
104 KeyBindingTree *p;
105 if (curpos == NULL)
106 p = firstnode;
107 else
108 p = curpos->first_child;
109 while (p) {
110 if (p->key == e->data.x.e->xkey.keycode &&
111 p->state == e->data.x.e->xkey.state) {
112 if (p->first_child != NULL) { /* part of a chain */
113 /* XXX TIMER */
114 if (!grabbed) {
115 /*grab should never fail because we should have a
116 sync grab at this point */
117 XGrabKeyboard(ob_display, ob_root, 0,
118 GrabModeAsync, GrabModeSync,
119 CurrentTime);
120 }
121 grabbed = TRUE;
122 curpos = p;
123 XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
124 } else {
125 keyaction_do(&p->action, focus_client);
126
127 XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
128 reset_chains();
129 }
130 break;
131 }
132 p = p->next_sibling;
133 }
134 }
135 }
136
137 static void binddef()
138 {
139 GList *list = g_list_append(NULL, NULL);
140 KeyAction a;
141
142 list->data = "C-Right";
143 a.action = Action_NextDesktop;
144 keyaction_set_bool(&a, 0, TRUE);
145 keyaction_set_none(&a, 1);
146 bind(list, &a);
147
148 list->data = "C-Left";
149 a.action = Action_PreviousDesktop;
150 keyaction_set_bool(&a, 0, TRUE);
151 keyaction_set_none(&a, 1);
152 bind(list, &a);
153
154 list->data = "C-1";
155 a.action = Action_Desktop;
156 keyaction_set_uint(&a, 0, 0);
157 keyaction_set_none(&a, 1);
158 bind(list, &a);
159
160 list->data = "C-2";
161 a.action = Action_Desktop;
162 keyaction_set_uint(&a, 0, 1);
163 keyaction_set_none(&a, 1);
164 bind(list, &a);
165
166 list->data = "C-3";
167 a.action = Action_Desktop;
168 keyaction_set_uint(&a, 0, 2);
169 keyaction_set_none(&a, 1);
170 bind(list, &a);
171
172 list->data = "C-4";
173 a.action = Action_Desktop;
174 keyaction_set_uint(&a, 0, 3);
175 keyaction_set_none(&a, 1);
176 bind(list, &a);
177
178 list->data = "C-space";
179 a.action = Action_Execute;
180 keyaction_set_string(&a, 0, "xterm");
181 keyaction_set_none(&a, 1);
182 bind(list, &a);
183 }
184
185 void plugin_startup()
186 {
187 dispatch_register(Event_X_KeyPress, (EventHandler)press, NULL);
188
189 /* XXX parse config file! */
190 binddef();
191 }
192
193 void plugin_shutdown()
194 {
195 dispatch_register(0, (EventHandler)press, NULL);
196 clearall();
197 }
198
This page took 0.044161 seconds and 4 git commands to generate.