From 0ae3ca9e8a2a3398cf07789e0d141887d40dcb6f Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Fri, 22 Aug 2008 05:52:23 -0700
Subject: move fullscreen and maximization handling to FbWinFrame

---
 src/FbWinFrame.cc |  72 +++++++++++++++++++++++++
 src/FbWinFrame.hh |  23 +++++++-
 src/Remember.cc   |  22 ++++----
 src/Window.cc     | 158 +++++++-----------------------------------------------
 src/Window.hh     |  25 ++-------
 src/fluxbox.cc    |   2 +-
 6 files changed, 129 insertions(+), 173 deletions(-)

diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc
index f050a6d..03f7420 100644
--- a/src/FbWinFrame.cc
+++ b/src/FbWinFrame.cc
@@ -529,8 +529,60 @@ void FbWinFrame::setFullscreen(bool newvalue) {
     if (newvalue == m_state.fullscreen)
         return;
 
+    saveGeometry();
     m_state.fullscreen = newvalue;
+    applyState();
+}
+
+void FbWinFrame::setMaximized(int value) {
+    if (value == m_state.maximized)
+        return;
+
+    saveGeometry();
+    m_state.maximized = value;
+    applyState();
+}
+
+void FbWinFrame::saveGeometry() {
+    if (m_state.fullscreen || m_state.maximized)
+        return;
+
+    m_state.x = x();
+    m_state.y = y();
+    m_state.width = width();
+    m_state.height = height();
+}
+
+void FbWinFrame::applyState() {
     applyDecorations();
+
+    if (m_state.fullscreen) {
+        const int head = m_screen.getHead(window());
+        moveResize(m_screen.getHeadX(head), m_screen.getHeadY(head),
+                   m_screen.getHeadWidth(head), m_screen.getHeadHeight(head));
+    } else if (m_state.maximized) {
+        const int head = m_screen.getHead(window());
+        int new_x = m_state.x, new_y = m_state.y;
+        unsigned int new_w = m_state.width, new_h = m_state.height;
+        if (m_state.maximized & MAX_VERT) {
+            new_y = m_screen.maxTop(head);
+            new_h = m_screen.maxBottom(head) - new_y - 2*window().borderWidth();
+        }
+        if (m_state.maximized & MAX_HORZ) {
+            new_x = m_screen.maxLeft(head);
+            new_w = m_screen.maxRight(head) - new_x - 2*window().borderWidth();
+        }
+        if (!m_screen.getMaxOverTabs()) {
+            new_y += yOffset();
+            new_h -= heightOffset();
+            new_x += xOffset();
+            new_w -= widthOffset();
+        }
+        moveResize(new_x, new_y, new_w, new_h);
+    } else
+        moveResize(m_state.x, m_state.y, m_state.width, m_state.height);
+
+    frameExtentSig().notify();
 }
 
 void FbWinFrame::setAlpha(bool focused, unsigned char alpha) {
@@ -1662,7 +1714,27 @@ void FbWinFrame::gravityTranslate(int &x, int &y,
     }
 }
 
