/*
* windows.cpp
*
* Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca
* Copyright (c) 2001 Waldo Bastian bastian@kde.org
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#include This option specifies how much KWin will try to prevent unwanted focus stealing "
"caused by unexpected activation of new windows. (Note: This feature does not "
"work with the Focus Under Mouse or Focus Strictly Under Mouse focus policies.)"
""
"
"
"Note that 'Focus under mouse' and 'Focus strictly under mouse' prevent certain"
" features such as the Alt+Tab walk through windows dialog in the KDE mode"
" from working properly."
);
focusCombo->setWhatsThis( wtstr);
connect(focusCombo, SIGNAL(activated(int)), this, SLOT(focusPolicyChanged()) );
// autoraise delay
autoRaiseOn = new QCheckBox(i18n("&Raise, with the following delay:"), fcsBox);
connect(autoRaiseOn,SIGNAL(toggled(bool)), this, SLOT(autoRaiseOnTog(bool)));
autoRaise = new KIntNumInput(500, fcsBox);
autoRaise->setRange(0, 3000, 100);
autoRaise->setSteps(100,100);
autoRaise->setSuffix(i18n(" ms"));
fLay->addRow( autoRaiseOn, autoRaise);
connect(focusCombo, SIGNAL(activated(int)), this, SLOT(setDelayFocusEnabled()) );
delayFocusOn = new QCheckBox(i18n("Delay focus by:"), fcsBox);
connect(delayFocusOn,SIGNAL(toggled(bool)), this, SLOT(delayFocusOnTog(bool)));
delayFocus = new KIntNumInput(500, fcsBox);
delayFocus->setRange(0, 3000, 100);
delayFocus->setSteps(100,100);
delayFocus->setSuffix(i18n(" ms"));
fLay->addRow( delayFocusOn, delayFocus);
clickRaiseOn = new QCheckBox(i18n("C&lick raises active window"), fcsBox);
connect(clickRaiseOn,SIGNAL(toggled(bool)), this, SLOT(clickRaiseOnTog(bool)));
fLay->addRow(clickRaiseOn);
autoRaiseOn->setWhatsThis( i18n("When this option is enabled, a window in the background will automatically"
" come to the front when the mouse pointer has been over it for some time.") );
wtstr = i18n("This is the delay after which the window that the mouse pointer is over will automatically"
" come to the front.");
autoRaise->setWhatsThis( wtstr );
clickRaiseOn->setWhatsThis( i18n("When this option is enabled, the active window will be brought to the"
" front when you click somewhere into the window contents. To change"
" it for inactive windows, you need to change the settings"
" in the Actions tab.") );
delayFocusOn->setWhatsThis( 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).") );
delayFocus->setWhatsThis( i18n("This is the delay after which the window the mouse pointer is over"
" will automatically receive focus.") );
separateScreenFocus = new QCheckBox( i18n( "S&eparate screen focus" ), fcsBox );
fLay->addRow( separateScreenFocus );
wtstr = i18n( "When this option is enabled, focus operations are limited only to the active Xinerama screen" );
separateScreenFocus->setWhatsThis( wtstr );
activeMouseScreen = new QCheckBox( i18n( "Active screen follows &mouse" ), fcsBox );
fLay->addRow( activeMouseScreen );
wtstr = i18n( "When this option is enabled, the active Xinerama screen (where new windows appear, for example)"
" is the screen containing the mouse pointer. When disabled, the active Xinerama screen is the "
" screen containing the focused window. By default this option is disabled for Click to focus and"
" enabled for other focus policies." );
activeMouseScreen->setWhatsThis( wtstr );
connect(focusCombo, SIGNAL(activated(int)), this, SLOT(updateActiveMouseScreen()));
if (!QApplication::desktop()->isVirtualDesktop() ||
QApplication::desktop()->numScreens() == 1) // No Ximerama
{
separateScreenFocus->hide();
activeMouseScreen->hide();
}
focusStealing = new QComboBox( this );
focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "None" ));
focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "Low" ));
focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "Normal" ));
focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "High" ));
focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "Extreme" ));
wtstr = i18n( ""
"
Windows that are prevented from stealing focus are marked as demanding attention, " "which by default means their taskbar entry will be highlighted. This can be changed " "in the Notifications control module.
" ); focusStealing->setWhatsThis( wtstr ); connect(focusStealing, SIGNAL(activated(int)), SLOT(changed())); fLay->addRow(i18n( "Focus stealing prevention level:" ), focusStealing); lay->addWidget(fcsBox); kbdBox = new KButtonGroup(this); kbdBox->setTitle(i18nc("@title:group", "Window Switching")); QVBoxLayout *kLay = new QVBoxLayout(kbdBox); altTabPopup = new QCheckBox( i18n("Show window list while switching windows"), kbdBox ); kLay->addWidget( altTabPopup ); wtstr = i18n("Hold down the Alt key and press the Tab key repeatedly to walk" " through the windows on the current desktop (the Alt+Tab" " combination can be reconfigured).\n\n" "If this checkbox is checked" " a popup widget is shown, displaying the icons of all windows to" " walk through and the title of the currently selected one.\n\n" "Otherwise, the focus is passed to a new window each time Tab" " is pressed, with no popup widget. In addition, the previously" " activated window will be sent to the back in this mode."); altTabPopup->setWhatsThis( wtstr ); connect(focusCombo, SIGNAL(activated(int)), this, SLOT(updateAltTabMode())); kLay->addWidget(altTabPopup); traverseAll = new QCheckBox( i18n( "&Traverse windows on all desktops" ), kbdBox ); kLay->addWidget( traverseAll ); wtstr = i18n( "Leave this option disabled if you want to limit walking through" " windows to the current desktop." ); traverseAll->setWhatsThis( wtstr ); kLay->addWidget(traverseAll); rollOverDesktops = new QCheckBox( i18n("Desktop navi&gation wraps around"), kbdBox ); kLay->addWidget(rollOverDesktops); wtstr = i18n( "Enable this option if you want keyboard or active desktop border navigation beyond" " the edge of a desktop to take you to the opposite edge of the new desktop." ); rollOverDesktops->setWhatsThis( wtstr ); kLay->addWidget(rollOverDesktops); showPopupinfo = new QCheckBox( i18n("Popup desktop name on desktop &switch"), kbdBox ); kLay->addWidget(showPopupinfo); wtstr = i18n( "Enable this option if you wish to see the current desktop" " name popup whenever the current desktop is changed." ); showPopupinfo->setWhatsThis( wtstr ); kLay->addWidget(showPopupinfo); lay->addWidget(kbdBox); lay->addStretch(); // Any changes goes to slotChanged() connect(focusCombo, SIGNAL(activated(int)), SLOT(changed())); connect(autoRaiseOn,SIGNAL(clicked()), SLOT(changed())); connect(delayFocusOn, SIGNAL(clicked()), SLOT(changed())); connect(clickRaiseOn, SIGNAL(clicked()), SLOT(changed())); connect(autoRaise, SIGNAL(valueChanged(int)), SLOT(changed())); connect(delayFocus, SIGNAL(valueChanged(int)), SLOT(changed())); connect(separateScreenFocus, SIGNAL(clicked()), SLOT(changed())); connect(activeMouseScreen, SIGNAL(clicked()), SLOT(changed())); connect(altTabPopup, SIGNAL(clicked()), SLOT(changed())); connect(traverseAll, SIGNAL(clicked()), SLOT(changed())); connect(rollOverDesktops, SIGNAL(clicked()), SLOT(changed())); connect(showPopupinfo, SIGNAL(clicked()), SLOT(changed())); load(); } int KFocusConfig::getFocus() { return focusCombo->currentIndex(); } void KFocusConfig::setFocus(int foc) { focusCombo->setCurrentIndex(foc); // this will disable/hide the auto raise delay widget if focus==click focusPolicyChanged(); updateAltTabMode(); } void KFocusConfig::updateAltTabMode() { // not KDE-style Alt+Tab with unreasonable focus policies altTabPopup->setEnabled( focusCombo->currentIndex() == 0 || focusCombo->currentIndex() == 1 ); } 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); } void KFocusConfig::focusPolicyChanged() { int policyIndex=focusCombo->currentIndex(); // the auto raise related widgets are: autoRaise autoRaiseOn->setEnabled(policyIndex != CLICK_TO_FOCUS); autoRaiseOnTog(policyIndex != CLICK_TO_FOCUS && autoRaiseOn->isChecked()); focusStealing->setDisabled(policyIndex == FOCUS_UNDER_MOUSE || policyIndex == FOCUS_STRICTLY_UNDER_MOUSE); } void KFocusConfig::setDelayFocusEnabled() { int policyIndex=focusCombo->currentIndex(); // the delayed focus related widgets are: delayFocus delayFocusOn->setEnabled(policyIndex != CLICK_TO_FOCUS); delayFocusOnTog(policyIndex != CLICK_TO_FOCUS && delayFocusOn->isChecked()); } void KFocusConfig::autoRaiseOnTog(bool a) { autoRaise->setEnabled(a); clickRaiseOn->setEnabled( !a ); } void KFocusConfig::delayFocusOnTog(bool a) { delayFocus->setEnabled(a); } void KFocusConfig::clickRaiseOnTog(bool ) { } void KFocusConfig::setFocusStealing(int l) { l = qMax( 0, qMin( 4, l )); focusStealing->setCurrentIndex(l); } void KFocusConfig::setSeparateScreenFocus(bool s) { separateScreenFocus->setChecked(s); } void KFocusConfig::setActiveMouseScreen(bool a) { activeMouseScreen->setChecked(a); } void KFocusConfig::updateActiveMouseScreen() { // on by default for non click to focus policies KConfigGroup cfg( config, "Windows" ); if( !cfg.hasKey( KWIN_ACTIVE_MOUSE_SCREEN )) setActiveMouseScreen( focusCombo->currentIndex() != 0 ); } void KFocusConfig::setAltTabMode(bool a) { altTabPopup->setChecked(a); } void KFocusConfig::setTraverseAll(bool a) { traverseAll->setChecked(a); } void KFocusConfig::setRollOverDesktops(bool a) { rollOverDesktops->setChecked(a); } void KFocusConfig::setShowPopupinfo(bool a) { showPopupinfo->setChecked(a); } void KFocusConfig::load( void ) { QString key; KConfigGroup cg(config, "Windows"); key = cg.readEntry(KWIN_FOCUS); if( key == "ClickToFocus") setFocus(CLICK_TO_FOCUS); else if( key == "FocusFollowsMouse") setFocus(FOCUS_FOLLOWS_MOUSE); else if(key == "FocusUnderMouse") setFocus(FOCUS_UNDER_MOUSE); else if(key == "FocusStrictlyUnderMouse") setFocus(FOCUS_STRICTLY_UNDER_MOUSE); int k = cg.readEntry(KWIN_AUTORAISE_INTERVAL,750); setAutoRaiseInterval(k); k = cg.readEntry(KWIN_DELAYFOCUS_INTERVAL,750); setDelayFocusInterval(k); setAutoRaise( cg.readEntry(KWIN_AUTORAISE, false)); setDelayFocus( cg.readEntry(KWIN_DELAYFOCUS, false)); setClickRaise( cg.readEntry(KWIN_CLICKRAISE, true)); focusPolicyChanged(); // this will disable/hide the auto raise delay widget if focus==click setDelayFocusEnabled(); setSeparateScreenFocus( cg.readEntry(KWIN_SEPARATE_SCREEN_FOCUS, false)); // on by default for non click to focus policies setActiveMouseScreen( cg.readEntry(KWIN_ACTIVE_MOUSE_SCREEN, focusCombo->currentIndex() != 0 )); key = cg.readEntry(KWIN_ALTTABMODE, "KDE"); setAltTabMode(key == "KDE"); setRollOverDesktops( cg.readEntry(KWIN_ROLL_OVER_DESKTOPS, true)); setShowPopupinfo( config->group("PopupInfo").readEntry(KWIN_SHOW_POPUP, false)); setTraverseAll( config->group("TabBox").readEntry(KWIN_TRAVERSE_ALL, false)); // setFocusStealing( cg.readEntry(KWIN_FOCUS_STEALING, 2 )); // TODO default to low for now setFocusStealing( cg.readEntry(KWIN_FOCUS_STEALING, 1 )); emit KCModule::changed(false); } void KFocusConfig::save( void ) { int v; KConfigGroup cg(config, "Windows"); v = getFocus(); if (v == CLICK_TO_FOCUS) cg.writeEntry(KWIN_FOCUS,"ClickToFocus"); else if (v == FOCUS_UNDER_MOUSE) cg.writeEntry(KWIN_FOCUS,"FocusUnderMouse"); else if (v == FOCUS_STRICTLY_UNDER_MOUSE) cg.writeEntry(KWIN_FOCUS,"FocusStrictlyUnderMouse"); else cg.writeEntry(KWIN_FOCUS,"FocusFollowsMouse"); v = getAutoRaiseInterval(); if (v <0) v = 0; cg.writeEntry(KWIN_AUTORAISE_INTERVAL,v); v = getDelayFocusInterval(); if (v <0) v = 0; cg.writeEntry(KWIN_DELAYFOCUS_INTERVAL,v); cg.writeEntry(KWIN_AUTORAISE, autoRaiseOn->isChecked()); cg.writeEntry(KWIN_DELAYFOCUS, delayFocusOn->isChecked()); cg.writeEntry(KWIN_CLICKRAISE, clickRaiseOn->isChecked()); cg.writeEntry(KWIN_SEPARATE_SCREEN_FOCUS, separateScreenFocus->isChecked()); cg.writeEntry(KWIN_ACTIVE_MOUSE_SCREEN, activeMouseScreen->isChecked()); if (altTabPopup->isChecked()) cg.writeEntry(KWIN_ALTTABMODE, "KDE"); else cg.writeEntry(KWIN_ALTTABMODE, "CDE"); cg.writeEntry( KWIN_ROLL_OVER_DESKTOPS, rollOverDesktops->isChecked()); config->group("PopupInfo").writeEntry( KWIN_SHOW_POPUP, showPopupinfo->isChecked()); config->group("TabBox").writeEntry( KWIN_TRAVERSE_ALL , traverseAll->isChecked()); cg.writeEntry(KWIN_FOCUS_STEALING, focusStealing->currentIndex()); if (standAlone) { config->sync(); // Send signal to all kwin instances QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); QDBusConnection::sessionBus().send(message); } emit KCModule::changed(false); } void KFocusConfig::defaults() { setAutoRaiseInterval(0); setDelayFocusInterval(0); setFocus(CLICK_TO_FOCUS); setAutoRaise(false); setDelayFocus(false); setClickRaise(true); setSeparateScreenFocus( false ); // setFocusStealing(2); // TODO default to low for now setFocusStealing(1); // on by default for non click to focus policies setActiveMouseScreen( focusCombo->currentIndex() != 0 ); setAltTabMode(true); setTraverseAll( false ); setRollOverDesktops(true); setShowPopupinfo(false); setDelayFocusEnabled(); emit KCModule::changed(true); } KAdvancedConfig::~KAdvancedConfig () { if (standAlone) delete config; } KAdvancedConfig::KAdvancedConfig (bool _standAlone, KConfig *_config, const KComponentData &inst, QWidget *parent) : KCModule(inst, parent), config(_config), standAlone(_standAlone) { QString wtstr; QBoxLayout *lay = new QVBoxLayout (this); //iTLabel = new QLabel(i18n(" Allowed overlap:\n" // "(% of desktop space)"), // plcBox); //iTLabel->setAlignment(AlignTop|AlignHCenter); //pLay->addWidget(iTLabel,1,1); //interactiveTrigger = new QSpinBox(0, 500, 1, plcBox); //pLay->addWidget(interactiveTrigger,1,2); //pLay->addRowSpacing(2,KDialog::spacingHint()); //lay->addWidget(plcBox); shBox = new KButtonGroup(this); shBox->setTitle(i18n("Shading")); QVBoxLayout *kLay = new QVBoxLayout(shBox); shadeHoverOn = new QCheckBox(i18n("&Enable hover"), shBox); connect(shadeHoverOn, SIGNAL(toggled(bool)), this, SLOT(shadeHoverChanged(bool))); kLay->addWidget(shadeHoverOn); shadeHover = new KIntNumInput(500, shBox); shadeHover->setLabel(i18n("Dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); shadeHover->setRange(0, 3000, 100); shadeHover->setSteps(100, 100); shadeHover->setSuffix(i18n(" ms")); shadeHoverOn->setWhatsThis( i18n("If Shade Hover is enabled, a shaded window will un-shade automatically " "when the mouse pointer has been over the title bar for some time.")); wtstr = i18n("Sets the time in milliseconds before the window unshades " "when the mouse pointer goes over the shaded window."); shadeHover->setWhatsThis( wtstr); kLay->addWidget(shadeHover); lay->addWidget(shBox); // Any changes goes to slotChanged() connect(shadeHoverOn, SIGNAL(toggled(bool)), SLOT(changed())); connect(shadeHover, SIGNAL(valueChanged(int)), SLOT(changed())); electricBox = new KButtonGroup(this); electricBox->setTitle(i18n("Active Desktop Borders")); QVBoxLayout *bLay = new QVBoxLayout(electricBox); electricBox->setWhatsThis( i18n("If this option is enabled, moving the mouse to a screen border" " will change your desktop. This is e.g. useful if you want to drag windows from one desktop" " to the other.") ); active_disable = new QRadioButton(i18n("D&isabled"), electricBox); bLay->addWidget(active_disable); active_move = new QRadioButton(i18n("Only &when moving windows"), electricBox); bLay->addWidget(active_move); active_always = new QRadioButton(i18n("A&lways enabled"), electricBox); bLay->addWidget(active_always); delays = new KIntNumInput(10, electricBox); delays->setRange(0, MAX_EDGE_RES, 50); delays->setSuffix(i18n(" ms")); delays->setLabel(i18n("Desktop &switch delay:"), Qt::AlignVCenter|Qt::AlignLeft); delays->setWhatsThis( i18n("Here you can set a delay for switching desktops using the active" " borders feature. Desktops will be switched after the mouse has been pushed against a screen border" " for the specified number of milliseconds.") ); bLay->addWidget(delays); connect( electricBox, SIGNAL(clicked(int)), this, SLOT(setEBorders())); // Any changes goes to slotChanged() connect(electricBox, SIGNAL(clicked(int)), SLOT(changed())); connect(delays, SIGNAL(valueChanged(int)), SLOT(changed())); lay->addWidget(electricBox); QFormLayout *vLay = new QFormLayout(); lay->addLayout( vLay ); placementCombo = new QComboBox(this); placementCombo->setEditable( false ); placementCombo->addItem(i18n("Smart"), SMART_PLACEMENT); placementCombo->addItem(i18n("Maximizing"), MAXIMIZING_PLACEMENT); placementCombo->addItem(i18n("Cascade"), CASCADE_PLACEMENT); placementCombo->addItem(i18n("Random"), RANDOM_PLACEMENT); placementCombo->addItem(i18n("Centered"), CENTERED_PLACEMENT); placementCombo->addItem(i18n("Zero-Cornered"), ZEROCORNERED_PLACEMENT); // CT: disabling is needed as long as functionality misses in kwin //placementCombo->addItem(i18n("Interactive"), INTERACTIVE_PLACEMENT); //placementCombo->addItem(i18n("Manual"), MANUAL_PLACEMENT); placementCombo->setCurrentIndex(SMART_PLACEMENT); // FIXME, when more policies have been added to KWin wtstr = i18n("The placement policy determines where a new window" " will appear on the desktop." "