Blame SOURCES/kde-workspace-4.11.1-kdm_plymouth081.patch

ff3475
diff --git a/kdm/backend/dm.c b/kdm/backend/dm.c
ff3475
index e0f1366..5a5f8a7 100644
ff3475
--- a/kdm/backend/dm.c
ff3475
+++ b/kdm/backend/dm.c
ff3475
@@ -1347,54 +1347,207 @@ getBusyVTs(void)
ff3475
     return activeVTs;
ff3475
 }
ff3475
 
ff3475
+static int
ff3475
+get_active_vt (void)
ff3475
+{
ff3475
+        int console_fd;
ff3475
+        struct vt_stat console_state = { 0 };
ff3475
+        console_fd = open ("/dev/tty0", O_RDONLY | O_NOCTTY);
ff3475
+        if (console_fd < 0) {
ff3475
+                return 0;
ff3475
+        }
ff3475
+        ioctl (console_fd, VT_GETSTATE, &console_state);
ff3475
+
ff3475
+        close (console_fd);
ff3475
+        return console_state.v_active;
ff3475
+}
ff3475
+
ff3475
+static int
ff3475
+plymouth_is_running (void)
ff3475
+{
ff3475
+        static int running = -1;
ff3475
+        if (running == 0)
ff3475
+            return 0;
ff3475
+
ff3475
+        int status;
ff3475
+        status = system ("/usr/bin/plymouth --ping");
ff3475
+
ff3475
+        running = WIFEXITED (status) && WEXITSTATUS (status) == 0;
ff3475
+        logWarn ("plymouth is %srunning\n", running?"":"NOT ");
ff3475
+        return running;
ff3475
+}
ff3475
+
ff3475
+static int
ff3475
+plymouth_has_active_vt (void)
ff3475
+{
ff3475
+        int status;
ff3475
+        status = system ("/usr/bin/plymouth --has-active-vt");
ff3475
+
ff3475
+        return WIFEXITED (status) && WEXITSTATUS (status) == 0;
ff3475
+}
ff3475
+
ff3475
+static int
ff3475
+plymouth_prepare_for_transition (void)
ff3475
+{
ff3475
+        int status;
ff3475
+        status = system ("/usr/bin/plymouth deactivate");
ff3475
+
ff3475
+        return WIFEXITED (status) && WEXITSTATUS (status) == 0;
ff3475
+}
ff3475
+
ff3475
+int
ff3475
+plymouth_quit_with_transition (void)
ff3475
+{
ff3475
+        int status;
ff3475
+        status = system ("/usr/bin/plymouth --wait quit --retain-splash");
ff3475
+
ff3475
+        return WIFEXITED (status) && WEXITSTATUS (status) == 0;
ff3475
+}
ff3475
+
ff3475
+int
ff3475
+plymouth_quit_without_transition (void)
ff3475
+{
ff3475
+        int status;
ff3475
+        status = system ("/usr/bin/plymouth --wait quit");
ff3475
+
ff3475
+        return WIFEXITED (status) && WEXITSTATUS (status) == 0;
ff3475
+}
ff3475
+
ff3475
+static int
ff3475
+triggered_to_force_display_on_active_vt (void)
ff3475
+{
ff3475
+   int should_force_display_on_active_vt;
ff3475
+   should_force_display_on_active_vt=open("/var/spool/gdm/force-display-on-active-vt", O_RDONLY);
ff3475
+   if ( should_force_display_on_active_vt >= 0 )
ff3475
+       close(should_force_display_on_active_vt);
ff3475
+   unlink("/var/spool/gdm/force-display-on-active-vt");
ff3475
+   return should_force_display_on_active_vt;
ff3475
+}
ff3475
+
ff3475
 static void
ff3475
 allocateVT(struct display *d)
