From d6befe5371c5df7d719cb184c4d20e38dc841a13 Mon Sep 17 00:00:00 2001
From: mathias <mathias>
Date: Wed, 16 Mar 2005 23:19:36 +0000
Subject: fix for gravity field on _NET_MOVERESIZE_WINDOW messages, patch from
 Rob Stevens <stever3 at nycap dot rr dot com>

---
 ChangeLog         |   4 ++-
 src/Ewmh.cc       |   7 ++--
 src/FbWinFrame.cc | 103 ++++++++++++++++++++++++++++++++----------------------
 src/FbWinFrame.hh |  13 +++----
 src/Window.cc     |  23 ++++++++++++
 src/Window.hh     |   3 +-
 6 files changed, 100 insertions(+), 53 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0a8e261..7a04b22 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,9 @@
 (Format: Year/Month/Day)
 Changes for 0.9.13
 *05/03/16:
-    added new option to specify, on which screen fluxbox should handle 
+  * fix for gravity field on _NET_MOVERESIZE_WINDOW (thanx to Rob Stevens)
+    Ewmh.cc, Window.(cc,hh), FbWinFrame.(cc,hh)
+  * added new option to specify, on which screen fluxbox should handle 
     the windows. default behavior is to handle each available screen. 
     closes #1159809. (Mathias)
 
diff --git a/src/Ewmh.cc b/src/Ewmh.cc
index 34c166c..d6ccf36 100644
--- a/src/Ewmh.cc
+++ b/src/Ewmh.cc
@@ -706,9 +706,10 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
         // ce.data.l[2] = y
         // ce.data.l[3] = width
         // ce.data.l[4] = height
-        // TODO: gravity and flags
-        winclient->fbwindow()->moveResize(ce.data.l[1], ce.data.l[2],
-                                          ce.data.l[3], ce.data.l[4]);
+        // TODO: flags
+        int win_gravity=ce.data.l[0] & 0xFF;
+        winclient->fbwindow()->moveResizeForClient(ce.data.l[1], ce.data.l[2],
+                                          ce.data.l[3], ce.data.l[4], win_gravity);
         return true;
     }
 
diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc
index 266f5c4..d4a3d66 100644
--- a/src/FbWinFrame.cc
+++ b/src/FbWinFrame.cc
@@ -166,16 +166,16 @@ void FbWinFrame::shade() {
 }
 
 
