all repos — openbox @ 2ae2b257d39ea62640c2590f794e4275c6db1cd4

openbox fork - make it a bit more like ryudo

might not compile... ob uses its own widgets now, which subclass only the base otk widget. working on compressing focus events and handling them etc.
Dana Jansens danakj@orodu.net
commit

2ae2b257d39ea62640c2590f794e4275c6db1cd4

parent

3c61812e588fb3c34d0713d7f82ccbf21091f032

M otk/eventdispatcher.ccotk/eventdispatcher.cc

@@ -11,8 +11,10 @@

namespace otk { OtkEventDispatcher::OtkEventDispatcher() - : _fallback(0), _master(0) + : _fallback(0), _master(0), _focus(None) { + _focus_e.xfocus.mode = NotifyNormal; + _focus_e.xfocus.detail = NotifyNonlinear; } OtkEventDispatcher::~OtkEventDispatcher()

@@ -36,9 +38,10 @@ }

void OtkEventDispatcher::dispatchEvents(void) { + OtkEventMap::iterator it; XEvent e; - OtkEventHandler *handler; - OtkEventMap::iterator it; + Window focus = _focus; + Window unfocus = None; while (XPending(OBDisplay::display)) { XNextEvent(OBDisplay::display, &e);

@@ -70,23 +73,58 @@

XConfigureWindow(otk::OBDisplay::display, e.xconfigurerequest.window, e.xconfigurerequest.value_mask, &xwc); } + // madly compress all focus events + } else if (e.type == FocusIn) { + // any other types are not ones we're interested in + if (e.xfocus.detail == NotifyNonlinear) { + if (e.xfocus.window != focus) { + unfocus = focus; + focus = e.xfocus.window; + } + } + } else if (e.type == FocusOut) { + // any other types are not ones we're interested in + if (e.xfocus.detail == NotifyNonlinear) { + if (e.xfocus.window == focus) { + unfocus = focus; + focus = None; + } + } } else { // normal events - - it = _map.find(e.xany.window); - - if (it != _map.end()) - handler = it->second; - else - handler = _fallback; - - if (handler) - handler->handle(e); + dispatch(e); } + } - if (_master) - _master->handle(e); + if (focus != _focus) { + _focus_e.xfocus.type = FocusIn; + _focus_e.xfocus.window = focus; + dispatch(_focus_e); + _focus = focus; } + if (unfocus != None) { + _focus_e.xfocus.type = FocusOut; + _focus_e.xfocus.window = unfocus; + dispatch(_focus_e); + } +} + +void OtkEventDispatcher::dispatch(const XEvent &e) { + OtkEventHandler *handler; + OtkEventMap::iterator it; + + it = _map.find(e.xany.window); + + if (it != _map.end()) + handler = it->second; + else + handler = _fallback; + + if (handler) + handler->handle(e); + + if (master) + master->handle(e); } OtkEventHandler *OtkEventDispatcher::findHandler(Window win)
M otk/eventdispatcher.hhotk/eventdispatcher.hh

@@ -36,9 +36,12 @@ private:

OtkEventMap _map; OtkEventHandler *_fallback; OtkEventHandler *_master; + XEvent _focus_e; //! The time at which the last XEvent with a time was received Time _lasttime; // XXX: store this! also provide an accessor! + + void dispatch(const XEvent &e); }; }
M otk/focuslabel.ccotk/focuslabel.cc

@@ -36,7 +36,7 @@

void OtkFocusLabel::update(void) { if (_dirty) { - const BFont &ft = style()->getFont(); + const BFont *ft = style()->getFont(); BColor *text_color = (isFocused() ? style()->getTextFocus() : style()->getTextUnfocus()); unsigned int sidemargin = style()->getBevelWidth() * 2;

@@ -54,7 +54,7 @@ int length;

do { t.resize(text_len); - length = ft.measureString(t); + length = ft->measureString(t); } while (length > max_length && text_len-- > 0); // justify the text

@@ -72,7 +72,7 @@ }

OtkFocusWidget::update(); - ft.drawString(_xftdraw, x, 0, *text_color, t); + ft->drawString(_xftdraw, x, 0, *text_color, t); } else OtkFocusWidget::update(); }
M otk/focuswidget.ccotk/focuswidget.cc

@@ -23,43 +23,30 @@

#include <stdio.h> void OtkFocusWidget::focus(void) { - if (!isVisible() || _focused) + if (_focused) return; - printf("FOCUS\n"); OtkWidget::focus(); if (_focus_bcolor) OtkWidget::setBorderColor(_focus_bcolor); OtkWidget::setTexture(_focus_texture); - OtkWidget::update(); + update(); } void OtkFocusWidget::unfocus(void) { - if (!isVisible() || !_focused) + if (!_focused) return; - printf("UNFOCUS\n"); OtkWidget::unfocus(); if (_unfocus_bcolor) OtkWidget::setBorderColor(_unfocus_bcolor); OtkWidget::setTexture(_unfocus_texture); - OtkWidget::update(); - - OtkWidget::OtkWidgetList children = OtkWidget::children(); - - OtkWidget::OtkWidgetList::iterator it = children.begin(), - end = children.end(); - - OtkFocusWidget *tmp = 0; - for (; it != end; ++it) { - tmp = dynamic_cast<OtkFocusWidget*>(*it); - if (tmp) tmp->unfocus(); - } + update(); } void OtkFocusWidget::setTexture(BTexture *texture)
M otk/label.ccotk/label.cc

@@ -32,7 +32,7 @@

void OtkLabel::update(void) { if (_dirty) { - const BFont &ft = style()->getFont(); + const BFont *ft = style()->getFont(); unsigned int sidemargin = style()->getBevelWidth() * 2; std::string t = _text; // the actual text to draw

@@ -48,7 +48,7 @@ int length;

do { t.resize(text_len); - length = ft.measureString(t); + length = ft->measureString(t); } while (length > max_length && text_len-- > 0); // justify the text

@@ -66,7 +66,7 @@ }

OtkWidget::update(); - ft.drawString(_xftdraw, x, 0, *style()->getTextUnfocus(), t); + ft->drawString(_xftdraw, x, 0, *style()->getTextUnfocus(), t); } else OtkWidget::update(); }
M otk/otk_wrap.ccotk/otk_wrap.cc

