From a4c41f621b97084516299a322d62750f2e86b6a9 Mon Sep 17 00:00:00 2001
From: rathnor <rathnor>
Date: Tue, 23 Sep 2003 13:52:05 +0000
Subject: add support for _NET_WM_STATE_FULLSCREEN

---
 ChangeLog     |  4 +++
 src/Ewmh.cc   | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 src/Ewmh.hh   | 30 +++++++++++++++----
 src/Window.cc | 12 +++++---
 src/Window.hh |  6 ++--
 5 files changed, 125 insertions(+), 21 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 07a1131..035fbae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 (Format: Year/Month/Day)
 Changes for 0.9.6:
+*03/09/23:
+  * Add support for _NET_WM_STATE_FULLSCREEN (Simon)
+    - fixes mozilla/firebird fullscreen
+    Ewmh.hh/cc Window.hh/cc
 *03/09/22:
   * Fix invisible minimize button for non-pixmap themes (Simon)
     WinButton.cc
diff --git a/src/Ewmh.cc b/src/Ewmh.cc
index 6b38e86..5924203 100644
--- a/src/Ewmh.cc
+++ b/src/Ewmh.cc
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Ewmh.cc,v 1.32 2003/08/27 21:06:04 fluxgen Exp $
+// $Id: Ewmh.cc,v 1.33 2003/09/23 13:52:05 rathnor Exp $
 
 #include "Ewmh.hh" 
 