-void FbWinFrame::move(int x, int y) {
-    moveResize(x, y, 0, 0, true, false);
+void FbWinFrame::move(int x, int y, int win_gravity) {
+    moveResize(x, y, 0, 0, true, false, win_gravity);
 }
 
-void FbWinFrame::resize(unsigned int width, unsigned int height) {
-    moveResize(0, 0, width, height, false, true);
+void FbWinFrame::resize(unsigned int width, unsigned int height, int win_gravity) {
+    moveResize(0, 0, width, height, false, true, win_gravity);
 }
 
 // need an atomic moveresize where possible
-void FbWinFrame::moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move, bool resize) {
+void FbWinFrame::moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move, bool resize, int win_gravity) {
     // total height for frame
 
     unsigned int total_height = height;
@@ -188,14 +188,17 @@ void FbWinFrame::moveResizeForClient(int x, int y, unsigned int width, unsigned
         if (m_use_handle)
             total_height += m_handle.height() + m_handle.borderWidth();
     }
-    moveResize(x, y, width, total_height, move, resize);
+    moveResize(x, y, width, total_height, move, resize, win_gravity);
 }
 
-void FbWinFrame::resizeForClient(unsigned int width, unsigned int height) {
-    moveResizeForClient(0, 0, width, height, false, true);
+void FbWinFrame::resizeForClient(unsigned int width, unsigned int height, int win_gravity) {
+    moveResizeForClient(0, 0, width, height, false, true, win_gravity);
 }
 
-void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height, bool move, bool resize) {
+void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height, bool move, bool resize, int win_gravity) {
+    if(win_gravity!=ForgetGravity) {
+        gravityTranslate(x, y, width + m_window.borderWidth()*2, height + m_window.borderWidth()*2, win_gravity, false);
+    }
     if (move && x == window().x() && y == window().y()) 
         move = false;
 
@@ -1456,6 +1459,10 @@ void FbWinFrame::updateTransparent() {
 // if win_gravity is negative, it does an inverse translation
 // This function should be used when a window is mapped/unmapped/pos configured
 void FbWinFrame::gravityTranslate(int &x, int &y, int win_gravity, bool move_frame) {
+    gravityTranslate(x, y, m_window.width(), m_window.height(), win_gravity, move_frame);
+}
+//use width and height given instead of the real values, allows figuring out where to place a window before doing a moveResize
+void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned int height, int win_gravity, bool move_frame) {
     bool invert = false;
     if (win_gravity < 0) {
         invert = true;
@@ -1483,44 +1490,57 @@ void FbWinFrame::gravityTranslate(int &x, int &y, int win_gravity, bool move_fra
     int x_offset = 0;
     int y_offset = 0;
 
-    // mostly no X offset, since we don't have extra frame on the sides
-    switch (win_gravity) {
-    case NorthWestGravity:
-    case NorthGravity:
-    case NorthEastGravity:
-        // no offset, since the top point is still the same
-        break;
-    case SouthWestGravity:
-    case SouthGravity:
-    case SouthEastGravity:
-        // window shifted down by height of titlebar, and the handle
-        // since that's necessary to get the bottom of the frame
-        // all the way up
-        if (m_use_titlebar)
-            y_offset -= m_titlebar.height() + m_titlebar.borderWidth();
-        if (m_use_handle)
-            y_offset -= m_handle.height() + m_handle.borderWidth();
-        break;
-    case WestGravity:
-    case EastGravity:
-    case CenterGravity:
-        // these centered ones are a little more interesting
-        if (m_use_titlebar)
-            y_offset -= m_titlebar.height() + m_titlebar.borderWidth();
-        if (m_use_handle)
-            y_offset -= m_handle.height() + m_handle.borderWidth();
-        y_offset /= 2;
-        break;
-    case StaticGravity:
+    /* win_gravity:    placed at the reference point
+     * StaticGravity    the left top corner of the client window
+     * NorthWestGravity    the left top corner of the frame window
+     * NorthGravity    the center of the frame window's top side
+     * NorthEastGravity    the right top corner of the frame window
+     * EastGravity    the center of the frame window's right side
+     * SouthEastGravity    the right bottom corner of the frame window
+     * SouthGravity    the center of the frame window's bottom side
+     * SouthWestGravity    the left bottom corner of the frame window
+     * WestGravity    the center of the frame window's left side
+     * CenterGravity    the center of the frame window
+     */ 
+    
+
+    //vertical offset
+    //North Gravities don't require a vertical offset
+    //South Gravities
+    if (win_gravity==SouthWestGravity || win_gravity==SouthGravity ||
+        win_gravity==SouthEastGravity) {
+        //We start on the frame so going the full height would take us one pixel past the edge of the frame
+        y_offset-=height-1;
+    }
+
+    //vertical centering
+    if (win_gravity==WestGravity || win_gravity==CenterGravity ||
+        win_gravity==EastGravity) {
+        y_offset-=height/2;
+    }
+
+    //horizontal offset
+    //West Gravities don't require a horizontal offset
+    //East Gravities
+    if (win_gravity==NorthEastGravity || win_gravity==EastGravity ||
+        win_gravity==SouthEastGravity ) {
+        //Starting on the frame so offset of one width would end up one pixel beyond the border
+        x_offset-=width-1;
+    }
+    //horizontal centering
+    if (win_gravity==NorthGravity || win_gravity==CenterGravity ||
+        win_gravity==SouthGravity ) {
+        x_offset-=width/2;
+    }
+
+    if( win_gravity==StaticGravity ) {
         if (m_use_titlebar)
             y_offset -= m_titlebar.height() + m_titlebar.borderWidth();
-        // static is the only one that also has the
-        // border taken into account
         x_offset -= m_window.borderWidth();
         y_offset -= m_window.borderWidth();
-        break;
     }
 
+
     if (invert) {
         x_offset = -x_offset;
         y_offset = -y_offset;
@@ -1528,7 +1548,6 @@ void FbWinFrame::gravityTranslate(int &x, int &y, int win_gravity, bool move_fra
 
     x += x_offset;
     y += y_offset;
-
     if (move_frame && (x_offset != 0 || y_offset != 0)) {
         move(x, y);
     }
diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh
index 32161d1..768f733 100644
--- a/src/FbWinFrame.hh
+++ b/src/FbWinFrame.hh
@@ -76,16 +76,16 @@ public:
     inline bool isVisible() const { return m_visible; }
     /// shade frame (ie resize to titlebar size)
     void shade();
-    void move(int x, int y);
-    void resize(unsigned int width, unsigned int height);
+    void move(int x, int y, int win_gravity=ForgetGravity);
+    void resize(unsigned int width, unsigned int height, int win_gravity=ForgetGravity);
     /// resize client to specified size and resize frame to it
-    void resizeForClient(unsigned int width, unsigned int height);
+    void resizeForClient(unsigned int width, unsigned int height, int win_gravity=ForgetGravity);
 
     // for when there needs to be an atomic move+resize operation
-    void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move = true, bool resize = true);
+    void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move = true, bool resize = true, int win_gravity=ForgetGravity);
 
     // can elect to ignore move or resize (mainly for use of move/resize individual functions
-    void moveResize(int x, int y, unsigned int width, unsigned int height, bool move = true, bool resize = true);
+    void moveResize(int x, int y, unsigned int width, unsigned int height, bool move = true, bool resize = true, int win_gravity=ForgetGravity);
 
     /// set focus/unfocus style
     void setFocus(bool newvalue);
@@ -133,7 +133,8 @@ public:
     // this function translates its arguments according to win_gravity
     // if win_gravity is negative, it does an inverse translation
     void gravityTranslate(int &x, int &y, int win_gravity, bool move_frame = false);
-
+    //use width and height given instead of the real values, allows figuring out where to place a window before doing a moveResize
+    void gravityTranslate(int &x, int &y, unsigned int width, unsigned int height, int win_gravity, bool move_frame = false);
     void setBorderWidth(unsigned int borderW);
 
     /**
diff --git a/src/Window.cc b/src/Window.cc
index 0bee703..e1fea07 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -1387,6 +1387,29 @@ void FluxboxWindow::moveResize(int new_x, int new_y,
 
 }
 
+void FluxboxWindow::moveResizeForClient(int new_x, int new_y,
+                               unsigned int new_width, unsigned int new_height, int gravity) {
+
+    // magic to detect if moved during initialisation
+    if (!isInitialized())
+        m_old_pos_x = 1;
+    frame().moveResizeForClient(new_x, new_y, new_width, new_height, true, true, gravity);
+    setFocusFlag(focused);
+    shaded = false;
+    sendConfigureNotify();
+
+    shape();
+
+    if (!moving) {
+        m_last_resize_x = new_x;
+        m_last_resize_y = new_y;
+    }
+
+}
+
+
+
+
 // returns whether the focus was "set" to this window
 // it doesn't guarantee that it has focus, but says that we have
 // tried. A FocusqIn event should eventually arrive for that
diff --git a/src/Window.hh b/src/Window.hh
index ac13da6..f4a038a 100644
--- a/src/Window.hh
+++ b/src/Window.hh
@@ -233,7 +233,8 @@ public:
     void resize(unsigned int width, unsigned int height);
     /// move and resize frame to pox x,y and size width, height
     void moveResize(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity);
-
+    /// move to pos x,y and resize client window to size width, height
+    void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity);
     void setWorkspace(int n);
     void changeBlackboxHints(const BlackboxHints &bh);
     void updateFunctions();
-- 
cgit v0.11.2