+int FbWinFrame::normalX() const {
+    if ((m_state.maximized & MAX_HORZ) || m_state.fullscreen)
+        return m_state.x;
+    return x();
+}
+
+int FbWinFrame::normalY() const {
+    if ((m_state.maximized & MAX_VERT) || m_state.fullscreen)
+        return m_state.y;
+    return y();
+}
+
+unsigned int FbWinFrame::normalWidth() const {
+    if ((m_state.maximized & MAX_HORZ) || m_state.fullscreen)
+        return m_state.width;
+    return width();
+}
+
 unsigned int FbWinFrame::normalHeight() const {
+    if ((m_state.maximized & MAX_VERT) || m_state.fullscreen)
+        return m_state.height;
     if (m_state.shaded)
         return m_height_before_shade;
     return height();
diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh
index 5756c8e..d2f7a1f 100644
--- a/src/FbWinFrame.hh
+++ b/src/FbWinFrame.hh
@@ -69,6 +69,16 @@ public:
     };
 
     /**
+     * Types of maximization
+     */
+    enum MaximizeMode {
+        MAX_NONE = 0, ///< normal state
+        MAX_HORZ = 1, ///< maximize horizontal
+        MAX_VERT = 2, ///< maximize vertical
+        MAX_FULL = 3  ///< maximize full
+    };
+
+    /**
        This enumeration represents individual decoration
        attributes, they can be OR-d together to get a mask.
        Useful for saving.
@@ -126,12 +136,15 @@ public:
             size_hints(),
             deco_mask(DECOR_NORMAL),
             focused(false),
-            shaded(false), fullscreen(false), maximized(0) { }
+            shaded(false), fullscreen(false), maximized(0),
+            x(0), y(0), width(1), height(1) { }
 
         SizeHints size_hints;
         unsigned int deco_mask;
         bool focused, shaded, fullscreen;
         int maximized;
+        int x, y;
+        unsigned int width, height;
     };
 
     /// create a top level window
@@ -182,7 +195,7 @@ public:
     /// set focus/unfocus style
     void setFocus(bool newvalue);
     void setFullscreen(bool value);
-    void setMaximized(int value) { m_state.maximized = value; }
+    void setMaximized(int value);
 
     void setFocusTitle(const std::string &str) { m_label.setText(str); }
     bool setTabMode(TabMode tabmode);
@@ -237,6 +250,8 @@ public:
     static int getDecoMaskFromString(const std::string &str);
     void setDecorationMask(unsigned int mask) { m_state.deco_mask = mask; }
     void applyDecorations();
+    void applyState();
+    void saveGeometry();
 
     /// determine if the given decoration should be shown in current state
     bool useBorder() const;
@@ -271,6 +286,10 @@ public:
     int y() const { return m_window.y(); }
     unsigned int width() const { return m_window.width(); }
     unsigned int height() const { return m_window.height(); }
+
+    int normalX() const;
+    int normalY() const;
+    unsigned int normalWidth() const;
     unsigned int normalHeight() const;
 
     // extra bits for tabs
diff --git a/src/Remember.cc b/src/Remember.cc
index a1f5d62..1df5045 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -535,13 +535,13 @@ int parseApp(ifstream &file, Application &app, string *first_line = 0) {
                 app.rememberMinimizedstate((strcasecmp(str_label.c_str(), "yes") == 0));
             } else if (str_key == "maximized") {
                 if (strcasecmp(str_label.c_str(), "yes") == 0)
-                    app.rememberMaximizedstate(FluxboxWindow::MAX_FULL);
+                    app.rememberMaximizedstate(FbWinFrame::MAX_FULL);
                 else if (strcasecmp(str_label.c_str(), "horz") == 0)
-                    app.rememberMaximizedstate(FluxboxWindow::MAX_HORZ);
+                    app.rememberMaximizedstate(FbWinFrame::MAX_HORZ);
                 else if (strcasecmp(str_label.c_str(), "vert") == 0)
-                    app.rememberMaximizedstate(FluxboxWindow::MAX_VERT);
+                    app.rememberMaximizedstate(FbWinFrame::MAX_VERT);
                 else
-                    app.rememberMaximizedstate(FluxboxWindow::MAX_NONE);
+                    app.rememberMaximizedstate(FbWinFrame::MAX_NONE);
             } else if (str_key == "fullscreen") {
                 app.rememberFullscreenstate((strcasecmp(str_label.c_str(), "yes") == 0));
             } else if (str_key == "jump") {
@@ -999,16 +999,16 @@ void Remember::save() {
         if (a.maximizedstate_remember) {
             apps_file << "  [Maximized]\t{";
             switch (a.maximizedstate) {
-            case FluxboxWindow::MAX_FULL:
+            case FbWinFrame::MAX_FULL:
                 apps_file << "yes" << "}" << endl;
                 break;
-            case FluxboxWindow::MAX_HORZ:
+            case FbWinFrame::MAX_HORZ:
                 apps_file << "horz" << "}" << endl;
                 break;
-            case FluxboxWindow::MAX_VERT:
+            case FbWinFrame::MAX_VERT:
                 apps_file << "vert" << "}" << endl;
                 break;
-            case FluxboxWindow::MAX_NONE:
+            case FbWinFrame::MAX_NONE:
             default:
                 apps_file << "no" << "}" << endl;
                 break;
@@ -1115,13 +1115,15 @@ void Remember::rememberAttrib(WinClient &winclient, Attribute attrib) {
         app->rememberHead(win->screen().getHead(win->fbWindow()));
         break;
     case REM_DIMENSIONS:
-        app->rememberDimensions(win->normalWidth(), win->normalHeight());
+        app->rememberDimensions(win->frame().normalWidth(),
+                                win->frame().normalHeight());
         break;
     case REM_POSITION: {
         int head = win->screen().getHead(win->fbWindow());
         int head_x = win->screen().maxLeft(head);
         int head_y = win->screen().maxTop(head);
-        app->rememberPosition(win->normalX() - head_x, win->normalY() - head_y);
+        app->rememberPosition(win->frame().normalX() - head_x,
+                              win->frame().normalY() - head_y);
         break;
     }
     case REM_FOCUSHIDDENSTATE:
diff --git a/src/Window.cc b/src/Window.cc
index 79419d0..c91e875 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -271,7 +271,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbTk::XLayer &layer):
     m_creation_time(0),
     moving(false), resizing(false), shaded(false), iconic(false),
     stuck(false), m_initialized(false), fullscreen(false),
-    maximized(MAX_NONE),
+    maximized(FbWinFrame::MAX_NONE),
     m_attaching_tab(0),
     display(FbTk::App::instance()->display()),
     m_button_grab_x(0), m_button_grab_y(0),
@@ -287,8 +287,6 @@ FluxboxWindow::FluxboxWindow(WinClient &client, FbTk::XLayer &layer):
     m_focus_new(BoolAcc(screen().focusControl(), &FocusControl::focusNew)),
     m_mouse_focus(BoolAcc(screen().focusControl(), &FocusControl::isMouseFocus)),
     m_click_focus(true),
-    m_old_pos_x(0), m_old_pos_y(0),
-    m_old_width(1),  m_old_height(1),
     m_last_button_x(0),  m_last_button_y(0),
     m_button_theme(*this, screen().focusedWinButtonTheme(),
                    screen().unfocusedWinButtonTheme()),
@@ -561,7 +559,7 @@ void FluxboxWindow::init() {
 
     if (maximized) {
         int tmp = maximized;
-        maximized = MAX_NONE;
+        maximized = FbWinFrame::MAX_NONE;
         setMaximizedState(tmp);
     }
 
@@ -1444,35 +1442,16 @@ void FluxboxWindow::setFullscreen(bool flag) {
         return;
     }
 
-    const int head = screen().getHead(fbWindow());
-
     if (flag && !isFullscreen()) {
 
         if (isShaded())
             shade();
 
         m_old_layernum = layerNum();
-        if (!maximized) {
-            m_old_pos_x = frame().x();
-            m_old_pos_y = frame().y();
-            m_old_width = frame().width();
-            m_old_height = frame().height();
-        }
-
         fullscreen = true;
         frame().setFullscreen(true);
 
-        // dont call Window::moveResize here, it might ignore the 
-        // resize if win state is not resizable; 
-        // instead we call frame resize directly
-        // (see tests/fullscreentest.cc)
-
-        // be xinerama aware
-        frame().moveResize(screen().getHeadX(head), screen().getHeadY(head),
-                           screen().getHeadWidth(head), screen().getHeadHeight(head));
-        sendConfigureNotify();
-
-        setFullscreenLayer();
+        setFullscreenLayer(); // calls stateSig().notify()
         if (!isFocused())
             screen().focusedWindowSig().attach(this);
 
@@ -1481,21 +1460,8 @@ void FluxboxWindow::setFullscreen(bool flag) {
         fullscreen = false;
         frame().setFullscreen(false);
 
-        // ensure we apply the sizehints here, otherwise some
-        // apps (eg xterm) end up a little bit .. crappy (visually)
-        frame().applySizeHints(m_old_width, m_old_height);
-
-        moveResize(m_old_pos_x, m_old_pos_y, m_old_width, m_old_height);
         moveToLayer(m_old_layernum);
-
-        m_old_layernum = ::Layer::NORMAL;
-
-        if (maximized) {
-            int tmp = maximized;
-            maximized = MAX_NONE;
-            setMaximizedState(tmp);
-        } else
-            stateSig().notify();
+        stateSig().notify();
     }
 }
 
@@ -1507,8 +1473,7 @@ void FluxboxWindow::setFullscreenLayer() {
         getOnHead() != foc->getOnHead()) {
         moveToLayer(::Layer::ABOVE_DOCK);
     } else {
-        moveToLayer(m_old_layernum);
-        lower();
+        moveToLayer(::Layer::DESKTOP);
     }
     stateSig().notify();
 
@@ -1520,7 +1485,7 @@ void FluxboxWindow::setFullscreenLayer() {
 void FluxboxWindow::maximize(int type) {
 
     // nothing to do
-    if (type == MAX_NONE)
+    if (type == FbWinFrame::MAX_NONE)
         return;
 
     int new_max = maximized;
@@ -1529,19 +1494,21 @@ void FluxboxWindow::maximize(int type) {
     // when _don't_ we want to toggle?
     // - type is horizontal maximise, or
     // - type is full and we are not maximised horz but already vertically
-    if (type != MAX_HORZ && !(type == MAX_FULL && maximized == MAX_VERT))
-        new_max ^= MAX_VERT;
+    if (type != FbWinFrame::MAX_HORZ &&
+        (type != FbWinFrame::MAX_FULL || maximized != FbWinFrame::MAX_VERT))
+        new_max ^= FbWinFrame::MAX_VERT;
 
     // maximize horizontally?
-    if (type != MAX_VERT && !(type == MAX_FULL && maximized == MAX_HORZ))
-        new_max ^= MAX_HORZ;
+    if (type != FbWinFrame::MAX_VERT &&
+        (type != FbWinFrame::MAX_FULL || maximized != FbWinFrame::MAX_HORZ))
+        new_max ^= FbWinFrame::MAX_HORZ;
 
     setMaximizedState(new_max);
 }
 
 void FluxboxWindow::setMaximizedState(int type) {
 
-    if (!m_initialized || isFullscreen() || type == maximized) {
+    if (!m_initialized || type == maximized) {
         // this will interfere with window placement, so we delay it
         maximized = type;
         return;
@@ -1553,69 +1520,8 @@ void FluxboxWindow::setMaximizedState(int type) {
     if (isResizing())
         stopResizing();
 
-    int head = screen().getHead(frame().window());
-    int new_x = frame().x(), new_y = frame().y();
-    unsigned int new_w = frame().width(), new_h = frame().height();
-
-    // These evaluate whether we need to TOGGLE the value for that field
-    // Why? If maximize is only set to zero outside this,
-    // and we only EVER toggle them, then:
-    // 1) We will never loose the old_ values
-    // 2) It shouldn't get confused
-
-    // Worst case being that some action will toggle the wrong way, but
-    // we still won't lose the state in that case.
-
-    // toggle maximize vertically?
-    if ((maximized ^ type) & MAX_VERT) {
-        // already maximized in that direction?
-        if (maximized & MAX_VERT) {
-            new_y = m_old_pos_y;
-            new_h = m_old_height;
-        } else {
-            m_old_pos_y  = new_y;
-            m_old_height = new_h;
-            new_y = screen().maxTop(head);
-            new_h = screen().maxBottom(head) - new_y - 2*frame().window().borderWidth();
-            if (!screen().getMaxOverTabs()) {
-                new_y += yOffset();
-                new_h -= heightOffset();
-            }
-        }
-        maximized ^= MAX_VERT;
-    }
-
-    // toggle maximize horizontally?
-    if ((maximized ^ type) & MAX_HORZ) {
-        // already maximized in that direction?
-        if (maximized & MAX_HORZ) {
-            new_x = m_old_pos_x;
-            new_w = m_old_width;
-        } else {
-            // only save if we weren't already maximized
-            m_old_pos_x = new_x;
-            m_old_width = new_w;
-            new_x = screen().maxLeft(head);
-            new_w = screen().maxRight(head) - new_x - 2*frame().window().borderWidth();
-            if (!screen().getMaxOverTabs()) {
-                new_x += xOffset();
-                new_w -= widthOffset();
-            }
-        }
-        maximized ^= MAX_HORZ;
-    }
-
-    frame().setMaximized(maximized);
-    // ensure we apply the sizehints here, otherwise some
-    // apps (eg xterm) end up a little bit .. crappy (visually)
-
-    // frankly, that xterm bug was pretty obscure, and it's really annoying not
-    // being able to maximize my terminals, so we make an option
-    // but we do fix size hints when restoring the window to normal size
-    if (!screen().getMaxIgnoreIncrement() || !maximized)
-        frame().applySizeHints(new_w, new_h, maximized ? true : false);
-
-    moveResize(new_x, new_y, new_w, new_h);
+    maximized = type;
+    frame().setMaximized(type);
 
     // notify listeners that we changed state
     stateSig().notify();
@@ -1625,21 +1531,21 @@ void FluxboxWindow::setMaximizedState(int type) {
  * Maximize window horizontal
  */
 void FluxboxWindow::maximizeHorizontal() {
-    maximize(MAX_HORZ);
+    maximize(FbWinFrame::MAX_HORZ);
 }
 
 /**
  * Maximize window vertical
  */
 void FluxboxWindow::maximizeVertical() {
-    maximize(MAX_VERT);
+    maximize(FbWinFrame::MAX_VERT);
 }
 
 /**
  * Maximize window fully
  */
 void FluxboxWindow::maximizeFull() {
-    maximize(MAX_FULL);
+    maximize(FbWinFrame::MAX_FULL);
 }
 
 void FluxboxWindow::setWorkspace(int n) {
@@ -3248,7 +3154,7 @@ void FluxboxWindow::startResizing(int x, int y, ReferenceCorner dir) {
     m_resize_corner = dir;
 
     resizing = true;
-    maximized = MAX_NONE;
+    maximized = FbWinFrame::MAX_NONE;
     frame().setMaximized(maximized);
 
     const Cursor& cursor = (m_resize_corner == LEFTTOP) ? frame().theme()->upperLeftAngleCursor() :
@@ -3541,32 +3447,6 @@ bool FluxboxWindow::isTransient() const {
     return (m_client && m_client->isTransient());
 }
 
-int FluxboxWindow::normalX() const {
-    if (maximized & MAX_HORZ || fullscreen)
-        return m_old_pos_x;
-    return x();
-}
-
-int FluxboxWindow::normalY() const {
-    if (maximized & MAX_VERT || fullscreen)
-        return m_old_pos_y;
-    return y();
-}
-
-unsigned int FluxboxWindow::normalWidth() const {
-    if (maximized & MAX_HORZ || fullscreen)
-        return m_old_width;
-    return width();
-}
-
-unsigned int FluxboxWindow::normalHeight() const {
-    if (maximized & MAX_VERT || fullscreen)
-        return m_old_height;
-    if (shaded)
-        return frame().normalHeight();
-    return height();
-}
-
 int FluxboxWindow::initialState() const { return m_client->initial_state; }
 
 void FluxboxWindow::fixsize() {
diff --git a/src/Window.hh b/src/Window.hh
index 5cf755e..16d5bc9 100644
--- a/src/Window.hh
+++ b/src/Window.hh
@@ -87,16 +87,6 @@ public:
         MwmDecorMaximize    = (1l << 6)  /// maximize
     };
 
-    /**
-     * Types of maximization
-     */
-    enum MaximizeMode {
-        MAX_NONE = 0, ///< normal state
-        MAX_HORZ = 1, ///< maximize horizontal
-        MAX_VERT = 2, ///< maximize vertical
-        MAX_FULL = 3  ///< maximize full
-    };
-
     /// Different resize modes when resizing a window
     enum ResizeModel {
         QUADRANTRESIZE,                   ///< resizes from one quadrant
@@ -222,7 +212,7 @@ public:
     /// set fullscreen
     void setFullscreen(bool flag);
     /// toggle maximize
-    void maximize(int type = MAX_FULL);
+    void maximize(int type = FbWinFrame::MAX_FULL);
     /// sets the maximized state
     void setMaximizedState(int type);
     /// maximizes the window horizontal
@@ -383,9 +373,9 @@ public:
     bool isIconic() const { return iconic; }
     bool isShaded() const { return shaded; }
     bool isFullscreen() const { return fullscreen; }
-    bool isMaximized() const { return maximized == MAX_FULL; }
-    bool isMaximizedVert() const { return (bool)(maximized & MAX_VERT); }
-    bool isMaximizedHorz() const { return (bool)(maximized & MAX_HORZ); }
+    bool isMaximized() const { return maximized == FbWinFrame::MAX_FULL; }
+    bool isMaximizedVert() const { return (bool)(maximized & FbWinFrame::MAX_VERT); }
+    bool isMaximizedHorz() const { return (bool)(maximized & FbWinFrame::MAX_HORZ); }
     int maximizedState() const { return maximized; }
     bool isIconifiable() const { return functions.iconify; }
     bool isMaximizable() const { return functions.maximize; }
@@ -435,11 +425,6 @@ public:
     unsigned int width() const { return frame().width(); }
     unsigned int height() const { return frame().height(); }
 
-    int normalX() const;
-    int normalY() const;
-    unsigned int normalWidth() const;
-    unsigned int normalHeight() const;
-
     int xOffset() const { return frame().xOffset(); }
     int yOffset() const { return frame().yOffset(); }
     int widthOffset() const { return frame().widthOffset(); }
@@ -587,8 +572,6 @@ private:
     /// if the window is focused with EnterNotify
     FbTk::DefaultValue<bool, BoolAcc> m_mouse_focus;
     bool m_click_focus;  ///< if the window is focused by clicking
-    int m_old_pos_x, m_old_pos_y; ///< old position so we can restore from maximized
-    unsigned int m_old_width, m_old_height; ///< old size so we can restore from maximized state
     int m_last_button_x, ///< last known x position of the mouse button
         m_last_button_y; ///< last known y position of the mouse button
 
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index d9deea7..5056624 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -263,7 +263,7 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile
     m_reconfig_timer.setCommand(reconfig_cmd);
     m_reconfig_timer.fireOnce(true);
 
-    // XSynchronize(disp, True);
+    XSynchronize(disp, True);
 
     s_singleton = this;
     m_have_shape = false;
-- 
cgit v0.11.2