diff options
Diffstat (limited to 'kwin/useractions.cpp')
-rw-r--r-- | kwin/useractions.cpp | 1119 |
1 files changed, 1119 insertions, 0 deletions
diff --git a/kwin/useractions.cpp b/kwin/useractions.cpp new file mode 100644 index 000000000..b722bf1a1 --- /dev/null +++ b/kwin/useractions.cpp @@ -0,0 +1,1119 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org> +Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org> + +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 direct user actions, such as + responses to global keyboard shortcuts, or selecting actions + from the window operations menu. + +*/ + +#include "client.h" +#include "workspace.h" + +#include <fixx11h.h> +#include <qhbox.h> +#include <qpushbutton.h> +#include <qslider.h> +#include <qtooltip.h> +#include <qpopupmenu.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kconfig.h> +#include <kglobalaccel.h> +#include <kapplication.h> +#include <qregexp.h> + +#include "killwindow.h" +#include "tabbox.h" + +namespace KWinInternal +{ + +//**************************************** +// Workspace +//**************************************** + +QPopupMenu* Workspace::clientPopup() + { + if ( !popup ) + { + popup = new QPopupMenu; + popup->setCheckable( TRUE ); + popup->setFont(KGlobalSettings::menuFont()); + connect( popup, SIGNAL( aboutToShow() ), this, SLOT( clientPopupAboutToShow() ) ); + connect( popup, SIGNAL( activated(int) ), this, SLOT( clientPopupActivated(int) ) ); + + advanced_popup = new QPopupMenu( popup ); + advanced_popup->setCheckable( TRUE ); + advanced_popup->setFont(KGlobalSettings::menuFont()); + connect( advanced_popup, SIGNAL( activated(int) ), this, SLOT( clientPopupActivated(int) ) ); + advanced_popup->insertItem( SmallIconSet( "up" ), + i18n("Keep &Above Others")+'\t'+keys->shortcut("Window Above Other Windows").seq(0).toString(), Options::KeepAboveOp ); + advanced_popup->insertItem( SmallIconSet( "down" ), + i18n("Keep &Below Others")+'\t'+keys->shortcut("Window Below Other Windows").seq(0).toString(), Options::KeepBelowOp ); + advanced_popup->insertItem( SmallIconSet( "window_fullscreen" ), + i18n("&Fullscreen")+'\t'+keys->shortcut("Window Fullscreen").seq(0).toString(), Options::FullScreenOp ); + advanced_popup->insertItem( i18n("&No Border")+'\t'+keys->shortcut("Window No Border").seq(0).toString(), Options::NoBorderOp ); + advanced_popup->insertItem( SmallIconSet("key_bindings"), + i18n("Window &Shortcut...")+'\t'+keys->shortcut("Setup Window Shortcut").seq(0).toString(), Options::SetupWindowShortcutOp ); + advanced_popup->insertItem( SmallIconSet( "wizard" ), i18n("&Special Window Settings..."), Options::WindowRulesOp ); + advanced_popup->insertItem( SmallIconSet( "wizard" ), i18n("&Special Application Settings..."), Options::ApplicationRulesOp ); + + popup->insertItem(i18n("Ad&vanced"), advanced_popup ); + desk_popup_index = popup->count(); + + if (options->useTranslucency){ + QPopupMenu *trans_popup = new QPopupMenu( popup ); + QVBox *transBox = new QVBox(trans_popup); + transButton = new QPushButton(transBox, "transButton"); + QToolTip::add(transButton, i18n("Reset opacity to default value")); + transSlider = new QSlider(0, 100, 1, 100, Qt::Vertical, transBox, "transSlider"); + QToolTip::add(transSlider, i18n("Slide this to set the window's opacity")); + connect(transButton, SIGNAL(clicked()), SLOT(resetClientOpacity())); + connect(transButton, SIGNAL(clicked()), trans_popup, SLOT(hide())); + connect(transSlider, SIGNAL(valueChanged(int)), SLOT(setTransButtonText(int))); + connect(transSlider, SIGNAL(valueChanged(int)), this, SLOT(setPopupClientOpacity(int))); +// connect(transSlider, SIGNAL(sliderReleased()), trans_popup, SLOT(hide())); + trans_popup->insertItem(transBox); + popup->insertItem(i18n("&Opacity"), trans_popup ); + } + + popup->insertItem( SmallIconSet( "move" ), i18n("&Move")+'\t'+keys->shortcut("Window Move").seq(0).toString(), Options::MoveOp ); + popup->insertItem( i18n("Re&size")+'\t'+keys->shortcut("Window Resize").seq(0).toString(), Options::ResizeOp ); + popup->insertItem( i18n("Mi&nimize")+'\t'+keys->shortcut("Window Minimize").seq(0).toString(), Options::MinimizeOp ); + popup->insertItem( i18n("Ma&ximize")+'\t'+keys->shortcut("Window Maximize").seq(0).toString(), Options::MaximizeOp ); + popup->insertItem( i18n("Sh&ade")+'\t'+keys->shortcut("Window Shade").seq(0).toString(), Options::ShadeOp ); + + popup->insertSeparator(); + + if (!KGlobal::config()->isImmutable() && + !kapp->authorizeControlModules(Workspace::configModules(true)).isEmpty()) + { + popup->insertItem(SmallIconSet( "configure" ), i18n("Configur&e Window Behavior..."), this, SLOT( configureWM() )); + popup->insertSeparator(); + } + + popup->insertItem( SmallIconSet( "fileclose" ), i18n("&Close")+'\t'+keys->shortcut("Window Close").seq(0).toString(), Options::CloseOp ); + } + return popup; + } + +//sets the transparency of the client to given value(given by slider) +void Workspace::setPopupClientOpacity(int value) + { + active_popup_client->setCustomOpacityFlag(true); + value = 100 - value; + value<100?active_popup_client->setOpacity(true, (uint)((value/100.0)*0xffffffff)):active_popup_client->setOpacity(false,0xffffffff); + } + +void Workspace::setTransButtonText(int value) + { + value = 100 - value; + if(value < 0) + transButton->setText("000 %"); + else if (value >= 100 ) + transButton->setText("100 %"); + else if(value < 10) + transButton->setText("00"+QString::number(value)+" %"); + else if(value < 100) + transButton->setText("0"+QString::number(value)+" %"); + } + +void Workspace::resetClientOpacity() + { + active_popup_client->setCustomOpacityFlag(false); + active_popup_client->updateOpacity(); + transSlider->setValue(100-active_popup_client->opacityPercentage()); + setTransButtonText(100-active_popup_client->opacityPercentage()); + } + + +/*! + The client popup menu will become visible soon. + + Adjust the items according to the respective popup client. + */ +void Workspace::clientPopupAboutToShow() + { + if ( !active_popup_client || !popup ) + return; + + if ( numberOfDesktops() == 1 ) + { + delete desk_popup; + desk_popup = 0; + } + else + { + initDesktopPopup(); + } + + popup->setItemEnabled( Options::ResizeOp, active_popup_client->isResizable() ); + popup->setItemEnabled( Options::MoveOp, active_popup_client->isMovable() ); + popup->setItemEnabled( Options::MaximizeOp, active_popup_client->isMaximizable() ); + popup->setItemChecked( Options::MaximizeOp, active_popup_client->maximizeMode() == Client::MaximizeFull ); + // This should be checked also when hover unshaded + popup->setItemChecked( Options::ShadeOp, active_popup_client->shadeMode() != ShadeNone ); + popup->setItemEnabled( Options::ShadeOp, active_popup_client->isShadeable()); + advanced_popup->setItemChecked( Options::KeepAboveOp, active_popup_client->keepAbove() ); + advanced_popup->setItemChecked( Options::KeepBelowOp, active_popup_client->keepBelow() ); + advanced_popup->setItemChecked( Options::FullScreenOp, active_popup_client->isFullScreen() ); + advanced_popup->setItemEnabled( Options::FullScreenOp, active_popup_client->userCanSetFullScreen() ); + advanced_popup->setItemChecked( Options::NoBorderOp, active_popup_client->noBorder() ); + advanced_popup->setItemEnabled( Options::NoBorderOp, active_popup_client->userCanSetNoBorder() ); + popup->setItemEnabled( Options::MinimizeOp, active_popup_client->isMinimizable() ); + popup->setItemEnabled( Options::CloseOp, active_popup_client->isCloseable() ); + if (options->useTranslucency) + { + transSlider->setValue(100-active_popup_client->opacityPercentage()); + setTransButtonText(100-active_popup_client->opacityPercentage()); + } + } + + +void Workspace::initDesktopPopup() + { + if (desk_popup) + return; + + desk_popup = new QPopupMenu( popup ); + desk_popup->setCheckable( TRUE ); + desk_popup->setFont(KGlobalSettings::menuFont()); + connect( desk_popup, SIGNAL( activated(int) ), + this, SLOT( slotSendToDesktop(int) ) ); + connect( desk_popup, SIGNAL( aboutToShow() ), + this, SLOT( desktopPopupAboutToShow() ) ); + + popup->insertItem(i18n("To &Desktop"), desk_popup, -1, desk_popup_index ); + } + +/*! + Adjusts the desktop popup to the current values and the location of + the popup client. + */ +void Workspace::desktopPopupAboutToShow() + { + if ( !desk_popup ) + return; + + desk_popup->clear(); + desk_popup->insertItem( i18n("&All Desktops"), 0 ); + if ( active_popup_client && active_popup_client->isOnAllDesktops() ) + desk_popup->setItemChecked( 0, TRUE ); + desk_popup->insertSeparator( -1 ); + int id; + const int BASE = 10; + for ( int i = 1; i <= numberOfDesktops(); i++ ) + { + QString basic_name("%1 %2"); + if (i<BASE) + { + basic_name.prepend('&'); + } + id = desk_popup->insertItem( + basic_name + .arg(i) + .arg( desktopName(i).replace( '&', "&&" )), + i ); + if ( active_popup_client && + !active_popup_client->isOnAllDesktops() && active_popup_client->desktop() == i ) + desk_popup->setItemChecked( id, TRUE ); + } + } + +void Workspace::closeActivePopup() + { + if( active_popup ) + { + active_popup->close(); + active_popup = NULL; + active_popup_client = NULL; + } + } + +/*! + Create the global accel object \c keys. + */ +void Workspace::initShortcuts() + { + keys = new KGlobalAccel( this ); + // a separate KGlobalAccel is needed for the shortcut for disabling global shortcuts, + // otherwise it would also disable itself + disable_shortcuts_keys = new KGlobalAccel( this ); + disable_shortcuts_keys->disableBlocking( true ); +#define IN_KWIN +#include "kwinbindings.cpp" + readShortcuts(); + } + +void Workspace::readShortcuts() + { + keys->readSettings(); + disable_shortcuts_keys->readSettings(); + + cutWalkThroughDesktops = keys->shortcut("Walk Through Desktops"); + cutWalkThroughDesktopsReverse = keys->shortcut("Walk Through Desktops (Reverse)"); + cutWalkThroughDesktopList = keys->shortcut("Walk Through Desktop List"); + cutWalkThroughDesktopListReverse = keys->shortcut("Walk Through Desktop List (Reverse)"); + cutWalkThroughWindows = keys->shortcut("Walk Through Windows"); + cutWalkThroughWindowsReverse = keys->shortcut("Walk Through Windows (Reverse)"); + + keys->updateConnections(); + disable_shortcuts_keys->updateConnections(); + + delete popup; + popup = NULL; // so that it's recreated next time + desk_popup = NULL; + } + + +void Workspace::setupWindowShortcut( Client* c ) + { + assert( client_keys_dialog == NULL ); + keys->suspend( true ); + disable_shortcuts_keys->suspend( true ); + client_keys->suspend( true ); + client_keys_dialog = new ShortcutDialog( c->shortcut()); + client_keys_client = c; + connect( client_keys_dialog, SIGNAL( dialogDone( bool )), SLOT( setupWindowShortcutDone( bool ))); + QRect r = clientArea( ScreenArea, c ); + QSize size = client_keys_dialog->sizeHint(); + QPoint pos = c->pos() + c->clientPos(); + if( pos.x() + size.width() >= r.right()) + pos.setX( r.right() - size.width()); + if( pos.y() + size.height() >= r.bottom()) + pos.setY( r.bottom() - size.height()); + client_keys_dialog->move( pos ); + client_keys_dialog->show(); + active_popup = client_keys_dialog; + active_popup_client = c; + } + +void Workspace::setupWindowShortcutDone( bool ok ) + { + keys->suspend( false ); + disable_shortcuts_keys->suspend( false ); + client_keys->suspend( false ); + if( ok ) + { + client_keys_client->setShortcut( KShortcut( client_keys_dialog->shortcut()).toString()); + } + closeActivePopup(); + delete client_keys_dialog; + client_keys_dialog = NULL; + client_keys_client = NULL; + } + +void Workspace::clientShortcutUpdated( Client* c ) + { + QString key = QString::number( c->window()); + client_keys->remove( key ); + if( !c->shortcut().isNull()) + { + client_keys->insert( key, key ); + client_keys->setShortcut( key, c->shortcut()); + client_keys->setSlot( key, c, SLOT( shortcutActivated())); + client_keys->setActionEnabled( key, true ); + } + client_keys->updateConnections(); + } + +void Workspace::clientPopupActivated( int id ) + { + WindowOperation op = static_cast< WindowOperation >( id ); + Client* c = active_popup_client ? active_popup_client : active_client; + QString type; + switch( op ) + { + case FullScreenOp: + if( !c->isFullScreen() && c->userCanSetFullScreen()) + type = "fullscreenaltf3"; + break; + case NoBorderOp: + if( !c->noBorder() && c->userCanSetNoBorder()) + type = "noborderaltf3"; + break; + default: + break; + }; + if( !type.isEmpty()) + helperDialog( type, c ); + performWindowOperation( c, op ); + } + + +void Workspace::performWindowOperation( Client* c, Options::WindowOperation op ) + { + if ( !c ) + return; + + if (op == Options::MoveOp || op == Options::UnrestrictedMoveOp ) + QCursor::setPos( c->geometry().center() ); + if (op == Options::ResizeOp || op == Options::UnrestrictedResizeOp ) + QCursor::setPos( c->geometry().bottomRight()); + switch ( op ) + { + case Options::MoveOp: + c->performMouseCommand( Options::MouseMove, QCursor::pos() ); + break; + case Options::UnrestrictedMoveOp: + c->performMouseCommand( Options::MouseUnrestrictedMove, QCursor::pos() ); + break; + case Options::ResizeOp: + c->performMouseCommand( Options::MouseResize, QCursor::pos() ); + break; + case Options::UnrestrictedResizeOp: + c->performMouseCommand( Options::MouseUnrestrictedResize, QCursor::pos() ); + break; + case Options::CloseOp: + c->closeWindow(); + break; + case Options::MaximizeOp: + c->maximize( c->maximizeMode() == Client::MaximizeFull + ? Client::MaximizeRestore : Client::MaximizeFull ); + break; + case Options::HMaximizeOp: + c->maximize( c->maximizeMode() ^ Client::MaximizeHorizontal ); + break; + case Options::VMaximizeOp: + c->maximize( c->maximizeMode() ^ Client::MaximizeVertical ); + break; + case Options::RestoreOp: + c->maximize( Client::MaximizeRestore ); + break; + case Options::MinimizeOp: + c->minimize(); + break; + case Options::ShadeOp: + c->performMouseCommand( Options::MouseShade, QCursor::pos()); + break; + case Options::OnAllDesktopsOp: + c->setOnAllDesktops( !c->isOnAllDesktops() ); + break; + case Options::FullScreenOp: + c->setFullScreen( !c->isFullScreen(), true ); + break; + case Options::NoBorderOp: + c->setUserNoBorder( !c->isUserNoBorder()); + break; + case Options::KeepAboveOp: + { + StackingUpdatesBlocker blocker( this ); + bool was = c->keepAbove(); + c->setKeepAbove( !c->keepAbove() ); + if( was && !c->keepAbove()) + raiseClient( c ); + break; + } + case Options::KeepBelowOp: + { + StackingUpdatesBlocker blocker( this ); + bool was = c->keepBelow(); + c->setKeepBelow( !c->keepBelow() ); + if( was && !c->keepBelow()) + lowerClient( c ); + break; + } + case Options::OperationsOp: + c->performMouseCommand( Options::MouseShade, QCursor::pos()); + break; + case Options::WindowRulesOp: + editWindowRules( c, false ); + break; + case Options::ApplicationRulesOp: + editWindowRules( c, true ); + break; + case Options::SetupWindowShortcutOp: + setupWindowShortcut( c ); + break; + case Options::LowerOp: + lowerClient(c); + break; + case Options::NoOp: + break; + } + } + +/*! + Performs a mouse command on this client (see options.h) + */ +bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPos, bool handled ) + { + bool replay = FALSE; + switch (command) + { + case Options::MouseRaise: + workspace()->raiseClient( this ); + break; + case Options::MouseLower: + workspace()->lowerClient( this ); + break; + case Options::MouseShade : + toggleShade(); + cancelShadeHover(); + break; + case Options::MouseSetShade: + setShade( ShadeNormal ); + cancelShadeHover(); + break; + case Options::MouseUnsetShade: + setShade( ShadeNone ); + cancelShadeHover(); + break; + case Options::MouseOperationsMenu: + if ( isActive() && options->clickRaise ) + autoRaise(); + workspace()->showWindowMenu( globalPos, this ); + break; + case Options::MouseToggleRaiseAndLower: + workspace()->raiseOrLowerClient( this ); + break; + case Options::MouseActivateAndRaise: + replay = isActive(); // for clickraise mode + workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled && replay ); + break; + case Options::MouseActivateAndLower: + workspace()->requestFocus( this ); + workspace()->lowerClient( this ); + break; + case Options::MouseActivate: + replay = isActive(); // for clickraise mode + workspace()->takeActivity( this, ActivityFocus, handled && replay ); + break; + case Options::MouseActivateRaiseAndPassClick: + workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled ); + replay = TRUE; + break; + case Options::MouseActivateAndPassClick: + workspace()->takeActivity( this, ActivityFocus, handled ); + replay = TRUE; + break; + case Options::MouseActivateRaiseAndMove: + case Options::MouseActivateRaiseAndUnrestrictedMove: + workspace()->raiseClient( this ); + workspace()->requestFocus( this ); + if( options->moveMode == Options::Transparent && isMovable()) + move_faked_activity = workspace()->fakeRequestedActivity( this ); + // fallthrough + case Options::MouseMove: + case Options::MouseUnrestrictedMove: + { + if (!isMovable()) + break; + if( moveResizeMode ) + finishMoveResize( false ); + mode = PositionCenter; + buttonDown = TRUE; + moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global + invertedMoveOffset = rect().bottomRight() - moveOffset; + unrestrictedMoveResize = ( command == Options::MouseActivateRaiseAndUnrestrictedMove + || command == Options::MouseUnrestrictedMove ); + setCursor( mode ); + if( !startMoveResize()) + { + buttonDown = false; + setCursor( mode ); + } + break; + } + case Options::MouseResize: + case Options::MouseUnrestrictedResize: + { + if (!isResizable() || isShade()) + break; + if( moveResizeMode ) + finishMoveResize( false ); + buttonDown = TRUE; + moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global + int x = moveOffset.x(), y = moveOffset.y(); + bool left = x < width() / 3; + bool right = x >= 2 * width() / 3; + bool top = y < height() / 3; + bool bot = y >= 2 * height() / 3; + if (top) + mode = left ? PositionTopLeft : (right ? PositionTopRight : PositionTop); + else if (bot) + mode = left ? PositionBottomLeft : (right ? PositionBottomRight : PositionBottom); + else + mode = (x < width() / 2) ? PositionLeft : PositionRight; + invertedMoveOffset = rect().bottomRight() - moveOffset; + unrestrictedMoveResize = ( command == Options::MouseUnrestrictedResize ); + setCursor( mode ); + if( !startMoveResize()) + { + buttonDown = false; + setCursor( mode ); + } + break; + } + case Options::MouseMaximize: + maximize( Client::MaximizeFull ); + break; + case Options::MouseRestore: + maximize( Client::MaximizeRestore ); + break; + case Options::MouseMinimize: + minimize(); + break; + case Options::MouseAbove: + { + StackingUpdatesBlocker blocker( workspace()); + if( keepBelow()) + setKeepBelow( false ); + else + setKeepAbove( true ); + break; + } + case Options::MouseBelow: + { + StackingUpdatesBlocker blocker( workspace()); + if( keepAbove()) + setKeepAbove( false ); + else + setKeepBelow( true ); + break; + } + case Options::MousePreviousDesktop: + workspace()->windowToPreviousDesktop( this ); + break; + case Options::MouseNextDesktop: + workspace()->windowToNextDesktop( this ); + break; + case Options::MouseOpacityMore: + if (opacity_ < 0xFFFFFFFF) + { + if (opacity_ < 0xF3333333) + { + setOpacity(TRUE, opacity_ + 0xCCCCCCC); + custom_opacity = true; + } + else + { + setOpacity(FALSE, 0xFFFFFFFF); + custom_opacity = false; + } + } + break; + case Options::MouseOpacityLess: + if (opacity_ > 0) + { + setOpacity(TRUE, (opacity_ > 0xCCCCCCC) ? opacity_ - 0xCCCCCCC : 0); + custom_opacity = true; + } + break; + case Options::MouseNothing: + replay = TRUE; + break; + } + return replay; + } + +// KDE4 remove me +void Workspace::showWindowMenuAt( unsigned long, int, int ) + { + slotWindowOperations(); + } + +void Workspace::slotActivateAttentionWindow() + { + if( attention_chain.count() > 0 ) + activateClient( attention_chain.first()); + } + +void Workspace::slotSwitchDesktopNext() + { + int d = currentDesktop() + 1; + if ( d > numberOfDesktops() ) + { + if ( options->rollOverDesktops ) + { + d = 1; + } + else + { + return; + } + } + setCurrentDesktop(d); + } + +void Workspace::slotSwitchDesktopPrevious() + { + int d = currentDesktop() - 1; + if ( d <= 0 ) + { + if ( options->rollOverDesktops ) + d = numberOfDesktops(); + else + return; + } + setCurrentDesktop(d); + } + +void Workspace::slotSwitchDesktopRight() + { + int desktop = desktopToRight( currentDesktop()); + if( desktop == currentDesktop()) + return; + setCurrentDesktop( desktop ); + } + +void Workspace::slotSwitchDesktopLeft() + { + int desktop = desktopToLeft( currentDesktop()); + if( desktop == currentDesktop()) + return; + setCurrentDesktop( desktop ); + } + +void Workspace::slotSwitchDesktopUp() + { + int desktop = desktopUp( currentDesktop()); + if( desktop == currentDesktop()) + return; + setCurrentDesktop( desktop ); + } + +void Workspace::slotSwitchDesktopDown() + { + int desktop = desktopDown( currentDesktop()); + if( desktop == currentDesktop()) + return; + setCurrentDesktop( desktop ); + } + +void Workspace::slotSwitchToDesktop( int i ) + { + setCurrentDesktop( i ); + } + + +void Workspace::slotWindowToDesktop( int i ) + { + Client* c = active_popup_client ? active_popup_client : active_client; + if( i >= 1 && i <= numberOfDesktops() && c + && !c->isDesktop() + && !c->isDock() + && !c->isTopMenu()) + sendClientToDesktop( c, i, true ); + } + +/*! + Maximizes the popup client + */ +void Workspace::slotWindowMaximize() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if ( c ) + performWindowOperation( c, Options::MaximizeOp ); + } + +/*! + Maximizes the popup client vertically + */ +void Workspace::slotWindowMaximizeVertical() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if ( c ) + performWindowOperation( c, Options::VMaximizeOp ); + } + +/*! + Maximizes the popup client horiozontally + */ +void Workspace::slotWindowMaximizeHorizontal() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if ( c ) + performWindowOperation( c, Options::HMaximizeOp ); + } + + +/*! + Minimizes the popup client + */ +void Workspace::slotWindowMinimize() + { + Client* c = active_popup_client ? active_popup_client : active_client; + performWindowOperation( c, Options::MinimizeOp ); + } + +/*! + Shades/unshades the popup client respectively + */ +void Workspace::slotWindowShade() + { + Client* c = active_popup_client ? active_popup_client : active_client; + performWindowOperation( c, Options::ShadeOp ); + } + +/*! + Raises the popup client + */ +void Workspace::slotWindowRaise() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if ( c ) + raiseClient( c ); + } + +/*! + Lowers the popup client + */ +void Workspace::slotWindowLower() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if ( c ) + lowerClient( c ); + } + +/*! + Does a toggle-raise-and-lower on the popup client; + */ +void Workspace::slotWindowRaiseOrLower() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if ( c ) + raiseOrLowerClient( c ); + } + +void Workspace::slotWindowOnAllDesktops() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if( c ) + c->setOnAllDesktops( !c->isOnAllDesktops()); + } + +void Workspace::slotWindowFullScreen() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if( c ) + performWindowOperation( c, Options::FullScreenOp ); + } + +void Workspace::slotWindowNoBorder() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if( c ) + performWindowOperation( c, Options::NoBorderOp ); + } + +void Workspace::slotWindowAbove() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if( c ) + performWindowOperation( c, Options::KeepAboveOp ); + } + +void Workspace::slotWindowBelow() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if( c ) + performWindowOperation( c, Options::KeepBelowOp ); + } +void Workspace::slotSetupWindowShortcut() + { + Client* c = active_popup_client ? active_popup_client : active_client; + if( c ) + performWindowOperation( c, Options::SetupWindowShortcutOp ); + } + +/*! + Move window to next desktop + */ +void Workspace::slotWindowToNextDesktop() + { + windowToNextDesktop( active_popup_client ? active_popup_client : active_client ); + } + +void Workspace::windowToNextDesktop( Client* c ) + { + int d = currentDesktop() + 1; + if ( d > numberOfDesktops() ) + d = 1; + if (c && !c->isDesktop() + && !c->isDock() && !c->isTopMenu()) + { + setClientIsMoving( c ); + setCurrentDesktop( d ); + setClientIsMoving( NULL ); + } + } + +/*! + Move window to previous desktop + */ +void Workspace::slotWindowToPreviousDesktop() + { + windowToPreviousDesktop( active_popup_client ? active_popup_client : active_client ); + } + +void Workspace::windowToPreviousDesktop( Client* c ) + { + int d = currentDesktop() - 1; + if ( d <= 0 ) + d = numberOfDesktops(); + if (c && !c->isDesktop() + && !c->isDock() && !c->isTopMenu()) + { + setClientIsMoving( c ); + setCurrentDesktop( d ); + setClientIsMoving( NULL ); + } + } + +void Workspace::slotWindowToDesktopRight() + { + int d = desktopToRight( currentDesktop()); + if( d == currentDesktop()) + return; + Client* c = active_popup_client ? active_popup_client : active_client; + if (c && !c->isDesktop() + && !c->isDock() && !c->isTopMenu()) + { + setClientIsMoving( c ); + setCurrentDesktop( d ); + setClientIsMoving( NULL ); + } + } + +void Workspace::slotWindowToDesktopLeft() + { + int d = desktopToLeft( currentDesktop()); + if( d == currentDesktop()) + return; + Client* c = active_popup_client ? active_popup_client : active_client; + if (c && !c->isDesktop() + && !c->isDock() && !c->isTopMenu()) + { + setClientIsMoving( c ); + setCurrentDesktop( d ); + setClientIsMoving( NULL ); + } + } + +void Workspace::slotWindowToDesktopUp() + { + int d = desktopUp( currentDesktop()); + if( d == currentDesktop()) + return; + Client* c = active_popup_client ? active_popup_client : active_client; + if (c && !c->isDesktop() + && !c->isDock() && !c->isTopMenu()) + { + setClientIsMoving( c ); + setCurrentDesktop( d ); + setClientIsMoving( NULL ); + } + } + +void Workspace::slotWindowToDesktopDown() + { + int d = desktopDown( currentDesktop()); + if( d == currentDesktop()) + return; + Client* c = active_popup_client ? active_popup_client : active_client; + if (c && !c->isDesktop() + && !c->isDock() && !c->isTopMenu()) + { + setClientIsMoving( c ); + setCurrentDesktop( d ); + setClientIsMoving( NULL ); + } + } + + +/*! + Kill Window feature, similar to xkill + */ +void Workspace::slotKillWindow() + { + KillWindow kill( this ); + kill.start(); + } + +/*! + Sends the popup client to desktop \a desk + + Internal slot for the window operation menu + */ +void Workspace::slotSendToDesktop( int desk ) + { + if ( !active_popup_client ) + return; + if ( desk == 0 ) + { // the 'on_all_desktops' menu entry + active_popup_client->setOnAllDesktops( !active_popup_client->isOnAllDesktops()); + return; + } + + sendClientToDesktop( active_popup_client, desk, false ); + + } + +/*! + Shows the window operations popup menu for the activeClient() + */ +void Workspace::slotWindowOperations() + { + if ( !active_client ) + return; + QPoint pos = active_client->pos() + active_client->clientPos(); + showWindowMenu( pos.x(), pos.y(), active_client ); + } + +void Workspace::showWindowMenu( const QRect &pos, Client* cl ) + { + if (!kapp->authorizeKAction("kwin_rmb")) + return; + if( !cl ) + return; + if( active_popup_client != NULL ) // recursion + return; + if ( cl->isDesktop() + || cl->isDock() + || cl->isTopMenu()) + return; + + active_popup_client = cl; + QPopupMenu* p = clientPopup(); + active_popup = p; + int x = pos.left(); + int y = pos.bottom(); + if (y == pos.top()) + p->exec( QPoint( x, y ) ); + else + { + QRect area = clientArea(ScreenArea, QPoint(x, y), currentDesktop()); + clientPopupAboutToShow(); // needed for sizeHint() to be correct :-/ + int popupHeight = p->sizeHint().height(); + if (y + popupHeight < area.height()) + p->exec( QPoint( x, y ) ); + else + p->exec( QPoint( x, pos.top() - popupHeight ) ); + } + // active popup may be already changed (e.g. the window shortcut dialog) + if( active_popup == p ) + closeActivePopup(); + } + +/*! + Closes the popup client + */ +void Workspace::slotWindowClose() + { + if ( tab_box->isVisible()) + return; + Client* c = active_popup_client ? active_popup_client : active_client; + performWindowOperation( c, Options::CloseOp ); + } + +/*! + Starts keyboard move mode for the popup client + */ +void Workspace::slotWindowMove() + { + Client* c = active_popup_client ? active_popup_client : active_client; + performWindowOperation( c, Options::UnrestrictedMoveOp ); + } + +/*! + Starts keyboard resize mode for the popup client + */ +void Workspace::slotWindowResize() + { + Client* c = active_popup_client ? active_popup_client : active_client; + performWindowOperation( c, Options::UnrestrictedResizeOp ); + } + +void Client::setShortcut( const QString& _cut ) + { + QString cut = rules()->checkShortcut( _cut ); + if( cut.isEmpty()) + return setShortcutInternal( KShortcut()); +// Format: +// base+(abcdef)<space>base+(abcdef) +// E.g. Alt+Ctrl+(ABCDEF) Win+X,Win+(ABCDEF) + if( !cut.contains( '(' ) && !cut.contains( ')' ) && !cut.contains( ' ' )) + { + if( workspace()->shortcutAvailable( KShortcut( cut ), this )) + setShortcutInternal( KShortcut( cut )); + else + setShortcutInternal( KShortcut()); + return; + } + QValueList< KShortcut > keys; + QStringList groups = QStringList::split( ' ', cut ); + for( QStringList::ConstIterator it = groups.begin(); + it != groups.end(); + ++it ) + { + QRegExp reg( "(.*\\+)\\((.*)\\)" ); + if( reg.search( *it ) > -1 ) + { + QString base = reg.cap( 1 ); + QString list = reg.cap( 2 ); + for( unsigned int i = 0; + i < list.length(); + ++i ) + { + KShortcut c( base + list[ i ] ); + if( !c.isNull()) + keys.append( c ); + } + } + } + for( QValueList< KShortcut >::ConstIterator it = keys.begin(); + it != keys.end(); + ++it ) + { + if( _shortcut == *it ) // current one is in the list + return; + } + for( QValueList< KShortcut >::ConstIterator it = keys.begin(); + it != keys.end(); + ++it ) + { + if( workspace()->shortcutAvailable( *it, this )) + { + setShortcutInternal( *it ); + return; + } + } + setShortcutInternal( KShortcut()); + } + +void Client::setShortcutInternal( const KShortcut& cut ) + { + if( _shortcut == cut ) + return; + _shortcut = cut; + updateCaption(); + workspace()->clientShortcutUpdated( this ); + } + +bool Workspace::shortcutAvailable( const KShortcut& cut, Client* ignore ) const + { + // TODO check global shortcuts etc. + for( ClientList::ConstIterator it = clients.begin(); + it != clients.end(); + ++it ) + { + if( (*it) != ignore && (*it)->shortcut() == cut ) + return false; + } + return true; + } + +} // namespace |