diff --git a/ChangeLog b/ChangeLog index e998884e7..042b9739f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2002-11-03 Havoc Pennington + + * src/window.c (meta_window_new): use window-props.h stuff for a + couple of properties + (implement_showing): fix printf string + + * src/xprops.c (meta_prop_free_values): new function + + * src/window-props.h, src/window-props.c: start moving code that + handles loading window properties into this file. + +2002-11-03 Havoc Pennington + + * src/stack.c (create_constraints): filter out windows that aren't + in the stack for whatever reason, avoids a crash + 2002-11-03 Havoc Pennington * src/window.c (meta_window_calc_showing): split into "see if we diff --git a/src/Makefile.am b/src/Makefile.am index 4340e0a02..c39d6c679 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,8 @@ metacity_SOURCES= \ util.h \ window.c \ window.h \ + window-props.c \ + window-props.h \ workspace.c \ workspace.h \ xprops.c \ diff --git a/src/display.c b/src/display.c index 033d67e9a..9e3b9ed95 100644 --- a/src/display.c +++ b/src/display.c @@ -25,6 +25,7 @@ #include "main.h" #include "screen.h" #include "window.h" +#include "window-props.h" #include "frame.h" #include "errors.h" #include "keybindings.h" @@ -383,6 +384,9 @@ meta_display_open (const char *name) display->atom_net_wm_action_close = atoms[74]; display->atom_net_wm_state_above = atoms[75]; display->atom_net_wm_state_below = atoms[76]; + + display->prop_hooks = NULL; + meta_display_init_window_prop_hooks (display); /* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK, * created in screen_new @@ -663,6 +667,8 @@ meta_display_close (MetaDisplay *display) XDestroyWindow (display->xdisplay, display->leader_window); XFlush (display->xdisplay); + + meta_display_free_window_prop_hooks (display); #ifndef USE_GDK_DISPLAY meta_event_queue_free (display->events); diff --git a/src/display.h b/src/display.h index b748a1adf..d40559430 100644 --- a/src/display.h +++ b/src/display.h @@ -57,6 +57,8 @@ typedef struct _MetaUISlave MetaUISlave; typedef struct _MetaWindow MetaWindow; typedef struct _MetaWorkspace MetaWorkspace; +typedef struct _MetaWindowPropHooks MetaWindowPropHooks; + typedef void (* MetaWindowPingFunc) (MetaDisplay *display, Window xwindow, gpointer user_data); @@ -262,6 +264,9 @@ struct _MetaDisplay /* currently-active window menu if any */ MetaWindowMenu *window_menu; MetaWindow *window_with_menu; + + /* Managed by window-props.c */ + MetaWindowPropHooks *prop_hooks; #ifdef HAVE_STARTUP_NOTIFICATION /* This is at the end in case someone doesn't include config.h before this file @@ -269,7 +274,6 @@ struct _MetaDisplay */ SnDisplay *sn_display; #endif - }; gboolean meta_display_open (const char *name); diff --git a/src/stack.c b/src/stack.c index 04dcac9aa..4b9943390 100644 --- a/src/stack.c +++ b/src/stack.c @@ -522,6 +522,8 @@ add_constraint (Constraint **constraints, w->transient_parent_is_root_window) && \ WINDOW_HAS_TRANSIENT_TYPE (w)) +#define WINDOW_IN_STACK(w) (w->stack_position >= 0) + static void create_constraints (Constraint **constraints, GList *windows) @@ -532,6 +534,12 @@ create_constraints (Constraint **constraints, while (tmp != NULL) { MetaWindow *w = tmp->data; + + if (!WINDOW_IN_STACK (w)) + { + tmp = tmp->next; + continue; + } if (WINDOW_TRANSIENT_FOR_WHOLE_GROUP (w)) { @@ -552,6 +560,12 @@ create_constraints (Constraint **constraints, { MetaWindow *group_window = tmp2->data; + if (!WINDOW_IN_STACK (group_window)) + { + tmp2 = tmp2->next; + continue; + } + #if 0 /* old way of doing it */ if (!(meta_window_is_ancestor_of_transient (w, group_window)) && @@ -581,7 +595,7 @@ create_constraints (Constraint **constraints, parent = meta_display_lookup_x_window (w->display, w->xtransient_for); - if (parent) + if (parent && WINDOW_IN_STACK (parent)) { meta_topic (META_DEBUG_STACK, "Constraining %s above %s due to transiency\n", w->desc, parent->desc); diff --git a/src/window-props.c b/src/window-props.c new file mode 100644 index 000000000..13c5eb03c --- /dev/null +++ b/src/window-props.c @@ -0,0 +1,328 @@ +/* MetaWindow property handling */ + +/* + * Copyright (C) 2001, 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 +#include "window-props.h" +#include "xprops.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; + + hooks = find_hooks (display, property); + g_assert (hooks != NULL); + if (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); + g_assert (hooks != NULL); + if (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); + } + } +} + +#define N_HOOKS 22 + +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 = XA_WM_NORMAL_HINTS; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + + hooks[i].property = display->atom_net_wm_name; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + + hooks[i].property = XA_WM_NAME; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + + hooks[i].property = XA_WM_HINTS; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++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_win_layer; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + + hooks[i].property = display->atom_net_wm_desktop; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + + hooks[i].property = display->atom_win_workspace; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + + hooks[i].property = display->atom_net_wm_icon_name; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++i; + + hooks[i].property = XA_WM_ICON_NAME; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++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_win_hints; + hooks[i].init_func = NULL; + hooks[i].reload_func = NULL; + ++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; +} diff --git a/src/window-props.h b/src/window-props.h new file mode 100644 index 000000000..33cfd0df3 --- /dev/null +++ b/src/window-props.h @@ -0,0 +1,36 @@ +/* MetaWindow property handling */ + +/* + * Copyright (C) 2001, 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. + */ + +#ifndef META_WINDOW_PROPS_H +#define META_WINDOW_PROPS_H + +#include "window.h" + +void meta_window_reload_property (MetaWindow *window, + Atom property); +void meta_window_reload_properties (MetaWindow *window, + const Atom *properties, + int n_properties); + +void meta_display_init_window_prop_hooks (MetaDisplay *display); +void meta_display_free_window_prop_hooks (MetaDisplay *display); + +#endif /* META_WINDOW_PROPS_H */ diff --git a/src/window.c b/src/window.c index 250c6017f..d8fec1b03 100644 --- a/src/window.c +++ b/src/window.c @@ -36,6 +36,7 @@ #include "resizepopup.h" #include "xprops.h" #include "group.h" +#include "window-props.h" #include #include @@ -160,19 +161,9 @@ meta_window_new (MetaDisplay *display, MetaWorkspace *space; gulong existing_wm_state; #define N_INITIAL_PROPS 2 - MetaPropValue initial_props[N_INITIAL_PROPS]; + Atom initial_props[N_INITIAL_PROPS]; g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props)); - - memset (initial_props, '\0', sizeof (initial_props)); - -#define INITIAL_PROP_WM_CLIENT_MACHINE 0 - initial_props[0].type = META_PROP_VALUE_STRING; - initial_props[0].atom = display->atom_wm_client_machine; - -#define INITIAL_PROP_NET_WM_PID 1 - initial_props[1].type = META_PROP_VALUE_CARDINAL; - initial_props[1].atom = display->atom_net_wm_pid; meta_verbose ("Attempting to manage 0x%lx\n", xwindow); @@ -436,37 +427,13 @@ meta_window_new (MetaDisplay *display, window->stack_position = -1; window->initial_workspace = 0; /* not used */ meta_display_register_x_window (display, &window->xwindow, window); - - meta_prop_get_values (display, window->xwindow, - initial_props, N_INITIAL_PROPS); - if (initial_props[INITIAL_PROP_WM_CLIENT_MACHINE].type != - META_PROP_VALUE_INVALID) - { - window->wm_client_machine = - g_strdup (initial_props[INITIAL_PROP_WM_CLIENT_MACHINE].v.str); - - meta_XFree (initial_props[INITIAL_PROP_WM_CLIENT_MACHINE].v.str); - - meta_verbose ("Window has client machine \"%s\"\n", - window->wm_client_machine); - } - - if (initial_props[INITIAL_PROP_NET_WM_PID].type != - META_PROP_VALUE_INVALID) - { - gulong cardinal = (int) initial_props[INITIAL_PROP_NET_WM_PID].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); - } - } + /* Fill these in the order we want them to be gotten */ + initial_props[0] = display->atom_wm_client_machine; + initial_props[1] = display->atom_net_wm_pid; + g_assert (N_INITIAL_PROPS == 2); + + meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS); update_size_hints (window); update_title (window); @@ -1187,8 +1154,8 @@ implement_showing (MetaWindow *window, gboolean showing) { /* Actually show/hide the window */ - meta_verbose ("Implement showing = %d for window %s\n", window->desc, - showing); + meta_verbose ("Implement showing = %d for window %s\n", + showing, window->desc); if (!showing) { diff --git a/src/xprops.c b/src/xprops.c index 30de32865..af8facc58 100644 --- a/src/xprops.c +++ b/src/xprops.c @@ -1042,3 +1042,64 @@ meta_prop_get_values (MetaDisplay *display, g_free (tasks); } +static void +free_value (MetaPropValue *value) +{ + switch (value->type) + { + case META_PROP_VALUE_INVALID: + break; + case META_PROP_VALUE_UTF8: + meta_XFree (value->v.str); + break; + case META_PROP_VALUE_STRING: + meta_XFree (value->v.str); + break; + case META_PROP_VALUE_MOTIF_HINTS: + meta_XFree (value->v.motif_hints); + break; + case META_PROP_VALUE_CARDINAL: + break; + case META_PROP_VALUE_WINDOW: + break; + case META_PROP_VALUE_ATOM_LIST: + meta_XFree (value->v.atom_list.atoms); + break; + case META_PROP_VALUE_TEXT_PROPERTY: + meta_XFree (value->v.str); + break; + case META_PROP_VALUE_WM_HINTS: + meta_XFree (value->v.wm_hints); + break; + case META_PROP_VALUE_CLASS_HINT: + meta_XFree (value->v.class_hint.res_class); + meta_XFree (value->v.class_hint.res_name); + break; + case META_PROP_VALUE_SIZE_HINTS: + meta_XFree (value->v.size_hints.hints); + break; + case META_PROP_VALUE_UTF8_LIST: + g_strfreev (value->v.string_list.strings); + break; + case META_PROP_VALUE_CARDINAL_LIST: + meta_XFree (value->v.cardinal_list.cardinals); + break; + } +} + +void +meta_prop_free_values (MetaPropValue *values, + int n_values) +{ + int i; + + i = 0; + while (i < n_values) + { + free_value (&values[i]); + ++i; + } + + /* Zero the whole thing to quickly detect breakage */ + memset (values, '\0', sizeof (MetaPropValue) * n_values); +} diff --git a/src/xprops.h b/src/xprops.h index 0bdf47964..a1c6adfd3 100644 --- a/src/xprops.h +++ b/src/xprops.h @@ -199,6 +199,9 @@ void meta_prop_get_values (MetaDisplay *display, MetaPropValue *values, int n_values); +void meta_prop_free_values (MetaPropValue *values, + int n_values); + #endif