You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tde-packaging/opensuse/core/tdebase/select-wm-gui.diff

636 lines
21 KiB

Subject: GUI configuration for selecting WM
From: Lubos Lunak
Feature: bnc#332079
Patch-upstream: no
Index: ksmserver/startup.cpp
===================================================================
--- ksmserver/startup.cpp.orig
+++ ksmserver/startup.cpp
@@ -103,38 +103,39 @@ void KSMServer::restoreSession( QString
config->setGroup( sessionGroup );
int count = config->readNumEntry( "count" );
appsToStart = count;
-
- QValueList<QStringList> wmCommands;
- 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 );
- }
- }
- }
- if ( wmCommands.isEmpty() )
- wmCommands << ( QStringList() << wm );
-
publishProgress( appsToStart, true );
+ upAndRunning( "ksmserver" );
connectDCOPSignal( launcher, launcher, "autoStart0Done()",
"autoStart0Done()", true);
connectDCOPSignal( launcher, launcher, "autoStart1Done()",
"autoStart1Done()", true);
connectDCOPSignal( launcher, launcher, "autoStart2Done()",
"autoStart2Done()", true);
- upAndRunning( "ksmserver" );
- if ( !wmCommands.isEmpty() ) {
- // when we have a window manager, we start it first and give
- // 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] );
- QTimer::singleShot( 4000, this, SLOT( autoStart0() ) );
- } else {
- autoStart0();
+ // find all commands to launch the wm in the session
+ QValueList<QStringList> wmStartCommands;
+ if ( !wm.isEmpty() ) {
+ for ( int i = 1; i <= count; i++ ) {
+ QString n = QString::number(i);
+ // special hack for it, both kde3(=native) and kde4 kwin have the same program,
+ // but the command for kde4 kwin starts with the kde4 wrapper
+ if( config->readEntry( QString("program")+n ) == "kwin" ) {
+ QStringList command = config->readListEntry( QString("restartCommand")+n );
+ if( wmCommands.count() > 1 && wmCommands[ 0 ].endsWith( "kde4" )
+ && command.count() > 1 && command[ 0 ].endsWith( "kde4" )) {
+ wmStartCommands << command; // kde4 wanted, kde4 found
+ } else if(!( wmCommands.count() > 1 && wmCommands[ 0 ].endsWith( "kde4" ))
+ && !( command.count() > 1 && command[ 0 ].endsWith( "kde4" ))) {
+ wmStartCommands << command; // native wanted, native found
+ }
+ } else if ( wm == config->readEntry( QString("program")+n ) ) {
+ wmStartCommands << config->readListEntry( QString("restartCommand")+n );
+ }
+ }
}
+ if( wmStartCommands.isEmpty()) // otherwise use the configured default
+ wmStartCommands << wmCommands;
+ launchWM( wmStartCommands );
}
/*!
@@ -157,17 +158,53 @@ void KSMServer::startDefaultSession()
"autoStart1Done()", true);
connectDCOPSignal( launcher, launcher, "autoStart2Done()",
"autoStart2Done()", true);
- startApplication( wm );
+ launchWM( QValueList< QStringList >() << wmCommands );
+}
+
+void KSMServer::launchWM( const QValueList< QStringList >& wmStartCommands )
+{
+ assert( state == LaunchingWM );
+
+ // when we have a window manager, we start it first and give
+ // it some time before launching other processes. Results in a
+ // visually more appealing startup.
+ wmProcess = startApplication( wmStartCommands[ 0 ] );
+ connect( wmProcess, SIGNAL( processExited( KProcess* )), SLOT( wmProcessChange()));
+ // there can be possibly more wm's (because of forking for multihead),
+ // but in such case care only about the process of the first one
+ for (unsigned int i = 1; i < wmStartCommands.count(); i++)
+ startApplication( wmStartCommands[i] );
QTimer::singleShot( 4000, this, SLOT( autoStart0() ) );
}
void KSMServer::clientSetProgram( KSMClient* client )
{
- if ( !wm.isEmpty() && client->program() == wm )
+ if ( client->program() == wm )
autoStart0();
}
+void KSMServer::wmProcessChange()
+{
+ if( state != LaunchingWM )
+ { // don't care about the process when not in the wm-launching state anymore
+ wmProcess = NULL;
+ return;
+ }
+ if( !wmProcess->isRunning())
+ { // wm failed to launch for some reason, go with kwin instead
+ kdWarning( 1218 ) << "Window manager '" << wm << "' failed to launch" << endl;
+ if( wm == "kwin" )
+ return; // uhoh, kwin itself failed
+ kdDebug( 1218 ) << "Launching KWin" << endl;
+ wm = "kwin";
+ wmCommands = ( QStringList() << "kwin" );
+ // launch it
+ launchWM( QValueList< QStringList >() << wmCommands );
+ return;
+ }
+}
+
void KSMServer::autoStart0()
{
if( state != LaunchingWM )
Index: ksmserver/server.h
===================================================================
--- ksmserver/server.h.orig
+++ ksmserver/server.h
@@ -30,6 +30,8 @@ Copyright (C) 2000 Matthias Ettrich <ett
#define SESSION_PREVIOUS_LOGOUT "saved at previous logout"
#define SESSION_BY_USER "saved by user"
+class KProcess;
+
typedef QValueList<QCString> QCStringList;
class KSMListener;
class KSMConnection;
@@ -98,6 +100,8 @@ public:
KApplication::ShutdownType sdtype,
KApplication::ShutdownMode sdmode );
+ void launchWM( const QValueList< QStringList >& wmStartCommands );
+
public slots:
void cleanUp();
@@ -120,6 +124,7 @@ private slots:
void autoStart2();
void tryRestoreNext();
void startupSuspendTimeout();
+ void wmProcessChange();
private:
void handlePendingInteractions();
@@ -138,13 +143,14 @@ private:
void startProtection();
void endProtection();
- void startApplication( QStringList command,
+ KProcess* startApplication( QStringList command,
const QString& clientMachine = QString::null,
const QString& userId = QString::null );
void executeCommand( const QStringList& command );
bool isWM( const KSMClient* client ) const;
bool isWM( const QString& program ) const;
+ void selectWm( const QString& kdewm );
bool defaultSession() const; // empty session
void setupXIOErrorHandler();
@@ -223,6 +229,8 @@ private:
int lastAppStarted;
QString lastIdStarted;
+ QStringList wmCommands;
+ KProcess* wmProcess;
QStringList excludeApps;
WindowMap legacyWindows;
Index: ksmserver/Makefile.am
===================================================================
--- ksmserver/Makefile.am.orig
+++ ksmserver/Makefile.am
@@ -15,7 +15,7 @@
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-SUBDIRS = .
+SUBDIRS = . windowmanagers
INCLUDES= -I$(top_srcdir)/kdmlib $(all_includes) $(DBUS_INCS)
Index: ksmserver/main.cpp
===================================================================
--- ksmserver/main.cpp.orig
+++ ksmserver/main.cpp
@@ -203,8 +203,6 @@ extern "C" KDE_EXPORT int kdemain( int a
}
QCString wm = args->getOption("windowmanager");
- if ( wm.isEmpty() )
- wm = "kwin";
bool only_local = args->isSet("local");
#ifndef HAVE__ICETRANSNOLISTEN
Index: ksmserver/server.cpp
===================================================================
--- ksmserver/server.cpp.orig
+++ ksmserver/server.cpp
@@ -77,6 +77,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE
#include <kprocess.h>
#include <dcopclient.h>
#include <dcopref.h>
+#include <kdesktopfile.h>
+#include <kshell.h>
#include "server.h"
#include "global.h"
@@ -98,11 +100,11 @@ KSMServer* KSMServer::self()
/*! Utility function to execute a command on the local machine. Used
* to restart applications.
*/
-void KSMServer::startApplication( QStringList command, const QString& clientMachine,
+KProcess* KSMServer::startApplication( QStringList command, const QString& clientMachine,
const QString& userId )
{
if ( command.isEmpty() )
- return;
+ return NULL;
if ( !userId.isEmpty()) {
struct passwd* pw = getpwuid( getuid());
if( pw != NULL && userId != QString::fromLocal8Bit( pw->pw_name )) {
@@ -116,12 +118,12 @@ void KSMServer::startApplication( QStrin
command.prepend( clientMachine );
command.prepend( xonCommand ); // "xon" by default
}
- int n = command.count();
- QCString app = command[0].latin1();
- QValueList<QCString> argList;
- for ( int i=1; i < n; i++)
- argList.append( QCString(command[i].latin1()));
- DCOPRef( launcher ).send( "exec_blind", app, DCOPArg( argList, "QValueList<QCString>" ) );
+ KProcess* process = new KProcess( this );
+ *process << command;
+ // make it auto-delete
+ connect( process, SIGNAL( processExited( KProcess* )), process, SLOT( deleteLater()));
+ process->start();
+ return process;
}
/*! Utility function to execute a command on the local machine. Used
@@ -580,10 +582,10 @@ extern "C" int _IceTransNoListen(const c
KSMServer::KSMServer( const QString& windowManager, bool _only_local )
: DCOPObject("ksmserver"), sessionGroup( "" )
+ , wmProcess( NULL )
{
the_server = this;
clean = false;
- wm = windowManager;
shutdownType = KApplication::ShutdownTypeNone;
@@ -595,6 +597,9 @@ KSMServer::KSMServer( const QString& win
config->setGroup("General" );
clientInteracting = 0;
xonCommand = config->readEntry( "xonCommand", "xon" );
+
+ KGlobal::dirs()->addResourceType( "windowmanagers", "share/apps/ksmserver/windowmanagers" );
+ selectWm( windowManager );
connect( &knotifyTimeoutTimer, SIGNAL( timeout()), SLOT( knotifyTimeout()));
connect( &startupSuspendTimeoutTimer, SIGNAL( timeout()), SLOT( startupSuspendTimeout()));
@@ -851,14 +856,12 @@ void KSMServer::storeSession()
config->setGroup( sessionGroup );
count = 0;
- if ( !wm.isEmpty() ) {
- // put the wm first
- for ( KSMClient* c = clients.first(); c; c = clients.next() )
- if ( c->program() == wm ) {
- clients.prepend( clients.take() );
- break;
- }
- }
+ // put the wm first
+ for ( KSMClient* c = clients.first(); c; c = clients.next() )
+ if ( c->program() == wm ) {
+ clients.prepend( clients.take() );
+ break;
+ }
for ( KSMClient* c = clients.first(); c; c = clients.next() ) {
int restartHint = c->restartStyleHint();
@@ -909,14 +912,65 @@ bool KSMServer::isWM( const KSMClient* c
bool KSMServer::isWM( const QString& program ) const
{
- // KWin relies on ksmserver's special treatment in phase1,
- // therefore make sure it's recognized even if ksmserver
- // was initially started with different WM, and kwin replaced
- // it later
- return program == wm || program == "kwin";
+ return program == wm;
}
bool KSMServer::defaultSession() const
{
return sessionGroup.isEmpty();
}
+
+static bool noDisplay( KDesktopFile& f )
+{
+ KConfigGroup gr( &f, "Desktop Entry" );
+ if (gr.readBoolEntry("NoDisplay", false)) {
+ return true;
+ }
+ if (gr.hasKey("OnlyShowIn")) {
+ if (!gr.readListEntry("OnlyShowIn", ';').contains("KDE"))
+ return true;
+ }
+ if (gr.hasKey("NotShowIn")) {
+ if (gr.readListEntry("NotShowIn", ';').contains("KDE"))
+ return true;
+ }
+ return false;
+}
+
+// selection logic:
+// - $KDEWM is set - use that
+// - a wm is selected using the kcm - use that
+// - if that fails, just use KWin
+void KSMServer::selectWm( const QString& kdewm )
+{
+ wm = "kwin"; // defaults
+ wmCommands = ( QStringList() << "kwin" );
+ if( !kdewm.isEmpty())
+ {
+ wmCommands = ( QStringList() << kdewm );
+ wm = kdewm;
+ return;
+ }
+ KConfigGroup config(KGlobal::config(), "General");
+ QString cfgwm = config.readEntry( "windowManager", "kwin" );
+ KDesktopFile file( cfgwm + ".desktop", true, "windowmanagers" );
+ if( noDisplay( file ))
+ return;
+ if( !file.tryExec())
+ return;
+ file.setDesktopGroup();
+ QString testexec = file.readEntry( "X-KDE-WindowManagerTestExec" );
+ if( !testexec.isEmpty())
+ {
+ int ret = system( QFile::encodeName( testexec ));
+ if( !WIFEXITED( ret ) || WEXITSTATUS( ret ) != 0 )
+ return;
+ }
+ QStringList cfgWmCommands = KShell::splitArgs( file.readEntry( "Exec" ));
+ if( cfgWmCommands.isEmpty())
+ return;
+ QString smname = file.readEntry( "X-KDE-WindowManagerId" );
+ // ok
+ wm = smname.isEmpty() ? cfgwm : smname;
+ wmCommands = cfgWmCommands;
+}
Index: ksmserver/windowmanagers/openbox.desktop
===================================================================
--- /dev/null
+++ ksmserver/windowmanagers/openbox.desktop
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Name=Openbox
+Exec=openbox
+TryExec=openbox
+
Index: ksmserver/windowmanagers/Makefile.am
===================================================================
--- /dev/null
+++ ksmserver/windowmanagers/Makefile.am
@@ -0,0 +1,2 @@
+windowmanager_DATA = compiz-custom.desktop compiz.desktop kwin4.desktop metacity.desktop openbox.desktop
+windowmanagerdir = $(kde_datadir)/ksmserver/windowmanagers
Index: ksmserver/windowmanagers/compiz.desktop
===================================================================
--- /dev/null
+++ ksmserver/windowmanagers/compiz.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Name=Compiz
+Exec=compiz ccp
+TryExec=compiz
Index: ksmserver/windowmanagers/compiz-custom.desktop
===================================================================
--- /dev/null
+++ ksmserver/windowmanagers/compiz-custom.desktop
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Name=Compiz custom (create wrapper script 'compiz-kde-launcher' to launch it)
+Exec=compiz-kde-launcher
+TryExec=compiz
+X-KDE-WindowManagerId=compiz
Index: ksmserver/windowmanagers/kwin4.desktop
===================================================================
--- /dev/null
+++ ksmserver/windowmanagers/kwin4.desktop
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Name=KWin (KDE4)
+Exec=kde4 /usr/bin/kwin
+TryExec=/usr/bin/kwin
+X-KDE-WindowManagerId=kwin
+
Index: ksmserver/windowmanagers/metacity.desktop
===================================================================
--- /dev/null
+++ ksmserver/windowmanagers/metacity.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+Name=Metacity (GNOME)
+Exec=metacity
+TryExec=metacity
Index: kcontrol/smserver/smserverconfigdlg.ui
===================================================================
--- kcontrol/smserver/smserverconfigdlg.ui.orig
+++ kcontrol/smserver/smserverconfigdlg.ui
@@ -1,4 +1,4 @@
-<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>SMServerConfigDlg</class>
<widget class="QWidget">
<property name="name">
@@ -8,8 +8,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>325</width>
- <height>366</height>
+ <width>334</width>
+ <height>476</height>
</rect>
</property>
<property name="caption">
@@ -148,6 +148,24 @@
</widget>
</vbox>
</widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>windowManagerGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Window Manager</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>windowManagerCombo</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
<widget class="QButtonGroup">
<property name="name">
<cstring>advancedGroup</cstring>
@@ -236,6 +254,12 @@
<receiver>SMServerConfigDlg</receiver>
<slot>configChanged()</slot>
</connection>
+ <connection>
+ <sender>windowManagerCombo</sender>
+ <signal>activated(int)</signal>
+ <receiver>SMServerConfigDlg</receiver>
+ <slot>configChanged()</slot>
+ </connection>
</connections>
<includes>
<include location="global" impldecl="in implementation">kdialog.h</include>
Index: kcontrol/smserver/kcmsmserver.cpp
===================================================================
--- kcontrol/smserver/kcmsmserver.cpp.orig
+++ kcontrol/smserver/kcmsmserver.cpp
@@ -22,6 +22,8 @@
#include <qcheckbox.h>
#include <qlayout.h>
#include <qradiobutton.h>
+#include <qcombobox.h>
+#include <qfile.h>
#include <dcopclient.h>
@@ -29,6 +31,12 @@
#include <kconfig.h>
#include <kgenericfactory.h>
#include <klineedit.h>
+#include <kstandarddirs.h>
+#include <qregexp.h>
+#include <kdesktopfile.h>
+#include <kdebug.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
#include "kcmsmserver.h"
#include "smserverconfigimpl.h"
@@ -52,6 +60,7 @@ SMServerConfig::SMServerConfig( QWidget
dialog->show();
topLayout->add(dialog);
+ KGlobal::dirs()->addResourceType( "windowmanagers", "share/apps/ksmserver/windowmanagers" );
load();
}
@@ -90,6 +99,7 @@ void SMServerConfig::load(bool useDefaul
dialog->logoutRadio->setChecked(true);
break;
}
+ loadWMs(c->readEntry("windowManager", "kwin"));
dialog->excludeLineedit->setText( c->readEntry("excludeApps"));
delete c;
@@ -116,6 +126,7 @@ void SMServerConfig::save()
dialog->rebootRadio->isChecked() ?
int(KApplication::ShutdownTypeReboot) :
int(KApplication::ShutdownTypeNone));
+ c->writeEntry("windowManager", currentWM());
c->writeEntry("excludeApps", dialog->excludeLineedit->text());
c->sync();
delete c;
@@ -123,6 +134,12 @@ void SMServerConfig::save()
// update the k menu if necessary
QByteArray data;
kapp->dcopClient()->send( "kicker", "kicker", "configure()", data );
+ if( oldwm != currentWM())
+ { // TODO switch it already in the session instead and tell ksmserver
+ KMessageBox::information( this,
+ i18n( "The new window manager will be used when KDE is started the next time." ),
+ i18n( "Window manager change" ), "windowmanagerchange" );
+ }
}
void SMServerConfig::defaults()
@@ -130,5 +147,72 @@ void SMServerConfig::defaults()
load( true );
}
+static bool noDisplay( KDesktopFile& f )
+{
+ KConfigGroup gr( &f, "Desktop Entry" );
+ if (gr.readBoolEntry("NoDisplay", false)) {
+ return true;
+ }
+ if (gr.hasKey("OnlyShowIn")) {
+ if (!gr.readListEntry("OnlyShowIn", ';').contains("KDE"))
+ return true;
+ }
+ if (gr.hasKey("NotShowIn")) {
+ if (gr.readListEntry("NotShowIn", ';').contains("KDE"))
+ return true;
+ }
+ return false;
+}
+
+void SMServerConfig::loadWMs( const QString& current )
+{
+ QString kwinname = i18n( "KWin (KDE default)" );
+ dialog->windowManagerCombo->insertItem( kwinname );
+ dialog->windowManagerCombo->setCurrentItem( 0 );
+ wms[ kwinname ] = "kwin";
+ oldwm = "kwin";
+ QStringList list = KGlobal::dirs()->findAllResources( "windowmanagers", QString(), false, true );
+ QRegExp reg( ".*/([^/\\.]*)\\.[^/\\.]*" );
+ for( QStringList::ConstIterator it = list.begin();
+ it != list.end();
+ ++it )
+ {
+ QString wmfile = *it;
+ KDesktopFile file( wmfile );
+ if( noDisplay( file ))
+ continue;
+ if( !file.tryExec())
+ continue;
+ file.setDesktopGroup();
+ QString testexec = file.readEntry( "X-KDE-WindowManagerTestExec" );
+ if( !testexec.isEmpty())
+ {
+ int ret = system( QFile::encodeName( testexec ));
+ if( !WIFEXITED( ret ) || WEXITSTATUS( ret ) != 0 )
+ continue;
+ }
+ QString name = file.readName();
+ if( name.isEmpty())
+ continue;
+ if( !reg.exactMatch( wmfile ))
+ continue;
+ QString wm = reg.cap( 1 );
+ if( wms.values().contains( wm ))
+ continue;
+ wms[ name ] = wm;
+ dialog->windowManagerCombo->insertItem( name );
+ if( wms[ name ] == current ) // make it selected
+ {
+ dialog->windowManagerCombo->setCurrentItem( dialog->windowManagerCombo->count() - 1 );
+ oldwm = wm;
+ }
+ }
+}
+
+QString SMServerConfig::currentWM() const
+{
+ return wms[ dialog->windowManagerCombo->currentText() ];
+}
+
#include "kcmsmserver.moc"
Index: kcontrol/smserver/kcmsmserver.h
===================================================================
--- kcontrol/smserver/kcmsmserver.h.orig
+++ kcontrol/smserver/kcmsmserver.h
@@ -40,6 +40,10 @@ public:
private:
SMServerConfigImpl* dialog;
+ void loadWMs( const QString& current );
+ QString currentWM() const;
+ QMap< QString, QString > wms; // i18n text -> internal name
+ QString oldwm; // the original value
};