[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Mixing KDE3 and KDE4
From:       Lubos Lunak <l.lunak () suse ! cz>
Date:       2008-03-16 18:00:10
Message-ID: 200803161900.10394.l.lunak () suse ! cz
[Download RAW message or body]

Hello,

 the 'mixing' in the subject refers to being able to run things from KDE3 and 
KDE4 at the same time, not just install them alongside. Currently, I'm aware 
of these issues:

- session management doesn't work - ksmserver restores "its" version (i.e. run 
KWrite from KDE3 in KDE4, you get the KDE4 version after next login)
- launching apps using .desktop files has a similar problem of launching 
the "native" version
- logout is delayed by waiting for the "other" kdeinit etc. to exit after a 
timeout

 I'd expect the list to be longer and therefore I'd like to collect all such 
problems. Some of these possibly don't exist with distros that install 
everything in /usr (I can't see how they want to install KWrite both from 
KDE3 and KDE4), but even there people e.g. may be interested in running other 
version they built from sources.

 To solve some of the above things I suggest the attached patches:

- there are scripts 'kde3' and 'kde4', to be used as wrappers when 
launching "foreign" KDE apps. They may need to be patched by specific 
distributions to run them from the proper prefix, set up some env. variables 
or whatever. They may also be extended to try to run the apps using kdeinit 
if possible for better performance.

 Does this look ok, or does somebody have a better idea?

- kdelibs is patched to make apps explicitly tell ksmserver their KDE version, 
ksmserver then will use kde3/kde4 if appropriate to launch such apps

- startkde is patched to immediatelly shut down "other" kdeinit (need some 
commits I did recently to be really fast)


(CC-ing packagers as they're most likely to know, but please keep the 
discussion on kde-core-devel, thanks)


-- 
Lubos Lunak
KDE developer
--------------------------------------------------------------
SUSE LINUX, s.r.o.   e-mail: l.lunak@suse.cz , l.lunak@kde.org
Lihovarska 1060/12   tel: +420 284 028 972
190 00 Prague 9      fax: +420 284 028 951
Czech Republic       http://www.suse.cz

["kdebase3.patch" (text/x-diff)]

--- kdebase/ksmserver/client.h.sav	2008-03-08 17:16:24.000000000 +0100
+++ kdebase/ksmserver/client.h	2008-03-14 15:47:01.000000000 +0100
@@ -51,6 +51,7 @@ public:
     int restartStyleHint() const;
     QString userId() const;
     const char* clientId() { return id ? id : ""; }
+    int specialKdeVersion() const;
 
 private:
     const char* id;
