not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / useractions.cpp
blobbe7bce42de3b06cbfccf5bd96e26c359b1f937de
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *********************************************************************/
24 This file contains things relevant to direct user actions, such as
25 responses to global keyboard shortcuts, or selecting actions
26 from the window operations menu.
30 #include "client.h"
31 #include "workspace.h"
32 #include "effects.h"
34 #include <fixx11h.h>
35 #include <QPushButton>
36 #include <QSlider>
38 #include <kglobalsettings.h>
39 #include <kiconloader.h>
40 #include <klocale.h>
41 #include <kconfig.h>
42 #include <kglobalaccel.h>
43 #include <kapplication.h>
44 #include <QRegExp>
45 #include <QMenu>
46 #include <QVBoxLayout>
47 #include <kauthorized.h>
48 #include <kactioncollection.h>
49 #include <kaction.h>
51 #include "killwindow.h"
52 #include "tabbox.h"
54 namespace KWin
57 //****************************************
58 // Workspace
59 //****************************************
61 QMenu* Workspace::clientPopup()
63 if ( !popup )
65 popup = new QMenu;
66 popup->setFont(KGlobalSettings::menuFont());
67 connect( popup, SIGNAL( aboutToShow() ), this, SLOT( clientPopupAboutToShow() ) );
68 connect( popup, SIGNAL( triggered(QAction*) ), this, SLOT( clientPopupActivated(QAction*) ) );
70 advanced_popup = new QMenu( popup );
71 advanced_popup->setFont(KGlobalSettings::menuFont());
73 mKeepAboveOpAction = advanced_popup->addAction( i18n("Keep &Above Others") );
74 mKeepAboveOpAction->setIcon( KIcon( "go-up" ) );
75 KAction *kaction = qobject_cast<KAction*>( keys->action("Window Above Other Windows") );
76 if ( kaction!=0 )
77 mKeepAboveOpAction->setShortcut( kaction->globalShortcut().primary() );
78 mKeepAboveOpAction->setCheckable( true );
79 mKeepAboveOpAction->setData( Options::KeepAboveOp );
81 mKeepBelowOpAction = advanced_popup->addAction( i18n("Keep &Below Others") );
82 mKeepBelowOpAction->setIcon( KIcon( "go-down" ) );
83 kaction = qobject_cast<KAction*>( keys->action("Window Below Other Windows") );
84 if ( kaction!=0 )
85 mKeepBelowOpAction->setShortcut( kaction->globalShortcut().primary() );
86 mKeepBelowOpAction->setCheckable( true );
87 mKeepBelowOpAction->setData( Options::KeepBelowOp );
89 mFullScreenOpAction = advanced_popup->addAction( i18n("&Fullscreen") );
90 mFullScreenOpAction->setIcon( KIcon( "view-fullscreen" ) );
91 kaction = qobject_cast<KAction*>( keys->action("Window Fullscreen") );
92 if ( kaction!=0 )
93 mFullScreenOpAction->setShortcut( kaction->globalShortcut().primary() );
94 mFullScreenOpAction->setCheckable( true );
95 mFullScreenOpAction->setData( Options::FullScreenOp );
97 mNoBorderOpAction = advanced_popup->addAction( i18n("&No Border") );
98 kaction = qobject_cast<KAction*>( keys->action("Window No Border") );
99 if ( kaction!=0 )
100 mNoBorderOpAction->setShortcut( kaction->globalShortcut().primary() );
101 mNoBorderOpAction->setCheckable( true );
102 mNoBorderOpAction->setData( Options::NoBorderOp );
104 QAction *action = advanced_popup->addAction( i18n("Window &Shortcut...") );
105 action->setIcon( KIcon("configure-shortcuts") );
106 kaction = qobject_cast<KAction*>( keys->action("Setup Window Shortcut") );
107 if ( kaction!=0 )
108 action->setShortcut( kaction->globalShortcut().primary() );
109 action->setData( Options::SetupWindowShortcutOp );
111 action = advanced_popup->addAction( i18n("&Special Window Settings...") );
112 action->setIcon( KIcon( "wizard" ) );
113 action->setData( Options::WindowRulesOp );
115 action = advanced_popup->addAction( i18n("&Special Application Settings...") );
116 action->setIcon( KIcon( "wizard" ) );
117 action->setData( Options::ApplicationRulesOp );
119 action = popup->addMenu( advanced_popup );
120 action->setText( i18n("Ad&vanced") );
122 trans_popup = 0;
123 if (compositing()){
124 trans_popup = new QMenu( popup );
125 trans_popup->setFont(KGlobalSettings::menuFont());
126 connect( trans_popup, SIGNAL( triggered(QAction*) ), this, SLOT( setPopupClientOpacity(QAction*)));
127 const int levels[] = { 100, 90, 75, 50, 25, 10 };
128 for( unsigned int i = 0;
129 i < sizeof( levels ) / sizeof( levels[ 0 ] );
130 ++i )
132 action = trans_popup->addAction( QString::number( levels[ i ] ) + "%" );
133 action->setCheckable( true );
134 action->setData( levels[ i ] );
136 action = popup->addMenu( trans_popup );
137 action->setText( i18n("&Opacity") );
140 mMoveOpAction = popup->addAction( i18n("&Move") );
141 mMoveOpAction->setIcon( KIcon( "transform-move" ) );
142 kaction = qobject_cast<KAction*>( keys->action("Window Move") );
143 if ( kaction!=0 )
144 mMoveOpAction->setShortcut( kaction->globalShortcut().primary() );
145 mMoveOpAction->setData( Options::MoveOp );
147 mResizeOpAction = popup->addAction( i18n("Re&size") );
148 kaction = qobject_cast<KAction*>( keys->action("Window Resize") );
149 if ( kaction!=0 )
150 mResizeOpAction->setShortcut( kaction->globalShortcut().primary() );
151 mResizeOpAction->setData( Options::ResizeOp );
153 mMinimizeOpAction = popup->addAction( i18n("Mi&nimize") );
154 kaction = qobject_cast<KAction*>( keys->action("Window Minimize") );
155 if ( kaction!=0 )
156 mMinimizeOpAction->setShortcut( kaction->globalShortcut().primary() );
157 mMinimizeOpAction->setData( Options::MinimizeOp );
159 mMaximizeOpAction = popup->addAction( i18n("Ma&ximize") );
160 kaction = qobject_cast<KAction*>( keys->action("Window Maximize") );
161 if ( kaction!=0 )
162 mMaximizeOpAction->setShortcut( kaction->globalShortcut().primary() );
163 mMaximizeOpAction->setCheckable( true );
164 mMaximizeOpAction->setData( Options::MaximizeOp );
166 mShadeOpAction = popup->addAction( i18n("Sh&ade") );
167 kaction = qobject_cast<KAction*>( keys->action("Window Shade") );
168 if ( kaction!=0 )
169 mShadeOpAction->setShortcut( kaction->globalShortcut().primary() );
170 mShadeOpAction->setCheckable( true );
171 mShadeOpAction->setData( Options::ShadeOp );
173 popup->addSeparator();
175 if (!KGlobal::config()->isImmutable() &&
176 !KAuthorized::authorizeControlModules(Workspace::configModules(true)).isEmpty())
178 action = popup->addAction( i18n("Configur&e Window Behavior...") );
179 action->setIcon( KIcon( "configure" ) );
180 connect( action, SIGNAL( triggered() ), this, SLOT( configureWM() ) );
181 popup->addSeparator();
184 mCloseOpAction = popup->addAction( i18n("&Close") );
185 mCloseOpAction->setIcon( KIcon( "window-close" ) );
186 kaction = qobject_cast<KAction*>( keys->action("Window Close") );
187 if ( kaction!=0 )
188 mCloseOpAction->setShortcut( kaction->globalShortcut().primary() );
189 mCloseOpAction->setData( Options::CloseOp );
191 return popup;
194 void Workspace::discardPopup()
196 delete popup;
197 popup = NULL;
198 desk_popup = NULL;
201 void Workspace::setPopupClientOpacity( QAction* action )
203 if( active_popup_client == NULL )
204 return;
205 int level = action->data().toInt();
206 active_popup_client->setOpacity( level / 100.0 );
210 The client popup menu will become visible soon.
212 Adjust the items according to the respective popup client.
214 void Workspace::clientPopupAboutToShow()
216 if ( !active_popup_client || !popup )
217 return;
219 if ( numberOfDesktops() == 1 )
221 delete desk_popup;
222 desk_popup = 0;
224 else
226 initDesktopPopup();
229 mResizeOpAction->setEnabled( active_popup_client->isResizable() );
230 mMoveOpAction->setEnabled( active_popup_client->isMovableAcrossScreens() );
231 mMaximizeOpAction->setEnabled( active_popup_client->isMaximizable() );
232 mMaximizeOpAction->setChecked( active_popup_client->maximizeMode() == Client::MaximizeFull );
233 mShadeOpAction->setEnabled( active_popup_client->isShadeable() );
234 mShadeOpAction->setChecked( active_popup_client->shadeMode() != ShadeNone );
235 mKeepAboveOpAction->setChecked( active_popup_client->keepAbove() );
236 mKeepBelowOpAction->setChecked( active_popup_client->keepBelow() );
237 mFullScreenOpAction->setEnabled( active_popup_client->userCanSetFullScreen() );
238 mFullScreenOpAction->setChecked( active_popup_client->isFullScreen() );
239 mNoBorderOpAction->setEnabled( active_popup_client->userCanSetNoBorder() );
240 mNoBorderOpAction->setChecked( active_popup_client->noBorder() );
241 mMinimizeOpAction->setEnabled( active_popup_client->isMinimizable() );
242 mCloseOpAction->setEnabled( active_popup_client->isCloseable() );
243 if( trans_popup != NULL )
245 foreach( QAction* action, trans_popup->actions())
247 if( action->data().toInt() == qRound( active_popup_client->opacity() * 100 ))
248 action->setChecked( true );
249 else
250 action->setChecked( false );
256 void Workspace::initDesktopPopup()
258 if (desk_popup)
259 return;
261 desk_popup = new QMenu( popup );
262 desk_popup->setFont(KGlobalSettings::menuFont());
263 connect( desk_popup, SIGNAL( triggered(QAction*) ),
264 this, SLOT( slotSendToDesktop(QAction*) ) );
265 connect( desk_popup, SIGNAL( aboutToShow() ),
266 this, SLOT( desktopPopupAboutToShow() ) );
268 QAction *action = desk_popup->menuAction();
269 popup->insertAction(advanced_popup->menuAction(), action);
270 action->setText( i18n("To &Desktop") );
274 Adjusts the desktop popup to the current values and the location of
275 the popup client.
277 void Workspace::desktopPopupAboutToShow()
279 if ( !desk_popup )
280 return;
282 desk_popup->clear();
283 QAction *action = desk_popup->addAction( i18n("&All Desktops") );
284 action->setData( 0 );
285 action->setCheckable( true );
287 if ( active_popup_client && active_popup_client->isOnAllDesktops() )
288 action->setChecked( true );
289 desk_popup->addSeparator();
291 const int BASE = 10;
292 for ( int i = 1; i <= numberOfDesktops(); i++ ) {
293 QString basic_name("%1 %2");
294 if (i<BASE) {
295 basic_name.prepend('&');
297 action = desk_popup->addAction( basic_name.arg(i).arg( desktopName(i).replace( '&', "&&" ) ) );
298 action->setData( i );
299 action->setCheckable( true );
301 if ( active_popup_client &&
302 !active_popup_client->isOnAllDesktops() && active_popup_client->desktop() == i )
303 action->setChecked( true );
307 void Workspace::closeActivePopup()
309 if( active_popup )
311 active_popup->close();
312 active_popup = NULL;
313 active_popup_client = NULL;
318 Create the global accel object \c keys.
320 void Workspace::initShortcuts()
322 keys = new KActionCollection( this );
323 KActionCollection* actionCollection = keys;
324 QAction* a = 0L;
326 // a separate KActionCollection is needed for the shortcut for disabling global shortcuts,
327 // otherwise it would also disable itself
328 disable_shortcuts_keys = new KActionCollection( this );
329 #ifdef __GNUC__
330 #warning TODO PORT ME (KGlobalAccel related)
331 #endif
332 // FIXME KAccel port... needed?
333 //disable_shortcuts_keys->disableBlocking( true );
334 #define IN_KWIN
335 #include "kwinbindings.cpp"
336 readShortcuts();
339 void Workspace::readShortcuts()
341 #ifdef __GNUC__
342 #warning TODO PORT ME (KGlobalAccel related)
343 #endif
344 //KGlobalAccel::self()->readSettings();
346 KAction *kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktops") );
347 if ( kaction!=0 )
348 cutWalkThroughDesktops = kaction->globalShortcut();
350 kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktops (Reverse)") );
351 if ( kaction!=0 )
352 cutWalkThroughDesktopsReverse = kaction->globalShortcut();
354 kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktop List") );
355 if ( kaction!=0 )
356 cutWalkThroughDesktopList = kaction->globalShortcut();
358 kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktop List (Reverse)") );
359 if ( kaction!=0 )
360 cutWalkThroughDesktopListReverse = kaction->globalShortcut();
362 kaction = qobject_cast<KAction*>( keys->action("Walk Through Windows") );
363 if ( kaction!=0 )
364 cutWalkThroughWindows = kaction->globalShortcut();
366 kaction = qobject_cast<KAction*>( keys->action("Walk Through Windows (Reverse)") );
367 if ( kaction!=0 )
368 cutWalkThroughWindowsReverse = kaction->globalShortcut();
369 discardPopup(); // so that it's recreated next time
373 void Workspace::setupWindowShortcut( Client* c )
375 assert( client_keys_dialog == NULL );
376 #ifdef __GNUC__
377 #warning TODO PORT ME (KGlobalAccel related)
378 #endif
379 // keys->setEnabled( false );
380 // disable_shortcuts_keys->setEnabled( false );
381 // client_keys->setEnabled( false );
382 client_keys_dialog = new ShortcutDialog( c->shortcut().primary());
383 client_keys_client = c;
384 connect( client_keys_dialog, SIGNAL( dialogDone( bool )), SLOT( setupWindowShortcutDone( bool )));
385 QRect r = clientArea( ScreenArea, c );
386 QSize size = client_keys_dialog->sizeHint();
387 QPoint pos = c->pos() + c->clientPos();
388 if( pos.x() + size.width() >= r.right())
389 pos.setX( r.right() - size.width());
390 if( pos.y() + size.height() >= r.bottom())
391 pos.setY( r.bottom() - size.height());
392 client_keys_dialog->move( pos );
393 client_keys_dialog->show();
394 active_popup = client_keys_dialog;
395 active_popup_client = c;
398 void Workspace::setupWindowShortcutDone( bool ok )
400 // keys->setEnabled( true );
401 // disable_shortcuts_keys->setEnabled( true );
402 // client_keys->setEnabled( true );
403 if( ok )
404 client_keys_client->setShortcut( KShortcut( client_keys_dialog->shortcut()).toString());
405 closeActivePopup();
406 client_keys_dialog->deleteLater();
407 client_keys_dialog = NULL;
408 client_keys_client = NULL;
411 void Workspace::clientShortcutUpdated( Client* c )
413 QString key = QString( "_k_session:%1" ).arg(c->window());
414 QAction* action = client_keys->action( key.toLatin1().constData() );
415 if( !c->shortcut().isEmpty())
417 if( action == NULL ) // new shortcut
419 action = client_keys->addAction(QString( key ));
420 action->setText( i18n("Activate Window (%1)", c->caption()) );
421 connect( action, SIGNAL(triggered(bool)), c, SLOT(shortcutActivated()) );
424 KAction *kaction = qobject_cast<KAction*>( action );
425 // no autoloading, since it's configured explicitly here and is not meant to be reused
426 // (the key is the window id anyway, which is kind of random)
427 kaction->setGlobalShortcut(
428 c->shortcut(), KAction::ActiveShortcut, KAction::NoAutoloading );
429 kaction->setEnabled( true );
431 else
433 KAction *kaction = qobject_cast<KAction*>( action );
434 if( kaction )
436 kaction->forgetGlobalShortcut();
438 delete action;
442 void Workspace::clientPopupActivated( QAction *action )
444 if ( !action->data().isValid() )
445 return;
447 WindowOperation op = static_cast< WindowOperation >( action->data().toInt() );
448 Client* c = active_popup_client ? active_popup_client : active_client;
449 QString type;
450 switch( op )
452 case FullScreenOp:
453 if( !c->isFullScreen() && c->userCanSetFullScreen())
454 type = "fullscreenaltf3";
455 break;
456 case NoBorderOp:
457 if( !c->noBorder() && c->userCanSetNoBorder())
458 type = "noborderaltf3";
459 break;
460 default:
461 break;
463 if( !type.isEmpty())
464 helperDialog( type, c );
465 performWindowOperation( c, op );
469 void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
471 if ( !c )
472 return;
474 if (op == Options::MoveOp || op == Options::UnrestrictedMoveOp )
475 QCursor::setPos( c->geometry().center() );
476 if (op == Options::ResizeOp || op == Options::UnrestrictedResizeOp )
477 QCursor::setPos( c->geometry().bottomRight());
478 switch ( op )
480 case Options::MoveOp:
481 c->performMouseCommand( Options::MouseMove, cursorPos() );
482 break;
483 case Options::UnrestrictedMoveOp:
484 c->performMouseCommand( Options::MouseUnrestrictedMove, cursorPos() );
485 break;
486 case Options::ResizeOp:
487 c->performMouseCommand( Options::MouseResize, cursorPos() );
488 break;
489 case Options::UnrestrictedResizeOp:
490 c->performMouseCommand( Options::MouseUnrestrictedResize, cursorPos() );
491 break;
492 case Options::CloseOp:
493 c->closeWindow();
494 break;
495 case Options::MaximizeOp:
496 c->maximize( c->maximizeMode() == Client::MaximizeFull
497 ? Client::MaximizeRestore : Client::MaximizeFull );
498 break;
499 case Options::HMaximizeOp:
500 c->maximize( c->maximizeMode() ^ Client::MaximizeHorizontal );
501 break;
502 case Options::VMaximizeOp:
503 c->maximize( c->maximizeMode() ^ Client::MaximizeVertical );
504 break;
505 case Options::RestoreOp:
506 c->maximize( Client::MaximizeRestore );
507 break;
508 case Options::MinimizeOp:
509 c->minimize();
510 break;
511 case Options::ShadeOp:
512 c->performMouseCommand( Options::MouseShade, cursorPos());
513 break;
514 case Options::OnAllDesktopsOp:
515 c->setOnAllDesktops( !c->isOnAllDesktops() );
516 break;
517 case Options::FullScreenOp:
518 c->setFullScreen( !c->isFullScreen(), true );
519 break;
520 case Options::NoBorderOp:
521 c->setNoBorder( !c->noBorder());
522 break;
523 case Options::KeepAboveOp:
525 StackingUpdatesBlocker blocker( this );
526 bool was = c->keepAbove();
527 c->setKeepAbove( !c->keepAbove() );
528 if( was && !c->keepAbove())
529 raiseClient( c );
530 break;
532 case Options::KeepBelowOp:
534 StackingUpdatesBlocker blocker( this );
535 bool was = c->keepBelow();
536 c->setKeepBelow( !c->keepBelow() );
537 if( was && !c->keepBelow())
538 lowerClient( c );
539 break;
541 case Options::OperationsOp:
542 c->performMouseCommand( Options::MouseShade, cursorPos());
543 break;
544 case Options::WindowRulesOp:
545 editWindowRules( c, false );
546 break;
547 case Options::ApplicationRulesOp:
548 editWindowRules( c, true );
549 break;
550 case Options::SetupWindowShortcutOp:
551 setupWindowShortcut( c );
552 break;
553 case Options::LowerOp:
554 lowerClient(c);
555 break;
556 case Options::NoOp:
557 break;
562 Performs a mouse command on this client (see options.h)
564 bool Client::performMouseCommand( Options::MouseCommand command, const QPoint &globalPos, bool handled )
566 bool replay = false;
567 switch (command)
569 case Options::MouseRaise:
570 workspace()->raiseClient( this );
571 break;
572 case Options::MouseLower:
573 workspace()->lowerClient( this );
574 break;
575 case Options::MouseShade :
576 toggleShade();
577 cancelShadeHoverTimer();
578 break;
579 case Options::MouseSetShade:
580 setShade( ShadeNormal );
581 cancelShadeHoverTimer();
582 break;
583 case Options::MouseUnsetShade:
584 setShade( ShadeNone );
585 cancelShadeHoverTimer();
586 break;
587 case Options::MouseOperationsMenu:
588 if ( isActive() && options->clickRaise )
589 autoRaise();
590 workspace()->showWindowMenu( globalPos, this );
591 break;
592 case Options::MouseToggleRaiseAndLower:
593 workspace()->raiseOrLowerClient( this );
594 break;
595 case Options::MouseActivateAndRaise:
596 replay = isActive(); // for clickraise mode
597 workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled && replay );
598 workspace()->setActiveScreenMouse( globalPos );
599 break;
600 case Options::MouseActivateAndLower:
601 workspace()->requestFocus( this );
602 workspace()->lowerClient( this );
603 workspace()->setActiveScreenMouse( globalPos );
604 break;
605 case Options::MouseActivate:
606 replay = isActive(); // for clickraise mode
607 workspace()->takeActivity( this, ActivityFocus, handled && replay );
608 workspace()->setActiveScreenMouse( globalPos );
609 break;
610 case Options::MouseActivateRaiseAndPassClick:
611 workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled );
612 workspace()->setActiveScreenMouse( globalPos );
613 replay = true;
614 break;
615 case Options::MouseActivateAndPassClick:
616 workspace()->takeActivity( this, ActivityFocus, handled );
617 workspace()->setActiveScreenMouse( globalPos );
618 replay = true;
619 break;
620 case Options::MouseActivateRaiseAndMove:
621 case Options::MouseActivateRaiseAndUnrestrictedMove:
622 workspace()->raiseClient( this );
623 workspace()->requestFocus( this );
624 workspace()->setActiveScreenMouse( globalPos );
625 if( options->moveMode == Options::Transparent && isMovableAcrossScreens())
626 move_faked_activity = workspace()->fakeRequestedActivity( this );
627 // fallthrough
628 case Options::MouseMove:
629 case Options::MouseUnrestrictedMove:
631 if (!isMovableAcrossScreens())
632 break;
633 if( moveResizeMode )
634 finishMoveResize( false );
635 mode = PositionCenter;
636 buttonDown = true;
637 moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global
638 invertedMoveOffset = rect().bottomRight() - moveOffset;
639 unrestrictedMoveResize = ( command == Options::MouseActivateRaiseAndUnrestrictedMove
640 || command == Options::MouseUnrestrictedMove );
641 if( !startMoveResize())
642 buttonDown = false;
643 updateCursor();
644 break;
646 case Options::MouseResize:
647 case Options::MouseUnrestrictedResize:
649 if (!isResizable() || isShade())
650 break;
651 if( moveResizeMode )
652 finishMoveResize( false );
653 buttonDown = true;
654 moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global
655 int x = moveOffset.x(), y = moveOffset.y();
656 bool left = x < width() / 3;
657 bool right = x >= 2 * width() / 3;
658 bool top = y < height() / 3;
659 bool bot = y >= 2 * height() / 3;
660 if (top)
661 mode = left ? PositionTopLeft : (right ? PositionTopRight : PositionTop);
662 else if (bot)
663 mode = left ? PositionBottomLeft : (right ? PositionBottomRight : PositionBottom);
664 else
665 mode = (x < width() / 2) ? PositionLeft : PositionRight;
666 invertedMoveOffset = rect().bottomRight() - moveOffset;
667 unrestrictedMoveResize = ( command == Options::MouseUnrestrictedResize );
668 if( !startMoveResize())
669 buttonDown = false;
670 updateCursor();
671 break;
673 case Options::MouseMaximize:
674 maximize( Client::MaximizeFull );
675 break;
676 case Options::MouseRestore:
677 maximize( Client::MaximizeRestore );
678 break;
679 case Options::MouseMinimize:
680 minimize();
681 break;
682 case Options::MouseAbove:
684 StackingUpdatesBlocker blocker( workspace());
685 if( keepBelow())
686 setKeepBelow( false );
687 else
688 setKeepAbove( true );
689 break;
691 case Options::MouseBelow:
693 StackingUpdatesBlocker blocker( workspace());
694 if( keepAbove())
695 setKeepAbove( false );
696 else
697 setKeepBelow( true );
698 break;
700 case Options::MousePreviousDesktop:
701 workspace()->windowToPreviousDesktop( this );
702 break;
703 case Options::MouseNextDesktop:
704 workspace()->windowToNextDesktop( this );
705 break;
706 case Options::MouseOpacityMore:
707 if( !isDesktop() ) // No point in changing the opacity of the desktop
708 setOpacity( qMin( opacity() + 0.1, 1.0 ));
709 break;
710 case Options::MouseOpacityLess:
711 if( !isDesktop() ) // No point in changing the opacity of the desktop
712 setOpacity( qMax( opacity() - 0.1, 0.0 ));
713 break;
714 case Options::MouseNothing:
715 replay = true;
716 break;
718 return replay;
721 // KDE4 remove me
722 void Workspace::showWindowMenuAt( unsigned long, int, int )
724 slotWindowOperations();
727 void Workspace::loadEffect( const QString& name )
729 if( effects )
730 static_cast<EffectsHandlerImpl*>(effects)->loadEffect( name );
733 void Workspace::toggleEffect( const QString& name )
735 if( effects )
736 static_cast<EffectsHandlerImpl*>(effects)->toggleEffect( name );
739 void Workspace::unloadEffect( const QString& name )
741 if( effects )
742 static_cast<EffectsHandlerImpl*>(effects)->unloadEffect( name );
745 void Workspace::reconfigureEffect( const QString& name )
747 if( effects )
748 static_cast<EffectsHandlerImpl*>(effects)->reconfigureEffect( name );
751 QStringList Workspace::loadedEffects() const
753 QStringList listModulesLoaded;
754 if ( effects )
755 listModulesLoaded = static_cast<EffectsHandlerImpl*>(effects)->loadedEffects();
756 return listModulesLoaded;
759 QStringList Workspace::listOfEffects() const
761 QStringList listModules;
762 if ( effects )
763 listModules = static_cast<EffectsHandlerImpl*>(effects)->listOfEffects();
764 return listModules;
767 void Workspace::slotActivateAttentionWindow()
769 if( attention_chain.count() > 0 )
770 activateClient( attention_chain.first());
773 void Workspace::slotSwitchDesktopNext()
775 int d = currentDesktop() + 1;
776 if ( d > numberOfDesktops() )
778 if ( options->rollOverDesktops )
780 d = 1;
782 else
784 return;
787 setCurrentDesktop(d);
790 void Workspace::slotSwitchDesktopPrevious()
792 int d = currentDesktop() - 1;
793 if ( d <= 0 )
795 if ( options->rollOverDesktops )
796 d = numberOfDesktops();
797 else
798 return;
800 setCurrentDesktop(d);
803 void Workspace::slotSwitchDesktopRight()
805 int desktop = desktopToRight( currentDesktop(), options->rollOverDesktops);
806 if( desktop == currentDesktop())
807 return;
808 setCurrentDesktop( desktop );
811 void Workspace::slotSwitchDesktopLeft()
813 int desktop = desktopToLeft( currentDesktop(), options->rollOverDesktops);
814 if( desktop == currentDesktop())
815 return;
816 setCurrentDesktop( desktop );
819 void Workspace::slotSwitchDesktopUp()
821 int desktop = desktopUp( currentDesktop(), options->rollOverDesktops);
822 if( desktop == currentDesktop())
823 return;
824 setCurrentDesktop( desktop );
827 void Workspace::slotSwitchDesktopDown()
829 int desktop = desktopDown( currentDesktop(), options->rollOverDesktops);
830 if( desktop == currentDesktop())
831 return;
832 setCurrentDesktop( desktop );
835 void Workspace::slotSwitchToDesktop( int i )
837 setCurrentDesktop( i );
841 void Workspace::slotWindowToDesktop( int i )
843 Client* c = active_popup_client ? active_popup_client : active_client;
844 if( i >= 1 && i <= numberOfDesktops() && c
845 && !c->isDesktop()
846 && !c->isDock()
847 && !c->isTopMenu())
848 sendClientToDesktop( c, i, true );
851 void Workspace::slotSwitchToScreen( int i )
853 setCurrentScreen( i );
856 void Workspace::slotSwitchToNextScreen()
858 slotSwitchToScreen(( activeScreen() + 1 ) % numScreens());
861 void Workspace::slotWindowToScreen( int i )
863 Client* c = active_popup_client ? active_popup_client : active_client;
864 if( i >= 0 && i <= numScreens() && c
865 && !c->isDesktop()
866 && !c->isDock()
867 && !c->isTopMenu())
869 sendClientToScreen( c, i );
873 void Workspace::slotWindowToNextScreen()
875 Client* c = active_popup_client ? active_popup_client : active_client;
876 if( c
877 && !c->isDesktop()
878 && !c->isDock()
879 && !c->isTopMenu())
881 sendClientToScreen( c, ( c->screen() + 1 ) % numScreens());
886 Maximizes the popup client
888 void Workspace::slotWindowMaximize()
890 Client* c = active_popup_client ? active_popup_client : active_client;
891 if ( c )
892 performWindowOperation( c, Options::MaximizeOp );
896 Maximizes the popup client vertically
898 void Workspace::slotWindowMaximizeVertical()
900 Client* c = active_popup_client ? active_popup_client : active_client;
901 if ( c )
902 performWindowOperation( c, Options::VMaximizeOp );
906 Maximizes the popup client horiozontally
908 void Workspace::slotWindowMaximizeHorizontal()
910 Client* c = active_popup_client ? active_popup_client : active_client;
911 if ( c )
912 performWindowOperation( c, Options::HMaximizeOp );
917 Minimizes the popup client
919 void Workspace::slotWindowMinimize()
921 Client* c = active_popup_client ? active_popup_client : active_client;
922 performWindowOperation( c, Options::MinimizeOp );
926 Shades/unshades the popup client respectively
928 void Workspace::slotWindowShade()
930 Client* c = active_popup_client ? active_popup_client : active_client;
931 performWindowOperation( c, Options::ShadeOp );
935 Raises the popup client
937 void Workspace::slotWindowRaise()
939 Client* c = active_popup_client ? active_popup_client : active_client;
940 if ( c )
941 raiseClient( c );
945 Lowers the popup client
947 void Workspace::slotWindowLower()
949 Client* c = active_popup_client ? active_popup_client : active_client;
950 if ( c )
951 lowerClient( c );
955 Does a toggle-raise-and-lower on the popup client;
957 void Workspace::slotWindowRaiseOrLower()
959 Client* c = active_popup_client ? active_popup_client : active_client;
960 if ( c )
961 raiseOrLowerClient( c );
964 void Workspace::slotWindowOnAllDesktops()
966 Client* c = active_popup_client ? active_popup_client : active_client;
967 if( c )
968 c->setOnAllDesktops( !c->isOnAllDesktops());
971 void Workspace::slotWindowFullScreen()
973 Client* c = active_popup_client ? active_popup_client : active_client;
974 if( c )
975 performWindowOperation( c, Options::FullScreenOp );
978 void Workspace::slotWindowNoBorder()
980 Client* c = active_popup_client ? active_popup_client : active_client;
981 if( c )
982 performWindowOperation( c, Options::NoBorderOp );
985 void Workspace::slotWindowAbove()
987 Client* c = active_popup_client ? active_popup_client : active_client;
988 if( c )
989 performWindowOperation( c, Options::KeepAboveOp );
992 void Workspace::slotWindowBelow()
994 Client* c = active_popup_client ? active_popup_client : active_client;
995 if( c )
996 performWindowOperation( c, Options::KeepBelowOp );
998 void Workspace::slotSetupWindowShortcut()
1000 Client* c = active_popup_client ? active_popup_client : active_client;
1001 if( c )
1002 performWindowOperation( c, Options::SetupWindowShortcutOp );
1006 Move window to next desktop
1008 void Workspace::slotWindowToNextDesktop()
1010 windowToNextDesktop( active_popup_client ? active_popup_client : active_client );
1013 void Workspace::windowToNextDesktop( Client* c )
1015 int d = currentDesktop() + 1;
1016 if ( d > numberOfDesktops() )
1017 d = 1;
1018 if (c && !c->isDesktop()
1019 && !c->isDock() && !c->isTopMenu())
1021 setClientIsMoving( c );
1022 setCurrentDesktop( d );
1023 setClientIsMoving( NULL );
1028 Move window to previous desktop
1030 void Workspace::slotWindowToPreviousDesktop()
1032 windowToPreviousDesktop( active_popup_client ? active_popup_client : active_client );
1035 void Workspace::windowToPreviousDesktop( Client* c )
1037 int d = currentDesktop() - 1;
1038 if ( d <= 0 )
1039 d = numberOfDesktops();
1040 if (c && !c->isDesktop()
1041 && !c->isDock() && !c->isTopMenu())
1043 setClientIsMoving( c );
1044 setCurrentDesktop( d );
1045 setClientIsMoving( NULL );
1049 void Workspace::slotWindowToDesktopRight()
1051 int d = desktopToRight( currentDesktop(), options->rollOverDesktops);
1052 if( d == currentDesktop())
1053 return;
1054 Client* c = active_popup_client ? active_popup_client : active_client;
1055 if (c && !c->isDesktop()
1056 && !c->isDock() && !c->isTopMenu())
1058 setClientIsMoving( c );
1059 setCurrentDesktop( d );
1060 setClientIsMoving( NULL );
1064 void Workspace::slotWindowToDesktopLeft()
1066 int d = desktopToLeft( currentDesktop(), options->rollOverDesktops);
1067 if( d == currentDesktop())
1068 return;
1069 Client* c = active_popup_client ? active_popup_client : active_client;
1070 if (c && !c->isDesktop()
1071 && !c->isDock() && !c->isTopMenu())
1073 setClientIsMoving( c );
1074 setCurrentDesktop( d );
1075 setClientIsMoving( NULL );
1079 void Workspace::slotWindowToDesktopUp()
1081 int d = desktopUp( currentDesktop(), options->rollOverDesktops);
1082 if( d == currentDesktop())
1083 return;
1084 Client* c = active_popup_client ? active_popup_client : active_client;
1085 if (c && !c->isDesktop()
1086 && !c->isDock() && !c->isTopMenu())
1088 setClientIsMoving( c );
1089 setCurrentDesktop( d );
1090 setClientIsMoving( NULL );
1094 void Workspace::slotWindowToDesktopDown()
1096 int d = desktopDown( currentDesktop(), options->rollOverDesktops);
1097 if( d == currentDesktop())
1098 return;
1099 Client* c = active_popup_client ? active_popup_client : active_client;
1100 if (c && !c->isDesktop()
1101 && !c->isDock() && !c->isTopMenu())
1103 setClientIsMoving( c );
1104 setCurrentDesktop( d );
1105 setClientIsMoving( NULL );
1111 Kill Window feature, similar to xkill
1113 void Workspace::slotKillWindow()
1115 KillWindow kill( this );
1116 kill.start();
1120 Sends the popup client to desktop \a desk
1122 Internal slot for the window operation menu
1124 void Workspace::slotSendToDesktop( QAction *action )
1126 int desk = action->data().toInt();
1127 if ( !active_popup_client )
1128 return;
1129 if ( desk == 0 )
1130 { // the 'on_all_desktops' menu entry
1131 active_popup_client->setOnAllDesktops( !active_popup_client->isOnAllDesktops());
1132 return;
1135 sendClientToDesktop( active_popup_client, desk, false );
1140 Shows the window operations popup menu for the activeClient()
1142 void Workspace::slotWindowOperations()
1144 if ( !active_client )
1145 return;
1146 QPoint pos = active_client->pos() + active_client->clientPos();
1147 showWindowMenu( pos.x(), pos.y(), active_client );
1150 void Workspace::showWindowMenu( const QRect &pos, Client* cl )
1152 if (!KAuthorized::authorizeKAction("kwin_rmb"))
1153 return;
1154 if( !cl )
1155 return;
1156 if( active_popup_client != NULL ) // recursion
1157 return;
1158 if ( cl->isDesktop()
1159 || cl->isDock()
1160 || cl->isTopMenu())
1161 return;
1163 active_popup_client = cl;
1164 QMenu* p = clientPopup();
1165 active_popup = p;
1166 int x = pos.left();
1167 int y = pos.bottom();
1168 if (y == pos.top())
1169 p->exec( QPoint( x, y ) );
1170 else
1172 QRect area = clientArea(ScreenArea, QPoint(x, y), currentDesktop());
1173 clientPopupAboutToShow(); // needed for sizeHint() to be correct :-/
1174 int popupHeight = p->sizeHint().height();
1175 if (y + popupHeight < area.height())
1176 p->exec( QPoint( x, y ) );
1177 else
1178 p->exec( QPoint( x, pos.top() - popupHeight ) );
1180 // active popup may be already changed (e.g. the window shortcut dialog)
1181 if( active_popup == p )
1182 closeActivePopup();
1186 Closes the popup client
1188 void Workspace::slotWindowClose()
1190 if ( tab_box->isVisible())
1191 return;
1192 Client* c = active_popup_client ? active_popup_client : active_client;
1193 performWindowOperation( c, Options::CloseOp );
1197 Starts keyboard move mode for the popup client
1199 void Workspace::slotWindowMove()
1201 Client* c = active_popup_client ? active_popup_client : active_client;
1202 performWindowOperation( c, Options::UnrestrictedMoveOp );
1206 Starts keyboard resize mode for the popup client
1208 void Workspace::slotWindowResize()
1210 Client* c = active_popup_client ? active_popup_client : active_client;
1211 performWindowOperation( c, Options::UnrestrictedResizeOp );
1214 void Client::setShortcut( const QString& _cut )
1216 QString cut = rules()->checkShortcut( _cut );
1217 if( cut.isEmpty())
1218 return setShortcutInternal( KShortcut());
1219 // Format:
1220 // base+(abcdef)<space>base+(abcdef)
1221 // E.g. Alt+Ctrl+(ABCDEF) Win+X,Win+(ABCDEF)
1222 if( !cut.contains( '(' ) && !cut.contains( ')' ) && !cut.contains( ' ' ))
1224 if( workspace()->shortcutAvailable( KShortcut( cut ), this ))
1225 setShortcutInternal( KShortcut( cut ));
1226 else
1227 setShortcutInternal( KShortcut());
1228 return;
1230 QList< KShortcut > keys;
1231 QStringList groups = cut.split( ' ');
1232 for( QStringList::ConstIterator it = groups.constBegin();
1233 it != groups.constEnd();
1234 ++it )
1236 QRegExp reg( "(.*\\+)\\((.*)\\)" );
1237 if( reg.indexIn( *it ) > -1 )
1239 QString base = reg.cap( 1 );
1240 QString list = reg.cap( 2 );
1241 for( int i = 0;
1242 i < list.length();
1243 ++i )
1245 KShortcut c( base + list[ i ] );
1246 if( !c.isEmpty())
1247 keys.append( c );
1251 for( QList< KShortcut >::ConstIterator it = keys.constBegin();
1252 it != keys.constEnd();
1253 ++it )
1255 if( _shortcut == *it ) // current one is in the list
1256 return;
1258 for( QList< KShortcut >::ConstIterator it = keys.constBegin();
1259 it != keys.constEnd();
1260 ++it )
1262 if( workspace()->shortcutAvailable( *it, this ))
1264 setShortcutInternal( *it );
1265 return;
1268 setShortcutInternal( KShortcut());
1271 void Client::setShortcutInternal( const KShortcut& cut )
1273 if( _shortcut == cut )
1274 return;
1275 _shortcut = cut;
1276 updateCaption();
1277 #if 0
1278 workspace()->clientShortcutUpdated( this );
1279 #else
1280 // Workaround for kwin<->kglobalaccel deadlock, when KWin has X grab and the kded
1281 // kglobalaccel module tries to create the key grab. KWin should preferably grab
1282 // they keys itself anyway :(.
1283 QTimer::singleShot( 0, this, SLOT( delayedSetShortcut()));
1284 #endif
1287 void Client::delayedSetShortcut()
1289 workspace()->clientShortcutUpdated( this );
1292 bool Workspace::shortcutAvailable( const KShortcut& cut, Client* ignore ) const
1294 // TODO check global shortcuts etc.
1295 for( ClientList::ConstIterator it = clients.constBegin();
1296 it != clients.constEnd();
1297 ++it )
1299 if( (*it) != ignore && (*it)->shortcut() == cut )
1300 return false;
1302 return true;
1305 } // namespace