4 #include "clientwrap.h"
12 typedef struct KeyBindingTree
{
18 /* the next binding in the tree at the same level */
19 struct KeyBindingTree
*next_sibling
;
20 /* the first child of this binding (next binding in a chained sequence).*/
21 struct KeyBindingTree
*first_child
;
25 static KeyBindingTree
*firstnode
, *curpos
;
26 static guint reset_key
, reset_state
;
27 static gboolean grabbed
, user_grabbed
;
28 static PyObject
*grab_func
;
30 /***************************************************************************
32 Define the type 'KeyboardData'
34 ***************************************************************************/
36 typedef struct KeyboardData
{
44 staticforward PyTypeObject KeyboardDataType
;
46 /***************************************************************************
50 ***************************************************************************/
52 static PyObject
*keybdata_new(PyObject
*keychain
, guint state
,
53 guint keycode
, gboolean press
)
55 KeyboardData
*data
= PyObject_New(KeyboardData
, &KeyboardDataType
);
56 data
->keychain
= keychain
;
59 data
->keycode
= keycode
;
61 return (PyObject
*) data
;
64 static void keybdata_dealloc(KeyboardData
*self
)
66 Py_DECREF(self
->keychain
);
67 PyObject_Del((PyObject
*)self
);
70 static PyObject
*keybdata_getattr(KeyboardData
*self
, char *name
)
72 if (!strcmp(name
, "keychain")) {
73 Py_INCREF(self
->keychain
);
74 return self
->keychain
;
75 } else if (!strcmp(name
, "state"))
76 return PyInt_FromLong(self
->state
);
77 else if (!strcmp(name
, "keycode"))
78 return PyInt_FromLong(self
->keycode
);
79 else if (!strcmp(name
, "press"))
80 return PyInt_FromLong(!!self
->press
);
82 PyErr_Format(PyExc_AttributeError
, "no such attribute '%s'", name
);
86 static PyTypeObject KeyboardDataType
= {
87 PyObject_HEAD_INIT(NULL
)
92 (destructor
) keybdata_dealloc
, /*tp_dealloc*/
94 (getattrfunc
) keybdata_getattr
, /*tp_getattr*/
104 /***************************************************************************/
108 static gboolean
grab_keyboard(gboolean grab
)
112 g_message("grab_keyboard(%s). grabbed: %d", (grab
?"True":"False"),grabbed
);
117 ret
= XGrabKeyboard(ob_display
, ob_root
, 0, GrabModeAsync
,
118 GrabModeAsync
, CurrentTime
) == GrabSuccess
;
120 XUngrabKeyboard(ob_display
, CurrentTime
);
125 /***************************************************************************
127 Define the type 'Keyboard'
129 ***************************************************************************/
131 #define IS_KEYBOARD(v) ((v)->ob_type == &KeyboardType)
132 #define CHECK_KEYBOARD(self, funcname) { \
133 if (!IS_KEYBOARD(self)) { \
134 PyErr_SetString(PyExc_TypeError, \
135 "descriptor '" funcname "' requires a 'Keyboard' " \
141 typedef struct Keyboard
{
145 staticforward PyTypeObject KeyboardType
;
148 static PyObject
*keyb_clearBinds(Keyboard
*self
, PyObject
*args
)
150 CHECK_KEYBOARD(self
, "clearBinds");
151 if (!PyArg_ParseTuple(args
, ":clearBinds"))
158 static PyObject
*keyb_grab(Keyboard
*self
, PyObject
*args
)
162 CHECK_KEYBOARD(self
, "grab");
163 if (!PyArg_ParseTuple(args
, "O:grab", &func
))
165 if (!PyCallable_Check(func
)) {
166 PyErr_SetString(PyExc_ValueError
, "expected a callable object");
169 if (!grab_keyboard(TRUE
)) {
170 PyErr_SetString(PyExc_RuntimeError
, "failed to grab keyboard");
174 Py_INCREF(grab_func
);
179 static PyObject
*keyb_ungrab(Keyboard
*self
, PyObject
*args
)
181 CHECK_KEYBOARD(self
, "ungrab");
182 if (!PyArg_ParseTuple(args
, ":ungrab"))
184 grab_keyboard(FALSE
);
185 Py_XDECREF(grab_func
);
191 #define METH(n, d) {#n, (PyCFunction)keyb_##n, METH_VARARGS, #d}
193 static PyMethodDef KeyboardMethods
[] = {
195 "bind(keychain, func)\n\n"
196 "Binds a key-chain to a function. The keychain is a tuple of strings "
197 "which define a chain of key presses. Each member of the tuple has "
198 "the format [Modifier-]...[Key]. Modifiers can be 'mod1', 'mod2', "
199 "'mod3', 'mod4', 'mod5', 'control', and 'shift'. The keys on your "
200 "keyboard that are bound to each of these modifiers can be found by "
201 "running 'xmodmap'. The Key can be any valid key definition. Key "
202 "definitions can be found by running 'xev', pressing the key while "
203 "its window is focused, and watching its output. Here are some "
204 "examples of valid keychains: ('a'), ('F7'), ('control-a', 'd'), "
205 "('control-mod1-x', 'control-mod4-g'), ('F1', 'space'). The func "
206 "must have a definition similar to 'def func(keydata, client)'. A "
207 "keychain cannot be bound to more than one function."),
210 "Removes all bindings that were previously made by bind()."),
213 "Grabs the entire keyboard, causing all possible keyboard events to "
214 "be passed to the given function. CAUTION: Be sure when you grab() "
215 "that you also have an ungrab() that will execute, or you will not "
216 "be able to type until you restart Openbox. The func must have a "
217 "definition similar to 'def func(keydata)'. The keyboard cannot be "
218 "grabbed if it is already grabbed."),
221 "Ungrabs the keyboard. The keyboard cannot be ungrabbed if it is not "
223 { NULL
, NULL
, 0, NULL
}
226 /***************************************************************************
230 ***************************************************************************/
232 static void keyb_dealloc(PyObject
*self
)
237 static PyTypeObject KeyboardType
= {
238 PyObject_HEAD_INIT(NULL
)
243 (destructor
) keyb_dealloc
, /*tp_dealloc*/
250 0, /*tp_as_sequence*/
255 /**************************************************************************/
257 void keyboard_startup()
259 PyObject
*input
, *inputdict
, *ptr
;
262 curpos
= firstnode
= NULL
;
263 grabbed
= user_grabbed
= FALSE
;
265 b
= translate("C-G", &reset_state
, &reset_key
);
268 KeyboardType
.ob_type
= &PyType_Type
;
269 KeyboardType
.tp_methods
= KeyboardMethods
;
270 PyType_Ready(&KeyboardType
);
271 PyType_Ready(&KeyboardDataType
);
273 /* get the input module/dict */
274 input
= PyImport_ImportModule("input"); /* new */
275 g_assert(input
!= NULL
);
276 inputdict
= PyModule_GetDict(input
); /* borrowed */
277 g_assert(inputdict
!= NULL
);
279 /* add a Keyboard instance to the input module */
280 ptr
= (PyObject
*) PyObject_New(Keyboard
, &KeyboardType
);
281 PyDict_SetItemString(inputdict
, "Keyboard", ptr
);
287 void keyboard_shutdown()
289 if (grabbed
|| user_grabbed
) {
291 grab_keyboard(FALSE
);
294 destroytree(firstnode
);