--- kdebase/ksmserver/startup.cpp.sav	2008-03-08 17:16:24.000000000 +0100
+++ kdebase/ksmserver/startup.cpp	2008-03-14 15:52:01.000000000 +0100
@@ -105,11 +105,13 @@ void KSMServer::restoreSession( QString 
     appsToStart = count;
 
     QValueList<QStringList> wmCommands;
+    int wmSpecialKdeVersion = 0;
     if ( !wm.isEmpty() ) {
 	for ( int i = 1; i <= count; i++ ) {
 	    QString n = QString::number(i);
 	    if ( wm == config->readEntry( QString("program")+n ) ) {
 		wmCommands << config->readListEntry( QString("restartCommand")+n );
+                wmSpecialKdeVersion = config->readNumEntry( QString( "specialKdeVersion")+n, 0 );
 	    }
 	}
     }
@@ -130,7 +132,7 @@ void KSMServer::restoreSession( QString 
         // it some time before launching other processes. Results in a
         // visually more appealing startup.
         for (uint i = 0; i < wmCommands.count(); i++)
-            startApplication( wmCommands[i] );
+            startApplication( wmCommands[i], QString(), QString(), wmSpecialKdeVersion );
         QTimer::singleShot( 4000, this, SLOT( autoStart0() ) );
     } else {
         autoStart0();
@@ -268,7 +270,8 @@ void KSMServer::tryRestoreNext()
             continue;
         startApplication( restartCommand,
                           config->readEntry( QString("clientMachine")+n ),
-                          config->readEntry( QString("userId")+n ));
+                          config->readEntry( QString("userId")+n ),
+                          config->readNumEntry( QString("specialKdeVersion")+n, 0 ));
         lastIdStarted = config->readEntry( QString("clientId")+n );
         if ( !lastIdStarted.isEmpty() ) {
             restoreTimer.start( 2000, TRUE );
--- kdebase/ksmserver/server.h.sav	2008-03-08 17:16:24.000000000 +0100
+++ kdebase/ksmserver/server.h	2008-03-14 15:49:14.000000000 +0100
@@ -134,7 +134,8 @@ private:
 
     void startApplication( QStringList command,
         const QString& clientMachine = QString::null,
-        const QString& userId = QString::null );
+        const QString& userId = QString::null,
+        int specialKdeVersion = 0 );
     void executeCommand( const QStringList& command );
     
     bool isWM( const KSMClient* client ) const;
--- kdebase/ksmserver/server.cpp.sav	2008-03-08 17:16:24.000000000 +0100
+++ kdebase/ksmserver/server.cpp	2008-03-14 15:51:41.000000000 +0100
@@ -99,10 +99,15 @@ KSMServer* KSMServer::self()
  * to restart applications.
  */
 void KSMServer::startApplication( QStringList command, const QString& clientMachine,
-    const QString& userId )
+    const QString& userId, int specialKdeVersion )
 {
     if ( command.isEmpty() )
         return;
+    if( specialKdeVersion != KDE_VERSION_MAJOR ) {
+        QString wrapper = "kde" + QString::number( specialKdeVersion );
+        if( !KStandardDirs::findExe( wrapper ).isEmpty())
+            command.prepend( wrapper );
+    }
     if ( !userId.isEmpty()) {
         struct passwd* pw = getpwuid( getuid());
         if( pw != NULL && userId != QString::fromLocal8Bit( pw->pw_name )) {
@@ -879,6 +884,9 @@ void KSMServer::storeSession()
         config->writePathEntry( QString("discardCommand")+n, c->discardCommand() );
         config->writeEntry( QString("restartStyleHint")+n, restartHint );
         config->writeEntry( QString("userId")+n, c->userId() );
+        int specialVersion = c->specialKdeVersion();
+        if( specialVersion != 0 && specialVersion != KDE_VERSION_MAJOR )
+            config->writeEntry( QString("specialKdeVersion")+n, specialVersion );
     }
     config->writeEntry( "count", count );
 
--- kdebase/ksmserver/client.cpp.sav	2008-03-08 17:16:24.000000000 +0100
+++ kdebase/ksmserver/client.cpp	2008-03-14 15:47:46.000000000 +0100
@@ -187,4 +187,10 @@ QString KSMClient::userId() const
     return QString::fromLatin1( (const char*) p->vals[0].value );
 }
 
-
+int KSMClient::specialKdeVersion() const
+{
+    SmProp* p = property( "_KDE_VERSION" );
+    if( !p || qstrcmp( p->type, SmARRAY8 ) != 0 || p->num_vals != 1 )
+        return 0;
+    return atoi( (const char*) p->vals[0].value );
+}
--- kdebase/Makefile.am.in.sav	2008-03-08 17:23:21.000000000 +0100
+++ kdebase/Makefile.am.in	2008-03-14 20:10:08.000000000 +0100
@@ -9,7 +9,7 @@ COMPILE_AFTER_kcontrol = kdm kdesktop
 
 AUTOMAKE_OPTIONS = foreign 1.6.1
 
-bin_SCRIPTS = startkde
+bin_SCRIPTS = startkde kde3
 
 EXTRA_DIST = admin bsd-port debian kdebase.spec.in README.pam kde.pamd kscreensaver.pamd mkpamserv
 
--- kdebase/startkde.sav	2008-03-08 17:23:21.000000000 +0100
+++ kdebase/startkde	2008-03-14 20:09:38.000000000 +0100
@@ -387,6 +387,8 @@ echo 'startkde: Shutting down...'  1>&2
 kdeinit_shutdown
 dcopserver_shutdown --wait
 artsshell -q terminate
+# KDE4 support
+kde4 kdeinit4_shutdown 2>/dev/null
 
 echo 'startkde: Running shutdown scripts...'  1>&2
 
--- kdebase/kde3.sav	2008-03-14 20:09:51.000000000 +0100
+++ kdebase/kde3	2008-03-14 20:15:08.000000000 +0100
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+#  Script for launching KDE3 applications from outside of the KDE3 desktop
+#
+#  Modify this to match your specific needs, such as setting up needed env. variables,
+#  and make sure this script is in $PATH (e.g. make a symlink if necessary).
+#
+
+exec "$@"

["kdelibs3.patch" (text/x-diff)]

--- kdelibs/kdecore/kapplication.cpp.sav	2008-03-08 17:26:49.000000000 +0100
+++ kdelibs/kdecore/kapplication.cpp	2008-03-14 15:33:14.000000000 +0100
@@ -1200,9 +1200,25 @@ void KApplication::propagateSessionManag
 #endif
 }
 
