diff --git a/activation.cpp b/activation.cpp index cf327aa1f0..dbcf0a17a7 100644 --- a/activation.cpp +++ b/activation.cpp @@ -331,6 +331,7 @@ void Workspace::takeActivity( Client* c, int flags, bool handled ) c = modal; handled = false; } + cancelDelayFocus(); } if ( !( flags & ActivityFocusForce ) && ( c->isTopMenu() || c->isDock() || c->isSplash()) ) flags &= ~ActivityFocus; // toplevel menus and dock windows don't take focus if not forced diff --git a/events.cpp b/events.cpp index 9978f9eb81..9bf1ed777f 100644 --- a/events.cpp +++ b/events.cpp @@ -890,8 +890,11 @@ void Client::enterNotifyEvent( XCrossingEvent* e ) if ( options->focusPolicy != Options::FocusStrictlyUnderMouse && ( isDesktop() || isDock() || isTopMenu() ) ) return; + if ( options->delayFocus ) + workspace()->requestDelayFocus( this ); + else + workspace()->requestFocus( this ); - workspace()->requestFocus( this ); return; } } @@ -927,6 +930,7 @@ void Client::leaveNotifyEvent( XCrossingEvent* e ) if ( lostMouse ) { cancelAutoRaise(); + workspace()->cancelDelayFocus(); delete shadeHoverTimer; shadeHoverTimer = 0; if ( shade_mode == ShadeHover && !moveResizeMode && !buttonDown ) diff --git a/kcmkwin/kwinoptions/windows.cpp b/kcmkwin/kwinoptions/windows.cpp index a137ac22f1..b44fbe8785 100644 --- a/kcmkwin/kwinoptions/windows.cpp +++ b/kcmkwin/kwinoptions/windows.cpp @@ -57,6 +57,8 @@ #define KWIN_GEOMETRY "GeometryTip" #define KWIN_AUTORAISE_INTERVAL "AutoRaiseInterval" #define KWIN_AUTORAISE "AutoRaise" +#define KWIN_DELAYFOCUS_INTERVAL "DelayFocusInterval" +#define KWIN_DELAYFOCUS "DelayFocus" #define KWIN_CLICKRAISE "ClickRaise" #define KWIN_ANIMSHADE "AnimateShade" #define KWIN_MOVE_RESIZE_MAXIMIZED "MoveResizeMaximizedWindows" @@ -164,6 +166,19 @@ KFocusConfig::KFocusConfig (bool _standAlone, KConfig *_config, QWidget * parent autoRaise->setSuffix(i18n(" msec")); fLay->addWidget(autoRaise); + connect(focusCombo, SIGNAL(activated(int)), this, SLOT(setDelayFocusEnabled()) ); + + delayFocusOn = new QCheckBox(i18n("Delay focus"), fcsBox); + fLay->addWidget(delayFocusOn); + connect(delayFocusOn,SIGNAL(toggled(bool)), this, SLOT(delayFocusOnTog(bool))); + + delayFocus = new KIntNumInput(500, fcsBox); + delayFocus->setLabel(i18n("Dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); + delayFocus->setRange(0, 3000, 100, true); + delayFocus->setSteps(100,100); + delayFocus->setSuffix(i18n(" msec")); + fLay->addWidget(delayFocus); + clickRaiseOn = new QCheckBox(i18n("C&lick raise active window"), fcsBox); connect(clickRaiseOn,SIGNAL(toggled(bool)), this, SLOT(clickRaiseOnTog(bool))); fLay->addWidget(clickRaiseOn); @@ -182,6 +197,11 @@ KFocusConfig::KFocusConfig (bool _standAlone, KConfig *_config, QWidget * parent " it for inactive windows, you need to change the settings" " in the Actions tab.") ); + QWhatsThis::add( delayFocusOn, i18n("When this option is enabled, there will be a delay after which the" + " window the mouse pointer is over will become active (receive focus).") ); + QWhatsThis::add( delayFocus, i18n("This is the delay after which the window the mouse pointer is over" + " will automatically receive focus.") ); + lay->addWidget(fcsBox); kbdBox = new QButtonGroup(i18n("Navigation"), this); @@ -235,6 +255,7 @@ KFocusConfig::KFocusConfig (bool _standAlone, KConfig *_config, QWidget * parent connect(focusCombo, SIGNAL(activated(int)), SLOT(changed())); connect(fcsBox, SIGNAL(clicked(int)), SLOT(changed())); connect(autoRaise, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(delayFocus, SIGNAL(valueChanged(int)), SLOT(changed())); connect(kdeMode, SIGNAL(clicked()), SLOT(changed())); connect(cdeMode, SIGNAL(clicked()), SLOT(changed())); connect(traverseAll, SIGNAL(clicked()), SLOT(changed())); @@ -263,16 +284,31 @@ void KFocusConfig::setAutoRaiseInterval(int tb) autoRaise->setValue(tb); } +void KFocusConfig::setDelayFocusInterval(int tb) +{ + delayFocus->setValue(tb); +} + int KFocusConfig::getAutoRaiseInterval() { return autoRaise->value(); } +int KFocusConfig::getDelayFocusInterval() +{ + return delayFocus->value(); +} + void KFocusConfig::setAutoRaise(bool on) { autoRaiseOn->setChecked(on); } +void KFocusConfig::setDelayFocus(bool on) +{ + delayFocusOn->setChecked(on); +} + void KFocusConfig::setClickRaise(bool on) { clickRaiseOn->setChecked(on); @@ -293,12 +329,30 @@ void KFocusConfig::setAutoRaiseEnabled() } } +void KFocusConfig::setDelayFocusEnabled() +{ + // the delayed focus related widgets are: delayFocus + if ( focusCombo->currentItem() != CLICK_TO_FOCUS ) + { + delayFocusOn->setEnabled(true); + delayFocusOnTog(delayFocusOn->isChecked()); + } + else + { + delayFocusOn->setEnabled(false); + delayFocusOnTog(false); + } +} void KFocusConfig::autoRaiseOnTog(bool a) { autoRaise->setEnabled(a); clickRaiseOn->setEnabled( !a ); } +void KFocusConfig::delayFocusOnTog(bool a) { + delayFocus->setEnabled(a); +} + void KFocusConfig::clickRaiseOnTog(bool ) { } @@ -338,11 +392,17 @@ void KFocusConfig::load( void ) int k = config->readNumEntry(KWIN_AUTORAISE_INTERVAL,750); setAutoRaiseInterval(k); + k = config->readNumEntry(KWIN_DELAYFOCUS_INTERVAL,750); + setDelayFocusInterval(k); + key = config->readEntry(KWIN_AUTORAISE); setAutoRaise(key == "on"); + key = config->readEntry(KWIN_DELAYFOCUS); + setDelayFocus(key == "on"); key = config->readEntry(KWIN_CLICKRAISE); setClickRaise(key != "off"); setAutoRaiseEnabled(); // this will disable/hide the auto raise delay widget if focus==click + setDelayFocusEnabled(); key = config->readEntry(KWIN_ALTTABMODE, "KDE"); setAltTabMode(key == "KDE"); @@ -379,11 +439,20 @@ void KFocusConfig::save( void ) if (v <0) v = 0; config->writeEntry(KWIN_AUTORAISE_INTERVAL,v); + v = getDelayFocusInterval(); + if (v <0) v = 0; + config->writeEntry(KWIN_DELAYFOCUS_INTERVAL,v); + if (autoRaiseOn->isChecked()) config->writeEntry(KWIN_AUTORAISE, "on"); else config->writeEntry(KWIN_AUTORAISE, "off"); + if (delayFocusOn->isChecked()) + config->writeEntry(KWIN_DELAYFOCUS, "on"); + else + config->writeEntry(KWIN_DELAYFOCUS, "off"); + if (clickRaiseOn->isChecked()) config->writeEntry(KWIN_CLICKRAISE, "on"); else @@ -417,8 +486,10 @@ void KFocusConfig::save( void ) void KFocusConfig::defaults() { setAutoRaiseInterval(0); + setDelayFocusInterval(0); setFocus(CLICK_TO_FOCUS); setAutoRaise(false); + setDelayFocus(false); setClickRaise(true); setAltTabMode(true); setTraverseAll( false ); diff --git a/kcmkwin/kwinoptions/windows.h b/kcmkwin/kwinoptions/windows.h index 56e4ce576d..f2a7c15413 100644 --- a/kcmkwin/kwinoptions/windows.h +++ b/kcmkwin/kwinoptions/windows.h @@ -77,8 +77,10 @@ public: void defaults(); private slots: + void setDelayFocusEnabled(); void setAutoRaiseEnabled(); void autoRaiseOnTog(bool);//CT 23Oct1998 + void delayFocusOnTog(bool); void clickRaiseOnTog(bool); void changed() { emit KCModule::changed(true); } @@ -87,10 +89,13 @@ private: int getFocus( void ); int getAutoRaiseInterval( void ); + int getDelayFocusInterval( void ); void setFocus(int); void setAutoRaiseInterval(int); void setAutoRaise(bool); + void setDelayFocusInterval(int); + void setDelayFocus(bool); void setClickRaise(bool); void setAltTabMode(bool); void setTraverseAll(bool); @@ -100,8 +105,10 @@ private: QButtonGroup *fcsBox; QComboBox *focusCombo; QCheckBox *autoRaiseOn; + QCheckBox *delayFocusOn; QCheckBox *clickRaiseOn; KIntNumInput *autoRaise; + KIntNumInput *delayFocus; QButtonGroup *kbdBox; QRadioButton *kdeMode; diff --git a/kwin.kcfg b/kwin.kcfg index d46c78d865..27fec89c23 100644 --- a/kwin.kcfg +++ b/kwin.kcfg @@ -45,6 +45,8 @@ + + diff --git a/options.cpp b/options.cpp index effbfb8b8d..f16ccd7781 100644 --- a/options.cpp +++ b/options.cpp @@ -108,11 +108,15 @@ unsigned long Options::updateSettings() { autoRaise = false; autoRaiseInterval = 0; + delayFocus = false; + delayFocusInterval = 0; } else { autoRaise = config->readBoolEntry("AutoRaise", FALSE ); autoRaiseInterval = config->readNumEntry("AutoRaiseInterval", 0 ); + delayFocus = config->readBoolEntry("DelayFocus", FALSE ); + delayFocusInterval = config->readNumEntry("DelayFocusInterval", 0 ); } shadeHover = config->readBoolEntry("ShadeHover", FALSE ); diff --git a/options.h b/options.h index 5c98c910cf..5b3bd2484c 100644 --- a/options.h +++ b/options.h @@ -83,6 +83,16 @@ class Options : public KDecorationOptions */ int autoRaiseInterval; + /** + whether delay focus is enabled or not. + */ + bool delayFocus; + + /** + delayed focus interval + */ + int delayFocusInterval; + /** Whether shade hover is enabled or not */ diff --git a/workspace.cpp b/workspace.cpp index 8543b482ba..383d09f8a1 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -70,6 +70,7 @@ Workspace::Workspace( bool restore ) most_recently_raised (0), movingClient(0), pending_take_activity ( NULL ), + delayfocus_client (0), was_user_interaction (false), session_saving (false), control_grab (false), @@ -109,6 +110,8 @@ Workspace::Workspace( bool restore ) updateXTime(); // needed for proper initialization of user_time in Client ctor + delayFocusTimer = 0; + electric_time_first = qt_x_time; electric_time_last = qt_x_time; @@ -1641,7 +1644,27 @@ QWidget* Workspace::desktopWidget() return desktop_widget; } - +//Delayed focus functions +void Workspace::delayFocus() + { + requestFocus( delayfocus_client ); + cancelDelayFocus(); + } + +void Workspace::requestDelayFocus( Client* c ) + { + delayfocus_client = c; + delete delayFocusTimer; + delayFocusTimer = new QTimer( this ); + connect( delayFocusTimer, SIGNAL( timeout() ), this, SLOT( delayFocus() ) ); + delayFocusTimer->start( options->delayFocusInterval, TRUE ); + } + +void Workspace::cancelDelayFocus() + { + delete delayFocusTimer; + delayFocusTimer = 0; + } // Electric Borders //========================================================================// diff --git a/workspace.h b/workspace.h index 06ce61b8ea..a74a23026c 100644 --- a/workspace.h +++ b/workspace.h @@ -244,6 +244,9 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine static QStringList configModules(bool controlCenter); + void cancelDelayFocus(); + void requestDelayFocus( Client* ); + public slots: void refresh(); // keybindings @@ -320,6 +323,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine void slotUpdateToolWindows(); void lostTopMenuSelection(); void lostTopMenuOwner(); + void delayFocus(); protected: bool keyPressMouseEmulation( XKeyEvent& ev ); @@ -431,6 +435,10 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine Client* movingClient; Client* pending_take_activity; + // delay(ed) window focus timer and client + QTimer* delayFocusTimer; + Client* delayfocus_client; + ClientList clients; ClientList desktops;