From kde-core-devel Sun Mar 16 18:00:10 2008 From: Lubos Lunak Date: Sun, 16 Mar 2008 18:00:10 +0000 To: kde-core-devel Subject: Mixing KDE3 and KDE4 Message-Id: <200803161900.10394.l.lunak () suse ! cz> X-MARC-Message: https://marc.info/?l=kde-core-devel&m=120569044704554 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Boundary-00=_qAW3HPxpe2M4FQr" --Boundary-00=_qAW3HPxpe2M4FQr Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 --Boundary-00=_qAW3HPxpe2M4FQr Content-Type: text/x-diff; charset="us-ascii"; name="kdebase3.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kdebase3.patch" --- 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 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 "$@" --Boundary-00=_qAW3HPxpe2M4FQr Content-Type: text/x-diff; charset="us-ascii"; name="kdelibs3.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kdelibs3.patch" --- 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(); --Boundary-00=_qAW3HPxpe2M4FQr Content-Type: text/x-diff; charset="us-ascii"; name="kdelibs4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kdelibs4.patch" --- 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(); --Boundary-00=_qAW3HPxpe2M4FQr Content-Type: text/x-diff; charset="us-ascii"; name="kdebase4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kdebase4.patch" --- 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 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 --Boundary-00=_qAW3HPxpe2M4FQr--