~muktupavels/metacity/lp1403583

1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3
/* Metacity window groups */
4
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
5
/*
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
6
 * Copyright (C) 2002 Red Hat Inc.
7
 * Copyright (C) 2003 Rob Adams
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
8
 *
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License as
11
 * published by the Free Software Foundation; either version 2 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * General Public License for more details.
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
18
 *
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
19
 * You should have received a copy of the GNU General Public License
1.2.68 by Dmitry Shachnev
Import upstream version 3.12.0
20
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
21
 */
22
23
#include <config.h>
24
#include "util.h"
25
#include "group-private.h"
26
#include "group-props.h"
27
#include "window.h"
28
29
static MetaGroup*
30
meta_group_new (MetaDisplay *display,
31
                Window       group_leader)
32
{
33
  MetaGroup *group;
34
#define N_INITIAL_PROPS 3
35
  Atom initial_props[N_INITIAL_PROPS];
36
  int i;
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
37
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
38
  g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
39
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
40
  group = g_new0 (MetaGroup, 1);
41
42
  group->display = display;
43
  group->windows = NULL;
44
  group->group_leader = group_leader;
45
  group->refcount = 1; /* owned by caller, hash table has only weak ref */
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
46
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
47
  if (display->groups_by_leader == NULL)
48
    display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash,
49
                                                  meta_unsigned_long_equal);
50
51
  g_assert (g_hash_table_lookup (display->groups_by_leader, &group_leader) == NULL);
52
53
  g_hash_table_insert (display->groups_by_leader,
54
                       &group->group_leader,
55
                       group);
56
57
  /* Fill these in the order we want them to be gotten */
58
  i = 0;
1.2.41 by Pedro Fragoso
Import upstream version 2.23.21
59
  initial_props[i++] = display->atom_WM_CLIENT_MACHINE;
60
  initial_props[i++] = display->atom__NET_WM_PID;
61
  initial_props[i++] = display->atom__NET_STARTUP_ID;
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
62
  g_assert (N_INITIAL_PROPS == i);
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
63
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
64
  meta_group_reload_properties (group, initial_props, N_INITIAL_PROPS);
65
66
  meta_topic (META_DEBUG_GROUPS,
67
              "Created new group with leader 0x%lx\n",
68
              group->group_leader);
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
69
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
70
  return group;
