File wm-switch-systemsettings.diff of Package kdebase4-runtime

Subject: Move the window manager selection UI to 'default applications' control module
From: Lubos Lunak
Patch-upstream: r847439-r856682 kdebase/runtime/kcontrol/componentchooser
Relates: kdebase4-workspace/wm-switch-systemsettings.diff

Move the window manager selection UI option (i.e. mainly Compiz switch) to a more
prominent and logical place, the 'default applications' control module. Also improve
the switching.

Index: componentchooserwm.h
===================================================================
--- kcontrol/componentchooser/componentchooserwm.h	(revision 0)
+++ kcontrol/componentchooser/componentchooserwm.h	(revision 856682)
@@ -0,0 +1,83 @@
+/***************************************************************************
+                          componentchooserwm.h  -  description
+                             -------------------
+    copyright            : (C) 2002 by Joseph Wenninger
+    email                : jowenn@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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 Foundationi                            *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef _COMPONENTCHOOSERWM_H_
+#define _COMPONENTCHOOSERWM_H_
+
+#include "ui_wmconfig_ui.h"
+#include "componentchooser.h"
+
+#include <kprocess.h>
+
+class KConfig;
+class KTimerDialog;
+class CfgPlugin;
+
+class WmConfig_UI : public QWidget, public Ui::WmConfig_UI
+{
+public:
+  WmConfig_UI( QWidget *parent ) : QWidget( parent ) {
+    setupUi( this );
+  }
+};
+
+class CfgWm: public WmConfig_UI,public CfgPlugin
+{
+Q_OBJECT
+public:
+    CfgWm(QWidget *parent);
+    virtual ~CfgWm();
+    virtual void load(KConfig *cfg);
+    virtual void save(KConfig *cfg);
+    virtual void defaults();
+
+protected Q_SLOTS:
+    void configChanged();
+    void configureWm();
+    void checkConfigureWm();
+    void wmLaunchError();
+    void wmLaunchFinished( int exitcode, QProcess::ExitStatus exitstatus );
+
+Q_SIGNALS:
+    void changed(bool);
+private:
+    bool tryWmLaunch();
+    void loadWMs( const QString& current );
+    QString currentWm() const;
+    bool saveAndConfirm();
+    struct WmData
+        {
+        QString internalName;
+        QString exec;
+        QString configureCommand;
+        QString restartArgument;
+        QString parentArgument;
+        };
+    WmData currentWmData() const;
+    QHash< QString, WmData > wms; // i18n text -> data
+    QString oldwm; // the original value
+    enum Launch
+    {
+        WmNone, // not trying to launch any WM at the moment
+        WmLaunching, // launching
+        WmOk, // was successful
+        WmFailed // it failed
+    };
+    Launch wmLaunchingState;
+    KTimerDialog* wmDialog;
+    KProcess* wmProcess;
+};
+
+#endif
Index: wmconfig_ui.ui
===================================================================
--- kcontrol/componentchooser/wmconfig_ui.ui	(revision 0)
+++ kcontrol/componentchooser/wmconfig_ui.ui	(revision 856682)
@@ -0,0 +1,124 @@
+<ui version="4.0" >
+ <class>WmConfig_UI</class>
+ <widget class="QWidget" name="WmConfig_UI" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>436</width>
+    <height>190</height>
+   </rect>
+  </property>
+  <property name="sizePolicy" >
+   <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>0</number>
+   </property>
+   <item row="5" column="1" >
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeType" >
+      <enum>QSizePolicy::Expanding</enum>
+     </property>
+     <property name="sizeHint" stdset="0" >
+      <size>
+       <width>0</width>
+       <height>87</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="1" column="0" colspan="2" >
+    <widget class="QRadioButton" name="differentRB" >
+     <property name="text" >
+      <string>Use a different &amp;window manager:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0" colspan="2" >
+    <widget class="QRadioButton" name="kwinRB" >
+     <property name="text" >
+      <string>&amp;Use the default KDE window manager (KWin)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2" >
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QComboBox" name="wmCombo" >
+       <property name="enabled" >
+        <bool>false</bool>
+       </property>
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+         <horstretch>1</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="configureButton" >
+       <property name="enabled" >
+        <bool>false</bool>
+       </property>
+       <property name="text" >
+        <string>Configure</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="4" column="0" colspan="2" >
+    <widget class="QLabel" name="label" >
+     <property name="text" >
+      <string>Note: Most window managers have their own configuration and do not follow KDE settings.</string>
+     </property>
+     <property name="wordWrap" >
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="3" margin="6" />
+ <layoutfunction spacing="KDialog::spacingHint" margin="KDialog::marginHint" />
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <tabstops>
+  <tabstop>kwinRB</tabstop>
+  <tabstop>differentRB</tabstop>
+  <tabstop>wmCombo</tabstop>
+ </tabstops>
+ <includes>
+  <include location="local" >kdialog.h</include>
+ </includes>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>differentRB</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>wmCombo</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>20</x>
+     <y>42</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>47</x>
+     <y>72</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
Index: windowmanagers/compiz-custom.desktop
===================================================================
--- kcontrol/componentchooser/windowmanagers/compiz-custom.desktop	(revision 0)
+++ kcontrol/componentchooser/windowmanagers/compiz-custom.desktop	(revision 856682)
@@ -0,0 +1,42 @@
+[Desktop Entry]
+Name=Compiz custom (create wrapper script 'compiz-kde-launcher' to launch it)
+Name[ca]=Compiz personalitzat (crea un script embolcall 'compiz-kde-launcher' per a engegar-lo)
+Name[da]=Brugerdefineret Compiz (opret wrapper-scriptet 'compiz-kde-launcher' for at starte den)
+Name[de]=Compiz benutzerdefiniert (erstellen Sie ein Mantel-Skript namens ‚compiz-kde-launcher‘, um es zu starten)
+Name[el]=Προσαρμοσμένο Compiz (δημιουργία σεναρίου 'compiz-kde-launcher' για την εκκίνησή του)
+Name[eo]=Compiz propra (kreu interfacan skripton 'compiz-kde-launcher' por lanĉi ĝin)
+Name[es]=Compiz personalizado (crea un script 'compiz-kde-launcher' para ejecutarlo)
+Name[et]=Kohandatud Compiz (käivitamiseks loo kohandav skript 'compiz-kde-launcher')
+Name[fr]=Compiz personnalisé (utilisez un script d'enrobage « compiz-kde-launcher » pour le lancer)
+Name[fy]=Compiz oanpast (wrapper script 'compiz-kde-launcher' oanmeitsje om it út te fieren)
+Name[gl]=Compiz personalizado (crea un script "compiz-kde-launcher" para executalo)
+Name[gu]=પોતાનું કોમ્પિઝ (તેને શરૂ કરવા માટે 'compiz-kde-launcher' સ્ક્રિપ્ટ બનાવો)
+Name[hu]=Egyedi Compiz (indításához egy "compiz-kde-launcher" nevű szkript szükséges)
+Name[it]=Compiz personalizzato (per lanciarlo crea uno script «compiz-kde-launcher» che prepara l'ambiente)
+Name[km]=Compiz ផ្ទាល់ខ្លួន (បង្កើត​ស្គ្រីប​រុំ 'compiz-kde-launcher' ដើម្បី​ចាប់ផ្ដើម​វា)
+Name[ko]=사용자 정의 컴피즈 ('compiz-kde-launcher' 래퍼 스크립트로 실행함)
+Name[lv]=Pielāgots Compiz (lai to palaistu, izveidojiet palaišanas skriptu 'compiz-kde-launcher')
+Name[ml]=ക്രമീകൃതകോമ്പിസ്(create wrapper script 'compiz-kde-launcher' to launch it)
+Name[mr]=इच्छिक Compiz (दाखल करण्याकरीता 'compiz-kde-launcher' स्क्रिप्ट निर्माण करा)
+Name[nds]=Egen Compiz (För't Opropen deit en Skript "compiz-kde-launcher" noot)
+Name[nl]=Compiz custom (maak het script 'compiz-kde-launcher' aan om het te starten)
+Name[nn]=Compiz sjølvvald (lag skriptet «compiz-kde-launcher» for å starta det)
+Name[pl]=Compiz custom (utwórz skrypt "comiz-kde-launcher", aby go uruchomić)
+Name[pt]=Personalizado do Compiz (criar um programa de interface 'compiz-kde-launcher' para o invocar)
+Name[pt_BR]=Compiz personalizado (criar um script 'compiz-kde-launcher' para iniciá-lo)
+Name[ro]=Compiz particularizat (creare script „compiz-kde-launcher” pentru a-l lansa)
+Name[sl]=Prilagojen Compiz (za zagon ustvarite skript »compiz-kde-launcher«)
+Name[sr]=Посебни Компиз (направите омотачку скрипту ‘compiz-kde-launcher’ за покретање)
+Name[sr@latin]=Posebni Compiz (napravite omotačku skriptu ‘compiz-kde-launcher’ za pokretanje)
+Name[sv]=Egen Compiz (skapa omgivande skript 'compiz-kde-launcher' för att starta den)
+Name[te]=Compiz custom (దానిని దించుటకు వ్రాపర్ స్క్రిప్‍ట్‌ 'compiz-kde-launcher' ను సృష్టించుము)
+Name[th]=Compiz custom (สร้างสคริปต์ครอบ 'compiz-kde-launcher' เพื่อเรียกใช้มัน)
+Name[tr]=Compiz özel (çalıştırmak için sarıcı betik 'compiz-kde-launcher' oluştur)
+Name[uk]=Нетиповий Compiz (створити скрипт-обгортку "compiz-kde-launcher" для його запуску)
+Name[x-test]=xxCompiz custom (create wrapper script 'compiz-kde-launcher' to launch it)xx
+Name[zh_CN]=Compiz 定制(创建执行用包装脚本“compiz-kde-launcher”)
+Name[zh_TW]=Compiz 自訂(建立外包文稿 compiz-kde-launcher 來啟動)
+Exec=compiz-kde-launcher
+TryExec=compiz
+X-KDE-WindowManagerId=compiz
+X-KDE-WindowManagerRestartArgument=--replace
Index: windowmanagers/openbox.desktop
===================================================================
--- kcontrol/componentchooser/windowmanagers/openbox.desktop	(revision 0)
+++ kcontrol/componentchooser/windowmanagers/openbox.desktop	(revision 856682)
@@ -0,0 +1,18 @@
+[Desktop Entry]
+Name=Openbox
+Name[bn]=ওপেনবক্স
+Name[cy]=Blwchagored (Openbox)
+Name[gu]=ઓપનબોક્સ
+Name[hi]=ओपनबाक्स
+Name[km]=បើក​ប្រអប់​
+Name[ml]=ഓപ്പണ്‍ബോക്സ്
+Name[mr]=ओपनबाक्स
+Name[ne]=खुला बाकस
+Name[pa]=ਓਪਨ-ਬਾਕਸੇ
+Name[sr]=Опенбокс
+Name[ta]=திறப்பு பெட்டி
+Name[te]=ఒపెన్ బాక్స్
+Name[x-test]=xxOpenboxxx
+Exec=openbox
+TryExec=openbox
+X-KDE-WindowManagerRestartArgument=--replace
Index: windowmanagers/metacity.desktop
===================================================================
--- kcontrol/componentchooser/windowmanagers/metacity.desktop	(revision 0)
+++ kcontrol/componentchooser/windowmanagers/metacity.desktop	(revision 856682)
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Name=Metacity (GNOME)
+Name[cs]=Metacity (Gnome)
+Name[gu]=મેટાસિટી (GNOME)
+Name[ko]=Metacity (그놈)
+Name[ml]=മെറ്റാസിറ്റി (ഗ്നോം)
+Name[mr]=मेटासिटी (GNOME)
+Name[pa]=ਮੈਟਾਸਿਟੀ (ਗਨੋਮ)
+Name[sr]=Метасити (Гном)
+Name[sr@latin]=Metacity (Gnome)
+Name[te]=మెటాసిటి (GNOME)
+Name[x-test]=xxMetacity (GNOME)xx
+Name[zh_CN]=Metacity(GNOME)
+Name[zh_TW]=Metacity(GNOME)
+Exec=metacity
+TryExec=metacity
+X-KDE-WindowManagerRestartArgument=--replace
Index: windowmanagers/compiz.desktop
===================================================================
--- kcontrol/componentchooser/windowmanagers/compiz.desktop	(revision 0)
+++ kcontrol/componentchooser/windowmanagers/compiz.desktop	(revision 856682)
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Name=Compiz
+Name[gu]=કોમ્પિઝ
+Name[ko]=컴피즈
+Name[ml]=കോമ്പിസ്
+Name[mr]=कॉम्पीज
+Name[pa]=ਕੰਪਿਜ਼
+Name[sr]=Компиз
+Name[x-test]=xxCompizxx
+Exec=compiz ccp
+TryExec=compiz
+X-KDE-WindowManagerConfigure=simple-ccsm
+X-KDE-WindowManagerRestartArgument=--replace
Index: windowmanagers/CMakeLists.txt
===================================================================
--- kcontrol/componentchooser/windowmanagers/CMakeLists.txt	(revision 0)
+++ kcontrol/componentchooser/windowmanagers/CMakeLists.txt	(revision 856682)
@@ -0,0 +1,5 @@
+########### install files ###############
+file(GLOB desktop_file "*.desktop")
+
+install( FILES ${desktop_file}
+    DESTINATION ${DATA_INSTALL_DIR}/ksmserver/windowmanagers )
Index: windowmanagers/README
===================================================================
--- kcontrol/componentchooser/windowmanagers/README	(revision 0)
+++ kcontrol/componentchooser/windowmanagers/README	(revision 856682)
@@ -0,0 +1,33 @@
+The list of window managers that the config module offers for using.
+The format is normal .desktop files:
+
+Name - required, name to display in the configuration dialog.
+
+Exec - required, the command to execute to launch the window manager.
+    If launching fails for any reason, it must quit with non-zero exit
+    value and not do anything else (show an error dialog, try to run
+    a fallback, etc.).
+    
+TryExec - optional.
+
+X-KDE-WindowManagerTestExec - optional, a command that will be run and if
+    the exit code is not 0, the window manager won't be used (can be used
+    e.g. to detect that a window manager which requires compositing support
+    cannot be run on systems without such support).
+
+X-KDE-WindowManagerId - optional, the name under which the window manager
+    registers with the session manager (if different from the name
+    of the .desktop file)
+
+X-KDE-WindowManagerConfigure - optional, the command to run to configure
+    the window manager
+
+X-KDE-WindowManagerRestartArgument - optional, the argument to pass
+    to the window manager to restart it directly in the running KDE
+    session; if not present, KDE restart is required (which is generally
+    a good idea anyway, but this can be useful for e.g. checking)
+
+X-KDE-WindowManagerConfigureParentArgument - option, if present, this
+    argument and the X window id of the configuration dialog will be passed
+    to the configuration command (e.g. '--parent 13254543'). The configuration
+    tool may specify this window as the parent of its window.

Property changes on: windowmanagers
___________________________________________________________________
Added: svn:mergeinfo

Index: ktimerdialog.cpp
===================================================================
--- kcontrol/componentchooser/ktimerdialog.cpp	(revision 0)
+++ kcontrol/componentchooser/ktimerdialog.cpp	(revision 856682)
@@ -0,0 +1,173 @@
+/*
+ *  This file is part of the KDE Libraries
+ *  Copyright (C) 2002 Hamish Rodda <rodda@kde.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ktimerdialog.h"
+
+#include <QLabel>
+#include <QLayout>
+#include <QPixmap>
+#include <QTimer>
+
+#include <QtGui/QProgressBar>
+
+#include <kwindowsystem.h>
+#include <kiconloader.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kvbox.h>
+
+#include "ktimerdialog.moc"
+
+KTimerDialog::KTimerDialog( int msec, TimerStyle style, QWidget *parent,
+                 const QString &caption,
+                 int buttonMask, ButtonCode defaultButton,
+                 bool separator,
+                 const KGuiItem &user1,
+                 const KGuiItem &user2,
+                 const KGuiItem &user3 )
+    : KDialog( parent )
+{
+    setCaption( caption );
+    setButtons( (ButtonCodes)buttonMask );
+    setDefaultButton( defaultButton );
+    setButtonFocus( defaultButton ); // setDefaultButton() doesn't do this
+    showButtonSeparator( separator );
+    setButtonGuiItem( User1, user1 );
+    setButtonGuiItem( User2, user2 );
+    setButtonGuiItem( User3, user3 );
+
+    totalTimer = new QTimer( this );
+    totalTimer->setSingleShot( true );
+    updateTimer = new QTimer( this );
+    updateTimer->setSingleShot( false );
+    msecTotal = msecRemaining = msec;
+    updateInterval = 1000;
+    tStyle = style;
+    KWindowSystem::setIcons( winId(), DesktopIcon("randr"), SmallIcon("randr") );
+    // default to canceling the dialog on timeout
+    if ( buttonMask & Cancel )
+        buttonOnTimeout = Cancel;
+
+    connect( totalTimer, SIGNAL( timeout() ), SLOT( slotInternalTimeout() ) );
+    connect( updateTimer, SIGNAL( timeout() ), SLOT( slotUpdateTime() ) );
+
+    // create the widgets
+    mainWidget = new KVBox( this );
+    timerWidget = new KHBox( mainWidget );
+    timerWidget->setSpacing(KDialog::spacingHint());
+    timerLabel = new QLabel( timerWidget );
+    timerProgress = new QProgressBar( timerWidget );
+    timerProgress->setRange( 0, msecTotal );
+    timerProgress->setTextVisible( false );
+
+    KDialog::setMainWidget( mainWidget );
+
+    slotUpdateTime( false );
+}
+
+KTimerDialog::~KTimerDialog()
+{
+}
+
+void KTimerDialog::setVisible( bool visible )
+{
+    KDialog::setVisible( visible );
+  
+    if ( visible ) {
+        totalTimer->start( msecTotal );
+        updateTimer->start( updateInterval );
+    }
+}
+
+int KTimerDialog::exec()
+{
+    totalTimer->start( msecTotal );
+    updateTimer->start( updateInterval );
+    return KDialog::exec();
+}
+
+void KTimerDialog::setMainWidget( QWidget *widget )
+{
+    // yuck, here goes.
+    KVBox *newWidget = new KVBox( this );
+
+    if ( widget->parentWidget() != mainWidget ) {
+        widget->setParent( newWidget);
+    } 
+    timerWidget->setParent( newWidget);
+
+    delete mainWidget;
+    mainWidget = newWidget;
+    KDialog::setMainWidget( mainWidget );
+}
+
+void KTimerDialog::setRefreshInterval( int msec )
+{
+    updateInterval = msec;
+    if ( updateTimer->isActive() )
+        updateTimer->start( updateInterval );
+}
+
+int KTimerDialog::timeoutButton() const
+{
+    return buttonOnTimeout;
+}
+
+void KTimerDialog::setTimeoutButton( const ButtonCode newButton )
+{
+    buttonOnTimeout = newButton;
+}
+
+int KTimerDialog::timerStyle() const
+{
+    return tStyle;
+}
+
+void KTimerDialog::setTimerStyle( const TimerStyle newStyle )
+{
+    tStyle = newStyle;
+}
+
+void KTimerDialog::slotUpdateTime( bool update )
+{
+    if ( update )
+        switch ( tStyle ) {
+            case CountDown:
+                msecRemaining -= updateInterval;
+                break;
+            case CountUp:
+                msecRemaining += updateInterval;
+                break;
+            case Manual:
+                break;
+        }
+
+    timerProgress->setValue( msecRemaining );
+
+    timerLabel->setText( i18np("1 second remaining:","%1 seconds remaining:",msecRemaining/1000) );
+}
+
+void KTimerDialog::slotInternalTimeout()
+{
+    emit timerTimeout();
+    slotButtonClicked( buttonOnTimeout );
+}
Index: ktimerdialog.h
===================================================================
--- kcontrol/componentchooser/ktimerdialog.h	(revision 0)
+++ kcontrol/componentchooser/ktimerdialog.h	(revision 856682)
@@ -0,0 +1,172 @@
+/*
+ *  This file is part of the KDE Libraries
+ *  Copyright (C) 2002 Hamish Rodda <rodda@kde.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef _KTIMERDIALOG_H_
+#define _KTIMERDIALOG_H_
+
+#include <QLabel>
+
+#include <kdialog.h>
+#include <kvbox.h>
+
+class QTimer;
+class KHBox;
+class QProgressBar;
+class QLabel;
+
+/**
+ * Provides a dialog that is only available for a specified amount
+ * of time, and reports the time remaining to the user.
+ *
+ * The timer is capable of counting up or down, for any number of milliseconds.
+ * 
+ * The button which is activated upon timeout can be specified, as can the
+ * update interval for the dialog box.
+ *
+ * In addition, this class retains all of the functionality of @see KDialog.
+ *
+ * @short A dialog with a time limit and corresponding UI features.
+ * @author Hamish Rodda <rodda@kde.org>
+ */
+class KTimerDialog : public KDialog
+{
+  Q_OBJECT
+
+  public:
+
+    /**
+     * @li @p CountDown - The timer counts downwards from the seconds given.
+     * @li @p CountUp - The timer counts up to the number of seconds given.
+     * @li @p Manual - The timer is not invoked; the caller must update the
+     * progress.
+     */
+    enum TimerStyle
+    {
+        CountDown,
+        CountUp,
+        Manual
+    };
+
+    /**
+     * Constructor for the standard mode where you must specify the main
+     * widget with @ref setMainWidget() . See @see KDialog for further details.
+     *
+     * For the rest of the arguments, See @see KDialog .
+     */
+    explicit KTimerDialog( int msec, TimerStyle style=CountDown, QWidget *parent=0,
+                           const QString &caption=QString(),
+                           int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok,
+                           bool separator=false,
+                           const KGuiItem &user1=KGuiItem(),
+                           const KGuiItem &user2=KGuiItem(),
+                           const KGuiItem &user3=KGuiItem() );
+
+    /**
+     * Destructor.
+     */
+    ~KTimerDialog();
+
+    /**
+     * Execute the dialog modelessly - see @see QDialog .
+     */
+    virtual void setVisible( bool visible );
+
+    /**
+     * Set the refresh interval for the timer progress. Defaults to one second.
+     */
+    void setRefreshInterval( int msec );
+
+    /**
+     * Retrieves the @ref ButtonCode which will be activated once the timer
+     * times out. @see setTimeoutButton
+     */
+    int timeoutButton() const;
+
+    /**
+     * Sets the @ref ButtonCode to determine which button will be activated
+     * once the timer times out. @see timeoutButton
+     */
+    void setTimeoutButton( ButtonCode newButton );
+
+    /**
+     * Retrieves the current @ref TimerStyle. @see setTimerStyle
+     */
+    int timerStyle() const;
+
+    /**
+     * Sets the @ref TimerStyle. @see timerStyle
+     */
+    void setTimerStyle( TimerStyle newStyle );
+
+    /**
+     * Overridden function which is used to set the main widget of the dialog.
+     * @see KDialog::setMainWidget.
+     */
+    void setMainWidget( QWidget *widget );
+
+  Q_SIGNALS:
+    /**
+     * Signal which is emitted once the timer has timed out.
+     */
+    void timerTimeout();
+
+  public Q_SLOTS:
+    /**
+     * Execute the dialog modally - see @see QDialog .
+     */
+    int exec();
+
+  private Q_SLOTS:
+    /**
+     * Updates the dialog with the current progress levels.
+     */
+    void slotUpdateTime( bool update = true );
+
+    /**
+     * The internal
+     */
+    void slotInternalTimeout();
+
+  private:
+    /**
+     * Prepares the layout that manages the widgets of the dialog
+     */
+    void setupLayout();
+
+    QTimer *totalTimer;
+    QTimer *updateTimer;
+    int msecRemaining, updateInterval, msecTotal;
+
+    ButtonCode buttonOnTimeout;
+    TimerStyle tStyle;
+
+    KHBox *timerWidget;
+    QProgressBar *timerProgress;
+    QLabel *timerLabel;
+    KVBox *mainWidget;
+
+    class KTimerDialogPrivate;
+    KTimerDialogPrivate *d;
+};
+
+#endif
+
+
+
Index: componentservices/kcm_wm.desktop
===================================================================
--- kcontrol/componentchooser/componentservices/kcm_wm.desktop	(revision 0)
+++ kcontrol/componentchooser/componentservices/kcm_wm.desktop	(revision 856682)
@@ -0,0 +1,28 @@
+Name=Window Manager
+Name[et]=Aknahaldur
+Name[ga]=Bainisteoir Fuinneog
+Name[gl]=Xestor de fiestras
+Name[gu]=વિન્ડો વ્યવસ્થાપક
+Name[he]=מנהל חלונות
+Name[ja]=ウィンドウマネージャ
+Name[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច
+Name[nds]=Finsterpleger
+Name[pt]=Gestor de Janelas
+Name[pt_BR]=Gestor de Janelas
+Name[sl]=Upravljalnik oken
+Name[sv]=Fönsterhanterare
+Name[tr]=Pencere Yöneticisi
+Name[uk]=Віконний менеджер
+Name[zh_TW]=視窗管理員
+Comment=Here you can select the window manager to be run in your KDE session.
+Comment[et]=Siin saab valida KDE seansis kasutatava aknahalduri.
+Comment[gl]=Aquí pode escoller a xestor de fiestrar a executar na sesión de KDE.
+Comment[km]=នៅ​ទីនេះ អ្នក​អាច​ជ្រើស​កម្មវិធី​គ្រប់គ្រង​បង្អួច​ឲ្យ​រត់​នៅ​ក្នុង​សម័យ KDE របស់​អ្នក ។
+Comment[nds]=Hier kannst Du den Finsterpleger utsöken, den Du för Dien KDE-Törns bruken wullt.
+Comment[pt]=Aqui poderá seleccionar o gestor de janelas a executar na sua sessão do KDE.
+Comment[pt_BR]=Aqui poderá seleccionar o gestor de janelas a executar na sua sessão do KDE.
+Comment[sl]=Tu lahko izberete upravljalnika oken, ki bo v uporabi v KDE.
+Comment[sv]=Här kan du välja fönsterhanterare som ska köras i KDE-sessionen.
+Comment[uk]=Тут ви можете обрати засіб керування вікнами, який буде запущено у вашому сеансі KDE.
+Comment[zh_TW]=您可以在此選擇 KDE 工作階段執行的視窗管理員。
+configurationType=internal_wm
Index: componentservices/CMakeLists.txt
===================================================================
--- kcontrol/componentchooser/componentservices/CMakeLists.txt	(revision 847439)
+++ kcontrol/componentchooser/componentservices/CMakeLists.txt	(revision 856682)
@@ -1,4 +1,4 @@
 install( FILES kcm_kemail.desktop kcm_browser.desktop  DESTINATION  ${DATA_INSTALL_DIR}/kcm_componentchooser )
 if(NOT WIN32)
-  install( FILES kcm_terminal.desktop DESTINATION  ${DATA_INSTALL_DIR}/kcm_componentchooser)
+  install( FILES kcm_terminal.desktop kcm_wm.desktop DESTINATION  ${DATA_INSTALL_DIR}/kcm_componentchooser)
 endif(NOT WIN32)
Index: componentchooser.cpp
===================================================================
--- kcontrol/componentchooser/componentchooser.cpp	(revision 847439)
+++ kcontrol/componentchooser/componentchooser.cpp	(revision 856682)
@@ -20,6 +20,7 @@
 #include "componentchooser.moc"
 #ifdef Q_OS_UNIX
 #include "componentchooserterminal.h"
+#include "componentchooserwm.h"
 #endif
 
 #include <QCheckBox>
@@ -385,6 +386,14 @@
 		}
 
 	}
+	else if (cfgType=="internal_wm")
+	{
+		if (!(configWidget && qobject_cast<CfgWm*>(configWidget)))
+		{
+			newConfigWidget = new CfgWm(configContainer);
+		}
+
+	}
 #endif
 	else if (cfgType=="internal_browser")
 	{
Index: componentchooserwm.cpp
===================================================================
--- kcontrol/componentchooser/componentchooserwm.cpp	(revision 0)
+++ kcontrol/componentchooser/componentchooserwm.cpp	(revision 856682)
@@ -0,0 +1,298 @@
+/***************************************************************************
+                          componentchooserwm.cpp  -  description
+                             -------------------
+    copyright            : (C) 2002 by Joseph Wenninger
+    email                : jowenn@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License verstion 2 as    *
+ *   published by the Free Software Foundation                             *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "componentchooserwm.h"
+#include "componentchooserwm.moc"
+
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kshell.h>
+#include <kstandarddirs.h>
+#include <ktimerdialog.h>
+#include <qdbusinterface.h>
+#include <qdbusconnectioninterface.h>
+#include <netwm.h>
+#include <qx11info_x11.h>
+
+CfgWm::CfgWm(QWidget *parent)
+: WmConfig_UI(parent)
+, CfgPlugin()
+, wmLaunchingState( WmNone )
+, wmProcess( NULL )
+{
+    connect(wmCombo,SIGNAL(activated(int)), this, SLOT(configChanged()));
+    connect(kwinRB,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
+    connect(differentRB,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
+    connect(differentRB,SIGNAL(toggled(bool)),this,SLOT(checkConfigureWm()));
+    connect(wmCombo,SIGNAL(activated(int)),this,SLOT(checkConfigureWm()));
+    connect(configureButton,SIGNAL(clicked()),this,SLOT(configureWm()));
+
+    KGlobal::dirs()->addResourceType( "windowmanagers", "data", "ksmserver/windowmanagers" );
+}
+
+CfgWm::~CfgWm()
+{
+}
+
+void CfgWm::configChanged()
+{
+    emit changed(true);
+}
+
+void CfgWm::defaults()
+{
+    wmCombo->setCurrentIndex( 0 );
+}
+
+
+void CfgWm::load(KConfig *)
+{
+    KConfig cfg("ksmserverrc", KConfig::NoGlobals);
+    KConfigGroup c( &cfg, "General");
+    loadWMs(c.readEntry("windowManager", "kwin"));
+    emit changed(false);
+}
+
+void CfgWm::save(KConfig *)
+{
+    saveAndConfirm();
+}
+
+bool CfgWm::saveAndConfirm()
+{
+    KConfig cfg("ksmserverrc", KConfig::NoGlobals);
+    KConfigGroup c( &cfg, "General");
+    c.writeEntry("windowManager", currentWm());
+    emit changed(false);
+    if( oldwm == currentWm())
+        return true;
+    QString restartArgument = currentWmData().restartArgument;
+    if( restartArgument.isEmpty())
+    {
+        KMessageBox::information( this,
+            i18n( "The new window manager will be used when KDE is started the next time." ),
+            i18n( "Window manager change" ), "windowmanagerchange" );
+        oldwm = currentWm();
+        return true;
+    }
+    else
+    {
+        if( tryWmLaunch())
+        {
+            oldwm = currentWm();
+            cfg.sync();
+            QDBusInterface ksmserver("org.kde.ksmserver", "/KSMServer" );
+            ksmserver.call( QDBus::NoBlock, "wmChanged" );
+            KMessageBox::information( window(),
+                i18n( "A new window manager is running.\n"
+                    "It is still recommended to restart this KDE session to make sure "
+                    "all running applications adjust for this change." ),
+                    i18n( "Window Manager Replaced" ), "restartafterwmchange" );
+            return true;
+        }
+        else
+        { // revert config
+            emit changed(true);
+            c.writeEntry("windowManager", oldwm);
+            if( oldwm == "kwin" )
+            {
+                kwinRB->setChecked( true );
+                wmCombo->setEnabled( false );
+            }
+            else
+            {
+                differentRB->setChecked( true );
+                wmCombo->setEnabled( true );
+                for( QHash< QString, WmData >::ConstIterator it = wms.begin();
+                     it != wms.end();
+                     ++it )
+                {
+                    if( (*it).internalName == oldwm ) // make it selected
+                        wmCombo->setCurrentIndex( wmCombo->findText( it.key()));
+                }
+            }
+            return false;
+        }
+    }
+}
+
+bool CfgWm::tryWmLaunch()
+{
+    if( currentWm() == "kwin"
+        && qstrcmp( NETRootInfo( QX11Info::display(), NET::SupportingWMCheck ).wmName(), "KWin" ) == 0 )
+    {
+        return true; // it is already running, don't necessarily restart e.g. after a failure with other WM
+    }
+    KMessageBox::information( window(), i18n( "Your running window manager will be now replaced with "
+        "the configured one." ), i18n( "Window manager change" ), "windowmanagerchange" );
+    wmLaunchingState = WmLaunching;
+    wmProcess = new KProcess;
+    *wmProcess << KShell::splitArgs( currentWmData().exec ) << currentWmData().restartArgument;
+    connect( wmProcess, SIGNAL( error( QProcess::ProcessError )), this, SLOT( wmLaunchError()));
+    connect( wmProcess, SIGNAL( finished( int, QProcess::ExitStatus )),
+        this, SLOT( wmLaunchFinished( int, QProcess::ExitStatus )));
+    wmProcess->start();
+    wmDialog = new KTimerDialog( 20000, KTimerDialog::CountDown, window(), i18n( "Config Window Manager Change" ),
+        KTimerDialog::Ok | KTimerDialog::Cancel, KTimerDialog::Cancel );
+    wmDialog->setButtonGuiItem( KDialog::Ok, KGuiItem( i18n( "&Accept Change" ), "dialog-ok" ));
+    wmDialog->setButtonGuiItem( KDialog::Cancel, KGuiItem( i18n( "&Revert to Previous" ), "dialog-cancel" ));
+    QLabel *label = new QLabel(
+        i18n( "The configured window manager has been launched.\n"
+            "Please check it has started properly and confirm the change.\n"
+            "The launch will be automatically reverted in 20 seconds." ), wmDialog );
+    label->setWordWrap( true );
+    wmDialog->setMainWidget( label );
+    if( wmDialog->exec() == QDialog::Accepted ) // the user confirmed
+        wmLaunchingState = WmOk;
+    else // cancelled for some reason
+        {
+        if( wmLaunchingState == WmLaunching )
+            { // time out
+            wmLaunchingState = WmFailed;
+            KProcess::startDetached( "kwin", QStringList() << "--replace" );
+            // Let's hope KWin never fails.
+            KMessageBox::sorry( window(),
+                i18n( "The running window manager has been reverted to the default KDE window manager KWin." ));
+            }
+        else if( wmLaunchingState == WmFailed )
+            {
+            KProcess::startDetached( "kwin", QStringList() << "--replace" );
+            // Let's hope KWin never fails.
+            KMessageBox::sorry( window(),
+                i18n( "The new window manager has failed to start.\n"
+                    "The running window manager has been reverted to the default KDE window manager KWin." ));
+            }
+        }
+    bool ret = ( wmLaunchingState == WmOk );
+    wmLaunchingState = WmNone;
+    delete wmDialog;
+    wmDialog = NULL;
+    // delete wmProcess; - it is intentionally leaked, since there is no KProcess:detach()
+    wmProcess = NULL;
+    return ret;
+}
+
+void CfgWm::wmLaunchError()
+{
+    if( wmLaunchingState != WmLaunching || sender() != wmProcess )
+        return;
+    wmLaunchingState = WmFailed;
+    wmDialog->reject();
+}
+
+
+void CfgWm::wmLaunchFinished( int exitcode, QProcess::ExitStatus exitstatus )
+{
+    if( wmLaunchingState != WmLaunching || sender() != wmProcess )
+        return;
+    if( exitstatus == QProcess::NormalExit && exitcode == 0 )
+        { // assume it's forked into background
+        wmLaunchingState = WmOk;
+        return;
+        }
+    // otherwise it's a failure
+    wmLaunchingState = WmFailed;
+    wmDialog->reject();
+}
+
+void CfgWm::loadWMs( const QString& current )
+{
+    WmData kwin;
+    kwin.internalName = "kwin";
+    kwin.exec = "kwin";
+    kwin.configureCommand = "";
+    kwin.restartArgument = "--replace";
+    kwin.parentArgument = "";
+    wms[ "KWin" ] = kwin;
+    oldwm = "kwin";
+    kwinRB->setChecked( true );
+    wmCombo->setEnabled( false );
+    
+    QStringList list = KGlobal::dirs()->findAllResources( "windowmanagers", QString(), KStandardDirs::NoDuplicates );
+    QRegExp reg( ".*/([^/\\.]*)\\.[^/\\.]*" );
+    foreach( const QString& wmfile, list )
+    {
+        KDesktopFile file( wmfile );
+        if( file.noDisplay())
+            continue;
+        if( !file.tryExec())
+            continue;
+        QString testexec = file.desktopGroup().readEntry( "X-KDE-WindowManagerTestExec" );
+        if( !testexec.isEmpty())
+        {
+            KProcess proc;
+            proc.setShellCommand( testexec );
+            if( proc.execute() != 0 )
+                continue;
+        }
+        QString name = file.readName();
+        if( name.isEmpty())
+            continue;
+        if( !reg.exactMatch( wmfile ))
+            continue;
+        QString wm = reg.cap( 1 );
+        if( wms.contains( name ))
+            continue;
+        WmData data;
+        data.internalName = wm;
+        data.exec = file.desktopGroup().readEntry( "Exec" );
+        if( data.exec.isEmpty())
+            continue;
+        data.configureCommand = file.desktopGroup().readEntry( "X-KDE-WindowManagerConfigure" );
+        data.restartArgument = file.desktopGroup().readEntry( "X-KDE-WindowManagerRestartArgument" );
+        data.parentArgument = file.desktopGroup().readEntry( "X-KDE-WindowManagerConfigureParentArgument" );
+        wms[ name ] = data;
+        wmCombo->addItem( name );
+        if( wms[ name ].internalName == current ) // make it selected
+        {
+            wmCombo->setCurrentIndex( wmCombo->count() - 1 );
+            oldwm = wm;
+            differentRB->setChecked( true );
+            wmCombo->setEnabled( true );
+        }
+    }
+    checkConfigureWm();
+}
+
+CfgWm::WmData CfgWm::currentWmData() const
+{
+    return kwinRB->isChecked() ? wms[ "KWin" ] : wms[ wmCombo->currentText() ];
+}
+
+QString CfgWm::currentWm() const
+{
+    return currentWmData().internalName;
+}
+
+void CfgWm::checkConfigureWm()
+{
+    configureButton->setEnabled( !currentWmData().configureCommand.isEmpty());
+}
+
+void CfgWm::configureWm()
+{
+    if( oldwm != currentWm() // needs switching first
+        && !saveAndConfirm())
+    {
+        return;
+    }
+    QStringList args;
+    if( !currentWmData().parentArgument.isEmpty())
+        args << currentWmData().parentArgument << QString::number( window()->winId());
+    if( !KProcess::startDetached( currentWmData().configureCommand, args ))
+        KMessageBox::sorry( window(), i18n( "Running the configuration tool failed" ));
+}
Index: CMakeLists.txt
===================================================================
--- kcontrol/componentchooser/CMakeLists.txt	(revision 847439)
+++ kcontrol/componentchooser/CMakeLists.txt	(revision 856682)
@@ -1,5 +1,6 @@
 
 add_subdirectory( componentservices ) 
+add_subdirectory( windowmanagers ) 
 
 
 
@@ -8,14 +9,15 @@
 set(kcm_componentchooser_PART_SRCS componentchooser.cpp kcm_componentchooser.cpp )
 
 if(NOT WIN32)
-  set(kcm_componentchooser_PART_SRCS ${kcm_componentchooser_PART_SRCS} componentchooserterminal.cpp)
+  set(kcm_componentchooser_PART_SRCS ${kcm_componentchooser_PART_SRCS}
+    componentchooserterminal.cpp componentchooserwm.cpp ktimerdialog.cpp)
 endif(NOT WIN32)
 
 
 kde4_add_ui_files(kcm_componentchooser_PART_SRCS browserconfig_ui.ui emailclientconfig_ui.ui componentchooser_ui.ui componentconfig_ui.ui) 
 
 if(NOT WIN32)
-  kde4_add_ui_files(kcm_componentchooser_PART_SRCS terminalemulatorconfig_ui.ui)
+  kde4_add_ui_files(kcm_componentchooser_PART_SRCS terminalemulatorconfig_ui.ui wmconfig_ui.ui)
 endif(NOT WIN32)
 
 kde4_add_plugin(kcm_componentchooser ${kcm_componentchooser_PART_SRCS})