Back to index

unity  6.0.0
transientfor.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 "transientfor.h"
00023 
00024 Atom compiz::X11TransientForReader::wmTransientFor = None;
00025 Atom compiz::X11TransientForReader::wmClientLeader = None;
00026 
00027 namespace compiz
00028 {
00029 class PrivateX11TransientForReader
00030 {
00031 public:
00032 
00033   PrivateX11TransientForReader () {};
00034 
00035   Window  mXid;
00036   Display *mDpy;
00037 };
00038 }
00039 
00040 unsigned int
00041 compiz::X11TransientForReader::getAncestor ()
00042 {
00043   Window        serverAncestor = None;
00044   unsigned long nItems, nLeft;
00045   int           actualFormat;
00046   Atom          actualType;
00047   void          *prop;
00048 
00049   if (XGetWindowProperty (priv->mDpy, priv->mXid, wmTransientFor, 0L, 2L, false,
00050                           XA_WINDOW, &actualType, &actualFormat, &nItems, &nLeft, (unsigned char **)&prop) == Success)
00051   {
00052     if (actualType == XA_WINDOW && actualFormat == 32 && nLeft == 0 && nItems == 1)
00053     {
00054       Window *data = static_cast <Window *> (prop);
00055 
00056       serverAncestor = *data;
00057     }
00058 
00059     XFree (prop);
00060   }
00061 
00062   return serverAncestor;
00063 }
00064 
00065 bool
00066 compiz::X11TransientForReader::isTransientFor (unsigned int ancestor)
00067 {
00068   if (!ancestor ||
00069       !priv->mXid)
00070     return false;
00071 
00072   return ancestor == getAncestor ();
00073 }
00074 
00075 bool
00076 compiz::X11TransientForReader::isGroupTransientFor (unsigned int clientLeader)
00077 {
00078   Window        serverClientLeader = None;
00079   Window        ancestor           = getAncestor ();
00080   unsigned long nItems, nLeft;
00081   int           actualFormat;
00082   Atom          actualType;
00083   void          *prop;
00084   std::vector<std::string> strings;
00085   std::list<Atom>   atoms;
00086 
00087   if (!clientLeader ||
00088       !priv->mXid)
00089 
00090   if (XGetWindowProperty (priv->mDpy, priv->mXid, wmClientLeader, 0L, 2L, false,
00091                           XA_WINDOW, &actualType, &actualFormat, &nItems, &nLeft, (unsigned char **)&prop) == Success)
00092   {
00093     if (actualType == XA_WINDOW && actualFormat == 32 && nLeft == 0 && nItems == 1)
00094     {
00095       Window *data = static_cast <Window *> (prop);
00096 
00097       serverClientLeader = *data;
00098     }
00099 
00100     XFree (prop);
00101   }
00102 
00103   /* Check if the returned client leader matches
00104      * the requested one */
00105   if (serverClientLeader == clientLeader &&
00106       clientLeader != priv->mXid)
00107   {
00108     if (ancestor == None || ancestor == DefaultRootWindow (priv->mDpy))
00109     {
00110            Atom wmWindowType = XInternAtom (priv->mDpy, "_NET_WM_WINDOW_TYPE", 0);
00111 
00112            /* We need to get some common type strings */
00113            strings.push_back ("_NET_WM_WINDOW_TYPE_UTILITY");
00114            strings.push_back ("_NET_WM_WINDOW_TYPE_TOOLBAR");
00115            strings.push_back ("_NET_WM_WINDOW_TYPE_MENU");
00116            strings.push_back ("_NET_WM_WINDOW_TYPE_DIALOG");
00117 
00118       for (std::string &s : strings)
00119            {
00120         atoms.push_back (XInternAtom (priv->mDpy, s.c_str (), 0));
00121            }
00122 
00123            const unsigned int atomsSize = atoms.size ();
00124 
00125            /* Now get the window type and check to see if this is a type that we
00126       * should consider to be part of a window group by this client leader */
00127 
00128            if (XGetWindowProperty (priv->mDpy, priv->mXid, wmWindowType, 0L, 15L, false,
00129                               XA_ATOM, &actualType, &actualFormat, &nItems, &nLeft, (unsigned char **)&prop) == Success)
00130       {
00131         if (actualType == XA_ATOM && actualFormat == 32 && nLeft == 0 && nItems)
00132         {
00133           Atom *data = static_cast <Atom *> (prop);
00134 
00135           while (nItems--)
00136           {
00137             atoms.remove (*data++);
00138           }
00139         }
00140            }
00141 
00142            /* Means something was found */
00143            if (atomsSize != atoms.size ())
00144         return true;
00145     }
00146   }
00147 
00148   return false;
00149 }
00150 
00151 std::vector<unsigned int>
00152 compiz::X11TransientForReader::getTransients ()
00153 {
00154   unsigned long nItems, nLeft;
00155   int           actualFormat;
00156   Atom          actualType;
00157   Atom          wmClientList;
00158   void          *prop;
00159   std::vector<unsigned int>   transients;
00160   std::vector<Window>   clientList;
00161 
00162   wmClientList = XInternAtom (priv->mDpy, "_NET_CLIENT_LIST", 0);
00163 
00164   if (XGetWindowProperty (priv->mDpy, DefaultRootWindow (priv->mDpy), wmClientList, 0L, 512L, false,
00165                           XA_WINDOW, &actualType, &actualFormat, &nItems, &nLeft,
00166                           (unsigned char **)&prop) == Success)
00167   {
00168     if (actualType == XA_WINDOW && actualFormat == 32 && nItems && !nLeft)
00169     {
00170       Window *data = static_cast <Window *> (prop);
00171 
00172       while (nItems--)
00173       {
00174         clientList.push_back (*data++);
00175       }
00176     }
00177 
00178     XFree (prop);
00179   }
00180 
00181   /* Now check all the windows in this client list
00182      * for the transient state (note that this won't
00183      * work for override redirect windows since there's
00184      * no concept of a client list for override redirect
00185      * windows, but it doesn't matter anyways in this
00186      * [external] case) */
00187 
00188   for (Window &w : clientList)
00189   {
00190     X11TransientForReader *reader = new X11TransientForReader (priv->mDpy, w);
00191 
00192     if (reader->isTransientFor (priv->mXid) ||
00193         reader->isGroupTransientFor (priv->mXid))
00194       transients.push_back (w);
00195 
00196     delete reader;
00197   }
00198 
00199   return transients;
00200 }
00201 
00202 compiz::X11TransientForReader::X11TransientForReader (Display *dpy, Window xid)
00203 {
00204   priv = new PrivateX11TransientForReader ();
00205 
00206   priv->mXid = xid;
00207   priv->mDpy = dpy;
00208 
00209   if (!wmTransientFor)
00210     wmTransientFor = XInternAtom (dpy, "WM_TRANSIENT_FOR", 0);
00211   if (!wmClientLeader)
00212     wmClientLeader = XInternAtom (dpy, "WM_CLIENT_LEADER", 0);
00213 }
00214 
00215 compiz::X11TransientForReader::~X11TransientForReader ()
00216 {
00217   delete priv;
00218 }