~unity-team/unity/4.0

« back to all changes in this revision

Viewing changes to plugins/unityshell/src/transientfor.cpp

MergeĀ lp:~unity-team/unity/unity.minimized_windows_switcher

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Canonical Ltd.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 *
 
18
 * Authored By:
 
19
 * Sam Spilsbury <sam.spilsbury@canonical.com>
 
20
 */
 
21
 
 
22
#include "transientfor.h"
 
23
 
 
24
Atom compiz::X11TransientForReader::wmTransientFor = None;
 
25
Atom compiz::X11TransientForReader::wmClientLeader = None;
 
26
 
 
27
namespace compiz
 
28
{
 
29
class PrivateX11TransientForReader
 
30
{
 
31
public:
 
32
 
 
33
  PrivateX11TransientForReader () {};
 
34
 
 
35
  Window  mXid;
 
36
  Display *mDpy;
 
37
};
 
38
}
 
39
 
 
40
unsigned int
 
41
compiz::X11TransientForReader::getAncestor ()
 
42
{
 
43
  Window        serverAncestor = None;
 
44
  unsigned long nItems, nLeft;
 
45
  int           actualFormat;
 
46
  Atom          actualType;
 
47
  unsigned char *prop;
 
48
 
 
49
  if (XGetWindowProperty (priv->mDpy, priv->mXid, wmTransientFor, 0L, 2L, false,
 
50
                          XA_WINDOW, &actualType, &actualFormat, &nItems, &nLeft, &prop) == Success)
 
51
  {
 
52
    if (actualType == XA_WINDOW && actualFormat == 32 && nLeft == 0 && nItems == 1)
 
53
    {
 
54
            Window *data = (Window *) prop;
 
55
 
 
56
            serverAncestor = *data;
 
57
    }
 
58
 
 
59
    XFree (prop);
 
60
  }
 
61
 
 
62
  return serverAncestor;
 
63
}
 
64
 
 
65
bool
 
66
compiz::X11TransientForReader::isTransientFor (unsigned int ancestor)
 
67
{
 
68
  return ancestor == getAncestor ();
 
69
}
 
70
 
 
71
bool
 
72
compiz::X11TransientForReader::isGroupTransientFor (unsigned int clientLeader)
 
73
{
 
74
  Window        serverClientLeader = None;
 
75
  Window        ancestor           = getAncestor ();
 
76
  unsigned long nItems, nLeft;
 
77
  int           actualFormat;
 
78
  Atom          actualType;
 
79
  unsigned char *prop;
 
80
  std::vector<std::string> strings;
 
81
  std::list<Atom>   atoms;
 
82
 
 
83
  if (XGetWindowProperty (priv->mDpy, priv->mXid, wmClientLeader, 0L, 2L, false,
 
84
                          XA_WINDOW, &actualType, &actualFormat, &nItems, &nLeft, &prop) == Success)
 
85
  {
 
86
    if (actualType == XA_WINDOW && actualFormat == 32 && nLeft == 0 && nItems == 1)
 
87
    {
 
88
            Window *data = (Window *) prop;
 
89
 
 
90
            serverClientLeader = *data;
 
91
    }
 
92
 
 
93
    XFree (prop);
 
94
  }
 
95
 
 
96
  /* Check if the returned client leader matches
 
97
     * the requested one */
 
98
  if (serverClientLeader == clientLeader &&
 
99
      clientLeader != priv->mXid)
 
100
  {
 
101
    if (ancestor == None || ancestor == DefaultRootWindow (priv->mDpy))
 
102
    {
 
103
            Atom wmWindowType = XInternAtom (priv->mDpy, "_NET_WM_WINDOW_TYPE", 0);
 
104
 
 
105
            /* We need to get some common type strings */
 
106
            strings.push_back ("_NET_WM_WINDOW_TYPE_UTILITY");
 
107
            strings.push_back ("_NET_WM_WINDOW_TYPE_TOOLBAR");
 
108
            strings.push_back ("_NET_WM_WINDOW_TYPE_MENU");
 
109
            strings.push_back ("_NET_WM_WINDOW_TYPE_DIALOG");
 
110
 
 
111
      for (std::string &s : strings)
 
112
            {
 
113
        atoms.push_back (XInternAtom (priv->mDpy, s.c_str (), 0));
 
114
            }
 
115
 
 
116
            const unsigned int atomsSize = atoms.size ();
 
117
 
 
118
            /* Now get the window type and check to see if this is a type that we
 
119
      * should consider to be part of a window group by this client leader */
 
120
 
 
121
            if (XGetWindowProperty (priv->mDpy, priv->mXid, wmWindowType, 0L, 15L, false,
 
122
                              XA_ATOM, &actualType, &actualFormat, &nItems, &nLeft, &prop) == Success)
 
123
      {
 
124
        if (actualType == XA_ATOM && actualFormat == 32 && nLeft == 0 && nItems)
 
125
        {
 
126
          Atom *data = (Atom *) prop;
 
127
 
 
128
          while (nItems--)
 
129
          {
 
130
            atoms.remove (*data++);
 
131
          }
 
132
        }
 
133
            }
 
134
 
 
135
            /* Means something was found */
 
136
            if (atomsSize != atoms.size ())
 
137
        return true;
 
138
    }
 
139
  }
 
140
 
 
141
  return false;
 
142
}
 
