diff options
author | George Lebl <jirka@5z.com> | 2003-12-30 23:39:21 +0000 |
---|---|---|
committer | George Lebl <jirka@src.gnome.org> | 2003-12-30 23:39:21 +0000 |
commit | 669245886f2437c8efb3adf73f7245e57cb6e818 (patch) | |
tree | a9aee98535bd3fe498c2e440ef07c9499fef7a26 | |
parent | afa6a5a8099360422eb1f18e1f729872796d8de8 (diff) | |
download | gdm-669245886f2437c8efb3adf73f7245e57cb6e818.tar.gz |
Complain on some more errors
Tue Dec 30 15:34:59 2003 George Lebl <jirka@5z.com>
* daemon/gdm.c, daemon/auth.c: Complain on some more errors
* gui/gdmlogin.c, gui/gdmcommon.[ch], gui/gdmsetup.(c|glade),
gui/greeter/greeter.c, gui/greeter/greeter_configuration.h,
daemon/gdm.[ch], daemon/slave.c: Make the login sound thingie
configurable and make it possible to play an arbitrary sound with
/usr/bin/play (or whatever else is configured). Add accessibility
section to gdmsetup which configures the accessibility modules
and the sound. Fixes #125487
* config/gdm.conf.in, docs/C/gdm.xml: Update docs for the
accessibility/sound stuff
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | acconfig.h | 1 | ||||
-rw-r--r-- | config/gdm.conf.in | 10 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | daemon/auth.c | 8 | ||||
-rw-r--r-- | daemon/gdm.c | 61 | ||||
-rw-r--r-- | daemon/gdm.h | 17 | ||||
-rw-r--r-- | daemon/slave.c | 55 | ||||
-rw-r--r-- | docs/C/gdm.xml | 49 | ||||
-rw-r--r-- | gui/gdmcommon.c | 20 | ||||
-rw-r--r-- | gui/gdmcommon.h | 2 | ||||
-rw-r--r-- | gui/gdmlogin.c | 14 | ||||
-rw-r--r-- | gui/gdmsetup-strings.c | 12 | ||||
-rw-r--r-- | gui/gdmsetup.c | 240 | ||||
-rw-r--r-- | gui/gdmsetup.glade | 372 | ||||
-rw-r--r-- | gui/greeter/greeter.c | 17 | ||||
-rw-r--r-- | gui/greeter/greeter_configuration.h | 3 |
17 files changed, 861 insertions, 40 deletions
@@ -1,3 +1,18 @@ +Tue Dec 30 15:34:59 2003 George Lebl <jirka@5z.com> + + * daemon/gdm.c, daemon/auth.c: Complain on some more errors + + * gui/gdmlogin.c, gui/gdmcommon.[ch], gui/gdmsetup.(c|glade), + gui/greeter/greeter.c, gui/greeter/greeter_configuration.h, + daemon/gdm.[ch], daemon/slave.c: Make the login sound thingie + configurable and make it possible to play an arbitrary sound with + /usr/bin/play (or whatever else is configured). Add accessibility + section to gdmsetup which configures the accessibility modules + and the sound. Fixes #125487 + + * config/gdm.conf.in, docs/C/gdm.xml: Update docs for the + accessibility/sound stuff + Mon Dec 29 16:52:32 2003 George Lebl <jirka@5z.com> * daemon/gdm.[ch]: add SET_SAFE_LOGOUT_ACTION which is like schedule @@ -25,6 +25,7 @@ #undef EXPANDED_BINDIR #undef EXPANDED_SBINDIR #undef EXPANDED_LIBEXECDIR +#undef EXPANDED_LIBDIR #undef EXPANDED_GDMCONFIGDIR #undef EXPANDED_LOCALEDIR #undef EXPANDED_AUTHDIR diff --git a/config/gdm.conf.in b/config/gdm.conf.in index cf68ffea..36cb79a1 100644 --- a/config/gdm.conf.in +++ b/config/gdm.conf.in @@ -137,6 +137,10 @@ Xnest=@X_SERVER_PATH@/Xnest -audit 0 -name Xnest # vts on linux systems for console logins) #DoubleLoginWarning=true +# Program used to play sounds. Should not require any 'daemon' or anything +# like that as it will be run when no one is logged in yet. +#SoundProgram=/usr/bin/play + [security] # If any distributions ship with this one off, they should be shot # this is only local, so it's only for say kiosk use, when you @@ -317,6 +321,12 @@ GraphicalThemeDir=@EXPANDED_DATADIR@/gdm/themes/ # If InfoMsgFile is present then InfoMsgFont can be used to specify the font # to be used when displaying the contents of the file. #InfoMsgFont=Sans 24 +# If SoundOnLogin is true, then the greeter will beep when login is ready +# for user input. If SoundOnLogin is a file and the greeter finds the +# 'play' executable (see daemon/SoundProgram) it will play that file +# instead of just beeping +#SoundOnLogin=true +#SoundOnLoginFile= # The chooser is what's displayed when a user wants an indirect XDMCP # session, or selects Run XDMCP chooser from the system menu diff --git a/configure.in b/configure.in index a688e2e5..05f476ab 100644 --- a/configure.in +++ b/configure.in @@ -557,6 +557,11 @@ EXPANDED_LIBEXECDIR=`eval echo $LIBEXECDIR_TMP` AC_SUBST(EXPANDED_LIBEXECDIR) AC_DEFINE_UNQUOTED(EXPANDED_LIBEXECDIR,"$EXPANDED_LIBEXECDIR") +LIBDIR_TMP="$libdir" +EXPANDED_LIBDIR=`eval echo $LIBDIR_TMP` +AC_SUBST(EXPANDED_LIBDIR) +AC_DEFINE_UNQUOTED(EXPANDED_LIBDIR,"$EXPANDED_LIBDIR") + dnl This is where the binary actually resides, dnl not the console helper link if test "x$enable_console_helper" = "xyes"; then diff --git a/daemon/auth.c b/daemon/auth.c index 543d6284..a6549235 100644 --- a/daemon/auth.c +++ b/daemon/auth.c @@ -881,9 +881,15 @@ gdm_auth_user_remove (GdmDisplay *d, uid_t user) af = gdm_auth_purge (d, af, TRUE /* remove when empty */); /* Close the file and unlock it */ - if (af != NULL) + if (af != NULL) { /* FIXME: what about out of diskspace errors on errors close */ + errno = 0; VE_IGNORE_EINTR (fclose (af)); + if G_UNLIKELY (errno != 0) { + gdm_error (_("Can't write to %s: %s"), d->userauth, + strerror (errno)); + } + } XauUnlockAuth (d->userauth); diff --git a/daemon/gdm.c b/daemon/gdm.c index d563adfb..bee7b5f7 100644 --- a/daemon/gdm.c +++ b/daemon/gdm.c @@ -190,6 +190,8 @@ gchar *GdmXnest = NULL; int GdmFirstVT = 7; gboolean GdmVTAllocation = TRUE; gboolean GdmDisallowTCP = TRUE; +gchar *GdmSoundProgram = NULL; +gchar *GdmSoundOnLoginFile = NULL; /* set in the main function */ @@ -407,9 +409,12 @@ gdm_config_parse (void) if (ve_string_empty (GdmXnest)) GdmXnest = NULL; - GdmFirstVT = ve_config_get_int (cfg, GDM_KEY_FIRSTVT); - GdmVTAllocation = ve_config_get_bool (cfg, GDM_KEY_VTALLOCATION); - GdmDisallowTCP = ve_config_get_bool (cfg, GDM_KEY_DISALLOWTCP); + GdmFirstVT = ve_config_get_int (cfg, GDM_KEY_FIRSTVT); + GdmVTAllocation = ve_config_get_bool (cfg, GDM_KEY_VTALLOCATION); + GdmDisallowTCP = ve_config_get_bool (cfg, GDM_KEY_DISALLOWTCP); + + GdmSoundProgram = ve_config_get_string (cfg, GDM_KEY_SOUND_PROGRAM); + GdmSoundOnLoginFile = ve_config_get_string (cfg, GDM_KEY_SOUND_ON_LOGIN_FILE); GdmDebug = ve_config_get_bool (cfg, GDM_KEY_DEBUG); @@ -1170,6 +1175,11 @@ suspend_machine (void) if (GdmSuspendReal != NULL && fork () == 0) { char **argv; + + /* sync everything to disk, just in case something goes + * wrong with the suspend */ + sync (); + if (GdmXdmcp) gdm_xdmcp_close (); /* In the child setup empty mask and set all signals to @@ -1181,6 +1191,9 @@ suspend_machine (void) VE_IGNORE_EINTR (chdir ("/")); + /* short sleep to give some processing time to master */ + usleep (1000); + argv = ve_split (GdmSuspendReal); if (argv != NULL && argv[0] != NULL) VE_IGNORE_EINTR (execv (argv[0], argv)); @@ -2170,7 +2183,7 @@ write_x_servers (GdmDisplay *d) fp = gdm_safe_fopen_w (file); if G_UNLIKELY (fp == NULL) { - gdm_error ("Can't open %s for writing", file); + gdm_error (_("Can't open %s for writing"), file); g_free (file); return; } @@ -2198,7 +2211,14 @@ write_x_servers (GdmDisplay *d) } /* FIXME: What about out of disk space errors? */ + errno = 0; VE_IGNORE_EINTR (fclose (fp)); + if G_UNLIKELY (errno != 0) { + gdm_error (_("Can't write to %s: %s"), file, + strerror (errno)); + } + + g_free (file); } static void @@ -3306,6 +3326,39 @@ update_config (const char *key) if (gdm_xdmcp_init ()) gdm_xdmcp_run (); } + } else if (is_key (key, GDM_KEY_SOUND_ON_LOGIN_FILE)) { + char *val = ve_config_get_string (cfg, GDM_KEY_SOUND_ON_LOGIN_FILE); + if (strcmp (ve_sure_string (val), ve_sure_string (GdmSoundOnLoginFile)) == 0) { + g_free (val); + goto update_config_ok; + } + g_free (GdmSoundOnLoginFile); + GdmSoundOnLoginFile = val; + + notify_displays_string (GDM_NOTIFY_SOUND_ON_LOGIN_FILE, val); + + goto update_config_ok; + } else if (is_key (key, GDM_KEY_GTK_MODULES_LIST)) { + char *val = ve_config_get_string (cfg, GDM_KEY_GTK_MODULES_LIST); + if (strcmp (ve_sure_string (val), ve_sure_string (GdmGtkModulesList)) == 0) { + g_free (val); + goto update_config_ok; + } + g_free (GdmGtkModulesList); + GdmGtkModulesList = val; + + notify_displays_string (GDM_NOTIFY_GTK_MODULES_LIST, val); + + goto update_config_ok; + } else if (is_key (key, GDM_KEY_ADD_GTK_MODULES)) { + gboolean val = ve_config_get_bool (cfg, GDM_KEY_ADD_GTK_MODULES); + if (ve_bool_equal (val, GdmAddGtkModules)) + goto update_config_ok; + GdmAddGtkModules = val; + + notify_displays_int (GDM_NOTIFY_ADD_GTK_MODULES, val); + + goto update_config_ok; } ve_config_destroy (cfg); diff --git a/daemon/gdm.h b/daemon/gdm.h index 7fc88626..9353f194 100644 --- a/daemon/gdm.h +++ b/daemon/gdm.h @@ -113,6 +113,7 @@ enum { #define GDM_INTERRUPT_CONFIGURE 'C' #define GDM_INTERRUPT_SUSPEND 'S' #define GDM_INTERRUPT_SELECT_USER 'U' +#define GDM_INTERRUPT_LOGIN_SOUND 'L' /* The dreaded miscellaneous category */ #define FIELD_SIZE 256 @@ -247,6 +248,10 @@ enum { #define GDM_KEY_INFO_MSG_FILE "greeter/InfoMsgFile=" #define GDM_KEY_INFO_MSG_FONT "greeter/InfoMsgFont=" +#define GDM_KEY_SOUND_ON_LOGIN "greeter/SoundOnLogin=true" +#define GDM_KEY_SOUND_ON_LOGIN_FILE "greeter/SoundOnLoginFile=" +#define GDM_KEY_SOUND_PROGRAM "daemon/SoundProgram=/usr/bin/play" + #define GDM_KEY_SCAN "chooser/ScanTime=4" #define GDM_KEY_HOST "chooser/DefaultHostImg=" EXPANDED_PIXMAPDIR "/nohost.png" #define GDM_KEY_HOSTDIR "chooser/HostImageDir=" EXPANDED_DATADIR "/hosts/" @@ -553,6 +558,9 @@ void gdm_final_cleanup (void); #define GDM_NOTIFY_TIMED_LOGIN "TimedLogin" /* <login> */ #define GDM_NOTIFY_TIMED_LOGIN_DELAY "TimedLoginDelay" /* <seconds> */ #define GDM_NOTIFY_DISALLOWTCP "DisallowTCP" /* <true/false as int> */ +#define GDM_NOTIFY_SOUND_ON_LOGIN_FILE "SoundOnLoginFile" /* <sound file> */ +#define GDM_NOTIFY_ADD_GTK_MODULES "AddGtkModules" /* <true/false as int> */ +#define GDM_NOTIFY_GTK_MODULES_LIST "GtkModulesList" /* <modules list> */ /* commands */ #define GDM_NOTIFY_DIRTY_SERVERS "DIRTY_SERVERS" @@ -723,12 +731,15 @@ void gdm_final_cleanup (void); * xdmcp/MaxPendingIndirect * xdmcp/MaxWaitIndirect * xdmcp/PingIntervalSeconds (only affects new connections) - * xdmcp/TimedLogin (2.3.90.3) - * xdmcp/TimedLoginEnable (2.3.90.3) - * xdmcp/TimedLoginDelay (2.3.90.3) + * daemon/TimedLogin (2.3.90.3) + * daemon/TimedLoginEnable (2.3.90.3) + * daemon/TimedLoginDelay (2.3.90.3) * greeter/SystemMenu (2.3.90.3) * greeter/ConfigAvailable (2.3.90.3) * greeter/ChooserButton (2.4.2.0) + * greeter/SoundOnLoginFile (2.5.90.0) + * daemon/AddGtkModules (2.5.90.0) + * daemon/GtkModulesList (2.5.90.0) * Supported since: 2.3.90.2 * Arguments: <key> * <key> is just the base part of the key such as "security/AllowRemoteRoot" diff --git a/daemon/slave.c b/daemon/slave.c index a5a09c4f..28d97978 100644 --- a/daemon/slave.c +++ b/daemon/slave.c @@ -174,6 +174,8 @@ extern gboolean GdmAllowRemoteRoot; extern gchar *GdmGlobalFaceDir; extern gboolean GdmDebug; extern gboolean GdmDisallowTCP; +extern gchar *GdmSoundProgram; +extern gchar *GdmSoundOnLoginFile; /* Local prototypes */ @@ -3625,13 +3627,9 @@ session_child_run (struct passwd *pwent, if ( ! gdm_selinux_setup (pwent->pw_name)) { /* 66 means no "session crashed" examine .xsession-errors dialog */ - /* FIXME: do this when we get out of string freeze */ - /* - gdm_error_box (d, GTK_MESSAGE_ERROR, _("Error! Unable to set executable context.")); + gdm_error_box (d, GTK_MESSAGE_ERROR, + _("Error! Unable to set executable context.")); _exit (66); - */ - /* errors have alredy been logged to .xsession-errors */ - _exit (1); } #endif @@ -4646,6 +4644,37 @@ check_for_interruption (const char *msg) /* Not interrupted, continue reading input, * just proxy this to the master server */ return TRUE; + case GDM_INTERRUPT_LOGIN_SOUND: + if (d->console && + ! ve_string_empty (GdmSoundProgram) && + ! ve_string_empty (GdmSoundOnLoginFile) && + access (GdmSoundProgram, X_OK) == 0 && + access (GdmSoundOnLoginFile, F_OK) == 0) { + pid_t pid; + + gdm_sigchld_block_push (); + gdm_sigterm_block_push (); + pid = fork (); + if (pid == 0) + gdm_unset_signals (); + gdm_sigterm_block_pop (); + gdm_sigchld_block_pop (); + + if (pid == 0) { + setsid (); + seteuid (0); + setegid (0); + execl (GdmSoundProgram, + GdmSoundProgram, + GdmSoundOnLoginFile, + NULL); + + _exit (0); + } + } else { + gdm_error (_("Login sound requested on non-local display or the play software cannot be run or the sound does not exist")); + } + return TRUE; case GDM_INTERRUPT_SELECT_USER: gdm_verify_select_user (&msg[2]); break; @@ -5248,6 +5277,20 @@ gdm_slave_handle_notify (const char *msg) GdmTimedLoginDelay = val; if (d->greetpid > 1) kill (d->greetpid, SIGHUP); + } else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_FILE " ", + strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FILE) + 1) == 0) { + g_free (GdmSoundOnLoginFile); + GdmSoundOnLoginFile = g_strdup + (&msg[strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FILE) + 1]); + if (d->greetpid > 1) + kill (d->greetpid, SIGHUP); + } else if (strncmp (msg, GDM_NOTIFY_GTK_MODULES_LIST " ", + strlen (GDM_NOTIFY_GTK_MODULES_LIST) + 1) == 0) { + g_free (GdmGtkModulesList); + GdmGtkModulesList = g_strdup + (&msg[strlen (GDM_NOTIFY_GTK_MODULES_LIST) + 1]); + } else if (sscanf (msg, GDM_NOTIFY_ADD_GTK_MODULES " %d", &val) == 1) { + GdmAddGtkModules = val; } } diff --git a/docs/C/gdm.xml b/docs/C/gdm.xml index fb8eb439..7c4ad1c6 100644 --- a/docs/C/gdm.xml +++ b/docs/C/gdm.xml @@ -3,7 +3,7 @@ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ <!ENTITY legal SYSTEM "legal.xml"> <!ENTITY version "2.5.90.0"> - <!ENTITY date "12/12/2003"> + <!ENTITY date "12/30/2003"> ]> <article id="index" lang="en"> @@ -33,7 +33,7 @@ <year>1998</year> <year>1999</year> <holder>Martin K. Petersen</holder> </copyright> <copyright> - <year>2001</year> <holder>George Lebl</holder> + <year>2001</year> <year>2003</year> <holder>George Lebl</holder> </copyright> <copyright> <year>2003</year> <holder>Red Hat, Inc.</holder> @@ -61,7 +61,7 @@ <para> GDM - Gnome Display Manager. Used to describe the software - package as a whole. + package as a whole. Sometimes also referred to as GDM2. </para> <para> @@ -1461,6 +1461,19 @@ </varlistentry> <varlistentry> + <term>SoundProgram</term> + <listitem> + <synopsis>SoundProgram=/usr/bin/play</synopsis> + <para> + Program to use when playing a sound. Currently used for + playing the login sound, see + the <filename>SoundOnLoginFile</filename> key. + Supported since 2.5.90.0. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>StandardXServer</term> <listitem> <synopsis>StandardXServer=/usr/X11R6/bin/X</synopsis> @@ -2454,6 +2467,36 @@ </para> </listitem> </varlistentry> + + <varlistentry> + <term>SoundOnLogin</term> + <listitem> + <synopsis>SoundOnLogin=true</synopsis> + <para> + If true, the greeter will play a sound or beep when + it is ready for a login. See also the + <filename>SoundOnLoginFile</filename> key. + Supported since 2.5.90.0. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>SoundOnLoginFile</term> + <listitem> + <synopsis>SoundOnLogin=/path/to/sound.wav</synopsis> + <para> + The file that will be played using the specified + sound program (by default that is + <filename>/usr/bin/play</filename>) instead of a beep + when the greeter is ready for a login. + See also the + <filename>SoundOnLogin</filename> key and the + <filename>SoundProgram</filename> key. + Supported since 2.5.90.0. + </para> + </listitem> + </varlistentry> <varlistentry> <term>SystemMenu</term> diff --git a/gui/gdmcommon.c b/gui/gdmcommon.c index 04da5544..615ae43e 100644 --- a/gui/gdmcommon.c +++ b/gui/gdmcommon.c @@ -36,6 +36,9 @@ extern gchar *GdmInfoMsgFile; extern gchar *GdmInfoMsgFont; +extern gchar *GdmSoundProgram; +extern gboolean GdmSoundOnLogin; +extern gchar *GdmSoundOnLoginFile; void gdm_common_show_info_msg (void) @@ -223,4 +226,21 @@ gdm_common_int_same (VeConfig *config, int cur, const char *key) } } +void +gdm_common_login_sound (void) +{ + if ( ! GdmSoundOnLogin) + return; + if (ve_string_empty (g_getenv ("GDM_IS_LOCAL")) || + ve_string_empty (GdmSoundProgram) || + ve_string_empty (GdmSoundOnLoginFile) || + access (GdmSoundProgram, F_OK) != 0 || + access (GdmSoundOnLoginFile, F_OK) != 0) { + gdk_beep (); + } else { + /* login sound interruption */ + printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_LOGIN_SOUND); + fflush (stdout); + } +} diff --git a/gui/gdmcommon.h b/gui/gdmcommon.h index c08a3d93..9d8cde49 100644 --- a/gui/gdmcommon.h +++ b/gui/gdmcommon.h @@ -40,6 +40,8 @@ gboolean gdm_common_bool_same (VeConfig *config, gboolean gdm_common_int_same (VeConfig *config, int cur, const char *key); +void gdm_common_login_sound (void); + /* The greeter defines this, we just call it from here */ void gdm_kill_thingies (void); diff --git a/gui/gdmlogin.c b/gui/gdmlogin.c index 196ae820..feded984 100644 --- a/gui/gdmlogin.c +++ b/gui/gdmlogin.c @@ -124,6 +124,10 @@ static gint GdmPositionX; static gint GdmPositionY; static gboolean GdmTitleBar; +gboolean GdmSoundOnLogin; +gchar *GdmSoundOnLoginFile; +gchar *GdmSoundProgram; + static gboolean GdmShowGnomeFailsafeSession; static gboolean GdmShowXtermFailsafeSession; static gboolean GdmShowLastSession; @@ -716,6 +720,10 @@ gdm_login_parse_config (void) GdmFlexiReapDelayMinutes = ve_config_get_int (config, GDM_KEY_FLEXI_REAP_DELAY_MINUTES); GdmUse24Clock = ve_config_get_bool (config, GDM_KEY_USE_24_CLOCK); + GdmSoundOnLogin = ve_config_get_bool (config, GDM_KEY_SOUND_ON_LOGIN); + GdmSoundOnLoginFile = ve_config_get_string (config, GDM_KEY_SOUND_ON_LOGIN_FILE); + GdmSoundProgram = ve_config_get_string (config, GDM_KEY_SOUND_PROGRAM); + if (GdmIconMaxWidth < 0) GdmIconMaxWidth = 128; if (GdmIconMaxHeight < 0) GdmIconMaxHeight = 128; if (GdmXineramaScreen < 0) GdmXineramaScreen = 0; @@ -1744,7 +1752,7 @@ gdm_login_ctrl_handler (GIOChannel *source, GIOCondition cond, gint fd) tmp = ve_locale_to_utf8 (buf); if (strcmp (tmp, _("Username:")) == 0) { - gdk_beep (); + gdm_common_login_sound (); gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _("_Username:")); } else { gtk_label_set_text (GTK_LABEL (label), tmp); @@ -3506,6 +3514,10 @@ gdm_reread_config (int sig, gpointer data) } } + GdmSoundProgram = ve_config_get_string (config, GDM_KEY_SOUND_PROGRAM); + GdmSoundOnLogin = ve_config_get_bool (config, GDM_KEY_SOUND_ON_LOGIN); + GdmSoundOnLoginFile = ve_config_get_string (config, GDM_KEY_SOUND_ON_LOGIN_FILE); + GdmUse24Clock = ve_config_get_bool (config, GDM_KEY_USE_24_CLOCK); update_clock (NULL); diff --git a/gui/gdmsetup-strings.c b/gui/gdmsetup-strings.c index 5412dc3e..38abc95b 100644 --- a/gui/gdmsetup-strings.c +++ b/gui/gdmsetup-strings.c @@ -68,11 +68,23 @@ gchar *s = N_("Allow root to login r_emotely with GDM"); gchar *s = N_("Allow remote _timed logins"); gchar *s = N_("Show the \"Actions\" menu (formerly known as the \"System\" menu). If not set, none of the system commands will be available (this includes reboot, shutdown, configure, chooser)"); gchar *s = N_("Show _actions menu"); +gchar *s = N_(" "); gchar *s = N_("Allow c_onfiguration from the login screen"); +gchar *s = N_(" "); gchar *s = N_("Allo_w running XDMCP chooser from the login screen"); gchar *s = N_("Always disallow TCP connections to _X server (disables all remote connections)"); gchar *s = N_("Retry _delay (seconds) :"); gchar *s = N_("Security"); +gchar *s = N_("Options"); +gchar *s = N_(" "); +gchar *s = N_("Enable _accessibility modules"); +gchar *s = N_("Make a _sound when login window is ready"); +gchar *s = N_(" "); +gchar *s = N_("acc_sound_file_box"); +gchar *s = N_("Sound _file:"); +gchar *s = N_("*"); +gchar *s = N_("_Test sound"); +gchar *s = N_("Accessibility"); gchar *s = N_("No XDMCP support in the binary. To enable XDMCP support you must recompile GDM with the XDMCP libraries."); gchar *s = N_("Enable _XDMCP"); gchar *s = N_(" "); diff --git a/gui/gdmsetup.c b/gui/gdmsetup.c index 436342be..633592ac 100644 --- a/gui/gdmsetup.c +++ b/gui/gdmsetup.c @@ -51,6 +51,7 @@ static gboolean RUNNING_UNDER_GDM = FALSE; static gboolean gdm_running = FALSE; static int GdmMinimalUID = 100; +static char *GdmSoundProgram = NULL; static GladeXML *xml; @@ -565,6 +566,27 @@ setup_intspin (const char *name, G_CALLBACK (intspin_changed), NULL); } +static void +setup_notify_entry (const char *name, + const char *key) +{ + GtkWidget *entry = glade_helper_get (xml, name, GTK_TYPE_ENTRY); + char *val; + + val = ve_config_get_string (ve_config_get (GDM_CONFIG_FILE), key); + + g_object_set_data_full (G_OBJECT (entry), + "key", g_strdup (key), + (GDestroyNotify) g_free); + + gtk_entry_set_text (GTK_ENTRY (entry), ve_sure_string (val)); + + g_signal_connect (G_OBJECT (entry), "changed", + G_CALLBACK (entry_changed), NULL); + + g_free (val); +} + static gboolean greeter_toggle_timeout (GtkWidget *toggle) { @@ -948,6 +970,204 @@ setup_xdmcp_support (void) } static void +test_sound (GtkWidget *button, gpointer data) +{ + GtkEntry *entry = GTK_ENTRY (data); + const char *file = gtk_entry_get_text (GTK_ENTRY (entry)); + const char *argv[3]; + + if (ve_string_empty (file) || + access (file, R_OK) != 0 || + ve_string_empty (GdmSoundProgram)) + return; + + argv[0] = GdmSoundProgram; + argv[1] = file; + argv[2] = NULL; + + g_spawn_async ("/" /* working directory */, + (char **)argv, + NULL /* envp */, + 0 /* flags */, + NULL /* child setup */, + NULL /* user data */, + NULL /* child pid */, + NULL /* error */); +} + +static gboolean +module_compare (const char *mod1, const char *mod2) +{ + char *base1; + char *base2; + char *p; + gboolean ret; + + /* first cannonify the names */ + base1 = g_path_get_basename (mod1); + base2 = g_path_get_basename (mod2); + if (strncmp (base1, "lib", 3) == 0) + strcpy (base1, &base1[3]); + if (strncmp (base2, "lib", 3) == 0) + strcpy (base2, &base2[3]); + p = strstr (base1, ".so"); + if (p != NULL) + *p = '\0'; + p = strstr (base2, ".so"); + if (p != NULL) + *p = '\0'; + + ret = (strcmp (base1, base2) == 0); + + g_free (base1); + g_free (base2); + + return ret; +} + +static gboolean +modules_list_contains (const char *modules_list, const char *module) +{ + char **vec; + int i; + + if (ve_string_empty (modules_list)) + return FALSE; + + vec = g_strsplit (modules_list, ":", -1); + if (vec == NULL) + return FALSE; + + for (i = 0; vec[i] != NULL; i++) { + if (module_compare (vec[i], module)) { + g_strfreev (vec); + return TRUE; + } + } + + g_strfreev (vec); + return FALSE; +} + +static char * +modules_list_remove (char *modules_list, const char *module) +{ + char **vec; + GString *str; + char *sep = ""; + int i; + + if (ve_string_empty (modules_list)) + return g_strdup (""); + + vec = g_strsplit (modules_list, ":", -1); + if (vec == NULL) + return g_strdup (""); + + str = g_string_new (NULL); + + for (i = 0; vec[i] != NULL; i++) { + if ( ! module_compare (vec[i], module)) { + g_string_append (str, sep); + sep = ":"; + g_string_append (str, vec[i]); + } + } + + g_strfreev (vec); + + return g_string_free (str, FALSE); +} + +static char * +modules_list_add (char *modules_list, const char *module) +{ + char *n; + if (ve_string_empty (modules_list)) + n = g_strdup (module); + else + n = g_strconcat (modules_list, ":", module, NULL); + g_free (modules_list); + return n; +} + +static void +acc_modules_toggled (GtkWidget *toggle, gpointer data) +{ + gboolean add_gtk_modules = ve_config_get_bool (ve_config_get (GDM_CONFIG_FILE), + GDM_KEY_ADD_GTK_MODULES); + char *modules_list = ve_config_get_string (ve_config_get (GDM_CONFIG_FILE), + GDM_KEY_GTK_MODULES_LIST); + + /* first whack the modules from the list */ + modules_list = modules_list_remove (modules_list, "gail"); + modules_list = modules_list_remove (modules_list, "atk-bridge"); + modules_list = modules_list_remove (modules_list, "dwellmouselistener"); + modules_list = modules_list_remove (modules_list, "keymouselistener"); + + if (GTK_TOGGLE_BUTTON (toggle)->active) { + if ( ! add_gtk_modules) { + g_free (modules_list); + modules_list = NULL; + } + + modules_list = modules_list_add (modules_list, "gail"); + modules_list = modules_list_add (modules_list, "atk-bridge"); + modules_list = modules_list_add (modules_list, EXPANDED_LIBDIR "/gtk-2.0/modules/libkeymouselistener"); + modules_list = modules_list_add (modules_list, EXPANDED_LIBDIR "/gtk-2.0/modules/libdwellmouselistener"); + + add_gtk_modules = TRUE; + } + + if (ve_string_empty (modules_list)) + add_gtk_modules = FALSE; + + ve_config_set_string (ve_config_get (GDM_CONFIG_FILE), + GDM_KEY_GTK_MODULES_LIST, + ve_sure_string (modules_list)); + ve_config_set_bool (ve_config_get (GDM_CONFIG_FILE), + GDM_KEY_ADD_GTK_MODULES, + add_gtk_modules); + + g_free (modules_list); + + update_key (GDM_KEY_GTK_MODULES_LIST); + update_key (GDM_KEY_ADD_GTK_MODULES); +} + +static void +setup_accessibility_support (void) +{ + GtkWidget *acc_modules = glade_helper_get (xml, "acc_modules", GTK_TYPE_TOGGLE_BUTTON); + GtkWidget *acc_sound_test = glade_helper_get (xml, "acc_sound_test", GTK_TYPE_BUTTON); + GtkWidget *acc_sound_file_entry = glade_helper_get (xml, "acc_sound_file_entry", GTK_TYPE_ENTRY); + + gboolean add_gtk_modules = ve_config_get_bool (ve_config_get (GDM_CONFIG_FILE), + GDM_KEY_ADD_GTK_MODULES); + char *modules_list = ve_config_get_string (ve_config_get (GDM_CONFIG_FILE), + GDM_KEY_GTK_MODULES_LIST); + + if (add_gtk_modules && + modules_list_contains (modules_list, "gail") && + modules_list_contains (modules_list, "atk-bridge") && + modules_list_contains (modules_list, "dwellmouselistener") && + modules_list_contains (modules_list, "keymouselistener")) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (acc_modules), + TRUE); + } else { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (acc_modules), + FALSE); + } + + g_signal_connect (G_OBJECT (acc_modules), "toggled", + G_CALLBACK (acc_modules_toggled), + NULL); + g_signal_connect (G_OBJECT (acc_sound_test), "clicked", + G_CALLBACK (test_sound), + acc_sound_file_entry); +} + +static void background_toggled (void) { GtkWidget *no_bg = glade_helper_get (xml, "sg_no_bg_rb", GTK_TYPE_TOGGLE_BUTTON); @@ -2148,8 +2368,11 @@ setup_gui (void) glade_helper_tagify_label (xml, "gg_desc_label", "b"); glade_helper_tagify_label (xml, "gg_copyright_label", "b"); + glade_helper_tagify_label (xml, "acc_options_cat_label", "b"); + glade_helper_tagify_label (xml, "enable_xdmcp", "b"); + setup_accessibility_support (); setup_xdmcp_support (); setup_background_support (); setup_greeter_backselect (); @@ -2227,10 +2450,18 @@ setup_gui (void) GDM_KEY_DISALLOWTCP, GDM_KEY_DISALLOWTCP /* notify_key */); - /* setup sensitivities */ + /* security sensitivities */ setup_sensitivity_positive_toggle ("sysmenu", "config_available"); setup_sensitivity_positive_toggle ("sysmenu", "chooser_button"); + setup_greeter_toggle ("acc_beep", + GDM_KEY_SOUND_ON_LOGIN); + setup_notify_entry ("acc_sound_file_entry", + GDM_KEY_SOUND_ON_LOGIN_FILE); + + /* accesibility sensitivities */ + setup_sensitivity_positive_toggle ("acc_beep", "acc_sound_file_box"); + setup_notify_toggle ("enable_xdmcp", GDM_KEY_XDMCP, GDM_KEY_XDMCP /* notify_key */); @@ -2485,6 +2716,13 @@ main (int argc, char *argv[]) * ui? Say it ain't so. Our config sections are SUCH A MESS */ GdmMinimalUID = ve_config_get_int (ve_config_get (GDM_CONFIG_FILE), GDM_KEY_MINIMALUID); + GdmSoundProgram = ve_config_get_string (ve_config_get (GDM_CONFIG_FILE), + GDM_KEY_SOUND_PROGRAM); + if (ve_string_empty (GdmSoundProgram) || + access (GdmSoundProgram, X_OK) != 0) { + g_free (GdmSoundProgram); + GdmSoundProgram = NULL; + } setup_gui (); diff --git a/gui/gdmsetup.glade b/gui/gdmsetup.glade index c8f597f2..3ffbcb32 100644 --- a/gui/gdmsetup.glade +++ b/gui/gdmsetup.glade @@ -1918,33 +1918,101 @@ widget</property> </child> <child> - <widget class="GtkCheckButton" id="config_available"> + <widget class="GtkHBox" id="hbox17"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Allow c_onfiguration from the login screen</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label62"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="config_available"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Allow c_onfiguration from the login screen</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> </widget> <packing> <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> + <property name="expand">True</property> + <property name="fill">True</property> </packing> </child> <child> - <widget class="GtkCheckButton" id="chooser_button"> + <widget class="GtkHBox" id="hbox18"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Allo_w running XDMCP chooser from the login screen</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label63"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="chooser_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Allo_w running XDMCP chooser from the login screen</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> </widget> <packing> <property name="padding">0</property> @@ -2078,6 +2146,274 @@ widget</property> </child> <child> + <widget class="GtkVBox" id="vbox20"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">18</property> + + <child> + <widget class="GtkVBox" id="vbox21"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="acc_options_cat_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Options</property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox16"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label61"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox22"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkCheckButton" id="acc_modules"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Enable _accessibility modules</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="acc_beep"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Make a _sound when login window is ready</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox19"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label64"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="acc_sound_file_box"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + <accessibility> + <atkproperty name="AtkObject::accessible_name" translatable="yes">acc_sound_file_box</atkproperty> + </accessibility> + + <child> + <widget class="GtkLabel" id="label65"> + <property name="visible">True</property> + <property name="label" translatable="yes">Sound _file:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">acc_sound_file_entry</property> + <accessibility> + <atkrelation target="acc_sound_test" type="label-for"/> + <atkrelation target="acc_sound_file_entry" type="label-for"/> + </accessibility> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GnomeFileEntry" id="acc_sound_file"> + <property name="visible">True</property> + <property name="max_saved">10</property> + <property name="directory_entry">False</property> + <property name="modal">False</property> + + <child internal-child="entry"> + <widget class="GtkEntry" id="acc_sound_file_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="acc_sound_test"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Test sound</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label59"> + <property name="visible">True</property> + <property name="label" translatable="yes">Accessibility</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> <widget class="GtkVBox" id="vbox1"> <property name="border_width">5</property> <property name="visible">True</property> diff --git a/gui/greeter/greeter.c b/gui/greeter/greeter.c index 96222f52..8c00341a 100644 --- a/gui/greeter/greeter.c +++ b/gui/greeter/greeter.c @@ -73,6 +73,9 @@ gchar *GdmServAuthDir; gchar *GdmInfoMsgFile; gchar *GdmInfoMsgFont; gint GdmFlexiReapDelayMinutes; +gboolean GdmSoundOnLogin; +gchar *GdmSoundOnLoginFile; +gchar *GdmSoundProgram; gboolean GdmUseCirclesInEntry = FALSE; @@ -194,6 +197,10 @@ greeter_parse_config (void) GdmGlobalFaceDir = ve_config_get_string (config, GDM_KEY_FACEDIR); GdmDefaultFace = ve_config_get_string (config, GDM_KEY_FACE); + GdmSoundProgram = ve_config_get_string (config, GDM_KEY_SOUND_PROGRAM); + GdmSoundOnLogin = ve_config_get_bool (config, GDM_KEY_SOUND_ON_LOGIN); + GdmSoundOnLoginFile = ve_config_get_string (config, GDM_KEY_SOUND_ON_LOGIN_FILE); + if (GdmXineramaScreen < 0) GdmXineramaScreen = 0; if (GdmIconMaxWidth < 0) GdmIconMaxWidth = 128; @@ -261,7 +268,7 @@ greeter_ctrl_handler (GIOChannel *source, tmp = ve_locale_to_utf8 (buf); if (tmp != NULL && strcmp (tmp, _("Username:")) == 0) { - gdk_beep (); + gdm_common_login_sound (); greeter_probably_login_prompt = TRUE; } else { greeter_probably_login_prompt = FALSE; @@ -818,9 +825,13 @@ greeter_reread_config (int sig, gpointer data) _exit (DISPLAY_RESTARTGREETER); } + GdmSoundProgram = ve_config_get_string (config, GDM_KEY_SOUND_PROGRAM); + GdmSoundOnLogin = ve_config_get_bool (config, GDM_KEY_SOUND_ON_LOGIN); + GdmSoundOnLoginFile = ve_config_get_string (config, GDM_KEY_SOUND_ON_LOGIN_FILE); + if ( ! gdm_common_bool_same (config, - GdmUse24Clock, - GDM_KEY_USE_24_CLOCK)) { + GdmUse24Clock, + GDM_KEY_USE_24_CLOCK)) { GdmUse24Clock = ve_config_get_bool (config, GDM_KEY_USE_24_CLOCK); greeter_item_clock_update (); diff --git a/gui/greeter/greeter_configuration.h b/gui/greeter/greeter_configuration.h index bb3c5198..79df729b 100644 --- a/gui/greeter/greeter_configuration.h +++ b/gui/greeter/greeter_configuration.h @@ -32,6 +32,9 @@ extern gchar *GdmWelcome; extern gchar *GdmServAuthDir; extern gchar *GdmInfoMsgFile; extern gchar *GdmInfoMsgFont; +extern gchar *GdmSoundProgram; +extern gchar *GdmSoundOnLoginFile; +extern gboolean GdmSoundOnLogin; extern gboolean GDM_IS_LOCAL; extern gboolean DOING_GDM_DEVELOPMENT; |