Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kwin / useractions.cpp
blob376e1499f0e8c391f5be6e15df44cb2e88283617
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::setPopupClientOpacity( QAction* action )
196 if( active_popup_client == NULL )
197 return;
198 int level = action->data().toInt();
199 active_popup_client->setOpacity( level / 100.0 );
203 The client popup menu will become visible soon.
205 Adjust the items according to the respective popup client.
207 void Workspace::clientPopupAboutToShow()
209 if ( !active_popup_client || !popup )
210 return;
212 if ( numberOfDesktops() == 1 )
214 delete desk_popup;
215 desk_popup = 0;
217 else
219 initDesktopPopup();
222 mResizeOpAction->setEnabled( active_popup_client->isResizable() );
223 mMoveOpAction->setEnabled( active_popup_client->isMovable() );
224 mMaximizeOpAction->setEnabled( active_popup_client->isMaximizable() );
225 mMaximizeOpAction->setChecked( active_popup_client->maximizeMode() == Client::MaximizeFull );
226 mShadeOpAction->setEnabled( active_popup_client->isShadeable() );
227 mShadeOpAction->setChecked( active_popup_client->shadeMode() != ShadeNone );
228 mKeepAboveOpAction->setChecked( active_popup_client->keepAbove() );
229 mKeepBelowOpAction->setChecked( active_popup_client->keepBelow() );
230 mFullScreenOpAction->setEnabled( active_popup_client->userCanSetFullScreen() );
231 mFullScreenOpAction->setChecked( active_popup_client->isFullScreen() );
232 mNoBorderOpAction->setEnabled( active_popup_client->userCanSetNoBorder() );
233 mNoBorderOpAction->setChecked( active_popup_client->noBorder() );
234 mMinimizeOpAction->setEnabled( active_popup_client->isMinimizable() );
235 mCloseOpAction->setEnabled( active_popup_client->isCloseable() );
236 if( trans_popup != NULL )
238 foreach( QAction* action, trans_popup->actions())
240 if( action->data().toInt() == qRound( active_popup_client->opacity() * 100 ))
241 action->setChecked( true );
242 else
243 action->setChecked( false );
249 void Workspace::initDesktopPopup()
251 if (desk_popup)
252 return;
254 desk_popup = new QMenu( popup );
255 desk_popup->setFont(KGlobalSettings::menuFont());
256 connect( desk_popup, SIGNAL( triggered(QAction*) ),
257 this, SLOT( slotSendToDesktop(QAction*) ) );
258 connect( desk_popup, SIGNAL( aboutToShow() ),
259 this, SLOT( desktopPopupAboutToShow() ) );
261 QAction *action = desk_popup->menuAction();
262 popup->insertAction(mMoveOpAction, action);
263 action->setText( i18n("To &Desktop") );
267 Adjusts the desktop popup to the current values and the location of
268 the popup client.
270 void Workspace::desktopPopupAboutToShow()
272 if ( !desk_popup )
273 return;
275 desk_popup->clear();
276 QAction *action = desk_popup->addAction( i18n("&All Desktops") );
277 action->setData( 0 );
278 action->setCheckable( true );
280 if ( active_popup_client && active_popup_client->isOnAllDesktops() )
281 action->setChecked( true );
282 desk_popup->addSeparator();
284 const int BASE = 10;
285 for ( int i = 1; i <= numberOfDesktops(); i++ ) {
286 QString basic_name("%1 %2");
287 if (i<BASE) {
288 basic_name.prepend('&');
290 action = desk_popup->addAction( basic_name.arg(i).arg( desktopName(i).replace( '&', "&&" ) ) );
291 action->setData( i );
292 action->setCheckable( true );
294 if ( active_popup_client &&
295 !active_popup_client->isOnAllDesktops() && active_popup_client->desktop() == i )
296 action->setChecked( true );
300 void Workspace::closeActivePopup()
302 if( active_popup )
304 active_popup->close();
305 active_popup = NULL;
306 active_popup_client = NULL;
311 Create the global accel object \c keys.
313 void Workspace::initShortcuts()
315 keys = new KActionCollection( this );
316 KActionCollection* actionCollection = keys;
317 QAction* a = 0L;
319 // a separate KActionCollection is needed for the shortcut for disabling global shortcuts,
320 // otherwise it would also disable itself
321 disable_shortcuts_keys = new KActionCollection( this );
322 #ifdef __GNUC__
323 #warning TODO PORT ME (KGlobalAccel related)
324 #endif
325 // FIXME KAccel port... needed?
326 //disable_shortcuts_keys->disableBlocking( true );
327 #define IN_KWIN
328 #include "kwinbindings.cpp"
329 readShortcuts();
332 void Workspace::readShortcuts()
334 #ifdef __GNUC__
335 #warning TODO PORT ME (KGlobalAccel related)
336 #endif
337 //KGlobalAccel::self()->readSettings();
339 KAction *kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktops") );
340 if ( kaction!=0 )
341 cutWalkThroughDesktops = kaction->globalShortcut();
343 kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktops (Reverse)") );
344 if ( kaction!=0 )
345 cutWalkThroughDesktopsReverse = kaction->globalShortcut();
347 kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktop List") );
348 if ( kaction!=0 )
349 cutWalkThroughDesktopList = kaction->globalShortcut();
351 kaction = qobject_cast<KAction*>( keys->action("Walk Through Desktop List (Reverse)") );
352 if ( kaction!=0 )
353 cutWalkThroughDesktopListReverse = kaction->globalShortcut();
355 kaction = qobject_cast<KAction*>( keys->action("Walk Through Windows") );
356 if ( kaction!=0 )
357 cutWalkThroughWindows = kaction->globalShortcut();
359 kaction = qobject_cast<KAction*>( keys->action("Walk Through Windows (Reverse)") );
360 if ( kaction!=0 )
361 cutWalkThroughWindowsReverse = kaction->globalShortcut();
363 delete popup;
364 popup = NULL; // so that it's recreated next time
365 desk_popup = NULL;
369 void Workspace::setupWindowShortcut( Client* c )
371 assert( client_keys_dialog == NULL );
372 #ifdef __GNUC__
373 #warning TODO PORT ME (KGlobalAccel related)
374 #endif
375 // keys->setEnabled( false );
376 // disable_shortcuts_keys->setEnabled( false );
377 // client_keys->setEnabled( false );
378 client_keys_dialog = new ShortcutDialog( c->shortcut().primary());
379 client_keys_client = c;
380 connect( client_keys_dialog, SIGNAL( dialogDone( bool )), SLOT( setupWindowShortcutDone( bool )));
381 QRect r = clientArea( ScreenArea, c );
382 QSize size = client_keys_dialog->sizeHint();
383 QPoint pos = c->pos() + c->clientPos();
384 if( pos.x() + size.width() >= r.right())
385 pos.setX( r.right() - size.width());
386 if( pos.y() + size.height() >= r.bottom())
387 pos.setY( r.bottom() - size.height());
388 client_keys_dialog->move( pos );
389 client_keys_dialog->show();
390 active_popup = client_keys_dialog;
391 active_popup_client = c;
394 void Workspace::setupWindowShortcutDone( bool ok )
396 // keys->setEnabled( true );
397 // disable_shortcuts_keys->setEnabled( true );
398 // client_keys->setEnabled( true );
399 if( ok )
400 client_keys_client->setShortcut( KShortcut( client_keys_dialog->shortcut()).toString());
401 closeActivePopup();
402 delete client_keys_dialog;
403 client_keys_dialog = NULL;
404 client_keys_client = NULL;
407 void Workspace::clientShortcutUpdated( Client* c )
409 QString key = QString::number( c->window());
410 QAction* action = client_keys->action( key.toLatin1().constData() );
411 if( !c->shortcut().isEmpty())
413 action->setShortcuts(c->shortcut());
414 connect(action, SIGNAL(triggered(bool)), c, SLOT(shortcutActivated()));
415 action->setEnabled( true );
417 else
419 delete action;
423 void Workspace::clientPopupActivated( QAction *action )
425 if ( !action->data().isValid() )
426 return;
428 WindowOperation op = static_cast< WindowOperation >( action->data().toInt() );
429 Client* c = active_popup_client ? active_popup_client : active_client;
430 QString type;
431 switch( op )
433 case FullScreenOp:
434 if( !c->isFullScreen() && c->userCanSetFullScreen())
435 type = "fullscreenaltf3";
436 break;
437 case NoBorderOp:
438 if( !c->noBorder() && c->userCanSetNoBorder())
439 type = "noborderaltf3";
440 break;
441 default:
442 break;
444 if( !type.isEmpty())
445 helperDialog( type, c );
446 performWindowOperation( c, op );
450 void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
452 if ( !c )
453 return;
455 if (op == Options::MoveOp || op == Options::UnrestrictedMoveOp )
456 QCursor::setPos( c->geometry().center() );
457 if (op == Options::ResizeOp || op == Options::UnrestrictedResizeOp )
458 QCursor::setPos( c->geometry().bottomRight());
459 switch ( op )
461 case Options::MoveOp:
462 c->performMouseCommand( Options::MouseMove, cursorPos() );
463 break;
464 case Options::UnrestrictedMoveOp:
465 c->performMouseCommand( Options::MouseUnrestrictedMove, cursorPos() );
466 break;
467 case Options::ResizeOp:
468 c->performMouseCommand( Options::MouseResize, cursorPos() );
469 break;
470 case Options::UnrestrictedResizeOp:
471 c->performMouseCommand( Options::MouseUnrestrictedResize, cursorPos() );
472 break;
473 case Options::CloseOp:
474 c->closeWindow();
475 break;
476 case Options::MaximizeOp:
477 c->maximize( c->maximizeMode() == Client::MaximizeFull
478 ? Client::MaximizeRestore : Client::MaximizeFull );
479 break;
480 case Options::HMaximizeOp:
481 c->maximize( c->maximizeMode() ^ Client::MaximizeHorizontal );
482 break;
483 case Options::VMaximizeOp:
484 c->maximize( c->maximizeMode() ^ Client::MaximizeVertical );
485 break;
486 case Options::RestoreOp:
487 c->maximize( Client::MaximizeRestore );
488 break;
489 case Options::MinimizeOp:
490 c->minimize();
491 break;
492 case Options::ShadeOp:
493 c->performMouseCommand( Options::MouseShade, cursorPos());
494 break;
495 case Options::OnAllDesktopsOp:
496 c->setOnAllDesktops( !c->isOnAllDesktops() );
497 break;
498 case Options::FullScreenOp:
499 c->setFullScreen( !c->isFullScreen(), true );
500 break;
501 case Options::NoBorderOp:
502 c->setUserNoBorder( !c->isUserNoBorder());
503 break;
504 case Options::KeepAboveOp:
506 StackingUpdatesBlocker blocker( this );
507 bool was = c->keepAbove();
508 c->setKeepAbove( !c->keepAbove() );
509 if( was && !c->keepAbove())
510 raiseClient( c );
511 break;
513 case Options::KeepBelowOp:
515 StackingUpdatesBlocker blocker( this );
516 bool was = c->keepBelow();
517 c->setKeepBelow( !c->keepBelow() );
518 if( was && !c->keepBelow())
519 lowerClient( c );
520 break;
522 case Options::OperationsOp:
523 c->performMouseCommand( Options::MouseShade, cursorPos());
524 break;
525 case Options::WindowRulesOp:
526 editWindowRules( c, false );
527 break;
528 case Options::ApplicationRulesOp:
529 editWindowRules( c, true );
530 break;
531 case Options::SetupWindowShortcutOp:
532 setupWindowShortcut( c );
533 break;
534 case Options::LowerOp:
535 lowerClient(c);
536 break;
537 case Options::NoOp:
538 break;
543 Performs a mouse command on this client (see options.h)
545 bool Client::performMouseCommand( Options::MouseCommand command, const QPoint &globalPos, bool handled )
547 bool replay = false;
548 switch (command)
550 case Options::MouseRaise:
551 workspace()->raiseClient( this );
552 break;
553 case Options::MouseLower:
554 workspace()->lowerClient( this );
555 break;
556 case Options::MouseShade :
557 toggleShade();
558 cancelShadeHover();
559 break;
560 case Options::MouseSetShade:
561 setShade( ShadeNormal );
562 cancelShadeHover();
563 break;
564 case Options::MouseUnsetShade:
565 setShade( ShadeNone );
566 cancelShadeHover();
567 break;
568 case Options::MouseOperationsMenu:
569 if ( isActive() && options->clickRaise )
570 autoRaise();
571 workspace()->showWindowMenu( globalPos, this );
572 break;
573 case Options::MouseToggleRaiseAndLower:
574 workspace()->raiseOrLowerClient( this );
575 break;
576 case Options::MouseActivateAndRaise:
577 replay = isActive(); // for clickraise mode
578 workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled && replay );
579 workspace()->setActiveScreenMouse( globalPos );
580 break;
581 case Options::MouseActivateAndLower:
582 workspace()->requestFocus( this );
583 workspace()->lowerClient( this );
584 workspace()->setActiveScreenMouse( globalPos );
585 break;
586 case Options::MouseActivate:
587 replay = isActive(); // for clickraise mode
588 workspace()->takeActivity( this, ActivityFocus, handled && replay );
589 workspace()->setActiveScreenMouse( globalPos );
590 break;
591 case Options::MouseActivateRaiseAndPassClick:
592 workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled );
593 workspace()->setActiveScreenMouse( globalPos );
594 replay = true;
595 break;
596 case Options::MouseActivateAndPassClick:
597 workspace()->takeActivity( this, ActivityFocus, handled );
598 workspace()->setActiveScreenMouse( globalPos );
599 replay = true;
600 break;
601 case Options::MouseActivateRaiseAndMove:
602 case Options::MouseActivateRaiseAndUnrestrictedMove:
603 workspace()->raiseClient( this );
604 workspace()->requestFocus( this );
605 workspace()->setActiveScreenMouse( globalPos );
606 if( options->moveMode == Options::Transparent && isMovable())
607 move_faked_activity = workspace()->fakeRequestedActivity( this );
608 // fallthrough
609 case Options::MouseMove:
610 case Options::MouseUnrestrictedMove:
612 if (!isMovable())
613 break;
614 if( moveResizeMode )
615 finishMoveResize( false );
616 mode = PositionCenter;
617 buttonDown = true;
618 moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global
619 invertedMoveOffset = rect().bottomRight() - moveOffset;
620 unrestrictedMoveResize = ( command == Options::MouseActivateRaiseAndUnrestrictedMove
621 || command == Options::MouseUnrestrictedMove );
622 if( !startMoveResize())
623 buttonDown = false;
624 updateCursor();
625 break;
627 case Options::MouseResize:
628 case Options::MouseUnrestrictedResize:
630 if (!isResizable() || isShade())
631 break;
632 if( moveResizeMode )
633 finishMoveResize( false );
634 buttonDown = true;
635 moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global
636 int x = moveOffset.x(), y = moveOffset.y();
637 bool left = x < width() / 3;
638 bool right = x >= 2 * width() / 3;
639 bool top = y < height() / 3;
640 bool bot = y >= 2 * height() / 3;
641 if (top)
642 mode = left ? PositionTopLeft : (right ? PositionTopRight : PositionTop);
643 else if (bot)
644 mode = left ? PositionBottomLeft : (right ? PositionBottomRight : PositionBottom);
645 else
646 mode = (x < width() / 2) ? PositionLeft : PositionRight;
647 invertedMoveOffset = rect().bottomRight() - moveOffset;
648 unrestrictedMoveResize = ( command == Options::MouseUnrestrictedResize );
649 if( !startMoveResize())
650 buttonDown = false;
651 updateCursor();
652 break;
654 case Options::MouseMaximize:
655 maximize( Client::MaximizeFull );
656 break;
657 case Options::MouseRestore:
658 maximize( Client::MaximizeRestore );
659 break;
660 case Options::MouseMinimize:
661 minimize();
662 break;
663 case Options::MouseAbove:
665 StackingUpdatesBlocker blocker( workspace());
666 if( keepBelow())
667 setKeepBelow( false );
668 else
669 setKeepAbove( true );
670 break;
672 case Options::MouseBelow:
674 StackingUpdatesBlocker blocker( workspace());
675 if( keepAbove())
676 setKeepAbove( false );
677 else
678 setKeepBelow( true );
679 break;
681 case Options::MousePreviousDesktop:
682 workspace()->windowToPreviousDesktop( this );
683 break;
684 case Options::MouseNextDesktop:
685 workspace()->windowToNextDesktop( this );
686 break;
687 case Options::MouseOpacityMore:
688 setOpacity( qMin( opacity() + 0.1, 1.0 ));
689 break;
690 case Options::MouseOpacityLess:
691 setOpacity( qMax( opacity() - 0.1, 0.0 ));
692 break;
693 case Options::MouseNothing:
694 replay = true;
695 break;
697 return replay;
700 // KDE4 remove me
701 void Workspace::showWindowMenuAt( unsigned long, int, int )
703 slotWindowOperations();
706 void Workspace::loadEffect( const QString& name )
708 if( effects )
709 static_cast<EffectsHandlerImpl*>(effects)->loadEffect( name );
712 void Workspace::toggleEffect( const QString& name )
714 if( effects )
715 static_cast<EffectsHandlerImpl*>(effects)->toggleEffect( name );
718 void Workspace::unloadEffect( const QString& name )
720 if( effects )
721 static_cast<EffectsHandlerImpl*>(effects)->unloadEffect( name );
724 void Workspace::reloadEffect( const QString& name )
726 if( effects )
727 static_cast<EffectsHandlerImpl*>(effects)->reloadEffect( name );
730 void Workspace::slotActivateAttentionWindow()
732 if( attention_chain.count() > 0 )
733 activateClient( attention_chain.first());
736 void Workspace::slotSwitchDesktopNext()
738 int d = currentDesktop() + 1;
739 if ( d > numberOfDesktops() )
741 if ( options->rollOverDesktops )
743 d = 1;
745 else
747 return;
750 setCurrentDesktop(d);
753 void Workspace::slotSwitchDesktopPrevious()
755 int d = currentDesktop() - 1;
756 if ( d <= 0 )
758 if ( options->rollOverDesktops )
759 d = numberOfDesktops();
760 else
761 return;
763 setCurrentDesktop(d);
766 void Workspace::slotSwitchDesktopRight()
768 int desktop = desktopToRight( currentDesktop(), options->rollOverDesktops);
769 if( desktop == currentDesktop())
770 return;
771 setCurrentDesktop( desktop );
774 void Workspace::slotSwitchDesktopLeft()
776 int desktop = desktopToLeft( currentDesktop(), options->rollOverDesktops);
777 if( desktop == currentDesktop())
778 return;
779 setCurrentDesktop( desktop );
782 void Workspace::slotSwitchDesktopUp()
784 int desktop = desktopUp( currentDesktop(), options->rollOverDesktops);
785 if( desktop == currentDesktop())
786 return;
787 setCurrentDesktop( desktop );
790 void Workspace::slotSwitchDesktopDown()
792 int desktop = desktopDown( currentDesktop(), options->rollOverDesktops);
793 if( desktop == currentDesktop())
794 return;
795 setCurrentDesktop( desktop );
798 void Workspace::slotSwitchToDesktop( int i )
800 setCurrentDesktop( i );
804 void Workspace::slotWindowToDesktop( int i )
806 Client* c = active_popup_client ? active_popup_client : active_client;
807 if( i >= 1 && i <= numberOfDesktops() && c
808 && !c->isDesktop()
809 && !c->isDock()
810 && !c->isTopMenu())
811 sendClientToDesktop( c, i, true );
814 void Workspace::slotSwitchToScreen( int i )
816 setCurrentScreen( i );
819 void Workspace::slotSwitchToNextScreen()
821 slotSwitchToScreen(( activeScreen() + 1 ) % numScreens());
824 void Workspace::slotWindowToScreen( int i )
826 Client* c = active_popup_client ? active_popup_client : active_client;
827 if( i >= 0 && i <= numScreens() && c
828 && !c->isDesktop()
829 && !c->isDock()
830 && !c->isTopMenu())
832 sendClientToScreen( c, i );
836 void Workspace::slotWindowToNextScreen()
838 Client* c = active_popup_client ? active_popup_client : active_client;
839 if( c
840 && !c->isDesktop()
841 && !c->isDock()
842 && !c->isTopMenu())
844 sendClientToScreen( c, ( c->screen() + 1 ) % numScreens());
849 Maximizes the popup client
851 void Workspace::slotWindowMaximize()
853 Client* c = active_popup_client ? active_popup_client : active_client;
854 if ( c )
855 performWindowOperation( c, Options::MaximizeOp );
859 Maximizes the popup client vertically
861 void Workspace::slotWindowMaximizeVertical()
863 Client* c = active_popup_client ? active_popup_client : active_client;
864 if ( c )
865 performWindowOperation( c, Options::VMaximizeOp );
869 Maximizes the popup client horiozontally
871 void Workspace::slotWindowMaximizeHorizontal()
873 Client* c = active_popup_client ? active_popup_client : active_client;
874 if ( c )
875 performWindowOperation( c, Options::HMaximizeOp );
880 Minimizes the popup client
882 void Workspace::slotWindowMinimize()
884 Client* c = active_popup_client ? active_popup_client : active_client;
885 performWindowOperation( c, Options::MinimizeOp );
889 Shades/unshades the popup client respectively
891 void Workspace::slotWindowShade()
893 Client* c = active_popup_client ? active_popup_client : active_client;
894 performWindowOperation( c, Options::ShadeOp );
898 Raises the popup client
900 void Workspace::slotWindowRaise()
902 Client* c = active_popup_client ? active_popup_client : active_client;
903 if ( c )
904 raiseClient( c );
908 Lowers the popup client
910 void Workspace::slotWindowLower()
912 Client* c = active_popup_client ? active_popup_client : active_client;
913 if ( c )
914 lowerClient( c );
918 Does a toggle-raise-and-lower on the popup client;
920 void Workspace::slotWindowRaiseOrLower()
922 Client* c = active_popup_client ? active_popup_client : active_client;
923 if ( c )
924 raiseOrLowerClient( c );
927 void Workspace::slotWindowOnAllDesktops()
929 Client* c = active_popup_client ? active_popup_client : active_client;
930 if( c )
931 c->setOnAllDesktops( !c->isOnAllDesktops());
934 void Workspace::slotWindowFullScreen()
936 Client* c = active_popup_client ? active_popup_client : active_client;
937 if( c )
938 performWindowOperation( c, Options::FullScreenOp );
941 void Workspace::slotWindowNoBorder()
943 Client* c = active_popup_client ? active_popup_client : active_client;
944 if( c )
945 performWindowOperation( c, Options::NoBorderOp );
948 void Workspace::slotWindowAbove()
950 Client* c = active_popup_client ? active_popup_client : active_client;
951 if( c )
952 performWindowOperation( c, Options::KeepAboveOp );
955 void Workspace::slotWindowBelow()
957 Client* c = active_popup_client ? active_popup_client : active_client;
958 if( c )
959 performWindowOperation( c, Options::KeepBelowOp );
961 void Workspace::slotSetupWindowShortcut()
963 Client* c = active_popup_client ? active_popup_client : active_client;
964 if( c )
965 performWindowOperation( c, Options::SetupWindowShortcutOp );
969 Move window to next desktop
971 void Workspace::slotWindowToNextDesktop()
973 windowToNextDesktop( active_popup_client ? active_popup_client : active_client );
976 void Workspace::windowToNextDesktop( Client* c )
978 int d = currentDesktop() + 1;
979 if ( d > numberOfDesktops() )
980 d = 1;
981 if (c && !c->isDesktop()
982 && !c->isDock() && !c->isTopMenu())
984 setClientIsMoving( c );
985 setCurrentDesktop( d );
986 setClientIsMoving( NULL );
991 Move window to previous desktop
993 void Workspace::slotWindowToPreviousDesktop()
995 windowToPreviousDesktop( active_popup_client ? active_popup_client : active_client );
998 void Workspace::windowToPreviousDesktop( Client* c )
1000 int d = currentDesktop() - 1;
1001 if ( d <= 0 )
1002 d = numberOfDesktops();
1003 if (c && !c->isDesktop()
1004 && !c->isDock() && !c->isTopMenu())
1006 setClientIsMoving( c );
1007 setCurrentDesktop( d );
1008 setClientIsMoving( NULL );
1012 void Workspace::slotWindowToDesktopRight()
1014 int d = desktopToRight( currentDesktop(), options->rollOverDesktops);
1015 if( d == currentDesktop())
1016 return;
1017 Client* c = active_popup_client ? active_popup_client : active_client;
1018 if (c && !c->isDesktop()
1019 && !c->isDock() && !c->isTopMenu())
1021 setClientIsMoving( c );
1022 setCurrentDesktop( d );
1023 setClientIsMoving( NULL );
1027 void Workspace::slotWindowToDesktopLeft()
1029 int d = desktopToLeft( currentDesktop(), options->rollOverDesktops);
1030 if( d == currentDesktop())
1031 return;
1032 Client* c = active_popup_client ? active_popup_client : active_client;
1033 if (c && !c->isDesktop()
1034 && !c->isDock() && !c->isTopMenu())
1036 setClientIsMoving( c );
1037 setCurrentDesktop( d );
1038 setClientIsMoving( NULL );
1042 void Workspace::slotWindowToDesktopUp()
1044 int d = desktopUp( currentDesktop(), options->rollOverDesktops);
1045 if( d == currentDesktop())
1046 return;
1047 Client* c = active_popup_client ? active_popup_client : active_client;
1048 if (c && !c->isDesktop()
1049 && !c->isDock() && !c->isTopMenu())
1051 setClientIsMoving( c );
1052 setCurrentDesktop( d );
1053 setClientIsMoving( NULL );
1057 void Workspace::slotWindowToDesktopDown()
1059 int d = desktopDown( currentDesktop(), options->rollOverDesktops);
1060 if( d == currentDesktop())
1061 return;
1062 Client* c = active_popup_client ? active_popup_client : active_client;
1063 if (c && !c->isDesktop()
1064 && !c->isDock() && !c->isTopMenu())
1066 setClientIsMoving( c );
1067 setCurrentDesktop( d );
1068 setClientIsMoving( NULL );
1074 Kill Window feature, similar to xkill
1076 void Workspace::slotKillWindow()
1078 KillWindow kill( this );
1079 kill.start();
1083 Sends the popup client to desktop \a desk
1085 Internal slot for the window operation menu
1087 void Workspace::slotSendToDesktop( QAction *action )
1089 int desk = action->data().toInt();
1090 if ( !active_popup_client )
1091 return;
1092 if ( desk == 0 )
1093 { // the 'on_all_desktops' menu entry
1094 active_popup_client->setOnAllDesktops( !active_popup_client->isOnAllDesktops());
1095 return;
1098 sendClientToDesktop( active_popup_client, desk, false );
1103 Shows the window operations popup menu for the activeClient()
1105 void Workspace::slotWindowOperations()
1107 if ( !active_client )
1108 return;
1109 QPoint pos = active_client->pos() + active_client->clientPos();
1110 showWindowMenu( pos.x(), pos.y(), active_client );
1113 void Workspace::showWindowMenu( const QRect &pos, Client* cl )
1115 if (!KAuthorized::authorizeKAction("kwin_rmb"))
1116 return;
1117 if( !cl )
1118 return;
1119 if( active_popup_client != NULL ) // recursion
1120 return;
1121 if ( cl->isDesktop()
1122 || cl->isDock()
1123 || cl->isTopMenu())
1124 return;
1126 active_popup_client = cl;
1127 QMenu* p = clientPopup();
1128 active_popup = p;
1129 int x = pos.left();
1130 int y = pos.bottom();
1131 if (y == pos.top())
1132 p->exec( QPoint( x, y ) );
1133 else
1135 QRect area = clientArea(ScreenArea, QPoint(x, y), currentDesktop());
1136 clientPopupAboutToShow(); // needed for sizeHint() to be correct :-/
1137 int popupHeight = p->sizeHint().height();
1138 if (y + popupHeight < area.height())
1139 p->exec( QPoint( x, y ) );
1140 else
1141 p->exec( QPoint( x, pos.top() - popupHeight ) );
1143 // active popup may be already changed (e.g. the window shortcut dialog)
1144 if( active_popup == p )
1145 closeActivePopup();
1149 Closes the popup client
1151 void Workspace::slotWindowClose()
1153 if ( tab_box->isVisible())
1154 return;
1155 Client* c = active_popup_client ? active_popup_client : active_client;
1156 performWindowOperation( c, Options::CloseOp );
1160 Starts keyboard move mode for the popup client
1162 void Workspace::slotWindowMove()
1164 Client* c = active_popup_client ? active_popup_client : active_client;
1165 performWindowOperation( c, Options::UnrestrictedMoveOp );
1169 Starts keyboard resize mode for the popup client
1171 void Workspace::slotWindowResize()
1173 Client* c = active_popup_client ? active_popup_client : active_client;
1174 performWindowOperation( c, Options::UnrestrictedResizeOp );
1177 void Client::setShortcut( const QString& _cut )
1179 QString cut = rules()->checkShortcut( _cut );
1180 if( cut.isEmpty())
1181 return setShortcutInternal( KShortcut());
1182 // Format:
1183 // base+(abcdef)<space>base+(abcdef)
1184 // E.g. Alt+Ctrl+(ABCDEF) Win+X,Win+(ABCDEF)
1185 if( !cut.contains( '(' ) && !cut.contains( ')' ) && !cut.contains( ' ' ))
1187 if( workspace()->shortcutAvailable( KShortcut( cut ), this ))
1188 setShortcutInternal( KShortcut( cut ));
1189 else
1190 setShortcutInternal( KShortcut());
1191 return;
1193 QList< KShortcut > keys;
1194 QStringList groups = cut.split( ' ');
1195 for( QStringList::ConstIterator it = groups.begin();
1196 it != groups.end();
1197 ++it )
1199 QRegExp reg( "(.*\\+)\\((.*)\\)" );
1200 if( reg.indexIn( *it ) > -1 )
1202 QString base = reg.cap( 1 );
1203 QString list = reg.cap( 2 );
1204 for( int i = 0;
1205 i < list.length();
1206 ++i )
1208 KShortcut c( base + list[ i ] );
1209 if( !c.isEmpty())
1210 keys.append( c );
1214 for( QList< KShortcut >::ConstIterator it = keys.begin();
1215 it != keys.end();
1216 ++it )
1218 if( _shortcut == *it ) // current one is in the list
1219 return;
1221 for( QList< KShortcut >::ConstIterator it = keys.begin();
1222 it != keys.end();
1223 ++it )
1225 if( workspace()->shortcutAvailable( *it, this ))
1227 setShortcutInternal( *it );
1228 return;
1231 setShortcutInternal( KShortcut());
1234 void Client::setShortcutInternal( const KShortcut& cut )
1236 if( _shortcut == cut )
1237 return;
1238 _shortcut = cut;
1239 updateCaption();
1240 workspace()->clientShortcutUpdated( this );
1243 bool Workspace::shortcutAvailable( const KShortcut& cut, Client* ignore ) const
1245 // TODO check global shortcuts etc.
1246 for( ClientList::ConstIterator it = clients.begin();
1247 it != clients.end();
1248 ++it )
1250 if( (*it) != ignore && (*it)->shortcut() == cut )
1251 return false;
1253 return true;
1256 } // namespace