From d7a30f93b517ac76816d0acea92e9c56ad5d6594 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 30 Dec 2002 22:27:46 +0000 Subject: [PATCH] so close to keybindings. wont link for now. --- otk/display.hh | 5 ++ scripts/clientmotion.py | 49 ++++++---------- src/actions.cc | 25 ++++++--- src/bindings.cc | 120 +++++++++++++++++++++++++++++++++++++++- src/bindings.hh | 16 +++++- src/openbox.cc | 3 +- src/python.cc | 41 +++++++++++++- src/python.hh | 17 ++++++ src/screen.cc | 7 +++ 9 files changed, 234 insertions(+), 49 deletions(-) diff --git a/otk/display.hh b/otk/display.hh index 7f5ab02d..9b3d6b31 100644 --- a/otk/display.hh +++ b/otk/display.hh @@ -113,6 +113,11 @@ public: bool allow_scroll_lock); static void ungrabButton(unsigned int button, unsigned int modifiers, Window grab_window); + static void grabKey(unsigned int keycode, unsigned int modifiers, + Window grab_window, bool owner_events, + int pointer_mode, int keyboard_mode, bool allow_scroll_lock); + static void ungrabKey(unsigned int button, unsigned int modifiers, + Window grab_window); }; } diff --git a/scripts/clientmotion.py b/scripts/clientmotion.py index 60de370b..4571c2fd 100644 --- a/scripts/clientmotion.py +++ b/scripts/clientmotion.py @@ -31,47 +31,32 @@ def def_motion_release(action, win, type, modifiers, button, xroot, yroot, delete_Rect(i[3]) posqueue.remove(i) break - - # ButtonPressAction *a = 0; - # for (int i=0; ibutton == e.button) - # a = _posqueue[i]; - # if (a) // found one and removed it - # _posqueue[i] = _posqueue[i+1]; - # } - # if (a) { // found one - # _posqueue[BUTTONS-1] = a; - # a->button = 0; - # } - - -def def_motion(action, win, type, modifiers, xroot, yroot, time): - client = Openbox_findClient(openbox, win) - if not client: return +def def_do_motion(client, xroot, yroot): global posqueue dx = xroot - posqueue[0][1] dy = yroot - posqueue[0][2] - # _dx = x_root - _posqueue[0]->pos.x(); - # _dy = y_root - _posqueue[0]->pos.y(); + area = posqueue[0][3] # A Rect + OBClient_move(client, Rect_x(area) + dx, Rect_y(area) + dy) +def def_do_resize(client, xroot, yroot, archor_corner): + global posqueue + dx = xroot - posqueue[0][1] + dy = yroot - posqueue[0][2] area = posqueue[0][3] # A Rect + OBClient_resize(client, anchor_corner, + Rect_width(area) - dx, Rect_height(area) + dy) + +def def_motion(action, win, type, modifiers, xroot, yroot, time): + client = Openbox_findClient(openbox, win) + if not client: return + if (type == Type_Titlebar) or (type == Type_Label): - OBClient_move(client, Rect_x(area) + dx, Rect_y(area) + dy) - # c->move(_posqueue[0]->clientarea.x() + _dx, - # _posqueue[0]->clientarea.y() + _dy); + def_do_move(client, xroot, yroot) elif type == Type_LeftGrip: - OBClient_resize(client, OBClient_TopRight, - Rect_width(area) - dx, Rect_height(area) + dy) - # c->resize(OBClient::TopRight, - # _posqueue[0]->clientarea.width() - _dx, - # _posqueue[0]->clientarea.height() + _dy); + def_do_resize(client, xroot, yroot, OBClient_TopRight) elif type == Type_RightGrip: - OBClient_resize(client, OBClient_TopLeft, - Rect_width(area) + dx, Rect_height(area) + dy) - # c->resize(OBClient::TopLeft, - # _posqueue[0]->clientarea.width() + _dx, - # _posqueue[0]->clientarea.height() + _dy); + def_do_resize(client, xroot, yroot, OBClient_TopLeft) def def_enter(action, win, type, modifiers): client = Openbox_findClient(openbox, win) diff --git a/src/actions.cc b/src/actions.cc index 716b033b..cbce4f12 100644 --- a/src/actions.cc +++ b/src/actions.cc @@ -9,6 +9,7 @@ #include "openbox.hh" #include "client.hh" #include "python.hh" +#include "bindings.hh" #include "otk/display.hh" #include @@ -41,6 +42,9 @@ void OBActions::buttonPressHandler(const XButtonEvent &e) python_callback(Action_ButtonPress, e.window, (OBWidget::WidgetType)(w ? w->type():-1), e.state, e.button, e.x_root, e.y_root, e.time); + if (w && w->type() == OBWidget::Type_Frame) // a binding + Openbox::instance->bindings()->fire(Action_ButtonPress, e.window, + e.state, e.button, e.time); if (_button) return; // won't count toward CLICK events @@ -59,6 +63,9 @@ void OBActions::buttonReleaseHandler(const XButtonEvent &e) python_callback(Action_ButtonRelease, e.window, (OBWidget::WidgetType)(w ? w->type():-1), e.state, e.button, e.x_root, e.y_root, e.time); + if (w && w->type() == OBWidget::Type_Frame) // a binding + Openbox::instance->bindings()->fire(Action_ButtonRelease, e.window, + e.state, e.button, e.time); // not for the button we're watching? if (_button != e.button) return; @@ -78,6 +85,9 @@ void OBActions::buttonReleaseHandler(const XButtonEvent &e) python_callback(Action_Click, e.window, (OBWidget::WidgetType)(w ? w->type():-1), e.state, e.button, e.time); + if (w && w->type() == OBWidget::Type_Frame) // a binding + Openbox::instance->bindings()->fire(Action_Click, e.window, + e.state, e.button, e.time); if (e.time - _release.time < DOUBLECLICKDELAY && _release.win == e.window && _release.button == e.button) { @@ -86,7 +96,10 @@ void OBActions::buttonReleaseHandler(const XButtonEvent &e) python_callback(Action_DoubleClick, e.window, (OBWidget::WidgetType)(w ? w->type():-1), e.state, e.button, e.time); - + if (w && w->type() == OBWidget::Type_Frame) // a binding + Openbox::instance->bindings()->fire(Action_DoubleClick, e.window, + e.state, e.button, e.time); + // reset so you cant triple click for 2 doubleclicks _release.win = 0; _release.button = 0; @@ -128,13 +141,11 @@ void OBActions::leaveHandler(const XCrossingEvent &e) void OBActions::keyPressHandler(const XKeyEvent &e) { - OBWidget *w = dynamic_cast - (Openbox::instance->findHandler(e.window)); +// OBWidget *w = dynamic_cast +// (Openbox::instance->findHandler(e.window)); - // run the KEY guile hook - python_callback(Action_KeyPress, e.window, - (OBWidget::WidgetType)(w ? w->type():-1), - e.state, e.keycode); + Openbox::instance->bindings()->fire(Action_KeyPress, e.window, + e.state, e.keycode, e.time); } diff --git a/src/bindings.cc b/src/bindings.cc index 1a102b54..6d1d420e 100644 --- a/src/bindings.cc +++ b/src/bindings.cc @@ -5,6 +5,11 @@ #endif #include "bindings.hh" +#include "screen.hh" +#include "openbox.hh" +#include "client.hh" +#include "frame.hh" +#include "python.hh" #include "otk/display.hh" extern "C" { @@ -170,6 +175,8 @@ OBBindings::OBBindings() OBBindings::~OBBindings() { + grabMouseOnAll(false); // ungrab everything + grabKeys(false); remove_all(); } @@ -188,14 +195,17 @@ bool OBBindings::add_mouse(const std::string &button, int id) p = p->next_sibling; newp = &p->next_sibling; } - display(); + + grabMouseOnAll(false); // ungrab everything + *newp = new BindingTree(id); - display(); (*newp)->text = button; (*newp)->chain = false; (*newp)->binding.key = n.binding.key; (*newp)->binding.modifiers = n.binding.modifiers; - + + grabMouseOnAll(true); + return true; } @@ -204,6 +214,12 @@ int OBBindings::remove_mouse(const std::string &button) { (void)button; assert(false); // XXX: function not implemented yet + + grabMouseOnAll(false); // ungrab everything + + // do shit... + + grabMouseOnAll(true); } @@ -261,6 +277,7 @@ int OBBindings::find_key(BindingTree *search) const { return -1; // it just isn't in here } + bool OBBindings::add_key(const StringVect &keylist, int id) { BindingTree *tree; @@ -274,9 +291,13 @@ bool OBBindings::add_key(const StringVect &keylist, int id) return false; } + grabKeys(false); + // assimilate this built tree into the main tree assimilate(tree); // assimilation destroys/uses the tree + grabKeys(true); + return true; } @@ -301,6 +322,14 @@ int OBBindings::remove_key(const StringVect &keylist) { (void)keylist; assert(false); // XXX: function not implemented yet + + grabKeys(false); + _curpos = &_keytree; + + // do shit here... + + grabKeys(true); + } @@ -352,4 +381,89 @@ void OBBindings::process(unsigned int modifiers, unsigned int key) } } + +void OBBindings::grabMouse(bool grab, const OBClient *client) +{ + BindingTree *p = _mousetree; + while (p) { + if (grab) + otk::OBDisplay::grabButton(p->binding.key, p->binding.modifiers, + client->frame->window(), false, + ButtonMotionMask | ButtonPressMask | + ButtonReleaseMask, GrabModeAsync, + GrabModeAsync, None, None, false); + else + otk::OBDisplay::ungrabButton(p->binding.key, p->binding.modifiers, + client->frame->window()); + p = p->next_sibling; + } +} + + +void OBBindings::grabMouseOnAll(bool grab) +{ + for (int i = 0; i < Openbox::instance->screenCount(); ++i) { + OBScreen *s = Openbox::instance->screen(i); + assert(s); + OBScreen::ClientList::iterator it, end = s->clients.end(); + for (it = s->clients.begin(); it != end; ++it) + grabMouse(grab, *it); + } +} + + +void OBBindings::grabKeys(bool grab) +{ + for (int i = 0; i < Openbox::instance->screenCount(); ++i) { + Window root = otk::OBDisplay::screenInfo(i)->rootWindow(); + + BindingTree *p = _curpos->first_child; + while (p) { + if (grab) + otk::OBDisplay::grabKey(p->binding.key, p->binding.modifiers, + root, false, GrabModeAsync, GrabModeAsync, + false); + else + otk::OBDisplay::ungrabKey(p->binding.key, p->binding.modifiers, + root); + p = p->next_sibling; + } + } +} + + +void OBBindings::fire(OBActions::ActionType type, Window window, + unsigned int modifiers, unsigned int key, Time time) +{ + if (type == OBActions::Action_KeyPress) { + BindingTree *p = _curpos->first_child; + while (p) { + if (p->binding.key == key && p->binding.modifiers == modifiers) { + if (p->chain) { + grabKeys(false); + _curpos = p; + grabKeys(true); + } else { + python_callback_binding(p->id, type, window, modifiers, key, time); + _curpos = &_keytree; + } + break; + } + p = p->next_sibling; + } + + assert(false); + } else { + BindingTree *p = _mousetree; + while (p) { + if (p->binding.key == key && p->binding.modifiers == modifiers) { + python_callback_binding(p->id, type, window, modifiers, key, time); + break; + } + p = p->next_sibling; + } + } +} + + } diff --git a/src/bindings.hh b/src/bindings.hh index 81b7075d..3fbf3b8d 100644 --- a/src/bindings.hh +++ b/src/bindings.hh @@ -6,11 +6,15 @@ @brief I dunno.. some binding stuff? */ +#include "actions.hh" + #include #include namespace ob { +class OBClient; + typedef struct Binding { unsigned int modifiers; unsigned int key; @@ -54,8 +58,11 @@ private: int find_key(BindingTree *search) const; bool translate(const std::string &str, Binding &b, bool askey) const; BindingTree *buildtree(const StringVect &keylist, int id) const; - void OBBindings::assimilate(BindingTree *node); - + void assimilate(BindingTree *node); + + void grabMouseOnAll(bool grab); + void grabKeys(bool grab); + public: //! Initializes an OBBinding object OBBindings(); @@ -109,6 +116,11 @@ public: // for reseting too...) void display(); + + void fire(OBActions::ActionType type, Window window, unsigned int modifiers, + unsigned int key, Time time); + + void grabMouse(bool grab, const OBClient *client); }; } diff --git a/src/openbox.cc b/src/openbox.cc index e7ffb76b..f5166ba7 100644 --- a/src/openbox.cc +++ b/src/openbox.cc @@ -163,11 +163,10 @@ Openbox::Openbox(int argc, char **argv) v.push_back("C-a"); _bindings->add_key(v, 3); - _bindings->add_mouse("A-1", 1); + _bindings->add_mouse("C-1", 1); printf("CHAINS:\n"); _bindings->display(); - ::exit(0); setMasterHandler(_actions); // set as the master event handler diff --git a/src/python.cc b/src/python.cc index ed71463c..a9b94811 100644 --- a/src/python.cc +++ b/src/python.cc @@ -16,7 +16,8 @@ static FunctionList mousefuncs; bool python_register(int action, PyObject *callback) { - if (action < 0 || action >= OBActions::NUM_ACTIONS) { + if (action < 0 || action >= OBActions::NUM_ACTIONS || + action == OBActions::Action_KeyPress) { PyErr_SetString(PyExc_AssertionError, "Invalid action type."); return false; } @@ -37,7 +38,8 @@ bool python_register(int action, PyObject *callback) bool python_preregister(int action, PyObject *callback) { - if (action < 0 || action >= OBActions::NUM_ACTIONS) { + if (action < 0 || action >= OBActions::NUM_ACTIONS || + action == OBActions::Action_KeyPress) { PyErr_SetString(PyExc_AssertionError, "Invalid action type."); return false; } @@ -58,7 +60,8 @@ bool python_preregister(int action, PyObject *callback) bool python_unregister(int action, PyObject *callback) { - if (action < 0 || action >= OBActions::NUM_ACTIONS) { + if (action < 0 || action >= OBActions::NUM_ACTIONS || + action == OBActions::Action_KeyPress) { PyErr_SetString(PyExc_AssertionError, "Invalid action type."); return false; } @@ -243,4 +246,36 @@ bool python_unbind_all() } +void python_callback_binding(int id, OBActions::ActionType action, + Window window, unsigned int state, + unsigned int keybutton, Time time) +{ + PyObject *func; + + assert(action >= 0 && action < OBActions::NUM_ACTIONS); + + if (action == OBActions::Action_KeyPress) + func = keyfuncs[id]; + else + func = mousefuncs[id]; + + if (!func) return; + + PyObject *arglist; + PyObject *result; + + arglist = Py_BuildValue("iliil", action, window, state, keybutton, time); + + // call the callback + result = PyEval_CallObject(func, arglist); + if (result) { + Py_DECREF(result); + } else { + // an exception occured in the script, display it + PyErr_Print(); + } + + Py_DECREF(arglist); +} + } diff --git a/src/python.hh b/src/python.hh index 2332add0..b868c472 100644 --- a/src/python.hh +++ b/src/python.hh @@ -17,8 +17,16 @@ extern "C" { namespace ob { //! Add a python callback funtion to the back of the hook list +/*! + Registering functions for KeyPress events is pointless. Use python_bind_key + instead to do this. +*/ bool python_register(int action, PyObject *callback); //! Add a python callback funtion to the front of the hook list +/*! + Registering functions for KeyPress events is pointless. Use python_bind_key + instead to do this. +*/ bool python_preregister(int action, PyObject *callback); //! Remove a python callback function from the hook list bool python_unregister(int action, PyObject *callback); @@ -37,6 +45,11 @@ bool python_bind_key(PyObject *keylist, PyObject *callback); bool python_unbind_key(PyObject *keylist); //! Adds a mouse binding +/*! + Bindings do not generate motion events. You can only handle motion events by + using register to set a function for all motion events. Bindings do generate + ButtonPress, ButtonRelease, Click, and DoubleClick events. +*/ bool python_bind_mouse(const std::string &button, PyObject *callback); bool python_unbind_mouse(const std::string &button); @@ -49,6 +62,10 @@ void python_callback(OBActions::ActionType action, Window window, long d1 = LONG_MIN, long d2 = LONG_MIN, long d3 = LONG_MIN, long d4 = LONG_MIN); +void python_callback_binding(int id, OBActions::ActionType action, + Window window, unsigned int state, + unsigned int keybutton, Time time); + } #endif // __python_hh diff --git a/src/screen.cc b/src/screen.cc index d61b501d..e4518fba 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -22,6 +22,7 @@ extern "C" { #include "client.hh" #include "openbox.hh" #include "frame.hh" +#include "bindings.hh" #include "otk/display.hh" static bool running; @@ -400,6 +401,9 @@ void OBScreen::manageWindow(Window window) clients.push_back(client); // update the root properties setClientList(); + + // grab buttons/keys on the window + Openbox::instance->bindings()->grabMouse(true, client); } @@ -407,6 +411,9 @@ void OBScreen::unmanageWindow(OBClient *client) { OBFrame *frame = client->frame; + // ungrab buttons/keys on the window + Openbox::instance->bindings()->grabMouse(false, client); + // XXX: pass around focus if this window was focused // remove from the wm's map -- 2.39.2