commit b9517a6bc31dd38f5a14819b7070e422ca01cbce
Author: David Nadlinger <david.nadlinger@gmail.com>
Date:   Wed Nov 19 20:34:47 2008 +0100

    Save a backup of kwinrc to another file to revert if the X server crashes while testing the new config.

diff --git a/kcmkwin/kwincompositing/main.cpp b/kcmkwin/kwincompositing/main.cpp
index cd3593d..fac67a5 100644
--- a/kcmkwin/kwincompositing/main.cpp
+++ b/kcmkwin/kwincompositing/main.cpp
@@ -25,6 +25,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <kaboutdata.h>
 #include <kconfig.h>
 #include <kconfiggroup.h>
+#include <kstandarddirs.h>
 #include <kdebug.h>
 #include <kmessagebox.h>
 #include <ksettings/dispatcher.h>
@@ -34,6 +35,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <kservice.h>
 #include <ktitlewidget.h>
 
+#include <QFile>
 #include <QtDBus/QtDBus>
 #include <QTimer>
 #include <QLabel>
@@ -68,9 +70,8 @@ ConfirmDialog::ConfirmDialog() :
 
 KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList &)
     : KCModule( KWinCompositingConfigFactory::componentData(), parent),
-        mKWinConfig(KSharedConfig::openConfig("kwinrc")),
-        m_showConfirmDialog (false)
-{
+        mNewConfig( KSharedConfig::openConfig( "kwinrc" ) )
+    {
     KGlobal::locale()->insertCatalog( "kwin_effects" );
     ui.setupUi(this);
     layout()->setMargin(0);
@@ -107,6 +108,16 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList
     connect(ui.glVSync, SIGNAL(toggled(bool)), this, SLOT(changed()));
     connect(ui.xrenderSmoothScale, SIGNAL(toggled(bool)), this, SLOT(changed()));
 
+    // Create the backup config. It will be used as a means to revert the config if
+    // the X server crashes and to determine if a confirmation dialog should be shown.
+    // After the new settings have been confirmed to be stable, it is updated with the new
+    // config. It will be written to disk before a new config is loaded and is deleted after
+    // the user has confirmed the new settings.
+    mBackupConfig = new KConfig( mNewConfig->name() + '~', KConfig::SimpleConfig );
+    // If the backup file already exists, it is a residue we want to clean up; it would
+    // probably be in an invalid state anyway.
+    deleteBackupConfigFile();
+
     // Open the temporary config file
     // Temporary conf file is used to synchronize effect checkboxes with effect
     //  selector by loading/saving effects from/to temp config when active tab
@@ -181,13 +192,11 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList
 }
 
 KWinCompositingConfig::~KWinCompositingConfig()
-{
-}
-
-void KWinCompositingConfig::reparseConfiguration(const QByteArray&conf)
-{
-    KSettings::Dispatcher::reparseConfiguration(conf);
-}
+    {
+    // Make sure that the backup config is not written to disk.
+    mBackupConfig->markAsClean();
+    delete mBackupConfig;
+    }
 
 void KWinCompositingConfig::compositingEnabled(bool enabled)
 {
@@ -195,45 +204,7 @@ void KWinCompositingConfig::compositingEnabled(bool enabled)
     ui.tabWidget->setTabEnabled(1, enabled);
     ui.tabWidget->setTabEnabled(2, enabled);
     ui.tabWidget->setTabEnabled(3, enabled);
-}
-
-void KWinCompositingConfig::showConfirmDialog(bool reinitCompositing)
-{
-    bool revert = false;
-    // Feel free to extend this to support several kwin instances (multihead) if you
-    // think it makes sense.
-    OrgKdeKWinInterface kwin("org.kde.kwin", "/KWin", QDBusConnection::sessionBus());
-    if( reinitCompositing ? !kwin.compositingActive().value() : !kwin.waitForCompositingSetup().value() )
-    {
-        KMessageBox::sorry( this, i18n(
-            "Failed to activate desktop effects using the given "
-            "configuration options. Settings will be reverted to their previous values.\n\n"
-            "Check your X configuration. You may also consider changing advanced options, "
-            "especially changing the compositing type." ));
-        revert = true;
-    }
-    else
-    {
-        ConfirmDialog confirm;
-        if( !confirm.exec())
-            revert = true;
-    }
-    if( revert )
-    {
-        // Revert settings
-        KConfigGroup config(mKWinConfig, "Compositing");
-        config.deleteGroup();
-        QMap<QString, QString>::const_iterator it = mPreviousConfig.constBegin();
-        for(; it != mPreviousConfig.constEnd(); ++it) {
-            if (it.value().isEmpty())
-                continue;
-            config.writeEntry(it.key(), it.value());
-        }
-        // Sync with KWin and reload
-        configChanged(reinitCompositing);
-        load();
     }
-}
 
 void KWinCompositingConfig::initEffectSelector()
 {
@@ -273,8 +244,8 @@ void KWinCompositingConfig::currentTabChanged(int tab)
 }
 
 void KWinCompositingConfig::loadGeneralTab()
-{
-    KConfigGroup config(mKWinConfig, "Compositing");
+    {
+    KConfigGroup config(mNewConfig, "Compositing");
     ui.useCompositing->setChecked(config.readEntry("Enabled", mDefaultPrefs.enableCompositing()));
     ui.animationSpeedCombo->setCurrentIndex(config.readEntry("AnimationSpeed", 3 ));
 
@@ -301,14 +272,14 @@ void KWinCompositingConfig::loadGeneralTab()
         ui.windowSwitchingCombo->setCurrentIndex( 3 );
     if( effectEnabled( "flipswitch", effectconfig ))
         ui.windowSwitchingCombo->setCurrentIndex( 4 );
-    KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows");
+    KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows");
     if( effectEnabled( "presentwindows", effectconfig ) && presentwindowsconfig.readEntry("TabBox", false) )
         ui.windowSwitchingCombo->setCurrentIndex( 2 );
 
     // desktop switching
     if( effectEnabled( "slide", effectconfig ))
         ui.desktopSwitchingCombo->setCurrentIndex( 1 );
-    KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube");
+    KConfigGroup cubeconfig(mNewConfig, "Effect-Cube");
     if( effectEnabled( "cube", effectconfig ) && cubeconfig.readEntry("AnimateDesktopChange", false))
         ui.desktopSwitchingCombo->setCurrentIndex( 2 );
 
@@ -331,8 +302,8 @@ void KWinCompositingConfig::loadEffectsTab()
 }
 
 void KWinCompositingConfig::loadAdvancedTab()
-{
-    KConfigGroup config(mKWinConfig, "Compositing");
+    {
+    KConfigGroup config(mNewConfig, "Compositing");
     QString backend = config.readEntry("Backend", "OpenGL");
     ui.compositingType->setCurrentIndex((backend == "XRender") ? 1 : 0);
     // 4 - off, 5 - shown, 6 - always, other are old values
@@ -355,18 +326,13 @@ void KWinCompositingConfig::loadAdvancedTab()
 }
 
 void KWinCompositingConfig::load()
-{
-    mKWinConfig->reparseConfiguration();
-
-    // Copy Plugins group to temp config file
-    QMap<QString, QString> entries = mKWinConfig->entryMap("Plugins");
-    QMap<QString, QString>::const_iterator it = entries.constBegin();
-    KConfigGroup tmpconfig(mTmpConfig, "Plugins");
-    tmpconfig.deleteGroup();
-    for(; it != entries.constEnd(); ++it)
     {
-        tmpconfig.writeEntry(it.key(), it.value());
-    }
+    mNewConfig->reparseConfiguration();
+
+    updateBackupWithNewConfig();
+
+    // Copy the plugin settings from the main config file to the temp config.
+    copyPluginsToTmpConfig();
 
     loadGeneralTab();
     loadEffectsTab();
@@ -376,14 +342,8 @@ void KWinCompositingConfig::load()
 }
 
 void KWinCompositingConfig::saveGeneralTab()
-{
-    KConfigGroup config(mKWinConfig, "Compositing");
-    // Check if any critical settings that need confirmation have changed
-    if(ui.useCompositing->isChecked()
-        && ui.useCompositing->isChecked() != config.readEntry("Enabled", mDefaultPrefs.enableCompositing()))
-        {
-        m_showConfirmDialog = true;
-        }
+    {
+    KConfigGroup config(mNewConfig, "Compositing");
 
     config.writeEntry("Enabled", ui.useCompositing->isChecked());
     config.writeEntry("AnimationSpeed", ui.animationSpeedCombo->currentIndex());
@@ -439,7 +399,7 @@ void KWinCompositingConfig::saveGeneralTab()
             effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", true);
             break;
         }
-    KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows");
+    KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows");
     presentwindowsconfig.writeEntry("TabBox", presentWindowSwitching);
 
     int desktopSwitcher = ui.desktopSwitchingCombo->currentIndex();
@@ -461,7 +421,7 @@ void KWinCompositingConfig::saveGeneralTab()
             effectconfig.writeEntry("kwin4_effect_cubeEnabled", true);
             break;
         }
-    KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube");
+    KConfigGroup cubeconfig(mNewConfig, "Effect-Cube");
     cubeconfig.writeEntry("AnimateDesktopChange", cubeDesktopSwitching);
 
     saveElectricBorders();
@@ -472,29 +432,13 @@ void KWinCompositingConfig::saveEffectsTab()
     ui.effectSelector->save();
 }
 
-bool KWinCompositingConfig::saveAdvancedTab()
-{
-    bool advancedChanged = false;
+void KWinCompositingConfig::saveAdvancedTab()
+    {
     static const int hps[] = { 6 /*always*/, 5 /*shown*/,  4 /*never*/ };
 
-    KConfigGroup config(mKWinConfig, "Compositing");
+    KConfigGroup config(mNewConfig, "Compositing");
     QString glModes[] = { "TFP", "SHM", "Fallback" };
 
-    if( config.readEntry("Backend", "OpenGL")
-            != ((ui.compositingType->currentIndex() == 0) ? "OpenGL" : "XRender")
-        || config.readEntry("GLMode", "TFP") != glModes[ui.glMode->currentIndex()]
-        || config.readEntry("GLDirect", mDefaultPrefs.enableDirectRendering())
-            != ui.glDirect->isChecked()
-        || config.readEntry("GLVSync", mDefaultPrefs.enableVSync()) != ui.glVSync->isChecked()
-        || config.readEntry("DisableChecks", false ) != ui.disableChecks->isChecked())
-        {
-        m_showConfirmDialog = true;
-        advancedChanged = true;
-        }
-    else if( config.readEntry("HiddenPreviews", 5) != hps[ ui.windowThumbnails->currentIndex() ]
-        || config.readEntry("XRenderSmoothScale", false ) != ui.xrenderSmoothScale->isChecked() )
-        advancedChanged = true;
-
     config.writeEntry("Backend", (ui.compositingType->currentIndex() == 0) ? "OpenGL" : "XRender");
     config.writeEntry("HiddenPreviews", hps[ ui.windowThumbnails->currentIndex() ] );
     config.writeEntry("DisableChecks", ui.disableChecks->isChecked());
@@ -505,16 +449,10 @@ bool KWinCompositingConfig::saveAdvancedTab()
     config.writeEntry("GLVSync", ui.glVSync->isChecked());
 
     config.writeEntry("XRenderSmoothScale", ui.xrenderSmoothScale->isChecked());
-
-    return advancedChanged;
-}
+    }
 
 void KWinCompositingConfig::save()
-{
-    // Save current config. We'll use this for restoring in case something goes wrong.
-    KConfigGroup config(mKWinConfig, "Compositing");
-    mPreviousConfig = config.entryMap();
-
+    {
     // bah; tab content being dependent on the other is really bad; and
     // deprecated in the HIG for a reason.  Its confusing!
     // Make sure we only call save on each tab once; as they are stateful due to the revert concept
@@ -527,40 +465,16 @@ void KWinCompositingConfig::save()
         saveEffectsTab();
         loadGeneralTab();
         saveGeneralTab();
-    }
-    bool advancedChanged = saveAdvancedTab();
-
-    // Copy Plugins group from temp config to real config
-    QMap<QString, QString> entries = mTmpConfig->entryMap("Plugins");
-    QMap<QString, QString>::const_iterator it = entries.constBegin();
-    KConfigGroup realconfig(mKWinConfig, "Plugins");
-    realconfig.deleteGroup();
-    for(; it != entries.constEnd(); ++it)
-    {
-        realconfig.writeEntry(it.key(), it.value());
-    }
+        }
+    copyPluginsToNewConfig();
 
-    emit changed( false );
+    saveElectricBorders();
+    saveAdvancedTab();
 
-    configChanged(advancedChanged);
+    emit changed( false );
 
-    if(m_showConfirmDialog)
-    {
-        m_showConfirmDialog = false;
-        showConfirmDialog(advancedChanged);
+    activateNewConfig();
     }
-}
-
-void KWinCompositingConfig::configChanged(bool reinitCompositing)
-{
-    // Send signal to kwin
-    mKWinConfig->sync();
-    // Send signal to all kwin instances
-    QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin",
-        reinitCompositing ? "reinitCompositing" : "reloadConfig");
-    QDBusConnection::sessionBus().send(message);
-}
-
 
 void KWinCompositingConfig::defaults()
 {
@@ -661,25 +575,25 @@ void KWinCompositingConfig::electricBorderSelectionChanged(int edge, int index)
 void KWinCompositingConfig::loadElectricBorders()
 {
     // Present Windows
-    KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows");
+    KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows");
     changeElectricBorder( (ElectricBorder)presentwindowsconfig.readEntry( "BorderActivateAll",
         int( ElectricTopLeft )), (int)PresentWindowsAll );
     changeElectricBorder( (ElectricBorder)presentwindowsconfig.readEntry( "BorderActivate",
         int( ElectricNone )), (int)PresentWindowsCurrent );
     // Desktop Grid
-    KConfigGroup gridconfig(mKWinConfig, "Effect-DesktopGrid");
+    KConfigGroup gridconfig(mNewConfig, "Effect-DesktopGrid");
     changeElectricBorder( (ElectricBorder)gridconfig.readEntry( "BorderActivate",
         int( ElectricNone )), (int)DesktopGrid );
     // Desktop Cube
-    KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube");
+    KConfigGroup cubeconfig(mNewConfig, "Effect-Cube");
     changeElectricBorder( (ElectricBorder)cubeconfig.readEntry( "BorderActivate",
         int( ElectricNone )), (int)Cube );
     // Desktop Cylinder
-    KConfigGroup cylinderconfig(mKWinConfig, "Effect-Cylinder");
+    KConfigGroup cylinderconfig(mNewConfig, "Effect-Cylinder");
     changeElectricBorder( (ElectricBorder)cylinderconfig.readEntry( "BorderActivate",
         int( ElectricNone )), (int)Cylinder );
     // Desktop Grid
-    KConfigGroup sphereconfig(mKWinConfig, "Effect-Sphere");
+    KConfigGroup sphereconfig(mNewConfig, "Effect-Sphere");
     changeElectricBorder( (ElectricBorder)sphereconfig.readEntry( "BorderActivate",
         int( ElectricNone )), (int)Sphere );
 }
@@ -756,24 +670,171 @@ ElectricBorder KWinCompositingConfig::checkEffectHasElectricBorder( int index )
 }
 
 void KWinCompositingConfig::saveElectricBorders()