@@ -1001,42 +1001,6 @@ return NULL;

} -static PyObject *_wrap_OtkEventDispatcher_setMasterHandler(PyObject *self, PyObject *args) { - PyObject *resultobj; - otk::OtkEventDispatcher *arg1 = (otk::OtkEventDispatcher *) 0 ; - otk::OtkEventHandler *arg2 = (otk::OtkEventHandler *) 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - - if(!PyArg_ParseTuple(args,(char *)"OO:OtkEventDispatcher_setMasterHandler",&obj0,&obj1)) goto fail; - if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_otk__OtkEventDispatcher,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; - if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_otk__OtkEventHandler,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; - (arg1)->setMasterHandler(arg2); - - Py_INCREF(Py_None); resultobj = Py_None; - return resultobj; - fail: - return NULL; -} - - -static PyObject *_wrap_OtkEventDispatcher_getMasterHandler(PyObject *self, PyObject *args) { - PyObject *resultobj; - otk::OtkEventDispatcher *arg1 = (otk::OtkEventDispatcher *) 0 ; - otk::OtkEventHandler *result; - PyObject * obj0 = 0 ; - - if(!PyArg_ParseTuple(args,(char *)"O:OtkEventDispatcher_getMasterHandler",&obj0)) goto fail; - if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_otk__OtkEventDispatcher,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; - result = (otk::OtkEventHandler *)((otk::OtkEventDispatcher const *)arg1)->getMasterHandler(); - - resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_otk__OtkEventHandler, 0); - return resultobj; - fail: - return NULL; -} - - static PyObject *_wrap_OtkEventDispatcher_findHandler(PyObject *self, PyObject *args) { PyObject *resultobj; otk::OtkEventDispatcher *arg1 = (otk::OtkEventDispatcher *) 0 ;

@@ -11327,10 +11291,7 @@ PyObject * obj0 = 0 ;

if(!PyArg_ParseTuple(args,(char *)"O:Style_getFont",&obj0)) goto fail; if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_otk__Style,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; - { - otk::BFont const &_result_ref = ((otk::Style const *)arg1)->getFont(); - result = (otk::BFont *) &_result_ref; - } + result = (otk::BFont *)((otk::Style const *)arg1)->getFont(); resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_otk__BFont, 0); return resultobj;

@@ -12745,8 +12706,6 @@ { (char *)"OtkEventDispatcher_clearHandler", _wrap_OtkEventDispatcher_clearHandler, METH_VARARGS },

{ (char *)"OtkEventDispatcher_dispatchEvents", _wrap_OtkEventDispatcher_dispatchEvents, METH_VARARGS }, { (char *)"OtkEventDispatcher_setFallbackHandler", _wrap_OtkEventDispatcher_setFallbackHandler, METH_VARARGS }, { (char *)"OtkEventDispatcher_getFallbackHandler", _wrap_OtkEventDispatcher_getFallbackHandler, METH_VARARGS }, - { (char *)"OtkEventDispatcher_setMasterHandler", _wrap_OtkEventDispatcher_setMasterHandler, METH_VARARGS }, - { (char *)"OtkEventDispatcher_getMasterHandler", _wrap_OtkEventDispatcher_getMasterHandler, METH_VARARGS }, { (char *)"OtkEventDispatcher_findHandler", _wrap_OtkEventDispatcher_findHandler, METH_VARARGS }, { (char *)"OtkEventDispatcher_swigregister", OtkEventDispatcher_swigregister, METH_VARARGS }, { (char *)"OtkEventHandler_handle", _wrap_OtkEventHandler_handle, METH_VARARGS },
M otk/style.hhotk/style.hh

@@ -16,6 +16,7 @@

struct PixmapMask { Pixmap mask; unsigned int w, h; + PixmapMask() { mask = None; w = h = 0; } }; class Style {

@@ -114,7 +115,7 @@ inline unsigned int getBevelWidth(void) const { return bevel_width; }

inline unsigned int getFrameWidth(void) const { return frame_width; } inline unsigned int getBorderWidth(void) const { return border_width; } - inline const BFont &getFont() const { return *font; } + inline const BFont *getFont() const { return font; } inline void setShadowFonts(bool fonts) { shadow_fonts = fonts; } inline bool hasShadowFonts(void) const { return shadow_fonts; }
M otk/widget.ccotk/widget.cc

@@ -187,12 +187,6 @@ }

