00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026 #include "util.h"
00027 #include "group-private.h"
00028 #include "group-props.h"
00029 #include "window.h"
00030
00031 static MetaGroup*
00032 meta_group_new (MetaDisplay *display,
00033 Window group_leader)
00034 {
00035 MetaGroup *group;
00036 #define N_INITIAL_PROPS 3
00037 Atom initial_props[N_INITIAL_PROPS];
00038 int i;
00039
00040 g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
00041
00042 group = g_new0 (MetaGroup, 1);
00043
00044 group->display = display;
00045 group->windows = NULL;
00046 group->group_leader = group_leader;
00047 group->refcount = 1;
00048
00049 if (display->groups_by_leader == NULL)
00050 display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash,
00051 meta_unsigned_long_equal);
00052
00053 g_assert (g_hash_table_lookup (display->groups_by_leader, &group_leader) == NULL);
00054
00055 g_hash_table_insert (display->groups_by_leader,
00056 &group->group_leader,
00057 group);
00058
00059
00060 i = 0;
00061 initial_props[i++] = display->atom_WM_CLIENT_MACHINE;
00062 initial_props[i++] = display->atom__NET_WM_PID;
00063 initial_props[i++] = display->atom__NET_STARTUP_ID;
00064 g_assert (N_INITIAL_PROPS == i);
00065
00066 meta_group_reload_properties (group, initial_props, N_INITIAL_PROPS);
00067
00068 meta_topic (META_DEBUG_GROUPS,
00069 "Created new group with leader 0x%lx\n",
00070 group->group_leader);
00071
00072 return group;
00073 }
00074
00075 static void
00076 meta_group_unref (MetaGroup *group)
00077 {
00078 g_return_if_fail (group->refcount > 0);
00079
00080 group->refcount -= 1;
00081 if (group->refcount == 0)
00082 {
00083 meta_topic (META_DEBUG_GROUPS,
00084 "Destroying group with leader 0x%lx\n",
00085 group->group_leader);
00086
00087 g_assert (group->display->groups_by_leader != NULL);
00088
00089 g_hash_table_remove (group->display->groups_by_leader,
00090 &group->group_leader);
00091
00092
00093 if (g_hash_table_size (group->display->groups_by_leader) == 0)
00094 {
00095 g_hash_table_destroy (group->display->groups_by_leader);
00096 group->display->groups_by_leader = NULL;
00097 }
00098
00099 g_free (group->wm_client_machine);
00100 g_free (group->startup_id);
00101
00102 g_free (group);
00103 }
00104 }
00105
00106 MetaGroup*
00107 meta_window_get_group (MetaWindow *window)
00108 {
00109 if (window->unmanaging)
00110 return NULL;
00111
00112 return window->group;
00113 }
00114
00115 void
00116 meta_window_compute_group (MetaWindow* window)
00117 {
00118 MetaGroup *group;
00119 MetaWindow *ancestor;
00120
00121
00122
00123 group = NULL;
00124
00125
00126
00127
00128 ancestor = meta_window_find_root_ancestor (window);
00129
00130 if (window->display->groups_by_leader)
00131 {
00132 if (ancestor != window)
00133 group = ancestor->group;
00134 else if (window->xgroup_leader != None)
00135 group = g_hash_table_lookup (window->display->groups_by_leader,
00136 &window->xgroup_leader);
00137 else
00138 group = g_hash_table_lookup (window->display->groups_by_leader,
00139 &window->xwindow);
00140 }
00141
00142 if (group != NULL)
00143 {
00144 window->group = group;
00145 group->refcount += 1;
00146 }
00147 else
00148 {
00149 if (ancestor != window && ancestor->xgroup_leader != None)
00150 group = meta_group_new (window->display,
00151 ancestor->xgroup_leader);
00152 else if (window->xgroup_leader != None)
00153 group = meta_group_new (window->display,
00154 window->xgroup_leader);
00155 else
00156 group = meta_group_new (window->display,
00157 window->xwindow);
00158
00159 window->group = group;
00160 }
00161
00162 window->group->windows = g_slist_prepend (window->group->windows, window);
00163
00164 meta_topic (META_DEBUG_GROUPS,
00165 "Adding %s to group with leader 0x%lx\n",
00166 window->desc, group->group_leader);
00167
00168 }
00169
00170 static void
00171 remove_window_from_group (MetaWindow *window)
00172 {
00173 if (window->group != NULL)
00174 {
00175 meta_topic (META_DEBUG_GROUPS,
00176 "Removing %s from group with leader 0x%lx\n",
00177 window->desc, window->group->group_leader);
00178
00179 window->group->windows =
00180 g_slist_remove (window->group->windows,
00181 window);
00182 meta_group_unref (window->group);
00183 window->group = NULL;
00184 }
00185 }
00186
00187 void
00188 meta_window_group_leader_changed (MetaWindow *window)
00189 {
00190 remove_window_from_group (window);
00191 meta_window_compute_group (window);
00192 }
00193
00194 void
00195 meta_window_shutdown_group (MetaWindow *window)
00196 {
00197 remove_window_from_group (window);
00198 }
00199
00200 MetaGroup*
00201 meta_display_lookup_group (MetaDisplay *display,
00202 Window group_leader)
00203 {
00204 MetaGroup *group;
00205
00206 group = NULL;
00207
00208 if (display->groups_by_leader)
00209 group = g_hash_table_lookup (display->groups_by_leader,
00210 &group_leader);
00211
00212 return group;
00213 }
00214
00215 GSList*
00216 meta_group_list_windows (MetaGroup *group)
00217 {
00218 return g_slist_copy (group->windows);
00219 }
00220
00221 void
00222 meta_group_update_layers (MetaGroup *group)
00223 {
00224 GSList *tmp;
00225 GSList *frozen_stacks;
00226
00227 if (group->windows == NULL)
00228 return;
00229
00230 frozen_stacks = NULL;
00231 tmp = group->windows;
00232 while (tmp != NULL)
00233 {
00234 MetaWindow *window = tmp->data;
00235
00236
00237
00238
00239
00240 meta_stack_freeze (window->screen->stack);
00241 frozen_stacks = g_slist_prepend (frozen_stacks, window->screen->stack);
00242
00243 meta_stack_update_layer (window->screen->stack,
00244 window);
00245
00246 tmp = tmp->next;
00247 }
00248
00249 tmp = frozen_stacks;
00250 while (tmp != NULL)
00251 {
00252 meta_stack_thaw (tmp->data);
00253 tmp = tmp->next;
00254 }
00255
00256 g_slist_free (frozen_stacks);
00257 }
00258
00259 const char*
00260 meta_group_get_startup_id (MetaGroup *group)
00261 {
00262 return group->startup_id;
00263 }
00264
00265 gboolean
00266 meta_group_property_notify (MetaGroup *group,
00267 XEvent *event)
00268 {
00269 meta_group_reload_property (group,
00270 event->xproperty.atom);
00271
00272 return TRUE;
00273
00274 }