/* MetaWindow property handling */ /* * Copyright (C) 2001, 2002, 2003 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 #include "window-props.h" #include "xprops.h" #include "frame.h" #include "group.h" #include typedef void (* InitValueFunc) (MetaDisplay *display, Atom property, MetaPropValue *value); typedef void (* ReloadValueFunc) (MetaWindow *window, MetaPropValue *value); struct _MetaWindowPropHooks { Atom property; InitValueFunc init_func; ReloadValueFunc reload_func; }; static void init_prop_value (MetaDisplay *display, Atom property, MetaPropValue *value); static void reload_prop_value (MetaWindow *window, MetaPropValue *value); static MetaWindowPropHooks* find_hooks (MetaDisplay *display, Atom property); void meta_window_reload_property (MetaWindow *window, Atom property) { meta_window_reload_properties (window, &property, 1); } void meta_window_reload_properties (MetaWindow *window, const Atom *properties, int n_properties) { int i; MetaPropValue *values; g_return_if_fail (properties != NULL); g_return_if_fail (n_properties > 0); values = g_new0 (MetaPropValue, n_properties); i = 0; while (i < n_properties) { init_prop_value (window->display, properties[i], &values[i]); ++i; } meta_prop_get_values (window->display, window->xwindow, values, n_properties); i = 0; while (i < n_properties) { reload_prop_value (window, &values[i]); ++i; } meta_prop_free_values (values, n_properties); g_free (values); } /* Fill in the MetaPropValue used to get the value of "property" */ static void init_prop_value (MetaDisplay *display, Atom property, MetaPropValue *value) { MetaWindowPropHooks *hooks; value->type = META_PROP_VALUE_INVALID; value->atom = None; hooks = find_hooks (display, property); if (hooks && hooks->init_func != NULL) (* hooks->init_func) (display, property, value); } static void reload_prop_value (MetaWindow *window, MetaPropValue *value) { MetaWindowPropHooks *hooks; hooks = find_hooks (window->display, value->atom); if (hooks && hooks->reload_func != NULL) (* hooks->reload_func) (window, value); } static void init_wm_client_machine (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_STRING; value->atom = display->atom_wm_client_machine; } static void reload_wm_client_machine (MetaWindow *window, MetaPropValue *value) { g_free (window->wm_client_machine); window->wm_client_machine = NULL; if (value->type != META_PROP_VALUE_INVALID) window->wm_client_machine = g_strdup (value->v.str); meta_verbose ("Window has client machine \"%s\"\n", window->wm_client_machine ? window->wm_client_machine : "unset"); } static void init_net_wm_pid (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_CARDINAL; value->atom = display->atom_net_wm_pid; } static void reload_net_wm_pid (MetaWindow *window, MetaPropValue *value) { if (value->type != META_PROP_VALUE_INVALID) { gulong cardinal = (int) value->v.cardinal; if (cardinal <= 0) meta_warning (_("Application set a bogus _NET_WM_PID %ld\n"), cardinal); else { window->net_wm_pid = cardinal; meta_verbose ("Window has _NET_WM_PID %d\n", window->net_wm_pid); } } } static void init_net_wm_user_time (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_CARDINAL; value->atom = display->atom_net_wm_user_time; } static void reload_net_wm_user_time (MetaWindow *window, MetaPropValue *value) { if (value->type != META_PROP_VALUE_INVALID) { gulong cardinal = value->v.cardinal; window->net_wm_user_time_set = TRUE; window->net_wm_user_time = cardinal; meta_topic (META_DEBUG_STARTUP, "Window %s has _NET_WM_USER_TIME of %lu\n", window->desc, window->net_wm_user_time); } } static void set_window_title (MetaWindow *window, const char *title) { char *str; g_free (window->title); if (title == NULL) window->title = g_strdup (""); else window->title = g_strdup (title); /* strndup is a hack since GNU libc has broken %.10s */ str = g_strndup (window->title, 10); g_free (window->desc); window->desc = g_strdup_printf ("0x%lx (%s)", window->xwindow, str); g_free (str); if (window->frame) meta_ui_set_frame_title (window->screen->ui, window->frame->xwindow, window->title); } static void init_net_wm_name (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_UTF8; value->atom = display->atom_net_wm_name; } static void reload_net_wm_name (MetaWindow *window, MetaPropValue *value) { if (value->type != META_PROP_VALUE_INVALID) { set_window_title (window, value->v.str); window->using_net_wm_name = TRUE; meta_verbose ("Using _NET_WM_NAME for new title of %s: \"%s\"\n", window->desc, window->title); } else { set_window_title (window, NULL); window->using_net_wm_name = FALSE; } } static void init_wm_name (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_TEXT_PROPERTY; value->atom = XA_WM_NAME; } static void reload_wm_name (MetaWindow *window, MetaPropValue *value) { if (window->using_net_wm_name) { meta_verbose ("Ignoring WM_NAME \"%s\" as _NET_WM_NAME is set\n", value->v.str); return; } if (value->type != META_PROP_VALUE_INVALID) { set_window_title (window, value->v.str); meta_verbose ("Using WM_NAME for new title of %s: \"%s\"\n", window->desc, window->title); } else { set_window_title (window, NULL); } } static void set_icon_title (MetaWindow *window, const char *title) { g_free (window->icon_name); if (title == NULL) window->icon_name = g_strdup (""); else window->icon_name = g_strdup (title); } static void init_net_wm_icon_name (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_UTF8; value->atom = display->atom_net_wm_icon_name; } static void reload_net_wm_icon_name (MetaWindow *window, MetaPropValue *value) { if (value->type != META_PROP_VALUE_INVALID) { set_icon_title (window, value->v.str); window->using_net_wm_icon_name = TRUE; meta_verbose ("Using _NET_WM_ICON_NAME for new title of %s: \"%s\"\n", window->desc, window->title); } else { set_icon_title (window, NULL); window->using_net_wm_icon_name = FALSE; } } static void init_wm_icon_name (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_TEXT_PROPERTY; value->atom = XA_WM_ICON_NAME; } static void reload_wm_icon_name (MetaWindow *window, MetaPropValue *value) { if (window->using_net_wm_icon_name) { meta_verbose ("Ignoring WM_ICON_NAME \"%s\" as _NET_WM_ICON_NAME is set\n", value->v.str); return; } if (value->type != META_PROP_VALUE_INVALID) { set_icon_title (window, value->v.str); meta_verbose ("Using WM_ICON_NAME for new title of %s: \"%s\"\n", window->desc, window->title); } else { set_icon_title (window, NULL); } } static void init_net_wm_desktop (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_CARDINAL; value->atom = display->atom_net_wm_desktop; } static void reload_net_wm_desktop (MetaWindow *window, MetaPropValue *value) { if (value->type != META_PROP_VALUE_INVALID) { window->initial_workspace_set = TRUE; window->initial_workspace = value->v.cardinal; meta_topic (META_DEBUG_PLACEMENT, "Read initial workspace prop %d for %s\n", window->initial_workspace, window->desc); } } static void init_net_startup_id (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_UTF8; value->atom = display->atom_net_startup_id; } static void reload_net_startup_id (MetaWindow *window, MetaPropValue *value) { g_free (window->startup_id); if (value->type != META_PROP_VALUE_INVALID) window->startup_id = g_strdup (value->v.str); else window->startup_id = NULL; meta_verbose ("New _NET_STARTUP_ID \"%s\" for %s\n", window->startup_id ? window->startup_id : "unset", window->desc); } static void init_update_counter (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_SYNC_COUNTER; value->atom = display->atom_net_wm_sync_request_counter; } static void reload_update_counter (MetaWindow *window, MetaPropValue *value) { if (value->type != META_PROP_VALUE_INVALID) { #ifdef HAVE_XSYNC XSyncCounter counter = value->v.xcounter; window->sync_request_counter = counter; meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx\n", window->sync_request_counter); #endif } } static void init_normal_hints (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_SIZE_HINTS; value->atom = XA_WM_NORMAL_HINTS; } #define FLAG_TOGGLED_ON(old,new,flag) \ (((old)->flags & (flag)) == 0 && \ ((new)->flags & (flag)) != 0) #define FLAG_TOGGLED_OFF(old,new,flag) \ (((old)->flags & (flag)) != 0 && \ ((new)->flags & (flag)) == 0) #define FLAG_CHANGED(old,new,flag) \ (FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag)) static void spew_size_hints_differences (const XSizeHints *old, const XSizeHints *new) { if (FLAG_CHANGED (old, new, USPosition)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USPosition now %s\n", FLAG_TOGGLED_ON (old, new, USPosition) ? "set" : "unset"); if (FLAG_CHANGED (old, new, USSize)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USSize now %s\n", FLAG_TOGGLED_ON (old, new, USSize) ? "set" : "unset"); if (FLAG_CHANGED (old, new, PPosition)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PPosition now %s\n", FLAG_TOGGLED_ON (old, new, PPosition) ? "set" : "unset"); if (FLAG_CHANGED (old, new, PSize)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PSize now %s\n", FLAG_TOGGLED_ON (old, new, PSize) ? "set" : "unset"); if (FLAG_CHANGED (old, new, PMinSize)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMinSize now %s (%d x %d -> %d x %d)\n", FLAG_TOGGLED_ON (old, new, PMinSize) ? "set" : "unset", old->min_width, old->min_height, new->min_width, new->min_height); if (FLAG_CHANGED (old, new, PMaxSize)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMaxSize now %s (%d x %d -> %d x %d)\n", FLAG_TOGGLED_ON (old, new, PMaxSize) ? "set" : "unset", old->max_width, old->max_height, new->max_width, new->max_height); if (FLAG_CHANGED (old, new, PResizeInc)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PResizeInc now %s (width_inc %d -> %d height_inc %d -> %d)\n", FLAG_TOGGLED_ON (old, new, PResizeInc) ? "set" : "unset", old->width_inc, new->width_inc, old->height_inc, new->height_inc); if (FLAG_CHANGED (old, new, PAspect)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PAspect now %s (min %d/%d -> %d/%d max %d/%d -> %d/%d)\n", FLAG_TOGGLED_ON (old, new, PAspect) ? "set" : "unset", old->min_aspect.x, old->min_aspect.y, new->min_aspect.x, new->min_aspect.y, old->max_aspect.x, old->max_aspect.y, new->max_aspect.x, new->max_aspect.y); if (FLAG_CHANGED (old, new, PBaseSize)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PBaseSize now %s (%d x %d -> %d x %d)\n", FLAG_TOGGLED_ON (old, new, PBaseSize) ? "set" : "unset", old->base_width, old->base_height, new->base_width, new->base_height); if (FLAG_CHANGED (old, new, PWinGravity)) meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PWinGravity now %s (%d -> %d)\n", FLAG_TOGGLED_ON (old, new, PWinGravity) ? "set" : "unset", old->win_gravity, new->win_gravity); } void meta_set_normal_hints (MetaWindow *window, XSizeHints *hints) { int x, y, w, h; /* Save the last ConfigureRequest, which we put here. * Values here set in the hints are supposed to * be ignored. */ x = window->size_hints.x; y = window->size_hints.y; w = window->size_hints.width; h = window->size_hints.height; /* as far as I can tell, value->v.size_hints.flags is just to * check whether we had old-style normal hints without gravity, * base size as returned by XGetNormalHints(), so we don't * really use it as we fixup window->size_hints to have those * fields if they're missing. */ /* * When the window is first created, NULL hints will * be passed in which will initialize all of the fields * as if flags were zero */ if (hints) window->size_hints = *hints; else window->size_hints.flags = 0; /* Put back saved ConfigureRequest. */ window->size_hints.x = x; window->size_hints.y = y; window->size_hints.width = w; window->size_hints.height = h; if (window->size_hints.flags & PBaseSize) { meta_topic (META_DEBUG_GEOMETRY, "Window %s sets base size %d x %d\n", window->desc, window->size_hints.base_width, window->size_hints.base_height); } else if (window->size_hints.flags & PMinSize) { window->size_hints.base_width = window->size_hints.min_width; window->size_hints.base_height = window->size_hints.min_height; } else { window->size_hints.base_width = 0; window->size_hints.base_height = 0; } window->size_hints.flags |= PBaseSize; if (window->size_hints.flags & PMinSize) { meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d\n", window->desc, window->size_hints.min_width, window->size_hints.min_height); } else if (window->size_hints.flags & PBaseSize) { window->size_hints.min_width = window->size_hints.base_width; window->size_hints.min_height = window->size_hints.base_height; } else { window->size_hints.min_width = 0; window->size_hints.min_height = 0; } window->size_hints.flags |= PMinSize; if (window->size_hints.flags & PMaxSize) { meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d\n", window->desc, window->size_hints.max_width, window->size_hints.max_height); } else { window->size_hints.max_width = G_MAXINT; window->size_hints.max_height = G_MAXINT; window->size_hints.flags |= PMaxSize; } if (window->size_hints.max_width < window->size_hints.min_width) { /* someone is on crack */ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max width %d less than min width %d, disabling resize\n", window->desc, window->size_hints.max_width, window->size_hints.min_width); window->size_hints.max_width = window->size_hints.min_width; } if (window->size_hints.max_height < window->size_hints.min_height) { /* another cracksmoker */ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max height %d less than min height %d, disabling resize\n", window->desc, window->size_hints.max_height, window->size_hints.min_height); window->size_hints.max_height = window->size_hints.min_height; } if (window->size_hints.min_width < 1) { /* another cracksmoker */ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min width to 0, which makes no sense\n", window->desc); window->size_hints.min_width = 1; } if (window->size_hints.max_width < 1) { /* another cracksmoker */ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max width to 0, which makes no sense\n", window->desc); window->size_hints.max_width = 1; } if (window->size_hints.min_height < 1) { /* another cracksmoker */ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min height to 0, which makes no sense\n", window->desc); window->size_hints.min_height = 1; } if (window->size_hints.max_height < 1) { /* another cracksmoker */ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max height to 0, which makes no sense\n", window->desc); window->size_hints.max_height = 1; } if (window->size_hints.flags & PResizeInc) { meta_topic (META_DEBUG_GEOMETRY, "Window %s sets resize width inc: %d height inc: %d\n", window->desc, window->size_hints.width_inc, window->size_hints.height_inc); if (window->size_hints.width_inc == 0) { window->size_hints.width_inc = 1; meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 width_inc to 1\n"); } if (window->size_hints.height_inc == 0) { window->size_hints.height_inc = 1; meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 height_inc to 1\n"); } } else { window->size_hints.width_inc = 1; window->size_hints.height_inc = 1; window->size_hints.flags |= PResizeInc; } if (window->size_hints.flags & PAspect) { meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min_aspect: %d/%d max_aspect: %d/%d\n", window->desc, window->size_hints.min_aspect.x, window->size_hints.min_aspect.y, window->size_hints.max_aspect.x, window->size_hints.max_aspect.y); /* don't divide by 0 */ if (window->size_hints.min_aspect.y < 1) window->size_hints.min_aspect.y = 1; if (window->size_hints.max_aspect.y < 1) window->size_hints.max_aspect.y = 1; } else { window->size_hints.min_aspect.x = 1; window->size_hints.min_aspect.y = G_MAXINT; window->size_hints.max_aspect.x = G_MAXINT; window->size_hints.max_aspect.y = 1; window->size_hints.flags |= PAspect; } if (window->size_hints.flags & PWinGravity) { meta_topic (META_DEBUG_GEOMETRY, "Window %s sets gravity %d\n", window->desc, window->size_hints.win_gravity); } else { meta_topic (META_DEBUG_GEOMETRY, "Window %s doesn't set gravity, using NW\n", window->desc); window->size_hints.win_gravity = NorthWestGravity; window->size_hints.flags |= PWinGravity; } } static void reload_normal_hints (MetaWindow *window, MetaPropValue *value) { if (value->type != META_PROP_VALUE_INVALID) { XSizeHints old_hints; meta_topic (META_DEBUG_GEOMETRY, "Updating WM_NORMAL_HINTS for %s\n", window->desc); old_hints = window->size_hints; meta_set_normal_hints (window, value->v.size_hints.hints); spew_size_hints_differences (&old_hints, &window->size_hints); meta_window_recalc_features (window); } } static void init_wm_protocols (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_ATOM_LIST; value->atom = display->atom_wm_protocols; } static void reload_wm_protocols (MetaWindow *window, MetaPropValue *value) { int i; window->take_focus = FALSE; window->delete_window = FALSE; window->net_wm_ping = FALSE; if (value->type == META_PROP_VALUE_INVALID) return; i = 0; while (i < value->v.atom_list.n_atoms) { if (value->v.atom_list.atoms[i] == window->display->atom_wm_take_focus) window->take_focus = TRUE; else if (value->v.atom_list.atoms[i] == window->display->atom_wm_delete_window) window->delete_window = TRUE; else if (value->v.atom_list.atoms[i] == window->display->atom_net_wm_ping) window->net_wm_ping = TRUE; ++i; } meta_verbose ("New _NET_STARTUP_ID \"%s\" for %s\n", window->startup_id ? window->startup_id : "unset", window->desc); } static void init_wm_hints (MetaDisplay *display, Atom property, MetaPropValue *value) { value->type = META_PROP_VALUE_WM_HINTS; value->atom = XA_WM_HINTS; } static void reload_wm_hints (MetaWindow *window, MetaPropValue *value) { Window old_group_leader; old_group_leader = window->xgroup_leader; /* Fill in defaults */ window->input = TRUE; window->initially_iconic = FALSE; window->xgroup_leader = None; window->wm_hints_pixmap = None; window->wm_hints_mask = None; if (value->type != META_PROP_VALUE_INVALID) { const XWMHints *hints = value->v.wm_hints; if (hints->flags & InputHint) window->input = hints->input; if (hints->flags & StateHint) window->initially_iconic = (hints->initial_state == IconicState); if (hints->flags & WindowGroupHint) window->xgroup_leader = hints->window_group; if (hints->flags & IconPixmapHint) window->wm_hints_pixmap = hints->icon_pixmap; if (hints->flags & IconMaskHint) window->wm_hints_mask = hints->icon_mask; meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n", window->input, window->initially_iconic, window->xgroup_leader, window->wm_hints_pixmap, window->wm_hints_mask); } if (window->xgroup_leader != old_group_leader) { meta_verbose ("Window %s changed its group leader to 0x%lx\n", window->desc, window->xgroup_leader); meta_window_group_leader_changed (window); } meta_icon_cache_property_changed (&window->icon_cache, window->display, XA_WM_HINTS); meta_window_queue_update_icon (window); meta_window_queue_move_resize (window); } #define N_HOOKS 24 void meta_display_init_window_prop_hooks (MetaDisplay *display) { int i; MetaWindowPropHooks *hooks; g_assert (display->prop_hooks == NULL); display->prop_hooks = g_new0 (MetaWindowPropHooks, N_HOOKS); hooks = display->prop_hooks; i = 0; hooks[i].property = display->atom_wm_state; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_wm_client_machine; hooks[i].init_func = init_wm_client_machine; hooks[i].reload_func = reload_wm_client_machine; ++i; hooks[i].property = display->atom_net_wm_pid; hooks[i].init_func = init_net_wm_pid; hooks[i].reload_func = reload_net_wm_pid; ++i; hooks[i].property = display->atom_net_wm_user_time; hooks[i].init_func = init_net_wm_user_time; hooks[i].reload_func = reload_net_wm_user_time; ++i; hooks[i].property = display->atom_net_wm_name; hooks[i].init_func = init_net_wm_name; hooks[i].reload_func = reload_net_wm_name; ++i; hooks[i].property = XA_WM_NAME; hooks[i].init_func = init_wm_name; hooks[i].reload_func = reload_wm_name; ++i; hooks[i].property = display->atom_net_wm_icon_name; hooks[i].init_func = init_net_wm_icon_name; hooks[i].reload_func = reload_net_wm_icon_name; ++i; hooks[i].property = XA_WM_ICON_NAME; hooks[i].init_func = init_wm_icon_name; hooks[i].reload_func = reload_wm_icon_name; ++i; hooks[i].property = display->atom_net_wm_state; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_motif_wm_hints; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_net_wm_icon_geometry; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = XA_WM_CLASS; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_wm_client_leader; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_sm_client_id; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_wm_window_role; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_net_wm_window_type; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_net_wm_desktop; hooks[i].init_func = init_net_wm_desktop; hooks[i].reload_func = reload_net_wm_desktop; ++i; hooks[i].property = display->atom_net_wm_strut; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_net_wm_strut_partial; hooks[i].init_func = NULL; hooks[i].reload_func = NULL; ++i; hooks[i].property = display->atom_net_startup_id; hooks[i].init_func = init_net_startup_id; hooks[i].reload_func = reload_net_startup_id; ++i; hooks[i].property = display->atom_net_wm_sync_request_counter; hooks[i].init_func = init_update_counter; hooks[i].reload_func = reload_update_counter; ++i; hooks[i].property = XA_WM_NORMAL_HINTS; hooks[i].init_func = init_normal_hints; hooks[i].reload_func = reload_normal_hints; ++i; hooks[i].property = display->atom_wm_protocols; hooks[i].init_func = init_wm_protocols; hooks[i].reload_func = reload_wm_protocols; ++i; hooks[i].property = XA_WM_HINTS; hooks[i].init_func = init_wm_hints; hooks[i].reload_func = reload_wm_hints; ++i; if (i != N_HOOKS) g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS); } void meta_display_free_window_prop_hooks (MetaDisplay *display) { g_assert (display->prop_hooks != NULL); g_free (display->prop_hooks); display->prop_hooks = NULL; } static MetaWindowPropHooks* find_hooks (MetaDisplay *display, Atom property) { int i; /* FIXME we could sort the array and do binary search or * something */ i = 0; while (i < N_HOOKS) { if (display->prop_hooks[i].property == property) return &display->prop_hooks[i]; ++i; } return NULL; }