-{
-    KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows");
+    {
+    KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows");
     presentwindowsconfig.writeEntry( "BorderActivateAll", (int)checkEffectHasElectricBorder( (int)PresentWindowsAll ));
     presentwindowsconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)PresentWindowsCurrent ));
 
-    KConfigGroup gridconfig(mKWinConfig, "Effect-DesktopGrid");
+    KConfigGroup gridconfig(mNewConfig, "Effect-DesktopGrid");
     gridconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)DesktopGrid ));
 
-    KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube");
+    KConfigGroup cubeconfig(mNewConfig, "Effect-Cube");
     cubeconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)Cube ));
 
-    KConfigGroup cylinderconfig(mKWinConfig, "Effect-Cylinder");
+    KConfigGroup cylinderconfig(mNewConfig, "Effect-Cylinder");
     cylinderconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)Cylinder ));
 
-    KConfigGroup sphereconfig(mKWinConfig, "Effect-Sphere");
+    KConfigGroup sphereconfig(mNewConfig, "Effect-Sphere");
     sphereconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)Sphere ));
-}
-    
+    }
+
+void KWinCompositingConfig::activateNewConfig()
+    {
+    // Write the backup file to disk so it can be used on the next KWin start
+    // if KWin or the X server should crash while testing the new config.
+    mBackupConfig->sync();
+
+    bool configOk = true;
+
+    // Tell KWin to load the new configuration.
+    bool couldReload = sendKWinReloadSignal();
+    // If it was not successfull, show an error message to the user.
+    if ( !couldReload )
+        {
+        KMessageBox::sorry( this, i18n(
+            "Failed to activate desktop effects using the given "
+            "configuration options. Settings will be reverted to their previous values.\n\n"
+            "Check your X configuration. You may also consider changing advanced options, "
+            "especially changing the compositing type." ) );
+        configOk = false;
+        }
+    else
+       {
+        // If the confirmation dialog should be shown, wait for its result.
+        if ( isConfirmationNeeded() )
+            {
+            ConfirmDialog confirm;
+            configOk = confirm.exec();
+            }
+        }
+
+    if ( configOk )
+        {
+        // The new config is stable and was accepted.
+        // Update our internal backup copy of the config.
+        updateBackupWithNewConfig();
+        }
+    else
+        {
+        // Copy back the old config and load it into the ui.
+        resetNewToBackupConfig();
+        load();
+        // Tell KWin to reload the (old) config.
+        sendKWinReloadSignal();
+        }
+
+    // Remove the backup file from disk because it is the same as the main config
+    // anyway and would only confuse the startup code if KWin is restarted while
+    // this module is still opened, (e.g. by calling "kwin --replace").
+    deleteBackupConfigFile();
+    }
+
+bool KWinCompositingConfig::isConfirmationNeeded() const
+    {
+    // Compare new config with the backup and see if any potentially dangerous
+    // values have been changed.
+    KConfigGroup newGroup( mNewConfig, "Compositing" );
+    KConfigGroup backupGroup( mBackupConfig, "Compositing" );
+
+    // Manually enabling compositing is potentially dangerous, but disabling is never.
+    bool newEnabled = newGroup.readEntry( "Enabled", mDefaultPrefs.enableCompositing() );
+    bool backupEnabled = backupGroup.readEntry( "Enabled", mDefaultPrefs.enableCompositing() );
+    if ( newEnabled && !backupEnabled )
+        {
+        return true;
+        }
+
+    // All potentially dangerous options along with their (usually safe) default values.
+    QHash<QString, QVariant> confirm;
+    confirm[ "Backend" ] = "OpenGL";
+    confirm[ "GLMode" ] = "TFP";
+    confirm[ "GLDirect" ] = mDefaultPrefs.enableDirectRendering();
+    confirm[ "GLVSync" ] = mDefaultPrefs.enableVSync();
+    confirm[ "DisableChecks" ] = false;
+
+    QHash<QString, QVariant>::const_iterator i = confirm.constBegin();
+    for( ; i != confirm.constEnd(); ++i )
+        {
+        if ( newGroup.readEntry( i.key(), i.value() ) !=
+            backupGroup.readEntry( i.key(), i.value() ) )
+            {
+            return true;
+            }
+        }
+
+    // If we have not returned yet, no critical settings have been changed.
+    return false;
+    }
+
+bool KWinCompositingConfig::sendKWinReloadSignal()
+    {
+    // Save the new config to the file system, thus allowing KWin to read it.
+    mNewConfig->sync();
+
+    // Send signal to all kwin instances.
+    QDBusMessage message = QDBusMessage::createSignal( "/KWin", "org.kde.KWin", "reloadCompositingConfig" );
+    QDBusConnection::sessionBus().send(message);
+
+    // If compositing is enabled, check if it could be started.
+    KConfigGroup newGroup( mNewConfig, "Compositing" );
+    bool enabled = newGroup.readEntry( "Enabled", mDefaultPrefs.enableCompositing() );
+
+    if ( !enabled )
+        {
+        return true;
+        }
+    else
+        {
+        // Feel free to extend this to support several kwin instances (multihead) if you
+        // think it makes sense.
+        OrgKdeKWinInterface kwin( "org.kde.kwin", "/KWin", QDBusConnection::sessionBus() );
+        return kwin.compositingActive().value();
+        }
+    }
+
+void KWinCompositingConfig::updateBackupWithNewConfig()
+    {
+    mNewConfig->copyTo( mBackupConfig->name(), mBackupConfig );
+    }
+
+void KWinCompositingConfig::resetNewToBackupConfig()
+    {
+    mBackupConfig->copyTo( mNewConfig->name(), mNewConfig.data() );
+    }
+
+void KWinCompositingConfig::deleteBackupConfigFile()
+    {
+    QString backupFileName = KStandardDirs::locate( "config", mBackupConfig->name() );
+    // If the file does not exist, QFile::remove() just fails silently.
+    QFile::remove( backupFileName );
+    }
+
+void KWinCompositingConfig::copyPluginsToTmpConfig()
+    {
+    KConfigGroup newGroup( mNewConfig, "Plugins" );
+    KConfigGroup tmpGroup( mTmpConfig, "Plugins" );
+    tmpGroup.deleteGroup();
+    newGroup.copyTo( &tmpGroup );
+    }
+
+void KWinCompositingConfig::copyPluginsToNewConfig()
+    {
+    KConfigGroup newGroup( mNewConfig, "Plugins" );
+    KConfigGroup tmpGroup( mTmpConfig, "Plugins" );
+    newGroup.deleteGroup();
+    tmpGroup.copyTo( &newGroup );
+    }
+
 } // namespace
     
 #include "main.moc"
