new splashscreens "none" and "simple"

Lubos Lunak <[email protected]>
Newsgroups gmane.comp.kde.devel.optimize
Message-ID <[email protected]>
 Hello,

 the attached patches reduce my KDE startup time 12s->11s (hot caches, 
3xKonsole,Klipper). The time is basically saved by avoiding ksplash 
altogether.

 The first new "splashscreen" is the none splashscreen. It's the most 
efficient splashscreen possible ;), and it's kinda boring (reminds of 
KDE1.x). The "simple" splashscreen actually even is a splashscreen, coded 
completely in Xlib, so it's very efficient. And it's also very tedious to 
code, just in case you wonder why it's only black&white and no texts. Since 
it doesn't use dcop, it needs also patching kded, ksmserver, kwin, kicker and 
kdesktop to send X messages about the progress.

 One thing I'd need to check is that I added it properly to KSplashML. It 
works for me, but I'm not sure it did it the way it's supposed to be, 
KSplashML seems to be a bit complicated for being just a splashscreen.

 And BTW, I don't propose that either of these splashscreens becomes the 
default.

 Comments?

-- 
Lubos Lunak
KDE developer
---------------------------------------------------------------------
SuSE CR, s.r.o.  e-mail: [email protected] , [email protected]
Drahobejlova 27  tel: +420 2 9654 2373
190 00 Praha 9   fax: +420 2 9654 2374
Czech Republic   http://www.suse.cz/

_______________________________________________
Kde-optimize mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/kde-optimize
ksplashml.patch (text/x-diff, 11.3 KB)
--- ksplashml/pics/themes/simple/Theme.rc.sav	2004-09-14 12:34:31.243170432 +0200
+++ ksplashml/pics/themes/simple/Theme.rc	2004-09-14 12:36:32.000000000 +0200
@@ -0,0 +1,7 @@
+# Default KSplash/ML Theme
+
+[KSplash Theme: Simple]
+Name = Simple Splash Screen
+Description = Very Simple Optimized Splash Screen
+Version = 1.0
+Author = Lubos Lunak <[email protected]>
--- ksplashml/pics/themes/simple/Makefile.am.sav	2004-09-14 12:34:28.470591928 +0200
+++ ksplashml/pics/themes/simple/Makefile.am	2004-09-14 12:35:36.643228112 +0200
@@ -0,0 +1,4 @@
+EXTRA_DIST=Theme.rc Preview.png
+
+ksplashml_pics_default_datadir = $(kde_datadir)/ksplash/Themes/Simple
+ksplashml_pics_default_data_DATA = $(EXTRA_DIST)
Soubory ksplashml/pics/themes/simple/Preview.png.sav a ksplashml/pics/themes/simple/Preview.png jsou různé
--- ksplashml/pics/themes/none/Theme.rc.sav	2004-09-14 12:34:35.582510752 +0200
+++ ksplashml/pics/themes/none/Theme.rc	2004-09-14 12:32:40.853952144 +0200
@@ -0,0 +1,6 @@
+# Default KSplash/ML Theme
+
+[KSplash Theme: None]
+Name = No Splash Screen
+Description = Splash Screen Turned Off
+Version = 1.0
--- ksplashml/pics/themes/none/Makefile.am.sav	2004-09-14 12:34:34.068740880 +0200
+++ ksplashml/pics/themes/none/Makefile.am	2004-09-14 12:31:35.442896136 +0200
@@ -0,0 +1,4 @@
+EXTRA_DIST=Theme.rc
+
+ksplashml_pics_default_datadir = $(kde_datadir)/ksplash/Themes/None
+ksplashml_pics_default_data_DATA = $(EXTRA_DIST)
--- ksplashml/themeengine/Makefile.am.sav	2003-10-06 22:50:50.000000000 +0200
+++ ksplashml/themeengine/Makefile.am	2004-09-14 12:53:47.000000000 +0200
@@ -1,4 +1,4 @@
-SUBDIRS = . default standard redmond
+SUBDIRS = . default standard redmond simple
 
 INCLUDES = -I$(srcdir)/.. $(all_includes)
 
