From 5821e6f9d707b0a13f6ca5d3f858d2d91d2a8e6d Mon Sep 17 00:00:00 2001 From: Lucas Murray Date: Mon, 8 Dec 2008 05:08:31 +0000 Subject: [PATCH] Reverted all code relating to automatic X crash detection with agreement from David. Due to an elusive bug somewhere in kdelibs we have not been able to find out how to fix the issues that some people were having. There seems to be a race condition as I cannot reproduce at all, David can reproduce sporadically and some reporters can always reproduce. This commit attempts to also keep the code style changes that were made at the same time as the original commit as well as some minor bug fixes that were made between then and now. Hopefully I didn't miss anything. We will be revisit this in KDE 4.3. BUG: 177178 svn path=/trunk/KDE/kdebase/workspace/; revision=894182 --- kcmkwin/kwincompositing/main.cpp | 389 ++++++++++++------------------- kcmkwin/kwincompositing/main.h | 33 ++- options.cpp | 109 +++------ options.h | 8 +- org.kde.KWin.xml | 5 +- workspace.cpp | 23 +- workspace.h | 5 +- 7 files changed, 225 insertions(+), 347 deletions(-) diff --git a/kcmkwin/kwincompositing/main.cpp b/kcmkwin/kwincompositing/main.cpp index 622e4c2e5f..c8ac20f80c 100644 --- a/kcmkwin/kwincompositing/main.cpp +++ b/kcmkwin/kwincompositing/main.cpp @@ -25,7 +25,6 @@ along with this program. If not, see . #include #include #include -#include #include #include #include @@ -35,7 +34,6 @@ along with this program. If not, see . #include #include -#include #include #include #include @@ -69,8 +67,9 @@ ConfirmDialog::ConfirmDialog() : KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList &) - : KCModule( KWinCompositingConfigFactory::componentData(), parent), - mNewConfig( KSharedConfig::openConfig( "kwinrc" ) ) + : KCModule( KWinCompositingConfigFactory::componentData(), parent ) + , mKWinConfig(KSharedConfig::openConfig( "kwinrc" )) + , m_showConfirmDialog( false ) { KGlobal::locale()->insertCatalog( "kwin_effects" ); ui.setupUi(this); @@ -88,6 +87,8 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList connect(ui.effectAnimations, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.effectSelector, SIGNAL(changed(bool)), this, SLOT(changed())); + connect(ui.effectSelector, SIGNAL(configCommitted(const QByteArray&)), + this, SLOT(reparseConfiguration(const QByteArray&))); connect(ui.windowSwitchingCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); connect(ui.desktopSwitchingCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); @@ -96,6 +97,7 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList connect(ui.edges_monitor, SIGNAL(changed()), this, SLOT(changed())); connect(ui.edges_monitor, SIGNAL(edgeSelectionChanged(int,int)), this, SLOT(electricBorderSelectionChanged(int,int))); + connect(ui.compositingType, SIGNAL(currentIndexChanged(int)), this, SLOT(compositingModeChanged())); connect(ui.compositingType, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); connect(ui.windowThumbnails, SIGNAL(activated(int)), this, SLOT(changed())); connect(ui.disableChecks, SIGNAL(toggled(bool)), this, SLOT(changed())); @@ -105,20 +107,12 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList connect(ui.glVSync, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.xrenderSmoothScale, SIGNAL(toggled(bool)), this, SLOT(changed())); - // TODO: Apparently nobody can tell why this slot should be needed. Could possibly be removed. - connect( ui.effectSelector, SIGNAL( configCommitted( const QByteArray& ) ), - this, SLOT( reparseConfiguration( const QByteArray& ) ) ); - - // 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 ); - updateBackupWithNewConfig(); - // 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 + // changes. + mTmpConfigFile.open(); + mTmpConfig = KSharedConfig::openConfig(mTmpConfigFile.fileName()); if( CompositingPrefs::compositingPossible() ) { @@ -187,9 +181,6 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList KWinCompositingConfig::~KWinCompositingConfig() { - // Make sure that the backup config is not written to disk. - mBackupConfig->markAsClean(); - delete mBackupConfig; } void KWinCompositingConfig::reparseConfiguration( const QByteArray& conf ) @@ -197,7 +188,7 @@ void KWinCompositingConfig::reparseConfiguration( const QByteArray& conf ) KSettings::Dispatcher::reparseConfiguration( conf ); } -void KWinCompositingConfig::compositingEnabled(bool enabled) +void KWinCompositingConfig::compositingEnabled( bool enabled ) { // Enable the other configuration tabs only when compositing is enabled. ui.compositingOptionsContainer->setEnabled(enabled); @@ -206,6 +197,45 @@ void KWinCompositingConfig::compositingEnabled(bool 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::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() { // Find all .desktop files of the effects @@ -213,14 +243,14 @@ void KWinCompositingConfig::initEffectSelector() QList effectinfos = KPluginInfo::fromServices(offers); // Add them to the plugin selector - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Appearance"), "Appearance", mNewConfig); - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Accessibility"), "Accessibility", mNewConfig); - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Focus"), "Focus", mNewConfig); - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Window Management"), "Window Management", mNewConfig); - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Candy"), "Candy", mNewConfig); - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Demos"), "Demos", mNewConfig); - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Tests"), "Tests", mNewConfig); - ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Tools"), "Tools", mNewConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Appearance"), "Appearance", mTmpConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Accessibility"), "Accessibility", mTmpConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Focus"), "Focus", mTmpConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Window Management"), "Window Management", mTmpConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Candy"), "Candy", mTmpConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Demos"), "Demos", mTmpConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Tests"), "Tests", mTmpConfig); + ui.effectSelector->addPlugins(effectinfos, KPluginSelector::ReadConfigFile, i18n("Tools"), "Tools", mTmpConfig); } void KWinCompositingConfig::currentTabChanged(int tab) @@ -249,12 +279,12 @@ void KWinCompositingConfig::currentTabChanged(int tab) void KWinCompositingConfig::loadGeneralTab() { - KConfigGroup config(mNewConfig, "Compositing"); + KConfigGroup config(mKWinConfig, "Compositing"); ui.useCompositing->setChecked(config.readEntry("Enabled", mDefaultPrefs.enableCompositing())); ui.animationSpeedCombo->setCurrentIndex(config.readEntry("AnimationSpeed", 3 )); // Load effect settings - KConfigGroup effectconfig(mNewConfig, "Plugins"); + KConfigGroup effectconfig(mTmpConfig, "Plugins"); #define LOAD_EFFECT_CONFIG(effectname) effectconfig.readEntry("kwin4_effect_" effectname "Enabled", true) int winManagementEnabled = LOAD_EFFECT_CONFIG("presentwindows") + LOAD_EFFECT_CONFIG("desktopgrid") @@ -279,7 +309,7 @@ void KWinCompositingConfig::loadGeneralTab() ui.windowSwitchingCombo->setCurrentIndex( 3 ); if( effectEnabled( "flipswitch", effectconfig )) ui.windowSwitchingCombo->setCurrentIndex( 4 ); - KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows"); + KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows"); if( effectEnabled( "presentwindows", effectconfig ) && presentwindowsconfig.readEntry("TabBox", false) ) ui.windowSwitchingCombo->setCurrentIndex( 2 ); @@ -288,9 +318,11 @@ void KWinCompositingConfig::loadGeneralTab() ui.desktopSwitchingCombo->setCurrentIndex( 0 ); if( effectEnabled( "slide", effectconfig )) ui.desktopSwitchingCombo->setCurrentIndex( 1 ); - KConfigGroup cubeconfig(mNewConfig, "Effect-Cube"); + KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube"); if( effectEnabled( "cube", effectconfig ) && cubeconfig.readEntry("AnimateDesktopChange", false)) ui.desktopSwitchingCombo->setCurrentIndex( 2 ); + + loadElectricBorders(); } bool KWinCompositingConfig::effectEnabled( const QString& effect, const KConfigGroup& cfg ) const @@ -310,7 +342,7 @@ void KWinCompositingConfig::loadEffectsTab() void KWinCompositingConfig::loadAdvancedTab() { - KConfigGroup config(mNewConfig, "Compositing"); + KConfigGroup config(mKWinConfig, "Compositing"); QString backend = config.readEntry("Backend", "OpenGL"); ui.compositingType->setCurrentIndex((backend == "XRender") ? 1 : 0); // 4 - off, 5 - shown, 6 - always, other are old values @@ -334,11 +366,17 @@ void KWinCompositingConfig::loadAdvancedTab() void KWinCompositingConfig::load() { - // Discard any unsaved changes. - resetNewToBackupConfig(); + mKWinConfig->reparseConfiguration(); + + // Copy Plugins group to temp config file + QMap entries = mKWinConfig->entryMap("Plugins"); + QMap::const_iterator it = entries.constBegin(); + KConfigGroup tmpconfig(mTmpConfig, "Plugins"); + tmpconfig.deleteGroup(); + for(; it != entries.constEnd(); ++it) + tmpconfig.writeEntry(it.key(), it.value()); loadGeneralTab(); - loadElectricBorders(); loadEffectsTab(); loadAdvancedTab(); @@ -347,13 +385,17 @@ void KWinCompositingConfig::load() void KWinCompositingConfig::saveGeneralTab() { - KConfigGroup config(mNewConfig, "Compositing"); + 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; config.writeEntry("Enabled", ui.useCompositing->isChecked()); config.writeEntry("AnimationSpeed", ui.animationSpeedCombo->currentIndex()); // Save effects - KConfigGroup effectconfig( mNewConfig, "Plugins" ); + KConfigGroup effectconfig(mTmpConfig, "Plugins"); #define WRITE_EFFECT_CONFIG(effectname, widget) effectconfig.writeEntry("kwin4_effect_" effectname "Enabled", widget->isChecked()) if (ui.effectWinManagement->checkState() != Qt::PartiallyChecked) { @@ -404,7 +446,7 @@ void KWinCompositingConfig::saveGeneralTab() effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", true); break; } - KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows"); + KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows"); presentwindowsconfig.writeEntry("TabBox", presentWindowSwitching); int desktopSwitcher = ui.desktopSwitchingCombo->currentIndex(); @@ -426,8 +468,10 @@ void KWinCompositingConfig::saveGeneralTab() effectconfig.writeEntry("kwin4_effect_cubeEnabled", true); break; } - KConfigGroup cubeconfig(mNewConfig, "Effect-Cube"); + KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube"); cubeconfig.writeEntry("AnimateDesktopChange", cubeDesktopSwitching); + + saveElectricBorders(); } void KWinCompositingConfig::saveEffectsTab() @@ -435,13 +479,29 @@ void KWinCompositingConfig::saveEffectsTab() ui.effectSelector->save(); } -void KWinCompositingConfig::saveAdvancedTab() +bool KWinCompositingConfig::saveAdvancedTab() { + bool advancedChanged = false; static const int hps[] = { 6 /*always*/, 5 /*shown*/, 4 /*never*/ }; - KConfigGroup config(mNewConfig, "Compositing"); + KConfigGroup config(mKWinConfig, "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()); @@ -452,10 +512,16 @@ void 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 @@ -471,15 +537,38 @@ void KWinCompositingConfig::save() loadGeneralTab(); saveGeneralTab(); } + bool advancedChanged = saveAdvancedTab(); - saveElectricBorders(); - saveAdvancedTab(); + // Copy Plugins group from temp config to real config + QMap entries = mTmpConfig->entryMap("Plugins"); + QMap::const_iterator it = entries.constBegin(); + KConfigGroup realconfig(mKWinConfig, "Plugins"); + realconfig.deleteGroup(); + for(; it != entries.constEnd(); ++it) + realconfig.writeEntry(it.key(), it.value()); emit changed( false ); - activateNewConfig(); + configChanged(advancedChanged); + + if(m_showConfirmDialog) + { + m_showConfirmDialog = false; + showConfirmDialog(advancedChanged); + } } +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() { ui.tabWidget->setCurrentIndex(0); @@ -518,7 +607,6 @@ QString KWinCompositingConfig::quickHelp() const return i18n("

