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.
jump to
@@ -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)
@@ -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); }; }
@@ -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(); }
@@ -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)
@@ -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(); }
@@ -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 },
@@ -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; }
@@ -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)
@@ -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)
@@ -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 } - }
@@ -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(); }; }
@@ -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"); }
@@ -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);
@@ -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,
@@ -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
@@ -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 +} }
@@ -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); }; }
@@ -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(); }
@@ -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); + } } }
@@ -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
@@ -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;
@@ -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,
@@ -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) {
@@ -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,
@@ -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
@@ -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);