143
 
 
144
std::vector<unsigned int>
 
145
compiz::X11TransientForReader::getTransients ()
 
146
{
 
147
  unsigned long nItems, nLeft;
 
148
  int           actualFormat;
 
149
  Atom          actualType;
 
150
  Atom          wmClientList;
 
151
  unsigned char *prop;
 
152
  std::vector<unsigned int>   transients;
 
153
  std::vector<Window>   clientList;
 
154
 
 
155
  wmClientList = XInternAtom (priv->mDpy, "_NET_CLIENT_LIST", 0);
 
156
 
 
157
  if (XGetWindowProperty (priv->mDpy, DefaultRootWindow (priv->mDpy), wmClientList, 0L, 512L, false,
 
158
                          XA_WINDOW, &actualType, &actualFormat, &nItems, &nLeft,
 
159
                          &prop) == Success)
 
160
  {
 
161
    if (actualType == XA_WINDOW && actualFormat == 32 && nItems && !nLeft)
 
162
    {
 
163
      Window *data = (Window *) prop;
 
164
 
 
165
      while (nItems--)
 
166
      {
 
167
        clientList.push_back (*data++);
 
168
      }
 
169
    }
 
170
 
 
171
    XFree (prop);
 
172
  }
 
173
 
 
174
  /* Now check all the windows in this client list
 
175
     * for the transient state (note that this won't
 
176
     * work for override redirect windows since there's
 
177
     * no concept of a client list for override redirect
 
178
     * windows, but it doesn't matter anyways in this
 
179
     * [external] case) */
 
180
 
 
181
  for (Window &w : clientList)
 
182
  {
 
183
    X11TransientForReader *reader = new X11TransientForReader (priv->mDpy, w);
 
184
 
 
185
    if (reader->isTransientFor (priv->mXid) ||
 
186
        reader->isGroupTransientFor (priv->mXid))
 
187
      transients.push_back (w);
 
188
 
 
189
    delete reader;
 
190
  }
 
191
 
 
192
  return transients;
 
193
}
 
194
 
 
195
compiz::X11TransientForReader::X11TransientForReader (Display *dpy, Window xid)
 
196
{
 
197
  priv = new PrivateX11TransientForReader ();
 
198
 
 
199
  priv->mXid = xid;
 
200
  priv->mDpy = dpy;
 
201
 
 
202
  if (!wmTransientFor)
 
203
    wmTransientFor = XInternAtom (dpy, "WM_TRANSIENT_FOR", 0);
 
204
  if (!wmClientLeader)
 
205
    wmClientLeader = XInternAtom (dpy, "WM_CLIENT_LEADER", 0);
 
206
}
 
207
 
 
208
compiz::X11TransientForReader::~X11TransientForReader ()
 
209
{
 
210
  delete priv;
 
211
}