lengthen to 15 seconds

2002-11-30  Havoc Pennington  <hp@pobox.com>

	* src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds

	* src/util.c (utf8_fputs): hmm, return a value

	* src/screen.c (meta_screen_apply_startup_properties): new
	function to apply initial workspace based on startup sequence.

	* src/window.c (meta_window_new): load _NET_STARTUP_ID
	(meta_window_get_startup_id): new function

	* src/window-props.c (meta_display_init_window_prop_hooks): add
	hooks for _NET_STARTUP_ID

	* src/display.c (event_callback): send property events to
	groups.

	* src/xprops.c (meta_prop_get_values): make a type of INVALID
	mean to ignore that property (don't fetch its value).

	* src/group.c (meta_group_property_notify): new function

	* src/screen.c (set_supported_hint): support _NET_STARTUP_ID

	* src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms
	we initialize

	* src/group-private.h: private header shared between
	group-props.c, group.c

	* src/group-props.h, src/group-props.c: new files to contain
	functions for retrieving group properties

	* src/window.c (meta_window_same_application): change this a bit
	to work with new definition of group

	* src/group.c (meta_window_get_group): always create a group for
	every window, using the window's own ID as group leader if
	required.

	* src/window.c (update_wm_hints): handle changes to group leader

	* src/group.c (meta_window_group_leader_changed): new function

	* src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH,
	not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen.

	* src/screen.c (startup_sequence_timeout): when timing out a
	startup sequence, send a remove message, don't just time it out
	locally.
This commit is contained in:
Havoc Pennington 2002-12-01 03:58:04 +00:00 committed by Havoc Pennington
parent eb40c5c2cf
commit 5e1439f89e
18 changed files with 684 additions and 78 deletions

View File

@ -1,3 +1,55 @@
2002-11-30 Havoc Pennington <hp@pobox.com>
* src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds
* src/util.c (utf8_fputs): hmm, return a value
* src/screen.c (meta_screen_apply_startup_properties): new
function to apply initial workspace based on startup sequence.
* src/window.c (meta_window_new): load _NET_STARTUP_ID
(meta_window_get_startup_id): new function
* src/window-props.c (meta_display_init_window_prop_hooks): add
hooks for _NET_STARTUP_ID
* src/display.c (event_callback): send property events to
groups.
* src/xprops.c (meta_prop_get_values): make a type of INVALID
mean to ignore that property (don't fetch its value).
* src/group.c (meta_group_property_notify): new function
* src/screen.c (set_supported_hint): support _NET_STARTUP_ID
* src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms
we initialize
* src/group-private.h: private header shared between
group-props.c, group.c
* src/group-props.h, src/group-props.c: new files to contain
functions for retrieving group properties
* src/window.c (meta_window_same_application): change this a bit
to work with new definition of group
* src/group.c (meta_window_get_group): always create a group for
every window, using the window's own ID as group leader if
required.
* src/window.c (update_wm_hints): handle changes to group leader
* src/group.c (meta_window_group_leader_changed): new function
* src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH,
not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen.
* src/screen.c (startup_sequence_timeout): when timing out a
startup sequence, send a remove message, don't just time it out
locally.
2002-11-26 Calum Benson <calum.benson@sun.com>
* src/themes/Crux :

View File

@ -96,7 +96,7 @@ PKG_CHECK_MODULES(METACITY_MESSAGE, gtk+-2.0 >= 2.0.0)
PKG_CHECK_MODULES(METACITY_WINDOW_DEMO, gtk+-2.0 >= 2.0.0)
PKG_CHECK_MODULES(METACITY_PROPS, gtk+-2.0 >= 2.0.0 gconf-2.0 >= 1.1.9 libglade-2.0)
STARTUP_NOTIFICATION_VERSION=0.2
STARTUP_NOTIFICATION_VERSION=0.4
if $PKG_CONFIG --atleast-version $STARTUP_NOTIFICATION_VERSION libstartup-notification-1.0; then
echo "Building with libstartup-notification"
PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 2.0.0 gconf-2.0 >= 1.1.9 libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION)

View File

@ -35,6 +35,9 @@ metacity_SOURCES= \
gradient.h \
group.c \
group.h \
group-private.h \
group-props.c \
group-props.h \
iconcache.c \
iconcache.h \
inlinepixbufs.h \

View File

@ -26,6 +26,7 @@
#include "screen.h"
#include "window.h"
#include "window-props.h"
#include "group-props.h"
#include "frame.h"
#include "errors.h"
#include "keybindings.h"
@ -225,7 +226,7 @@ meta_display_open (const char *name)
"_METACITY_SET_KEYBINDINGS_MESSAGE",
"_NET_WM_STATE_HIDDEN",
"_NET_WM_WINDOW_TYPE_UTILITY",
"_NET_WM_WINDOW_TYPE_SPLASHSCREEN",
"_NET_WM_WINDOW_TYPE_SPLASH",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_PING",
"_NET_WM_PID",
@ -250,7 +251,8 @@ meta_display_open (const char *name)
"_NET_WM_ACTION_CHANGE_DESKTOP",
"_NET_WM_ACTION_CLOSE",
"_NET_WM_STATE_ABOVE",
"_NET_WM_STATE_BELOW"
"_NET_WM_STATE_BELOW",
"_NET_STARTUP_ID"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@ -358,7 +360,7 @@ meta_display_open (const char *name)
display->atom_metacity_set_keybindings_message = atoms[48];
display->atom_net_wm_state_hidden = atoms[49];
display->atom_net_wm_window_type_utility = atoms[50];
display->atom_net_wm_window_type_splashscreen = atoms[51];
display->atom_net_wm_window_type_splash = atoms[51];
display->atom_net_wm_state_fullscreen = atoms[52];
display->atom_net_wm_ping = atoms[53];
display->atom_net_wm_pid = atoms[54];
@ -384,9 +386,12 @@ 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->atom_net_startup_id = atoms[77];
display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (display);
display->group_prop_hooks = NULL;
meta_display_init_group_prop_hooks (display);
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
@ -669,6 +674,7 @@ meta_display_close (MetaDisplay *display)
XFlush (display->xdisplay);
meta_display_free_window_prop_hooks (display);
meta_display_free_group_prop_hooks (display);
#ifndef USE_GDK_DISPLAY
meta_event_queue_free (display->events);
@ -1525,25 +1531,34 @@ event_callback (XEvent *event,
case CirculateRequest:
break;
case PropertyNotify:
if (window && !frame_was_receiver)
meta_window_property_notify (window, event);
else
{
MetaScreen *screen;
{
MetaGroup *group;
MetaScreen *screen;
if (window && !frame_was_receiver)
meta_window_property_notify (window, event);
group = meta_display_lookup_group (display,
event->xproperty.window);
if (group != NULL)
meta_group_property_notify (group, event);
screen = NULL;
if (window == NULL &&
group == NULL) /* window/group != NULL means it wasn't a root window */
screen = meta_display_screen_for_root (display,
event->xproperty.window);
if (screen)
{
if (event->xproperty.atom ==
display->atom_net_desktop_layout)
meta_screen_update_workspace_layout (screen);
else if (event->xproperty.atom ==
display->atom_net_desktop_names)
meta_screen_update_workspace_names (screen);
}
}
if (screen != NULL)
{
if (event->xproperty.atom ==
display->atom_net_desktop_layout)
meta_screen_update_workspace_layout (screen);
else if (event->xproperty.atom ==
display->atom_net_desktop_names)
meta_screen_update_workspace_names (screen);
}
}
break;
case SelectionClear:
/* do this here instead of at end of function

View File

@ -58,6 +58,7 @@ typedef struct _MetaWindow MetaWindow;
typedef struct _MetaWorkspace MetaWorkspace;
typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
typedef struct _MetaGroupPropHooks MetaGroupPropHooks;
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
@ -133,7 +134,7 @@ struct _MetaDisplay
Atom atom_metacity_set_keybindings_message;
Atom atom_net_wm_state_hidden;
Atom atom_net_wm_window_type_utility;
Atom atom_net_wm_window_type_splashscreen;
Atom atom_net_wm_window_type_splash;
Atom atom_net_wm_ping;
Atom atom_net_wm_pid;
Atom atom_wm_client_machine;
@ -159,6 +160,7 @@ struct _MetaDisplay
Atom atom_net_wm_action_close;
Atom atom_net_wm_state_above;
Atom atom_net_wm_state_below;
Atom atom_net_startup_id;
/* This is the actual window from focus events,
* not the one we last set
@ -267,6 +269,9 @@ struct _MetaDisplay
/* Managed by window-props.c */
MetaWindowPropHooks *prop_hooks;
/* Managed by group-props.c */
MetaGroupPropHooks *group_prop_hooks;
#ifdef HAVE_STARTUP_NOTIFICATION
/* This is at the end in case someone doesn't include config.h before this file

41
src/group-private.h Normal file
View File

@ -0,0 +1,41 @@
/* Metacity window group private header */
/*
* 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.
*/
#ifndef META_GROUP_PRIVATE_H
#define META_GROUP_PRIVATE_H
#include "group.h"
struct _MetaGroup
{
int refcount;
MetaDisplay *display;
GSList *windows;
Window group_leader;
char *startup_id;
char *wm_client_machine;
};
#endif

230
src/group-props.c Normal file
View File

@ -0,0 +1,230 @@
/* MetaGroup property handling */
/*
* 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 <config.h>
#include "group-props.h"
#include "group-private.h"
#include "xprops.h"
#include <X11/Xatom.h>
typedef void (* InitValueFunc) (MetaDisplay *display,
Atom property,
MetaPropValue *value);
typedef void (* ReloadValueFunc) (MetaGroup *group,
MetaPropValue *value);
struct _MetaGroupPropHooks
{
Atom property;
InitValueFunc init_func;
ReloadValueFunc reload_func;
};
static void init_prop_value (MetaDisplay *display,
Atom property,
MetaPropValue *value);
static void reload_prop_value (MetaGroup *group,
MetaPropValue *value);
static MetaGroupPropHooks* find_hooks (MetaDisplay *display,
Atom property);
void
meta_group_reload_property (MetaGroup *group,
Atom property)
{
meta_group_reload_properties (group, &property, 1);
}
void
meta_group_reload_properties (MetaGroup *group,
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 (group->display, properties[i], &values[i]);
++i;
}
meta_prop_get_values (group->display, group->group_leader,
values, n_properties);
i = 0;
while (i < n_properties)
{
reload_prop_value (group, &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)
{
MetaGroupPropHooks *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 (MetaGroup *group,
MetaPropValue *value)
{
MetaGroupPropHooks *hooks;
hooks = find_hooks (group->display, value->atom);
if (hooks && hooks->reload_func != NULL)
(* hooks->reload_func) (group, 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 (MetaGroup *group,
MetaPropValue *value)
{
g_free (group->wm_client_machine);
group->wm_client_machine = NULL;
if (value->type != META_PROP_VALUE_INVALID)
group->wm_client_machine = g_strdup (value->v.str);
meta_verbose ("Group has client machine \"%s\"\n",
group->wm_client_machine ? group->wm_client_machine : "unset");
}
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 (MetaGroup *group,
MetaPropValue *value)
{
g_free (group->startup_id);
group->startup_id = NULL;
if (value->type != META_PROP_VALUE_INVALID)
group->startup_id = g_strdup (value->v.str);
meta_verbose ("Group has startup id \"%s\"\n",
group->startup_id ? group->startup_id : "unset");
}
#define N_HOOKS 3
void
meta_display_init_group_prop_hooks (MetaDisplay *display)
{
int i;
MetaGroupPropHooks *hooks;
g_assert (display->group_prop_hooks == NULL);
display->group_prop_hooks = g_new0 (MetaGroupPropHooks, N_HOOKS);
hooks = display->group_prop_hooks;
i = 0;
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 = 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;
if (i != N_HOOKS)
g_error ("Initialized %d group hooks should have been %d\n", i, N_HOOKS);
}
void
meta_display_free_group_prop_hooks (MetaDisplay *display)
{
g_assert (display->group_prop_hooks != NULL);
g_free (display->group_prop_hooks);
display->group_prop_hooks = NULL;
}
static MetaGroupPropHooks*
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->group_prop_hooks[i].property == property)
return &display->group_prop_hooks[i];
++i;
}
return NULL;
}

35
src/group-props.h Normal file
View File

@ -0,0 +1,35 @@
/* MetaGroup property handling */
/*
* 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.
*/
#ifndef META_GROUP_PROPS_H
#define META_GROUP_PROPS_H
#include "group.h"
void meta_group_reload_property (MetaGroup *group,
Atom property);
void meta_group_reload_properties (MetaGroup *group,
const Atom *properties,
int n_properties);
void meta_display_init_group_prop_hooks (MetaDisplay *display);
void meta_display_free_group_prop_hooks (MetaDisplay *display);
#endif /* META_GROUP_PROPS_H */

View File

@ -21,23 +21,21 @@
#include <config.h>
#include "util.h"
#include "group.h"
#include "group-private.h"
#include "group-props.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;
#define N_INITIAL_PROPS 3
Atom initial_props[N_INITIAL_PROPS];
int i;
g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
group = g_new0 (MetaGroup, 1);
group->display = display;
@ -54,6 +52,19 @@ meta_group_new (MetaDisplay *display,
g_hash_table_insert (display->groups_by_leader,
&group->group_leader,
group);
/* Fill these in the order we want them to be gotten */
i = 0;
initial_props[i++] = display->atom_wm_client_machine;
initial_props[i++] = display->atom_net_wm_pid;
initial_props[i++] = display->atom_net_startup_id;
g_assert (N_INITIAL_PROPS == i);
meta_group_reload_properties (group, initial_props, N_INITIAL_PROPS);
meta_topic (META_DEBUG_GROUPS,
"Created new group with leader 0x%lx\n",
group->group_leader);
return group;
}
@ -66,6 +77,10 @@ meta_group_unref (MetaGroup *group)
group->refcount -= 1;
if (group->refcount == 0)
{
meta_topic (META_DEBUG_GROUPS,
"Destroying group with leader 0x%lx\n",
group->group_leader);
g_assert (group->display->groups_by_leader != NULL);
g_hash_table_remove (group->display->groups_by_leader,
@ -78,6 +93,9 @@ meta_group_unref (MetaGroup *group)
group->display->groups_by_leader = NULL;
}
g_free (group->wm_client_machine);
g_free (group->startup_id);
g_free (group);
}
}
@ -88,16 +106,23 @@ meta_window_get_group (MetaWindow *window)
if (window->unmanaging)
return NULL;
if (window->cached_group == NULL &&
window->xgroup_leader != None) /* some windows have no group */
if (window->cached_group == NULL)
{
MetaGroup *group;
/* use window->xwindow if no window->xgroup_leader */
group = NULL;
if (window->display->groups_by_leader)
group = g_hash_table_lookup (window->display->groups_by_leader,
&window->xgroup_leader);
{
if (window->xgroup_leader != None)
group = g_hash_table_lookup (window->display->groups_by_leader,
&window->xgroup_leader);
else
group = g_hash_table_lookup (window->display->groups_by_leader,
&window->xwindow);
}
if (group != NULL)
{
@ -106,24 +131,36 @@ meta_window_get_group (MetaWindow *window)
}
else
{
group = meta_group_new (window->display,
window->xgroup_leader);
if (window->xgroup_leader != None)
group = meta_group_new (window->display,
window->xgroup_leader);
else
group = meta_group_new (window->display,
window->xwindow);
window->cached_group = group;
}
window->cached_group->windows = g_slist_prepend (window->cached_group->windows,
window);
meta_topic (META_DEBUG_GROUPS,
"Adding %s to group with leader 0x%lx\n",
window->desc, group->group_leader);
}
return window->cached_group;
}
void
meta_window_shutdown_group (MetaWindow *window)
static void
remove_window_from_group (MetaWindow *window)
{
if (window->cached_group != NULL)
{
meta_topic (META_DEBUG_GROUPS,
"Removing %s from group with leader 0x%lx\n",
window->desc, window->cached_group->group_leader);
window->cached_group->windows =
g_slist_remove (window->cached_group->windows,
window);
@ -132,6 +169,19 @@ meta_window_shutdown_group (MetaWindow *window)
}
}
void
meta_window_group_leader_changed (MetaWindow *window)
{
remove_window_from_group (window);
meta_window_get_group (window);
}
void
meta_window_shutdown_group (MetaWindow *window)
{
remove_window_from_group (window);
}
MetaGroup*
meta_display_lookup_group (MetaDisplay *display,
Window group_leader)
@ -190,3 +240,19 @@ meta_group_update_layers (MetaGroup *group)
g_slist_free (frozen_stacks);
}
const char*
meta_group_get_startup_id (MetaGroup *group)
{
return group->startup_id;
}
gboolean
meta_group_property_notify (MetaGroup *group,
XEvent *event)
{
meta_group_reload_property (group,
event->xproperty.atom);
return TRUE;
}