void OtkWidget::focus(void) { -/* if (! _visible) - return; - - XSetInputFocus(otk::OBDisplay::display, _window, RevertToPointerRoot, - CurrentTime);*/ - _focused = true; OtkWidget::OtkWidgetList::iterator it = _children.begin(),

@@ -253,7 +247,7 @@

void OtkWidget::render(void) { if (!_texture) return; - + _bg_pixmap = _texture->render(_rect.width(), _rect.height(), _bg_pixmap); if (_bg_pixmap)

@@ -392,8 +386,8 @@

void OtkWidget::update(void) { if (_dirty) { - if (! _unmanaged) - adjust(); + if (!_unmanaged) + adjust(); render(); XClearWindow(OBDisplay::display, _window); }

@@ -444,15 +438,6 @@ {

assert(style); _style = style; _dirty = true; - - // reset textures/colors - if (_focused) { - unfocus(); - focus(); - } else { - focus(); - unfocus(); - } OtkWidgetList::iterator it, end = _children.end(); for (it = _children.begin(); it != end; ++it)
M scripts/clicks.pyscripts/clicks.py

@@ -18,11 +18,15 @@ print "OBClient_shade(client)"

elif button == Button5: print "OBClient_unshade(client)" -def def_click_model(action, win, type, modifiers, button, time): +def def_press_model(action, win, type, modifiers, button, xroot, yroot, time): if button != Button1: return client = Openbox_findClient(openbox, win) - if not client: return - print "OBClient_focus(client)" + if not client or (type == Type_StickyButton or + type == Type_IconifyButton or + type == Type_MaximizeButton or + type == Type_CloseButton): + return + OBClient_focus(client) print "OBClient_raise(client)" def def_click_root(action, win, type, modifiers, button, time):

@@ -46,7 +50,7 @@ if button == Button1 and (type == Type_Titlebar or type == Type_Label):

print "OBClient_toggleshade(client)" -register(Action_Click, def_click_model) +preregister(Action_ButtonPress, def_press_model) register(Action_Click, def_click_client) register(Action_Click, def_click_root) register(Action_DoubleClick, def_doubleclick_client)
M src/backgroundwidget.ccsrc/backgroundwidget.cc

@@ -10,7 +10,7 @@ namespace ob {

OBBackgroundWidget::OBBackgroundWidget(otk::OtkWidget *parent, OBWidget::WidgetType type) - : otk::OtkFocusWidget(parent), + : otk::OtkWidget(parent), OBWidget(type) { }

@@ -21,37 +21,67 @@ {

} -void OBBackgroundWidget::setStyle(otk::Style *style) +void OBBackgroundWidget::setTextures() { switch (type()) { case Type_Titlebar: - setTexture(style->getTitleFocus()); - setUnfocusTexture(style->getTitleUnfocus()); - setBorderColor(style->getBorderColor()); + if (_focused) + setTexture(_style->getTitleFocus()); + else + setTexture(_style->getTitleUnfocus()); break; case Type_Handle: - setTexture(style->getHandleFocus()); - setUnfocusTexture(style->getHandleUnfocus()); - setBorderColor(style->getBorderColor()); + if (_focused) + setTexture(_style->getHandleFocus()); + else + setTexture(_style->getHandleUnfocus()); break; case Type_Plate: - setBorderColor(&style->getFrameFocus()->color()); - setUnfocusBorderColor(&style->getFrameUnfocus()->color()); + if (_focused) + setBorderColor(&_style->getFrameFocus()->color()); + else + setBorderColor(&_style->getFrameUnfocus()->color()); break; default: assert(false); // there's no other background widgets! } +} + - otk::OtkFocusWidget::setStyle(style); +void OBBackgroundWidget::setStyle(otk::Style *style) +{ + OtkWidget::setStyle(style); + setTextures(); + switch (type()) { + case Type_Titlebar: + case Type_Handle: + setBorderColor(_style->getBorderColor()); + break; + case Type_Plate: + break; + default: + assert(false); // there's no other background widgets! + } } -void OBBackgroundWidget::adjust() +void OBBackgroundWidget::focus() +{ + otk::OtkWidget::focus(); + setTextures(); +} + + +void OBBackgroundWidget::unfocus() { - otk::OtkFocusWidget::adjust(); + otk::OtkWidget::unfocus(); + setTextures(); +} + +void OBBackgroundWidget::adjust() +{ // XXX: adjust shit } - }
M src/backgroundwidget.hhsrc/backgroundwidget.hh

@@ -2,14 +2,15 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-

#ifndef __obbackgroundwidget_hh #define __obbackgroundwidget_hh -#include "otk/focuswidget.hh" +#include "otk/widget.hh" #include "widget.hh" namespace ob { -class OBBackgroundWidget : public otk::OtkFocusWidget, public OBWidget +class OBBackgroundWidget : public otk::OtkWidget, public OBWidget { private: + void setTextures(); public: OBBackgroundWidget(otk::OtkWidget *parent, OBWidget::WidgetType type);

@@ -18,6 +19,9 @@

virtual void setStyle(otk::Style *style); virtual void adjust(); + + virtual void focus(); + virtual void unfocus(); }; }
M src/buttonwidget.ccsrc/buttonwidget.cc

@@ -10,8 +10,10 @@ namespace ob {

OBButtonWidget::OBButtonWidget(otk::OtkWidget *parent, OBWidget::WidgetType type) - : otk::OtkButton(parent), - OBWidget(type) + : otk::OtkWidget(parent), + OBWidget(type), + _pressed(false), + _button(0) { }

@@ -21,36 +23,98 @@ {

} +void OBButtonWidget::setTextures() +{ + switch (type()) { + case Type_LeftGrip: + case Type_RightGrip: + if (_focused) + setTexture(_style->getGripFocus()); + else + setTexture(_style->getGripUnfocus()); + break; + case Type_StickyButton: + case Type_CloseButton: + case Type_MaximizeButton: + case Type_IconifyButton: + if (_pressed) { + if (_focused) + setTexture(_style->getButtonPressedFocus()); + else + setTexture(_style->getButtonPressedUnfocus()); + } else { + if (_focused) + setTexture(_style->getButtonFocus()); + else + setTexture(_style->getButtonUnfocus()); + } + break; + default: + assert(false); // there's no other button widgets! + } +} + + void OBButtonWidget::setStyle(otk::Style *style) { - otk::OtkButton::setStyle(style); + otk::OtkWidget::setStyle(style); + setTextures(); switch (type()) { case Type_LeftGrip: case Type_RightGrip: - setTexture(style->getGripFocus()); - setUnfocusTexture(style->getGripUnfocus()); - setPressedFocusTexture(style->getGripFocus()); - setPressedUnfocusTexture(style->getGripUnfocus()); - setTexture(style->getGripFocus()); - setUnfocusTexture(style->getGripUnfocus()); - setPressedFocusTexture(style->getGripFocus()); - setPressedUnfocusTexture(style->getGripUnfocus()); setBorderColor(_style->getBorderColor()); - setUnfocusBorderColor(style->getBorderColor()); break; - default: + case Type_StickyButton: + case Type_CloseButton: + case Type_MaximizeButton: + case Type_IconifyButton: break; + default: + assert(false); // there's no other button widgets! } +} + + +void OBButtonWidget::focus() +{ + otk::OtkWidget::focus(); + setTextures(); +} + + +void OBButtonWidget::unfocus() +{ + otk::OtkWidget::unfocus(); + setTextures(); } void OBButtonWidget::adjust() { - otk::OtkButton::adjust(); + // XXX: adjust shit +} - // XXX: adjust shit + +void OBButtonWidget::buttonPressHandler(const XButtonEvent &e) +{ + OtkWidget::buttonPressHandler(e); + if (_button) return; + _button = e.button; + _pressed = true; + setTextures(); + update(); } + +void OBButtonWidget::buttonReleaseHandler(const XButtonEvent &e) +{ + OtkWidget::buttonPressHandler(e); + if (e.button != _button) return; + _button = 0; + _pressed = false; + setTextures(); + update(); +} }
M src/buttonwidget.hhsrc/buttonwidget.hh

@@ -2,14 +2,17 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-

#ifndef __obbuttonwidget_hh #define __obbuttonwidget_hh -#include "otk/button.hh" +#include "otk/widget.hh" #include "widget.hh" namespace ob { -class OBButtonWidget : public otk::OtkButton, public OBWidget +class OBButtonWidget : public otk::OtkWidget, public OBWidget { private: + void setTextures(); + bool _pressed; + unsigned int _button; public: OBButtonWidget(otk::OtkWidget *parent, OBWidget::WidgetType type);

@@ -18,6 +21,12 @@

virtual void setStyle(otk::Style *style); virtual void adjust(); + + virtual void focus(); + virtual void unfocus(); + + virtual void buttonPressHandler(const XButtonEvent &e); + virtual void buttonReleaseHandler(const XButtonEvent &e); }; }
M src/client.ccsrc/client.cc

@@ -40,6 +40,8 @@ // the state is kinda assumed to be normal. is this right? XXX

_wmstate = NormalState; // no default decors or functions, each has to be enabled _decorations = _functions = 0; + // start unfocused + _focused = false; getArea(); getDesktop();

@@ -460,6 +462,9 @@ }

if (_title.empty()) _title = _("Unnamed Window"); + + if (frame) + frame->setTitle(_title); }

@@ -856,6 +861,37 @@ ce.xclient.data.l[2] = 0l;

ce.xclient.data.l[3] = 0l; ce.xclient.data.l[4] = 0l; XSendEvent(otk::OBDisplay::display, _window, False, NoEventMask, &ce); +} + + +bool OBClient::focus() +{ + if (!_can_focus) return false; + + XSetInputFocus(otk::OBDisplay::display, _window, RevertToNone, CurrentTime); + return true; +} + + +void OBClient::focusHandler(const XFocusChangeEvent &) +{ + frame->focus(); + _focused = true; + + Openbox::instance->setFocusedClient(this); +} + + +void OBClient::unfocusHandler(const XFocusChangeEvent &) +{ + frame->unfocus(); + _focused = false; + + if (Openbox::instance->focusedClient() == this) { + printf("UNFOCUSING\n"); + Openbox::instance->setFocusedClient(0); + } else + printf("UNFOCUSED ALREADY COULDNT UNFOCUS\n"); }
M src/client.hhsrc/client.hh

@@ -234,6 +234,8 @@ //! Urgency flag

bool _urgent; //! Notify the window when it receives focus? bool _focus_notify; + //! Does the client window have the input focus? + bool _focused; //! The window uses shape extension to be non-rectangular? bool _shaped;

@@ -431,7 +433,12 @@ void resize(Corner anchor, int x, int y);

//! Request the client to close its window. void close(); + + //! Attempt to focus the client window + bool focus(); + virtual void focusHandler(const XFocusChangeEvent &e); + virtual void unfocusHandler(const XFocusChangeEvent &e); virtual void propertyHandler(const XPropertyEvent &e); virtual void clientMessageHandler(const XClientMessageEvent &e); virtual void shapeHandler(const XShapeEvent &e);
M src/frame.ccsrc/frame.cc

@@ -43,31 +43,15 @@ assert(style);

XSelectInput(otk::OBDisplay::display, window(), OBFrame::event_mask); - unmanaged(); - _titlebar.unmanaged(); - _button_close.unmanaged(); - _button_iconify.unmanaged(); - _button_max.unmanaged(); - _button_stick.unmanaged(); - _label.unmanaged(); - _handle.unmanaged(); - _grip_left.unmanaged(); - _grip_right.unmanaged(); - _plate.unmanaged(); - _grip_left.setCursor(Openbox::instance->cursors().ll_angle); _grip_right.setCursor(Openbox::instance->cursors().lr_angle); - _button_close.setText("X"); - _button_iconify.setText("I"); - _button_max.setText("M"); - _button_stick.setText("S"); _label.setText(_client->title()); _style = 0; setStyle(style); - //XXX: uncomment me unfocus(); // stuff starts out focused in otk + otk::OtkWidget::unfocus(); // stuff starts out appearing focused in otk _plate.show(); // the other stuff is shown based on decor settings

@@ -81,6 +65,13 @@ releaseClient(false);

} +void OBFrame::setTitle(const std::string &text) +{ + _label.setText(text); + _label.update(); +} + + void OBFrame::setStyle(otk::Style *style) { assert(style);

@@ -97,9 +88,7 @@ }

_style = style; - // XXX: change when focus changes! - XSetWindowBorder(otk::OBDisplay::display, window(), - _style->getBorderColor()->pixel()); + setBorderColor(_style->getBorderColor()); // if !replace, then adjust() will get called after the client is grabbed! if (replace) {

@@ -107,6 +96,25 @@ // size/position everything

adjustSize(); adjustPosition(); } +} + + +void OBFrame::focus() +{ + otk::OtkWidget::focus(); + update(); +} + + +void OBFrame::unfocus() +{ + otk::OtkWidget::unfocus(); + update(); +} + + +void OBFrame::adjust() +{ }

