From feb7462e381b4015bc736e90da87dc7cc5711b1a Mon Sep 17 00:00:00 2001
From: rathnor <rathnor>
Date: Wed, 24 Sep 2003 14:02:25 +0000
Subject: Fix updates to mwm_hints, and make configure request move and resize
 atomic

---
 ChangeLog         |   5 +++
 src/FbAtoms.cc    |   4 +-
 src/FbAtoms.hh    |   6 ++-
 src/FbWinFrame.cc |  85 +++++++++++++++++++++++------------------
 src/FbWinFrame.hh |   9 ++++-
 src/WinClient.cc  |   4 +-
 src/Window.cc     | 112 +++++++++++++++++++++++++++---------------------------
 src/Window.hh     |  12 +++---
 8 files changed, 131 insertions(+), 106 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5f33641..19f5dfb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
 (Format: Year/Month/Day)
 Changes for 0.9.6:
 *03/09/24:
+  * Fix updates to mwm_hints, and make configure request
+    move and resize atomic (Simon)
+    - fixes mplayer fullscreen window being moveable
+    - fixes focus loss when toggling mplayer fullscreen
+    FbWinFrame.hh/cc Window.hh/cc FbAtoms.hh/cc WinClient.cc
   * Fixed the "aterm"-bug  (Henrik)
     Window.cc
 *03/09/23:
diff --git a/src/FbAtoms.cc b/src/FbAtoms.cc
index 0271a56..de8a9a8 100644
--- a/src/FbAtoms.cc
+++ b/src/FbAtoms.cc
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: FbAtoms.cc,v 1.8 2003/05/13 11:47:29 fluxgen Exp $
+// $Id: FbAtoms.cc,v 1.9 2003/09/24 14:02:25 rathnor Exp $
 
 #include "FbAtoms.hh"
 #include "App.hh"
