From 81378f9494db4ab1d033947532d7fac968095ecd Mon Sep 17 00:00:00 2001
From: rathnor <rathnor>
Date: Mon, 29 Sep 2003 14:58:15 +0000
Subject: fix handling of base_Width/height hints in wm_normal_hints - fixes
 abiword resize issues

---
 ChangeLog        |  3 +++
 src/WinClient.cc | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 src/WinClient.hh | 12 +++++++++-
 src/Window.cc    | 59 ++++++++++++----------------------------------
 src/Window.hh    |  5 ++--
 5 files changed, 95 insertions(+), 56 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5576fc1..48106b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,9 @@
 (Format: Year/Month/Day)
 Changes for 0.9.6:
 *03/09/29:
+  * Fix resize calculations, particularly wrt base_width/height (Simon)
+    - fixes abiword resize issues
+    Window.hh/cc WinClient.hh/cc
   * Nearest-quadrant resizing (Thanks Mathias Gumz)
     Window.hh/cc Screen.hh/cc FbWinFrameTheme.hh/cc
   * Update from Han 
diff --git a/src/WinClient.cc b/src/WinClient.cc
index 614b7a4..e032304 100644
--- a/src/WinClient.cc
+++ b/src/WinClient.cc
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: WinClient.cc,v 1.27 2003/09/24 14:02:25 rathnor Exp $
+// $Id: WinClient.cc,v 1.28 2003/09/29 14:58:15 rathnor Exp $
 
 #include "WinClient.hh"
 
@@ -43,7 +43,7 @@ WinClient::WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin):FbTk::Fb
                      window_group(0),
                      x(0), y(0), old_bw(0),
                      min_width(1), min_height(1),
-                     max_width(1), max_height(1),
+                     max_width(0), max_height(0),
                      width_inc(1), height_inc(1),
                      min_aspect_x(1), min_aspect_y(1),
                      max_aspect_x(1), max_aspect_y(1),
