Fast User Switching gdm patch
- From: Ed Palmer <ed LONESTAR ORG>
- To: gdm sunsite dk
- Subject: Fast User Switching gdm patch
- Date: Fri, 13 Sep 2002 20:20:35 +0000
This patch to gdm emulates Windows XP's "Fast User Switching", which i
call "Multiple Desktops". Here's an example case:
user 1 logs in-> assigned to vt 7
user 1 runs "gdmflexiserver", starts new xnest on vt 8
user 2 logs in on vt 8
user 2 runs "gdmflexiserver", starts new xnest on vt 9
user 1 logs in-> screen switches to vt 7 , gdmlogin keeps running
user 1 runs "gdmflexiserver", vt switches to vt 9 revealing gdm login
screen
I'd appreciate any feedback. The patch is against -11 from aug 30
don't know about cvs.
cat FastUserSwitching.diff | patch -p0
from the gdm-...-11 directory you want to patch...
--
\--- === E D P A L M E R
\ | |_|
/--- | http://ed.freeshell.org
diff -C 3 -r daemon/gdm.c ../gdm-2.4.0.11NEWEST/daemon/gdm.c
*** daemon/gdm.c Tue Aug 27 21:03:35 2002
--- ../gdm-2.4.0.11NEWEST/daemon/gdm.c Fri Sep 13 15:49:56 2002
***************
*** 64,69 ****
--- 64,74 ----
static void gdm_safe_restart (void);
static void gdm_restart_now (void);
+ #ifdef __linux__
+ GdmDisplay * login_what_display (char *login);
+ #endif
+
+
/* Global vars */
GSList *displays = NULL; /* List of displays managed */
GSList *xservers = NULL; /* List of x server definitions */
***************
*** 161,167 ****
gchar *GdmXnest = NULL;
int GdmFirstVT = 7;
gboolean GdmVTAllocation = TRUE;
!
/* set in the main function */
char **stored_argv = NULL;
--- 166,172 ----
gchar *GdmXnest = NULL;
int GdmFirstVT = 7;
gboolean GdmVTAllocation = TRUE;
! gboolean GdmMultipleDesktops = TRUE;
/* set in the main function */
char **stored_argv = NULL;
***************
*** 315,320 ****
--- 320,328 ----
GdmVTAllocation = gnome_config_get_bool (GDM_KEY_VTALLOCATION);
GdmDebug = gnome_config_get_bool (GDM_KEY_DEBUG);
+
+ GdmMultipleDesktops = gnome_config_get_bool (GDM_KEY_MULTIPLE_DESKTOPS);
+
gnome_config_pop_prefix();
***************
*** 2765,2768 ****
--- 2773,2830 ----
}
}
+
+
+ #ifdef __linux__
+ /* returns
+ GdmDisplay * pointing to a display with a currently running greeter
+ or NULL
+ */
+ GdmDisplay *
+ find_available_greeter ()
+ {
+ GSList *li;
+
+ for (li = displays; li !=NULL; li=li->next) {
+ GdmDisplay *disp = li->data;
+ if (disp == NULL)
+ gdm_error("find_avialable_greeter: null display in displays list");
+ if ( ( disp->login == NULL || !strlen(disp->login) )
+ && disp->vt > 0 )
+ return disp;
+ }
+
+ return NULL;
+ }
+
+ /* what display is this login logged in on (if any) else NULL */
+ GdmDisplay *
+ login_what_display (char *login)
+ {
+ GSList *li;
+
+ if (login==NULL) {
+ gdm_error("login_what_display: attempted to pass null login");
+ return NULL;
+ }
+
+ for (li = displays; li !=NULL; li=li->next) {
+ GdmDisplay *disp = li->data;
+ if (disp==NULL) {
+ gdm_debug("login_what_display: disp is NULL");
+ } else if (disp->login==NULL) {
+ /* do nothing */
+
+ } else if (strcmp(login, disp->login) == 0) {
+ gdm_debug("login_what_display: (%s) is on vt %d", login, disp->vt);
+ return disp;
+ }
+ }
+ return NULL;
+ }
+
+ #endif
+
+
+
/* EOF */
diff -C 3 -r daemon/gdm.h ../gdm-2.4.0.11NEWEST/daemon/gdm.h
*** daemon/gdm.h Fri Aug 23 13:02:11 2002
--- ../gdm-2.4.0.11NEWEST/daemon/gdm.h Fri Sep 13 14:32:43 2002
***************
*** 151,156 ****
--- 151,158 ----
#define GDM_KEY_UAUTHFILE "daemon/UserAuthFile=.Xauthority"
#define GDM_KEY_USER "daemon/User=gdm"
+ #define GDM_KEY_MULTIPLE_DESKTOPS "daemon/MultipleDesktops=true"
+
/* This defaults to true for backward compatibility,
* it will not actually do timed login since the TimedLogin defaults
* to nothing */
***************
*** 623,628 ****
--- 625,635 ----
* from a local display we started */
};
+ #ifdef __linux__
+ GdmDisplay * login_what_display (char *login);
+ GdmDisplay * find_available_greeter (void);
+ #endif
+
#endif /* GDM_H */
/* EOF */
diff -C 3 -r daemon/misc.c ../gdm-2.4.0.11NEWEST/daemon/misc.c
*** daemon/misc.c Fri Aug 30 14:51:06 2002
--- ../gdm-2.4.0.11NEWEST/daemon/misc.c Fri Sep 13 14:16:09 2002
***************
*** 143,149 ****
va_start (args, format);
s = g_strdup_vprintf (format, args);
va_end (args);
!
do_syslog (LOG_INFO, s);
g_free (s);
--- 143,149 ----
va_start (args, format);
s = g_strdup_vprintf (format, args);
va_end (args);
!
do_syslog (LOG_INFO, s);
g_free (s);
***************
*** 187,202 ****
{
va_list args;
char *s;
!
if ( ! GdmDebug)
! return;
va_start (args, format);
s = g_strdup_vprintf (format, args);
va_end (args);
do_syslog (LOG_ERR, s); /* Maybe should be LOG_DEBUG, but then normally
! * you wouldn't get it in the log. ??? */
g_free (s);
}
--- 187,202 ----
{
va_list args;
char *s;
!
if ( ! GdmDebug)
! return;
va_start (args, format);
s = g_strdup_vprintf (format, args);
va_end (args);
do_syslog (LOG_ERR, s); /* Maybe should be LOG_DEBUG, but then normally
! /* you wouldn't get it in the log. ??? */
g_free (s);
}
diff -C 3 -r daemon/server.c ../gdm-2.4.0.11NEWEST/daemon/server.c
*** daemon/server.c Fri Aug 30 15:18:51 2002
--- ../gdm-2.4.0.11NEWEST/daemon/server.c Fri Sep 13 14:16:09 2002
***************
*** 340,372 ****
return FALSE;
}
static int
display_vt (GdmDisplay *disp)
{
char *logname = g_strconcat (GdmLogDir, "/", d->name, ".log", NULL);
FILE *fp;
char buf[256];
fp = fopen (logname, "r");
g_free (logname);
!
! if (fp == NULL)
! return FALSE;
!
while (fgets (buf, sizeof (buf), fp) != NULL) {
! int vt;
! /* Note: this is probably XFree86 specific, and perhaps even
! * version 3 specific (I don't have xfree v4 to test this),
! * of course additions are welcome to make this more robust */
! if (sscanf (buf, "(using VT number %d)", &vt) == 1) {
fclose (fp);
return vt;
}
}
fclose (fp);
return -1;
}
static void
check_child_status (void)
{
--- 340,421 ----
return FALSE;
}
+ /* Read a fp looking for vt info, returning it if necessary
+ * Add additional */
+ static int
+ parse_vt (char *buf) {
+
+ int vt;
+
+ if ( (sscanf (buf, "(using VT number %d)", &vt) == 1) ||
+ /* Note: this is probably XFree86 specific, and perhaps even
+ * version 3 specific (I don't have xfree v4 to test this),
+ * of course additions are welcome to make this more robust */
+ /* I noticed it in 4.0 as well */
+ (sscanf (buf, "Using vt %d", &vt) == 1) ||
+ /* this is what works for some 4.2's... namely Mandrake 9.0 Beta 4
+ * however, Redhat 7.2's 4.2 server doesn't put this info in the gdm info file */
+ (sscanf (buf, "(--) using VT number %d", &vt) == 1) /* from 4.2 Xserver log */
+ )
+ return vt;
+
+ else return -1;
+
+ }
+
+ /* Read the gdm log file looking for the vt, continuing to the XServer log if necessary
+ * Returns vt, or -1 on failure */
static int
display_vt (GdmDisplay *disp)
{
char *logname = g_strconcat (GdmLogDir, "/", d->name, ".log", NULL);
FILE *fp;
char buf[256];
+
+ char xserver_logfile[256];
+ xserver_logfile[0]=0;
fp = fopen (logname, "r");
g_free (logname);
!
while (fgets (buf, sizeof (buf), fp) != NULL) {
! int vt=-1;
!
! sscanf (buf, "(==) Log file: \"%[^\"]\"", xserver_logfile);
!
! if ( (vt=parse_vt(buf))!=-1 ){
fclose (fp);
+ gdm_debug("display_vt: found vt=%d in gdm log", vt);
return vt;
}
}
fclose (fp);
+
+ if (strlen (xserver_logfile)) {
+ /* we didn't find a vt listed in the gdm log, lets try the XServer log itself */
+ gdm_debug("display_vt: continuing on to XServer log [%s]", xserver_logfile);
+ fp = fopen (xserver_logfile, "r");
+
+ if (fp == NULL)
+ return -1;
+
+ while (fgets (buf, sizeof (buf), fp) != NULL) {
+ int vt=-1;
+ if ( (vt=parse_vt(buf))!=-1 ){
+ fclose (fp);
+ gdm_debug("display_vt: found vt=%d in XServer log", vt);
+ return vt;
+ }
+ }
+ fclose (fp);
+ }
+
+ gdm_debug("display_vt: unable to set the vt");
return -1;
}
+
+
static void
check_child_status (void)
{
diff -C 3 -r daemon/slave.c ../gdm-2.4.0.11NEWEST/daemon/slave.c
*** daemon/slave.c Fri Aug 30 14:53:43 2002
--- ../gdm-2.4.0.11NEWEST/daemon/slave.c Fri Sep 13 15:52:07 2002
***************
*** 63,68 ****
--- 63,73 ----
#include "choose.h"
#include "errorgui.h"
+ #ifdef __linux__
+ #include <sys/ioctl.h>
+ #include <linux/vt.h>
+ #endif
+
/* Some per slave globals */
static GdmDisplay *d;
static gchar *login = NULL;
***************
*** 135,141 ****
extern gboolean GdmAllowRemoteRoot;
extern gchar *GdmGlobalFaceDir;
extern gboolean GdmDebug;
!
/* Local prototypes */
static gint gdm_slave_xerror_handler (Display *disp, XErrorEvent *evt);
--- 140,146 ----
extern gboolean GdmAllowRemoteRoot;
extern gchar *GdmGlobalFaceDir;
extern gboolean GdmDebug;
! extern gboolean GdmMultipleDesktops;
/* Local prototypes */
static gint gdm_slave_xerror_handler (Display *disp, XErrorEvent *evt);
***************
*** 162,167 ****
--- 167,176 ----
static void create_temp_auth_file (void);
static void set_xnest_parent_stuff (void);
+ #ifdef __linux__
+ static int vt_switch (int switchto);
+ #endif
+
/* Yay thread unsafety */
static gboolean x_error_occured = FALSE;
static gboolean gdm_got_ack = FALSE;
***************
*** 249,258 ****
--- 258,283 ----
time_t first_time;
int death_count;
struct sigaction alrm, term, child, usr2;
+ #ifdef __linux__
+ GdmDisplay *tmp_disp = find_available_greeter ();
+ #endif
if (!display)
return;
+ #ifdef __linux__
+ /* if display is xnest, and we have an available greeter just go there and kill this slave */
+ if (GdmMultipleDesktops &&
+ display->type == TYPE_FLEXI && tmp_disp != NULL) {
+ gdm_debug("gdm_slave_start: will not start new greeter. switching to %d.", tmp_disp->vt);
+
+ if (vt_switch (tmp_disp->vt)) {
+ display->login=NULL;
+ return;
+ }
+ } else { gdm_debug("gdm_slave_start: no available greeter. starting new one of type [%d]", display->type ); }
+ #endif
+
gdm_debug ("gdm_slave_start: Starting slave process for %s", display->name);
if (display->type == TYPE_XDMCP &&
GdmPingInterval > 0) {
***************
*** 324,332 ****
gdm_debug ("gdm_slave_start: Loop Thingie");
gdm_slave_run (display);
! /* remote and flexi only run once */
if (display->type != TYPE_LOCAL)
break;
the_time = time (NULL);
--- 349,376 ----
gdm_debug ("gdm_slave_start: Loop Thingie");
gdm_slave_run (display);
!
! #ifdef __linux__
! if (display->type != TYPE_LOCAL &&
! display->type != TYPE_FLEXI )
! break;
! /* remote display always exits here */
!
! /* we will continue if there are no other available greeters on other displays */
! d=find_available_greeter();
! if (GdmMultipleDesktops && display->type != TYPE_LOCAL && d != NULL && d->vt > 0 && d->vt != display->vt) {
! /* switch to that display then break out of here */
! if ( vt_switch(d->vt) ) {
! gdm_debug("gdm_slave_start: another suitable greeter was found. exiting");
! break;
! }
! }
! #else
! /* otherwise remote and flexi only run once */
if (display->type != TYPE_LOCAL)
break;
+ #endif
+
the_time = time (NULL);
***************
*** 676,681 ****
--- 720,728 ----
gdm_first_login = FALSE;
do {
+ #ifdef __linux__
+ GdmDisplay *disp;
+ #endif
check_notifies_now ();
if ( ! greet) {
***************
*** 685,690 ****
--- 732,742 ----
}
gdm_slave_wait_for_login (); /* wait for a password */
+ #ifdef __linux__
+ disp=login_what_display(login);
+ if (disp==NULL) gdm_debug("disp is NULL");
+ else gdm_debug("disp on %d", disp->vt);
+ #endif
d->logged_in = TRUE;
gdm_slave_send_num (GDM_SOP_LOGGED_IN, TRUE);
***************
*** 697,703 ****
ParsedTimedLogin);
gdm_slave_session_start ();
}
! } else {
gdm_slave_send_string (GDM_SOP_LOGIN, login);
gdm_slave_session_start ();
}
--- 749,768 ----
ParsedTimedLogin);
gdm_slave_session_start ();
}
! }
!
! #ifdef __linux__
! else if ( GdmMultipleDesktops && disp!=NULL && disp->vt>=0 &&
! vt_switch(disp->vt) ){
! /* this user is already logged in! (and has a valid vt we switched to) */
! gdm_debug("found login for '%s' on vt=%d",
! login, disp->vt);
! gdm_slave_greeter_ctl_no_ret (GDM_ENABLE, "");
! gdm_slave_greeter_ctl_no_ret (GDM_RESETOK, "");
! }
! #endif
! /* fall through to normal login */
! else {
gdm_slave_send_string (GDM_SOP_LOGIN, login);
gdm_slave_session_start ();
}
***************
*** 3809,3812 ****
--- 3874,3896 ----
return TRUE;
}
+
+ #ifdef __linux__
+ /* switch to vt "switchto"
+ there is a linux utility "chvt", should that be used instead? */
+ static int
+ vt_switch (int switchto)
+ {
+ int fd;
+
+ fd = open("/dev/console", O_RDWR);
+
+ if (ioctl(fd, VT_ACTIVATE, switchto)) {
+ gdm_error("vt_switch: unable to switch to vt %d", switchto);
+ return (0);
+ }
+ return 1;
+ }
+ #endif
+
/* EOF */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]