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();