diff --git a/kcmkwin/kwinoptions/windows.cpp b/kcmkwin/kwinoptions/windows.cpp index b44fbe878..83176a709 100644 --- a/kcmkwin/kwinoptions/windows.cpp +++ b/kcmkwin/kwinoptions/windows.cpp @@ -1,1161 +1,1161 @@ /* * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "windows.h" // kwin config keywords #define KWIN_FOCUS "FocusPolicy" #define KWIN_PLACEMENT "Placement" #define KWIN_MOVE "MoveMode" #define KWIN_MINIMIZE_ANIM "AnimateMinimize" #define KWIN_MINIMIZE_ANIM_SPEED "AnimateMinimizeSpeed" #define KWIN_RESIZE_OPAQUE "ResizeMode" #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" #define KWIN_ALTTABMODE "AltTabStyle" #define KWIN_TRAVERSE_ALL "TraverseAll" #define KWIN_SHOW_POPUP "ShowPopup" #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" #define KWM_ELECTRIC_BORDER_DELAY "ElectricBorderDelay" //CT 15mar 98 - magics #define KWM_BRDR_SNAP_ZONE "BorderSnapZone" #define KWM_BRDR_SNAP_ZONE_DEFAULT 10 #define KWM_WNDW_SNAP_ZONE "WindowSnapZone" #define KWM_WNDW_SNAP_ZONE_DEFAULT 10 #define MAX_BRDR_SNAP 100 #define MAX_WNDW_SNAP 100 #define MAX_EDGE_RES 1000 KFocusConfig::~KFocusConfig () { if (standAlone) delete config; } // removed the LCD display over the slider - this is not good GUI design :) RNolden 051701 KFocusConfig::KFocusConfig (bool _standAlone, KConfig *_config, QWidget * parent, const char *) : KCModule(parent, "kcmkwm"), config(_config), standAlone(_standAlone) { QString wtstr; QBoxLayout *lay = new QVBoxLayout (this, 0, KDialog::spacingHint()); //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); // focus policy fcsBox = new QButtonGroup(i18n("Focus"),this); fcsBox->setColumnLayout( 0, Qt::Horizontal ); QBoxLayout *fLay = new QVBoxLayout(fcsBox->layout(), KDialog::spacingHint()); QBoxLayout *cLay = new QHBoxLayout(fLay); QLabel *fLabel = new QLabel(i18n("&Policy:"), fcsBox); cLay->addWidget(fLabel, 0); focusCombo = new QComboBox(false, fcsBox); focusCombo->insertItem(i18n("Click to Focus"), CLICK_TO_FOCUS); focusCombo->insertItem(i18n("Focus Follows Mouse"), FOCUS_FOLLOWS_MOUSE); focusCombo->insertItem(i18n("Focus Under Mouse"), FOCUS_UNDER_MOUSE); focusCombo->insertItem(i18n("Focus Strictly Under Mouse"), FOCUS_STRICTLY_UNDER_MOUSE); cLay->addWidget(focusCombo,1 ,Qt::AlignLeft); fLabel->setBuddy(focusCombo); // FIXME, when more policies have been added to KWin wtstr = i18n("The focus policy is used to determine the active window, i.e." " the window you can work in.
    " "
  • Click to focus: A window becomes active when you click into it." " This is the behavior you might know from other operating systems.
  • " "
  • Focus follows mouse: Moving the mouse pointer actively on to a" " normal window activates it. New windows will receive the focus," " without you having to point the mouse at them explicitly." " Very practical if you are using the mouse a lot.
  • " "
  • Focus under mouse: The window that happens to be under the" " mouse pointer is active. If the mouse points nowhere, the last window" " that was under the mouse has focus." " New windows will not automatically receive the focus.
  • " "
  • Focus strictly under mouse: Only the window under the mouse pointer is" " active. If the mouse points nowhere, nothing has focus." "
" "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." ); QWhatsThis::add( focusCombo, wtstr); QWhatsThis::add(fLabel, wtstr); connect(focusCombo, SIGNAL(activated(int)), this, SLOT(setAutoRaiseEnabled()) ); // autoraise delay autoRaiseOn = new QCheckBox(i18n("Auto &raise"), fcsBox); fLay->addWidget(autoRaiseOn); connect(autoRaiseOn,SIGNAL(toggled(bool)), this, SLOT(autoRaiseOnTog(bool))); autoRaise = new KIntNumInput(500, fcsBox); autoRaise->setLabel(i18n("Dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); autoRaise->setRange(0, 3000, 100, true); autoRaise->setSteps(100,100); 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); // fLay->addColSpacing(0,QMAX(autoRaiseOn->sizeHint().width(), // clickRaiseOn->sizeHint().width()) + 15); QWhatsThis::add( autoRaiseOn, 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."); QWhatsThis::add( autoRaise, wtstr ); QWhatsThis::add( clickRaiseOn, 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.") ); 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); kbdBox->setColumnLayout( 0, Qt::Horizontal ); QGridLayout *kLay = new QGridLayout(kbdBox->layout(), 4, 4, KDialog::spacingHint()); QLabel *altTabLabel = new QLabel( i18n("Walk through windows mode:"), kbdBox); kLay->addWidget(altTabLabel, 1, 0); kdeMode = new QRadioButton(i18n("&KDE"), kbdBox); kLay->addWidget(kdeMode, 1, 1); cdeMode = new QRadioButton(i18n("CD&E"), kbdBox); kLay->addWidget(cdeMode, 1, 2); 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). The two different modes mean:
    " "
  • KDE: a nice widget is shown, displaying the icons of all windows to" " walk through and the title of the currently selected one;" "
  • CDE: the focus is passed to a new window each time Tab is pressed." " No fancy widget.
"); QWhatsThis::add( altTabLabel, wtstr ); QWhatsThis::add( kdeMode, wtstr ); QWhatsThis::add( cdeMode, wtstr ); traverseAll = new QCheckBox( i18n( "&Traverse windows on all desktops" ), kbdBox ); kLay->addMultiCellWidget( traverseAll, 2, 2, 0, 2 ); wtstr = i18n( "Leave this option disabled if you want to limit walking through" " windows to the current desktop." ); QWhatsThis::add( traverseAll, wtstr ); rollOverDesktops = new QCheckBox( i18n("Desktop navi&gation wraps around"), kbdBox ); kLay->addMultiCellWidget(rollOverDesktops, 3, 3, 0, 2); 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." ); QWhatsThis::add( rollOverDesktops, wtstr ); showPopupinfo = new QCheckBox( i18n("Popup desktop name on desktop &switch"), kbdBox ); kLay->addMultiCellWidget(showPopupinfo, 4, 4, 0, 2); wtstr = i18n( "Enable this option if you wish to see the current desktop" " name popup whenever the current desktop is changed." ); QWhatsThis::add( showPopupinfo, wtstr ); lay->addWidget(kbdBox); lay->addStretch(); // Any changes goes to slotChanged() 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())); connect(rollOverDesktops, SIGNAL(clicked()), SLOT(changed())); connect(showPopupinfo, SIGNAL(clicked()), SLOT(changed())); load(); } int KFocusConfig::getFocus() { return focusCombo->currentItem(); } void KFocusConfig::setFocus(int foc) { focusCombo->setCurrentItem(foc); // this will disable/hide the auto raise delay widget if focus==click setAutoRaiseEnabled(); } 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::setAutoRaiseEnabled() { // the auto raise related widgets are: autoRaise if ( focusCombo->currentItem() != CLICK_TO_FOCUS ) { autoRaiseOn->setEnabled(true); autoRaiseOnTog(autoRaiseOn->isChecked()); } else { autoRaiseOn->setEnabled(false); autoRaiseOnTog(false); } } 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 ) { } void KFocusConfig::setAltTabMode(bool a) { kdeMode->setChecked(a); cdeMode->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; config->setGroup( "Windows" ); key = config->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 = 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"); setRollOverDesktops( config->readBoolEntry(KWIN_ROLL_OVER_DESKTOPS, true )); config->setGroup( "PopupInfo" ); setShowPopupinfo( config->readBoolEntry(KWIN_SHOW_POPUP, false )); config->setGroup( "TabBox" ); setTraverseAll( config->readBoolEntry(KWIN_TRAVERSE_ALL, false )); config->setGroup("Desktops"); emit KCModule::changed(false); } void KFocusConfig::save( void ) { int v; config->setGroup( "Windows" ); v = getFocus(); if (v == CLICK_TO_FOCUS) config->writeEntry(KWIN_FOCUS,"ClickToFocus"); else if (v == FOCUS_UNDER_MOUSE) config->writeEntry(KWIN_FOCUS,"FocusUnderMouse"); else if (v == FOCUS_STRICTLY_UNDER_MOUSE) config->writeEntry(KWIN_FOCUS,"FocusStrictlyUnderMouse"); else config->writeEntry(KWIN_FOCUS,"FocusFollowsMouse"); v = getAutoRaiseInterval(); 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 config->writeEntry(KWIN_CLICKRAISE, "off"); if (kdeMode->isChecked()) config->writeEntry(KWIN_ALTTABMODE, "KDE"); else config->writeEntry(KWIN_ALTTABMODE, "CDE"); config->writeEntry( KWIN_ROLL_OVER_DESKTOPS, rollOverDesktops->isChecked()); config->setGroup( "PopupInfo" ); config->writeEntry( KWIN_SHOW_POPUP, showPopupinfo->isChecked()); config->setGroup( "TabBox" ); config->writeEntry( KWIN_TRAVERSE_ALL , traverseAll->isChecked()); config->setGroup("Desktops"); if (standAlone) { config->sync(); if ( !kapp->dcopClient()->isAttached() ) kapp->dcopClient()->attach(); kapp->dcopClient()->send("kwin*", "", "reconfigure()", ""); } emit KCModule::changed(false); } void KFocusConfig::defaults() { setAutoRaiseInterval(0); setDelayFocusInterval(0); setFocus(CLICK_TO_FOCUS); setAutoRaise(false); setDelayFocus(false); setClickRaise(true); setAltTabMode(true); setTraverseAll( false ); setRollOverDesktops(true); setShowPopupinfo(false); emit KCModule::changed(true); } KAdvancedConfig::~KAdvancedConfig () { if (standAlone) delete config; } KAdvancedConfig::KAdvancedConfig (bool _standAlone, KConfig *_config, QWidget *parent, const char *) : KCModule(parent, "kcmkwm"), config(_config), standAlone(_standAlone) { QString wtstr; QBoxLayout *lay = new QVBoxLayout (this, 0, KDialog::spacingHint()); //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 QVButtonGroup(i18n("Shading"), this); animateShade = new QCheckBox(i18n("Anima&te"), shBox); QWhatsThis::add(animateShade, i18n("Animate the action of reducing the window to its titlebar (shading)" " as well as the expansion of a shaded window") ); shadeHoverOn = new QCheckBox(i18n("&Enable hover"), shBox); connect(shadeHoverOn, SIGNAL(toggled(bool)), this, SLOT(shadeHoverChanged(bool))); shadeHover = new KIntNumInput(500, shBox); shadeHover->setLabel(i18n("Dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); shadeHover->setRange(0, 3000, 100, true); shadeHover->setSteps(100, 100); shadeHover->setSuffix(i18n(" msec")); QWhatsThis::add(shadeHoverOn, 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."); QWhatsThis::add(shadeHover, wtstr); lay->addWidget(shBox); // Any changes goes to slotChanged() connect(animateShade, SIGNAL(toggled(bool)), SLOT(changed())); connect(shadeHoverOn, SIGNAL(toggled(bool)), SLOT(changed())); connect(shadeHover, SIGNAL(valueChanged(int)), SLOT(changed())); electricBox = new QVButtonGroup(i18n("Active Desktop Borders"), this); electricBox->setMargin(15); QWhatsThis::add( electricBox, 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); active_move = new QRadioButton(i18n("Only &when moving windows"), electricBox); active_always = new QRadioButton(i18n("A&lways enabled"), electricBox); delays = new KIntNumInput(10, electricBox); delays->setRange(0, MAX_EDGE_RES, 50, true); delays->setSuffix(i18n(" msec")); delays->setLabel(i18n("Desktop &switch delay:")); QWhatsThis::add( delays, 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.") ); 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); QHBoxLayout* focusStealingLayout = new QHBoxLayout( lay,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 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.)" "
    " - "
  • None: The standard old behavior - prevention is turned off " + "
  • None: Prevention is turned off " "and new windows always become activated.
  • " "
  • Low: Prevention is enabled; when some window does not 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.
  • " + "
  • Normal: Prevention is enabled.
  • " "
  • 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 not 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->addStretch(); load(); } void KAdvancedConfig::setShadeHover(bool on) { shadeHoverOn->setChecked(on); shadeHover->setEnabled(on); } void KAdvancedConfig::setShadeHoverInterval(int k) { shadeHover->setValue(k); } int KAdvancedConfig::getShadeHoverInterval() { return shadeHover->value(); } void KAdvancedConfig::shadeHoverChanged(bool a) { shadeHover->setEnabled(a); } 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" ); setAnimateShade(config->readBoolEntry(KWIN_ANIMSHADE, true)); setShadeHover(config->readBoolEntry(KWIN_SHADEHOVER, false)); setShadeHoverInterval(config->readNumEntry(KWIN_SHADEHOVER_INTERVAL, 250)); setElectricBorders(config->readNumEntry(KWM_ELECTRIC_BORDER, false)); setElectricBorderDelay(config->readNumEntry(KWM_ELECTRIC_BORDER_DELAY, 150)); // setFocusStealing( config->readNumEntry(KWIN_FOCUS_STEALING, 2 )); // TODO default to low for now setFocusStealing( config->readNumEntry(KWIN_FOCUS_STEALING, 1 )); emit KCModule::changed(false); } void KAdvancedConfig::save( void ) { int v; config->setGroup( "Windows" ); config->writeEntry(KWIN_ANIMSHADE, animateShade->isChecked()); if (shadeHoverOn->isChecked()) config->writeEntry(KWIN_SHADEHOVER, "on"); else config->writeEntry(KWIN_SHADEHOVER, "off"); v = getShadeHoverInterval(); if (v<0) v = 0; config->writeEntry(KWIN_SHADEHOVER_INTERVAL, v); config->writeEntry(KWM_ELECTRIC_BORDER, getElectricBorders()); config->writeEntry(KWM_ELECTRIC_BORDER_DELAY,getElectricBorderDelay()); config->writeEntry(KWIN_FOCUS_STEALING, focusStealing->currentItem()); if (standAlone) { config->sync(); if ( !kapp->dcopClient()->isAttached() ) kapp->dcopClient()->attach(); kapp->dcopClient()->send("kwin*", "", "reconfigure()", ""); } emit KCModule::changed(false); } void KAdvancedConfig::defaults() { setAnimateShade(true); setShadeHover(false); setShadeHoverInterval(250); setElectricBorders(0); setElectricBorderDelay(150); // setFocusStealing(2); // TODO default to low for now setFocusStealing(1); emit KCModule::changed(true); } void KAdvancedConfig::setEBorders() { delays->setEnabled(!active_disable->isChecked()); } int KAdvancedConfig::getElectricBorders() { if (active_move->isChecked()) return 1; if (active_always->isChecked()) return 2; return 0; } int KAdvancedConfig::getElectricBorderDelay() { return delays->value(); } void KAdvancedConfig::setElectricBorders(int i){ switch(i) { case 1: active_move->setChecked(true); break; case 2: active_always->setChecked(true); break; default: active_disable->setChecked(true); break; } setEBorders(); } void KAdvancedConfig::setElectricBorderDelay(int delay) { delays->setValue(delay); } KMovingConfig::~KMovingConfig () { if (standAlone) delete config; } KMovingConfig::KMovingConfig (bool _standAlone, KConfig *_config, QWidget *parent, const char *) : KCModule(parent, "kcmkwm"), config(_config), standAlone(_standAlone) { QString wtstr; QBoxLayout *lay = new QVBoxLayout (this, 0, KDialog::spacingHint()); windowsBox = new QButtonGroup(i18n("Windows"), this); windowsBox->setColumnLayout( 0, Qt::Horizontal ); QBoxLayout *wLay = new QVBoxLayout (windowsBox->layout(), KDialog::spacingHint()); QBoxLayout *bLay = new QVBoxLayout; wLay->addLayout(bLay); opaque = new QCheckBox(i18n("Di&splay content in moving windows"), windowsBox); bLay->addWidget(opaque); QWhatsThis::add( opaque, i18n("Enable this option if you want a window's content to be fully shown" " while moving it, instead of just showing a window 'skeleton'. The result may not be satisfying" " on slow machines without graphic acceleration.") ); resizeOpaqueOn = new QCheckBox(i18n("Display content in &resizing windows"), windowsBox); bLay->addWidget(resizeOpaqueOn); QWhatsThis::add( resizeOpaqueOn, i18n("Enable this option if you want a window's content to be shown" " while resizing it, instead of just showing a window 'skeleton'. The result may not be satisfying" " on slow machines.") ); geometryTipOn = new QCheckBox(i18n("Display window &geometry when moving or resizing"), windowsBox); bLay->addWidget(geometryTipOn); QWhatsThis::add(geometryTipOn, i18n("Enable this option if you want a window's geometry to be displayed" " while it is being moved or resized. The window position relative" " to the top-left corner of the screen is displayed together with" " its size.")); QGridLayout *rLay = new QGridLayout(2,3); bLay->addLayout(rLay); rLay->setColStretch(0,0); rLay->setColStretch(1,1); minimizeAnimOn = new QCheckBox(i18n("Animate minimi&ze and restore"), windowsBox); QWhatsThis::add( minimizeAnimOn, i18n("Enable this option if you want an animation shown when" " windows are minimized or restored." ) ); rLay->addWidget(minimizeAnimOn,0,0); minimizeAnimSlider = new QSlider(0,10,10,0,QSlider::Horizontal, windowsBox); minimizeAnimSlider->setSteps(1, 1); // QSlider::Below clashes with a X11/X.h #define #undef Below minimizeAnimSlider->setTickmarks(QSlider::Below); rLay->addMultiCellWidget(minimizeAnimSlider,0,0,1,2); connect(minimizeAnimOn, SIGNAL(toggled(bool)), this, SLOT(setMinimizeAnim(bool))); connect(minimizeAnimSlider, SIGNAL(valueChanged(int)), this, SLOT(setMinimizeAnimSpeed(int))); minimizeAnimSlowLabel= new QLabel(i18n("Slow"),windowsBox); minimizeAnimSlowLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft); rLay->addWidget(minimizeAnimSlowLabel,1,1); minimizeAnimFastLabel= new QLabel(i18n("Fast"),windowsBox); minimizeAnimFastLabel->setAlignment(Qt::AlignTop|Qt::AlignRight); rLay->addWidget(minimizeAnimFastLabel,1,2); wtstr = i18n("Here you can set the speed of the animation shown when windows are" " minimized and restored. "); QWhatsThis::add( minimizeAnimSlider, wtstr ); QWhatsThis::add( minimizeAnimSlowLabel, wtstr ); QWhatsThis::add( minimizeAnimFastLabel, wtstr ); moveResizeMaximized = new QCheckBox( i18n("Allow moving and resizing o&f maximized windows"), windowsBox); bLay->addWidget(moveResizeMaximized); QWhatsThis::add(moveResizeMaximized, i18n("When enabled, this feature activates the border of maximized windows" " and allows you to move or resize them," " just like for normal windows")); QBoxLayout *vLay = new QHBoxLayout(bLay); QLabel *plcLabel = new QLabel(i18n("&Placement:"),windowsBox); placementCombo = new QComboBox(false, windowsBox); placementCombo->insertItem(i18n("Smart"), SMART_PLACEMENT); placementCombo->insertItem(i18n("Cascade"), CASCADE_PLACEMENT); placementCombo->insertItem(i18n("Random"), RANDOM_PLACEMENT); placementCombo->insertItem(i18n("Centered"), CENTERED_PLACEMENT); placementCombo->insertItem(i18n("Zero-Cornered"), ZEROCORNERED_PLACEMENT); // CT: disabling is needed as long as functionality misses in kwin //placementCombo->insertItem(i18n("Interactive"), INTERACTIVE_PLACEMENT); //placementCombo->insertItem(i18n("Manual"), MANUAL_PLACEMENT); placementCombo->setCurrentItem(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. For now, there are three different policies:" "
  • Smart will try to achieve a minimum overlap of windows
  • " "
  • Cascade will cascade the windows
  • " "
  • Random will use a random position
") ; QWhatsThis::add( plcLabel, wtstr); QWhatsThis::add( placementCombo, wtstr); plcLabel->setBuddy(placementCombo); vLay->addWidget(plcLabel, 0); vLay->addWidget(placementCombo, 1, Qt::AlignLeft); bLay->addSpacing(10); lay->addWidget(windowsBox); //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); //CT 15mar98 - add EdgeResistance, BorderAttractor, WindowsAttractor config MagicBox = new QVButtonGroup(i18n("Snap Zones"), this); MagicBox->setMargin(15); BrdrSnap = new KIntNumInput(10, MagicBox); BrdrSnap->setSpecialValueText( i18n("none") ); BrdrSnap->setRange( 0, MAX_BRDR_SNAP); BrdrSnap->setLabel(i18n("&Border snap zone:")); BrdrSnap->setSuffix(i18n(" pixels")); BrdrSnap->setSteps(1,10); QWhatsThis::add( BrdrSnap, i18n("Here you can set the snap zone for screen borders, i.e." " the 'strength' of the magnetic field which will make windows snap to the border when" " moved near it.") ); WndwSnap = new KIntNumInput(10, MagicBox); WndwSnap->setSpecialValueText( i18n("none") ); WndwSnap->setRange( 0, MAX_WNDW_SNAP); WndwSnap->setLabel(i18n("&Window snap zone:")); WndwSnap->setSuffix( i18n(" pixels")); BrdrSnap->setSteps(1,10); QWhatsThis::add( WndwSnap, i18n("Here you can set the snap zone for windows, i.e." " the 'strength' of the magnetic field which will make windows snap to each other when" " they're moved near another window.") ); OverlapSnap=new QCheckBox(i18n("Snap windows onl&y when overlapping"),MagicBox); QWhatsThis::add( OverlapSnap, i18n("Here you can set that windows will be only" " snapped if you try to overlap them, i.e. they will not be snapped if the windows" " comes only near another window or border.") ); lay->addWidget(MagicBox); lay->addStretch(); load(); // Any changes goes to slotChanged() connect( opaque, SIGNAL(clicked()), SLOT(changed())); connect( resizeOpaqueOn, SIGNAL(clicked()), SLOT(changed())); connect( geometryTipOn, SIGNAL(clicked()), SLOT(changed())); connect( minimizeAnimOn, SIGNAL(clicked() ), SLOT(changed())); connect( minimizeAnimSlider, SIGNAL(valueChanged(int)), SLOT(changed())); connect( moveResizeMaximized, SIGNAL(toggled(bool)), SLOT(changed())); connect( placementCombo, SIGNAL(activated(int)), SLOT(changed())); connect( BrdrSnap, SIGNAL(valueChanged(int)), SLOT(changed())); connect( WndwSnap, SIGNAL(valueChanged(int)), SLOT(changed())); connect( OverlapSnap, SIGNAL(clicked()), SLOT(changed())); } int KMovingConfig::getMove() { return (opaque->isChecked())? OPAQUE : TRANSPARENT; } void KMovingConfig::setMove(int trans) { opaque->setChecked(trans == OPAQUE); } void KMovingConfig::setGeometryTip(bool showGeometryTip) { geometryTipOn->setChecked(showGeometryTip); } bool KMovingConfig::getGeometryTip() { return geometryTipOn->isChecked(); } // placement policy --- CT 31jan98 --- int KMovingConfig::getPlacement() { return placementCombo->currentItem(); } void KMovingConfig::setPlacement(int plac) { placementCombo->setCurrentItem(plac); } bool KMovingConfig::getMinimizeAnim() { return minimizeAnimOn->isChecked(); } int KMovingConfig::getMinimizeAnimSpeed() { return minimizeAnimSlider->value(); } void KMovingConfig::setMinimizeAnim(bool anim) { minimizeAnimOn->setChecked( anim ); minimizeAnimSlider->setEnabled( anim ); minimizeAnimSlowLabel->setEnabled( anim ); minimizeAnimFastLabel->setEnabled( anim ); } void KMovingConfig::setMinimizeAnimSpeed(int speed) { minimizeAnimSlider->setValue(speed); } int KMovingConfig::getResizeOpaque() { return (resizeOpaqueOn->isChecked())? RESIZE_OPAQUE : RESIZE_TRANSPARENT; } void KMovingConfig::setResizeOpaque(int opaque) { resizeOpaqueOn->setChecked(opaque == RESIZE_OPAQUE); } void KMovingConfig::setMoveResizeMaximized(bool a) { moveResizeMaximized->setChecked(a); } void KMovingConfig::load( void ) { QString key; config->setGroup( "Windows" ); key = config->readEntry(KWIN_MOVE, "Opaque"); if( key == "Transparent") setMove(TRANSPARENT); else if( key == "Opaque") setMove(OPAQUE); //CT 17Jun1998 - variable animation speed from 0 (none!!) to 10 (max) bool anim = config->readBoolEntry(KWIN_MINIMIZE_ANIM, true ); int animSpeed = config->readNumEntry(KWIN_MINIMIZE_ANIM_SPEED, 5); if( animSpeed < 1 ) animSpeed = 0; if( animSpeed > 10 ) animSpeed = 10; setMinimizeAnim( anim ); setMinimizeAnimSpeed( animSpeed ); // DF: please keep the default consistent with kwin (options.cpp line 145) key = config->readEntry(KWIN_RESIZE_OPAQUE, "Opaque"); if( key == "Opaque") setResizeOpaque(RESIZE_OPAQUE); else if ( key == "Transparent") setResizeOpaque(RESIZE_TRANSPARENT); //KS 10Jan2003 - Geometry Tip during window move/resize bool showGeomTip = config->readBoolEntry(KWIN_GEOMETRY, false); setGeometryTip( showGeomTip ); // placement policy --- CT 19jan98 --- key = config->readEntry(KWIN_PLACEMENT); //CT 13mar98 interactive placement // if( key.left(11) == "interactive") { // setPlacement(INTERACTIVE_PLACEMENT); // int comma_pos = key.find(','); // if (comma_pos < 0) // interactiveTrigger->setValue(0); // else // interactiveTrigger->setValue (key.right(key.length() // - comma_pos).toUInt(0)); // iTLabel->setEnabled(true); // interactiveTrigger->show(); // } // else { // interactiveTrigger->setValue(0); // iTLabel->setEnabled(false); // interactiveTrigger->hide(); if( key == "Random") setPlacement(RANDOM_PLACEMENT); else if( key == "Cascade") setPlacement(CASCADE_PLACEMENT); //CT 31jan98 //CT 31mar98 manual placement else if( key == "manual") setPlacement(MANUAL_PLACEMENT); else if( key == "Centered") setPlacement(CENTERED_PLACEMENT); else if( key == "ZeroCornered") setPlacement(ZEROCORNERED_PLACEMENT); else setPlacement(SMART_PLACEMENT); // } setMoveResizeMaximized(config->readBoolEntry(KWIN_MOVE_RESIZE_MAXIMIZED, true)); int v; v = config->readNumEntry(KWM_BRDR_SNAP_ZONE, KWM_BRDR_SNAP_ZONE_DEFAULT); if (v > MAX_BRDR_SNAP) setBorderSnapZone(MAX_BRDR_SNAP); else if (v < 0) setBorderSnapZone (0); else setBorderSnapZone(v); v = config->readNumEntry(KWM_WNDW_SNAP_ZONE, KWM_WNDW_SNAP_ZONE_DEFAULT); if (v > MAX_WNDW_SNAP) setWindowSnapZone(MAX_WNDW_SNAP); else if (v < 0) setWindowSnapZone (0); else setWindowSnapZone(v); OverlapSnap->setChecked(config->readBoolEntry("SnapOnlyWhenOverlapping",false)); emit KCModule::changed(false); } void KMovingConfig::save( void ) { int v; config->setGroup( "Windows" ); v = getMove(); if (v == TRANSPARENT) config->writeEntry(KWIN_MOVE,"Transparent"); else config->writeEntry(KWIN_MOVE,"Opaque"); config->writeEntry(KWIN_GEOMETRY, getGeometryTip()); // placement policy --- CT 31jan98 --- v =getPlacement(); if (v == RANDOM_PLACEMENT) config->writeEntry(KWIN_PLACEMENT, "Random"); else if (v == CASCADE_PLACEMENT) config->writeEntry(KWIN_PLACEMENT, "Cascade"); else if (v == CENTERED_PLACEMENT) config->writeEntry(KWIN_PLACEMENT, "Centered"); else if (v == ZEROCORNERED_PLACEMENT) config->writeEntry(KWIN_PLACEMENT, "ZeroCornered"); //CT 13mar98 manual and interactive placement // else if (v == MANUAL_PLACEMENT) // config->writeEntry(KWIN_PLACEMENT, "Manual"); // else if (v == INTERACTIVE_PLACEMENT) { // QString tmpstr = QString("Interactive,%1").arg(interactiveTrigger->value()); // config->writeEntry(KWIN_PLACEMENT, tmpstr); // } else config->writeEntry(KWIN_PLACEMENT, "Smart"); config->writeEntry(KWIN_MINIMIZE_ANIM, getMinimizeAnim()); config->writeEntry(KWIN_MINIMIZE_ANIM_SPEED, getMinimizeAnimSpeed()); v = getResizeOpaque(); if (v == RESIZE_OPAQUE) config->writeEntry(KWIN_RESIZE_OPAQUE, "Opaque"); else config->writeEntry(KWIN_RESIZE_OPAQUE, "Transparent"); config->writeEntry(KWIN_MOVE_RESIZE_MAXIMIZED, moveResizeMaximized->isChecked()); config->writeEntry(KWM_BRDR_SNAP_ZONE,getBorderSnapZone()); config->writeEntry(KWM_WNDW_SNAP_ZONE,getWindowSnapZone()); config->writeEntry("SnapOnlyWhenOverlapping",OverlapSnap->isChecked()); if (standAlone) { config->sync(); if ( !kapp->dcopClient()->isAttached() ) kapp->dcopClient()->attach(); kapp->dcopClient()->send("kwin*", "", "reconfigure()", ""); } emit KCModule::changed(false); } void KMovingConfig::defaults() { setMove(OPAQUE); setResizeOpaque(RESIZE_TRANSPARENT); setGeometryTip(false); setPlacement(SMART_PLACEMENT); setMoveResizeMaximized(true); //copied from kcontrol/konq/kwindesktop, aleXXX setWindowSnapZone(KWM_WNDW_SNAP_ZONE_DEFAULT); setBorderSnapZone(KWM_BRDR_SNAP_ZONE_DEFAULT); OverlapSnap->setChecked(false); setMinimizeAnim( true ); setMinimizeAnimSpeed( 5 ); emit KCModule::changed(true); } int KMovingConfig::getBorderSnapZone() { return BrdrSnap->value(); } void KMovingConfig::setBorderSnapZone(int pxls) { BrdrSnap->setValue(pxls); } int KMovingConfig::getWindowSnapZone() { return WndwSnap->value(); } void KMovingConfig::setWindowSnapZone(int pxls) { WndwSnap->setValue(pxls); } #include "windows.moc" diff --git a/manage.cpp b/manage.cpp index 209a9a585..0ec81e46b 100644 --- a/manage.cpp +++ b/manage.cpp @@ -1,546 +1,549 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ /* This file contains things relevant to handling incoming events. */ #include "client.h" #include #include #include #include "notifications.h" #include "rules.h" extern Time qt_x_time; extern Atom qt_window_role; namespace KWinInternal { /*! Manages the clients. This means handling the very first maprequest: reparenting, initial geometry, initial state, placement, etc. Returns false if KWin is not going to manage this window. */ bool Client::manage( Window w, bool isMapped ) { XWindowAttributes attr; if( !XGetWindowAttributes(qt_xdisplay(), w, &attr)) return false; grabXServer(); // from this place on, manage() mustn't return false block_geometry = 1; embedClient( w, attr ); // SELI order all these things in some sane manner bool init_minimize = false; XWMHints * hints = XGetWMHints(qt_xdisplay(), w ); if (hints && (hints->flags & StateHint) && hints->initial_state == IconicState) init_minimize = true; if (hints) XFree(hints); if( isMapped ) init_minimize = false; // if it's already mapped, ignore hint unsigned long properties[ 2 ]; properties[ WinInfo::PROTOCOLS ] = NET::WMDesktop | NET::WMState | NET::WMWindowType | NET::WMStrut | NET::WMName | NET::WMIconGeometry | NET::WMIcon | NET::WMPid | NET::WMIconName | 0; properties[ WinInfo::PROTOCOLS2 ] = NET::WM2UserTime | NET::WM2StartupId | NET::WM2ExtendedStrut | 0; info = new WinInfo( this, qt_xdisplay(), client, qt_xrootwin(), properties, 2 ); cmap = attr.colormap; bool mresize, mmove, mminimize, mmaximize, mclose; if( Motif::funcFlags( client, mresize, mmove, mminimize, mmaximize, mclose )) { if( !hasNETSupport()) // NETWM apps should set type and size constraints { motif_may_resize = mresize; // this should be set using minsize==maxsize, but oh well motif_may_move = mmove; } // mminimize; - ignore, bogus - e.g. shading or sending to another desktop is "minimizing" too // mmaximize; - ignore, bogus - maximizing is basically just resizing motif_may_close = mclose; // motif apps like to crash when they set this hint and WM closes them anyway } XClassHint classHint; if ( XGetClassHint( qt_xdisplay(), client, &classHint ) ) { // Qt3.2 and older had this all lowercase, Qt3.3 capitalized resource class // force lowercase, so that workarounds listing resource classes still work resource_name = QCString( classHint.res_name ).lower(); resource_class = QCString( classHint.res_class ).lower(); XFree( classHint.res_name ); XFree( classHint.res_class ); } ignore_focus_stealing = options->checkIgnoreFocusStealing( this ); // TODO change to rules window_role = getStringProperty( w, qt_window_role ); // first only read the caption text, so that setupWindowRules() can use it for matching, // and only then really set the caption using setCaption(), which checks for duplicates etc. // and also relies on rules already existing cap_normal = readName(); setupWindowRules( false ); setCaption( cap_normal, true ); detectNoBorder(); fetchIconicName(); getWMHints(); // needs to be done before readTransient() because of reading the group getWmClientLeader(); // needs to be done before readTransient() because of same app comparing modal = ( info->state() & NET::Modal ) != 0; // needs to be valid before handling groups readTransient(); getIcons(); getWindowProtocols(); getWmNormalHints(); // get xSizeHint // TODO try to obey all state information from info->state() original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar) != 0; skip_pager = ( info->state() & NET::SkipPager) != 0; KStartupInfoId asn_id; KStartupInfoData asn_data; bool asn_valid = workspace()->checkStartupNotification( window(), asn_id, asn_data ); workspace()->updateClientLayer( this ); SessionInfo* session = workspace()->takeSessionInfo( this ); if ( session ) { if ( session->minimized ) init_minimize = true; if( session->userNoBorder ) setUserNoBorder( true ); } init_minimize = rules()->checkMinimize( init_minimize, !isMapped ); if( rules()->checkNoBorder( false, !isMapped )) setUserNoBorder( true ); // initial desktop placement if ( info->desktop() ) desk = info->desktop(); // window had the initial desktop property! else if( asn_valid && asn_data.desktop() != 0 ) desk = asn_data.desktop(); if ( session ) { desk = session->desktop; if( session->onAllDesktops ) desk = NET::OnAllDesktops; } else if ( desk == 0 ) { // if this window is transient, ensure that it is opened on the // same window as its parent. this is necessary when an application // starts up on a different desktop than is currently displayed if( isTransient()) { ClientList mainclients = mainClients(); bool on_current = false; Client* maincl = NULL; // this is slightly duplicated from Placement::placeOnMainWindow() for( ClientList::ConstIterator it = mainclients.begin(); it != mainclients.end(); ++it ) { if( (*it)->isSpecialWindow() && !(*it)->isOverride()) continue; // don't consider toolbars etc when placing maincl = *it; if( (*it)->isOnCurrentDesktop()) on_current = true; } if( on_current ) desk = workspace()->currentDesktop(); else if( maincl != NULL ) desk = maincl->desktop(); } } if ( desk == 0 ) // assume window wants to be visible on the current desktop desk = workspace()->currentDesktop(); if( desk != NET::OnAllDesktops ) // do range check desk = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desk )); desk = rules()->checkDesktop( desk, !isMapped ); info->setDesktop( desk ); workspace()->updateOnAllDesktopsOfTransients( this ); // SELI // onAllDesktopsChange(); decoration doesn't exist here yet QRect geom( attr.x, attr.y, attr.width, attr.height ); bool placementDone = FALSE; if ( session ) geom = session->geometry; QRect area; if( isMapped || session ) area = workspace()->clientArea( WorkArea, geom.center(), desktop()); else if( options->xineramaPlacementEnabled ) area = workspace()->clientArea( PlacementArea, QCursor::pos(), desktop()); else area = workspace()->clientArea( PlacementArea, geom.center(), desktop()); // if it's noborder window, and has size of one screen or the whole desktop geometry, it's fullscreen hack if( ( geom.size() == workspace()->clientArea( FullArea, geom.center(), desktop()).size() || geom.size() == workspace()->clientArea( ScreenArea, geom.center(), desktop()).size()) && noBorder() && !isUserNoBorder() && isFullScreenable( true )) { fullscreen_mode = FullScreenHack; geom = workspace()->clientArea( FullScreenArea, geom.center(), desktop()); placementDone = true; } if ( isDesktop() ) { // desktops are treated slightly special geom = workspace()->clientArea( FullArea, geom.center(), desktop()); placementDone = true; } if ( isMapped || session || placementDone || ( isTransient() && !isUtility() && !isDialog() && !isSplash())) { // TODO placementDone = TRUE; } else if( isTransient() && !hasNETSupport()) placementDone = true; else if( isDialog() && hasNETSupport()) // see Placement::placeDialog() ; // force using placement policy else if( isSplash()) ; // force using placement policy else { bool ignorePPosition = ( options->ignorePositionClasses.contains(QString::fromLatin1(resourceClass()))); if ( ( (xSizeHint.flags & PPosition) && !ignorePPosition ) || (xSizeHint.flags & USPosition) ) { placementDone = TRUE; // disobey xinerama placement option for now (#70943) area = workspace()->clientArea( PlacementArea, geom.center(), desktop()); } if ( (xSizeHint.flags & USSize) || (xSizeHint.flags & PSize) ) { // keep in mind that we now actually have a size :-) } } if (xSizeHint.flags & PMaxSize) geom.setSize( geom.size().boundedTo( rules()->checkMaxSize( QSize(xSizeHint.max_width, xSizeHint.max_height ) ) ) ); if (xSizeHint.flags & PMinSize) geom.setSize( geom.size().expandedTo( rules()->checkMinSize( QSize(xSizeHint.min_width, xSizeHint.min_height ) ) ) ); if( isMovable()) { if( geom.x() > area.right() || geom.y() > area.bottom()) placementDone = FALSE; // weird, do not trust. } if ( placementDone ) move( geom.x(), geom.y() ); // before gravitating updateDecoration( false ); // also gravitates // TODO is CentralGravity right here, when resizing is done after gravitating? plainResize( rules()->checkSize( sizeForClientSize( geom.size()), !isMapped )); QPoint forced_pos = rules()->checkPosition( invalidPoint, !isMapped ); if( forced_pos != invalidPoint ) { move( forced_pos ); placementDone = true; } if( !placementDone ) { // placement needs to be after setting size workspace()->place( this, area ); placementDone = TRUE; } if( !isMapped && !session // trust position from session or if already mapped && ( !isSpecialWindow() || isToolbar()) && isMovable()) keepInArea( area ); XShapeSelectInput( qt_xdisplay(), window(), ShapeNotifyMask ); if ( (is_shape = Shape::hasShape( window())) ) { updateShape(); } //CT extra check for stupid jdk 1.3.1. But should make sense in general // if client has initial state set to Iconic and is transient with a parent // window that is not Iconic, set init_state to Normal if( init_minimize && isTransient()) { ClientList mainclients = mainClients(); for( ClientList::ConstIterator it = mainclients.begin(); it != mainclients.end(); ++it ) if( (*it)->isShown( true )) init_minimize = false; // SELI even e.g. for NET::Utility? } if( init_minimize ) minimize( true ); // no animation // SELI this seems to be mainly for kstart and ksystraycmd // probably should be replaced by something better bool doNotShow = false; if ( workspace()->isNotManaged( caption() ) ) doNotShow = TRUE; // other settings from the previous session if ( session ) { // session restored windows are not considered to be new windows WRT rules, // i.e. obey only forcing rules setKeepAbove( session->keepAbove ); setKeepBelow( session->keepBelow ); setSkipTaskbar( session->skipTaskbar, true ); setSkipPager( session->skipPager ); setShade( session->shaded ? ShadeNormal : ShadeNone ); if( session->maximized != MaximizeRestore ) { maximize( (MaximizeMode) session->maximized ); geom_restore = session->restore; } if( session->fullscreen == FullScreenHack ) ; // nothing, this should be already set again above else if( session->fullscreen != FullScreenNone ) { setFullScreen( true, false ); geom_fs_restore = session->fsrestore; } } else { geom_restore = geometry(); // remember restore geometry if ( isMaximizable() && ( width() >= area.width() || height() >= area.height() ) ) { // window is too large for the screen, maximize in the // directions necessary if ( width() >= area.width() && height() >= area.height() ) { maximize( Client::MaximizeFull ); geom_restore = QRect(); // use placement when unmaximizing } else if ( width() >= area.width() ) { maximize( Client::MaximizeHorizontal ); geom_restore = QRect(); // use placement when unmaximizing geom_restore.setY( y()); // but only for horizontal direction geom_restore.setHeight( height()); } else if ( height() >= area.height() ) { maximize( Client::MaximizeVertical ); geom_restore = QRect(); // use placement when unmaximizing geom_restore.setX( x()); // but only for vertical direction geom_restore.setWidth( width()); } } // window may want to be maximized // done after checking that the window isn't larger than the workarea, so that // the restore geometry from the checks above takes precedence, and window // isn't restored larger than the workarea MaximizeMode maxmode = static_cast< MaximizeMode > ((( info->state() & NET::MaxVert ) ? MaximizeVertical : 0 ) | (( info->state() & NET::MaxHoriz ) ? MaximizeHorizontal : 0 )); MaximizeMode forced_maxmode = rules()->checkMaximize( maxmode, !isMapped ); // either hints were set to maximize, or is forced to maximize, // or is forced to non-maximize and hints were set to maximize if( forced_maxmode != MaximizeRestore || maxmode != MaximizeRestore ) maximize( forced_maxmode ); // read other initial states setShade( rules()->checkShade( info->state() & NET::Shaded ? ShadeNormal : ShadeNone, !isMapped )); setKeepAbove( rules()->checkKeepAbove( info->state() & NET::KeepAbove, !isMapped )); setKeepBelow( rules()->checkKeepBelow( info->state() & NET::KeepBelow, !isMapped )); setSkipTaskbar( rules()->checkSkipTaskbar( info->state() & NET::SkipTaskbar, !isMapped ), true ); setSkipPager( rules()->checkSkipPager( info->state() & NET::SkipPager, !isMapped )); if( info->state() & NET::DemandsAttention ) demandAttention(); if( info->state() & NET::Modal ) setModal( true ); if( fullscreen_mode != FullScreenHack && isFullScreenable()) setFullScreen( rules()->checkFullScreen( info->state() & NET::FullScreen, !isMapped ), false ); } updateAllowedActions( true ); // TODO this should avoid flicker, because real restacking is done // only after manage() finishes, but the window is shown sooner // - keep it? XLowerWindow( qt_xdisplay(), frameId()); user_time = readUserTimeMapTimestamp( asn_valid ? &asn_id : NULL, asn_valid ? &asn_data : NULL, session ); if( isTopMenu()) // they're shown in Workspace::addClient() if their mainwindow hideClient( true ); // is the active one if ( isShown( true ) && !doNotShow ) { if( isDialog()) Notify::raise( Notify::TransNew ); if( isNormalWindow()) Notify::raise( Notify::New ); + bool allow = workspace()->allowClientActivation( this, userTime(), false, session && session->active ); + // if session saving, force showing new windows (i.e. "save file?" dialogs etc.) - if( workspace()->sessionSaving() && !isOnCurrentDesktop()) + // also force if activation is allowed + if( !isOnCurrentDesktop() && !isMapped && ( allow || workspace()->sessionSaving())) workspace()->setCurrentDesktop( desktop()); if( isOnCurrentDesktop()) { setMappingState( NormalState ); if( isMapped ) { workspace()->raiseClient( this ); rawShow(); } else { - if( workspace()->allowClientActivation( this, userTime(), false, session && session->active )) + if( allow ) { workspace()->raiseClient( this ); rawShow(); if( !isSpecialWindow() || isOverride()) if ( options->focusPolicyIsReasonable() && wantsTabFocus() ) workspace()->requestFocus( this ); } else { workspace()->restackClientUnderActive( this ); rawShow(); if( !session && ( !isSpecialWindow() || isOverride())) demandAttention(); } } } else { virtualDesktopChange(); workspace()->raiseClient( this ); if( !session && !isMapped ) demandAttention(); } } else if( !doNotShow ) // !isShown() { rawHide(); setMappingState( IconicState ); } else // doNotShow { // SELI HACK !!! hideClient( true ); setMappingState( IconicState ); } assert( mappingState() != WithdrawnState ); if( user_time == CurrentTime || user_time == -1U ) // no known user time, set something old { user_time = qt_x_time - 1000000; if( user_time == CurrentTime || user_time == -1U ) // let's be paranoid user_time = qt_x_time - 1000000 + 10; } updateWorkareaDiffs(); // sendSyntheticConfigureNotify(); done when setting mapping state delete session; ungrabXServer(); if( client_rules->discardTemporary( true )) setupWindowRules( true ); return true; } // called only from manage() void Client::embedClient( Window w, const XWindowAttributes &attr ) { assert( client == None ); assert( frame == None ); assert( wrapper == None ); client = w; // we don't want the window to be destroyed when we are destroyed XAddToSaveSet( qt_xdisplay(), client ); XSelectInput( qt_xdisplay(), client, NoEventMask ); XUnmapWindow( qt_xdisplay(), client ); XWindowChanges wc; // set the border width to 0 wc.border_width = 0; // TODO possibly save this, and also use it for initial configuring of the window XConfigureWindow( qt_xdisplay(), client, CWBorderWidth, &wc ); XSetWindowAttributes swa; swa.colormap = attr.colormap; swa.background_pixmap = None; swa.border_pixel = 0; frame = XCreateWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0, attr.depth, InputOutput, attr.visual, CWColormap | CWBackPixmap | CWBorderPixel, &swa ); wrapper = XCreateWindow( qt_xdisplay(), frame, 0, 0, 1, 1, 0, attr.depth, InputOutput, attr.visual, CWColormap | CWBackPixmap | CWBorderPixel, &swa ); XDefineCursor( qt_xdisplay(), frame, arrowCursor.handle()); // some apps are stupid and don't define their own cursor - set the arrow one for them XDefineCursor( qt_xdisplay(), wrapper, arrowCursor.handle()); XReparentWindow( qt_xdisplay(), client, wrapper, 0, 0 ); XSelectInput( qt_xdisplay(), frame, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | KeymapStateMask | ButtonMotionMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | ExposureMask | PropertyChangeMask | StructureNotifyMask | SubstructureRedirectMask | VisibilityChangeMask ); XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask ); XSelectInput( qt_xdisplay(), client, FocusChangeMask | PropertyChangeMask | ColormapChangeMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask ); updateMouseGrab(); } } // namespace diff --git a/rules.cpp b/rules.cpp index 3182adb3b..c1c32596f 100644 --- a/rules.cpp +++ b/rules.cpp @@ -1,577 +1,577 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2004 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #include "rules.h" #include #include #include #include #include #include "client.h" #include "workspace.h" namespace KWinInternal { static WindowRules dummyRules; // dummy used to avoid NULL checks WindowRules::WindowRules() : temporary_state( 0 ) , wmclassregexp( false ) , wmclasscomplete( false ) , windowroleregexp( false ) , titleregexp( false ) , extraroleregexp( false ) , clientmachineregexp( false ) , types( NET::AllTypesMask ) , placementrule( DontCareRule ) , positionrule( DontCareRule ) , sizerule( DontCareRule ) , minsizerule( DontCareRule ) , maxsizerule( DontCareRule ) , desktoprule( DontCareRule ) , typerule( DontCareRule ) , maximizevertrule( DontCareRule ) , maximizehorizrule( DontCareRule ) , minimizerule( DontCareRule ) , shaderule( DontCareRule ) , skiptaskbarrule( DontCareRule ) , skippagerrule( DontCareRule ) , aboverule( DontCareRule ) , belowrule( DontCareRule ) , fullscreenrule( DontCareRule ) , noborderrule( DontCareRule ) - , fspleveladjustrule( DontCareRule ) + , fsplevelrule( DontCareRule ) , acceptfocusrule( DontCareRule ) , moveresizemoderule( DontCareRule ) , closeablerule( DontCareRule ) { } WindowRules::WindowRules( const QString& str, bool temporary ) : temporary_state( temporary ? 2 : 0 ) { KTempFile file; QFile* f = file.file(); if( f != NULL ) { QCString s = str.utf8(); f->writeBlock( s.data(), s.length()); } file.close(); KSimpleConfig cfg( file.name()); readFromCfg( cfg ); file.unlink(); } #define READ_MATCH_STRING( var, func ) \ var = cfg.readEntry( #var ) func; \ var##regexp = cfg.readBoolEntry( #var "regexp" ); #define READ_SET_RULE( var, type, func ) \ var = func ( cfg.read##type##Entry( #var )); \ var##rule = readRule( cfg, #var "rule" ); #define READ_SET_RULE_2( var, type, func, funcarg ) \ var = func ( cfg.read##type##Entry( #var ), funcarg ); \ var##rule = readRule( cfg, #var "rule" ); #define READ_FORCE_RULE( var, type, func ) \ var = func ( cfg.read##type##Entry( #var )); \ var##rule = readForceRule( cfg, #var "rule" ); WindowRules::WindowRules( KConfig& cfg ) : temporary_state( 0 ) { readFromCfg( cfg ); } +static int limit0to4( int i ) { return QMAX( 0, QMIN( 4, i )); } + void WindowRules::readFromCfg( KConfig& cfg ) { wmclass = cfg.readEntry( "wmclass" ).lower().latin1(); wmclassregexp = cfg.readBoolEntry( "wmclassregexp" ); wmclasscomplete = cfg.readBoolEntry( "wmclasscomplete" ); READ_MATCH_STRING( windowrole, .lower().latin1() ); READ_MATCH_STRING( title, ); READ_MATCH_STRING( extrarole, .lower().latin1() ); READ_MATCH_STRING( clientmachine, .lower().latin1() ); types = cfg.readUnsignedLongNumEntry( "types", NET::AllTypesMask ); READ_SET_RULE_2( placement,, Placement::policyFromString, false ); READ_SET_RULE( position, Point, ); READ_SET_RULE( size, Size, ); if( size.isEmpty()) sizerule = DontCareRule; READ_SET_RULE( minsize, Size, ); if( !minsize.isValid()) minsizerule = DontCareRule; READ_SET_RULE( maxsize, Size, ); if( maxsize.isEmpty()) maxsizerule = DontCareRule; READ_SET_RULE( desktop, Num, ); type = readType( cfg, "type" ); typerule = type != NET::Unknown ? readForceRule( cfg, "typerule" ) : DontCareRule; READ_SET_RULE( maximizevert, Bool, ); READ_SET_RULE( maximizehoriz, Bool, ); READ_SET_RULE( minimize, Bool, ); READ_SET_RULE( shade, Bool, ); READ_SET_RULE( skiptaskbar, Bool, ); READ_SET_RULE( skippager, Bool, ); READ_SET_RULE( above, Bool, ); READ_SET_RULE( below, Bool, ); READ_SET_RULE( fullscreen, Bool, ); READ_SET_RULE( noborder, Bool, ); - READ_FORCE_RULE( fspleveladjust, Num, ); + READ_FORCE_RULE( fsplevel, Num, limit0to4 ); // fsp is 0-4 READ_FORCE_RULE( acceptfocus, Bool, ); READ_FORCE_RULE( moveresizemode, , Options::stringToMoveResizeMode ); READ_FORCE_RULE( closeable, Bool, ); kdDebug() << "READ RULE:" << wmclass << "/" << title << endl; } #undef READ_MATCH_STRING #undef READ_SET_RULE #undef READ_SET_RULE_2 #undef READ_FORCE_RULE #define WRITE_MATCH_STRING( var, cast ) \ if( !var.isEmpty()) \ { \ cfg.writeEntry( #var, cast var ); \ cfg.writeEntry( #var "regexp", var##regexp ); \ } \ else \ { \ cfg.deleteEntry( #var ); \ cfg.deleteEntry( #var "regexp" ); \ } #define WRITE_SET_RULE( var, func ) \ if( var##rule != DontCareRule ) \ { \ cfg.writeEntry( #var, func ( var )); \ cfg.writeEntry( #var "rule", var##rule ); \ } \ else \ { \ cfg.deleteEntry( #var ); \ cfg.deleteEntry( #var "rule" ); \ } #define WRITE_WITH_DEFAULT( var, default ) \ if( var != default ) \ cfg.writeEntry( #var, var ); \ else \ cfg.deleteEntry( #var ); void WindowRules::write( KConfig& cfg ) const { // always write wmclass cfg.writeEntry( "wmclass", ( const char* )wmclass ); cfg.writeEntry( "wmclassregexp", wmclassregexp ); cfg.writeEntry( "wmclasscomplete", wmclasscomplete ); WRITE_MATCH_STRING( windowrole, (const char*) ); WRITE_MATCH_STRING( title, ); WRITE_MATCH_STRING( extrarole, (const char*) ); WRITE_MATCH_STRING( clientmachine, (const char*) ); WRITE_WITH_DEFAULT( types, NET::AllTypesMask ); WRITE_SET_RULE( placement, Placement::policyToString ); WRITE_SET_RULE( position, ); WRITE_SET_RULE( size, ); WRITE_SET_RULE( minsize, ); WRITE_SET_RULE( maxsize, ); WRITE_SET_RULE( desktop, ); WRITE_SET_RULE( type, ); WRITE_SET_RULE( maximizevert, ); WRITE_SET_RULE( maximizehoriz, ); WRITE_SET_RULE( minimize, ); WRITE_SET_RULE( shade, ); WRITE_SET_RULE( skiptaskbar, ); WRITE_SET_RULE( skippager, ); WRITE_SET_RULE( above, ); WRITE_SET_RULE( below, ); WRITE_SET_RULE( fullscreen, ); WRITE_SET_RULE( noborder, ); - WRITE_SET_RULE( fspleveladjust, ); + WRITE_SET_RULE( fsplevel, ); WRITE_SET_RULE( acceptfocus, ); WRITE_SET_RULE( moveresizemode, Options::moveResizeModeToString ); WRITE_SET_RULE( closeable, ); } #undef WRITE_MATCH_STRING #undef WRITE_SET_RULE #undef WRITE_WITH_DEFAULT SettingRule WindowRules::readRule( KConfig& cfg, const QString& key ) { int v = cfg.readNumEntry( key ); if( v >= DontCareRule && v <= LastRule ) return static_cast< SettingRule >( v ); return DontCareRule; } SettingRule WindowRules::readForceRule( KConfig& cfg, const QString& key ) { int v = cfg.readNumEntry( key ); if( v == DontCareRule || v == ForceRule ) return static_cast< SettingRule >( v ); return DontCareRule; } NET::WindowType WindowRules::readType( KConfig& cfg, const QString& key ) { int v = cfg.readNumEntry( key ); if( v >= NET::Normal && v <= NET::Splash ) return static_cast< NET::WindowType >( v ); return NET::Unknown; } bool WindowRules::match( const Client* c ) const { if( types != NET::AllTypesMask ) { NET::WindowType t = c->windowType( true ); // direct type if( t == NET::Unknown ) t = NET::Normal; // NET::Unknown->NET::Normal is only here for matching if( !NET::typeMatchesMask( t, types )) return false; } if( !wmclass.isEmpty()) { // TODO optimize? QCString cwmclass = wmclasscomplete ? c->resourceName() + ' ' + c->resourceClass() : c->resourceClass(); if( wmclassregexp && QRegExp( wmclass ).search( cwmclass ) == -1 ) return false; if( !wmclassregexp && wmclass != cwmclass ) return false; } if( !windowrole.isEmpty()) { if( windowroleregexp && QRegExp( windowrole ).search( c->windowRole()) == -1 ) return false; if( !windowroleregexp && windowrole != c->windowRole()) return false; } if( !title.isEmpty()) { if( titleregexp && QRegExp( title ).search( c->caption( false )) == -1 ) return false; if( !titleregexp && title != c->caption( false )) return false; } // TODO extrarole if( !clientmachine.isEmpty()) { if( clientmachineregexp && QRegExp( clientmachine ).search( c->wmClientMachine( true )) == -1 && QRegExp( clientmachine ).search( c->wmClientMachine( false )) == -1 ) return false; if( !clientmachineregexp && clientmachine != c->wmClientMachine( true ) && clientmachine != c->wmClientMachine( false )) return false; } return true; } void WindowRules::update( Client* c ) { // TODO check this setting is for this client ? if( positionrule == RememberRule ) position = c->pos(); if( sizerule == RememberRule ) size = c->size(); if( desktoprule == RememberRule ) desktop = c->desktop(); if( maximizevertrule == RememberRule ) maximizevert = c->maximizeMode() & MaximizeVertical; if( maximizehorizrule == RememberRule ) maximizehoriz = c->maximizeMode() & MaximizeHorizontal; if( minimizerule == RememberRule ) minimize = c->isMinimized(); if( shaderule == RememberRule ) shade = c->shadeMode() != Client::ShadeNone; if( skiptaskbarrule == RememberRule ) skiptaskbar = c->skipTaskbar(); if( skippagerrule == RememberRule ) skippager = c->skipPager(); if( aboverule == RememberRule ) above = c->keepAbove(); if( belowrule == RememberRule ) below = c->keepBelow(); if( fullscreenrule == RememberRule ) fullscreen = c->isFullScreen(); if( noborderrule == RememberRule ) noborder = c->isUserNoBorder(); } Placement::Policy WindowRules::checkPlacement( Placement::Policy placement ) const { return checkForceRule( placementrule ) ? this->placement : placement; } // TODO at to porad jeste kontroluje min/max size , + udelat override pro min/max? QRect WindowRules::checkGeometry( const QRect& rect, bool init ) const { return QRect( checkRule( positionrule, init ) ? this->position : rect.topLeft(), checkRule( sizerule, init ) ? this->size : rect.size()); } QPoint WindowRules::checkPosition( const QPoint& pos, bool init ) const { return checkRule( positionrule, init ) ? this->position : pos; } QSize WindowRules::checkSize( const QSize& s, bool init ) const { return checkRule( sizerule, init ) ? this->size : s; } QSize WindowRules::checkMinSize( const QSize& s ) const { return checkForceRule( minsizerule ) ? this->minsize : s; } QSize WindowRules::checkMaxSize( const QSize& s ) const { return checkForceRule( maxsizerule ) ? this->maxsize : s; } int WindowRules::checkDesktop( int req_desktop, bool init ) const { // TODO chaining? return checkRule( desktoprule, init ) ? this->desktop : req_desktop; } NET::WindowType WindowRules::checkType( NET::WindowType req_type ) const { return checkForceRule( typerule ) ? this->type : req_type; } KDecorationDefines::MaximizeMode WindowRules::checkMaximize( MaximizeMode mode, bool init ) const { bool vert = checkRule( maximizevertrule, init ) ? this->maximizevert : bool( mode & MaximizeVertical ); bool horiz = checkRule( maximizehorizrule, init ) ? this->maximizehoriz : bool( mode & MaximizeHorizontal ); return static_cast< MaximizeMode >(( vert ? MaximizeVertical : 0 ) | ( horiz ? MaximizeHorizontal : 0 )); } bool WindowRules::checkMinimize( bool minimize, bool init ) const { return checkRule( minimizerule, init ) ? this->minimize : minimize; } Client::ShadeMode WindowRules::checkShade( Client::ShadeMode shade, bool init ) const { if( checkRule( shaderule, init )) { if( !this->shade ) return Client::ShadeNone; if( this->shade && shade == Client::ShadeNone ) return Client::ShadeNormal; } return shade; } bool WindowRules::checkSkipTaskbar( bool skip, bool init ) const { return checkRule( skiptaskbarrule, init ) ? this->skiptaskbar : skip; } bool WindowRules::checkSkipPager( bool skip, bool init ) const { return checkRule( skippagerrule, init ) ? this->skippager : skip; } bool WindowRules::checkKeepAbove( bool above, bool init ) const { return checkRule( aboverule, init ) ? this->above : above; } bool WindowRules::checkKeepBelow( bool below, bool init ) const { return checkRule( belowrule, init ) ? this->below : below; } bool WindowRules::checkFullScreen( bool fs, bool init ) const { return checkRule( fullscreenrule, init ) ? this->fullscreen : fs; } bool WindowRules::checkNoBorder( bool noborder, bool init ) const { return checkRule( noborderrule, init ) ? this->noborder : noborder; } int WindowRules::checkFSP( int fsp ) const { - if( !checkForceRule( fspleveladjustrule )) - return fsp; - return QMIN( 4, QMAX( 0, fsp + fspleveladjust )); + return checkForceRule( fsplevelrule ) ? this->fsplevel : fsp; } bool WindowRules::checkAcceptFocus( bool focus ) const { return checkForceRule( acceptfocusrule ) ? this->acceptfocus : focus; } Options::MoveResizeMode WindowRules::checkMoveResizeMode( Options::MoveResizeMode mode ) const { return checkForceRule( moveresizemoderule ) ? this->moveresizemode : mode; } bool WindowRules::checkCloseable( bool closeable ) const { return checkForceRule( closeablerule ) ? this->closeable : closeable; } bool WindowRules::isTemporary() const { return temporary_state > 0; } bool WindowRules::discardTemporary( bool force ) { if( temporary_state == 0 ) // not temporary return false; if( force || --temporary_state == 0 ) // too old { kdDebug() << "DISCARD:" << wmclass << "/" << title << endl; delete this; return true; } return false; } // Client void Client::setupWindowRules( bool ignore_temporary ) { client_rules = workspace()->findWindowRules( this, ignore_temporary ); // check only after getting the rules, because there may be a rule forcing window type if( isTopMenu()) // TODO cannot have restrictions client_rules = &dummyRules; } void Client::updateWindowRules() { client_rules->update( this ); } void Client::finishWindowRules() { updateWindowRules(); client_rules = &dummyRules; } // Workspace WindowRules* Workspace::findWindowRules( const Client* c, bool ignore_temporary ) { for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin(); it != windowRules.end(); ++it ) { if( ignore_temporary && (*it)->isTemporary()) continue; // TODO chaining for wildcard matches if( (*it)->match( c )) { kdDebug() << "RULE FOUND:" << c << endl; WindowRules* ret = *it; if( ret->isTemporary()) windowRules.remove( *it ); return ret; } } kdDebug() << "RULE DUMMY:" << c << endl; return &dummyRules; } void Workspace::editWindowRules( Client* c ) { // TODO } void Workspace::loadWindowRules() { while( !windowRules.isEmpty()) { delete windowRules.front(); windowRules.pop_front(); } KConfig cfg( "kwinrulesrc", true ); cfg.setGroup( "General" ); int count = cfg.readNumEntry( "count" ); kdDebug() << "RULES:" << count << endl; for( int i = 1; i <= count; ++i ) { cfg.setGroup( QString::number( i )); WindowRules* setting = new WindowRules( cfg ); windowRules.append( setting ); } } void Workspace::writeWindowRules() { KConfig cfg( "kwinrulesrc" ); cfg.setGroup( "General" ); cfg.writeEntry( "count", windowRules.count()); int i = 1; for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin(); it != windowRules.end(); ++it ) { if( (*it)->isTemporary()) continue; cfg.setGroup( QString::number( i )); (*it)->write( cfg ); ++i; } } void Workspace::gotTemporaryRulesMessage( const QString& message ) { bool was_temporary = false; for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin(); it != windowRules.end(); ++it ) if( (*it)->isTemporary()) was_temporary = true; WindowRules* rule = new WindowRules( message, true ); windowRules.prepend( rule ); // highest priority first if( !was_temporary ) QTimer::singleShot( 60000, this, SLOT( cleanupTemporaryRules())); } void Workspace::cleanupTemporaryRules() { kdDebug() << "CLEANUP" << endl; bool has_temporary = false; for( QValueList< WindowRules* >::Iterator it = windowRules.begin(); it != windowRules.end(); ) { if( (*it)->discardTemporary( false )) it = windowRules.remove( it ); else { if( (*it)->isTemporary()) has_temporary = true; ++it; } } if( has_temporary ) QTimer::singleShot( 60000, this, SLOT( cleanupTemporaryRules())); } } // namespace diff --git a/rules.h b/rules.h index e81f75331..a597cadbf 100644 --- a/rules.h +++ b/rules.h @@ -1,156 +1,156 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2004 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #ifndef KWIN_RULES_H #define KWIN_RULES_H #include #include #include #include "placement.h" #include "lib/kdecoration.h" #include "client.h" #include "options.h" class KConfig; namespace KWinInternal { class Client; enum SettingRule { DontCareRule, ForceRule, ApplyRule, RememberRule, LastRule = RememberRule }; class WindowRules : public KDecorationDefines { public: WindowRules(); WindowRules( KConfig& ); WindowRules( const QString&, bool temporary ); void write( KConfig& ) const; void update( Client* ); bool isTemporary() const; bool discardTemporary( bool force ); // removes if temporary and forced or too old bool match( const Client* c ) const; Placement::Policy checkPlacement( Placement::Policy placement ) const; QRect checkGeometry( const QRect& rect, bool init = false ) const; // use 'invalidPoint' with checkPosition, unlike QSize() and QRect(), QPoint() is a valid point QPoint checkPosition( const QPoint& pos, bool init = false ) const; QSize checkSize( const QSize& s, bool init = false ) const; QSize checkMinSize( const QSize& s ) const; QSize checkMaxSize( const QSize& s ) const; int checkDesktop( int desktop, bool init = false ) const; NET::WindowType checkType( NET::WindowType type ) const; MaximizeMode checkMaximize( MaximizeMode mode, bool init = false ) const; bool checkMinimize( bool minimized, bool init = false ) const; Client::ShadeMode checkShade( Client::ShadeMode shade, bool init = false ) const; bool checkSkipTaskbar( bool skip, bool init = false ) const; bool checkSkipPager( bool skip, bool init = false ) const; bool checkKeepAbove( bool above, bool init = false ) const; bool checkKeepBelow( bool below, bool init = false ) const; bool checkFullScreen( bool fs, bool init = false ) const; bool checkNoBorder( bool noborder, bool init = false ) const; int checkFSP( int fsp ) const; bool checkAcceptFocus( bool focus ) const; Options::MoveResizeMode checkMoveResizeMode( Options::MoveResizeMode mode ) const; bool checkCloseable( bool closeable ) const; private: void readFromCfg( KConfig& cfg ); static SettingRule readRule( KConfig&, const QString& key ); static SettingRule readForceRule( KConfig&, const QString& key ); static NET::WindowType readType( KConfig&, const QString& key ); static bool checkRule( SettingRule rule, bool init ); static bool checkForceRule( SettingRule rule ); int temporary_state; // e.g. for kstart QCString wmclass; bool wmclassregexp; bool wmclasscomplete; QCString windowrole; bool windowroleregexp; QString title; // TODO "caption" ? bool titleregexp; QCString extrarole; bool extraroleregexp; QCString clientmachine; bool clientmachineregexp; unsigned long types; // types for matching Placement::Policy placement; SettingRule placementrule; QPoint position; SettingRule positionrule; QSize size; SettingRule sizerule; QSize minsize; SettingRule minsizerule; QSize maxsize; SettingRule maxsizerule; int desktop; SettingRule desktoprule; NET::WindowType type; // type for setting SettingRule typerule; bool maximizevert; SettingRule maximizevertrule; bool maximizehoriz; SettingRule maximizehorizrule; bool minimize; SettingRule minimizerule; bool shade; SettingRule shaderule; bool skiptaskbar; SettingRule skiptaskbarrule; bool skippager; SettingRule skippagerrule; bool above; SettingRule aboverule; bool below; SettingRule belowrule; bool fullscreen; SettingRule fullscreenrule; bool noborder; SettingRule noborderrule; - int fspleveladjust; - SettingRule fspleveladjustrule; + int fsplevel; + SettingRule fsplevelrule; bool acceptfocus; SettingRule acceptfocusrule; Options::MoveResizeMode moveresizemode; SettingRule moveresizemoderule; bool closeable; SettingRule closeablerule; }; inline bool WindowRules::checkRule( SettingRule rule, bool init ) { if( rule != DontCareRule ) { if( rule == ForceRule || init ) return true; } return false; } inline bool WindowRules::checkForceRule( SettingRule rule ) { return rule == ForceRule; } } // namespace #endif