@@ -142,13 +150,13 @@ // set the titlebar size

_titlebar.setGeometry(-bwidth, -bwidth, width, - (_style->getFont().height() + + (_style->getFont()->height() + _style->getBevelWidth() * 2)); _innersize.top += _titlebar.height() + bwidth; // set the label size _label.setGeometry(0, _style->getBevelWidth(), - width, _style->getFont().height()); + width, _style->getFont()->height()); // set the buttons sizes if (_decorations & OBClient::Decor_Iconify) _button_iconify.setGeometry(0, _style->getBevelWidth() + 1,
M src/frame.hhsrc/frame.hh

@@ -93,6 +93,15 @@

//! Set the style to decorate the frame with virtual void setStyle(otk::Style *style); + //! Realign children + virtual void adjust(); + //! Displays focused decorations + virtual void focus(); + //! Displays unfocused decorations + virtual void unfocus(); + + void setTitle(const std::string &text); + //! Update the frame's size to match the client void adjustSize(); //! Update the frame's position to match the client
M src/labelwidget.ccsrc/labelwidget.cc

@@ -4,37 +4,115 @@ #ifdef HAVE_CONFIG_H

# include "../config.h" #endif +#include "otk/screeninfo.hh" +#include "otk/display.hh" #include "labelwidget.hh" namespace ob { OBLabelWidget::OBLabelWidget(otk::OtkWidget *parent, OBWidget::WidgetType type) - : otk::OtkFocusLabel(parent), + : otk::OtkWidget(parent), OBWidget(type) { + const otk::ScreenInfo *info = otk::OBDisplay::screenInfo(_screen); + _xftdraw = XftDrawCreate(otk::OBDisplay::display, _window, info->visual(), + info->colormap()); } OBLabelWidget::~OBLabelWidget() { + XftDrawDestroy(_xftdraw); +} + + +void OBLabelWidget::setText(const std::string &text) +{ + _text = text; + _dirty = true; +} + + +void OBLabelWidget::setTextures() +{ + if (_focused) { + setTexture(_style->getLabelFocus()); + _text_color = _style->getTextFocus(); + } else { + setTexture(_style->getLabelUnfocus()); + _text_color = _style->getTextUnfocus(); + } } void OBLabelWidget::setStyle(otk::Style *style) { - setTexture(style->getLabelFocus()); - setUnfocusTexture(style->getLabelUnfocus()); + OtkWidget::setStyle(style); + setTextures(); + _font = style->getFont(); + assert(_font); + _sidemargin = style->getBevelWidth() * 2; + _justify = style->textJustify(); +} + - otk::OtkFocusLabel::setStyle(style); +void OBLabelWidget::focus() +{ + otk::OtkWidget::focus(); + setTextures(); } -void OBLabelWidget::adjust() +void OBLabelWidget::unfocus() { - otk::OtkFocusLabel::adjust(); + otk::OtkWidget::unfocus(); + setTextures(); +} - // XXX: adjust shit + +void OBLabelWidget::update() +{ + if (_dirty) { + std::string t = _text; + int x = _sidemargin; // x coord for the text + + // find a string that will fit inside the area for text + int max_length = width() - _sidemargin * 2; + if (max_length <= 0) { + t = ""; // can't fit anything + } else { + size_t text_len = t.size(); + int length; + + do { + t.resize(text_len); + length = _font->measureString(t); + } while (length > max_length && text_len-- > 0); + + // justify the text + switch (_justify) { + case otk::Style::RightJustify: + x += max_length - length; + break; + case otk::Style::CenterJustify: + x += (max_length - length) / 2; + break; + case otk::Style::LeftJustify: + break; + } + } + + OtkWidget::update(); + + _font->drawString(_xftdraw, x, 0, *_text_color, t); + } else + OtkWidget::update(); } + +void OBLabelWidget::adjust() +{ + // XXX: adjust shit +} }
M src/labelwidget.hhsrc/labelwidget.hh

@@ -2,14 +2,24 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-

#ifndef __oblabelwidget_hh #define __oblabelwidget_hh -#include "otk/focuslabel.hh" +#include "otk/widget.hh" +#include "otk/font.hh" +#include "otk/style.hh" #include "widget.hh" namespace ob { -class OBLabelWidget : public otk::OtkFocusLabel, public OBWidget +class OBLabelWidget : public otk::OtkWidget, public OBWidget { private: + void setTextures(); + const otk::BFont *_font; + otk::BColor *_text_color; + int _sidemargin; + otk::Style::TextJustify _justify; + std::string _text; + //! Object used by Xft to render to the drawable + XftDraw *_xftdraw; public: OBLabelWidget(otk::OtkWidget *parent, OBWidget::WidgetType type);

@@ -18,6 +28,14 @@

virtual void setStyle(otk::Style *style); virtual void adjust(); + + virtual void focus(); + virtual void unfocus(); + + virtual void update(); + + inline const std::string &text() const { return _text; } + void setText(const std::string &text); }; }
M src/main.ccsrc/main.cc

