Back to index

unity  6.0.0
minimizedwindowhandler.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 Canonical Ltd.
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  *
00018  * Authored By:
00019  * Sam Spilsbury <sam.spilsbury@canonical.com>
00020  */
00021 
00022 #include "minimizedwindowhandler.h"
00023 #include "inputremover.h"
00024 #include <cstring>
00025 
00026 namespace compiz
00027 {
00028 class PrivateMinimizedWindowHandler
00029 {
00030 public:
00031 
00032   PrivateMinimizedWindowHandler () {};
00033 
00034   Display      *mDpy;
00035   unsigned int mXid;
00036 
00037   std::list <MinimizedWindowHandler::Ptr> mTransients;
00038 
00039   WindowInputRemoverLock::Ptr mRemover;
00040   WindowInputRemoverLockAcquireInterface *mLockAcquire;
00041 };
00042 }
00043 
00044 bool
00045 compiz::MinimizedWindowHandler::contains (boost::shared_ptr <MinimizedWindowHandler> mw)
00046 {
00047   for (MinimizedWindowHandler::Ptr h : priv->mTransients)
00048   {
00049     if (h->priv->mXid == mw->priv->mXid)
00050       return true;
00051   }
00052 
00053   return false;
00054 }
00055 
00056 void
00057 compiz::MinimizedWindowHandler::setVisibility (bool visible, Window shapeWin)
00058 {
00059   if (!visible && !priv->mRemover)
00060   {
00061     priv->mRemover = priv->mLockAcquire->InputRemover();
00062     if (!priv->mRemover)
00063       return;
00064   }
00065   else if (visible && priv->mRemover)
00066   {
00067     priv->mRemover.reset();
00068   }
00069 }
00070 
00071 std::vector<unsigned int>
00072 compiz::MinimizedWindowHandler::getTransients ()
00073 {
00074   std::vector<unsigned int> transients;
00075   compiz::X11TransientForReader *reader = new compiz::X11TransientForReader (priv->mDpy, priv->mXid);
00076 
00077   transients = reader->getTransients();
00078 
00079   delete reader;
00080 
00081   return transients;
00082 }
00083 
00084 void
00085 compiz::MinimizedWindowHandler::minimize ()
00086 {
00087   Atom          wmState = XInternAtom (priv->mDpy, "WM_STATE", 0);
00088   Atom          netWmState = XInternAtom (priv->mDpy, "_NET_WM_STATE", 0);
00089   Atom          netWmStateHidden = XInternAtom (priv->mDpy, "_NET_WM_STATE_HIDDEN", 0);
00090   Atom          actualType;
00091   int           actualFormat;
00092   unsigned long nItems, nLeft;
00093   void          *prop;
00094   unsigned long data[2];
00095   Window        root = DefaultRootWindow (priv->mDpy), parent = priv->mXid, lastParent = priv->mXid;
00096   Window        *children;
00097   unsigned int  nchildren;
00098   compiz::MinimizedWindowHandler::Ptr holder = compiz::MinimizedWindowHandler::Ptr (new compiz::MinimizedWindowHandler (priv->mDpy, 0, priv->mLockAcquire));
00099   auto          predicate_this = boost::bind (&compiz::MinimizedWindowHandler::contains, this, _1);
00100   auto          predicate_holder = !boost::bind (&compiz::MinimizedWindowHandler::contains, holder.get(), _1);
00101 
00102   std::vector<unsigned int> transients = getTransients ();
00103 
00104   for (unsigned int &w : transients)
00105   {
00106     compiz::MinimizedWindowHandler::Ptr p = compiz::MinimizedWindowHandler::Ptr (new compiz::MinimizedWindowHandler (priv->mDpy, w, priv->mLockAcquire));
00107     holder->priv->mTransients.push_back (p);
00108   }
00109 
00110   priv->mTransients.remove_if (predicate_holder);
00111   holder->priv->mTransients.remove_if (predicate_this);
00112 
00113   for (MinimizedWindowHandler::Ptr &mw : holder->priv->mTransients)
00114     priv->mTransients.push_back (mw);
00115 
00116   for (MinimizedWindowHandler::Ptr &mw : priv->mTransients)
00117     mw->minimize();
00118 
00119   do
00120   {
00121     if (XQueryTree (priv->mDpy, parent, &root, &parent, &children, &nchildren))
00122     {
00123       if (root != parent)
00124         lastParent = parent;
00125       XFree (children);
00126     }
00127     else
00128       root = parent;
00129   } while (root != parent);
00130 
00131   setVisibility (false, lastParent);
00132 
00133   /* Change the WM_STATE to IconicState */
00134   data[0] = IconicState;
00135   data[1] = None;
00136 
00137   XChangeProperty (priv->mDpy, priv->mXid, wmState, wmState,
00138                    32, PropModeReplace, (unsigned char *) data, 2);
00139 
00140   if (XGetWindowProperty (priv->mDpy, priv->mXid, netWmState, 0L, 512L, false, XA_ATOM, &actualType, &actualFormat,
00141                           &nItems, &nLeft, (unsigned char **) &prop) == Success)
00142   {
00143     if (actualType == XA_ATOM && actualFormat == 32 && nItems && !nLeft)
00144     {
00145       Atom *data = (Atom *) prop;
00146 
00147       /* Don't append _NET_WM_STATE_HIDDEN */
00148       while (nItems--)
00149         if (*data++ == netWmStateHidden)
00150           netWmStateHidden = 0;
00151     }
00152 
00153     if (prop)
00154       XFree (prop);
00155   }
00156 
00157   /* Add _NET_WM_STATE_HIDDEN */
00158   if (netWmStateHidden)
00159     XChangeProperty (priv->mDpy, priv->mXid, netWmState, XA_ATOM,
00160                      32, PropModeAppend, (const unsigned char *) &netWmStateHidden, 1);
00161 }
00162 
00163 void
00164 compiz::MinimizedWindowHandler::unminimize ()
00165 {
00166   Atom          wmState = XInternAtom (priv->mDpy, "WM_STATE", 0);
00167   Atom          netWmState = XInternAtom (priv->mDpy, "_NET_WM_STATE", 0);
00168   Atom          netWmStateHidden = XInternAtom (priv->mDpy, "_NET_WM_STATE_HIDDEN", 0);
00169   Atom          *nextState = NULL;
00170   unsigned int  nextStateSize = 0;
00171   Atom          actualType;
00172   int           actualFormat;
00173   unsigned long nItems, nLeft;
00174   void          *prop;
00175   unsigned long data[2];
00176   Window        root = DefaultRootWindow (priv->mDpy), parent = priv->mXid, lastParent = priv->mXid;
00177   Window        *children;
00178   unsigned int  nchildren;
00179   compiz::MinimizedWindowHandler::Ptr holder = compiz::MinimizedWindowHandler::Ptr (new compiz::MinimizedWindowHandler (priv->mDpy, 0, priv->mLockAcquire));
00180   auto          predicate_this = boost::bind (&compiz::MinimizedWindowHandler::contains, this, _1);
00181   auto          predicate_holder = !boost::bind (&compiz::MinimizedWindowHandler::contains, holder.get(), _1);
00182 
00183   std::vector<unsigned int> transients = getTransients();
00184 
00185   for (unsigned int &w : transients)
00186   {
00187     compiz::MinimizedWindowHandler::Ptr p = compiz::MinimizedWindowHandler::Ptr (new compiz::MinimizedWindowHandler (priv->mDpy, w, priv->mLockAcquire));
00188     holder->priv->mTransients.push_back (p);
00189   }
00190 
00191   priv->mTransients.remove_if (predicate_holder);
00192   holder->priv->mTransients.remove_if (predicate_this);
00193 
00194   for (MinimizedWindowHandler::Ptr &mw : holder->priv->mTransients)
00195     priv->mTransients.push_back (mw);
00196 
00197   for (MinimizedWindowHandler::Ptr &mw : priv->mTransients)
00198     mw->unminimize();
00199 
00200   do
00201   {
00202     if (XQueryTree (priv->mDpy, parent, &root, &parent, &children, &nchildren))
00203     {
00204       if (root != parent)
00205         lastParent = parent;
00206       XFree (children);
00207     }
00208     else
00209       root = parent;
00210   } while (root != parent);
00211 
00212   setVisibility (true, lastParent);
00213 
00214   data[0] = NormalState;
00215   data[1] = None;
00216 
00217   XChangeProperty (priv->mDpy, priv->mXid, wmState, wmState,
00218                    32, PropModeReplace, (unsigned char *) data, 2);
00219 
00220   if (XGetWindowProperty (priv->mDpy, priv->mXid, netWmState, 0L, 512L, false, XA_ATOM, &actualType, &actualFormat,
00221                           &nItems, &nLeft, (unsigned char **) &prop) == Success)
00222   {
00223     if (actualType == XA_ATOM && actualFormat == 32 && nItems && !nLeft)
00224     {
00225       Atom *data = (Atom *) prop;
00226       Atom *pbegin = NULL;
00227       int  count = 0;
00228 
00229       nextStateSize = nItems;
00230 
00231       pbegin = nextState = (Atom *) malloc (sizeof (Atom) * nextStateSize);
00232       pbegin = nextState = (Atom *) memcpy (nextState, data, sizeof (Atom) * nextStateSize);
00233 
00234       /* Remove _NET_WM_STATE_HIDDEN */
00235       while (nItems--)
00236       {
00237         if (*nextState++ == netWmStateHidden)
00238         {
00239           nextState = (Atom *) memmove (nextState - 1, nextState, nItems);
00240           pbegin = nextState - count;
00241 
00242           nextStateSize--;
00243           pbegin = (Atom *) realloc (pbegin, sizeof (Atom) * nextStateSize);
00244         }
00245 
00246         count++;
00247       }
00248 
00249       nextState = pbegin;
00250     }
00251 
00252     XFree (prop);
00253   }
00254 
00255   /* Write new _NET_WM_STATE */
00256   if (nextState)
00257     XChangeProperty (priv->mDpy, priv->mXid, netWmState, XA_ATOM,
00258                      32, PropModeReplace, (const unsigned char *) nextState, nextStateSize);
00259   else
00260     XDeleteProperty (priv->mDpy, priv->mXid, netWmState);
00261 }
00262 
00263 compiz::MinimizedWindowHandler::MinimizedWindowHandler (Display *dpy, unsigned int xid, compiz::WindowInputRemoverLockAcquireInterface *lock_acquire)
00264 {
00265   priv = new PrivateMinimizedWindowHandler;
00266 
00267   priv->mDpy = dpy;
00268   priv->mXid = xid;
00269   priv->mLockAcquire = lock_acquire;
00270 }
00271 
00272 compiz::MinimizedWindowHandler::~MinimizedWindowHandler ()
00273 {
00274   delete priv;
00275 }