/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2008 Martin Gräßlin Copyright (C) 2009 Lucas Murray This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "kdebug.h" #include "main.h" #include #include #include #include K_PLUGIN_FACTORY( KWinScreenEdgesConfigFactory, registerPlugin(); ) K_EXPORT_PLUGIN( KWinScreenEdgesConfigFactory( "kcmkwinscreenedges" )) namespace KWin { KWinScreenEdgesConfigForm::KWinScreenEdgesConfigForm( QWidget* parent ) : QWidget( parent ) { setupUi( this ); } KWinScreenEdgesConfig::KWinScreenEdgesConfig( QWidget* parent, const QVariantList& args ) : KCModule( KWinScreenEdgesConfigFactory::componentData(), parent, args ) , m_config( KSharedConfig::openConfig( "kwinrc" )) { m_ui = new KWinScreenEdgesConfigForm( this ); QVBoxLayout* layout = new QVBoxLayout( this ); layout->addWidget( m_ui ); monitorInit(); connect( m_ui->monitor, SIGNAL( changed() ), this, SLOT( changed() )); connect( m_ui->desktopSwitchCombo, SIGNAL( currentIndexChanged(int) ), this, SLOT( changed() )); connect( m_ui->activationDelaySpin, SIGNAL( valueChanged(int) ), this, SLOT( changed() )); connect( m_ui->triggerCooldownSpin, SIGNAL( valueChanged(int) ), this, SLOT( changed() )); connect( m_ui->quickMaximizeBox, SIGNAL( stateChanged(int) ), this, SLOT( changed() )); connect( m_ui->quickTileBox, SIGNAL( stateChanged(int) ), this, SLOT( changed() )); // Visual feedback of action group conflicts connect( m_ui->desktopSwitchCombo, SIGNAL( currentIndexChanged(int) ), this, SLOT( groupChanged() )); connect( m_ui->quickMaximizeBox, SIGNAL( stateChanged(int) ), this, SLOT( groupChanged() )); connect( m_ui->quickTileBox, SIGNAL( stateChanged(int) ), this, SLOT( groupChanged() )); // NOTICE: this is intended to workaround broken GL implementations that successfully segfault on glXQuery :-( KConfigGroup gl_workaround_config(m_config, "Compositing"); const bool checkIsSafe = gl_workaround_config.readEntry("CheckIsSafe", true); if( checkIsSafe && CompositingPrefs::compositingPossible() ) { gl_workaround_config.writeEntry("CheckIsSafe", false); gl_workaround_config.sync(); m_defaultPrefs.detect(); // Driver-specific config detection gl_workaround_config.writeEntry("CheckIsSafe", true); gl_workaround_config.sync(); } load(); } KWinScreenEdgesConfig::~KWinScreenEdgesConfig() { } void KWinScreenEdgesConfig::groupChanged() { // Monitor conflicts bool hide = false; if( m_ui->desktopSwitchCombo->currentIndex() == 2 ) hide = true; monitorHideEdge( ElectricTop, hide ); monitorHideEdge( ElectricRight, hide ); monitorHideEdge( ElectricBottom, hide ); monitorHideEdge( ElectricLeft, hide ); // Desktop switch conflicts if( m_ui->quickTileBox->isChecked() || m_ui->quickMaximizeBox->isChecked() ) { m_ui->desktopSwitchLabel->setEnabled( false ); m_ui->desktopSwitchCombo->setEnabled( false ); m_ui->desktopSwitchCombo->setCurrentIndex( 0 ); } else { m_ui->desktopSwitchLabel->setEnabled( true ); m_ui->desktopSwitchCombo->setEnabled( true ); } } void KWinScreenEdgesConfig::load() { KCModule::load(); monitorLoad(); KConfigGroup config( m_config, "Windows" ); m_ui->desktopSwitchCombo->setCurrentIndex( config.readEntry( "ElectricBorders", 0 )); m_ui->activationDelaySpin->setValue( config.readEntry( "ElectricBorderDelay", 150 )); m_ui->triggerCooldownSpin->setValue( config.readEntry( "ElectricBorderCooldown", 350 )); m_ui->quickMaximizeBox->setChecked( config.readEntry( "ElectricBorderMaximize", true )); m_ui->quickTileBox->setChecked( config.readEntry( "ElectricBorderTiling", true )); emit changed( false ); } void KWinScreenEdgesConfig::save() { KCModule::save(); monitorSave(); KConfigGroup config( m_config, "Windows" ); config.writeEntry( "ElectricBorders", m_ui->desktopSwitchCombo->currentIndex() ); config.writeEntry( "ElectricBorderDelay", m_ui->activationDelaySpin->value() ); config.writeEntry( "ElectricBorderCooldown", m_ui->triggerCooldownSpin->value() ); config.writeEntry( "ElectricBorderMaximize", m_ui->quickMaximizeBox->isChecked() ); config.writeEntry( "ElectricBorderTiling", m_ui->quickTileBox->isChecked() ); config.sync(); // Reload KWin. QDBusMessage message = QDBusMessage::createSignal( "/KWin", "org.kde.KWin", "reloadConfig" ); QDBusConnection::sessionBus().send( message ); emit changed( false ); } void KWinScreenEdgesConfig::defaults() { monitorDefaults(); m_ui->desktopSwitchCombo->setCurrentIndex( 0 ); m_ui->activationDelaySpin->setValue( 150 ); m_ui->triggerCooldownSpin->setValue( 350 ); m_ui->quickMaximizeBox->setChecked( true ); m_ui->quickTileBox->setChecked( true ); emit changed( true ); } void KWinScreenEdgesConfig::showEvent( QShowEvent* e ) { KCModule::showEvent( e ); monitorShowEvent(); } // Copied from kcmkwin/kwincompositing/main.cpp bool KWinScreenEdgesConfig::effectEnabled( const QString& effect, const KConfigGroup& cfg ) const { KService::List services = KServiceTypeTrader::self()->query( "KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_" + effect + '\''); if( services.isEmpty()) return false; QVariant v = services.first()->property("X-KDE-PluginInfo-EnabledByDefault"); return cfg.readEntry("kwin4_effect_" + effect + "Enabled", v.toBool()); } //----------------------------------------------------------------------------- // Monitor void KWinScreenEdgesConfig::monitorAddItem( const QString& item ) { for( int i = 0; i < 8; i++ ) m_ui->monitor->addEdgeItem( i, item ); } void KWinScreenEdgesConfig::monitorItemSetEnabled( int index, bool enabled ) { for( int i = 0; i < 8; i++ ) m_ui->monitor->setEdgeItemEnabled( i, index, enabled ); } void KWinScreenEdgesConfig::monitorInit() { monitorAddItem( i18n( "No Action" )); monitorAddItem( i18n( "Show Dashboard" )); monitorAddItem( i18n( "Show Desktop" )); // Search the effect names KServiceTypeTrader* trader = KServiceTypeTrader::self(); KService::List services; services = trader->query( "KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_presentwindows'" ); if( services.isEmpty() ) { // adding empty strings in case the effect is not found // TODO: after string freeze add a info that the effect is missing monitorAddItem( QString() ); monitorAddItem( QString() ); } else { monitorAddItem( services.first()->name() + " - " + i18n( "All Desktops" )); monitorAddItem( services.first()->name() + " - " + i18n( "Current Desktop" )); } services = trader->query( "KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_desktopgrid'" ); if( services.isEmpty() ) { // adding empty strings in case the effect is not found // TODO: after string freeze add a info that the effect is missing monitorAddItem( QString() ); } else { monitorAddItem( services.first()->name()); } services = trader->query( "KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_cube'" ); if( services.isEmpty() ) { // adding empty strings in case the effect is not found // TODO: after string freeze add a info that the effect is missing monitorAddItem( QString() ); monitorAddItem( QString() ); monitorAddItem( QString() ); } else { monitorAddItem( services.first()->name() + " - " + i18n( "Cube" )); monitorAddItem( services.first()->name() + " - " + i18n( "Cylinder" )); monitorAddItem( services.first()->name() + " - " + i18n( "Sphere" )); } services = trader->query( "KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_flipswitch'" ); if( services.isEmpty() ) { // adding empty strings in case the effect is not found // TODO: after string freeze add a info that the effect is missing monitorAddItem( QString() ); monitorAddItem( QString() ); } else { monitorAddItem( services.first()->name() + " - " + i18n( "All Desktops" )); monitorAddItem( services.first()->name() + " - " + i18n( "Current Desktop" )); } monitorShowEvent(); } void KWinScreenEdgesConfig::monitorLoadAction( ElectricBorder edge, const QString& configName ) { KConfigGroup config( m_config, "ElectricBorders" ); QString lowerName = config.readEntry( configName, "None" ).toLower(); if( lowerName == "dashboard" ) monitorChangeEdge( edge, int( ElectricActionDashboard )); } void KWinScreenEdgesConfig::monitorLoad() { // Load ElectricBorderActions monitorLoadAction( ElectricTop, "Top" ); monitorLoadAction( ElectricTopRight, "TopRight" ); monitorLoadAction( ElectricRight, "Right" ); monitorLoadAction( ElectricBottomRight, "BottomRight" ); monitorLoadAction( ElectricBottom, "Bottom" ); monitorLoadAction( ElectricBottomLeft, "BottomLeft" ); monitorLoadAction( ElectricLeft, "Left" ); monitorLoadAction( ElectricTopLeft, "TopLeft" ); // Load effect-specific actions: // Present Windows KConfigGroup presentWindowsConfig( m_config, "Effect-PresentWindows" ); QList list = QList(); // PresentWindows BorderActivateAll list.append( int( ElectricTopLeft ) ); list = presentWindowsConfig.readEntry( "BorderActivateAll", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( PresentWindowsAll ) ); } // PresentWindows BorderActivate list.clear(); list.append( int( ElectricNone ) ); list = presentWindowsConfig.readEntry( "BorderActivate", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( PresentWindowsCurrent ) ); } // Desktop Grid KConfigGroup gridConfig( m_config, "Effect-DesktopGrid" ); list.clear(); list.append( int( ElectricNone ) ); list = gridConfig.readEntry( "BorderActivate", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( DesktopGrid ) ); } // Desktop Cube KConfigGroup cubeConfig( m_config, "Effect-Cube" ); list.clear(); list.append( int( ElectricNone ) ); list = cubeConfig.readEntry( "BorderActivate", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( Cube ) ); } list.clear(); list.append( int( ElectricNone ) ); list = cubeConfig.readEntry( "BorderActivateCylinder", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( Cylinder ) ); } list.clear(); list.append( int( ElectricNone ) ); list = cubeConfig.readEntry( "BorderActivateSphere", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( Sphere ) ); } // Flip Switch KConfigGroup flipSwitchConfig( m_config, "Effect-FlipSwitch" ); list.clear(); // FlipSwitch BorderActivateAll list.append( int( ElectricNone ) ); list = flipSwitchConfig.readEntry( "BorderActivateAll", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( FlipSwitchAll ) ); } // FlipSwitch BorderActivate list.clear(); list.append( int( ElectricNone ) ); list = flipSwitchConfig.readEntry( "BorderActivate", list ); foreach( int i, list ) { monitorChangeEdge( ElectricBorder( i ), int( FlipSwitchCurrent ) ); } } void KWinScreenEdgesConfig::monitorSaveAction( int edge, const QString& configName ) { KConfigGroup config( m_config, "ElectricBorders" ); int item = m_ui->monitor->selectedEdgeItem( edge ); if( item == 1 ) // Plasma dashboard config.writeEntry( configName, "Dashboard" ); else if( item == 2 ) config.writeEntry( configName, "ShowDesktop" ); else // Anything else config.writeEntry( configName, "None" ); } void KWinScreenEdgesConfig::monitorSave() { // Save ElectricBorderActions monitorSaveAction( int( Monitor::Top ), "Top" ); monitorSaveAction( int( Monitor::TopRight ), "TopRight" ); monitorSaveAction( int( Monitor::Right ), "Right" ); monitorSaveAction( int( Monitor::BottomRight ), "BottomRight" ); monitorSaveAction( int( Monitor::Bottom ), "Bottom" ); monitorSaveAction( int( Monitor::BottomLeft ), "BottomLeft" ); monitorSaveAction( int( Monitor::Left ), "Left" ); monitorSaveAction( int( Monitor::TopLeft ), "TopLeft" ); // Save effect-specific actions: // Present Windows KConfigGroup presentWindowsConfig( m_config, "Effect-PresentWindows" ); presentWindowsConfig.writeEntry( "BorderActivateAll", monitorCheckEffectHasEdge( int( PresentWindowsAll ))); presentWindowsConfig.writeEntry( "BorderActivate", monitorCheckEffectHasEdge( int( PresentWindowsCurrent ))); // Desktop Grid KConfigGroup gridConfig( m_config, "Effect-DesktopGrid" ); gridConfig.writeEntry( "BorderActivate", monitorCheckEffectHasEdge( int( DesktopGrid ))); // Desktop Cube KConfigGroup cubeConfig( m_config, "Effect-Cube" ); cubeConfig.writeEntry( "BorderActivate", monitorCheckEffectHasEdge( int( Cube ))); cubeConfig.writeEntry( "BorderActivateCylinder", monitorCheckEffectHasEdge( int( Cylinder ))); cubeConfig.writeEntry( "BorderActivateSphere", monitorCheckEffectHasEdge( int( Sphere ))); // Flip Switch KConfigGroup flipSwitchConfig( m_config, "Effect-FlipSwitch" ); flipSwitchConfig.writeEntry( "BorderActivateAll", monitorCheckEffectHasEdge( int( FlipSwitchAll ))); flipSwitchConfig.writeEntry( "BorderActivate", monitorCheckEffectHasEdge( int( FlipSwitchCurrent ))); } void KWinScreenEdgesConfig::monitorDefaults() { // Clear all edges for( int i = 0; i < 8; i++ ) m_ui->monitor->selectEdgeItem( i, 0 ); // Present windows = Top-left m_ui->monitor->selectEdgeItem( int( Monitor::TopLeft ), int( PresentWindowsAll )); } void KWinScreenEdgesConfig::monitorShowEvent() { // Check if they are enabled KConfigGroup config( m_config, "Compositing" ); if( config.readEntry( "Enabled", m_defaultPrefs.recommendCompositing() )) { // Compositing enabled config = KConfigGroup( m_config, "Plugins" ); // Present Windows bool enabled = effectEnabled( "presentwindows", config ); monitorItemSetEnabled( int( PresentWindowsCurrent ), enabled ); monitorItemSetEnabled( int( PresentWindowsAll ), enabled ); // Desktop Grid enabled = effectEnabled( "desktopgrid", config ); monitorItemSetEnabled( int( DesktopGrid ), enabled ); // Desktop Cube enabled = effectEnabled( "cube", config ); monitorItemSetEnabled( int( Cube ), enabled ); monitorItemSetEnabled( int( Cylinder ), enabled ); monitorItemSetEnabled( int( Sphere ), enabled ); // Flip Switch enabled = effectEnabled( "flipswitch", config ); monitorItemSetEnabled( int( FlipSwitchAll ), enabled ); monitorItemSetEnabled( int( FlipSwitchCurrent ), enabled ); } else // Compositing disabled { monitorItemSetEnabled( int( PresentWindowsCurrent ), false ); monitorItemSetEnabled( int( PresentWindowsAll ), false ); monitorItemSetEnabled( int( DesktopGrid ), false ); monitorItemSetEnabled( int( Cube ), false ); monitorItemSetEnabled( int( Cylinder ), false ); monitorItemSetEnabled( int( Sphere ), false ); monitorItemSetEnabled( int( FlipSwitchAll ), false ); monitorItemSetEnabled( int( FlipSwitchCurrent ), false ); } } void KWinScreenEdgesConfig::monitorChangeEdge( ElectricBorder border, int index ) { switch( border ) { case ElectricTop: m_ui->monitor->selectEdgeItem( int( Monitor::Top ), index ); break; case ElectricTopRight: m_ui->monitor->selectEdgeItem( int( Monitor::TopRight ), index ); break; case ElectricRight: m_ui->monitor->selectEdgeItem( int( Monitor::Right ), index ); break; case ElectricBottomRight: m_ui->monitor->selectEdgeItem( int( Monitor::BottomRight ), index ); break; case ElectricBottom: m_ui->monitor->selectEdgeItem( int( Monitor::Bottom ), index ); break; case ElectricBottomLeft: m_ui->monitor->selectEdgeItem( int( Monitor::BottomLeft ), index ); break; case ElectricLeft: m_ui->monitor->selectEdgeItem( int( Monitor::Left ), index ); break; case ElectricTopLeft: m_ui->monitor->selectEdgeItem( int( Monitor::TopLeft ), index ); break; default: // Nothing break; } } void KWinScreenEdgesConfig::monitorHideEdge( ElectricBorder border, bool hidden ) { switch( border ) { case ElectricTop: m_ui->monitor->setEdgeHidden( int( Monitor::Top ), hidden ); break; case ElectricTopRight: m_ui->monitor->setEdgeHidden( int( Monitor::TopRight ), hidden ); break; case ElectricRight: m_ui->monitor->setEdgeHidden( int( Monitor::Right ), hidden ); break; case ElectricBottomRight: m_ui->monitor->setEdgeHidden( int( Monitor::BottomRight ), hidden ); break; case ElectricBottom: m_ui->monitor->setEdgeHidden( int( Monitor::Bottom ), hidden ); break; case ElectricBottomLeft: m_ui->monitor->setEdgeHidden( int( Monitor::BottomLeft ), hidden ); break; case ElectricLeft: m_ui->monitor->setEdgeHidden( int( Monitor::Left ), hidden ); break; case ElectricTopLeft: m_ui->monitor->setEdgeHidden( int( Monitor::TopLeft ), hidden ); break; default: // Nothing break; } } QList KWinScreenEdgesConfig::monitorCheckEffectHasEdge( int index ) const { QList list = QList(); if( m_ui->monitor->selectedEdgeItem( int( Monitor::Top )) == index ) list.append( int( ElectricTop ) ); if( m_ui->monitor->selectedEdgeItem( int( Monitor::TopRight )) == index ) list.append( int( ElectricTopRight ) ); if( m_ui->monitor->selectedEdgeItem( int( Monitor::Right )) == index ) list.append( int( ElectricRight ) ); if( m_ui->monitor->selectedEdgeItem( int( Monitor::BottomRight )) == index ) list.append( int( ElectricBottomRight ) ); if( m_ui->monitor->selectedEdgeItem( int( Monitor::Bottom )) == index ) list.append( int( ElectricBottom ) ); if( m_ui->monitor->selectedEdgeItem( int( Monitor::BottomLeft )) == index ) list.append( int( ElectricBottomLeft ) ); if( m_ui->monitor->selectedEdgeItem( int( Monitor::Left )) == index ) list.append( int( ElectricLeft ) ); if( m_ui->monitor->selectedEdgeItem( int( Monitor::TopLeft )) == index ) list.append( int( ElectricTopLeft ) ); if( list.isEmpty() ) list.append( int( ElectricNone ) ); return list; } } // namespace #include "main.moc"