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