Desktop Effects

"); } - void KWinCompositingConfig::setupElectricBorders() { addItemToEdgesMonitor( i18n("No Effect")); @@ -534,32 +622,22 @@ void KWinCompositingConfig::setupElectricBorders() } services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_desktopgrid'"); if( !services.isEmpty() ) - { addItemToEdgesMonitor( services.first()->name()); - } services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_cube'"); if( !services.isEmpty() ) - { addItemToEdgesMonitor( services.first()->name()); - } services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_cylinder'"); if( !services.isEmpty() ) - { addItemToEdgesMonitor( services.first()->name()); - } services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_sphere'"); if( !services.isEmpty() ) - { addItemToEdgesMonitor( services.first()->name()); - } } void KWinCompositingConfig::addItemToEdgesMonitor(const QString& item) { for( int i=0; i<8; i++ ) - { ui.edges_monitor->addEdgeItem( i, item ); - } } void KWinCompositingConfig::electricBorderSelectionChanged(int edge, int index) @@ -579,25 +657,25 @@ void KWinCompositingConfig::electricBorderSelectionChanged(int edge, int index) void KWinCompositingConfig::loadElectricBorders() { // Present Windows - KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows"); + KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows"); changeElectricBorder( (ElectricBorder)presentwindowsconfig.readEntry( "BorderActivateAll", int( ElectricTopLeft )), (int)PresentWindowsAll ); changeElectricBorder( (ElectricBorder)presentwindowsconfig.readEntry( "BorderActivate", int( ElectricNone )), (int)PresentWindowsCurrent ); // Desktop Grid - KConfigGroup gridconfig(mNewConfig, "Effect-DesktopGrid"); + KConfigGroup gridconfig(mKWinConfig, "Effect-DesktopGrid"); changeElectricBorder( (ElectricBorder)gridconfig.readEntry( "BorderActivate", int( ElectricNone )), (int)DesktopGrid ); // Desktop Cube - KConfigGroup cubeconfig(mNewConfig, "Effect-Cube"); + KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube"); changeElectricBorder( (ElectricBorder)cubeconfig.readEntry( "BorderActivate", int( ElectricNone )), (int)Cube ); // Desktop Cylinder - KConfigGroup cylinderconfig(mNewConfig, "Effect-Cylinder"); + KConfigGroup cylinderconfig(mKWinConfig, "Effect-Cylinder"); changeElectricBorder( (ElectricBorder)cylinderconfig.readEntry( "BorderActivate", int( ElectricNone )), (int)Cylinder ); // Desktop Grid - KConfigGroup sphereconfig(mNewConfig, "Effect-Sphere"); + KConfigGroup sphereconfig(mKWinConfig, "Effect-Sphere"); changeElectricBorder( (ElectricBorder)sphereconfig.readEntry( "BorderActivate", int( ElectricNone )), (int)Sphere ); } @@ -639,213 +717,42 @@ void KWinCompositingConfig::changeElectricBorder( ElectricBorder border, int ind ElectricBorder KWinCompositingConfig::checkEffectHasElectricBorder( int index ) { if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::Top ) == index ) - { return ElectricTop; - } if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::TopRight ) == index ) - { return ElectricTopRight; - } if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::Right ) == index ) - { return ElectricRight; - } if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::BottomRight ) == index ) - { return ElectricBottomRight; - } if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::Bottom ) == index ) - { return ElectricBottom; - } if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::BottomLeft ) == index ) - { return ElectricBottomLeft; - } if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::Left ) == index ) - { return ElectricLeft; - } if( ui.edges_monitor->selectedEdgeItem( (int)Monitor::TopLeft ) == index ) - { return ElectricTopLeft; - } return ElectricNone; } void KWinCompositingConfig::saveElectricBorders() - { - KConfigGroup presentwindowsconfig(mNewConfig, "Effect-PresentWindows"); +{ + KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows"); presentwindowsconfig.writeEntry( "BorderActivateAll", (int)checkEffectHasElectricBorder( (int)PresentWindowsAll )); presentwindowsconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)PresentWindowsCurrent )); - KConfigGroup gridconfig(mNewConfig, "Effect-DesktopGrid"); + KConfigGroup gridconfig(mKWinConfig, "Effect-DesktopGrid"); gridconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)DesktopGrid )); - KConfigGroup cubeconfig(mNewConfig, "Effect-Cube"); + KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube"); cubeconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)Cube )); - KConfigGroup cylinderconfig(mNewConfig, "Effect-Cylinder"); + KConfigGroup cylinderconfig(mKWinConfig, "Effect-Cylinder"); cylinderconfig.writeEntry( "BorderActivate", (int)checkEffectHasElectricBorder( (int)Cylinder )); - KConfigGroup sphereconfig(mNewConfig, "Effect-Sphere"); + KConfigGroup sphereconfig(mKWinConfig, "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. - 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 confirm; - confirm[ "Backend" ] = "OpenGL"; - confirm[ "GLMode" ] = "TFP"; - confirm[ "GLDirect" ] = mDefaultPrefs.enableDirectRendering(); - confirm[ "GLVSync" ] = mDefaultPrefs.enableVSync(); - confirm[ "DisableChecks" ] = false; - - QHash::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 we added or removed shadows we need to reload decorations as well - // We have to do this separately so the settings are in sync - // HACK: This should really just reload decorations, not do a full reconfigure - - KConfigGroup effectConfig; - - effectConfig = KConfigGroup( mBackupConfig, "Compositing" ); - bool enabledBefore = effectConfig.readEntry( "Enabled", mDefaultPrefs.enableCompositing() ); - effectConfig = KConfigGroup( mNewConfig, "Compositing" ); - bool enabledAfter = effectConfig.readEntry( "Enabled", mDefaultPrefs.enableCompositing() ); - - effectConfig = KConfigGroup( mBackupConfig, "Plugins" ); - bool shadowBefore = effectEnabled( "shadow", effectConfig ); - effectConfig = KConfigGroup( mNewConfig, "Plugins" ); - bool shadowAfter = effectEnabled( "shadow", effectConfig ); - - if( enabledBefore != enabledAfter || shadowBefore != shadowAfter ) - { - message = QDBusMessage::createMethodCall( "org.kde.kwin", "/KWin", "org.kde.KWin", "reconfigure" ); - 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 ); - } +} } // namespace diff --git a/kcmkwin/kwincompositing/main.h b/kcmkwin/kwincompositing/main.h index d24e2e4048..6e9c0dfe87 100644 --- a/kcmkwin/kwincompositing/main.h +++ b/kcmkwin/kwincompositing/main.h @@ -53,48 +53,43 @@ 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 reparseConfiguration( const QByteArray& conf ); - 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(); - void saveAdvancedTab(); + bool saveAdvancedTab(); + void electricBorderSelectionChanged(int edge, int index); + 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(); - void activateNewConfig(); - bool isConfirmationNeeded() const; - bool sendKWinReloadSignal(); - - void updateBackupWithNewConfig(); - void resetNewToBackupConfig(); - void deleteBackupConfigFile(); - + KSharedConfigPtr mKWinConfig; Ui::KWinCompositingConfig ui; CompositingPrefs mDefaultPrefs; - KSharedConfigPtr mNewConfig; - KConfig* mBackupConfig; + QMap mPreviousConfig; + KTemporaryFile mTmpConfigFile; + KSharedConfigPtr mTmpConfig; + bool m_showConfirmDialog; enum ElectricBorderEffects { diff --git a/options.cpp b/options.cpp index a7ceb5aef3..b3151d381b 100644 --- a/options.cpp +++ b/options.cpp @@ -23,12 +23,10 @@ along with this program. If not, see . #ifndef KCMRULES -#include #include #include #include #include -#include #include #include @@ -47,14 +45,9 @@ 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? - if( importBackup() ) - kWarning( 1212 ) << "The new settings have most likely caused the X server " - "to crash. The configuration options have been reverted to their old values."; - updateSettings(); } @@ -62,44 +55,13 @@ Options::~Options() { } - unsigned long Options::updateSettings() { - 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 ) - { + KSharedConfig::Ptr _config = KGlobal::config(); unsigned long changed = 0; - changed |= KDecorationOptions::updateSettings( configFile.data() ); // read decoration settings + changed |= KDecorationOptions::updateSettings( _config.data() ); // read decoration settings - loadWindowSettings( configFile ); - loadMouseBindings( configFile ); - loadCompositingSettings( configFile ); - - return changed; - } - -void Options::loadWindowSettings( KSharedConfigPtr configFile ) - { - KConfigGroup config( configFile, "Windows" ); + KConfigGroup config( _config, "Windows" ); moveMode = stringToMoveResizeMode( config.readEntry("MoveMode", "Opaque" )); resizeMode = stringToMoveResizeMode( config.readEntry("ResizeMode", "Opaque" )); show_geometry_tip = config.readEntry("GeometryTip", false); @@ -132,7 +94,6 @@ void Options::loadWindowSettings( KSharedConfigPtr configFile ) if( !focusPolicyIsReasonable()) // #48786, comments #7 and later focusStealingPreventionLevel = 0; - // This was once loaded from kdeglobals. xineramaEnabled = config.readEntry ("XineramaEnabled", true); xineramaPlacementEnabled = config.readEntry ("XineramaPlacementEnabled", true); xineramaMovementEnabled = config.readEntry ("XineramaMovementEnabled", true); @@ -193,29 +154,8 @@ void Options::loadWindowSettings( KSharedConfigPtr configFile ) 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 - KConfigGroup config( configFile, "MouseBindings" ); + config = KConfigGroup( _config, "MouseBindings" ); CmdActiveTitlebar1 = mouseCommand(config.readEntry("CommandActiveTitlebar1","Raise"), true ); CmdActiveTitlebar2 = mouseCommand(config.readEntry("CommandActiveTitlebar2","Lower"), true ); CmdActiveTitlebar3 = mouseCommand(config.readEntry("CommandActiveTitlebar3","Operations menu"), true ); @@ -231,19 +171,42 @@ void Options::loadMouseBindings( KSharedConfigPtr configFile ) CmdAll2 = mouseCommand(config.readEntry("CommandAll2","Toggle raise and lower"), false ); CmdAll3 = mouseCommand(config.readEntry("CommandAll3","Resize"), false ); CmdAllWheel = mouseWheelCommand(config.readEntry("CommandAllWheel","Nothing")); - } -void Options::loadCompositingSettings( KSharedConfigPtr configFile ) - { + 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 + // Driver-specific config detection CompositingPrefs prefs; prefs.detect(); + reloadCompositingSettings( prefs ); + + return changed; + } + +void Options::reloadCompositingSettings(const CompositingPrefs& prefs) + { + KSharedConfig::Ptr _config = KGlobal::config(); + KConfigGroup config(_config, "Compositing"); // Compositing settings - KConfigGroup config( configFile, "Compositing"); - - refreshRate = config.readEntry( "RefreshRate", 0 ); - useCompositing = config.readEntry("Enabled", prefs.enableCompositing()); QString compositingBackend = config.readEntry("Backend", "OpenGL"); if( compositingBackend == "XRender" ) diff --git a/options.h b/options.h index 45b9c6e21c..015a3d6260 100644 --- a/options.h +++ b/options.h @@ -44,7 +44,6 @@ class Options : public KDecorationOptions ~Options(); virtual unsigned long updateSettings(); - bool importBackup(); /*! Different focus policies: @@ -314,12 +313,6 @@ 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 @@ -349,6 +342,7 @@ 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 ddc0605260..5b58242897 100644 --- a/org.kde.KWin.xml +++ b/org.kde.KWin.xml @@ -34,7 +34,7 @@ - + @@ -56,6 +56,9 @@ + + + diff --git a/workspace.cpp b/workspace.cpp index d6037ee3ad..409cb18375 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", "reloadCompositingConfig", this, SLOT(slotReloadCompositingConfig())); + dbus.connect(QString(), "/KWin", "org.kde.KWin", "reinitCompositing", this, SLOT(slotReinitCompositing())); _self = this; mgr = new PluginMgr; QX11Info info; @@ -972,6 +972,19 @@ void Workspace::reconfigure() reconfigureTimer.start( 200 ); } +// This DBUS call is used by the compositing kcm. Since the reconfigure() +// DBUS call delays the actual reconfiguring, it is not possible to immediately +// call compositingActive(). Therefore the kcm will instead call this to ensure +// the reconfiguring has already happened. +bool Workspace::waitForCompositingSetup() + { + if( !reconfigureTimer.isActive()) + return false; + reconfigureTimer.stop(); + slotReconfigure(); + return compositingActive(); + } + void Workspace::slotSettingsChanged(int category) { kDebug(1212) << "Workspace::slotSettingsChanged()"; @@ -1053,6 +1066,7 @@ void Workspace::slotReconfigure() setupCompositing(); if( effects ) // setupCompositing() may fail effects->reconfigure(); + addRepaintFull(); } else finishCompositing(); @@ -1068,17 +1082,18 @@ void Workspace::slotReconfigure() } } -void Workspace::slotReloadCompositingConfig() +void Workspace::slotReinitCompositing() { - // Load the compositing settings from the test config. + // Reparse config. Config options will be reloaded by setupCompositing() KGlobal::config()->reparseConfiguration(); options->updateSettings(); // Update any settings that can be set in the compositing kcm. updateElectricBorders(); - // Reinitialize compositing. + // Stop any current compositing finishCompositing(); + // And start new one setupCompositing(); if( effects ) // setupCompositing() may fail effects->reconfigure(); diff --git a/workspace.h b/workspace.h index 4bc78ff59b..32a928ddff 100644 --- a/workspace.h +++ b/workspace.h @@ -262,7 +262,8 @@ class Workspace : public QObject, public KDecorationDefines void previousDesktop(); void circulateDesktopApplications(); bool compositingActive(); - + bool waitForCompositingSetup(); + void setCurrentScreen( int new_screen ); QString desktopName( int desk ) const; @@ -468,6 +469,7 @@ class Workspace : public QObject, public KDecorationDefines void reconfigure(); void slotReconfigure(); + void slotReinitCompositing(); void slotKillWindow(); @@ -498,7 +500,6 @@ class Workspace : public QObject, public KDecorationDefines void writeWindowRules(); void slotBlockShortcuts(int data); void slotReloadConfig(); - void slotReloadCompositingConfig(); void setPopupClientOpacity( QAction* action ); void setupCompositing(); void performCompositing();