all repos — openbox @ d7a30f93b517ac76816d0acea92e9c56ad5d6594

openbox fork - make it a bit more like ryudo

so close to keybindings. wont link for now.
Dana Jansens danakj@orodu.net
commit

d7a30f93b517ac76816d0acea92e9c56ad5d6594

parent

db1fb534b8f5a1f19710ac77ef2ce85c4c1270ec

M otk/display.hhotk/display.hh

@@ -113,6 +113,11 @@ int keyboard_mode, Window confine_to, Cursor cursor,

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); }; }
M scripts/clientmotion.pyscripts/clientmotion.py

@@ -31,47 +31,32 @@ if client:

delete_Rect(i[3]) posqueue.remove(i) break - - # ButtonPressAction *a = 0; - # for (int i=0; i<BUTTONS; ++i) { - # if (_posqueue[i]->button == 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_do_motion(client, xroot, yroot): + global posqueue + dx = xroot - posqueue[0][1] + dy = yroot - posqueue[0][2] + 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 - 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 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)
M src/actions.ccsrc/actions.cc

@@ -9,6 +9,7 @@ #include "widget.hh"

#include "openbox.hh" #include "client.hh" #include "python.hh" +#include "bindings.hh" #include "otk/display.hh" #include <stdio.h>

@@ -41,6 +42,9 @@

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 @@ // run the RELEASE guile hook

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 @@ // run the CLICK guile hook

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 @@ // run the DOUBLECLICK guile hook

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::keyPressHandler(const XKeyEvent &e) { - OBWidget *w = dynamic_cast<OBWidget*> - (Openbox::instance->findHandler(e.window)); +// OBWidget *w = dynamic_cast<OBWidget*> +// (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); }
M src/bindings.ccsrc/bindings.cc

@@ -5,6 +5,11 @@ # include "../config.h"

#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() { + grabMouseOnAll(false); // ungrab everything + grabKeys(false); remove_all(); }

@@ -188,14 +195,17 @@ return false; // conflict

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 @@ }

return -1; // it just isn't in here } + bool OBBindings::add_key(const StringVect &keylist, int id) { BindingTree *tree;

@@ -274,9 +291,13 @@ destroytree(tree);

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); + }

@@ -351,5 +380,90 @@ _curpos = &_keytree; // back to the start

} } } + + +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; + } + } +} + }
M src/bindings.hhsrc/bindings.hh

@@ -6,10 +6,14 @@ /*! @file binding.hh

@brief I dunno.. some binding stuff? */ +#include "actions.hh" + #include <string> #include <vector> namespace ob { + +class OBClient; typedef struct Binding { unsigned int modifiers;

@@ -54,8 +58,11 @@

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 @@ // and hold state for which chain we're in etc. (it could have a timer

// 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); }; }
M src/openbox.ccsrc/openbox.cc

@@ -163,11 +163,10 @@ v.clear();

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
M src/python.ccsrc/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_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_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; }

@@ -242,5 +245,37 @@ Openbox::instance->bindings()->remove_all();

return true; } + +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); +} }
M src/python.hhsrc/python.hh

@@ -17,8 +17,16 @@

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_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);

@@ -48,6 +61,10 @@ void python_callback(OBActions::ActionType action, Window window,

OBWidget::WidgetType type, unsigned int state, 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); }
M src/screen.ccsrc/screen.cc

@@ -22,6 +22,7 @@ #include "screen.hh"

#include "client.hh" #include "openbox.hh" #include "frame.hh" +#include "bindings.hh" #include "otk/display.hh" static bool running;

@@ -400,12 +401,18 @@ // add to the screen's list

clients.push_back(client); // update the root properties setClientList(); + + // grab buttons/keys on the window + Openbox::instance->bindings()->grabMouse(true, client); } 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