@@ -13,32 +13,20 @@ #ifdef HAVE_LOCALE_H

# include <locale.h> #endif // HAVE_LOCALE_H -#include <guile/gh.h> - #include "gettext.h" } #include <string> using std::string; -#include "blackbox.hh" #include "openbox.hh" -void main_prog(int argc, char **argv) { - ob::Openbox openbox(argc, argv); - //ob::Blackbox blackbox(argc, argv, 0); - - //Blackbox blackbox(argv, session_display, rc_file); - openbox.eventLoop(); -} - int main(int argc, char **argv) { // initialize the locale setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - // start up guile - //gh_enter(argc, argv, main_prog); - main_prog(argc, argv); + ob::Openbox openbox(argc, argv); + openbox.eventLoop(); }
M src/openbox.ccsrc/openbox.cc

@@ -108,6 +108,8 @@ _argv0 = argv[0];

_doshutdown = false; _rcfilepath = otk::expandTilde("~/.openbox/rc3"); _scriptfilepath = otk::expandTilde("~/.openbox/user.py"); + _focused_client = 0; + _sync = false; parseCommandLine(argc, argv);

@@ -128,7 +130,9 @@

// open the X display (and gets some info about it, and its screens) otk::OBDisplay::initialize(_displayreq); assert(otk::OBDisplay::display); - + + XSynchronize(otk::OBDisplay::display, _sync); + // set up the signal handler action.sa_handler = Openbox::signalHandler; action.sa_mask = sigset_t();