View File

@ -28,6 +28,8 @@
MetaGroup* meta_window_get_group (MetaWindow *window);
void meta_window_shutdown_group (MetaWindow *window);
void meta_window_group_leader_changed (MetaWindow *window);
/* note, can return NULL */
MetaGroup* meta_display_lookup_group (MetaDisplay *display,
Window group_leader);
@ -36,6 +38,11 @@ GSList* meta_group_list_windows (MetaGroup *group);
void meta_group_update_layers (MetaGroup *group);
const char* meta_group_get_startup_id (MetaGroup *group);
gboolean meta_group_property_notify (MetaGroup *group,
XEvent *event);
#endif

View File

@ -90,7 +90,7 @@ set_wm_check_hint (MetaScreen *screen)
static int
set_supported_hint (MetaScreen *screen)
{
#define N_SUPPORTED 44
#define N_SUPPORTED 45
#define N_WIN_SUPPORTED 1
Atom atoms[N_SUPPORTED];
@ -119,7 +119,7 @@ set_supported_hint (MetaScreen *screen)
atoms[22] = screen->display->atom_net_wm_moveresize;
atoms[23] = screen->display->atom_net_wm_state_hidden;
atoms[24] = screen->display->atom_net_wm_window_type_utility;
atoms[25] = screen->display->atom_net_wm_window_type_splashscreen;
atoms[25] = screen->display->atom_net_wm_window_type_splash;
atoms[26] = screen->display->atom_net_wm_state_fullscreen;
atoms[27] = screen->display->atom_net_wm_ping;
atoms[28] = screen->display->atom_net_active_window;
@ -138,6 +138,7 @@ set_supported_hint (MetaScreen *screen)
atoms[41] = screen->display->atom_net_wm_action_close;
atoms[42] = screen->display->atom_net_wm_state_above;
atoms[43] = screen->display->atom_net_wm_state_below;
atoms[44] = screen->display->atom_net_startup_id;
XChangeProperty (screen->display->xdisplay, screen->xroot,
screen->display->atom_net_supported,
@ -1800,7 +1801,12 @@ typedef struct
GTimeVal now;
} CollectTimedOutData;
#define STARTUP_TIMEOUT 5000
/* This should be fairly long, as it should never be required unless
* apps or .desktop files are buggy, and it's confusing if
* OpenOffice or whatever seems to stop launching - people
* might decide they need to launch it again.
*/
#define STARTUP_TIMEOUT 15000
static void
collect_timed_out_foreach (void *element,
@ -1848,7 +1854,7 @@ startup_sequence_timeout (void *data)
"Timed out sequence %s\n",
sn_startup_sequence_get_id (sequence));
remove_sequence (screen, sequence);
sn_startup_sequence_complete (sequence);
tmp = tmp->next;
}
@ -1913,3 +1919,68 @@ meta_screen_sn_event (SnMonitorEvent *event,
}
}
#endif
void
meta_screen_apply_startup_properties (MetaScreen *screen,
MetaWindow *window)
{
#ifdef HAVE_STARTUP_NOTIFICATION
const char *startup_id;
GSList *tmp;
SnStartupSequence *sequence;
startup_id = meta_window_get_startup_id (window);
if (startup_id == NULL)
return;
sequence = NULL;
tmp = screen->startup_sequences;
while (tmp != NULL)
{
const char *id;
id = sn_startup_sequence_get_id (tmp->data);
if (strcmp (id, startup_id) == 0)
{
sequence = tmp->data;
break;
}
tmp = tmp->next;
}
if (sequence != NULL)
{
int space;
meta_topic (META_DEBUG_STARTUP,
"Found startup sequence for window %s ID \"%s\"\n",
window->desc, startup_id);
if (!window->initial_workspace_set)
{
space = sn_startup_sequence_get_workspace (sequence);
if (space >= 0)
{
meta_topic (META_DEBUG_STARTUP,
"Setting initial window workspace to %d based on startup info\n",
space);
window->initial_workspace_set = TRUE;
window->initial_workspace = space;
}
}
return;
}
else
{
meta_topic (META_DEBUG_STARTUP,
"Did not find startup sequence for window %s ID \"%s\"\n",
window->desc, startup_id);
}
#endif /* HAVE_STARTUP_NOTIFICATION */
}

