summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2002-12-25 22:02:34 +0000
committerDana Jansens <danakj@orodu.net>2002-12-25 22:02:34 +0000
commit2ae2b257d39ea62640c2590f794e4275c6db1cd4 (patch)
treef26abe4a0601d263fbc460eddc012c1d674c868b
parent3c61812e588fb3c34d0713d7f82ccbf21091f032 (diff)
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.
-rw-r--r--otk/eventdispatcher.cc68
-rw-r--r--otk/eventdispatcher.hh3
-rw-r--r--otk/focuslabel.cc6
-rw-r--r--otk/focuswidget.cc21
-rw-r--r--otk/label.cc6
-rw-r--r--otk/otk_wrap.cc43
-rw-r--r--otk/style.hh3
-rw-r--r--otk/widget.cc21
-rw-r--r--scripts/clicks.py12
-rw-r--r--src/backgroundwidget.cc58
-rw-r--r--src/backgroundwidget.hh8
-rw-r--r--src/buttonwidget.cc94
-rw-r--r--src/buttonwidget.hh13
-rw-r--r--src/client.cc36
-rw-r--r--src/client.hh7
-rw-r--r--src/frame.cc52
-rw-r--r--src/frame.hh9
-rw-r--r--src/labelwidget.cc92
-rw-r--r--src/labelwidget.hh22
-rw-r--r--src/main.cc16
-rw-r--r--src/openbox.cc25
-rw-r--r--src/openbox.hh28
-rw-r--r--src/openbox.i1
-rw-r--r--src/openbox_wrap.cc182
-rw-r--r--src/python.cc21
-rw-r--r--src/python.hh5
-rw-r--r--src/screen.cc8
-rw-r--r--src/screen.hh6
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 <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)
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 <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();
}
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);