+++ /dev/null
-#include "focus.h"
-#include "openbox.h"
-#include "keyboard.h"
-#include "clientwrap.h"
-
-#include <Python.h>
-#include <glib.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
-
-typedef struct KeyBindingTree {
- guint state;
- guint key;
- GList *keylist;
- PyObject *func;
-
- /* the next binding in the tree at the same level */
- struct KeyBindingTree *next_sibling;
- /* the first child of this binding (next binding in a chained sequence).*/
- struct KeyBindingTree *first_child;
-} KeyBindingTree;
-
-
-static KeyBindingTree *firstnode, *curpos;
-static guint reset_key, reset_state;
-static gboolean grabbed, user_grabbed;
-static PyObject *grab_func;
-
-/***************************************************************************
-
- Define the type 'KeyboardData'
-
- ***************************************************************************/
-
-typedef struct KeyboardData {
- PyObject_HEAD
- PyObject *keychain;
- guint state;
- guint keycode;
- gboolean press;
-} KeyboardData;
-
-staticforward PyTypeObject KeyboardDataType;
-
-/***************************************************************************
-
- Type methods/struct
-
- ***************************************************************************/
-
-static PyObject *keybdata_new(PyObject *keychain, guint state,
- guint keycode, gboolean press)
-{
- KeyboardData *data = PyObject_New(KeyboardData, &KeyboardDataType);
- data->keychain = keychain;
- Py_INCREF(keychain);
- data->state = state;
- data->keycode = keycode;
- data->press = press;
- return (PyObject*) data;
-}
-
-static void keybdata_dealloc(KeyboardData *self)
-{
- Py_DECREF(self->keychain);
- PyObject_Del((PyObject*)self);
-}
-
-static PyObject *keybdata_getattr(KeyboardData *self, char *name)
-{
- if (!strcmp(name, "keychain")) {
- Py_INCREF(self->keychain);
- return self->keychain;
- } else if (!strcmp(name, "state"))
- return PyInt_FromLong(self->state);
- else if (!strcmp(name, "keycode"))
- return PyInt_FromLong(self->keycode);
- else if (!strcmp(name, "press"))
- return PyInt_FromLong(!!self->press);
-
- PyErr_Format(PyExc_AttributeError, "no such attribute '%s'", name);
- return NULL;
-}
-
-static PyTypeObject KeyboardDataType = {
- PyObject_HEAD_INIT(NULL)
- 0,
- "KeyboardData",
- sizeof(KeyboardData),
- 0,
- (destructor) keybdata_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc) keybdata_getattr, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
-};
-
-/***************************************************************************/
-
-
-
-static gboolean grab_keyboard(gboolean grab)
-{
- gboolean ret = TRUE;
-
- g_message("grab_keyboard(%s). grabbed: %d", (grab?"True":"False"),grabbed);
-
- user_grabbed = grab;
- if (!grabbed) {
- if (grab)
- ret = XGrabKeyboard(ob_display, ob_root, 0, GrabModeAsync,
- GrabModeAsync, CurrentTime) == GrabSuccess;
- else
- XUngrabKeyboard(ob_display, CurrentTime);
- }
- return ret;
-}
-
-/***************************************************************************
-
- Define the type 'Keyboard'
-
- ***************************************************************************/
-
-#define IS_KEYBOARD(v) ((v)->ob_type == &KeyboardType)
-#define CHECK_KEYBOARD(self, funcname) { \
- if (!IS_KEYBOARD(self)) { \
- PyErr_SetString(PyExc_TypeError, \
- "descriptor '" funcname "' requires a 'Keyboard' " \
- "object"); \
- return NULL; \
- } \
-}
-
-typedef struct Keyboard {
- PyObject_HEAD
-} Keyboard;
-
-staticforward PyTypeObject KeyboardType;
-
-
-static PyObject *keyb_clearBinds(Keyboard *self, PyObject *args)
-{
- CHECK_KEYBOARD(self, "clearBinds");
- if (!PyArg_ParseTuple(args, ":clearBinds"))
- return NULL;
- clearall();
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *keyb_grab(Keyboard *self, PyObject *args)
-{
- PyObject *func;
-
- CHECK_KEYBOARD(self, "grab");
- if (!PyArg_ParseTuple(args, "O:grab", &func))
- return NULL;
- if (!PyCallable_Check(func)) {
- PyErr_SetString(PyExc_ValueError, "expected a callable object");
- return NULL;
- }
- if (!grab_keyboard(TRUE)) {
- PyErr_SetString(PyExc_RuntimeError, "failed to grab keyboard");
- return NULL;
- }
- grab_func = func;
- Py_INCREF(grab_func);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *keyb_ungrab(Keyboard *self, PyObject *args)
-{
- CHECK_KEYBOARD(self, "ungrab");
- if (!PyArg_ParseTuple(args, ":ungrab"))
- return NULL;
- grab_keyboard(FALSE);
- Py_XDECREF(grab_func);
- grab_func = NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-#define METH(n, d) {#n, (PyCFunction)keyb_##n, METH_VARARGS, #d}
-
-static PyMethodDef KeyboardMethods[] = {
- METH(bind,
- "bind(keychain, func)\n\n"
- "Binds a key-chain to a function. The keychain is a tuple of strings "
- "which define a chain of key presses. Each member of the tuple has "
- "the format [Modifier-]...[Key]. Modifiers can be 'mod1', 'mod2', "
- "'mod3', 'mod4', 'mod5', 'control', and 'shift'. The keys on your "
- "keyboard that are bound to each of these modifiers can be found by "
- "running 'xmodmap'. The Key can be any valid key definition. Key "
- "definitions can be found by running 'xev', pressing the key while "
- "its window is focused, and watching its output. Here are some "
- "examples of valid keychains: ('a'), ('F7'), ('control-a', 'd'), "
- "('control-mod1-x', 'control-mod4-g'), ('F1', 'space'). The func "
- "must have a definition similar to 'def func(keydata, client)'. A "
- "keychain cannot be bound to more than one function."),
- METH(clearBinds,
- "clearBinds()\n\n"
- "Removes all bindings that were previously made by bind()."),
- METH(grab,
- "grab(func)\n\n"
- "Grabs the entire keyboard, causing all possible keyboard events to "
- "be passed to the given function. CAUTION: Be sure when you grab() "
- "that you also have an ungrab() that will execute, or you will not "
- "be able to type until you restart Openbox. The func must have a "
- "definition similar to 'def func(keydata)'. The keyboard cannot be "
- "grabbed if it is already grabbed."),
- METH(ungrab,
- "ungrab()\n\n"
- "Ungrabs the keyboard. The keyboard cannot be ungrabbed if it is not "
- "grabbed."),
- { NULL, NULL, 0, NULL }
-};
-
-/***************************************************************************
-
- Type methods/struct
-
- ***************************************************************************/
-
-static void keyb_dealloc(PyObject *self)
-{
- PyObject_Del(self);
-}
-
-static PyTypeObject KeyboardType = {
- PyObject_HEAD_INIT(NULL)
- 0,
- "Keyboard",
- sizeof(Keyboard),
- 0,
- (destructor) keyb_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
-};
-
-/**************************************************************************/
-
-void keyboard_startup()
-{
- PyObject *input, *inputdict, *ptr;
- gboolean b;
-
- curpos = firstnode = NULL;
- grabbed = user_grabbed = FALSE;
-
- b = translate("C-G", &reset_state, &reset_key);
- g_assert(b);
-
- KeyboardType.ob_type = &PyType_Type;
- KeyboardType.tp_methods = KeyboardMethods;
- PyType_Ready(&KeyboardType);
- PyType_Ready(&KeyboardDataType);
-
- /* get the input module/dict */
- input = PyImport_ImportModule("input"); /* new */
- g_assert(input != NULL);
- inputdict = PyModule_GetDict(input); /* borrowed */
- g_assert(inputdict != NULL);
-
- /* add a Keyboard instance to the input module */
- ptr = (PyObject*) PyObject_New(Keyboard, &KeyboardType);
- PyDict_SetItemString(inputdict, "Keyboard", ptr);
- Py_DECREF(ptr);
-
- Py_DECREF(input);
-}
-
-void keyboard_shutdown()
-{
- if (grabbed || user_grabbed) {
- grabbed = FALSE;
- grab_keyboard(FALSE);
- }
- grab_keys(FALSE);
- destroytree(firstnode);
- firstnode = NULL;
-}
-
+++ /dev/null
-#include "pointer.h"
-#include "keyboard.h"
-#include "frame.h"
-#include "engine.h"
-#include "openbox.h"
-#include "hooks.h"
-#include "configwrap.h"
-
-#include <glib.h>
-#include <Python.h>
-#include <structmember.h> /* for PyMemberDef stuff */
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-typedef enum {
- Action_Press,
- Action_Release,
- Action_Click,
- Action_DoubleClick,
- Action_Motion,
- NUM_ACTIONS
-} Action;
-
-/* GData of GSList*s of PointerBinding*s. */
-static GData *bound_contexts;
-static gboolean grabbed;
-PyObject *grab_func;
-
-struct foreach_grab_temp {
- Client *client;
- gboolean grab;
-};
-
-typedef struct {
- guint state;
- guint button;
- Action action;
- char *name;
- GSList *funcs[NUM_ACTIONS];
-} PointerBinding;
-
-/***************************************************************************
-
- Define the type 'ButtonData'
-
- ***************************************************************************/
-
-typedef struct PointerData {
- PyObject_HEAD
- Action action;
- GQuark context;
- char *button;
- guint state;
- guint buttonnum;
- int posx, posy;
- int pressposx, pressposy;
- int pcareax, pcareay, pcareaw, pcareah;
-} PointerData;
-
-staticforward PyTypeObject PointerDataType;
-
-/***************************************************************************
-
- Type methods/struct
-
- ***************************************************************************/
-
-static PyObject *ptrdata_new(char *button, GQuark context, Action action,
- guint state, guint buttonnum, int posx, int posy,
- int pressposx, int pressposy, int pcareax,
- int pcareay, int pcareaw, int pcareah)
-{
- PointerData *self = PyObject_New(PointerData, &PointerDataType);
- self->button = g_strdup(button);
- self->context = context;
- self->action = action;
- self->state = state;
- self->buttonnum = buttonnum;
- self->posx = posx;
- self->posy = posy;
- self->pressposx = pressposx;
- self->pressposy = pressposy;
- self->pcareax = pcareax;
- self->pcareay = pcareay;
- self->pcareaw = pcareaw;
- self->pcareah = pcareah;
- return (PyObject*) self;
-}
-
-static void ptrdata_dealloc(PointerData *self)
-{
- g_free(self->button);
- PyObject_Del((PyObject*)self);
-}
-
-static PyObject *ptrdata_getattr(PointerData *self, char *name)
-{
- if (!strcmp(name, "button"))
- return PyString_FromString(self->button);
- if (!strcmp(name, "action"))
- return PyInt_FromLong(self->action);
- if (!strcmp(name, "context"))
- return PyString_FromString(g_quark_to_string(self->context));
- if (!strcmp(name, "state"))
- return PyInt_FromLong(self->state);
- if (!strcmp(name, "buttonnum"))
- return PyInt_FromLong(self->buttonnum);
-
- if (self->action == Action_Motion) { /* the rest are only for motions */
- if (!strcmp(name, "pos")) {
- PyObject *pos = PyTuple_New(2);
- PyTuple_SET_ITEM(pos, 0, PyInt_FromLong(self->posx));
- PyTuple_SET_ITEM(pos, 1, PyInt_FromLong(self->posy));
- return pos;
- }
- if (!strcmp(name, "presspos")) {
- PyObject *presspos = PyTuple_New(2);
- PyTuple_SET_ITEM(presspos, 0, PyInt_FromLong(self->pressposx));
- PyTuple_SET_ITEM(presspos, 1, PyInt_FromLong(self->pressposy));
- return presspos;
- }
- if (!strcmp(name, "pressclientarea")) {
- if (self->pcareaw < 0) { /* < 0 indicates no client */
- Py_INCREF(Py_None);
- return Py_None;
- } else {
- PyObject *ca = PyTuple_New(4);
- PyTuple_SET_ITEM(ca, 0, PyInt_FromLong(self->pcareax));
- PyTuple_SET_ITEM(ca, 1, PyInt_FromLong(self->pcareay));
- PyTuple_SET_ITEM(ca, 2, PyInt_FromLong(self->pcareaw));
- PyTuple_SET_ITEM(ca, 3, PyInt_FromLong(self->pcareah));
- return ca;
- }
- }
- }
-
- PyErr_Format(PyExc_AttributeError, "no such attribute '%s'", name);
- return NULL;
-}
-
-static PyTypeObject PointerDataType = {
- PyObject_HEAD_INIT(NULL)
- 0,
- "PointerData",
- sizeof(PointerData),
- 0,
- (destructor) ptrdata_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc) ptrdata_getattr, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
-};
-
-/***************************************************************************/
-
-static gboolean translate(char *str, guint *state, guint *button)
-{
- char **parsed;
- char *l;
- int i;
- gboolean ret = FALSE;
-
- parsed = g_strsplit(str, "-", -1);
-
- /* first, find the button (last token) */
- l = NULL;
- for (i = 0; parsed[i] != NULL; ++i)
- l = parsed[i];
- if (l == NULL)
- goto translation_fail;
-
- /* figure out the mod mask */
- *state = 0;
- for (i = 0; parsed[i] != l; ++i) {
- guint m = keyboard_translate_modifier(parsed[i]);
- if (!m) goto translation_fail;
- *state |= m;
- }
-
- /* figure out the button */
- *button = atoi(l);
- if (!*button) {
- g_warning("Invalid button '%s' in pointer binding.", l);
- goto translation_fail;
- }
-
- ret = TRUE;
-
-translation_fail:
- g_strfreev(parsed);
- return ret;
-}
-
-static void grab_button(Client *client, guint state, guint button,
- GQuark context, gboolean grab)
-{
- Window win;
- int mode = GrabModeAsync;
- unsigned int mask;
-
- if (context == g_quark_try_string("frame")) {
- win = client->frame->window;
- mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
- } else if (context == g_quark_try_string("client")) {
- win = client->frame->plate;
- mode = GrabModeSync; /* this is handled in pointer_event */
- mask = ButtonPressMask; /* can't catch more than this with Sync mode
- the release event is manufactured in
- pointer_fire */
- } else return;
-
- if (grab)
- XGrabButton(ob_display, button, state, win, FALSE, mask, mode,
- GrabModeAsync, None, None);
- else
- XUngrabButton(ob_display, button, state, win);
-}
-
-static void foreach_grab(GQuark key, gpointer data, gpointer user_data)
-{
- struct foreach_grab_temp *d = user_data;
- GSList *it;
- for (it = data; it != NULL; it = it->next) {
- PointerBinding *b = it->data;
- grab_button(d->client, b->state, b->button, key, d->grab);
- }
-}
-
-void pointer_grab_all(Client *client, gboolean grab)
-{
- struct foreach_grab_temp bt;
- bt.client = client;
- bt.grab = grab;
- g_datalist_foreach(&bound_contexts, foreach_grab, &bt);
-}
-
-static void grab_all_clients(gboolean grab)
-{
- GSList *it;
-
- for (it = client_list; it != NULL; it = it->next)
- pointer_grab_all(it->data, grab);
-}
-
-static gboolean grab_pointer(gboolean grab)
-{
- gboolean ret = TRUE;
- if (grab)
- ret = XGrabPointer(ob_display, ob_root, FALSE, (ButtonPressMask |
- ButtonReleaseMask |
- ButtonMotionMask |
- PointerMotionMask),
- GrabModeAsync, GrabModeAsync, None, None,
- CurrentTime) == GrabSuccess;
- else
- XUngrabPointer(ob_display, CurrentTime);
- if (ret) grabbed = grab;
- return ret;
-}
-
-static void foreach_clear(GQuark key, gpointer data, gpointer user_data)
-{
- GSList *it;
- user_data = user_data;
- for (it = data; it != NULL; it = it->next) {
- int i;
-
- PointerBinding *b = it->data;
- for (i = 0; i < NUM_ACTIONS; ++i)
- while (b->funcs[i] != NULL) {
- Py_DECREF((PyObject*)b->funcs[i]->data);
- b->funcs[i] = g_slist_delete_link(b->funcs[i], b->funcs[i]);
- }
- g_free(b->name);
- g_free(b);
- }
- g_slist_free(data);
-}
-
-static void clearall()
-{
- grab_all_clients(FALSE);
- g_datalist_foreach(&bound_contexts, foreach_clear, NULL);
-}
-
-static void fire_event(char *button, GQuark context, Action action,
- guint state, guint buttonnum, int posx, int posy,
- int pressposx, int pressposy, int pcareax,
- int pcareay, int pcareaw, int pcareah,
- PyObject *client, GSList *functions)
-{
- PyObject *ptrdata, *args, *ret;
- GSList *it;
-
- ptrdata = ptrdata_new(button, context, action,
- state, buttonnum, posx, posy, pressposx, pressposy,
- pcareax, pcareay, pcareaw, pcareah);
- args = Py_BuildValue("OO", ptrdata, client);
-
- if (grabbed) {
- ret = PyObject_CallObject(grab_func, args);
- if (ret == NULL) PyErr_Print();
- Py_XDECREF(ret);
- } else {
- for (it = functions; it != NULL; it = it->next) {
- ret = PyObject_CallObject(it->data, args);
- if (ret == NULL) PyErr_Print();
- Py_XDECREF(ret);
- }
- }
-
- Py_DECREF(args);
- Py_DECREF(ptrdata);
-}
-
-void pointer_event(XEvent *e, Client *c)
-{
- static guint button = 0, lastbutton = 0;
- static Time time = 0;
- static Rect carea;
- static guint pressx, pressy;
- GQuark contextq;
- gboolean click = FALSE, dblclick = FALSE;
- PyObject *client;
- GString *str = g_string_sized_new(0);
- guint state;
- GSList *it = NULL;
- PointerBinding *b = NULL;
- guint drag_threshold;
-
- drag_threshold = configwrap_get_int("input", "drag_threshold");
-
- contextq = engine_get_context(c, e->xany.window);
-
- /* pick a button, figure out clicks/double clicks */
- switch (e->type) {
- case ButtonPress:
- if (!button) {
- button = e->xbutton.button;
- if (c != NULL) carea = c->frame->area;
- else carea.width = -1; /* indicates no client */
- pressx = e->xbutton.x_root;
- pressy = e->xbutton.y_root;
- }
- state = e->xbutton.state;
- break;
- case ButtonRelease:
- state = e->xbutton.state;
- break;
- case MotionNotify:
- state = e->xmotion.state;
- break;
- default:
- g_assert_not_reached();
- return;
- }
-
- if (!grabbed) {
- for (it = g_datalist_id_get_data(&bound_contexts, contextq);
- it != NULL; it = it->next) {
- b = it->data;
- if (b->state == state && b->button == button)
- break;
- }
- /* if not grabbed and not bound, then nothing to do! */
- if (it == NULL) return;
- }
-
- if (c) client = clientwrap_new(c);
- else client = Py_None;
-
- /* build the button string */
- if (state & ControlMask) g_string_append(str, "C-");
- if (state & ShiftMask) g_string_append(str, "S-");
- if (state & Mod1Mask) g_string_append(str, "Mod1-");
- if (state & Mod2Mask) g_string_append(str, "Mod2-");
- if (state & Mod3Mask) g_string_append(str, "Mod3-");
- if (state & Mod4Mask) g_string_append(str, "Mod4-");
- if (state & Mod5Mask) g_string_append(str, "Mod5-");
- g_string_append_printf(str, "%d", button);
-
- /* figure out clicks/double clicks */
- switch (e->type) {
- case ButtonRelease:
- if (button == e->xbutton.button) {
- /* determine if this is a valid 'click'. Its not if the release is
- not over the window, or if a drag occured. */
- if (ABS(e->xbutton.x_root - pressx) < drag_threshold &&
- ABS(e->xbutton.y_root - pressy) < drag_threshold &&
- e->xbutton.x >= 0 && e->xbutton.y >= 0) {
- int junk;
- Window wjunk;
- guint ujunk, w, h;
- XGetGeometry(ob_display, e->xany.window, &wjunk, &junk, &junk,
- &w, &h, &ujunk, &ujunk);
- if (e->xbutton.x < (signed)w && e->xbutton.y < (signed)h)
- click =TRUE;
- }
-
- /* determine if this is a valid 'double-click' */
- if (click) {
- if (lastbutton == button &&
- e->xbutton.time -
- configwrap_get_int("input", "double_click_rate") < time) {
- dblclick = TRUE;
- lastbutton = 0;
- } else
- lastbutton = button;
- } else
- lastbutton = 0;
- time = e->xbutton.time;
- pressx = pressy = 0;
- button = 0;
- carea.x = carea.y = carea.width = carea.height = 0;
- }
- break;
- }
-
- /* fire off the events */
- switch (e->type) {
- case ButtonPress:
- fire_event(str->str, contextq, Action_Press,
- state, button, 0, 0, 0, 0, 0, 0, 0, 0,
- client, b == NULL ? NULL : b->funcs[Action_Press]);
- break;
- case ButtonRelease:
- fire_event(str->str, contextq, Action_Release,
- state, button, 0, 0, 0, 0, 0, 0, 0, 0,
- client, b == NULL ? NULL : b->funcs[Action_Release]);
- break;
- case MotionNotify:
- /* watch out for the drag threshold */
- if (ABS(e->xmotion.x_root - pressx) < drag_threshold &&
- ABS(e->xmotion.y_root - pressy) < drag_threshold)
- break;
- fire_event(str->str, contextq, Action_Motion,
- state, button, e->xmotion.x_root,
- e->xmotion.y_root, pressx, pressy,
- carea.x, carea.y, carea.width, carea.height,
- client, b == NULL ? NULL : b->funcs[Action_Motion]);
- break;
- }
-
- if (click)
- fire_event(str->str, contextq, Action_Click,
- state, button, 0, 0, 0, 0, 0, 0, 0, 0,
- client, b == NULL ? NULL : b->funcs[Action_Click]);
- if (dblclick)
- fire_event(str->str, contextq, Action_DoubleClick,
- state, button, 0, 0, 0, 0, 0, 0, 0, 0,
- client, b == NULL ? NULL : b->funcs[Action_DoubleClick]);
-
- g_string_free(str, TRUE);
- if (client != Py_None) { Py_DECREF(client); }
-
- if (contextq == g_quark_try_string("client")) {
- /* Replay the event, so it goes to the client*/
- XAllowEvents(ob_display, ReplayPointer, CurrentTime);
- /* generate a release event since we don't get real ones */
- if (e->type == ButtonPress) {
- e->type = ButtonRelease;
- pointer_event(e, c);
- }
- }
-}
-
-/***************************************************************************
-
- Define the type 'Pointer'
-
- ***************************************************************************/
-
-#define IS_POINTER(v) ((v)->ob_type == &PointerType)
-#define CHECK_POINTER(self, funcname) { \
- if (!IS_POINTER(self)) { \
- PyErr_SetString(PyExc_TypeError, \
- "descriptor '" funcname "' requires a 'Pointer' " \
- "object"); \
- return NULL; \
- } \
-}
-
-typedef struct Pointer {
- PyObject_HEAD
- Action press;
- Action release;
- Action click;
- Action doubleclick;
- Action motion;
-} Pointer;
-
-staticforward PyTypeObject PointerType;
-
-static PyObject *ptr_bind(Pointer *self, PyObject *args)
-{
- char *buttonstr;
- char *contextstr;
- guint state, button;
- PointerBinding *b;
- GSList *it;
- GQuark context;
- PyObject *func;
- Action action;
- int i;
-
- CHECK_POINTER(self, "grab");
- if (!PyArg_ParseTuple(args, "ssiO:grab",
- &buttonstr, &contextstr, &action, &func))
- return NULL;
-
- if (!translate(buttonstr, &state, &button)) {
- PyErr_SetString(PyExc_ValueError, "invalid button");
- return NULL;
- }
-
- context = g_quark_try_string(contextstr);
- if (!context) {
- PyErr_SetString(PyExc_ValueError, "invalid context");
- return NULL;
- }
-
- if (action < 0 || action >= NUM_ACTIONS) {
- PyErr_SetString(PyExc_ValueError, "invalid action");
- return NULL;
- }
-
- if (!PyCallable_Check(func)) {
- PyErr_SetString(PyExc_ValueError, "expected a callable object");
- return NULL;
- }
-
- for (it = g_datalist_id_get_data(&bound_contexts, context);
- it != NULL; it = it->next){
- b = it->data;
- if (b->state == state && b->button == button) {
- /* already bound */
- b->funcs[action] = g_slist_append(b->funcs[action], func);
- Py_INCREF(Py_None);
- return Py_None;
- }
- }
-
- grab_all_clients(FALSE);
-
- /* add the binding */
- b = g_new(PointerBinding, 1);
- b->state = state;
- b->button = button;
- b->name = g_strdup(buttonstr);
- for (i = 0; i < NUM_ACTIONS; ++i)
- if (i != (signed)action) b->funcs[i] = NULL;
- b->funcs[action] = g_slist_append(NULL, func);
- g_datalist_id_set_data(&bound_contexts, context,
- g_slist_append(g_datalist_id_get_data(&bound_contexts, context), b));
- grab_all_clients(TRUE);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *ptr_clearBinds(Pointer *self, PyObject *args)
-{
- CHECK_POINTER(self, "clearBinds");
- if (!PyArg_ParseTuple(args, ":clearBinds"))
- return NULL;
- clearall();
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *ptr_grab(Pointer *self, PyObject *args)
-{
- PyObject *func;
-
- CHECK_POINTER(self, "grab");
- if (!PyArg_ParseTuple(args, "O:grab", &func))
- return NULL;
- if (!PyCallable_Check(func)) {
- PyErr_SetString(PyExc_ValueError, "expected a callable object");
- return NULL;
- }
- if (!grab_pointer(TRUE)) {
- PyErr_SetString(PyExc_RuntimeError, "failed to grab pointer");
- return NULL;
- }
- grab_func = func;
- Py_INCREF(grab_func);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *ptr_ungrab(Pointer *self, PyObject *args)
-{
- CHECK_POINTER(self, "ungrab");
- if (!PyArg_ParseTuple(args, ":ungrab"))
- return NULL;
- grab_pointer(FALSE);
- Py_XDECREF(grab_func);
- grab_func = NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-#define METH(n, d) {#n, (PyCFunction)ptr_##n, METH_VARARGS, #d}
-
-static PyMethodDef PointerMethods[] = {
- METH(bind,
- "bind(button, context, func)\n\n"
- "Binds a pointer button for a context to a function. See the "
- "Terminology section for a decription and list of common contexts. "
- "The button is a string which defines a modifier and button "
- "combination with the format [Modifier-]...[Button]. Modifiers can "
- "be 'mod1', 'mod2', 'mod3', 'mod4', 'mod5', 'control', and 'shift'. "
- "The keys on your keyboard that are bound to each of these modifiers "
- "can be found by running 'xmodmap'. The button is the number of the "
- "button. Button numbers can be found by running 'xev', pressing the "
- "button with the pointer over its window, and watching its output. "
- "Here are some examples of valid buttons: 'control-1', '2', "
- "'mod1-shift-5'. The func must have a definition similar to "
- "'def func(keydata, client)'. A button and context may be bound to "
- "more than one function."),
- METH(clearBinds,
- "clearBinds()\n\n"
- "Removes all bindings that were previously made by bind()."),
- METH(grab,
- "grab(func)\n\n"
- "Grabs the pointer device, causing all possible pointer events to be "
- "sent to the given function. CAUTION: Be sure when you grab() that "
- "you also have an ungrab() that will execute, or you will not be "
- "able to use the pointer device until you restart Openbox. The func "
- "must have a definition similar to 'def func(keydata)'. The pointer "
- "cannot be grabbed if it is already grabbed."),
- METH(ungrab,
- "ungrab()\n\n"
- "Ungrabs the pointer. The pointer cannot be ungrabbed if it is not "
- "grabbed."),
- { NULL, NULL, 0, NULL }
-};
-
-static PyMemberDef PointerMembers[] = {
- {"Action_Press", T_INT, offsetof(Pointer, press), READONLY,
- "a pointer button press"},
- {"Action_Release", T_INT, offsetof(Pointer, release), READONLY,
- "a pointer button release"},
- {"Action_Click", T_INT, offsetof(Pointer, click), READONLY,
- "a pointer button click (press-release)"},
- {"Action_DoubleClick", T_INT, offsetof(Pointer, doubleclick), READONLY,
- "a pointer button double-click"},
- {"Action_Motion", T_INT, offsetof(Pointer, motion), READONLY,
- "a pointer drag"},
- {NULL}
-};
-
-/***************************************************************************
-
- Type methods/struct
-
- ***************************************************************************/
-
-static void ptr_dealloc(PyObject *self)
-{
- PyObject_Del(self);
-}
-
-static PyTypeObject PointerType = {
- PyObject_HEAD_INIT(NULL)
- 0,
- "Pointer",
- sizeof(Pointer),
- 0,
- (destructor) ptr_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
-};
-
-/**************************************************************************/
-
-void pointer_startup()
-{
- PyObject *input, *inputdict;
- Pointer *ptr;
-
- grabbed = FALSE;
- configwrap_add_int("input", "double_click_rate", "Double-Click Rate",
- "An integer containing the number of milliseconds in "
- "which 2 clicks must be received to cause a "
- "double-click event.", 300);
- configwrap_add_int("input", "drag_threshold", "Drag Threshold",
- "An integer containing the number of pixels a drag "
- "must go before motion events start getting generated. "
- "Once a drag has begun, the button release will not "
- "count as a click event.", 3);
- g_datalist_init(&bound_contexts);
-
- PointerType.ob_type = &PyType_Type;
- PointerType.tp_methods = PointerMethods;
- PointerType.tp_members = PointerMembers;
- PyType_Ready(&PointerType);
- PyType_Ready(&PointerDataType);
-
- /* get the input module/dict */
- input = PyImport_ImportModule("input"); /* new */
- g_assert(input != NULL);
- inputdict = PyModule_GetDict(input); /* borrowed */
- g_assert(inputdict != NULL);
-
- /* add a Pointer instance to the input module */
- ptr = PyObject_New(Pointer, &PointerType);
- ptr->press = Action_Press;
- ptr->release = Action_Release;
- ptr->click = Action_Click;
- ptr->doubleclick = Action_DoubleClick;
- ptr->motion = Action_Motion;
- PyDict_SetItemString(inputdict, "Pointer", (PyObject*) ptr);
- Py_DECREF(ptr);
-
- Py_DECREF(input);
-}
-
-void pointer_shutdown()
-{
- if (grabbed)
- grab_pointer(FALSE);
- clearall();
- g_datalist_clear(&bound_contexts);
-}
-