+// QSessionManager::setManagerProperty() is broken in Qt3
+static void setVersionSmProperty( QSessionManager& sm )
+{
+    SmProp prop;
+    prop.name = (char*)"_KDE_VERSION";
+    prop.type = (char*)SmARRAY8;
+    prop.num_vals = 1;
+    SmPropValue val;
+    prop.vals = &val;
+    val.length = 1;
+    val.value = (SmPointer)"3";
+    SmProp* p[ 1 ] = { &prop };
+    SmcSetProperties( (SmcConn)sm.handle(), 1, p );
+}
+
 void KApplication::commitData( QSessionManager& sm )
 {
     d->session_save = true;
+    setVersionSmProperty( sm );
     bool canceled = false;
     for (KSessionManaged* it = sessionClients()->first();
          it && !canceled;
@@ -1247,6 +1263,7 @@ void KApplication::commitData( QSessionM
 void KApplication::saveState( QSessionManager& sm )
 {
     d->session_save = true;
+    setVersionSmProperty( sm );
 #ifdef Q_WS_X11
     static bool firstTime = true;
     mySmcConnection = (SmcConn) sm.handle();

["kdelibs4.patch" (text/x-diff)]

--- kdelibs/kdeui/kernel/kapplication.cpp.sav	2008-03-11 19:15:21.000000000 +0100
+++ kdelibs/kdeui/kernel/kapplication.cpp	2008-03-14 15:06:24.000000000 +0100
@@ -683,6 +683,7 @@ void KApplication::enableSessionManageme
 void KApplication::commitData( QSessionManager& sm )
 {
     d->session_save = true;
+    sm.setManagerProperty( "_KDE_VERSION", QString::number( KDE_VERSION_MAJOR ));
     bool canceled = false;
 
     foreach (KSessionManager *it, KSessionManager::sessionClients()) {
@@ -732,6 +733,7 @@ commitDataRestart:
 void KApplication::saveState( QSessionManager& sm )
 {
     d->session_save = true;
+    sm.setManagerProperty( "_KDE_VERSION", QString::number( KDE_VERSION_MAJOR ));
 #ifdef Q_WS_X11
     static bool firstTime = true;
     mySmcConnection = (SmcConn) sm.handle();

["kdebase4.patch" (text/x-diff)]

--- kdebase/runtime/kde4.sav	2008-03-14 20:09:51.000000000 +0100
+++ kdebase/runtime/kde4	2008-03-14 20:15:29.000000000 +0100
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+#  Script for launching KDE4 applications from outside of the KDE4 desktop
+#
+#  Modify this to match your specific needs, such as setting up needed env. \
variables, +#  and make sure this script is in $PATH (e.g. make a symlink if \
necessary). +#
+
+exec "$@"
--- kdebase/runtime/CMakeLists.txt.sav	2008-02-09 15:13:25.000000000 +0100
+++ kdebase/runtime/CMakeLists.txt	2008-03-14 20:14:44.000000000 +0100
@@ -80,3 +80,5 @@ if(CMAKE_SOURCE_DIR STREQUAL "${CMAKE_CU
   macro_display_feature_log()
 endif(CMAKE_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
 
+########### install files ###############
+install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/kde4 DESTINATION ${BIN_INSTALL_DIR})
--- kdebase/workspace/ksmserver/client.h.sav	2008-01-19 18:39:05.000000000 +0100
+++ kdebase/workspace/ksmserver/client.h	2008-03-14 12:58:51.000000000 +0100
@@ -58,6 +58,7 @@ public:
     int restartStyleHint() const;
     QString userId() const;
     const char* clientId() { return id ? id : ""; }
+    int specialKdeVersion() const;
 
 private:
     const char* id;
--- kdebase/workspace/ksmserver/startup.cpp.sav	2008-01-19 18:39:05.000000000 +0100
+++ kdebase/workspace/ksmserver/startup.cpp	2008-03-14 15:35:41.000000000 +0100
@@ -100,11 +100,13 @@ void KSMServer::restoreSession( const QS
     appsToStart = count;
 
     QList<QStringList> wmCommands;
+    int wmSpecialKdeVersion = 0;
     if ( !wm.isEmpty() ) {
 	for ( int i = 1; i <= count; i++ ) {
 	    QString n = QString::number(i);
 	    if ( wm == configSessionGroup.readEntry( QString("program")+n, QString() ) ) {
 		wmCommands << configSessionGroup.readEntry( QString("restartCommand")+n, \
QStringList() ); +                wmSpecialKdeVersion = configSessionGroup.readEntry( \
QString( "specialKdeVersion")+n, 0 );  }
 	}
     }
@@ -122,7 +124,7 @@ void KSMServer::restoreSession( const QS
         // it some time before launching other processes. Results in a
         // visually more appealing startup.
         for (int i = 0; i < wmCommands.count(); i++)
-            startApplication( wmCommands[i] );
+            startApplication( wmCommands[i], QString(), QString(), \
wmSpecialKdeVersion );  QTimer::singleShot( 4000, this, SLOT( autoStart0() ) );
     } else {
         autoStart0();
@@ -258,7 +260,8 @@ void KSMServer::tryRestoreNext()
             continue;
         startApplication( restartCommand,
                           config.readEntry( QString("clientMachine")+n, QString() ),
-                          config.readEntry( QString("userId")+n, QString() ));
+                          config.readEntry( QString("userId")+n, QString() ),
+                          config.readEntry( QString("specialKdeVersion")+n, 0 ));
         lastIdStarted = config.readEntry( QString("clientId")+n, QString() );
         if ( !lastIdStarted.isEmpty() ) {
             restoreTimer.setSingleShot( true );
--- kdebase/workspace/ksmserver/server.h.sav	2008-03-03 22:05:03.000000000 +0100
+++ kdebase/workspace/ksmserver/server.h	2008-03-14 13:04:42.000000000 +0100
@@ -144,7 +144,8 @@ private:
 
     void startApplication( QStringList& command,
         const QString& clientMachine = QString(),
-        const QString& userId = QString() );
+        const QString& userId = QString(),
+        int specialKdeVersion = 0 );
     void executeCommand( const QStringList& command );
 
     bool isWM( const KSMClient* client ) const;
--- kdebase/workspace/ksmserver/server.cpp.sav	2008-03-03 22:05:00.000000000 +0100
+++ kdebase/workspace/ksmserver/server.cpp	2008-03-14 15:46:47.000000000 +0100
@@ -94,10 +94,15 @@ KSMServer* KSMServer::self()
  * to restart applications.
  */
 void KSMServer::startApplication( QStringList& command, const QString& \
                clientMachine,
-    const QString& userId )
+    const QString& userId, int specialKdeVersion )
 {
     if ( command.isEmpty() )
         return;
+    if( specialKdeVersion != KDE_VERSION_MAJOR ) {
+        QString wrapper = "kde" + QString::number( specialKdeVersion );
+        if( !KStandardDirs::findExe( wrapper ).isEmpty())
+            command.prepend( wrapper );
+    }
     if ( !userId.isEmpty()) {
         struct passwd* pw = getpwuid( getuid());
         if( pw != NULL && userId != QString::fromLocal8Bit( pw->pw_name )) {
@@ -881,6 +886,9 @@ void KSMServer::storeSession()
         cg.writePathEntry( QString("discardCommand")+n, c->discardCommand() );
         cg.writeEntry( QString("restartStyleHint")+n, restartHint );
         cg.writeEntry( QString("userId")+n, c->userId() );
+        int specialVersion = c->specialKdeVersion();
+        if( specialVersion != 0 && specialVersion != KDE_VERSION_MAJOR )
+            cg.writeEntry( QString("specialKdeVersion")+n, specialVersion );
     }
     cg.writeEntry( "count", count );
 
--- kdebase/workspace/ksmserver/client.cpp.sav	2008-01-19 18:39:05.000000000 +0100
+++ kdebase/workspace/ksmserver/client.cpp	2008-03-14 15:47:12.000000000 +0100
@@ -183,3 +183,11 @@ QString KSMClient::userId() const
         return QString();
     return QLatin1String( (const char*) p->vals[0].value );
 }
+
+int KSMClient::specialKdeVersion() const
+{
+    SmProp* p = property( "_KDE_VERSION" );
+    if( !p || qstrcmp( p->type, SmARRAY8 ) != 0 || p->num_vals != 1 )
+        return 0;
+    return atoi( (const char*) p->vals[0].value );
+}
--- kdebase/workspace/startkde.cmake.sav	2008-03-11 19:17:44.000000000 +0100
+++ kdebase/workspace/startkde.cmake	2008-03-14 20:17:03.000000000 +0100
@@ -401,6 +401,8 @@ test -n "$ksplash_pid" && kill "$ksplash
 
 # Clean up
 kdeinit4_shutdown
+# KDE4 support
+kde4 kdeinit4_shutdown 2>/dev/null
 
 echo 'startkde: Running shutdown scripts...'  1>&2
 



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic