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

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