diff --git a/activation.cpp b/activation.cpp index 7cd31b22cc..15bfc8ada9 100644 --- a/activation.cpp +++ b/activation.cpp @@ -411,8 +411,19 @@ void Workspace::gotFocusIn( const Client* c ) // session_active -> the window was active when saving session bool Workspace::allowClientActivation( const Client* c, Time time, bool focus_in, bool session_active ) { - if( session_saving ) + // options->focusStealingPreventionLevel : + // 0 - none - old KWin behaviour, new windows always get focus + // 1 - low - focus stealing prevention is applied normally, when unsure, activation is allowed + // 2 - normal - focus stealing prevention is applied normally, when unsure, activation is not allowed, + // this is the default + // 3 - high - new window gets focus only if it belongs to the active application, + // or when no window is currently active + // 4 - extreme - no window gets focus without user intervention + if( session_saving + && options->focusStealingPreventionLevel <= 3 ) // <= normal + { return true; + } Client* ac = activeClient(); if( focus_in ) { @@ -422,6 +433,10 @@ bool Workspace::allowClientActivation( const Client* c, Time time, bool focus_in // got FocusOut, and therefore got deactivated. ac = last_active_client; } + if( options->focusStealingPreventionLevel == 0 ) // none + return true; + if( options->focusStealingPreventionLevel == 5 ) // extreme + return false; if( ac == NULL || ac->isDesktop()) { kdDebug( 1212 ) << "Activation: No client active, allowing" << endl; @@ -435,17 +450,22 @@ bool Workspace::allowClientActivation( const Client* c, Time time, bool focus_in kdDebug( 1212 ) << "Activation: Belongs to active application" << endl; return true; } + if( options->focusStealingPreventionLevel == 4 ) // high + return false; if( time == -1U ) // no time known if( session_active ) return !was_user_interaction; // see Client::readUserTimeMapTimestamp() else { kdDebug() << "Activation: No timestamp at all" << endl; - // no timestamp at all, don't activate - because there's also creation timestamp - // done on CreateNotify, this case should happen only in case application - // maps again already used window, i.e. this won't happen after app startup + if( options->focusStealingPreventionLevel == 1 ) // low + return true; + // no timestamp at all, don't activate - because there's also creation timestamp + // done on CreateNotify, this case should happen only in case application + // maps again already used window, i.e. this won't happen after app startup return false; } + // options->focusStealingPreventionLevel == 2 // normal Time user_time = ac->userTime(); kdDebug( 1212 ) << "Activation, compared:" << time << ":" << user_time << ":" << ( timestampCompare( time, user_time ) >= 0 ) << endl; diff --git a/kcmkwin/kwinoptions/windows.cpp b/kcmkwin/kwinoptions/windows.cpp index efeae09727..89f04b514f 100644 --- a/kcmkwin/kwinoptions/windows.cpp +++ b/kcmkwin/kwinoptions/windows.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,7 @@ #define KWIN_ROLL_OVER_DESKTOPS "RollOverDesktops" #define KWIN_SHADEHOVER "ShadeHover" #define KWIN_SHADEHOVER_INTERVAL "ShadeHoverInterval" +#define KWIN_FOCUS_STEALING "FocusStealingPreventionLevel" // kwm config keywords #define KWM_ELECTRIC_BORDER "ElectricBorders" @@ -511,6 +513,38 @@ KAdvancedConfig::KAdvancedConfig (bool _standAlone, KConfig *_config, QWidget *p lay->addWidget(electricBox); + QHBoxLayout* focusStealingLayout = new QHBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint()); + QLabel* focusStealingLabel = new QLabel( i18n( "Focus Stealing Prevention Level:" ), this ); + focusStealing = new QComboBox( this ); + focusStealing->insertItem( i18n( "Focus Stealing Prevention Level", "None" )); + focusStealing->insertItem( i18n( "Focus Stealing Prevention Level", "Low" )); + focusStealing->insertItem( i18n( "Focus Stealing Prevention Level", "Normal" )); + focusStealing->insertItem( i18n( "Focus Stealing Prevention Level", "High" )); + focusStealing->insertItem( i18n( "Focus Stealing Prevention Level", "Extreme" )); + focusStealingLabel->setBuddy( focusStealing ); + focusStealingLayout->addWidget( focusStealingLabel ); + focusStealingLayout->addWidget( focusStealing, AlignLeft ); + wtstr = i18n( "This option specifies how much will KWin try to prevent unwanted focus stealing " + "caused by unexpected activation of new windows.
    " + "
  • None: The standard old behaviour - prevention is turned off " + "and new windows get always activated.
  • " + "
  • Low: Prevention is enabled; when some window doesn't have support " + "for the underlying mechanism and KWin cannot reliably decide whether to " + "activate the window or not, it will be activated. This setting may have both" + "worse and better results than normal level depending on the applications.
  • " + "
  • Normal: Prevention is enabled; the default setting.
  • " + "
  • High: New windows get activated only if no window is currently active " + "or if they belong to the currently active application. This setting is probably " + "not really usable when noting using mouse focus policy.
  • " + "
  • Extreme: All windows must be explicitly activated by the user.
  • " + "