View File

@ -152,5 +152,8 @@ void meta_screen_resize (MetaScreen *screen,
void meta_screen_show_desktop (MetaScreen *screen);
void meta_screen_unshow_desktop (MetaScreen *screen);
void meta_screen_apply_startup_properties (MetaScreen *screen,
MetaWindow *window);
#endif

View File

@ -158,15 +158,18 @@ utf8_fputs (const char *str,
FILE *f)
{
char *l;
int retval;
l = g_locale_from_utf8 (str, -1, NULL, NULL, NULL);
if (l == NULL)
fputs (str, f); /* just print it anyway, better than nothing */
retval = fputs (str, f); /* just print it anyway, better than nothing */
else
fputs (l, f);
retval = fputs (l, f);
g_free (l);
return retval;
}
void
@ -262,6 +265,8 @@ topic_name (MetaDebugTopic topic)
return "STARTUP";
case META_DEBUG_PREFS:
return "PREFS";
case META_DEBUG_GROUPS:
return "GROUPS";
}
return "Window manager";

View File

@ -62,7 +62,8 @@ typedef enum
META_DEBUG_SYNC = 1 << 13,
META_DEBUG_ERRORS = 1 << 14,
META_DEBUG_STARTUP = 1 << 15,
META_DEBUG_PREFS = 1 << 16
META_DEBUG_PREFS = 1 << 16,
META_DEBUG_GROUPS = 1 << 17
} MetaDebugTopic;