@@ -181,6 +185,10 @@ printf(_("No screens were found without a window manager. Exiting.\n"));

::exit(1); } + // set up input focus + _focused_screen = _screens[0]; + setFocusedClient(0); + _state = State_Normal; // done starting }

@@ -223,6 +231,8 @@ if (++i >= argc)

err = true; else _scriptfilepath = argv[i]; + } else if (arg == "-sync") { + _sync = true; } else if (arg == "-version") { showVersion(); ::exit(0);

@@ -319,6 +329,19 @@ if (it != _clients.end())

return it->second; else return (OBClient*) 0; +} + + +void Openbox::setFocusedClient(OBClient *c) +{ + _focused_client = c; + if (c) { + _focused_screen = _screens[c->screen()]; + } else { + assert(_focused_screen); + XSetInputFocus(otk::OBDisplay::display, _focused_screen->focuswindow(), + RevertToNone, CurrentTime); + } } }
M src/openbox.hhsrc/openbox.hh

@@ -121,6 +121,9 @@

//! The action interface through which all user-available actions occur OBActions *_actions; + //! Run the application in synchronous mode? (for debugging) + bool _sync; + //! The running state of the window manager RunState _state;

@@ -133,6 +136,19 @@

//! The configuration of the application. TEMPORARY otk::Configuration _config; + //! The client with input focus + /*! + Updated by the clients themselves. + */ + OBClient *_focused_client; + + //! The screen with input focus + /*! + Updated by the clients when they update the Openbox::focused_client + property. + */ + OBScreen *_focused_screen; + //! Parses the command line used when executing this application void parseCommandLine(int argv, char **argv); //! Displays the version string to stdout

@@ -203,6 +219,18 @@

//! Finds an OBClient based on its window id OBClient *findClient(Window window); + //! The client with input focus + inline OBClient *focusedClient() { return _focused_client; } + + //! Change the client which has focus. + /*! + This is called by the clients themselves when their focus state changes. + */ + void setFocusedClient(OBClient *c); + + //! The screen with input focus + inline OBScreen *focusedScreen() { return _focused_screen; } + //! Requests that the window manager exit /*! Causes the Openbox::eventLoop function to stop looping, so that the window
M src/openbox.isrc/openbox.i

@@ -53,6 +53,7 @@ };

%} %ignore ob::python_callback; %rename(register) ob::python_register; +%rename(preregister) ob::python_preregister; %rename(unregister) ob::python_unregister; %ignore ob::OBScreen::clients;
M src/openbox_wrap.ccsrc/openbox_wrap.cc

@@ -658,17 +658,18 @@ #define SWIGTYPE_p_XConfigureRequestEvent swig_types[9]

#define SWIGTYPE_p_otk__OtkEventHandler swig_types[10] #define SWIGTYPE_p_otk__Rect swig_types[11] #define SWIGTYPE_p_ob__OBWidget swig_types[12] -#define SWIGTYPE_p_XClientMessageEvent swig_types[13] -#define SWIGTYPE_p_otk__OBProperty swig_types[14] -#define SWIGTYPE_p_otk__OtkEventDispatcher swig_types[15] -#define SWIGTYPE_p_XPropertyEvent swig_types[16] -#define SWIGTYPE_p_XDestroyWindowEvent swig_types[17] -#define SWIGTYPE_p_otk__BImageControl swig_types[18] -#define SWIGTYPE_p_PyObject swig_types[19] -#define SWIGTYPE_p_ob__MwmHints swig_types[20] -#define SWIGTYPE_p_otk__Configuration swig_types[21] -#define SWIGTYPE_p_XUnmapEvent swig_types[22] -static swig_type_info *swig_types[24]; +#define SWIGTYPE_p_XFocusChangeEvent swig_types[13] +#define SWIGTYPE_p_XClientMessageEvent swig_types[14] +#define SWIGTYPE_p_otk__OBProperty swig_types[15] +#define SWIGTYPE_p_otk__OtkEventDispatcher swig_types[16] +#define SWIGTYPE_p_XPropertyEvent swig_types[17] +#define SWIGTYPE_p_XDestroyWindowEvent swig_types[18] +#define SWIGTYPE_p_otk__BImageControl swig_types[19] +#define SWIGTYPE_p_PyObject swig_types[20] +#define SWIGTYPE_p_ob__MwmHints swig_types[21] +#define SWIGTYPE_p_otk__Configuration swig_types[22] +#define SWIGTYPE_p_XUnmapEvent swig_types[23] +static swig_type_info *swig_types[25]; /* -------- TYPES TABLE (END) -------- */