" ); + QWhatsThis::add( focusStealing, wtstr ); + QWhatsThis::add( focusStealingLabel, wtstr ); + + connect(focusStealing, SIGNAL(activated(int)), SLOT(changed())); + + lay->addLayout( focusStealingLayout ); + lay->addStretch(); load(); @@ -538,6 +572,11 @@ void KAdvancedConfig::setAnimateShade(bool a) { animateShade->setChecked(a); } +void KAdvancedConfig::setFocusStealing(int l) { + l = KMAX( 0, KMIN( 4, l )); + focusStealing->setCurrentItem(l); +} + void KAdvancedConfig::load( void ) { config->setGroup( "Windows" ); @@ -548,6 +587,9 @@ void KAdvancedConfig::load( void ) setElectricBorders(config->readNumEntry(KWM_ELECTRIC_BORDER, false)); setElectricBorderDelay(config->readNumEntry(KWM_ELECTRIC_BORDER_DELAY, 150)); + + setFocusStealing( config->readNumEntry(KWIN_FOCUS_STEALING, 2 )); + setChanged(false); } @@ -568,6 +610,8 @@ void KAdvancedConfig::save( void ) config->writeEntry(KWM_ELECTRIC_BORDER, getElectricBorders()); config->writeEntry(KWM_ELECTRIC_BORDER_DELAY,getElectricBorderDelay()); + + config->writeEntry(KWIN_FOCUS_STEALING, focusStealing->currentItem()); if (standAlone) { @@ -586,6 +630,7 @@ void KAdvancedConfig::defaults() setShadeHoverInterval(250); setElectricBorders(0); setElectricBorderDelay(150); + setFocusStealing(2); setChanged(true); } diff --git a/kcmkwin/kwinoptions/windows.h b/kcmkwin/kwinoptions/windows.h index 0cd63aea2b..40afa7c015 100644 --- a/kcmkwin/kwinoptions/windows.h +++ b/kcmkwin/kwinoptions/windows.h @@ -213,6 +213,10 @@ private: QRadioButton *active_move; QRadioButton *active_always; KIntNumInput *delays; + + void setFocusStealing( int ); + + QComboBox* focusStealing; }; #endif diff --git a/options.cpp b/options.cpp index c6065445aa..d33294e2ef 100644 --- a/options.cpp +++ b/options.cpp @@ -62,6 +62,9 @@ unsigned long Options::updateSettings() altTabStyle = CDE; rollOverDesktops = config->readBoolEntry("RollOverDesktops", TRUE); + + focusStealingPreventionLevel = config->readNumEntry( "FocusStealingPreventionLevel", 2 ); + focusStealingPreventionLevel = KMAX( 0, KMIN( 4, focusStealingPreventionLevel )); KConfig *gc = new KConfig("kdeglobals", false, false); bool isVirtual = KApplication::desktop()->isVirtualDesktop(); diff --git a/options.h b/options.h index 4148e8f1a4..dbd3eaf881 100644 --- a/options.h +++ b/options.h @@ -180,6 +180,9 @@ class Options : public KDecorationOptions */ bool rollOverDesktops; + // 0 - 4 , see Workspace::allowClientActivation() + int focusStealingPreventionLevel; + /** * List of window classes to ignore PPosition size hint */