diff -u -p -d -N -r -x Makefile -x Makefile.in -x Makefile.rules.in -x Makefile.calls.in -x '*~' ksplashml/themeengine/simple.sav/configure.in.in ksplashml/themeengine/simple/configure.in.in
--- ksplashml/themeengine/simple.sav/configure.in.in	1970-01-01 01:00:00.000000000 +0100
+++ ksplashml/themeengine/simple/configure.in.in	2004-09-14 13:03:42.350961584 +0200
@@ -0,0 +1,21 @@
+xinerama_save_ldflags="$LDFLAGS"
+LDFLAGS="$X_LDFLAGS"
+
+LIB_XINERAMA=
+
+KDE_CHECK_HEADER(X11/extensions/Xinerama.h,
+    [
+    AC_CHECK_LIB(Xinerama,XineramaQueryExtension,
+	[
+        AC_DEFINE(HAVE_XINERAMA, 1, [Define if you have the Xinerama extension])
+	LIB_XINERAMA="-lXinerama -lXext"
+        ],
+        [],
+        [ $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ])
+     ], [],
+     [
+     #include <X11/Xlib.h>
+     ] )
+
+AC_SUBST(LIB_XINERAMA)
+LDFLAGS="$xinerama_save_ldflags"
diff -u -p -d -N -r -x Makefile -x Makefile.in -x Makefile.rules.in -x Makefile.calls.in -x '*~' ksplashml/themeengine/simple.sav/main.cpp ksplashml/themeengine/simple/main.cpp
--- ksplashml/themeengine/simple.sav/main.cpp	1970-01-01 01:00:00.000000000 +0100
+++ ksplashml/themeengine/simple/main.cpp	2004-09-14 13:31:02.640599656 +0200
@@ -0,0 +1,169 @@
+/***************************************************************************
+ *   Copyright 2004 Lubos Lunak <[email protected]>                          *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License (version 2) as   *
+ *   published by the Free Software Foundation. (The original KSplash/ML   *
+ *   codebase (upto version 0.95.3) is BSD-licensed.)                      *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <config.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xinerama.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+
+//#define DEBUG
+
+int main( int argc, char* argv[])
+    {
+    if( fork() != 0 )
+        return 0;
+    Display* dpy = XOpenDisplay( NULL );
+    if( dpy == NULL )
+        return 1;
+    bool test = false;
+    if( argc == 2 && strcmp( argv[ 1 ], "--test" ) == 0 )
+        test = true;
+    int sx, sy, sw, sh;
+#ifdef HAVE_XINERAMA
+    // Xinerama code from Qt
+    XineramaScreenInfo *xinerama_screeninfo = 0;
+    int unused;
+    bool use_xinerama = XineramaQueryExtension( dpy, &unused, &unused )
+        && XineramaIsActive( dpy );
+    if (use_xinerama)
+        {
+        int screenCount;
+	xinerama_screeninfo = XineramaQueryScreens( dpy, &screenCount );
+        sx = xinerama_screeninfo[ 0 ].x_org;
+        sy = xinerama_screeninfo[ 0 ].y_org;
+        sw = xinerama_screeninfo[ 0 ].width;
+        sh = xinerama_screeninfo[ 0 ].height;
+        }
+    else
+#endif
+        {
+        sx = sy = 0;
+        sw = WidthOfScreen( ScreenOfDisplay( dpy, DefaultScreen( dpy )));
+	sh = HeightOfScreen( ScreenOfDisplay( dpy, DefaultScreen( dpy )));
+        }
+    XSetWindowAttributes attrs;
+    attrs.override_redirect = True;
+    const int states = 7;
+    const int frame = 3;
+    const int segment = sw / 2 / states;
+    const int w = segment * states + 2 * frame;
+    const int h = sh / 20 + frame;
+    Window win = XCreateWindow( dpy, DefaultRootWindow( dpy ), sx + ( sw - w ) / 2, sy + ( sh - h ) /2, w, h,
+        0, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attrs );
+    Pixmap pix = XCreatePixmap( dpy, DefaultRootWindow( dpy ), w, h, DefaultDepth( dpy, 0 ));
+    XGCValues values;
+    values.foreground = WhitePixel( dpy, 0 );
+    GC gc = XCreateGC( dpy, pix, GCForeground, &values );
+    XFillRectangle( dpy, pix, gc, 0, 0, w, h );
+    values.foreground = BlackPixel( dpy, 0 );
+    XChangeGC( dpy, gc, GCForeground, &values );
+//    XFillRectangle( dpy, pix, gc, 0, 0, w, frame );
+//    XFillRectangle( dpy, pix, gc, 0, h - frame, w, frame );
+//    XFillRectangle( dpy, pix, gc, 0, 0, frame, h );
+//    XFillRectangle( dpy, pix, gc, w - frame, 0, frame, h );
+    XSetWindowBackgroundPixmap( dpy, win, pix );
+    XSelectInput( dpy, win, ButtonPressMask );
+    XSelectInput( dpy, DefaultRootWindow( dpy ), SubstructureNotifyMask );
+    XMapWindow( dpy, win );
+    int pos = 0;
+    int state = 1; // cannot check dcop connection - make this state initial
+    const int delay = 10; // ms
+    time_t final_time = time( NULL ) + 60;
+    time_t test_time = time( NULL ) + 1;
+    Atom kde_splash_progress = XInternAtom( dpy, "_KDE_SPLASH_PROGRESS", False );
+    for(;;)
+        {
+        while( XPending( dpy ))
+            {
+            XEvent ev;
+            XNextEvent( dpy, &ev );
+            if( ev.type == ButtonPress && ev.xbutton.window == win )
+                {
+                final_time = time( NULL );
+                break;
+                }
+            if( ev.type == ConfigureNotify && ev.xconfigure.event == DefaultRootWindow( dpy ))
+                XRaiseWindow( dpy, win );
+            if( ev.type == ClientMessage && ev.xclient.window == DefaultRootWindow( dpy )
+                && ev.xclient.message_type == kde_splash_progress )
+                {
+                // based on ksplash
+                const char* s = ev.xclient.data.b;
+#ifdef DEBUG
+                fprintf( stderr,"MESSAGE: %s\n", s );
+#endif
+                if( strcmp( s, "dcop" ) == 0 && state < 1 )
+                    state = 1; // not actually used, state starts from 1, because dcop cannot be checked
+                else if( strcmp( s, "kded" ) == 0 && state < 2 )
+                    state = 2;
+                else if( strcmp( s, "kcminit" ) == 0 )
+                    ; // unused
+                else if( strcmp( s, "ksmserver" ) == 0 && state < 3 )
+                    state = 3;
+                else if( strcmp( s, "wm started" ) == 0 && state < 4 )
+                    state = 4;
+                else if( strcmp( s, "kdesktop" ) == 0 && state < 5 )
+                    state = 5;
+                else if( strcmp( s, "kicker" ) == 0 && state < 6 )
+                    state = 6;
+                else if( strcmp( s, "session ready" ) == 0 && state < 7 )
+                    state = 7;
+                }
+            }
+        if( test && time( NULL ) >= test_time )
+            {
+            ++state;
+            test_time = time( NULL ) + 1;
+            }
+        if( pos != state )
+            {
+            while( pos < state && pos < states )
+                {
+#ifdef DEBUG
+                fprintf( stderr, "POS: %d\n", pos );
+#endif
+                final_time = time( NULL ) + 60;
+                XFillRectangle( dpy, pix, gc, frame + pos * segment, frame, segment, h - 2 * frame );
+                XSetWindowBackgroundPixmap( dpy, win, pix );
+                XClearWindow( dpy, win );
+                ++pos;
+                if( pos >= states )
+                    {
+#ifdef DEBUG
+                    fprintf( stderr, "CLOSING DOWN\n" );
+#endif
+                    final_time = time( NULL ) + 2;
+                    }
+                }
+            }
+        fd_set set;
+        FD_ZERO( &set );
+        FD_SET( XConnectionNumber( dpy ), &set );
+        struct timeval tv;
+        tv.tv_sec = 0;
+        tv.tv_usec = delay * 1000;
+        select( XConnectionNumber( dpy ) + 1, &set, NULL, NULL, &tv );
+        if( time( NULL ) >= final_time )
+            {
+#ifdef DEBUG
+            fprintf( stderr, "EXITING\n" );
+#endif
+            break; // --->
+            }
+        }
+    XFreePixmap( dpy, pix );
+    XDestroyWindow( dpy, win );
+    XFreeGC( dpy, gc );
+    XCloseDisplay( dpy );
+    }
diff -u -p -d -N -r -x Makefile -x Makefile.in -x Makefile.rules.in -x Makefile.calls.in -x '*~' ksplashml/themeengine/simple.sav/Makefile.am ksplashml/themeengine/simple/Makefile.am
--- ksplashml/themeengine/simple.sav/Makefile.am	1970-01-01 01:00:00.000000000 +0100
+++ ksplashml/themeengine/simple/Makefile.am	2004-09-14 13:07:40.750719312 +0200
@@ -0,0 +1,7 @@
+
+INCLUDES = $(all_includes)
+
+bin_PROGRAMS = ksplashsimple
+ksplashsimple_SOURCES = main.cpp
+ksplashsimple_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+ksplashsimple_LDADD = $(LIB_XINERAMA) $(LIB_X11)
--- ksplashml/kcmksplash/installer.cpp.sav	2004-07-10 23:58:43.000000000 +0200
+++ ksplashml/kcmksplash/installer.cpp	2004-09-14 13:26:09.254201168 +0200
@@ -330,10 +330,10 @@ void SplashInstaller::slotSetTheme(int i
         path = mThemesList->text2path[path];
     enabled = false;
     KURL url;
+    QString themeName;
     if (!path.isEmpty())
     {
       // Make sure the correct plugin is installed.
-      QString themeName;
       int i = path.findRev('/');
       if (i >= 0)
         themeName = path.mid(i+1);
@@ -381,7 +381,7 @@ void SplashInstaller::slotSetTheme(int i
         error = i18n("Could not load theme configuration file.");
       }
     }
-    mBtnTest->setEnabled(enabled);
+    mBtnTest->setEnabled(enabled && themeName != "None" );
     mText->setText(infoTxt);
     if (!enabled)
     {
@@ -458,6 +458,17 @@ void SplashInstaller::slotTest()
   if (r >= 0)
     themeName = themeName.mid(r+1);
 
+  // special handling for none and simple splashscreens
+  if( themeName == "None" )
+    return;
+  if( themeName == "Simple" )
+  {
+    KProcess proc;
+    proc << "ksplashsimple" << "--test";
+    if (!proc.start(KProcess::Block))
+      KMessageBox::error(this,i18n("Unable to start ksplashsimple."));
+    return;
+  }
   KProcess proc;
   proc << "ksplash" << "--test" << "--theme" << themeName;
   if (!proc.start(KProcess::Block))
Preview.png (image/png, 52.1 KB) - not displayed
desktop.cc.patch (text/x-diff, 730 B)
--- desktop.cc.sav	2004-09-01 13:36:03.000000000 +0200
+++ desktop.cc	2004-09-14 12:12:52.202654608 +0200
@@ -279,6 +279,16 @@ KDesktop::slotStart()
   if (!m_bInit) return;
 
   kapp->dcopClient()->send( "ksplash", "", "upAndRunning(QString)", QString("kdesktop"));
+#ifdef Q_WS_X11
+  XEvent e;
+  e.xclient.type = ClientMessage;
+  e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
+  e.xclient.display = qt_xdisplay();
+  e.xclient.window = qt_xrootwin();
+  e.xclient.format = 8;
+  strcpy( e.xclient.data.b, "kdesktop" );
+  XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
+#endif
 
   // In case we started without database
   KImageIO::registerFormats();
kded.cpp.patch (text/x-diff, 1016 B)
--- kded.cpp.sav	2004-09-12 23:37:38.000000000 +0200
+++ kded.cpp	2004-09-14 12:06:56.741692888 +0200
@@ -48,6 +48,11 @@
 #include <kio/global.h>
 #include <kservicetype.h>
 
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+#endif
+
 Kded *Kded::_self = 0;
 
 static bool checkStamps = true;
@@ -841,7 +846,16 @@ extern "C" int kdemain(int argc, char *a
      QByteArray data;
      client->send( "*", "ksycoca", "notifyDatabaseChanged()", data );
      client->send( "ksplash", "", "upAndRunning(QString)",  QString("kded"));
-
+#ifdef Q_WS_X11
+     XEvent e;
+     e.xclient.type = ClientMessage;
+     e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
+     e.xclient.display = qt_xdisplay();
+     e.xclient.window = qt_xrootwin();
+     e.xclient.format = 8;
+     strcpy( e.xclient.data.b, "kded" );
+     XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
+#endif
      int result = k.exec(); // keep running
 
      delete kded;
kicker.cpp.patch (text/x-diff, 983 B)
--- kicker.cpp.sav	2004-06-13 19:08:36.000000000 +0200
+++ kicker.cpp	2004-09-14 12:13:54.914121016 +0200
@@ -40,6 +40,11 @@
 #include <kiconloader.h>
 #include <kdebug.h>
 
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+#endif
+
 #include "extensionmanager.h"
 #include "menumanager.h"
 #include "panel.h"
@@ -69,6 +74,16 @@ Kicker* Kicker::kicker() { return (Kicke
 
 	dcopClient()->setDefaultObject("Panel");
 	dcopClient()->send( "ksplash", "", "upAndRunning(QString)", KCmdLineArgs::appName());
+#ifdef Q_WS_X11
+        XEvent e;
+        e.xclient.type = ClientMessage;
+        e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
+        e.xclient.display = qt_xdisplay();
+        e.xclient.window = qt_xrootwin();
+        e.xclient.format = 8;
+        strcpy( e.xclient.data.b, "kicker" );
+        XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
+#endif
 
 	disableSessionManagement();
main.cpp.patch (text/x-diff, 767 B)
--- main.cpp.sav	2004-08-04 14:39:34.000000000 +0200
+++ main.cpp	2004-09-14 12:14:32.342431048 +0200
@@ -122,9 +122,16 @@ Application::Application( )
 
     initting = FALSE; // startup done, we are up and running now.
     dcopClient()->send( "ksplash", "", "upAndRunning(QString)", QString("wm started"));
+    XEvent e;
+    e.xclient.type = ClientMessage;
+    e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
+    e.xclient.display = qt_xdisplay();
+    e.xclient.window = qt_xrootwin();
+    e.xclient.format = 8;
+    strcpy( e.xclient.data.b, "wm started" );
+    XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
     }
 
-
 Application::~Application()
     {
     delete Workspace::self();
server.cpp.patch (text/x-diff, 894 B)
--- server.cpp.sav	2004-08-26 18:55:15.000000000 +0200
+++ server.cpp	2004-09-14 12:17:14.819730744 +0200
@@ -49,6 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #include <time.h>
 #include <errno.h>
 #include <string.h>
+#include <assert.h>
 
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
@@ -1548,6 +1549,15 @@ void KSMServer::publishProgress( int pro
 void KSMServer::upAndRunning( const QString& msg )
 {
     DCOPRef( "ksplash" ).send( "upAndRunning", msg );
+    XEvent e;
+    e.xclient.type = ClientMessage;
+    e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
+    e.xclient.display = qt_xdisplay();
+    e.xclient.window = qt_xrootwin();
+    e.xclient.format = 8;
+    assert( strlen( msg.latin1()) < 20 );
+    strcpy( e.xclient.data.b, msg.latin1());
+    XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
 }
startkde.patch (text/x-diff, 575 B)
--- startkde.sav	2004-08-08 12:53:51.000000000 +0200
+++ startkde	2004-09-14 13:35:01.491288832 +0200
@@ -194,7 +194,14 @@ if kreadconfig --file kpersonalizerrc --
 fi
 
 # the splashscreen and progress indicator
-ksplash --nodcop
+splash=`kreadconfig --file ksplashrc --group KSplash --key Theme`
+if test "$splash" = "None"; then
+    echo >/dev/null #nothing
+elif test "$splash" = "Simple"; then
+    ksplashsimple
+else
+    ksplash --nodcop
+fi
 
 # We set LD_BIND_NOW to increase the efficiency of kdeinit.
 # kdeinit unsets this variable before loading applications.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.