@@ -1229,6 +1230,59 @@ return NULL;

} +static PyObject *_wrap_Openbox_focusedClient(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::Openbox *arg1 = (ob::Openbox *) 0 ; + ob::OBClient *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Openbox_focusedClient",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__Openbox,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (ob::OBClient *)(arg1)->focusedClient(); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_ob__OBClient, 0); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Openbox_setFocusedClient(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::Openbox *arg1 = (ob::Openbox *) 0 ; + ob::OBClient *arg2 = (ob::OBClient *) 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:Openbox_setFocusedClient",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__Openbox,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_ob__OBClient,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + (arg1)->setFocusedClient(arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_Openbox_focusedScreen(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::Openbox *arg1 = (ob::Openbox *) 0 ; + ob::OBScreen *result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:Openbox_focusedScreen",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__Openbox,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (ob::OBScreen *)(arg1)->focusedScreen(); + + resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_ob__OBScreen, 0); + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_Openbox_shutdown(PyObject *self, PyObject *args) { PyObject *resultobj; ob::Openbox *arg1 = (ob::Openbox *) 0 ;

@@ -1358,6 +1412,23 @@ return NULL;

} +static PyObject *_wrap_OBScreen_focuswindow(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBScreen *arg1 = (ob::OBScreen *) 0 ; + Window result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:OBScreen_focuswindow",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBScreen,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (Window)((ob::OBScreen const *)arg1)->focuswindow(); + + resultobj = PyInt_FromLong((long)result); + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_OBScreen_addStrut(PyObject *self, PyObject *args) { PyObject *resultobj; ob::OBScreen *arg1 = (ob::OBScreen *) 0 ;

@@ -2172,6 +2243,67 @@ return NULL;

} +static PyObject *_wrap_OBClient_focus(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBClient *arg1 = (ob::OBClient *) 0 ; + bool result; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:OBClient_focus",&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBClient,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + result = (bool)(arg1)->focus(); + + resultobj = PyInt_FromLong((long)result); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_OBClient_focusHandler(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBClient *arg1 = (ob::OBClient *) 0 ; + XFocusChangeEvent *arg2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:OBClient_focusHandler",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBClient,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_XFocusChangeEvent,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg2 == NULL) { + PyErr_SetString(PyExc_TypeError,"null reference"); SWIG_fail; + } + (arg1)->focusHandler((XFocusChangeEvent const &)*arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_OBClient_unfocusHandler(PyObject *self, PyObject *args) { + PyObject *resultobj; + ob::OBClient *arg1 = (ob::OBClient *) 0 ; + XFocusChangeEvent *arg2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:OBClient_unfocusHandler",&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__OBClient,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if ((SWIG_ConvertPtr(obj1,(void **) &arg2, SWIGTYPE_p_XFocusChangeEvent,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; + if (arg2 == NULL) { + PyErr_SetString(PyExc_TypeError,"null reference"); SWIG_fail; + } + (arg1)->unfocusHandler((XFocusChangeEvent const &)*arg2); + + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_OBClient_propertyHandler(PyObject *self, PyObject *args) { PyObject *resultobj; ob::OBClient *arg1 = (ob::OBClient *) 0 ;

@@ -2329,6 +2461,24 @@ return NULL;

} +static PyObject *_wrap_preregister(PyObject *self, PyObject *args) { + PyObject *resultobj; + int arg1 ; + PyObject *arg2 = (PyObject *) 0 ; + bool result; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"iO:preregister",&arg1,&obj1)) goto fail; + arg2 = obj1; + result = (bool)ob::python_preregister(arg1,arg2); + + resultobj = PyInt_FromLong((long)result); + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_unregister(PyObject *self, PyObject *args) { PyObject *resultobj; int arg1 ;

@@ -2371,6 +2521,9 @@ { (char *)"Openbox_cursors", _wrap_Openbox_cursors, METH_VARARGS },

{ (char *)"Openbox_addClient", _wrap_Openbox_addClient, METH_VARARGS }, { (char *)"Openbox_removeClient", _wrap_Openbox_removeClient, METH_VARARGS }, { (char *)"Openbox_findClient", _wrap_Openbox_findClient, METH_VARARGS }, + { (char *)"Openbox_focusedClient", _wrap_Openbox_focusedClient, METH_VARARGS }, + { (char *)"Openbox_setFocusedClient", _wrap_Openbox_setFocusedClient, METH_VARARGS }, + { (char *)"Openbox_focusedScreen", _wrap_Openbox_focusedScreen, METH_VARARGS }, { (char *)"Openbox_shutdown", _wrap_Openbox_shutdown, METH_VARARGS }, { (char *)"Openbox_swigregister", Openbox_swigregister, METH_VARARGS }, { (char *)"OBScreen_client", _wrap_OBScreen_client, METH_VARARGS },

@@ -2379,6 +2532,7 @@ { (char *)"OBScreen_managed", _wrap_OBScreen_managed, METH_VARARGS },

{ (char *)"OBScreen_imageControl", _wrap_OBScreen_imageControl, METH_VARARGS }, { (char *)"OBScreen_area", _wrap_OBScreen_area, METH_VARARGS }, { (char *)"OBScreen_style", _wrap_OBScreen_style, METH_VARARGS }, + { (char *)"OBScreen_focuswindow", _wrap_OBScreen_focuswindow, METH_VARARGS }, { (char *)"OBScreen_addStrut", _wrap_OBScreen_addStrut, METH_VARARGS }, { (char *)"OBScreen_removeStrut", _wrap_OBScreen_removeStrut, METH_VARARGS }, { (char *)"OBScreen_loadStyle", _wrap_OBScreen_loadStyle, METH_VARARGS },

@@ -2425,6 +2579,9 @@ { (char *)"OBClient_area", _wrap_OBClient_area, METH_VARARGS },

{ (char *)"OBClient_move", _wrap_OBClient_move, METH_VARARGS }, { (char *)"OBClient_resize", _wrap_OBClient_resize, METH_VARARGS }, { (char *)"OBClient_close", _wrap_OBClient_close, METH_VARARGS }, + { (char *)"OBClient_focus", _wrap_OBClient_focus, METH_VARARGS }, + { (char *)"OBClient_focusHandler", _wrap_OBClient_focusHandler, METH_VARARGS }, + { (char *)"OBClient_unfocusHandler", _wrap_OBClient_unfocusHandler, METH_VARARGS }, { (char *)"OBClient_propertyHandler", _wrap_OBClient_propertyHandler, METH_VARARGS }, { (char *)"OBClient_clientMessageHandler", _wrap_OBClient_clientMessageHandler, METH_VARARGS }, { (char *)"OBClient_shapeHandler", _wrap_OBClient_shapeHandler, METH_VARARGS },

@@ -2433,6 +2590,7 @@ { (char *)"OBClient_unmapHandler", _wrap_OBClient_unmapHandler, METH_VARARGS },

{ (char *)"OBClient_destroyHandler", _wrap_OBClient_destroyHandler, METH_VARARGS }, { (char *)"OBClient_swigregister", OBClient_swigregister, METH_VARARGS }, { (char *)"register", _wrap_register, METH_VARARGS }, + { (char *)"preregister", _wrap_preregister, METH_VARARGS }, { (char *)"unregister", _wrap_unregister, METH_VARARGS }, { NULL, NULL } };

@@ -2465,6 +2623,7 @@ static swig_type_info _swigt__p_XConfigureRequestEvent[] = {{"_p_XConfigureRequestEvent", 0, "XConfigureRequestEvent *", 0},{"_p_XConfigureRequestEvent"},{0}};

static swig_type_info _swigt__p_otk__OtkEventHandler[] = {{"_p_otk__OtkEventHandler", 0, "otk::OtkEventHandler *", 0},{"_p_otk__OtkEventHandler"},{"_p_ob__Openbox", _p_ob__OpenboxTo_p_otk__OtkEventHandler},{"_p_ob__OBClient", _p_ob__OBClientTo_p_otk__OtkEventHandler},{0}}; static swig_type_info _swigt__p_otk__Rect[] = {{"_p_otk__Rect", 0, "otk::Rect *", 0},{"_p_otk__Rect"},{0}}; static swig_type_info _swigt__p_ob__OBWidget[] = {{"_p_ob__OBWidget", 0, "ob::OBWidget *", 0},{"_p_ob__OBWidget"},{"_p_ob__OBClient", _p_ob__OBClientTo_p_ob__OBWidget},{0}}; +static swig_type_info _swigt__p_XFocusChangeEvent[] = {{"_p_XFocusChangeEvent", 0, "XFocusChangeEvent *", 0},{"_p_XFocusChangeEvent"},{0}}; static swig_type_info _swigt__p_XClientMessageEvent[] = {{"_p_XClientMessageEvent", 0, "XClientMessageEvent *", 0},{"_p_XClientMessageEvent"},{0}}; static swig_type_info _swigt__p_otk__OBProperty[] = {{"_p_otk__OBProperty", 0, "otk::OBProperty *", 0},{"_p_otk__OBProperty"},{0}}; static swig_type_info _swigt__p_otk__OtkEventDispatcher[] = {{"_p_otk__OtkEventDispatcher", 0, "otk::OtkEventDispatcher *", 0},{"_p_otk__OtkEventDispatcher"},{"_p_ob__Openbox", _p_ob__OpenboxTo_p_otk__OtkEventDispatcher},{0}};

@@ -2490,6 +2649,7 @@ _swigt__p_XConfigureRequestEvent,

_swigt__p_otk__OtkEventHandler, _swigt__p_otk__Rect, _swigt__p_ob__OBWidget, +_swigt__p_XFocusChangeEvent, _swigt__p_XClientMessageEvent, _swigt__p_otk__OBProperty, _swigt__p_otk__OtkEventDispatcher,
M src/python.ccsrc/python.cc

@@ -32,6 +32,27 @@ }

return true; } +bool python_preregister(int action, PyObject *callback) +{ + if (action < 0 || action >= OBActions::NUM_ACTIONS) { + PyErr_SetString(PyExc_AssertionError, "Invalid action type."); + return false; + } + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_AssertionError, "Invalid callback function."); + return false; + } + + FunctionList::iterator it = std::find(callbacks[action].begin(), + callbacks[action].end(), + callback); + if (it == callbacks[action].end()) { // not already in there + Py_XINCREF(callback); // Add a reference to new callback + callbacks[action].insert(callbacks[action].begin(), callback); + } + return true; +} + bool python_unregister(int action, PyObject *callback) { if (action < 0 || action >= OBActions::NUM_ACTIONS) {
M src/python.hhsrc/python.hh

@@ -15,9 +15,14 @@ }