diff --git a/kcmkwin/kwincompositing/main.h b/kcmkwin/kwincompositing/main.h
index 5c8dbb9..04235da 100644
--- a/kcmkwin/kwincompositing/main.h
+++ b/kcmkwin/kwincompositing/main.h
@@ -53,43 +53,52 @@ class KWinCompositingConfig : public KCModule
         virtual QString quickHelp() const;
 
     public slots:
-        virtual void compositingEnabled(bool enabled);
-        virtual void showConfirmDialog(bool reinitCompositing);
-        void currentTabChanged(int tab);
-
         virtual void load();
         virtual void save();
         virtual void defaults();
-        void reparseConfiguration(const QByteArray&conf);
 
+    private slots:
+        void compositingEnabled(bool enabled);
+        void currentTabChanged(int tab);
+        void electricBorderSelectionChanged(int edge, int index);
+
+    private:
         void loadGeneralTab();
         void loadEffectsTab();
         void loadAdvancedTab();
         void loadElectricBorders();
         void saveGeneralTab();
         void saveEffectsTab();
-        bool saveAdvancedTab();
-        void electricBorderSelectionChanged(int edge, int index);
+        void saveAdvancedTab();
 
-        void configChanged(bool reinitCompositing);
         void initEffectSelector();
 
-    private:
         bool effectEnabled( const QString& effect, const KConfigGroup& cfg ) const;