@@ -76,9 +76,10 @@ void Ewmh::initForScreen(BScreen &screen) {
         m_net_wm_state_shaded,
 	m_net_wm_state_maximized_horz,
 	m_net_wm_state_maximized_vert,
-		
+	m_net_wm_state_fullscreen,
+
         m_net_wm_desktop,
-				
+
         // root properties
         m_net_client_list,
         m_net_number_of_desktops,
@@ -132,6 +133,10 @@ void Ewmh::setupFrame(FluxboxWindow &win) {
 
 }
 
+void Ewmh::updateFrameClose(FluxboxWindow &win) {
+    clearState(win);
+}
+
 void Ewmh::updateClientList(BScreen &screen) {
     size_t num=0;
 
@@ -411,6 +416,7 @@ void Ewmh::createAtoms() {
     m_net_wm_state_shaded = XInternAtom(disp, "_NET_WM_STATE_SHADED", False);
     m_net_wm_state_maximized_horz = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
     m_net_wm_state_maximized_vert = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+    m_net_wm_state_fullscreen = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False);
     
     m_net_wm_strut = XInternAtom(disp, "_NET_WM_STRUT", False);
     m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", False);
@@ -421,8 +427,44 @@ void Ewmh::createAtoms() {
     m_net_wm_ping = XInternAtom(disp, "_NET_WM_PING", False);
 }
 
+
+void Ewmh::setFullscreen(FluxboxWindow &win, bool value) {
+    // fullscreen implies maximised, above dock layer, 
+    // and no decorations (or decorations offscreen)
+    WindowState *saved_state = getState(win);
+    if (value) {
+        // fullscreen on
+        if (!saved_state) { // not already fullscreen
+            saved_state = new WindowState(win.x(), win.y(), win.width(),
+                                          win.height(), win.layerNum(), win.decorationMask());
+            saveState(win, saved_state);
+
+            // actually make it fullscreen
+
+            // clear decorations
+            win.setDecorationMask(0);
+
+            // be xinerama aware
+            BScreen &screen = win.screen();
+            int head = screen.getHead(win.fbWindow());
+            win.moveResize(screen.getHeadX(head), screen.getHeadY(head),
+                           screen.getHeadWidth(head), screen.getHeadHeight(head));
+            win.moveToLayer(Fluxbox::instance()->getAboveDockLayer());
+        }
+    } else { // turn off fullscreen
+        if (saved_state) { // no saved state, can't restore it
+            win.setDecorationMask(saved_state->decor);
+            win.moveResize(saved_state->x, saved_state->y,
+                           saved_state->width, saved_state->height);
+            win.moveToLayer(saved_state->layer);
+            clearState(win);
+            saved_state = 0;
+        }
+    }
+}
+
 // set window state
-void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) const {
+void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) {
 
     if (state == m_net_wm_state_sticky) { // STICKY
         if (value && !win.isStuck() ||
@@ -440,13 +482,13 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) const {
         if ((value && !win.isMaximized()) ||
             (!value && win.isMaximized()))
 		win.maximizeVertical();
+    } else if (state == m_net_wm_state_fullscreen) { // fullscreen
+        setFullscreen(win, value);
     }
-    
-	
 }
 
 // toggle window state
-void Ewmh::toggleState(FluxboxWindow &win, Atom state) const {
+void Ewmh::toggleState(FluxboxWindow &win, Atom state) {
     if (state == m_net_wm_state_sticky) {
         win.stick();
     } else if (state == m_net_wm_state_shaded){
@@ -455,8 +497,9 @@ void Ewmh::toggleState(FluxboxWindow &win, Atom state) const {
         win.maximizeHorizontal();
     } else if (state == m_net_wm_state_maximized_vert) { // maximized Vertical
         win.maximizeVertical();
+    } else if (state == m_net_wm_state_fullscreen) { // fullscreen
+        setFullscreen(win, getState(win) == 0); // toggle current state
     }
-    
 }
 
 
@@ -477,3 +520,38 @@ void Ewmh::updateStrut(WinClient &winclient) {
             winclient.screen().updateAvailableWorkspaceArea();
     }
 }
+
+Ewmh::WindowState::WindowState(int t_x, int t_y, 
+                               unsigned int t_width, 
+                               unsigned int t_height,
+                               int t_layer, unsigned int t_decor) :
+    x(t_x), y(t_y),
+    layer(t_layer),
+    width(t_width),
+    height(t_height),
+    decor(t_decor)
+{}
+
+Ewmh::WindowState *Ewmh::getState(FluxboxWindow &win) {
+    SavedState::iterator it = m_savedstate.find(&win);
+    if (it == m_savedstate.end())
+        return 0;
+    else
+        return it->second;
+}
+
+void Ewmh::clearState(FluxboxWindow &win) {
+    WindowState *state = 0;
+    SavedState::iterator it = m_savedstate.find(&win);
+    if (it == m_savedstate.end())
+        return;
+
+    state = it->second;
+
+    m_savedstate.erase(it);
+    delete state;
+}
+
+void Ewmh::saveState(FluxboxWindow &win, WindowState *state) {
+    m_savedstate[&win] = state;
+}
diff --git a/src/Ewmh.hh b/src/Ewmh.hh
index 08de6cf..c4419ba 100644
--- a/src/Ewmh.hh
+++ b/src/Ewmh.hh
@@ -19,12 +19,13 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: Ewmh.hh,v 1.11 2003/08/27 21:06:04 fluxgen Exp $
+// $Id: Ewmh.hh,v 1.12 2003/09/23 13:52:05 rathnor Exp $
 
 #include "AtomHandler.hh"
 
 #include <X11/Xatom.h>
 #include <vector>
+#include <map>
 
 class Ewmh:public AtomHandler {
 public:
@@ -50,16 +51,25 @@ public:
                             BScreen * screen, WinClient * const winclient);
 
     bool propertyNotify(WinClient &winclient, Atom the_property);
-    //ignore these ones
-    void updateFrameClose(FluxboxWindow &win) {}
+    void updateFrameClose(FluxboxWindow &win);
+
+    //ignore this one
     void updateClientClose(WinClient &winclient) {}
 
+    void setFullscreen(FluxboxWindow &win, bool value);
+
 private:
 	
+    typedef struct WindowState {
+        WindowState(int x, int y, unsigned int width, unsigned int height, int layer, unsigned int decor);
+        int x, y, layer;
+        unsigned int width, height, decor;
+    } WindowState;
+
     enum { STATE_REMOVE = 0, STATE_ADD = 1, STATE_TOGGLE = 2};
-	
-    void setState(FluxboxWindow &win, Atom state, bool value) const;
-    void toggleState(FluxboxWindow &win, Atom state) const;
+
+    void setState(FluxboxWindow &win, Atom state, bool value);
+    void toggleState(FluxboxWindow &win, Atom state);
     void createAtoms();
     void updateStrut(WinClient &winclient);
 
@@ -76,6 +86,7 @@ private:
     Atom m_net_properties, m_net_wm_name, m_net_wm_desktop, m_net_wm_window_type,
         m_net_wm_state, m_net_wm_state_sticky, m_net_wm_state_shaded,
 	m_net_wm_state_maximized_horz, m_net_wm_state_maximized_vert,
+        m_net_wm_state_fullscreen,
         m_net_wm_strut, m_net_wm_icon_geometry, m_net_wm_icon, m_net_wm_pid,
         m_net_wm_handled_icons;
 			
@@ -83,4 +94,11 @@ private:
     Atom m_net_wm_ping;
 
     std::vector<Window> m_windows;
+    typedef std::map<FluxboxWindow *, WindowState *> SavedState;
+    SavedState m_savedstate;
+
+    WindowState *getState(FluxboxWindow &win);
+    void clearState(FluxboxWindow &win);
+    void saveState(FluxboxWindow &win, WindowState *state);
+
 };
diff --git a/src/Window.cc b/src/Window.cc
index 38fe3f5..7c331c1 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.231 2003/09/16 13:11:42 rathnor Exp $
+// $Id: Window.cc,v 1.232 2003/09/23 13:52:05 rathnor Exp $
 
 #include "Window.hh"
 
@@ -1084,8 +1084,8 @@ void FluxboxWindow::getBlackboxHints() {
     }
 }
 
-void FluxboxWindow::move(int x, int y) {
-    moveResize(x, y, frame().width(), frame().height());
+void FluxboxWindow::move(int x, int y, int gravity) {
+    moveResize(x, y, frame().width(), frame().height(), gravity);
 }
 
 void FluxboxWindow::resize(unsigned int width, unsigned int height) {
@@ -1093,7 +1093,11 @@ void FluxboxWindow::resize(unsigned int width, unsigned int height) {
 }
 
 void FluxboxWindow::moveResize(int new_x, int new_y,
-                               unsigned int new_width, unsigned int new_height) {
+                               unsigned int new_width, unsigned int new_height, int gravity) {
+
+    if (gravity != ForgetGravity) {
+        frame().gravityTranslate(new_x, new_y, gravity, false);
+    }
 
     bool send_event = (frame().x() != new_x || frame().y() != new_y);
 
diff --git a/src/Window.hh b/src/Window.hh
index ee0b35e..a07bf66 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.93 2003/09/12 16:30:21 fluxgen Exp $
+// $Id: Window.hh,v 1.94 2003/09/23 13:52:05 rathnor Exp $
 
 #ifndef	 WINDOW_HH
 #define	 WINDOW_HH
@@ -206,11 +206,11 @@ public:
     void restore(WinClient *client, bool remap);
     void restore(bool remap);
     /// move frame to x, y
-    void move(int x, int y);
+    void move(int x, int y, int gravity = ForgetGravity);
     /// resize frame to width, height
     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);
+    void moveResize(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity);
 
     void setWorkspace(int n);
     void changeBlackboxHints(const BlackboxHints &bh);
-- 
cgit v0.11.2