diff options
author | Havoc Pennington <hp@redhat.com> | 2002-08-12 21:32:13 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2002-08-12 21:32:13 +0000 |
commit | 27e35b8bcde23717494af4f651eedabfae2d6b96 (patch) | |
tree | a1905e1484bc72a00e3caa3b76776ee4062ebb75 /src/group.c | |
parent | 501264647eb4241127f6cee9c9bfc16a6e75d193 (diff) | |
download | metacity-27e35b8bcde23717494af4f651eedabfae2d6b96.tar.gz |
window is in fullscreen layer if any member of its group is fullscreen
2002-08-12 Havoc Pennington <hp@redhat.com>
* src/stack.c (compute_layer): window is in fullscreen layer if
any member of its group is fullscreen
* src/window.c (meta_window_unmake_fullscreen): update layer for
whole window group
(meta_window_make_fullscreen): ditto
* src/util.c (meta_unsigned_long_hash): move hash/equal funcs for
Window in here.
* src/group.c: track window groups so we can do stuff with them.
Diffstat (limited to 'src/group.c')
-rw-r--r-- | src/group.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/group.c b/src/group.c new file mode 100644 index 00000000..8550c50c --- /dev/null +++ b/src/group.c @@ -0,0 +1,188 @@ +/* Metacity window groups */ + +/* + * Copyright (C) 2002 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "util.h" +#include "group.h" +#include "window.h" + +struct _MetaGroup +{ + MetaDisplay *display; + GSList *windows; + Window group_leader; + int refcount; +}; + +static MetaGroup* +meta_group_new (MetaDisplay *display, + Window group_leader) +{ + MetaGroup *group; + + group = g_new0 (MetaGroup, 1); + + group->display = display; + group->windows = NULL; + group->group_leader = group_leader; + group->refcount = 1; /* owned by caller, hash table has only weak ref */ + + if (display->groups_by_leader == NULL) + display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash, + meta_unsigned_long_equal); + + g_assert (g_hash_table_lookup (display->groups_by_leader, &group_leader) == NULL); + + g_hash_table_insert (display->groups_by_leader, + &group->group_leader, + group); + + return group; +} + +static void +meta_group_unref (MetaGroup *group) +{ + g_return_if_fail (group->refcount > 0); + + group->refcount -= 1; + if (group->refcount == 0) + { + g_assert (group->display->groups_by_leader != NULL); + + g_hash_table_remove (group->display->groups_by_leader, + &group->group_leader); + + /* mop up hash table, this is how it gets freed on display close */ + if (g_hash_table_size (group->display->groups_by_leader) == 0) + { + g_hash_table_destroy (group->display->groups_by_leader); + group->display->groups_by_leader = NULL; + } + + g_free (group); + } +} + +MetaGroup* +meta_window_get_group (MetaWindow *window) +{ + if (window->cached_group == NULL && + window->xgroup_leader != None) /* some windows have no group */ + { + MetaGroup *group; + + group = NULL; + + if (window->display->groups_by_leader) + group = g_hash_table_lookup (window->display->groups_by_leader, + &window->xgroup_leader); + + if (group != NULL) + { + window->cached_group = group; + group->refcount += 1; + } + else + { + group = meta_group_new (window->display, + window->xgroup_leader); + + window->cached_group = group; + } + + window->cached_group->windows = g_slist_prepend (window->cached_group->windows, + window); + } + + return window->cached_group; +} + +void +meta_window_shutdown_group (MetaWindow *window) +{ + if (window->cached_group != NULL) + { + window->cached_group->windows = + g_slist_remove (window->cached_group->windows, + window); + meta_group_unref (window->cached_group); + window->cached_group = NULL; + } +} + +MetaGroup* +meta_display_lookup_group (MetaDisplay *display, + Window group_leader) +{ + MetaGroup *group; + + group = NULL; + + if (display->groups_by_leader) + group = g_hash_table_lookup (display->groups_by_leader, + &group_leader); + + return group; +} + +GSList* +meta_group_list_windows (MetaGroup *group) +{ + return g_slist_copy (group->windows); +} + +void +meta_group_update_layers (MetaGroup *group) +{ + GSList *tmp; + GSList *frozen_stacks; + + if (group->windows == NULL) + return; + + frozen_stacks = NULL; + tmp = group->windows; + while (tmp != NULL) + { + MetaWindow *window = tmp->data; + + /* we end up freezing the same stack a lot of times, + * but doesn't hurt anything. have to handle + * groups that span 2 screens. + */ + meta_stack_freeze (window->screen->stack); + frozen_stacks = g_slist_prepend (frozen_stacks, window->screen->stack); + + meta_stack_update_layer (window->screen->stack, + window); + + tmp = tmp->next; + } + + tmp = frozen_stacks; + while (tmp != NULL) + { + meta_stack_thaw (tmp->data); + tmp = tmp->next; + } + + g_slist_free (frozen_stacks); +} |