71
}
72
73
static void
74
meta_group_unref (MetaGroup *group)
75
{
76
  g_return_if_fail (group->refcount > 0);
77
78
  group->refcount -= 1;
79
  if (group->refcount == 0)
80
    {
81
      meta_topic (META_DEBUG_GROUPS,
82
                  "Destroying group with leader 0x%lx\n",
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
83
                  group->group_leader);
84
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
85
      g_assert (group->display->groups_by_leader != NULL);
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
86
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
87
      g_hash_table_remove (group->display->groups_by_leader,
88
                           &group->group_leader);
89
90
      /* mop up hash table, this is how it gets freed on display close */
91
      if (g_hash_table_size (group->display->groups_by_leader) == 0)
92
        {
93
          g_hash_table_destroy (group->display->groups_by_leader);
94
          group->display->groups_by_leader = NULL;
95
        }
96
97
      g_free (group->wm_client_machine);
98
      g_free (group->startup_id);
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
99
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
100
      g_free (group);
101
    }
102
}
103
104
MetaGroup*
105
meta_window_get_group (MetaWindow *window)
106
{
107
  if (window->unmanaging)
108
    return NULL;
109
110
  return window->group;
111
}
112
113
void
114
meta_window_compute_group (MetaWindow* window)
115
{
116
  MetaGroup *group;
117
  MetaWindow *ancestor;
118
119
  /* use window->xwindow if no window->xgroup_leader */
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
120
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
121
  group = NULL;
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
122
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
123
  /* Determine the ancestor of the window; its group setting will override the
124
   * normal grouping rules; see bug 328211.
125
   */
126
  ancestor = meta_window_find_root_ancestor (window);
127
128
  if (window->display->groups_by_leader)
129
    {
130
      if (ancestor != window)
131
        group = ancestor->group;
132
      else if (window->xgroup_leader != None)
133
        group = g_hash_table_lookup (window->display->groups_by_leader,
134
                                     &window->xgroup_leader);
135
      else
136
        group = g_hash_table_lookup (window->display->groups_by_leader,
137
                                     &window->xwindow);
138
    }
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
139
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
140
  if (group != NULL)
141
    {
142
      window->group = group;
143
      group->refcount += 1;
144
    }
145
  else
146
    {
147
      if (ancestor != window && ancestor->xgroup_leader != None)
148
        group = meta_group_new (window->display,
149
                                ancestor->xgroup_leader);
150
      else if (window->xgroup_leader != None)
151
        group = meta_group_new (window->display,
152
                                window->xgroup_leader);
153
      else
154
        group = meta_group_new (window->display,
155
                                window->xwindow);
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
156
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
157
      window->group = group;
158
    }
159
160
  window->group->windows = g_slist_prepend (window->group->windows, window);
161
162
  meta_topic (META_DEBUG_GROUPS,
163
              "Adding %s to group with leader 0x%lx\n",
164
              window->desc, group->group_leader);
165
166
}
167
168
static void
169
remove_window_from_group (MetaWindow *window)
170
{
171
  if (window->group != NULL)
172
    {
173
      meta_topic (META_DEBUG_GROUPS,
174
                  "Removing %s from group with leader 0x%lx\n",
175
                  window->desc, window->group->group_leader);
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
176
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
177
      window->group->windows =
178
        g_slist_remove (window->group->windows,
179
                        window);
180
      meta_group_unref (window->group);
181
      window->group = NULL;
182
    }
183
}
184
185
void
186
meta_window_group_leader_changed (MetaWindow *window)
187
{
188
  remove_window_from_group (window);
189
  meta_window_compute_group (window);
190
}
191
192
void
193
meta_window_shutdown_group (MetaWindow *window)
194
{
195
  remove_window_from_group (window);
196
}
197
198
MetaGroup*
199
meta_display_lookup_group (MetaDisplay *display,
200
                           Window       group_leader)
201
{
202
  MetaGroup *group;
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
203
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
204
  group = NULL;
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
205
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
206
  if (display->groups_by_leader)
207
    group = g_hash_table_lookup (display->groups_by_leader,
208
                                 &group_leader);
209
210
  return group;
211
}
212
213
GSList*
214
meta_group_list_windows (MetaGroup *group)
215
{
216
  return g_slist_copy (group->windows);
217
}
218
219
void
220
meta_group_update_layers (MetaGroup *group)
221
{
222
  GSList *tmp;
223
  GSList *frozen_stacks;
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
224
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
225
  if (group->windows == NULL)
226
    return;
227
228
  frozen_stacks = NULL;
229
  tmp = group->windows;
230
  while (tmp != NULL)
231
    {
232
      MetaWindow *window = tmp->data;
233
234
      /* we end up freezing the same stack a lot of times,
235
       * but doesn't hurt anything. have to handle
236
       * groups that span 2 screens.
237
       */
238
      meta_stack_freeze (window->screen->stack);
239
      frozen_stacks = g_slist_prepend (frozen_stacks, window->screen->stack);
240
241
      meta_stack_update_layer (window->screen->stack,
242
                               window);
1.2.69 by Dmitry Shachnev
Import upstream version 3.14.0
243
1.2.37 by Pedro Fragoso
Import upstream version 2.21.8
244
      tmp = tmp->next;
245
    }
246
247
  tmp = frozen_stacks;
248
  while (tmp != NULL)
249
    {
250
      meta_stack_thaw (tmp->data);
251
      tmp = tmp->next;
252
    }
253
254
  g_slist_free (frozen_stacks);
255
}
256
257
const char*
258
meta_group_get_startup_id (MetaGroup *group)
259
{
260
  return group->startup_id;
261
}
262
263
gboolean
264
meta_group_property_notify (MetaGroup  *group,
265
                            XEvent     *event)
266
{
267
  meta_group_reload_property (group,
268
                              event->xproperty.atom);
269
270
  return TRUE;
271
272
}