View File

@ -97,10 +97,12 @@ init_prop_value (MetaDisplay *display,
MetaPropValue *value)
{
MetaWindowPropHooks *hooks;
value->type = META_PROP_VALUE_INVALID;
value->atom = None;
hooks = find_hooks (display, property);
g_assert (hooks != NULL);
if (hooks->init_func != NULL)
if (hooks && hooks->init_func != NULL)
(* hooks->init_func) (display, property, value);
}
@ -111,8 +113,7 @@ reload_prop_value (MetaWindow *window,
MetaWindowPropHooks *hooks;
hooks = find_hooks (window->display, value->atom);
g_assert (hooks != NULL);
if (hooks->reload_func != NULL)
if (hooks && hooks->reload_func != NULL)
(* hooks->reload_func) (window, value);
}
@ -385,7 +386,33 @@ reload_win_workspace (MetaWindow *window,
}
}
#define N_HOOKS 22
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);
}
#define N_HOOKS 23
void
meta_display_init_window_prop_hooks (MetaDisplay *display)
@ -509,6 +536,11 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
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;
if (i != N_HOOKS)
g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS);

View File

@ -157,7 +157,7 @@ meta_window_new (MetaDisplay *display,
GSList *tmp;
MetaWorkspace *space;
gulong existing_wm_state;
#define N_INITIAL_PROPS 8
#define N_INITIAL_PROPS 9
Atom initial_props[N_INITIAL_PROPS];
int i;
@ -401,7 +401,8 @@ meta_window_new (MetaDisplay *display,
window->role = NULL;
window->sm_client_id = NULL;
window->wm_client_machine = NULL;
window->startup_id = NULL;
window->net_wm_pid = -1;
window->xtransient_for = None;
@ -439,6 +440,7 @@ meta_window_new (MetaDisplay *display,
initial_props[i++] = XA_WM_ICON_NAME;
initial_props[i++] = display->atom_net_wm_desktop;
initial_props[i++] = display->atom_win_workspace;
initial_props[i++] = display->atom_net_startup_id;
g_assert (N_INITIAL_PROPS == i);
meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS);
@ -477,6 +479,11 @@ meta_window_new (MetaDisplay *display,
*/
window->placed = TRUE;
}
/* Apply any window attributes such as initial workspace
* based on startup notification
*/
meta_screen_apply_startup_properties (window->screen, window);
/* FIXME we have a tendency to set this then immediately
* change it again.
@ -972,6 +979,7 @@ meta_window_free (MetaWindow *window)
g_free (window->sm_client_id);
g_free (window->wm_client_machine);
g_free (window->startup_id);
g_free (window->role);
g_free (window->res_class);
g_free (window->res_name);
@ -2881,6 +2889,22 @@ meta_window_get_outer_rect (MetaWindow *window,
*rect = window->rect;
}
const char*
meta_window_get_startup_id (MetaWindow *window)
{
if (window->startup_id == NULL)
{
MetaGroup *group;
group = meta_window_get_group (window);
if (group != NULL)
return meta_group_get_startup_id (group);
}
return window->startup_id;
}
void
meta_window_focus (MetaWindow *window,
Time timestamp)
@ -3873,6 +3897,11 @@ static gboolean
process_property_notify (MetaWindow *window,
XPropertyEvent *event)
{
/* FIXME once we move entirely to the window-props.h framework, we
* can just call reload on the property in the event and get rid of
* this if-else chain.
*/
if (event->atom == XA_WM_NAME)
{
meta_verbose ("Property notify on %s for WM_NAME\n", window->desc);
@ -4018,6 +4047,13 @@ process_property_notify (MetaWindow *window,
meta_verbose ("Property notify on %s for _WIN_HINTS\n", window->desc);
update_struts (window);
}
else if (event->atom == window->display->atom_net_startup_id)
{
meta_verbose ("Property notify on %s for _NET_STARTUP_ID\n", window->desc);
meta_window_reload_property (window,
window->display->atom_net_startup_id);
}
return TRUE;
}
@ -4400,16 +4436,10 @@ update_wm_hints (MetaWindow *window)
if (window->xgroup_leader != old_group_leader)
{
if (old_group_leader != None)
{
meta_warning ("Window %s changed its group leader, not handled right now.\n",
window->desc);
/* ignore the change */
window->xgroup_leader = old_group_leader;
}
/* ensure this window is listed in the group for this group leader */
meta_window_get_group (window);
meta_verbose ("Window %s changed its group leader to 0x%lx\n",
window->desc, window->xgroup_leader);
meta_window_group_leader_changed (window);
}
}
@ -4865,7 +4895,7 @@ update_net_wm_type (MetaWindow *window)
atoms[i] == window->display->atom_net_wm_window_type_dialog ||
atoms[i] == window->display->atom_net_wm_window_type_normal ||
atoms[i] == window->display->atom_net_wm_window_type_utility ||
atoms[i] == window->display->atom_net_wm_window_type_splashscreen)
atoms[i] == window->display->atom_net_wm_window_type_splash)
{
window->type_atom = atoms[i];
break;
@ -5152,7 +5182,7 @@ recalc_window_type (MetaWindow *window)
window->type = META_WINDOW_NORMAL;
else if (window->type_atom == window->display->atom_net_wm_window_type_utility)
window->type = META_WINDOW_UTILITY;
else if (window->type_atom == window->display->atom_net_wm_window_type_splashscreen)
else if (window->type_atom == window->display->atom_net_wm_window_type_splash)
window->type = META_WINDOW_SPLASHSCREEN;
else
meta_bug ("Set a type atom for %s that wasn't handled in recalc_window_type\n",
@ -6321,9 +6351,9 @@ gboolean
meta_window_same_application (MetaWindow *window,
MetaWindow *other_window)
{
return (window->xgroup_leader != None &&
other_window->xgroup_leader != None &&
window->xgroup_leader == other_window->xgroup_leader);
return
meta_window_get_group (window) ==
meta_window_get_group (other_window);
}
void

View File

@ -79,6 +79,7 @@ struct _MetaWindow
char *role;
char *sm_client_id;
char *wm_client_machine;
char *startup_id;
int net_wm_pid;
@ -437,4 +438,6 @@ void meta_window_update_layer (MetaWindow *window);
gboolean meta_window_get_icon_geometry (MetaWindow *window,
MetaRectangle *rect);
const char* meta_window_get_startup_id (MetaWindow *window);
#endif

View File

@ -866,7 +866,9 @@ meta_prop_get_values (MetaDisplay *display,
tasks = g_new0 (AgGetPropertyTask*, n_values);
/* Start up tasks */
/* Start up tasks. The "values" array can have values
* with atom == None, which means to ignore that element.
*/
i = 0;
while (i < n_values)
{
@ -875,7 +877,11 @@ meta_prop_get_values (MetaDisplay *display,
switch (values[i].type)
{
case META_PROP_VALUE_INVALID:
meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_GNUC_FUNCTION);
/* This means we don't really want a value, e.g. got
* property notify on an atom we don't care about.
*/
if (values[i].atom != None)
meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_GNUC_FUNCTION);
break;
case META_PROP_VALUE_UTF8_LIST:
case META_PROP_VALUE_UTF8:
@ -911,10 +917,11 @@ meta_prop_get_values (MetaDisplay *display,
break;
}
}
tasks[i] = get_task (display, xwindow,
values[i].atom, values[i].required_type);
if (values[i].atom != None)
tasks[i] = get_task (display, xwindow,
values[i].atom, values[i].required_type);
++i;
}
@ -932,8 +939,8 @@ meta_prop_get_values (MetaDisplay *display,
if (tasks[i] == NULL)
{
/* task creation failed for this property
* (doesn't actually happen I guess)
/* Probably values[i].type was None, or ag_task_create()
* returned NULL.
*/
values[i].type = META_PROP_VALUE_INVALID;
goto next;