+
         void setupElectricBorders();
         void addItemToEdgesMonitor(const QString& item);
         void changeElectricBorder( ElectricBorder border, int index );
         ElectricBorder checkEffectHasElectricBorder( int index );
         void saveElectricBorders();
 
-        KSharedConfigPtr mKWinConfig;
+        void activateNewConfig();
+        bool isConfirmationNeeded() const;
+        bool sendKWinReloadSignal();
+
+        void updateBackupWithNewConfig();
+        void resetNewToBackupConfig();
+        void deleteBackupConfigFile();
+
+        void copyPluginsToTmpConfig();
+        void copyPluginsToNewConfig();
+
         Ui::KWinCompositingConfig ui;
         CompositingPrefs mDefaultPrefs;
 
-        QMap<QString, QString> mPreviousConfig;
+        KSharedConfigPtr mNewConfig;
+        KConfig* mBackupConfig;
         KTemporaryFile mTmpConfigFile;
         KSharedConfigPtr mTmpConfig;
-        bool m_showConfirmDialog;
 
         enum ElectricBorderEffects
             {
diff --git a/options.cpp b/options.cpp
index d4d701a..966c4b9 100644
--- a/options.cpp
+++ b/options.cpp
@@ -23,10 +23,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #ifndef KCMRULES
 
+#include <QFile>
 #include <QPalette>
 #include <QPixmap>
 #include <kapplication.h>
 #include <kconfig.h>
+#include <kstandarddirs.h>
 #include <kglobal.h>
 #include <kglobalsettings.h>
 
@@ -45,9 +47,14 @@ namespace KWin
 #ifndef KCMRULES
 
 Options::Options()
-    :   electric_borders( 0 ),
-        electric_border_delay(0)
     {
+    // If there is any contents in the backup file, it means that KWin crashed
+    // while testing a new config. Revert the config.
+    // TODO: Notify the user?
+    bool backupImported = importBackup();
+    kWarning( 1212, backupImported ) << "The new settings have most likely caused the X server "
+        "to crash. The configuration options have been reverted to their old values.";
+
     updateSettings();
     }
 
@@ -55,13 +62,44 @@ Options::~Options()
     {
     }
 
+
 unsigned long Options::updateSettings()
     {
-    KSharedConfig::Ptr _config = KGlobal::config();
+    return loadSettings( KGlobal::config() );
+    }
+
+bool Options::importBackup()
+    {
+    QString configFileName = KStandardDirs::locate( "config", KGlobal::config()->name() );
+    QString backupFileName = configFileName + '~';
+
+    if ( !QFile::exists( backupFileName ) )
+        {
+        return false;
+        }
+
+    QFile::remove( configFileName );
+    QFile::rename( backupFileName, configFileName );
+
+    KGlobal::config()->reparseConfiguration();
+    return true;
+    }
+
+unsigned long Options::loadSettings( KSharedConfigPtr configFile )
+    {
     unsigned long changed = 0;
-    changed |= KDecorationOptions::updateSettings( _config.data() ); // read decoration settings
+    changed |= KDecorationOptions::updateSettings( configFile.data() ); // read decoration settings
+
+    loadWindowSettings( configFile );
+    loadMouseBindings( configFile );
+    loadCompositingSettings( configFile );
 
-    KConfigGroup config(_config, "Windows");
+    return changed;
+    }
+
+void Options::loadWindowSettings( KSharedConfigPtr configFile )
+    {
+    KConfigGroup config( configFile, "Windows" );
     moveMode = stringToMoveResizeMode( config.readEntry("MoveMode", "Opaque" ));
     resizeMode = stringToMoveResizeMode( config.readEntry("ResizeMode", "Opaque" ));
     show_geometry_tip = config.readEntry("GeometryTip", false);
@@ -94,12 +132,12 @@ unsigned long Options::updateSettings()
     if( !focusPolicyIsReasonable()) // #48786, comments #7 and later
         focusStealingPreventionLevel = 0;
 
-    KConfigGroup gWindowsConfig( _config, "Windows"); // from kdeglobals
-    xineramaEnabled = gWindowsConfig.readEntry ("XineramaEnabled", true);
-    xineramaPlacementEnabled = gWindowsConfig.readEntry ("XineramaPlacementEnabled", true);
-    xineramaMovementEnabled = gWindowsConfig.readEntry ("XineramaMovementEnabled", true);
-    xineramaMaximizeEnabled = gWindowsConfig.readEntry ("XineramaMaximizeEnabled", true);
-    xineramaFullscreenEnabled = gWindowsConfig.readEntry ("XineramaFullscreenEnabled", true);
+    // This was once loaded from kdeglobals.
+    xineramaEnabled = config.readEntry ("XineramaEnabled", true);
+    xineramaPlacementEnabled = config.readEntry ("XineramaPlacementEnabled", true);
+    xineramaMovementEnabled = config.readEntry ("XineramaMovementEnabled", true);
+    xineramaMaximizeEnabled = config.readEntry ("XineramaMaximizeEnabled", true);
+    xineramaFullscreenEnabled = config.readEntry ("XineramaFullscreenEnabled", true);
 
     placement = Placement::policyFromString( config.readEntry("Placement"), true );
     xineramaPlacementScreen = qBound( -1, config.readEntry( "XineramaPlacementScreen", -1 ),
@@ -155,8 +193,29 @@ unsigned long Options::updateSettings()
     hideUtilityWindowsForInactive = config.readEntry( "HideUtilityWindowsForInactive", true);
     showDesktopIsMinimizeAll = config.readEntry( "ShowDesktopIsMinimizeAll", false );
 
+    // Read button tooltip animation effect from kdeglobals
+    // Since we want to allow users to enable window decoration tooltips
+    // and not kstyle tooltips and vise-versa, we don't read the
+    // "EffectNoTooltip" setting from kdeglobals.
+
+#if 0
+    FIXME: we have no mac style menu implementation in kwin anymore, so this just breaks
+           things for people!
+    KConfig _globalConfig("kdeglobals");
+    KConfigGroup globalConfig(&_globalConfig, "KDE");
+    topmenus = globalConfig.readEntry("macStyle", false);
+#else
+    topmenus = false;
+#endif
+
+    //    QToolTip::setGloballyEnabled( d->show_tooltips );
+    // KDE4 this probably needs to be done manually in clients
+    }
+
+void Options::loadMouseBindings( KSharedConfigPtr configFile )
+    {
     // Mouse bindings
-    config = KConfigGroup(_config,"MouseBindings");
+    KConfigGroup config( configFile, "MouseBindings" );
     CmdActiveTitlebar1 = mouseCommand(config.readEntry("CommandActiveTitlebar1","Raise"), true );
     CmdActiveTitlebar2 = mouseCommand(config.readEntry("CommandActiveTitlebar2","Lower"), true );
     CmdActiveTitlebar3 = mouseCommand(config.readEntry("CommandActiveTitlebar3","Operations menu"), true );
@@ -172,42 +231,19 @@ unsigned long Options::updateSettings()
     CmdAll2 = mouseCommand(config.readEntry("CommandAll2","Toggle raise and lower"), false );
     CmdAll3 = mouseCommand(config.readEntry("CommandAll3","Resize"), false );
     CmdAllWheel = mouseWheelCommand(config.readEntry("CommandAllWheel","Nothing"));
+    }
 
-    config=KConfigGroup(_config,"Compositing");
-    refreshRate = config.readEntry( "RefreshRate", 0 );
-
-    // Read button tooltip animation effect from kdeglobals
-    // Since we want to allow users to enable window decoration tooltips
-    // and not kstyle tooltips and vise-versa, we don't read the
-    // "EffectNoTooltip" setting from kdeglobals.
-
-#if 0
-    FIXME: we have no mac style menu implementation in kwin anymore, so this just breaks
-           things for people!
-    KConfig _globalConfig("kdeglobals");
-    KConfigGroup globalConfig(&_globalConfig, "KDE");
-    topmenus = globalConfig.readEntry("macStyle", false);
-#else
-    topmenus = false;
-#endif
-
-//    QToolTip::setGloballyEnabled( d->show_tooltips );
-// KDE4 this probably needs to be done manually in clients
-
+void Options::loadCompositingSettings( KSharedConfigPtr configFile )
+    {
     // Driver-specific config detection
     CompositingPrefs prefs;
     prefs.detect();
-    reloadCompositingSettings( prefs );
 
-    return changed;
-    }
+    // Compositing settings
+    KConfigGroup config( configFile, "Compositing");
 
-void Options::reloadCompositingSettings(const CompositingPrefs& prefs)
-    {
-    KSharedConfig::Ptr _config = KGlobal::config();
-    KConfigGroup config(_config, "Compositing");
+    refreshRate = config.readEntry( "RefreshRate", 0 );
 
-    // Compositing settings
     useCompositing = config.readEntry("Enabled", prefs.enableCompositing());
     QString compositingBackend = config.readEntry("Backend", "OpenGL");
     if( compositingBackend == "XRender" )
diff --git a/options.h b/options.h
index c7bcd5f..db085f7 100644
--- a/options.h
+++ b/options.h
@@ -44,6 +44,7 @@ class Options : public KDecorationOptions
         ~Options();
 
         virtual unsigned long updateSettings();
+        bool importBackup();
 
         /*!
           Different focus policies:
@@ -313,6 +314,12 @@ class Options : public KDecorationOptions
         double animationTimeFactor() const;
 
     private:
+        unsigned long loadSettings( KSharedConfigPtr configFile );
+        void loadWindowSettings( KSharedConfigPtr configFile );
+        void loadMouseBindings( KSharedConfigPtr configFile );
+        void loadCompositingSettings( KSharedConfigPtr configFile );
+
+
         WindowOperation OpTitlebarDblClick;
 
     // mouse bindings
@@ -342,7 +349,6 @@ class Options : public KDecorationOptions
         int animationSpeed; // 0 - instant, 5 - very slow
 
         MouseCommand wheelToMouseCommand( MouseWheelCommand com, int delta );
-        void reloadCompositingSettings(const CompositingPrefs& prefs);
     };
 
 extern Options* options;
diff --git a/org.kde.KWin.xml b/org.kde.KWin.xml
index ec27372..ddc0605 100644
--- a/org.kde.KWin.xml
+++ b/org.kde.KWin.xml
@@ -34,7 +34,7 @@
     <method name="previousDesktop"/>
     <method name="circulateDesktopApplications"/>
     <signal name="reloadConfig"/>
-    <signal name="reinitCompositing"/>
+    <signal name="reloadCompositingConfig"/>
     <method name="loadEffect">
       <arg name="name" type="s" direction="in"/>
     </method>
@@ -49,16 +49,13 @@
     </method>
     <method name="loadedEffects">
       <arg type="as" direction="out"/>
-    </method>    
+    </method>
     <method name="listOfEffects">
       <arg type="as" direction="out"/>
     </method>
     <method name="compositingActive">
       <arg type="b" direction="out"/>
     </method>
-    <method name="waitForCompositingSetup">
-      <arg type="b" direction="out"/>
-    </method>
     <method name="decorationSupportedColors">
       <arg type="ai" direction="out"/>
       <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QList&lt;int>"/>
diff --git a/workspace.cpp b/workspace.cpp
index 03f02c8..fccf285 100644
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -147,7 +147,7 @@ Workspace::Workspace( bool restore )
     QDBusConnection dbus = QDBusConnection::sessionBus();
     dbus.registerObject("/KWin", this);
     dbus.connect(QString(), "/KWin", "org.kde.KWin", "reloadConfig", this, SLOT(slotReloadConfig()));
-    dbus.connect(QString(), "/KWin", "org.kde.KWin", "reinitCompositing", this, SLOT(slotReinitCompositing()));
+    dbus.connect(QString(), "/KWin", "org.kde.KWin", "reloadCompositingConfig", this, SLOT(slotReloadCompositingConfig()));
     _self = this;
     mgr = new PluginMgr;
     QX11Info info;
@@ -1081,15 +1081,17 @@ void Workspace::slotReconfigure()
         }
     }
 
-void Workspace::slotReinitCompositing()
+void Workspace::slotReloadCompositingConfig()
     {
-    // Reparse config. Config options will be reloaded by setupCompositing()
+    // Load the compositing settings from the test config.
     KGlobal::config()->reparseConfiguration();
     options->updateSettings();
 
-    // Stop any current compositing
+    // Update any settings that can be set in the compositing kcm.
+    updateElectricBorders();
+
+    // Reinitialize compositing.
     finishCompositing();
-    // And start new one
     setupCompositing();
     if( effects ) // setupCompositing() may fail
         effects->reconfigure();
diff --git a/workspace.h b/workspace.h
index 32a928d..c710bfd 100644
--- a/workspace.h
+++ b/workspace.h
@@ -469,7 +469,6 @@ class Workspace : public QObject, public KDecorationDefines
 
         void reconfigure();
         void slotReconfigure();
-        void slotReinitCompositing();
 
         void slotKillWindow();
 
@@ -500,6 +499,7 @@ class Workspace : public QObject, public KDecorationDefines
         void writeWindowRules();
         void slotBlockShortcuts(int data);
         void slotReloadConfig();
+        void slotReloadCompositingConfig();
         void setPopupClientOpacity( QAction* action );
         void setupCompositing();
         void performCompositing();