ff3475
 {
ff3475
     struct display *cd;
ff3475
-    int i, tvt, volun;
ff3475
+    int i, tvt;
ff3475
 
ff3475
     if ((d->displayType & d_location) == dLocal &&
ff3475
         d->status == notRunning && !d->serverVT && d->reqSrvVT >= 0)
ff3475
     {
ff3475
+        /* Try to find the correct VT.
ff3475
+         * If ServerVT is specified in the config, use it (if the admin used the
ff3475
+         * same VT for multiple display, it is his/her own fault, no checks done).
ff3475
+         * Otherwise, walk the list of specified VTs. Positive numbers are used
ff3475
+         * even if the VT is already in use by a tty. Negative numbers and 
ff3475
+         * unspecified numbers (up to #15) are used if not already in use.
ff3475
+         * VTs already in use (cd->serverVT) or requested (cd->reqSrvVT)
ff3475
+         * by any display are skipped.
ff3475
+         */
ff3475
+
ff3475
+        /* some special handling is needed for Plymouth:
ff3475
+         * if no VT is requested, use the active VT from plymouth for the first
ff3475
+         * started display.
ff3475
+         * If the display takes over the VT from plymouth, deactivate plymouth
ff3475
+         */
ff3475
+
ff3475
+        char allowedVTs[16] = { 0 };
ff3475
         if (d->reqSrvVT && d->reqSrvVT < 16) {
ff3475
-            d->serverVT = d->reqSrvVT;
ff3475
+            allowedVTs[d->reqSrvVT] = 1;
ff3475
         } else {
ff3475
-            for (i = tvt = 0;;) {
ff3475
-                if (serverVTs[i]) {
ff3475
-                    tvt = atoi(serverVTs[i++]);
ff3475
-                    volun = False;
ff3475
-                    if (tvt < 0) {
ff3475
-                        tvt = -tvt;
ff3475
-                        volun = True;
ff3475
-                    }
ff3475
-                    if (!tvt || tvt >= 16)
ff3475
-                        continue;
ff3475
-                } else {
ff3475
-                    if (++tvt >= 16)
ff3475
-                        break;
ff3475
-                    volun = True;
ff3475
+            for (i = 0; serverVTs[i]; i++) {
ff3475
+                tvt = atoi(serverVTs[i]);
ff3475
+                if ((tvt >= 0) && (tvt < 16)) {
ff3475
+                    allowedVTs[tvt] = 1;
ff3475
+                } else if (tvt > -16) {
ff3475
+                    allowedVTs[-tvt] = 2;
ff3475
                 }
ff3475
-                for (cd = displays; cd; cd = cd->next) {
ff3475
-                    if (cd->reqSrvVT == tvt && /* protect from lusers */
ff3475
-                            (cd->status != zombie || cd->zstatus != DS_REMOVE))
ff3475
-                        goto next;
ff3475
-                    if (cd->serverVT == tvt) {
ff3475
-                        if (cd->status != zombie || cd->zstatus == DS_REMOTE)
ff3475
-                            goto next;
ff3475
-                        if (!cd->follower) {
ff3475
-                            d->serverVT = -1;
ff3475
-                            cd->follower = d;
ff3475
-                            return;
ff3475
-                        }
ff3475
-                    }
ff3475
+            }
ff3475
+
ff3475
+            for (tvt = 15; allowedVTs[tvt] == 0; tvt--) {
ff3475
+              allowedVTs[tvt] = 2;
ff3475
+            }
ff3475
+
ff3475
+            for (cd = displays; cd; cd = cd->next) {
ff3475
+                if (cd->status != zombie) {
ff3475
+                    if (cd->reqSrvVT >= 0) allowedVTs[cd->reqSrvVT] = 0;
ff3475
+                    if (cd->serverVT >= 0) allowedVTs[cd->serverVT] = 0;
ff3475
+                } else if (cd->zstatus == DS_REMOTE) {
ff3475
+                    /* dying, but will spawn new server for remote login */
ff3475
+                    if (cd->serverVT >= 0) allowedVTs[cd->serverVT] = 0;
ff3475
+                } else if (cd->zstatus != DS_REMOVE) {
ff3475
+                    /* dying, but will be restarted or reserved */
ff3475
+                    if (cd->reqSrvVT >= 0) allowedVTs[cd->reqSrvVT] = 0;
ff3475
                 }
ff3475
-                if (!volun || !((1 << tvt) & getBusyVTs())) {
ff3475
-                    d->serverVT = tvt;
ff3475
+            }
ff3475
+        }
ff3475
+
ff3475
+        /* check for plymouth using newer methods */
ff3475
+        d->plymouth_vt = -1;
ff3475
+        if (plymouth_is_running ()) {
ff3475
+            if (plymouth_has_active_vt ()) {
ff3475
+                int vt = get_active_vt ();
ff3475
+                if (allowedVTs[vt]) {
ff3475
+                    logWarn ("plymouth is active on VT %d, reusing for %s\n", vt, d->name);
ff3475
+                    d->serverVT = vt;
ff3475
+                    d->plymouth_vt = vt;
ff3475
                     return;
ff3475
                 }
ff3475
-          next: ;
ff3475
+            }
ff3475
+        /* fallback to old/deprecated method */
ff3475
+        } else if ( triggered_to_force_display_on_active_vt() >= 0 ) {
ff3475
+            int vt = get_active_vt ();
ff3475
+            if (allowedVTs[vt]) {
ff3475
+                d->serverVT = vt;
ff3475
+                return;
ff3475
+            }
ff3475
+        }
ff3475
+
ff3475
+        for (tvt = 0; tvt < 16; tvt++) {
ff3475
+            if ((allowedVTs[tvt] == 1) ||
ff3475
+                ((allowedVTs[tvt] == 2) && !((1 << tvt) & getBusyVTs()))) {
ff3475
+                d->serverVT = tvt;
ff3475
+                return;
ff3475
             }
ff3475
         }
ff3475
+
ff3475
+        for (cd = displays; cd; cd = cd->next) {
ff3475
+            if ((cd->status == zombie) && (cd->zstatus != DS_REMOTE) &&
ff3475
+                (cd->follower == 0) && (cd->reqSrvVT != cd->serverVT)) {
ff3475
+            /* removed; or restarted/reserved on any VT */
ff3475
+                    d->serverVT = -1;
ff3475
+                    cd->follower = d;
ff3475
+                    return;
ff3475
+            }
ff3475
+        }
ff3475
+    }
ff3475
+}
ff3475
+
ff3475
+static void
ff3475
+replacePlymouth(void)
ff3475
+{
ff3475
+    struct display *cd;
ff3475
+
ff3475
+    /* if one display reuses plymouth' VT, plymouth is stopped in the
ff3475
+     * startServerSuccess/Failed callback (see server.c). In any other
ff3475
+     * case plymouth is stopped now.
ff3475
+     */
ff3475
+    for (cd = displays; cd; cd = cd->next) {
ff3475
+        if ((cd->serverVT > 0) && (cd->serverVT == cd->plymouth_vt)) {
ff3475
+            if (cd->status == notRunning) {
ff3475
+                /* tell plymouth to quit when server has started */
ff3475
+                logWarn ("plymouth should quit after server startup\n");
ff3475
+                plymouth_prepare_for_transition ();
ff3475
+                kickDisplay(cd);
ff3475
+                return;
ff3475
+            } else if (cd->status == running) {
ff3475
+                /* replacing server is starting up, do nothing */
ff3475
+                return;
ff3475
+            }
ff3475
+        }
ff3475
+    }
ff3475
+
ff3475
+    if ( plymouth_is_running ()) {
ff3475
+        plymouth_prepare_for_transition ();
ff3475
+        plymouth_quit_without_transition ();
ff3475
     }
ff3475
 }
ff3475
 #endif
ff3475
@@ -1407,6 +1560,7 @@ startDisplays(void)
ff3475
 #ifdef HAVE_VTS
ff3475
     activeVTs = -1;
ff3475
     forEachDisplayRev(allocateVT);
ff3475
+    replacePlymouth();
ff3475
 #endif
ff3475
     forEachDisplay(kickDisplay);
ff3475
 }
ff3475
diff --git a/kdm/backend/dm.h b/kdm/backend/dm.h
ff3475
index 64e106b..930af0e 100644
ff3475
--- a/kdm/backend/dm.h
ff3475
+++ b/kdm/backend/dm.h
ff3475
@@ -304,6 +304,8 @@ struct display {
ff3475
     int authNum;                /* number of authorizations */
ff3475
     char *authFile;             /* file to store authorization in */
ff3475
     char *greeterAuthFile;      /* file to store authorization for greeter in */
ff3475
+    
ff3475
+    int plymouth_vt;            /* Plymouth's VT nr */
ff3475
 };
ff3475
 
ff3475
 #define d_location   1
ff3475
@@ -428,6 +430,9 @@ int anyDisplaysLeft(void);
ff3475
 void forEachDisplay(void (*f)(struct display *));
ff3475
 #ifdef HAVE_VTS
ff3475
 void forEachDisplayRev(void (*f)(struct display *));
ff3475
+/* function for plymouth */
ff3475
+int plymouth_quit_with_transition (void);
ff3475
+int plymouth_quit_without_transition (void);
ff3475
 #endif
ff3475
 void removeDisplay(struct display *old);
ff3475
 struct display
ff3475
diff --git a/kdm/backend/server.c b/kdm/backend/server.c
ff3475
index d8dd6f3..8b4708e 100644
ff3475
--- a/kdm/backend/server.c
ff3475
+++ b/kdm/backend/server.c
ff3475
@@ -80,6 +80,7 @@ startServerOnce(void)
ff3475
     char **argv;
ff3475
 
ff3475
     debug("startServerOnce for %s, try %d\n", d->name, ++d->startTries);
ff3475
+
ff3475
     d->serverStatus = starting;
ff3475
     switch (Fork(&d->serverPid)) {
ff3475
     case 0:
ff3475
@@ -137,6 +138,12 @@ startServerSuccess()
ff3475
     struct display *d = startingServer;
ff3475
     d->serverStatus = ignore;
ff3475
     serverTimeout = TO_INF;
ff3475
+    if ((d->serverVT > 0) && (d->serverVT == d->plymouth_vt)) {
ff3475
+        int plymouth_running;
ff3475
+        logWarn ("Quitting Plymouth with transition\n" );
ff3475
+        plymouth_running = !plymouth_quit_with_transition ();
ff3475
+        logWarn ("Is Plymouth still running? %s\n", plymouth_running ? "yes" : "no");
ff3475
+    }
ff3475
     debug("X server ready, starting session\n");
ff3475
     startDisplayP2(d);
ff3475
 }
ff3475
@@ -154,6 +161,10 @@ startServerFailed()
ff3475
         startingServer = 0;
ff3475
         logError("X server for display %s cannot be started,"
ff3475
                  " session disabled\n", d->name);
ff3475
+        if ((d->serverVT > 0) && (d->serverVT == d->plymouth_vt)) {
ff3475
+            logWarn ("Quitting Plymouth without transition\n" );
ff3475
+            plymouth_quit_without_transition ();
ff3475
+        }
ff3475
         stopDisplay(d);
ff3475
     }
ff3475
 }