@@ -46,7 +46,6 @@ FbAtoms::~FbAtoms() {
 FbAtoms *FbAtoms::instance() {
     if (s_singleton == 0)
         throw string("Create one instance of FbAtoms first!");
-
     return s_singleton;
 }
 
@@ -60,6 +59,7 @@ void FbAtoms::initAtoms() {
     xa_wm_change_state = XInternAtom(display, "WM_CHANGE_STATE", False);
     xa_wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
     xa_wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False);
+    motif_wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
 
     blackbox_hints = XInternAtom(display, "_BLACKBOX_HINTS", False);
     blackbox_attributes = XInternAtom(display, "_BLACKBOX_ATTRIBUTES", False);
diff --git a/src/FbAtoms.hh b/src/FbAtoms.hh
index 2b4898c..3af1f31 100644
--- a/src/FbAtoms.hh
+++ b/src/FbAtoms.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: FbAtoms.hh,v 1.10 2003/04/26 18:56:02 fluxgen Exp $
+// $Id: FbAtoms.hh,v 1.11 2003/09/24 14:02:25 rathnor Exp $
 #ifndef FBATOMS_HH
 #define FBATOMS_HH
 
@@ -34,7 +34,6 @@ public:
 
     static FbAtoms *instance();
 
-
     inline Atom getWMChangeStateAtom() const { return xa_wm_change_state; }
     inline Atom getWMStateAtom() const { return xa_wm_state; }
     inline Atom getWMDeleteAtom() const { return xa_wm_delete_window; }
@@ -44,6 +43,7 @@ public:
     // this atom is for normal app->WM hints about decorations, stacking,
     // starting workspace etc...
     inline Atom getFluxboxHintsAtom() const { return blackbox_hints;}
+    inline Atom getMWMHintsAtom() const { return motif_wm_hints; }
 
     // these atoms are for normal app->WM interaction beyond the scope of the
     // ICCCM...
@@ -78,6 +78,8 @@ private:
 // NETAttributes
     Atom blackbox_attributes, blackbox_change_attributes, blackbox_hints;
 
+    Atom motif_wm_hints;
+
     // NETStructureMessages
     Atom blackbox_structure_messages, blackbox_notify_startup,
         blackbox_notify_window_add, blackbox_notify_window_del,
diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc
index 1781fcd..fb309b4 100644
--- a/src/FbWinFrame.cc
+++ b/src/FbWinFrame.cc
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: FbWinFrame.cc,v 1.53 2003/09/16 13:11:41 rathnor Exp $
+// $Id: FbWinFrame.cc,v 1.54 2003/09/24 14:02:25 rathnor Exp $
 
 #include "FbWinFrame.hh"
 
@@ -163,53 +163,66 @@ void FbWinFrame::shade() {
 
 
 void FbWinFrame::move(int x, int y) {
-    // don't update unless we really changes position
-    if (x == window().x() && y == window().y())
-        return;
+    moveResize(x, y, 0, 0, true, false);
+}
 
-    window().move(x, y);
-    // update transparent only if we need to
-    if (theme().alpha() == 255)
-        return;
+void FbWinFrame::resize(unsigned int width, unsigned int height) {
+    moveResize(0, 0, width, height, false, true);
+}
 
-    // restart update timer
-    m_update_timer.start();
+// need an atomic moveresize where possible
+void FbWinFrame::moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move, bool resize) {
+    // total height for frame
 
-    /*
+    unsigned int total_height = height;
 
-    */
+    if (resize) {
+        // having a titlebar = 1 extra border + titlebar height
+        if (m_use_titlebar)
+            total_height += m_titlebar.height() + m_titlebar.borderWidth();
+        // having a handle = 1 extra border + handle height
+        if (m_use_handle)
+            total_height += m_handle.height() + m_handle.borderWidth();
+    }
+    moveResize(x, y, width, total_height, move, resize);
 }
 
-void FbWinFrame::resize(unsigned int width, unsigned int height) {
-    // update unshaded size if  we're in shaded state and just resize width
-    if (m_shaded) {
+void FbWinFrame::resizeForClient(unsigned int width, unsigned int height) {
+    moveResizeForClient(0, 0, width, height, false, true);
+}
+
+void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height, bool move, bool resize) {
+    if (move && x == window().x() && y == window().y()) 
+        move = false;
+
+    if (resize && width == FbWinFrame::width() && height == FbWinFrame::height()) 
+        resize = false;
+
+    if (!move && !resize)
+        return;
+
+    if (resize && m_shaded) {
+        // update unshaded size if  we're in shaded state and just resize width
         m_width_before_shade = width;
         m_height_before_shade = height;
-        m_window.resize(width, m_window.height());
+        height = m_window.height();
+    }
+
+    if (move && resize) {
+        m_window.moveResize(x, y, width, height);
+    } else if (move) {
+        m_window.move(x, y);
+        // this stuff will be caught by reconfigure if resized
+        if (theme().alpha() != 255) {
+            // restart update timer
+            m_update_timer.start();
+        }
     } else {
         m_window.resize(width, height);
     }
 
-    reconfigure();
-}
-
-void FbWinFrame::resizeForClient(unsigned int width, unsigned int height) {
-    // total height for frame
-    unsigned int total_height = height;
-
-    // having a titlebar = 1 extra border + titlebar height
-    if (m_use_titlebar)
-        total_height += m_titlebar.height() + m_titlebar.borderWidth();
-    // having a handle = 1 extra border + handle height
-    if (m_use_handle)
-        total_height += m_handle.height() + m_handle.borderWidth();
-    resize(width, total_height);
-}
-
-void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height) {
-    move(x, y);
-    if (width != FbWinFrame::width() || height != FbWinFrame::height())
-        resize(width, height);
+    if (resize)
+        reconfigure();
 }
 
 void FbWinFrame::setFocus(bool newvalue) {
diff --git a/src/FbWinFrame.hh b/src/FbWinFrame.hh
index 23b004b..f57ce32 100644
--- a/src/FbWinFrame.hh
+++ b/src/FbWinFrame.hh
@@ -19,7 +19,7 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-// $Id: FbWinFrame.hh,v 1.20 2003/09/14 10:32:31 fluxgen Exp $
+// $Id: FbWinFrame.hh,v 1.21 2003/09/24 14:02:25 rathnor Exp $
 
 #ifndef FBWINFRAME_HH
 #define FBWINFRAME_HH
@@ -80,7 +80,12 @@ public:
     void resize(unsigned int width, unsigned int height);
     /// resize client to specified size and resize frame to it
     void resizeForClient(unsigned int width, unsigned int height);
-    void moveResize(int x, int y, unsigned int width, unsigned int height);
+
+    // 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);
+
+    // 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);
 
     /// set focus/unfocus style
     void setFocus(bool newvalue);
diff --git a/src/WinClient.cc b/src/WinClient.cc
index 1c7b249..614b7a4 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.26 2003/09/21 13:24:27 rathnor Exp $
+// $Id: WinClient.cc,v 1.27 2003/09/24 14:02:25 rathnor Exp $
 
 #include "WinClient.hh"
 
@@ -356,12 +356,12 @@ void WinClient::updateMWMHints() {
     int format;
     Atom atom_return;
     unsigned long num = 0, len = 0;
-    Atom  motif_wm_hints = XInternAtom(FbTk::App::instance()->display(), "_MOTIF_WM_HINTS", False);
 
     if (m_mwm_hint) {
         XFree(m_mwm_hint);
         m_mwm_hint = 0;
     }
+    Atom motif_wm_hints = FbAtoms::instance()->getMWMHintsAtom();
 
     if (!(property(motif_wm_hints, 0,
                    PropMwmHintsElements, false,
diff --git a/src/Window.cc b/src/Window.cc
index 5d2f600..f35c21e 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.233 2003/09/24 11:33:40 fluxgen Exp $
+// $Id: Window.cc,v 1.234 2003/09/24 14:02:25 rathnor Exp $
 
 #include "Window.hh"
 
@@ -415,9 +415,9 @@ void FluxboxWindow::init() {
     decorations.close = false;
 
     if (m_client->getBlackboxHint() != 0)
-        getBlackboxHints();
+        updateBlackboxHintsFromClient(*m_client);
     else
-        getMWMHints();
+        updateMWMHintsFromClient(*m_client);
     
     //!!
     // fetch client size and placement
@@ -498,8 +498,7 @@ void FluxboxWindow::init() {
 
     }
 
-    frame().move(wattrib.x, wattrib.y);
-    frame().resizeForClient(wattrib.width, wattrib.height);
+    frame().moveResizeForClient(wattrib.x, wattrib.y, wattrib.width, wattrib.height);
 
     // if we're a transient then we should be on the same layer as our parent
     if (m_client->isTransient() && 
@@ -907,8 +906,8 @@ bool FluxboxWindow::isGroupable() const {
 
 void FluxboxWindow::associateClientWindow() {
     m_client->setBorderWidth(0);
-    updateTitleFromClient();
-    updateIconNameFromClient();
+    updateTitleFromClient(*m_client);
+    updateIconNameFromClient(*m_client);
 
     frame().setClientWindow(*m_client);
     frame().resizeForClient(m_client->width(), m_client->height());
@@ -964,25 +963,24 @@ void FluxboxWindow::reconfigure() {
 }
 
 /// update current client title and title in our frame
-void FluxboxWindow::updateTitleFromClient() {
-    m_client->updateTitle();
+void FluxboxWindow::updateTitleFromClient(WinClient &client) {
+    client.updateTitle();
     // compare old title with new and see if we need to update
     // graphics
-    if (m_labelbuttons[m_client]->text() != m_client->title()) {
-        m_labelbuttons[m_client]->setText(m_client->title());    
-        m_labelbuttons[m_client]->clear(); // redraw text
-        m_labelbuttons[m_client]->updateTransparent();
+    if (m_labelbuttons[&client]->text() != client.title()) {
+        m_labelbuttons[&client]->setText(client.title());    
+        m_labelbuttons[&client]->clear(); // redraw text
+        m_labelbuttons[&client]->updateTransparent();
     }
 }
 
 /// update icon title from client
-void FluxboxWindow::updateIconNameFromClient() {
-    m_client->updateIconTitle();
+void FluxboxWindow::updateIconNameFromClient(WinClient &client) {
+    client.updateIconTitle();
 }
 
-
-void FluxboxWindow::getMWMHints() {
-    const WinClient::MwmHints *hint = m_client->getMwmHint();
+void FluxboxWindow::updateMWMHintsFromClient(WinClient &client) {
+    const WinClient::MwmHints *hint = client.getMwmHint();
 
     if (!hint) return;
 
@@ -1049,8 +1047,8 @@ void FluxboxWindow::updateFunctions() {
         setupWindow();
 }
 
-void FluxboxWindow::getBlackboxHints() {
-    const FluxboxWindow::BlackboxHints *hint = m_client->getBlackboxHint();
+void FluxboxWindow::updateBlackboxHintsFromClient(WinClient &client) {
+    const FluxboxWindow::BlackboxHints *hint = client.getBlackboxHint();
     if (!hint) return;
 
     if (hint->flags & ATTRIB_SHADED)
@@ -1912,10 +1910,12 @@ void FluxboxWindow::handleEvent(XEvent &event) {
         // case MapRequest:
         //        mapRequestEvent(event.xmaprequest);
         //break;
-    case PropertyNotify:
-        if (event.xproperty.state != PropertyDelete) {
-            propertyNotifyEvent(event.xproperty.atom);
+    case PropertyNotify: {
+        WinClient *client = findClient(event.xproperty.window);
+        if (client) {
+            propertyNotifyEvent(*client, event.xproperty.atom);
         }
+    }
         break;
 
     default:
@@ -2076,8 +2076,7 @@ void FluxboxWindow::destroyNotifyEvent(XDestroyWindowEvent &de) {
 }
 
 
-void FluxboxWindow::propertyNotifyEvent(Atom atom) {
-
+void FluxboxWindow::propertyNotifyEvent(WinClient &client, Atom atom) {
     switch(atom) {
     case XA_WM_CLASS:
     case XA_WM_CLIENT_MACHINE:
@@ -2085,31 +2084,28 @@ void FluxboxWindow::propertyNotifyEvent(Atom atom) {
         break;
 
     case XA_WM_TRANSIENT_FOR: {
-        // TODO: this property notify should be handled by winclient
-        // but for now we'll justhave to update all transient info
-        //bool was_transient = isTransient();
-        for_each(clientList().begin(), clientList().end(), 
-                 mem_fun(&WinClient::updateTransientInfo));
-        reconfigure();
-        // TODO: this is broken whilst we don't know which client
+        bool was_transient = client.isTransient();
+        client.updateTransientInfo();
         // update our layer to be the same layer as our transient for
-        //if (isTransient() && isTransient() != was_transient)
-        //    layerItem().setLayer(getTransientFor()->layerItem().getLayer());
+        if (client.isTransient() && !was_transient
+            && client.transientFor()->fbwindow())
+            layerItem().setLayer(client.transientFor()->fbwindow()->layerItem().getLayer());
             
     } break;
 
     case XA_WM_HINTS:
-        m_client->updateWMHints();
+        client.updateWMHints();
         hintSig().notify(); // notify listeners
         break;
 
     case XA_WM_ICON_NAME:
-        updateIconNameFromClient();
+        client.updateIconTitle();
+        updateIconNameFromClient(client);
         updateIcon();
         break;
 
     case XA_WM_NAME:
-        updateTitleFromClient();
+        updateTitleFromClient(client);
 
         if (! iconic)
             screen().getWorkspace(m_workspace_number)->update();
@@ -2120,27 +2116,27 @@ void FluxboxWindow::propertyNotifyEvent(Atom atom) {
         break;
 
     case XA_WM_NORMAL_HINTS: {
-        m_client->updateWMNormalHints();
+        client.updateWMNormalHints();
 
-        if ((m_client->normal_hint_flags & PMinSize) &&
-            (m_client->normal_hint_flags & PMaxSize)) {
+        if ((client.normal_hint_flags & PMinSize) &&
+            (client.normal_hint_flags & PMaxSize)) {
 
-            if (m_client->max_width != 0 && m_client->max_width <= m_client->min_width &&
-                m_client->max_height != 0 && m_client->max_height <= m_client->min_height) {
+            if (client.max_width != 0 && client.max_width <= client.min_width &&
+                client.max_height != 0 && client.max_height <= client.min_height) {
                 decorations.maximize = false;
                 decorations.handle = false;
                 functions.resize=false;
                 functions.maximize=false;
             } else {
                 // TODO: is broken while handled by FbW, needs to be in WinClient
-                if (! winClient().isTransient()) {
+                if (! client.isTransient()) {
                     decorations.maximize = true;
                     decorations.handle = true;
                     functions.maximize = true;	        
                 }
                 functions.resize = true;
             }
- 
+            setupWindow();
     	}
 
         // save old values
@@ -2159,13 +2155,16 @@ void FluxboxWindow::propertyNotifyEvent(Atom atom) {
     }
 
     default:
-        if (atom == FbAtoms::instance()->getWMProtocolsAtom()) {
-            m_client->updateWMProtocols();
-            //!!TODO  check this area            
-            // reset window actions
-            setupWindow();
-            
-        } 
+        FbAtoms *fbatoms = FbAtoms::instance();
+        if (atom == fbatoms->getWMProtocolsAtom()) {
+            client.updateWMProtocols();
+        } else if (atom == fbatoms->getMWMHintsAtom()) {
+            client.updateMWMHints();
+            updateMWMHintsFromClient(client);
+        } else if (atom == fbatoms->getFluxboxHintsAtom()) {
+            client.updateBlackboxHints();
+            updateBlackboxHintsFromClient(client);
+        }
         break;
     }
 
@@ -2208,11 +2207,12 @@ void FluxboxWindow::configureRequestEvent(XConfigureRequestEvent &cr) {
 
     // the request is for client window so we resize the frame to it first
     if (frame().width() != cw || frame().height() != ch) {        
-        frame().resizeForClient(cw, ch);
+        if (frame().x() != cx || frame().y() != cy) 
+            frame().moveResizeForClient(cx, cy, cw, ch);
+        else 
+            frame().resizeForClient(cw, ch);
         send_notify = true;
-    }
-
-    if (frame().x() != cx || frame().y() != cy) {
+    } else if (frame().x() != cx || frame().y() != cy) {
         move(cx, cy);
         // since we already send a notify in move we don't need to do that again
         send_notify = false;
@@ -2627,7 +2627,7 @@ void FluxboxWindow::applyDecorations(bool initial) {
 
     // if the location changes, shift it
     if (grav_x != 0 || grav_y != 0)
-        frame().move(grav_x + frame().x(), grav_y + frame().y());
+        move(grav_x + frame().x(), grav_y + frame().y());
 
     frame().reconfigure();
 }
diff --git a/src/Window.hh b/src/Window.hh
index a07bf66..8c2fe46 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.94 2003/09/23 13:52:05 rathnor Exp $
+// $Id: Window.hh,v 1.95 2003/09/24 14:02:25 rathnor Exp $
 
 #ifndef	 WINDOW_HH
 #define	 WINDOW_HH
@@ -236,7 +236,7 @@ public:
     void unmapNotifyEvent(XUnmapEvent &unmapev);
     void exposeEvent(XExposeEvent &ee);
     void configureRequestEvent(XConfigureRequestEvent &ce);
-    void propertyNotifyEvent(Atom a);
+    void propertyNotifyEvent(WinClient &client, Atom a);
     void enterNotifyEvent(XCrossingEvent &ev);
     void leaveNotifyEvent(XCrossingEvent &ev);
     //@}
@@ -374,11 +374,11 @@ private:
 
     bool getState();
     /// gets title string from client window and updates frame's title
-    void updateTitleFromClient();
+    void updateTitleFromClient(WinClient &client);
     /// gets icon name from client window
-    void updateIconNameFromClient();
-    void getMWMHints();
-    void getBlackboxHints();
+    void updateIconNameFromClient(WinClient &client);
+    void updateMWMHintsFromClient(WinClient &client);
+    void updateBlackboxHintsFromClient(WinClient &client);
     void saveBlackboxAttribs();
     void setNetWMAttributes();
     void associateClientWindow();
-- 
cgit v0.11.2