From 2ae2b257d39ea62640c2590f794e4275c6db1cd4 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 25 Dec 2002 22:02:34 +0000 Subject: [PATCH] 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. --- otk/eventdispatcher.cc | 68 +++++++++++---- otk/eventdispatcher.hh | 3 + otk/focuslabel.cc | 6 +- otk/focuswidget.cc | 21 +---- otk/label.cc | 6 +- otk/otk_wrap.cc | 43 +--------- otk/style.hh | 3 +- otk/widget.cc | 21 +---- scripts/clicks.py | 12 ++- src/backgroundwidget.cc | 58 +++++++++---- src/backgroundwidget.hh | 8 +- src/buttonwidget.cc | 94 +++++++++++++++++---- src/buttonwidget.hh | 13 ++- src/client.cc | 36 ++++++++ src/client.hh | 7 ++ src/frame.cc | 52 +++++++----- src/frame.hh | 9 ++ src/labelwidget.cc | 92 ++++++++++++++++++-- src/labelwidget.hh | 22 ++++- src/main.cc | 16 +--- src/openbox.cc | 25 +++++- src/openbox.hh | 28 +++++++ src/openbox.i | 1 + src/openbox_wrap.cc | 182 +++++++++++++++++++++++++++++++++++++--- src/python.cc | 21 +++++ src/python.hh | 5 ++ src/screen.cc | 8 ++ src/screen.hh | 6 ++ 28 files changed, 673 insertions(+), 193 deletions(-) diff --git a/otk/eventdispatcher.cc b/otk/eventdispatcher.cc index 33d8ba2d..73c329e8 100644 --- a/otk/eventdispatcher.cc +++ b/otk/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::clearHandler(Window id) void OtkEventDispatcher::dispatchEvents(void) { - XEvent e; - OtkEventHandler *handler; OtkEventMap::iterator it; + XEvent e; + Window focus = _focus; + Window unfocus = None; while (XPending(OBDisplay::display)) { XNextEvent(OBDisplay::display, &e); @@ -70,23 +73,58 @@ void OtkEventDispatcher::dispatchEvents(void) 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) diff --git a/otk/eventdispatcher.hh b/otk/eventdispatcher.hh index a9b5af7b..716a8118 100644 --- a/otk/eventdispatcher.hh +++ b/otk/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); }; } diff --git a/otk/focuslabel.cc b/otk/focuslabel.cc index 136eb742..a5c85127 100644 --- a/otk/focuslabel.cc +++ b/otk/focuslabel.cc @@ -36,7 +36,7 @@ void OtkFocusLabel::setStyle(Style *style) 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 @@ void OtkFocusLabel::update(void) 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 @@ void OtkFocusLabel::update(void) OtkFocusWidget::update(); - ft.drawString(_xftdraw, x, 0, *text_color, t); + ft->drawString(_xftdraw, x, 0, *text_color, t); } else OtkFocusWidget::update(); } diff --git a/otk/focuswidget.cc b/otk/focuswidget.cc index a5d2696d..e2eef1ee 100644 --- a/otk/focuswidget.cc +++ b/otk/focuswidget.cc @@ -23,43 +23,30 @@ OtkFocusWidget::~OtkFocusWidget() #include 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(*it); - if (tmp) tmp->unfocus(); - } + update(); } void OtkFocusWidget::setTexture(BTexture *texture) diff --git a/otk/label.cc b/otk/label.cc index cc67a316..4a61efd0 100644 --- a/otk/label.cc +++ b/otk/label.cc @@ -32,7 +32,7 @@ void OtkLabel::setStyle(Style *style) 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 @@ void OtkLabel::update(void) 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 @@ void OtkLabel::update(void) OtkWidget::update(); - ft.drawString(_xftdraw, x, 0, *style()->getTextUnfocus(), t); + ft->drawString(_xftdraw, x, 0, *style()->getTextUnfocus(), t); } else OtkWidget::update(); } diff --git a/otk/otk_wrap.cc b/otk/otk_wrap.cc index 73f9bea6..08451e98 100644 --- a/otk/otk_wrap.cc +++ b/otk/otk_wrap.cc @@ -1001,42 +1001,6 @@ static PyObject *_wrap_OtkEventDispatcher_getFallbackHandler(PyObject *self, PyO } -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 @@ static PyObject *_wrap_Style_getFont(PyObject *self, PyObject *args) { 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 @@ static PyMethodDef SwigMethods[] = { { (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 }, diff --git a/otk/style.hh b/otk/style.hh index f7584c3e..95f9b487 100644 --- a/otk/style.hh +++ b/otk/style.hh @@ -16,6 +16,7 @@ namespace otk { struct PixmapMask { Pixmap mask; unsigned int w, h; + PixmapMask() { mask = None; w = h = 0; } }; class Style { @@ -114,7 +115,7 @@ public: 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; } diff --git a/otk/widget.cc b/otk/widget.cc index 07122bc6..e085bc9f 100644 --- a/otk/widget.cc +++ b/otk/widget.cc @@ -187,12 +187,6 @@ void OtkWidget::hide(bool recursive) 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::ungrabKeyboard(void) 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::adjustVert(void) void OtkWidget::update(void) { if (_dirty) { - if (! _unmanaged) - adjust(); + if (!_unmanaged) + adjust(); render(); XClearWindow(OBDisplay::display, _window); } @@ -445,15 +439,6 @@ void OtkWidget::setStyle(Style *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) (*it)->setStyle(style); diff --git a/scripts/clicks.py b/scripts/clicks.py index 3c958bf4..39effd53 100644 --- a/scripts/clicks.py +++ b/scripts/clicks.py @@ -18,11 +18,15 @@ def def_click_client(action, win, type, modifiers, button, time): 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 @@ def def_doubleclick_client(action, win, type, modifiers, button, time): 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) diff --git a/src/backgroundwidget.cc b/src/backgroundwidget.cc index 7d715f55..8b63b44d 100644 --- a/src/backgroundwidget.cc +++ b/src/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 @@ OBBackgroundWidget::~OBBackgroundWidget() } -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: + if (_focused) + setTexture(_style->getHandleFocus()); + else + setTexture(_style->getHandleUnfocus()); break; + case Type_Plate: + if (_focused) + setBorderColor(&_style->getFrameFocus()->color()); + else + setBorderColor(&_style->getFrameUnfocus()->color()); + break; + default: + assert(false); // there's no other background widgets! + } +} + + +void OBBackgroundWidget::setStyle(otk::Style *style) +{ + OtkWidget::setStyle(style); + setTextures(); + switch (type()) { + case Type_Titlebar: case Type_Handle: - setTexture(style->getHandleFocus()); - setUnfocusTexture(style->getHandleUnfocus()); - setBorderColor(style->getBorderColor()); + setBorderColor(_style->getBorderColor()); break; case Type_Plate: - setBorderColor(&style->getFrameFocus()->color()); - setUnfocusBorderColor(&style->getFrameUnfocus()->color()); break; default: assert(false); // there's no other background widgets! } +} + + +void OBBackgroundWidget::focus() +{ + otk::OtkWidget::focus(); + setTextures(); +} + - otk::OtkFocusWidget::setStyle(style); +void OBBackgroundWidget::unfocus() +{ + otk::OtkWidget::unfocus(); + setTextures(); } void OBBackgroundWidget::adjust() { - otk::OtkFocusWidget::adjust(); - // XXX: adjust shit } - } diff --git a/src/backgroundwidget.hh b/src/backgroundwidget.hh index 0cbfb3fa..7b698c15 100644 --- a/src/backgroundwidget.hh +++ b/src/backgroundwidget.hh @@ -2,14 +2,15 @@ #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 @@ public: virtual void setStyle(otk::Style *style); virtual void adjust(); + + virtual void focus(); + virtual void unfocus(); }; } diff --git a/src/buttonwidget.cc b/src/buttonwidget.cc index 867cc5be..853b0339 100644 --- a/src/buttonwidget.cc +++ b/src/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 @@ OBButtonWidget::~OBButtonWidget() } +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::adjust() +void OBButtonWidget::focus() { - otk::OtkButton::adjust(); + otk::OtkWidget::focus(); + setTextures(); +} + +void OBButtonWidget::unfocus() +{ + otk::OtkWidget::unfocus(); + setTextures(); +} + + +void OBButtonWidget::adjust() +{ // 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(); +} + } diff --git a/src/buttonwidget.hh b/src/buttonwidget.hh index bb23dd90..66a9cf37 100644 --- a/src/buttonwidget.hh +++ b/src/buttonwidget.hh @@ -2,14 +2,17 @@ #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 @@ public: 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); }; } diff --git a/src/client.cc b/src/client.cc index a22a18a6..2f966cee 100644 --- a/src/client.cc +++ b/src/client.cc @@ -40,6 +40,8 @@ OBClient::OBClient(int screen, Window window) _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 @@ void OBClient::updateTitle() if (_title.empty()) _title = _("Unnamed Window"); + + if (frame) + frame->setTitle(_title); } @@ -859,6 +864,37 @@ void OBClient::close() } +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"); +} + + void OBClient::configureRequestHandler(const XConfigureRequestEvent &e) { OtkEventHandler::configureRequestHandler(e); diff --git a/src/client.hh b/src/client.hh index eeb04232..61f7b071 100644 --- a/src/client.hh +++ b/src/client.hh @@ -234,6 +234,8 @@ private: 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 @@ public: //! 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); diff --git a/src/frame.cc b/src/frame.cc index 4e30a1f5..fed6132e 100644 --- a/src/frame.cc +++ b/src/frame.cc @@ -43,31 +43,15 @@ OBFrame::OBFrame(OBClient *client, otk::Style *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 @@ OBFrame::~OBFrame() } +void OBFrame::setTitle(const std::string &text) +{ + _label.setText(text); + _label.update(); +} + + void OBFrame::setStyle(otk::Style *style) { assert(style); @@ -97,9 +88,7 @@ void OBFrame::setStyle(otk::Style *style) _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) { @@ -110,6 +99,25 @@ void OBFrame::setStyle(otk::Style *style) } +void OBFrame::focus() +{ + otk::OtkWidget::focus(); + update(); +} + + +void OBFrame::unfocus() +{ + otk::OtkWidget::unfocus(); + update(); +} + + +void OBFrame::adjust() +{ +} + + void OBFrame::adjustSize() { // XXX: only if not overridden or something!!! MORE LOGIC HERE!! @@ -142,13 +150,13 @@ void OBFrame::adjustSize() _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, diff --git a/src/frame.hh b/src/frame.hh index 37eee7ea..5f70b643 100644 --- a/src/frame.hh +++ b/src/frame.hh @@ -93,6 +93,15 @@ public: //! 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 diff --git a/src/labelwidget.cc b/src/labelwidget.cc index 9b18c0a9..5a33cf3d 100644 --- a/src/labelwidget.cc +++ b/src/labelwidget.cc @@ -4,37 +4,115 @@ # 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 +} + } diff --git a/src/labelwidget.hh b/src/labelwidget.hh index def81fef..01662f85 100644 --- a/src/labelwidget.hh +++ b/src/labelwidget.hh @@ -2,14 +2,24 @@ #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 @@ public: 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); }; } diff --git a/src/main.cc b/src/main.cc index 5d878d79..a8312af5 100644 --- a/src/main.cc +++ b/src/main.cc @@ -13,32 +13,20 @@ extern "C" { # include #endif // HAVE_LOCALE_H -#include - #include "gettext.h" } #include 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(); } diff --git a/src/openbox.cc b/src/openbox.cc index 41f0c7b1..ff42f58b 100644 --- a/src/openbox.cc +++ b/src/openbox.cc @@ -108,6 +108,8 @@ Openbox::Openbox(int argc, char **argv) _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 @@ Openbox::Openbox(int argc, char **argv) // 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 @@ Openbox::Openbox(int argc, char **argv) ::exit(1); } + // set up input focus + _focused_screen = _screens[0]; + setFocusedClient(0); + _state = State_Normal; // done starting } @@ -223,6 +231,8 @@ void Openbox::parseCommandLine(int argc, char **argv) err = true; else _scriptfilepath = argv[i]; + } else if (arg == "-sync") { + _sync = true; } else if (arg == "-version") { showVersion(); ::exit(0); @@ -321,5 +331,18 @@ OBClient *Openbox::findClient(Window window) 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); + } +} + } diff --git a/src/openbox.hh b/src/openbox.hh index 1489ffb7..976a4977 100644 --- a/src/openbox.hh +++ b/src/openbox.hh @@ -121,6 +121,9 @@ private: //! 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 @@ private: //! 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 @@ public: //! 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 diff --git a/src/openbox.i b/src/openbox.i index ef82956b..20c8ea06 100644 --- a/src/openbox.i +++ b/src/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; diff --git a/src/openbox_wrap.cc b/src/openbox_wrap.cc index b95ae259..12cd7e20 100644 --- a/src/openbox_wrap.cc +++ b/src/openbox_wrap.cc @@ -658,17 +658,18 @@ SWIG_InstallConstants(PyObject *d, swig_const_info constants[]) { #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 @@ static PyObject *_wrap_Openbox_findClient(PyObject *self, PyObject *args) { } +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 @@ static PyObject *_wrap_OBScreen_style(PyObject *self, PyObject *args) { } +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 @@ static PyObject *_wrap_OBClient_close(PyObject *self, PyObject *args) { } +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 @@ static PyObject *_wrap_register(PyObject *self, PyObject *args) { } +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 @@ static PyMethodDef SwigMethods[] = { { (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 @@ static PyMethodDef SwigMethods[] = { { (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 @@ static PyMethodDef SwigMethods[] = { { (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 @@ static PyMethodDef SwigMethods[] = { { (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_XConfigureReque 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, diff --git a/src/python.cc b/src/python.cc index d44b2d48..97a3a4d2 100644 --- a/src/python.cc +++ b/src/python.cc @@ -32,6 +32,27 @@ bool python_register(int action, PyObject *callback) 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) { diff --git a/src/python.hh b/src/python.hh index 6ca4e1c5..30cd752d 100644 --- a/src/python.hh +++ b/src/python.hh @@ -15,9 +15,14 @@ extern "C" { 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, diff --git a/src/screen.cc b/src/screen.cc index 947471c2..d61b501d 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -89,6 +89,14 @@ OBScreen::OBScreen(int screen, const otk::Configuration &config) 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 diff --git a/src/screen.hh b/src/screen.hh index 7e95d40f..37f22d88 100644 --- a/src/screen.hh +++ b/src/screen.hh @@ -62,6 +62,7 @@ private: //! 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 @@ private: //! 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 @@ public: 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); -- 2.39.2