namespace ob { +//! Add a python callback funtion to the back of the hook list bool python_register(int action, PyObject *callback); +//! Add a python callback funtion to the front of the hook list +bool python_preregister(int action, PyObject *callback); +//! Remove a python callback function from the hook list bool python_unregister(int action, PyObject *callback); +//! Fire a python callback function void python_callback(OBActions::ActionType action, Window window, OBWidget::WidgetType type, unsigned int state, long d1 = LONG_MIN, long d2 = LONG_MIN,
M src/screen.ccsrc/screen.cc

@@ -89,6 +89,14 @@ otk::OBProperty::net_desktop_viewport,

otk::OBProperty::Atom_Cardinal, viewport, 2); + // create the window which gets focus when no clients get it + XSetWindowAttributes attr; + attr.override_redirect = true; + _focuswindow = XCreateWindow(otk::OBDisplay::display, _info->rootWindow(), + -100, -100, 1, 1, 0, 0, InputOnly, + _info->visual(), CWOverrideRedirect, &attr); + XMapWindow(otk::OBDisplay::display, _focuswindow); + // these may be further updated if any pre-existing windows are found in // the manageExising() function setClientList(); // initialize the client lists, which will be empty
M src/screen.hhsrc/screen.hh

@@ -62,6 +62,7 @@

//! The style with which to render on the screen otk::Style _style; + //! The screen's root window OBRootWindow _root; //! Is the root colormap currently installed?

@@ -73,6 +74,9 @@

//! Areas of the screen reserved by applications StrutList _struts; + //! An offscreen window which gets focus when nothing else has it + Window _focuswindow; + //! Calculate the OBScreen::_area member void calcArea();

@@ -113,6 +117,8 @@ //! Returns the area of the screen not reserved by applications' Struts

inline const otk::Rect &area() const { return _area; } //! Returns the style in use on the screen inline const otk::Style *style() const { return &_style; } + //! An offscreen window which gets focus when nothing else has it + inline Window focuswindow() const { return _focuswindow; } //! Adds a window's strut to the screen's list of reserved spaces void addStrut(otk::Strut *strut);