@@ -434,8 +434,23 @@ void WinClient::updateWMNormalHints() {
         if (sizehint.flags & PMinSize) {
             min_width = sizehint.min_width;
             min_height = sizehint.min_height;
-        } else
+            if (!(sizehint.flags & PBaseSize)) {
+                base_width = min_width;
+                base_height = min_height;
+            }
+        } else {
             min_width = min_height = 1;
+            base_width = base_height = 0;
+        }
+
+        if (sizehint.flags & PBaseSize) {
+            base_width = sizehint.base_width;
+            base_height = sizehint.base_height;
+            if (!(sizehint.flags & PMinSize)) {
+                min_width = base_width;
+                min_height = base_height;
+            }
+        } // default set in PMinSize
 
         if (sizehint.flags & PMaxSize) {
             max_width = sizehint.max_width;
@@ -460,12 +475,6 @@ void WinClient::updateWMNormalHints() {
             min_aspect_x = min_aspect_y =
                 max_aspect_x = max_aspect_y = 1;
 
-        if (sizehint.flags & PBaseSize) {
-            base_width = sizehint.base_width;
-            base_height = sizehint.base_height;
-        } else
-            base_width = base_height = 0;
-
         if (sizehint.flags & PWinGravity)
             m_win_gravity = sizehint.win_gravity;
         else
@@ -605,3 +614,48 @@ void WinClient::updateWMProtocols() {
     }
 
 }
+
+
+/**
+ * Changes width and height to the nearest (lower) value
+ * that conforms to it's size hints.
+ *
+ * display_* give the values that would be displayed
+ * to the user when resizing.
+ * We use pointers for display_* since they are optional.
+ *
+ * See ICCCM section 4.1.2.3
+ */
+void WinClient::applySizeHints(int &width, int &height, 
+                               int *display_width, int *display_height) {
+
+    int i = width, j = height;
+
+    // Check minimum size
+    if (width < 0 || width < min_width) 
+        width = min_width;
+
+    if (height < 0 || height < min_height)
+        height = min_height;
+
+    // Check maximum size
+    if (max_width > 0 && width > max_width)
+        width = max_width;
+
+    if (max_height > 0 && height > max_height)
+        height = max_height;
+
+    // enforce incremental size limits, wrt base size
+    // only calculate this if we really need to
+    i = (width - base_width) / width_inc;
+    width = i*width_inc + base_width;
+
+    j = (height - base_height) / height_inc;
+    height = j*height_inc + base_height;
+
+    if (display_width)
+        *display_width = i;
+
+    if (display_height)
+        *display_height = j;
+}
diff --git a/src/WinClient.hh b/src/WinClient.hh
index 6bdfe3f..c93a76d 100644
--- a/src/WinClient.hh
+++ b/src/WinClient.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: WinClient.hh,v 1.14 2003/09/21 12:49:48 rathnor Exp $
+// $Id: WinClient.hh,v 1.15 2003/09/29 14:58:15 rathnor Exp $
 
 #ifndef WINCLIENT_HH
 #define WINCLIENT_HH
@@ -102,6 +102,16 @@ public:
     void updateWMHints();
     void updateWMNormalHints();
 
+    /**
+     * Changes width and height to the nearest (lower) value
+     * that conforms to it's size hints.
+     *
+     * display_* give the values that would be displayed
+     * to the user when resizing.
+     * We use pointers for display_* since they are optional.
+     */
+    void applySizeHints(int &width, int &height, int *display_width = 0, int *display_height = 0);
+
     // grouping is tracked by remembering the window to the left in the group
     Window getGroupLeftWindow() const;
     void setGroupLeftWindow(Window win);
diff --git a/src/Window.cc b/src/Window.cc
index 193f689..e6ff0c6 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Window.cc,v 1.235 2003/09/29 12:53:58 rathnor Exp $
+// $Id: Window.cc,v 1.236 2003/09/29 14:58:15 rathnor Exp $
 
 #include "Window.hh"
 
@@ -2437,11 +2437,11 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
 
             fixsize(&gx, &gy);
 
-           // draw resize rectangle
-           parent().drawRectangle(screen().rootTheme().opGC(),
-                                  m_last_resize_x, m_last_resize_y,
-                                  m_last_resize_w - 1 + 2 * frame().window().borderWidth(), 
-                                  m_last_resize_h - 1 + 2 * frame().window().borderWidth());
+            // draw resize rectangle
+            parent().drawRectangle(screen().rootTheme().opGC(),
+                                   m_last_resize_x, m_last_resize_y,
+                                   m_last_resize_w - 1 + 2 * frame().window().borderWidth(), 
+                                   m_last_resize_h - 1 + 2 * frame().window().borderWidth());
 
             if (screen().doShowWindowPos())
                 screen().showGeometry(gx, gy);
@@ -3166,7 +3166,7 @@ void FluxboxWindow::downsize() {
 }
 
 
-void FluxboxWindow::fixsize(int *gx, int *gy) {
+void FluxboxWindow::fixsize(int *user_w, int *user_h) {
     int titlebar_height = (decorations.titlebar ? 
                            frame().titlebar().height()  + 
                            frame().titlebar().borderWidth() : 0);
@@ -3177,49 +3177,20 @@ void FluxboxWindow::fixsize(int *gx, int *gy) {
 
     // dx is new width = current width + difference between new and old x values
     //int dx = frame().width() + frame().x() - m_last_resize_x;
-    int dx = m_last_resize_w - m_client->base_width;
+    int dw = m_last_resize_w;
 
     // dy = new height (w/o decorations), similarly
-    int dy = m_last_resize_h - m_client->base_height - decoration_height;
-
-    // check minimum size
-    if (dx < static_cast<signed int>(m_client->min_width))
-        dx = m_client->min_width;
-    if (dy < static_cast<signed int>(m_client->min_height))
-        dy = m_client->min_height;
-
-    // check maximum size
-    if (m_client->max_width > 0 && dx > static_cast<signed int>(m_client->max_width))
-        dx = m_client->max_width;
-    if (m_client->max_height > 0 && dy > static_cast<signed int>(m_client->max_height))
-        dy = m_client->max_height;
-
-    // make sure we have valid increment
-    if (m_client->width_inc == 0)
-        m_client->width_inc = 1;
-    if (m_client->height_inc == 0)
-        m_client->height_inc = 1;
-
-    // set snapping
-    dx /= m_client->width_inc;
-    dy /= m_client->height_inc;
-
-    // set return values
-    if (gx != 0)
-        *gx = dx;
-    if (gy != 0)
-        *gy = dy;
-
-    // snapping
-    dx = dx * m_client->width_inc + m_client->base_width;
-    dy = dy * m_client->height_inc + m_client->base_height + decoration_height;
+    int dh = m_last_resize_h - decoration_height;
+
+    m_client->applySizeHints(dw, dh, user_w, user_h);
 
     // update last resize 
-    m_last_resize_w = dx;
-    m_last_resize_h = dy;
+    m_last_resize_w = dw;
+    m_last_resize_h = dh + decoration_height;
 
+    // move X if necessary
     if (m_resize_corner == LEFTTOP || m_resize_corner == LEFTBOTTOM) {
-    m_last_resize_x = frame().x() + frame().width() - m_last_resize_w;	
+        m_last_resize_x = frame().x() + frame().width() - m_last_resize_w;	
     }
 
     if (m_resize_corner == LEFTTOP || m_resize_corner == RIGHTTOP) {
diff --git a/src/Window.hh b/src/Window.hh
index e023253..9d94166 100644
--- a/src/Window.hh
+++ b/src/Window.hh
@@ -22,7 +22,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Window.hh,v 1.96 2003/09/29 12:53:58 rathnor Exp $
+// $Id: Window.hh,v 1.97 2003/09/29 14:58:15 rathnor Exp $
 
 #ifndef	 WINDOW_HH
 #define	 WINDOW_HH
@@ -398,7 +398,8 @@ private:
 
     // modifies left and top if snap is necessary
     void doSnapping(int &left, int &top);
-    void fixsize(int *x = 0, int *y = 0);
+    // user_w/h return the values that should be shown to the user
+    void fixsize(int *user_w = 0, int *user_h = 0);
     void resizeClient(WinClient &client, unsigned int width, unsigned int height);
     /// sends configurenotify to all clients
     void sendConfigureNotify(bool send_to_netizens = true);
-- 
cgit v0.11.2