From 1fa445c88033e564a25d907a7f478e76bff9e89e Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 4 Dec 2002 00:26:45 +0000 Subject: [PATCH] handle configure requests --- otk/eventdispatcher.cc | 2 +- src/client.cc | 145 ++++++++++++++++++++++++++++++++++------- src/client.hh | 131 +++++++++++++++---------------------- src/frame.cc | 15 ++++- src/frame.hh | 2 +- src/openbox.cc | 1 - src/rootwindow.cc | 20 ++++++ src/rootwindow.hh | 2 + 8 files changed, 213 insertions(+), 105 deletions(-) diff --git a/otk/eventdispatcher.cc b/otk/eventdispatcher.cc index 69fa3d5a..2a0c4448 100644 --- a/otk/eventdispatcher.cc +++ b/otk/eventdispatcher.cc @@ -33,7 +33,7 @@ void OtkEventDispatcher::clearHandler(Window id) { _map.erase(id); } -#include + void OtkEventDispatcher::dispatchEvents(void) { XEvent e; diff --git a/src/client.cc b/src/client.cc index 80bab9db..0fd5787b 100644 --- a/src/client.cc +++ b/src/client.cc @@ -5,6 +5,7 @@ #endif #include "client.hh" +#include "frame.hh" #include "bbscreen.hh" #include "openbox.hh" #include "otk/display.hh" @@ -374,10 +375,10 @@ void OBClient::updateNormalHints() // defaults _gravity = NorthWestGravity; - _inc_x = _inc_y = 1; - _base_x = _base_y = 0; - _min_x = _min_y = 0; - _max_x = _max_y = INT_MAX; + _size_inc.setPoint(1, 1); + _base_size.setPoint(0, 0); + _min_size.setPoint(0, 0); + _max_size.setPoint(INT_MAX, INT_MAX); // XXX: might want to cancel any interactive resizing of the window at this // point.. @@ -389,25 +390,17 @@ void OBClient::updateNormalHints() if (size.flags & PWinGravity) _gravity = size.win_gravity; - if (size.flags & PMinSize) { - _min_x = size.min_width; - _min_y = size.min_height; - } + if (size.flags & PMinSize) + _min_size.setPoint(size.min_width, size.min_height); - if (size.flags & PMaxSize) { - _max_x = size.max_width; - _max_y = size.max_height; - } + if (size.flags & PMaxSize) + _max_size.setPoint(size.max_width, size.max_height); - if (size.flags & PBaseSize) { - _base_x = size.base_width; - _base_y = size.base_height; - } + if (size.flags & PBaseSize) + _base_size.setPoint(size.base_width, size.base_height); - if (size.flags & PResizeInc) { - _inc_x = size.width_inc; - _inc_y = size.height_inc; - } + if (size.flags & PResizeInc) + _size_inc.setPoint(size.width_inc, size.height_inc); } } @@ -719,9 +712,117 @@ void OBClient::shapeHandler(const XShapeEvent &e) #endif -void OBClient::setArea(const otk::Rect &area) +void OBClient::resize(Corner anchor, int w, int h) +{ + w -= _base_size.x(); + h -= _base_size.y(); + + // is the window resizable? if it is not, then don't check its sizes, the + // client can do what it wants and the user can't change it anyhow + if (_min_size.x() <= _max_size.x() && _min_size.y() <= _max_size.y()) { + // smaller than min size or bigger than max size? + if (w < _min_size.x()) w = _min_size.x(); + else if (w > _max_size.x()) w = _max_size.x(); + if (h < _min_size.y()) h = _min_size.y(); + else if (h > _max_size.y()) h = _max_size.y(); + } + + // keep to the increments + w /= _size_inc.x(); + h /= _size_inc.y(); + + // store the logical size + _logical_size.setPoint(w, h); + + w *= _size_inc.x(); + h *= _size_inc.y(); + + w += _base_size.x(); + h += _base_size.y(); + + switch (anchor) { + case TopLeft: + break; + case TopRight: + _area.setX(_area.x() - _area.width() - w); + break; + case BottomLeft: + _area.setY(_area.y() - _area.height() - h); + break; + case BottomRight: + _area.setX(_area.x() - _area.width() - w); + _area.setY(_area.y() - _area.height() - h); + break; + } + + _area.setSize(w, h); + + // resize the frame to match + frame->adjust(); +} + + +void OBClient::move(int x, int y) { - _area = area; + _area.setPos(x, y); + // move the frame to be in the requested position + frame->applyGravity(); } + +void OBClient::configureRequestHandler(const XConfigureRequestEvent &e) +{ + // XXX: if we are iconic (or shaded? (fvwm does that)) ignore the event + + if (e.value_mask & CWBorderWidth) + _border_width = e.border_width; + + // resize, then move, as specified in the EWMH section 7.7 + if (e.value_mask & (CWWidth | CWHeight)) { + int w = (e.value_mask & CWWidth) ? e.width : _area.width(); + int h = (e.value_mask & CWHeight) ? e.height : _area.height(); + + Corner corner; + switch (_gravity) { + case NorthEastGravity: + case EastGravity: + corner = TopRight; + break; + case SouthWestGravity: + case SouthGravity: + corner = BottomLeft; + break; + case SouthEastGravity: + corner = BottomRight; + break; + default: // NorthWest, Static, etc + corner = TopLeft; + } + + resize(corner, w, h); + } + + if (e.value_mask & (CWX | CWY)) { + int x = (e.value_mask & CWX) ? e.x : _area.x(); + int y = (e.value_mask & CWY) ? e.y : _area.y(); + move(x, y); + } + + if (e.value_mask & CWStackMode) { + switch (e.detail) { + case Below: + case BottomIf: + // XXX: lower the window + break; + + case Above: + case TopIf: + default: + // XXX: raise the window + break; + } + } +} + + } diff --git a/src/client.hh b/src/client.hh index 325162ed..9c0bd7d4 100644 --- a/src/client.hh +++ b/src/client.hh @@ -17,6 +17,7 @@ extern "C" { #include +#include "otk/point.hh" #include "otk/strut.hh" #include "otk/rect.hh" #include "otk/eventhandler.hh" @@ -41,8 +42,17 @@ class OBClient : public otk::OtkEventHandler { public: //! The frame window which decorates around the client window + /*! + NOTE: This should NEVER be used inside the client class's constructor! + */ OBFrame *frame; - + + //! Corners of the client window, used for anchor positions + enum Corner { TopLeft, + TopRight, + BottomLeft, + BottomRight }; + //! Possible window types enum WindowType { Type_Desktop, //!< A desktop (bottom-most window) Type_Dock, //!< A dock bar/panel window @@ -153,9 +163,23 @@ private: //! The type of window (what its function is) WindowType _type; - //! Position and size of the window (relative to the root window) + //! Position and size of the window + /*! + This will not always be the actual position of the window on screen, it is + rather, the position requested by the client, to which the window's gravity + is applied. + */ otk::Rect _area; + //! The logical size of the window + /*! + The "logical" size of the window is refers to the user's perception of the + size of the window, and is the value that should be displayed to the user. + For example, with xterms, this value it the number of characters being + displayed in the terminal, instead of the number of pixels. + */ + otk::Point _logical_size; + //! Width of the border on the window. /*! The window manager will set this to 0 while the window is being managed, @@ -163,42 +187,24 @@ private: */ int _border_width; - //! The minimum width of the client window - /*! - If the min is > the max, then the window is not resizable - */ - int _min_x; - //! The minimum height of the client window - /*! - If the min is > the max, then the window is not resizable - */ - int _min_y; - //! The maximum width of the client window + //! The minimum size of the client window /*! If the min is > the max, then the window is not resizable */ - int _max_x; - //! The maximum height of the client window + otk::Point _min_size; + //! The maximum size of the client window /*! If the min is > the max, then the window is not resizable */ - int _max_y; - //! The size of increments to resize the client window by (for the width) - int _inc_x; - //! The size of increments to resize the client window by (for the height) - int _inc_y; - //! The base width of the client window + otk::Point _max_size; + //! The size of increments to resize the client window by + otk::Point _size_inc; + //! The base size of the client window /*! - This value should be subtracted from the window's actual width when - displaying its size to the user, or working with its min/max width + This value should be subtracted from the window's actual size when + displaying its size to the user, or working with its min/max size */ - int _base_x; - //! The base height of the client window - /*! - This value should be subtracted from the window's actual height when - displaying its size to the user, or working with its min/max height - */ - int _base_y; + otk::Point _base_size; //! Where to place the decorated window in relation to the undecorated window int _gravity; @@ -289,6 +295,21 @@ private: void updateClass(); // XXX: updateTransientFor(); + //! Move the client window + /*! + This shouldnt be used to move the window internally! It will apply + window gravity after moving the window. + */ + void move(int x, int y); + + //! Resizes the client window, anchoring it in a given corner + /*! + This also maintains things like the client's minsize, and size increments. + @param anchor The corner to keep in the same position when resizing + @param size The new size for the client + */ + void resize(Corner anchor, int x, int y); + public: //! Constructs a new OBClient object around a specified window id /*! @@ -387,49 +408,8 @@ public: */ inline bool floating() const { return _floating; } - //! Returns the window's border width - /*! - The border width is set to 0 when the client becomes managed, but the - border width is stored here so that it can be restored to the client window - when it is unmanaged later. - */ + //! Returns the client's requested border width (not used by the wm) inline int borderWidth() const { return _border_width; } - //! Returns the minimum width of the client window - /*! - If the min is > the max, then the window is not resizable - */ - inline int minX() const { return _min_x; } - //! Returns the minimum height of the client window - /*! - If the min is > the max, then the window is not resizable - */ - inline int minY() const { return _min_y; } - //! Returns the maximum width of the client window - /*! - If the min is > the max, then the window is not resizable - */ - inline int maxX() const { return _max_x; } - //! Returns the maximum height of the client window - /*! - If the min is > the max, then the window is not resizable - */ - inline int maxY() const { return _max_y; } - //! Returns the increment size for resizing the window (for the width) - inline int incrementX() const { return _inc_x; } - //! Returns the increment size for resizing the window (for the height) - inline int incrementY() const { return _inc_y; } - //! Returns the base width of the window - /*! - This value should be subtracted from the window's actual width when - displaying its size to the user, or working with its min/max width - */ - inline int baseX() const { return _base_x; } - //! Returns the base height of the window - /*! - This value should be subtracted from the window's actual height when - displaying its size to the user, or working with its min/max height - */ - inline int baseY() const { return _base_y; } //! Returns the position and size of the client relative to the root window inline const otk::Rect &area() const { return _area; } @@ -440,12 +420,7 @@ public: virtual void shapeHandler(const XShapeEvent &e); - //! Changes the stored positions and size of the OBClient window - /*! - This does not actually change the physical geometry, that needs to be done - before/after setting this value to keep it in sync - */ - void setArea(const otk::Rect &area); + virtual void configureRequestHandler(const XConfigureRequestEvent &e); }; } diff --git a/src/frame.cc b/src/frame.cc index d991e454..725a4306 100644 --- a/src/frame.cc +++ b/src/frame.cc @@ -196,8 +196,13 @@ void OBFrame::adjust() // that the ONE LABEL!! // adds an extra sep so that there's a space on either side of the // titlebar.. note: x = sep, below. - _label.setWidth(width - sep * 2 - - (_button_iconify.width() + sep) * (layout.size() - 1)); + int lwidth = width - sep * 2 - + (_button_iconify.width() + sep) * (layout.size() - 1); + // quick sanity check for really small windows. if this is needed, its + // obviously not going to be displayed right... + // XXX: maybe we should make this look better somehow? constraints? + if (lwidth <= 0) lwidth = 1; + _label.setWidth(lwidth); int x = sep; for (int i = 0, len = layout.size(); i < len; ++i) { @@ -449,4 +454,10 @@ void OBFrame::applyGravity() } +void OBFrame::reverseGravity() +{ + move(_client->area().x() - _size.left, _client->area().y() - _size.top); +} + + } diff --git a/src/frame.hh b/src/frame.hh index 7f146a21..500dcb4a 100644 --- a/src/frame.hh +++ b/src/frame.hh @@ -91,7 +91,7 @@ public: //! Reversely applies gravity for the client's gravity, moving the frame so //! that the client is in its pre-gravity position - void restoreGravity(); + void reverseGravity(); }; } diff --git a/src/openbox.cc b/src/openbox.cc index 80622c1c..0c534a0f 100644 --- a/src/openbox.cc +++ b/src/openbox.cc @@ -280,6 +280,5 @@ OBClient *Openbox::findClient(Window window) return (OBClient*) 0; } - } diff --git a/src/rootwindow.cc b/src/rootwindow.cc index 3fccc44a..bc62fdc5 100644 --- a/src/rootwindow.cc +++ b/src/rootwindow.cc @@ -108,4 +108,24 @@ void OBRootWindow::mapRequestHandler(const XMapRequestEvent &e) } } + +#include +void OBRootWindow::configureRequestHandler(const XConfigureRequestEvent &e) +{ + // when configure requests come to the root window, just pass them on + XWindowChanges xwc; + + xwc.x = e.x; + xwc.y = e.y; + xwc.width = e.width; + xwc.height = e.height; + xwc.border_width = e.border_width; + xwc.sibling = e.above; + xwc.stack_mode = e.detail; + + XConfigureWindow(otk::OBDisplay::display, e.window, + e.value_mask, &xwc); +} + + } diff --git a/src/rootwindow.hh b/src/rootwindow.hh index 7d0a9c82..1dbfc04a 100644 --- a/src/rootwindow.hh +++ b/src/rootwindow.hh @@ -58,6 +58,8 @@ public: virtual void mapRequestHandler(const XMapRequestEvent &); + virtual void configureRequestHandler(const XConfigureRequestEvent &e); + //! Sets the name of a desktop /*! @param i The index of the desktop to set the name for (base 0) -- 2.39.2