...
This commit is contained in:
parent
67d9ca1d9f
commit
043b048c55
@ -9,3 +9,4 @@
|
|||||||
#undef GETTEXT_PACKAGE
|
#undef GETTEXT_PACKAGE
|
||||||
#undef HAVE_SHAPE_EXT
|
#undef HAVE_SHAPE_EXT
|
||||||
#undef HAVE_XFT
|
#undef HAVE_XFT
|
||||||
|
#undef HAVE_SM
|
||||||
|
19
configure.in
19
configure.in
@ -43,6 +43,25 @@ AM_GNU_GETTEXT
|
|||||||
## here we get the flags we'll actually use
|
## here we get the flags we'll actually use
|
||||||
PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 1.3.6)
|
PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 1.3.6)
|
||||||
|
|
||||||
|
CFLAGS="$METACITY_CFLAGS $CFLAGS"
|
||||||
|
|
||||||
|
found_sm=false
|
||||||
|
case "$METACITY_LIBS" in
|
||||||
|
*-lSM*)
|
||||||
|
found_sm=true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_CHECK_LIB(SM, SmcSaveYourselfDone,
|
||||||
|
AC_CHECK_HEADERS(X11/SM/SMlib.h,
|
||||||
|
METACITY_LIBS="-lSM -lICE $METACITY_LIBS" found_sm=true),
|
||||||
|
, $METACITY_LIBS)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test "$found_sm" = "true"; then
|
||||||
|
AC_DEFINE(HAVE_SM)
|
||||||
|
fi
|
||||||
|
|
||||||
# Check for shaped window extension
|
# Check for shaped window extension
|
||||||
AC_CHECK_LIB(Xext, XShapeCombineMask, AC_DEFINE(HAVE_SHAPE_EXT),,$METACITY_LIBS)
|
AC_CHECK_LIB(Xext, XShapeCombineMask, AC_DEFINE(HAVE_SHAPE_EXT),,$METACITY_LIBS)
|
||||||
|
|
||||||
|
112
src/main.c
112
src/main.c
@ -24,6 +24,7 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
#include "session.h"
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
@ -37,12 +38,23 @@
|
|||||||
static MetaExitCode meta_exit_code = META_EXIT_SUCCESS;
|
static MetaExitCode meta_exit_code = META_EXIT_SUCCESS;
|
||||||
static GMainLoop *meta_main_loop = NULL;
|
static GMainLoop *meta_main_loop = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage (void)
|
||||||
|
{
|
||||||
|
g_print ("metacity [--disable-sm] [--sm-client-id=ID] [--display=DISPLAY]\n");
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
sigset_t empty_mask;
|
sigset_t empty_mask;
|
||||||
char *display_name;
|
char *display_name;
|
||||||
|
int i;
|
||||||
|
const char *client_id;
|
||||||
|
gboolean disable_sm;
|
||||||
|
const char *prev_arg;
|
||||||
|
|
||||||
sigemptyset (&empty_mask);
|
sigemptyset (&empty_mask);
|
||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
@ -52,27 +64,105 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
g_set_prgname (PACKAGE);
|
g_set_prgname (PACKAGE);
|
||||||
|
|
||||||
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
|
||||||
|
|
||||||
meta_set_verbose (TRUE);
|
meta_set_verbose (TRUE);
|
||||||
meta_set_debugging (TRUE);
|
meta_set_debugging (TRUE);
|
||||||
meta_set_syncing (g_getenv ("METACITY_SYNC") != NULL);
|
meta_set_syncing (g_getenv ("METACITY_SYNC") != NULL);
|
||||||
|
|
||||||
if (g_getenv ("METACITY_DISPLAY"))
|
/* Parse options lamely */
|
||||||
|
|
||||||
|
display_name = NULL;
|
||||||
|
client_id = NULL;
|
||||||
|
disable_sm = FALSE;
|
||||||
|
prev_arg = NULL;
|
||||||
|
i = 1;
|
||||||
|
while (i < argc)
|
||||||
|
{
|
||||||
|
const char *arg = argv[i];
|
||||||
|
|
||||||
|
if (strcmp (arg, "--help") == 0 ||
|
||||||
|
strcmp (arg, "-h") == 0 ||
|
||||||
|
strcmp (arg, "-?") == 0)
|
||||||
|
usage ();
|
||||||
|
else if (strcmp (arg, "--sm-disable") == 0)
|
||||||
|
disable_sm = TRUE;
|
||||||
|
else if (strstr (arg, "--display=") == arg)
|
||||||
|
{
|
||||||
|
const char *disp;
|
||||||
|
|
||||||
|
if (display_name != NULL)
|
||||||
|
meta_fatal ("Can't specify display twice\n");
|
||||||
|
|
||||||
|
disp = strchr (arg, '=');
|
||||||
|
++disp;
|
||||||
|
|
||||||
|
display_name =
|
||||||
|
g_strconcat ("DISPLAY=", disp, NULL);
|
||||||
|
}
|
||||||
|
else if (prev_arg &&
|
||||||
|
strcmp (prev_arg, "--display") == 0)
|
||||||
|
{
|
||||||
|
if (display_name != NULL)
|
||||||
|
meta_fatal ("Can't specify display twice\n");
|
||||||
|
|
||||||
|
display_name = g_strconcat ("DISPLAY=", arg, NULL);
|
||||||
|
}
|
||||||
|
else if (strcmp (arg, "--display") == 0)
|
||||||
|
; /* wait for next arg */
|
||||||
|
else if (strstr (arg, "--sm-client-id=") == arg)
|
||||||
|
{
|
||||||
|
const char *id;
|
||||||
|
|
||||||
|
if (client_id)
|
||||||
|
meta_fatal ("Can't specify client ID twice\n");
|
||||||
|
|
||||||
|
id = strchr (arg, '=');
|
||||||
|
++id;
|
||||||
|
|
||||||
|
client_id = g_strdup (id);
|
||||||
|
}
|
||||||
|
else if (prev_arg &&
|
||||||
|
strcmp (prev_arg, "--sm-client-id") == 0)
|
||||||
|
{
|
||||||
|
if (client_id)
|
||||||
|
meta_fatal ("Can't specify client ID twice\n");
|
||||||
|
|
||||||
|
client_id = g_strdup (arg);
|
||||||
|
}
|
||||||
|
else if (strcmp (arg, "--sm-client-id") == 0)
|
||||||
|
; /* wait for next arg */
|
||||||
|
else
|
||||||
|
usage ();
|
||||||
|
|
||||||
|
prev_arg = arg;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
|
||||||
|
if (display_name == NULL &&
|
||||||
|
g_getenv ("METACITY_DISPLAY"))
|
||||||
{
|
{
|
||||||
meta_verbose ("Using METACITY_DISPLAY %s\n",
|
meta_verbose ("Using METACITY_DISPLAY %s\n",
|
||||||
g_getenv ("METACITY_DISPLAY"));
|
g_getenv ("METACITY_DISPLAY"));
|
||||||
display_name =
|
display_name =
|
||||||
g_strconcat ("DISPLAY=", g_getenv ("METACITY_DISPLAY"), NULL);
|
g_strconcat ("DISPLAY=", g_getenv ("METACITY_DISPLAY"), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (display_name)
|
||||||
|
{
|
||||||
putenv (display_name);
|
putenv (display_name);
|
||||||
/* DO NOT FREE display_name, putenv() sucks */
|
/* DO NOT FREE display_name, putenv() sucks */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* gtk_init() below overrides this, so it can be removed */
|
/* gtk_init() below overrides this, so it can be removed */
|
||||||
meta_errors_init ();
|
meta_errors_init ();
|
||||||
|
|
||||||
g_type_init (0); /* grumble */
|
g_type_init (0); /* grumble */
|
||||||
|
|
||||||
|
if (!disable_sm)
|
||||||
|
meta_session_init (client_id); /* client_id == NULL is fine */
|
||||||
|
|
||||||
meta_ui_init (&argc, &argv);
|
meta_ui_init (&argc, &argv);
|
||||||
|
|
||||||
if (!meta_display_open (NULL))
|
if (!meta_display_open (NULL))
|
||||||
@ -80,6 +170,19 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
g_main_run (meta_main_loop);
|
g_main_run (meta_main_loop);
|
||||||
|
|
||||||
|
{
|
||||||
|
GSList *displays;
|
||||||
|
GSList *tmp;
|
||||||
|
|
||||||
|
displays = meta_displays_list ();
|
||||||
|
tmp = displays;
|
||||||
|
while (tmp != NULL)
|
||||||
|
{
|
||||||
|
meta_display_close (tmp->data);
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return meta_exit_code;
|
return meta_exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +197,7 @@ meta_quit (MetaExitCode code)
|
|||||||
{
|
{
|
||||||
meta_exit_code = code;
|
meta_exit_code = code;
|
||||||
|
|
||||||
|
if (g_main_is_running (meta_main_loop))
|
||||||
g_main_quit (meta_main_loop);
|
g_main_quit (meta_main_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
456
src/session.c
456
src/session.c
@ -1,7 +1,8 @@
|
|||||||
/* Metacity Session Management */
|
/* Metacity Session Management */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2001 Havoc Pennington
|
* Copyright (C) 2001 Havoc Pennington (some code in here from
|
||||||
|
* libgnomeui, (C) Tom Tromey, Carsten Schaar)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -16,12 +17,461 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA. */
|
||||||
*/
|
|
||||||
|
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_SM
|
||||||
|
void
|
||||||
|
meta_session_init (const char *previous_id)
|
||||||
|
{
|
||||||
|
meta_verbose ("Compiled without session management support\n");
|
||||||
|
}
|
||||||
|
#else /* HAVE_SM */
|
||||||
|
|
||||||
|
#include <X11/ICE/ICElib.h>
|
||||||
|
#include <X11/SM/SMlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "main.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static void ice_io_error_handler (IceConn connection);
|
||||||
|
|
||||||
|
static void new_ice_connection (IceConn connection, IcePointer client_data,
|
||||||
|
Bool opening, IcePointer *watch_data);
|
||||||
|
|
||||||
|
/* This is called when data is available on an ICE connection. */
|
||||||
|
static gboolean
|
||||||
|
process_ice_messages (GIOChannel *channel,
|
||||||
|
GIOCondition condition,
|
||||||
|
gpointer client_data)
|
||||||
|
{
|
||||||
|
IceConn connection = (IceConn) client_data;
|
||||||
|
IceProcessMessagesStatus status;
|
||||||
|
|
||||||
|
status = IceProcessMessages (connection, NULL, NULL);
|
||||||
|
|
||||||
|
if (status == IceProcessMessagesIOError)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
IcePointer context = IceGetConnectionContext (connection);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* We were disconnected */
|
||||||
|
IceSetShutdownNegotiation (connection, False);
|
||||||
|
IceCloseConnection (connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is called when a new ICE connection is made. It arranges for
|
||||||
|
the ICE connection to be handled via the event loop. */
|
||||||
|
static void
|
||||||
|
new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
|
||||||
|
IcePointer *watch_data)
|
||||||
|
{
|
||||||
|
guint input_id;
|
||||||
|
|
||||||
|
if (opening)
|
||||||
|
{
|
||||||
|
/* Make sure we don't pass on these file descriptors to any
|
||||||
|
* exec'ed children
|
||||||
|
*/
|
||||||
|
GIOChannel *channel;
|
||||||
|
|
||||||
|
fcntl (IceConnectionNumber(connection),F_SETFD,
|
||||||
|
fcntl(IceConnectionNumber(connection),F_GETFD,0) | FD_CLOEXEC);
|
||||||
|
|
||||||
|
channel = g_io_channel_unix_new (IceConnectionNumber (connection));
|
||||||
|
|
||||||
|
input_id = g_io_add_watch (channel,
|
||||||
|
G_IO_IN | G_IO_ERR,
|
||||||
|
process_ice_messages,
|
||||||
|
connection);
|
||||||
|
|
||||||
|
g_io_channel_unref (channel);
|
||||||
|
|
||||||
|
*watch_data = (IcePointer) GUINT_TO_POINTER (input_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
input_id = GPOINTER_TO_UINT ((gpointer) *watch_data);
|
||||||
|
|
||||||
|
g_source_remove (input_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IceIOErrorHandler gnome_ice_installed_handler;
|
||||||
|
|
||||||
|
/* We call any handler installed before (or after) gnome_ice_init but
|
||||||
|
avoid calling the default libICE handler which does an exit() */
|
||||||
|
static void
|
||||||
|
ice_io_error_handler (IceConn connection)
|
||||||
|
{
|
||||||
|
if (gnome_ice_installed_handler)
|
||||||
|
(*gnome_ice_installed_handler) (connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ice_init (void)
|
||||||
|
{
|
||||||
|
static gboolean ice_initted = FALSE;
|
||||||
|
|
||||||
|
if (! ice_initted)
|
||||||
|
{
|
||||||
|
IceIOErrorHandler default_handler;
|
||||||
|
|
||||||
|
gnome_ice_installed_handler = IceSetIOErrorHandler (NULL);
|
||||||
|
default_handler = IceSetIOErrorHandler (ice_io_error_handler);
|
||||||
|
|
||||||
|
if (gnome_ice_installed_handler == default_handler)
|
||||||
|
gnome_ice_installed_handler = NULL;
|
||||||
|
|
||||||
|
IceAddConnectionWatch (new_ice_connection, NULL);
|
||||||
|
|
||||||
|
ice_initted = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STATE_DISCONNECTED,
|
||||||
|
STATE_IDLE,
|
||||||
|
STATE_SAVING_PHASE_1,
|
||||||
|
STATE_WAITING_FOR_PHASE_2,
|
||||||
|
STATE_SAVING_PHASE_2,
|
||||||
|
STATE_FROZEN,
|
||||||
|
STATE_REGISTERING
|
||||||
|
} ClientState;
|
||||||
|
|
||||||
|
static void save_phase_2_callback (SmcConn smc_conn,
|
||||||
|
SmPointer client_data);
|
||||||
|
static void interact_callback (SmcConn smc_conn,
|
||||||
|
SmPointer client_data);
|
||||||
|
static void shutdown_cancelled_callback (SmcConn smc_conn,
|
||||||
|
SmPointer client_data);
|
||||||
|
static void save_complete_callback (SmcConn smc_conn,
|
||||||
|
SmPointer client_data);
|
||||||
|
static void die_callback (SmcConn smc_conn,
|
||||||
|
SmPointer client_data);
|
||||||
|
static void save_yourself_callback (SmcConn smc_conn,
|
||||||
|
SmPointer client_data,
|
||||||
|
int save_style,
|
||||||
|
Bool shutdown,
|
||||||
|
int interact_style,
|
||||||
|
Bool fast);
|
||||||
|
static void set_clone_restart_commands (void);
|
||||||
|
|
||||||
|
static gchar *client_id = NULL;
|
||||||
|
static gpointer session_connection = NULL;
|
||||||
|
static ClientState current_state = STATE_DISCONNECTED;
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_session_init (const char *previous_id)
|
||||||
|
{
|
||||||
|
/* Some code here from twm */
|
||||||
|
char buf[256];
|
||||||
|
unsigned long mask;
|
||||||
|
SmcCallbacks callbacks;
|
||||||
|
|
||||||
|
meta_verbose ("Initializing session with session ID '%s'\n",
|
||||||
|
previous_id ? previous_id : "(none)");
|
||||||
|
|
||||||
|
ice_init ();
|
||||||
|
|
||||||
|
mask = SmcSaveYourselfProcMask | SmcDieProcMask |
|
||||||
|
SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
|
||||||
|
|
||||||
|
callbacks.save_yourself.callback = save_yourself_callback;
|
||||||
|
callbacks.save_yourself.client_data = NULL;
|
||||||
|
|
||||||
|
callbacks.die.callback = die_callback;
|
||||||
|
callbacks.die.client_data = NULL;
|
||||||
|
|
||||||
|
callbacks.save_complete.callback = save_complete_callback;
|
||||||
|
callbacks.save_complete.client_data = NULL;
|
||||||
|
|
||||||
|
callbacks.shutdown_cancelled.callback = shutdown_cancelled_callback;
|
||||||
|
callbacks.shutdown_cancelled.client_data = NULL;
|
||||||
|
|
||||||
|
session_connection =
|
||||||
|
SmcOpenConnection (NULL, /* use SESSION_MANAGER env */
|
||||||
|
NULL, /* means use existing ICE connection */
|
||||||
|
SmProtoMajor,
|
||||||
|
SmProtoMinor,
|
||||||
|
mask,
|
||||||
|
&callbacks,
|
||||||
|
previous_id,
|
||||||
|
&client_id,
|
||||||
|
255, buf);
|
||||||
|
|
||||||
|
if (session_connection == NULL)
|
||||||
|
{
|
||||||
|
meta_warning ("Failed to open connection to session manager: %s\n", buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
meta_verbose ("Obtained session ID '%s'\n", client_id);
|
||||||
|
|
||||||
|
if (previous_id && strcmp (previous_id, client_id) == 0)
|
||||||
|
current_state = STATE_IDLE;
|
||||||
|
else
|
||||||
|
current_state = STATE_REGISTERING;
|
||||||
|
|
||||||
|
{
|
||||||
|
SmProp prop1, prop2, prop3, prop4, prop5, *props[5];
|
||||||
|
SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val;
|
||||||
|
char pid[32];
|
||||||
|
char hint = SmRestartIfRunning;
|
||||||
|
|
||||||
|
prop1.name = SmProgram;
|
||||||
|
prop1.type = SmARRAY8;
|
||||||
|
prop1.num_vals = 1;
|
||||||
|
prop1.vals = &prop1val;
|
||||||
|
prop1val.value = "metacity";
|
||||||
|
prop1val.length = strlen ("metacity");
|
||||||
|
|
||||||
|
/* twm sets getuid() for this, but the SM spec plainly
|
||||||
|
* says pw_name, twm is on crack
|
||||||
|
*/
|
||||||
|
prop2.name = SmUserID;
|
||||||
|
prop2.type = SmARRAY8;
|
||||||
|
prop2.num_vals = 1;
|
||||||
|
prop2.vals = &prop2val;
|
||||||
|
prop2val.value = g_get_user_name ();
|
||||||
|
prop2val.length = strlen (prop2val.value);
|
||||||
|
|
||||||
|
prop3.name = SmRestartStyleHint;
|
||||||
|
prop3.type = SmCARD8;
|
||||||
|
prop3.num_vals = 1;
|
||||||
|
prop3.vals = &prop3val;
|
||||||
|
prop3val.value = &hint;
|
||||||
|
prop3val.length = 1;
|
||||||
|
|
||||||
|
sprintf (pid, "%d", getpid ());
|
||||||
|
prop4.name = SmProcessID;
|
||||||
|
prop4.type = SmARRAY8;
|
||||||
|
prop4.num_vals = 1;
|
||||||
|
prop4.vals = &prop4val;
|
||||||
|
prop4val.value = pid;
|
||||||
|
prop4val.length = strlen (prop4val.value);
|
||||||
|
|
||||||
|
/* Always start in home directory */
|
||||||
|
prop5.name = SmCurrentDirectory;
|
||||||
|
prop5.type = SmARRAY8;
|
||||||
|
prop5.num_vals = 1;
|
||||||
|
prop5.vals = &prop5val;
|
||||||
|
prop5val.value = g_get_home_dir ();
|
||||||
|
prop5val.length = strlen (prop5val.value);
|
||||||
|
|
||||||
|
props[0] = &prop1;
|
||||||
|
props[1] = &prop2;
|
||||||
|
props[2] = &prop3;
|
||||||
|
props[3] = &prop4;
|
||||||
|
props[4] = &prop5;
|
||||||
|
|
||||||
|
SmcSetProperties (session_connection, 5, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_clone_restart_commands ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
disconnect (void)
|
||||||
|
{
|
||||||
|
SmcCloseConnection (session_connection, 0, NULL);
|
||||||
|
session_connection = NULL;
|
||||||
|
current_state = STATE_DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
save_yourself_possibly_done (gboolean shutdown,
|
||||||
|
gboolean successful)
|
||||||
|
{
|
||||||
|
if (current_state == STATE_SAVING_PHASE_1)
|
||||||
|
{
|
||||||
|
Status status;
|
||||||
|
|
||||||
|
status = SmcRequestSaveYourselfPhase2 (session_connection,
|
||||||
|
save_phase_2_callback,
|
||||||
|
GINT_TO_POINTER (shutdown));
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
current_state = STATE_WAITING_FOR_PHASE_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_state == STATE_SAVING_PHASE_1 ||
|
||||||
|
current_state == STATE_SAVING_PHASE_2)
|
||||||
|
{
|
||||||
|
SmcSaveYourselfDone (session_connection,
|
||||||
|
successful);
|
||||||
|
|
||||||
|
if (shutdown)
|
||||||
|
current_state = STATE_FROZEN;
|
||||||
|
else
|
||||||
|
current_state = STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
save_phase_2_callback (SmcConn smc_conn, SmPointer client_data)
|
||||||
|
{
|
||||||
|
gboolean shutdown;
|
||||||
|
|
||||||
|
shutdown = GPOINTER_TO_INT (client_data);
|
||||||
|
|
||||||
|
current_state = STATE_SAVING_PHASE_2;
|
||||||
|
|
||||||
|
save_yourself_possibly_done (shutdown, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
save_yourself_callback (SmcConn smc_conn,
|
||||||
|
SmPointer client_data,
|
||||||
|
int save_style,
|
||||||
|
Bool shutdown,
|
||||||
|
int interact_style,
|
||||||
|
Bool fast)
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
|
||||||
|
successful = TRUE;
|
||||||
|
|
||||||
|
/* The first SaveYourself after registering for the first time
|
||||||
|
* is a special case (SM specs 7.2).
|
||||||
|
*
|
||||||
|
* This SaveYourself seems to be included in the protocol to
|
||||||
|
* ask the client to specify its initial SmProperties since
|
||||||
|
* there is little point saving a copy of the initial state.
|
||||||
|
*
|
||||||
|
* A bug in xsm means that it does not send us a SaveComplete
|
||||||
|
* in response to this initial SaveYourself. Therefore, we
|
||||||
|
* must not set a grab because it would never be released.
|
||||||
|
* Indeed, even telling the app that this SaveYourself has
|
||||||
|
* arrived is hazardous as the app may take its own steps
|
||||||
|
* to freeze its WM state while waiting for the SaveComplete.
|
||||||
|
*
|
||||||
|
* Fortunately, we have already set the SmProperties during
|
||||||
|
* gnome_client_connect so there is little lost in simply
|
||||||
|
* returning immediately.
|
||||||
|
*
|
||||||
|
* Apps which really want to save their initial states can
|
||||||
|
* do so safely using gnome_client_save_yourself_request.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (current_state == STATE_REGISTERING)
|
||||||
|
{
|
||||||
|
current_state = STATE_IDLE;
|
||||||
|
|
||||||
|
/* Double check that this is a section 7.2 SaveYourself: */
|
||||||
|
|
||||||
|
if (save_style == SmSaveLocal &&
|
||||||
|
interact_style == SmInteractStyleNone &&
|
||||||
|
!shutdown && !fast)
|
||||||
|
{
|
||||||
|
/* The protocol requires this even if xsm ignores it. */
|
||||||
|
SmcSaveYourselfDone (session_connection, successful);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_state = STATE_SAVING_PHASE_1;
|
||||||
|
|
||||||
|
set_clone_restart_commands ();
|
||||||
|
|
||||||
|
save_yourself_possibly_done (shutdown, successful);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
die_callback (SmcConn smc_conn, SmPointer client_data)
|
||||||
|
{
|
||||||
|
meta_verbose ("Exiting at request of session manager\n");
|
||||||
|
disconnect ();
|
||||||
|
meta_quit (META_EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
save_complete_callback (SmcConn smc_conn, SmPointer client_data)
|
||||||
|
{
|
||||||
|
/* nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shutdown_cancelled_callback (SmcConn smc_conn, SmPointer client_data)
|
||||||
|
{
|
||||||
|
/* nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
interact_callback (SmcConn smc_conn, SmPointer client_data)
|
||||||
|
{
|
||||||
|
/* nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_clone_restart_commands (void)
|
||||||
|
{
|
||||||
|
char *restartv[10];
|
||||||
|
char *clonev[10];
|
||||||
|
int i;
|
||||||
|
SmProp prop1, prop2, *props[2];
|
||||||
|
|
||||||
|
/* Restart (use same client ID) */
|
||||||
|
|
||||||
|
prop1.name = SmRestartCommand;
|
||||||
|
prop1.type = SmLISTofARRAY8;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
restartv[i] = "metacity";
|
||||||
|
++i;
|
||||||
|
restartv[i] = "--sm-client-id";
|
||||||
|
++i;
|
||||||
|
restartv[i] = client_id;
|
||||||
|
++i;
|
||||||
|
restartv[i] = NULL;
|
||||||
|
|
||||||
|
prop1.vals = g_new (SmPropValue, i);
|
||||||
|
i = 0;
|
||||||
|
while (restartv[i])
|
||||||
|
{
|
||||||
|
prop1.vals[i].value = restartv[i];
|
||||||
|
prop1.vals[i].length = strlen (restartv[i]);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
prop1.num_vals = i;
|
||||||
|
|
||||||
|
/* Clone (no client ID) */
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
clonev[i] = "metacity";
|
||||||
|
++i;
|
||||||
|
clonev[i] = NULL;
|
||||||
|
|
||||||
|
prop2.name = SmCloneCommand;
|
||||||
|
prop2.type = SmLISTofARRAY8;
|
||||||
|
|
||||||
|
prop2.vals = g_new (SmPropValue, i);
|
||||||
|
i = 0;
|
||||||
|
while (clonev[i])
|
||||||
|
{
|
||||||
|
prop2.vals[i].value = clonev[i];
|
||||||
|
prop2.vals[i].length = strlen (clonev[i]);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
prop2.num_vals = i;
|
||||||
|
|
||||||
|
props[0] = &prop1;
|
||||||
|
props[1] = &prop2;
|
||||||
|
|
||||||
|
SmcSetProperties (session_connection, 2, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_SM */
|
||||||
|
Loading…
Reference in New Issue
Block a user