]> Dogcows Code - chaz/openbox/blob - plugins/keyboard/keyboard.c
mouse and key bindings plugins work. segfault somewhere still on shutdown
[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 <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 /* XXX grab all lock keys too */
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_keyboard(FALSE);
38 }
39 }
40
41 static gboolean kbind(GList *keylist, Action *action)
42 {
43 KeyBindingTree *tree, *t;
44 gboolean conflict;
45
46 g_assert(keylist != NULL);
47 g_assert(action != NULL);
48
49 if (!(tree = tree_build(keylist))) {
50 g_warning("invalid binding");
51 return FALSE;
52 }
53 if ((t = tree_find(tree, &conflict)) != NULL) {
54 /* already bound to something */
55 g_warning("keychain is already bound");
56 tree_destroy(tree);
57 return FALSE;
58 }
59 if (conflict) {
60 g_warning("conflict with binding");
61 tree_destroy(tree);
62 return FALSE;
63 }
64
65 /* grab the server here to make sure no key presses go missed */
66 grab_server(TRUE);
67 grab_keys(FALSE);
68
69 /* set the action */
70 t = tree;
71 while (t->first_child) t = t->first_child;
72 t->action = action;
73 /* assimilate this built tree into the main tree. assimilation
74 destroys/uses the tree */
75 tree_assimilate(tree);
76
77 grab_keys(TRUE);
78 grab_server(FALSE);
79
80 return TRUE;
81 }
82
83 static void press(ObEvent *e, void *foo)
84 {
85 if (e->data.x.e->xkey.keycode == reset_key &&
86 e->data.x.e->xkey.state == reset_state) {
87 reset_chains();
88 XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
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 XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
104 }
105 curpos = p;
106 } else {
107 if (p->action->func != NULL) {
108 p->action->data.any.c = focus_client;
109
110 g_assert(!(p->action->func == action_move ||
111 p->action->func == action_resize));
112
113 p->action->func(&p->action->data);
114 }
115
116 XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
117 reset_chains();
118 }
119 break;
120 }
121 p = p->next_sibling;
122 }
123 }
124 }
125
126 static void binddef()
127 {
128 GList *list = g_list_append(NULL, NULL);
129 Action *a;
130
131 /* When creating an Action struct, all of the data elements in the
132 appropriate struct need to be set, except the Client*, which will be set
133 at call-time when then action function is used.
134 */
135
136 list->data = "C-Right";
137 a = action_new(action_next_desktop);
138 a->data.nextprevdesktop.wrap = TRUE;
139 kbind(list, a);
140
141 list->data = "C-Left";
142 a = action_new(action_previous_desktop);
143 a->data.nextprevdesktop.wrap = TRUE;
144 kbind(list, a);
145
146 list->data = "C-1";
147 a = action_new(action_desktop);
148 a->data.desktop.desk = 0;
149 kbind(list, a);
150
151 list->data = "C-2";
152 a = action_new(action_desktop);
153 a->data.desktop.desk = 1;
154 kbind(list, a);
155
156 list->data = "C-3";
157 a = action_new(action_desktop);
158 a->data.desktop.desk = 2;
159 kbind(list, a);
160
161 list->data = "C-4";
162 a = action_new(action_desktop);
163 a->data.desktop.desk = 3;
164 kbind(list, a);
165
166 list->data = "C-space";
167 a = action_new(action_execute);
168 a->data.execute.path = g_strdup("xterm");
169 kbind(list, a);
170 }
171
172 void plugin_startup()
173 {
174 dispatch_register(Event_X_KeyPress, (EventHandler)press, NULL);
175
176 /* XXX parse config file! */
177 binddef();
178 }
179
180 void plugin_shutdown()
181 {
182 dispatch_register(0, (EventHandler)press, NULL);
183
184 grab_keys(FALSE);
185 tree_destroy(firstnode);
186 firstnode = NULL;
187 grab_keys(TRUE);
188 }
189
This page took 0.043588 seconds and 5 git commands to generate.