2007-11-27 22:40:25 +03:00
/********************************************************************
2007-04-29 21:35:43 +04:00
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 >
2007-11-27 22:40:25 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-29 21:35:43 +04:00
/*
This file contains things relevant to direct user actions , such as
responses to global keyboard shortcuts , or selecting actions
from the window operations menu .
*/
2012-03-23 11:03:09 +04:00
///////////////////////////////////////////////////////////////////////////////
// NOTE: if you change the menu, keep kde-workspace/libs/taskmanager/taskactions.cpp in sync
//////////////////////////////////////////////////////////////////////////////
2012-08-19 14:00:53 +04:00
# include "useractions.h"
2013-02-26 11:45:44 +04:00
# include "cursor.h"
2007-04-29 21:35:43 +04:00
# include "client.h"
2017-09-24 11:15:13 +03:00
# include "composite.h"
2013-07-10 13:45:51 +04:00
# include "input.h"
2007-04-29 21:35:43 +04:00
# include "workspace.h"
# include "effects.h"
2017-07-20 20:14:07 +03:00
# include "platform.h"
2013-04-03 14:19:27 +04:00
# include "screens.h"
2018-02-16 22:55:06 +03:00
# include "shell_client.h"
2012-11-16 11:23:47 +04:00
# include "virtualdesktops.h"
2012-08-31 15:28:31 +04:00
# include "scripting/scripting.h"
2012-02-26 14:38:16 +04:00
# ifdef KWIN_BUILD_ACTIVITIES
2013-04-04 18:14:12 +04:00
# include "activities.h"
2014-02-04 12:36:15 +04:00
# include <kactivities/info.h>
2012-02-26 14:38:16 +04:00
# endif
2017-01-11 12:21:03 +03:00
# include "appmenu.h"
2010-05-12 00:30:20 +04:00
2014-03-17 19:24:10 +04:00
# include <KProcess>
2012-08-19 14:00:53 +04:00
2013-08-28 14:27:09 +04:00
# include <QAction>
2013-03-25 00:57:26 +04:00
# include <QCheckBox>
2013-08-19 13:42:16 +04:00
# include <QtConcurrentRun>
2014-05-01 18:22:04 +04:00
# include <QPointer>
2007-04-29 21:35:43 +04:00
# include <QPushButton>
2014-03-17 19:24:10 +04:00
# include <KGlobalAccel>
# include <KLocalizedString>
2007-04-29 21:35:43 +04:00
# include <kconfig.h>
# include <QRegExp>
# include <QMenu>
2014-02-03 16:40:47 +04:00
# include <QWidgetAction>
2007-04-29 21:35:43 +04:00
# include <kauthorized.h>
# include "killwindow.h"
2011-06-30 15:02:30 +04:00
# ifdef KWIN_BUILD_TABBOX
2007-04-29 21:35:43 +04:00
# include "tabbox.h"
2011-06-30 15:02:30 +04:00
# endif
2007-04-29 21:35:43 +04:00
namespace KWin
{
2012-08-19 14:00:53 +04:00
UserActionsMenu : : UserActionsMenu ( QObject * parent )
: QObject ( parent )
, m_menu ( NULL )
, m_desktopMenu ( NULL )
, m_screenMenu ( NULL )
, m_activityMenu ( NULL )
, m_addTabsMenu ( NULL )
, m_switchToTabMenu ( NULL )
2012-08-31 15:28:31 +04:00
, m_scriptsMenu ( NULL )
2012-08-19 14:00:53 +04:00
, m_resizeOperation ( NULL )
, m_moveOperation ( NULL )
, m_maximizeOperation ( NULL )
, m_shadeOperation ( NULL )
, m_keepAboveOperation ( NULL )
, m_keepBelowOperation ( NULL )
, m_fullScreenOperation ( NULL )
, m_noBorderOperation ( NULL )
, m_minimizeOperation ( NULL )
, m_closeOperation ( NULL )
, m_removeFromTabGroup ( NULL )
, m_closeTabGroup ( NULL )
2015-03-06 13:33:51 +03:00
, m_client ( QWeakPointer < AbstractClient > ( ) )
2012-08-19 14:00:53 +04:00
{
}
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
UserActionsMenu : : ~ UserActionsMenu ( )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
discard ( ) ;
}
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
bool UserActionsMenu : : isShown ( ) const
{
return m_menu & & m_menu - > isVisible ( ) ;
}
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
bool UserActionsMenu : : hasClient ( ) const
{
2012-12-21 00:26:33 +04:00
return ! m_client . isNull ( ) & & isShown ( ) ;
2012-08-19 14:00:53 +04:00
}
2012-03-23 11:03:09 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : close ( )
{
if ( ! m_menu ) {
return ;
}
m_menu - > close ( ) ;
2012-12-21 00:26:33 +04:00
m_client . clear ( ) ;
2012-08-19 14:00:53 +04:00
}
2012-03-23 11:03:09 +04:00
2015-03-06 13:33:51 +03:00
bool UserActionsMenu : : isMenuClient ( const AbstractClient * c ) const
2012-08-19 14:00:53 +04:00
{
if ( ! c | | m_client . isNull ( ) ) {
return false ;
}
return c = = m_client . data ( ) ;
}
2011-01-30 17:34:42 +03:00
2015-03-06 13:33:51 +03:00
void UserActionsMenu : : show ( const QRect & pos , const QWeakPointer < AbstractClient > & cl )
2012-08-19 14:00:53 +04:00
{
2016-08-30 14:52:41 +03:00
if ( ! KAuthorized : : authorizeAction ( QStringLiteral ( " kwin_rmb " ) ) )
2012-08-19 14:00:53 +04:00
return ;
if ( cl . isNull ( ) )
return ;
2012-12-21 00:26:33 +04:00
if ( isShown ( ) ) // recursion
2012-08-19 14:00:53 +04:00
return ;
if ( cl . data ( ) - > isDesktop ( )
| | cl . data ( ) - > isDock ( ) )
return ;
2011-01-30 17:34:42 +03:00
2012-08-19 14:00:53 +04:00
m_client = cl ;
init ( ) ;
Workspace * ws = Workspace : : self ( ) ;
int x = pos . left ( ) ;
int y = pos . bottom ( ) ;
2015-11-09 15:57:41 +03:00
const bool needsPopup = kwinApp ( ) - > shouldUseWaylandForCompositing ( ) ;
2013-03-25 00:57:26 +04:00
if ( y = = pos . top ( ) ) {
m_client . data ( ) - > blockActivityUpdates ( true ) ;
2015-11-09 15:57:41 +03:00
if ( needsPopup ) {
m_menu - > popup ( QPoint ( x , y ) ) ;
} else {
m_menu - > exec ( QPoint ( x , y ) ) ;
}
2013-03-25 00:57:26 +04:00
if ( ! m_client . isNull ( ) )
m_client . data ( ) - > blockActivityUpdates ( false ) ;
}
2012-08-19 14:00:53 +04:00
else {
2013-03-25 00:57:26 +04:00
m_client . data ( ) - > blockActivityUpdates ( true ) ;
2012-11-16 11:23:47 +04:00
QRect area = ws - > clientArea ( ScreenArea , QPoint ( x , y ) , VirtualDesktopManager : : self ( ) - > current ( ) ) ;
2012-08-19 14:00:53 +04:00
menuAboutToShow ( ) ; // needed for sizeHint() to be correct :-/
int popupHeight = m_menu - > sizeHint ( ) . height ( ) ;
2015-11-09 15:57:41 +03:00
if ( y + popupHeight < area . height ( ) ) {
if ( needsPopup ) {
m_menu - > popup ( QPoint ( x , y ) ) ;
} else {
m_menu - > exec ( QPoint ( x , y ) ) ;
}
} else {
if ( needsPopup ) {
m_menu - > popup ( QPoint ( x , pos . top ( ) - popupHeight ) ) ;
} else {
m_menu - > exec ( QPoint ( x , pos . top ( ) - popupHeight ) ) ;
}
}
2013-03-25 00:57:26 +04:00
if ( ! m_client . isNull ( ) )
m_client . data ( ) - > blockActivityUpdates ( true ) ;
2012-08-19 14:00:53 +04:00
}
}
2011-01-30 17:34:42 +03:00
2015-09-22 15:44:25 +03:00
void UserActionsMenu : : grabInput ( )
{
m_menu - > windowHandle ( ) - > setMouseGrabEnabled ( true ) ;
m_menu - > windowHandle ( ) - > setKeyboardGrabEnabled ( true ) ;
}
2015-03-06 13:33:51 +03:00
void UserActionsMenu : : helperDialog ( const QString & message , const QWeakPointer < AbstractClient > & c )
2012-08-19 14:00:53 +04:00
{
QStringList args ;
QString type ;
2013-08-19 13:42:16 +04:00
auto shortcut = [ ] ( const QString & name ) {
2013-12-10 13:01:13 +04:00
QAction * action = Workspace : : self ( ) - > findChild < QAction * > ( name ) ;
2012-08-19 14:00:53 +04:00
assert ( action ! = NULL ) ;
2013-08-19 13:42:16 +04:00
const auto shortcuts = KGlobalAccel : : self ( ) - > shortcut ( action ) ;
return QStringLiteral ( " %1 (%2) " ) . arg ( action - > text ( ) )
. arg ( shortcuts . isEmpty ( ) ? QString ( ) : shortcuts . first ( ) . toString ( QKeySequence : : NativeText ) ) ;
} ;
if ( message = = QStringLiteral ( " noborderaltf3 " ) ) {
2013-07-23 09:02:52 +04:00
args < < QStringLiteral ( " --msgbox " ) < < i18n (
2012-08-19 14:00:53 +04:00
" You have selected to show a window without its border. \n "
" Without the border, you will not be able to enable the border "
" again using the mouse: use the window operations menu instead, "
" activated using the %1 keyboard shortcut. " ,
2013-08-19 13:42:16 +04:00
shortcut ( QStringLiteral ( " Window Operations Menu " ) ) ) ;
2013-07-23 09:02:52 +04:00
type = QStringLiteral ( " altf3warning " ) ;
2015-11-05 17:14:06 +03:00
} else if ( message = = QLatin1String ( " fullscreenaltf3 " ) ) {
2013-07-23 09:02:52 +04:00
args < < QStringLiteral ( " --msgbox " ) < < i18n (
2012-08-19 14:00:53 +04:00
" You have selected to show a window in fullscreen mode. \n "
" If the application itself does not have an option to turn the fullscreen "
" mode off you will not be able to disable it "
" again using the mouse: use the window operations menu instead, "
" activated using the %1 keyboard shortcut. " ,
2013-08-19 13:42:16 +04:00
shortcut ( QStringLiteral ( " Window Operations Menu " ) ) ) ;
2013-07-23 09:02:52 +04:00
type = QStringLiteral ( " altf3warning " ) ;
2012-08-19 14:00:53 +04:00
} else
abort ( ) ;
if ( ! type . isEmpty ( ) ) {
2013-07-23 09:02:52 +04:00
KConfig cfg ( QStringLiteral ( " kwin_dialogsrc " ) ) ;
2012-08-19 14:00:53 +04:00
KConfigGroup cg ( & cfg , " Notification Messages " ) ; // Depends on KMessageBox
if ( ! cg . readEntry ( type , true ) )
return ;
2015-11-05 17:14:06 +03:00
args < < QStringLiteral ( " --dontagain " ) < < QLatin1String ( " kwin_dialogsrc: " ) + type ;
2012-08-19 14:00:53 +04:00
}
if ( ! c . isNull ( ) )
2016-05-02 18:47:39 +03:00
args < < QStringLiteral ( " --embed " ) < < QString : : number ( c . data ( ) - > windowId ( ) ) ;
2013-08-19 13:42:16 +04:00
QtConcurrent : : run ( [ args ] ( ) {
KProcess : : startDetached ( QStringLiteral ( " kdialog " ) , args ) ;
} ) ;
2012-08-19 14:00:53 +04:00
}
2012-03-23 11:03:09 +04:00
2011-01-30 17:34:42 +03:00
2012-08-19 14:00:53 +04:00
QStringList configModules ( bool controlCenter )
{
QStringList args ;
2013-07-23 09:02:52 +04:00
args < < QStringLiteral ( " kwindecoration " ) ;
2012-08-19 14:00:53 +04:00
if ( controlCenter )
2013-07-23 09:02:52 +04:00
args < < QStringLiteral ( " kwinoptions " ) ;
else if ( KAuthorized : : authorizeControlModule ( QStringLiteral ( " kde-kwinoptions.desktop " ) ) )
args < < QStringLiteral ( " kwinactions " ) < < QStringLiteral ( " kwinfocus " ) < < QStringLiteral ( " kwinmoving " ) < < QStringLiteral ( " kwinadvanced " )
2014-03-10 17:55:04 +04:00
< < QStringLiteral ( " kwinrules " ) < < QStringLiteral ( " kwincompositing " ) < < QStringLiteral ( " kwineffects " )
2012-08-19 14:00:53 +04:00
# ifdef KWIN_BUILD_TABBOX
2013-07-23 09:02:52 +04:00
< < QStringLiteral ( " kwintabbox " )
2012-08-19 14:00:53 +04:00
# endif
2013-07-23 09:02:52 +04:00
< < QStringLiteral ( " kwinscreenedges " )
< < QStringLiteral ( " kwinscripts " )
2012-08-19 14:00:53 +04:00
;
return args ;
}
2012-03-23 11:03:09 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : init ( )
{
if ( m_menu ) {
return ;
}
m_menu = new QMenu ;
2014-03-27 19:48:25 +04:00
connect ( m_menu , & QMenu : : aboutToShow , this , & UserActionsMenu : : menuAboutToShow ) ;
connect ( m_menu , & QMenu : : triggered , this , & UserActionsMenu : : slotWindowOperation , Qt : : QueuedConnection ) ;
2012-08-19 14:00:53 +04:00
QMenu * advancedMenu = new QMenu ( m_menu ) ;
2013-10-14 09:25:27 +04:00
connect ( advancedMenu , & QMenu : : aboutToShow , [ this , advancedMenu ] ( ) {
advancedMenu - > setPalette ( m_client . data ( ) - > palette ( ) ) ;
} ) ;
2012-08-19 14:00:53 +04:00
2013-09-06 16:56:16 +04:00
auto setShortcut = [ ] ( QAction * action , const QString & actionName ) {
2013-12-10 13:01:13 +04:00
const auto shortcuts = KGlobalAccel : : self ( ) - > shortcut ( Workspace : : self ( ) - > findChild < QAction * > ( actionName ) ) ;
2013-09-06 16:56:16 +04:00
if ( ! shortcuts . isEmpty ( ) ) {
action - > setShortcut ( shortcuts . first ( ) ) ;
}
} ;
2012-08-19 14:00:53 +04:00
m_moveOperation = advancedMenu - > addAction ( i18n ( " &Move " ) ) ;
2013-09-06 17:12:35 +04:00
m_moveOperation - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " transform-move " ) ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_moveOperation , QStringLiteral ( " Window Move " ) ) ;
2012-08-19 14:00:53 +04:00
m_moveOperation - > setData ( Options : : UnrestrictedMoveOp ) ;
2015-09-28 10:28:37 +03:00
m_resizeOperation = advancedMenu - > addAction ( i18n ( " &Resize " ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_resizeOperation , QStringLiteral ( " Window Resize " ) ) ;
2012-08-19 14:00:53 +04:00
m_resizeOperation - > setData ( Options : : ResizeOp ) ;
m_keepAboveOperation = advancedMenu - > addAction ( i18n ( " Keep &Above Others " ) ) ;
2014-10-02 19:43:29 +04:00
m_keepAboveOperation - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " go-up " ) ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_keepAboveOperation , QStringLiteral ( " Window Above Other Windows " ) ) ;
2012-08-19 14:00:53 +04:00
m_keepAboveOperation - > setCheckable ( true ) ;
m_keepAboveOperation - > setData ( Options : : KeepAboveOp ) ;
m_keepBelowOperation = advancedMenu - > addAction ( i18n ( " Keep &Below Others " ) ) ;
2013-09-06 17:12:35 +04:00
m_keepBelowOperation - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " go-down " ) ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_keepBelowOperation , QStringLiteral ( " Window Below Other Windows " ) ) ;
2012-08-19 14:00:53 +04:00
m_keepBelowOperation - > setCheckable ( true ) ;
m_keepBelowOperation - > setData ( Options : : KeepBelowOp ) ;
m_fullScreenOperation = advancedMenu - > addAction ( i18n ( " &Fullscreen " ) ) ;
2013-09-06 17:12:35 +04:00
m_fullScreenOperation - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " view-fullscreen " ) ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_fullScreenOperation , QStringLiteral ( " Window Fullscreen " ) ) ;
2012-08-19 14:00:53 +04:00
m_fullScreenOperation - > setCheckable ( true ) ;
m_fullScreenOperation - > setData ( Options : : FullScreenOp ) ;
2015-09-28 10:28:37 +03:00
m_shadeOperation = advancedMenu - > addAction ( i18n ( " &Shade " ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_shadeOperation , QStringLiteral ( " Window Shade " ) ) ;
2012-08-19 14:00:53 +04:00
m_shadeOperation - > setCheckable ( true ) ;
m_shadeOperation - > setData ( Options : : ShadeOp ) ;
m_noBorderOperation = advancedMenu - > addAction ( i18n ( " &No Border " ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_noBorderOperation , QStringLiteral ( " Window No Border " ) ) ;
2012-08-19 14:00:53 +04:00
m_noBorderOperation - > setCheckable ( true ) ;
m_noBorderOperation - > setData ( Options : : NoBorderOp ) ;
advancedMenu - > addSeparator ( ) ;
2015-09-28 10:28:37 +03:00
m_shortcutOperation = advancedMenu - > addAction ( i18n ( " Window Short&cut... " ) ) ;
2015-02-06 18:55:44 +03:00
m_shortcutOperation - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " configure-shortcuts " ) ) ) ;
setShortcut ( m_shortcutOperation , QStringLiteral ( " Setup Window Shortcut " ) ) ;
m_shortcutOperation - > setData ( Options : : SetupWindowShortcutOp ) ;
2012-08-19 14:00:53 +04:00
2015-09-28 10:28:37 +03:00
QAction * action = advancedMenu - > addAction ( i18n ( " Special &Window Settings... " ) ) ;
2013-09-06 17:12:35 +04:00
action - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " preferences-system-windows-actions " ) ) ) ;
2012-08-19 14:00:53 +04:00
action - > setData ( Options : : WindowRulesOp ) ;
2018-02-16 22:55:06 +03:00
m_rulesOperation = action ;
2012-08-19 14:00:53 +04:00
action = advancedMenu - > addAction ( i18n ( " S&pecial Application Settings... " ) ) ;
2013-09-06 17:12:35 +04:00
action - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " preferences-system-windows-actions " ) ) ) ;
2012-08-19 14:00:53 +04:00
action - > setData ( Options : : ApplicationRulesOp ) ;
2018-02-16 22:55:06 +03:00
m_applicationRulesOperation = action ;
2016-01-29 13:24:18 +03:00
if ( ! kwinApp ( ) - > config ( ) - > isImmutable ( ) & &
2012-08-19 14:00:53 +04:00
! KAuthorized : : authorizeControlModules ( configModules ( true ) ) . isEmpty ( ) ) {
advancedMenu - > addSeparator ( ) ;
action = advancedMenu - > addAction ( i18nc ( " Entry in context menu of window decoration to open the configuration module of KWin " ,
2015-09-28 10:28:37 +03:00
" Window Manager S&ettings... " ) ) ;
2013-09-06 17:12:35 +04:00
action - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " configure " ) ) ) ;
2014-03-27 19:48:25 +04:00
connect ( action , & QAction : : triggered , this ,
2015-07-07 18:35:57 +03:00
[ this ] ( ) {
2014-03-27 19:48:25 +04:00
// opens the KWin configuration
QStringList args ;
2016-10-26 09:10:04 +03:00
args < < QStringLiteral ( " --icon " ) < < QStringLiteral ( " preferences-system-windows " ) ;
const QString path = QStandardPaths : : locate ( QStandardPaths : : GenericDataLocation ,
QStringLiteral ( " kservices5/kwinfocus.desktop " ) ) ;
if ( ! path . isEmpty ( ) ) {
args < < QStringLiteral ( " --desktopfile " ) < < path ;
}
args < < configModules ( false ) ;
2015-12-15 12:22:03 +03:00
QProcess * p = new Process ( this ) ;
2015-07-07 18:35:57 +03:00
p - > setArguments ( args ) ;
p - > setProcessEnvironment ( kwinApp ( ) - > processStartupEnvironment ( ) ) ;
p - > setProgram ( QStringLiteral ( " kcmshell5 " ) ) ;
2015-08-23 21:56:10 +03:00
connect ( p , static_cast < void ( QProcess : : * ) ( int , QProcess : : ExitStatus ) > ( & QProcess : : finished ) , p , & QProcess : : deleteLater ) ;
2015-07-07 18:35:57 +03:00
connect ( p , static_cast < void ( QProcess : : * ) ( QProcess : : ProcessError ) > ( & QProcess : : error ) , this ,
[ p ] ( QProcess : : ProcessError e ) {
if ( e = = QProcess : : FailedToStart ) {
qCDebug ( KWIN_CORE ) < < " Failed to start kcmshell5 " ;
}
}
) ;
p - > start ( ) ;
2014-03-27 19:48:25 +04:00
}
) ;
2012-08-19 14:00:53 +04:00
}
2011-01-30 17:34:42 +03:00
2012-08-19 14:00:53 +04:00
m_minimizeOperation = m_menu - > addAction ( i18n ( " Mi&nimize " ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_minimizeOperation , QStringLiteral ( " Window Minimize " ) ) ;
2012-08-19 14:00:53 +04:00
m_minimizeOperation - > setData ( Options : : MinimizeOp ) ;
m_maximizeOperation = m_menu - > addAction ( i18n ( " Ma&ximize " ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_maximizeOperation , QStringLiteral ( " Window Maximize " ) ) ;
2012-08-19 14:00:53 +04:00
m_maximizeOperation - > setCheckable ( true ) ;
m_maximizeOperation - > setData ( Options : : MaximizeOp ) ;
m_menu - > addSeparator ( ) ;
// Actions for window tabbing
2014-07-22 15:11:19 +04:00
if ( false ) {
2012-08-19 14:00:53 +04:00
m_removeFromTabGroup = m_menu - > addAction ( i18n ( " &Untab " ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_removeFromTabGroup , QStringLiteral ( " Untab " ) ) ;
2012-08-19 14:00:53 +04:00
m_removeFromTabGroup - > setData ( Options : : RemoveTabFromGroupOp ) ;
2009-11-15 06:24:04 +03:00
2012-08-19 14:00:53 +04:00
m_closeTabGroup = m_menu - > addAction ( i18n ( " Close Entire &Group " ) ) ;
2013-09-06 17:12:35 +04:00
m_closeTabGroup - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " window-close " ) ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_closeTabGroup , QStringLiteral ( " Close TabGroup " ) ) ;
2012-08-19 14:00:53 +04:00
m_closeTabGroup - > setData ( Options : : CloseTabGroupOp ) ;
2010-05-07 20:03:14 +04:00
2012-08-19 14:00:53 +04:00
m_menu - > addSeparator ( ) ;
}
2009-04-27 21:30:33 +04:00
2012-08-19 14:00:53 +04:00
m_menu - > addSeparator ( ) ;
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
action = m_menu - > addMenu ( advancedMenu ) ;
2013-05-15 22:55:49 +04:00
action - > setText ( i18n ( " &More Actions " ) ) ;
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
m_menu - > addSeparator ( ) ;
2008-08-07 15:51:20 +04:00
2012-08-19 14:00:53 +04:00
m_closeOperation = m_menu - > addAction ( i18n ( " &Close " ) ) ;
2013-09-06 17:12:35 +04:00
m_closeOperation - > setIcon ( QIcon : : fromTheme ( QStringLiteral ( " window-close " ) ) ) ;
2013-09-06 16:56:16 +04:00
setShortcut ( m_closeOperation , QStringLiteral ( " Window Close " ) ) ;
2012-08-19 14:00:53 +04:00
m_closeOperation - > setData ( Options : : CloseOp ) ;
2011-08-19 23:53:30 +04:00
}
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : discard ( )
2011-08-19 23:53:30 +04:00
{
2012-08-19 14:00:53 +04:00
delete m_menu ;
m_menu = NULL ;
m_desktopMenu = NULL ;
m_screenMenu = NULL ;
m_activityMenu = NULL ;
m_switchToTabMenu = NULL ;
m_addTabsMenu = NULL ;
2012-08-31 15:28:31 +04:00
m_scriptsMenu = NULL ;
2011-08-19 23:53:30 +04:00
}
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : menuAboutToShow ( )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
if ( m_client . isNull ( ) | | ! m_menu )
2007-04-29 21:35:43 +04:00
return ;
2012-11-16 11:23:47 +04:00
if ( VirtualDesktopManager : : self ( ) - > count ( ) = = 1 ) {
2012-08-19 14:00:53 +04:00
delete m_desktopMenu ;
m_desktopMenu = 0 ;
2011-01-30 17:34:42 +03:00
} else {
2007-04-29 21:35:43 +04:00
initDesktopPopup ( ) ;
2011-01-30 17:34:42 +03:00
}
2013-04-03 14:19:27 +04:00
if ( screens ( ) - > count ( ) = = 1 | | ( ! m_client . data ( ) - > isMovable ( ) & & ! m_client . data ( ) - > isMovableAcrossScreens ( ) ) ) {
2012-08-19 14:00:53 +04:00
delete m_screenMenu ;
m_screenMenu = NULL ;
2012-08-18 00:32:06 +04:00
} else {
initScreenPopup ( ) ;
}
2007-04-29 21:35:43 +04:00
2013-10-14 09:25:27 +04:00
m_menu - > setPalette ( m_client . data ( ) - > palette ( ) ) ;
2012-08-19 14:00:53 +04:00
m_resizeOperation - > setEnabled ( m_client . data ( ) - > isResizable ( ) ) ;
m_moveOperation - > setEnabled ( m_client . data ( ) - > isMovableAcrossScreens ( ) ) ;
m_maximizeOperation - > setEnabled ( m_client . data ( ) - > isMaximizable ( ) ) ;
2014-12-02 15:49:08 +03:00
m_maximizeOperation - > setChecked ( m_client . data ( ) - > maximizeMode ( ) = = MaximizeFull ) ;
2012-08-19 14:00:53 +04:00
m_shadeOperation - > setEnabled ( m_client . data ( ) - > isShadeable ( ) ) ;
m_shadeOperation - > setChecked ( m_client . data ( ) - > shadeMode ( ) ! = ShadeNone ) ;
m_keepAboveOperation - > setChecked ( m_client . data ( ) - > keepAbove ( ) ) ;
m_keepBelowOperation - > setChecked ( m_client . data ( ) - > keepBelow ( ) ) ;
m_fullScreenOperation - > setEnabled ( m_client . data ( ) - > userCanSetFullScreen ( ) ) ;
m_fullScreenOperation - > setChecked ( m_client . data ( ) - > isFullScreen ( ) ) ;
m_noBorderOperation - > setEnabled ( m_client . data ( ) - > userCanSetNoBorder ( ) ) ;
m_noBorderOperation - > setChecked ( m_client . data ( ) - > noBorder ( ) ) ;
m_minimizeOperation - > setEnabled ( m_client . data ( ) - > isMinimizable ( ) ) ;
m_closeOperation - > setEnabled ( m_client . data ( ) - > isCloseable ( ) ) ;
2015-02-06 18:55:44 +03:00
m_shortcutOperation - > setEnabled ( m_client . data ( ) - > rules ( ) - > checkShortcut ( QString ( ) ) . isNull ( ) ) ;
2012-08-19 14:00:53 +04:00
2014-07-22 15:11:19 +04:00
if ( false ) {
2012-01-12 10:42:55 +04:00
initTabbingPopups ( ) ;
2013-10-14 09:25:27 +04:00
m_addTabsMenu - > setPalette ( m_client . data ( ) - > palette ( ) ) ;
2012-01-12 10:42:55 +04:00
} else {
2012-08-19 14:00:53 +04:00
delete m_addTabsMenu ;
m_addTabsMenu = 0 ;
2011-01-30 17:34:42 +03:00
}
2012-08-31 15:28:31 +04:00
// drop the existing scripts menu
delete m_scriptsMenu ;
m_scriptsMenu = NULL ;
// ask scripts whether they want to add entries for the given Client
2013-04-04 11:11:17 +04:00
QList < QAction * > scriptActions = Scripting : : self ( ) - > actionsForUserActionMenu ( m_client . data ( ) , m_scriptsMenu ) ;
2012-08-31 15:28:31 +04:00
if ( ! scriptActions . isEmpty ( ) ) {
2015-09-22 15:44:25 +03:00
m_scriptsMenu = new QMenu ( m_menu ) ;
m_scriptsMenu - > setPalette ( m_client . data ( ) - > palette ( ) ) ;
2012-08-31 15:28:31 +04:00
m_scriptsMenu - > addActions ( scriptActions ) ;
QAction * action = m_scriptsMenu - > menuAction ( ) ;
// set it as the first item after desktop
m_menu - > insertAction ( m_closeOperation , action ) ;
action - > setText ( i18n ( " &Extensions " ) ) ;
}
2014-06-01 20:55:36 +04:00
2018-02-16 22:55:06 +03:00
// disable rules for Wayland windows - dialog is X11 only
if ( qobject_cast < ShellClient * > ( m_client . data ( ) ) ) {
m_rulesOperation - > setEnabled ( false ) ;
m_applicationRulesOperation - > setEnabled ( false ) ;
} else {
m_rulesOperation - > setEnabled ( true ) ;
m_applicationRulesOperation - > setEnabled ( true ) ;
}
2014-06-01 20:55:36 +04:00
showHideActivityMenu ( ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : showHideActivityMenu ( )
2012-04-12 23:52:44 +04:00
{
# ifdef KWIN_BUILD_ACTIVITIES
2015-07-07 12:48:42 +03:00
if ( ! Activities : : self ( ) ) {
return ;
}
2013-04-04 18:14:12 +04:00
const QStringList & openActivities_ = Activities : : self ( ) - > running ( ) ;
2014-12-05 13:42:15 +03:00
qCDebug ( KWIN_CORE ) < < " activities: " < < openActivities_ . size ( ) ;
2012-04-12 23:52:44 +04:00
if ( openActivities_ . size ( ) < 2 ) {
2012-08-19 14:00:53 +04:00
delete m_activityMenu ;
m_activityMenu = 0 ;
2012-04-12 23:52:44 +04:00
} else {
initActivityPopup ( ) ;
}
# endif
}
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : selectPopupClientTab ( QAction * action )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
if ( ! ( ! m_client . isNull ( ) & & m_client . data ( ) - > tabGroup ( ) ) | | ! action - > data ( ) . isValid ( ) )
2012-01-12 10:42:55 +04:00
return ;
if ( Client * other = action - > data ( ) . value < Client * > ( ) ) {
2012-08-19 14:00:53 +04:00
m_client . data ( ) - > tabGroup ( ) - > setCurrent ( other ) ;
2009-11-15 06:24:04 +03:00
return ;
}
2012-01-12 10:42:55 +04:00
// failed conversion, try "1" & "2", being prev and next
int direction = action - > data ( ) . toInt ( ) ;
if ( direction = = 1 )
2012-08-19 14:00:53 +04:00
m_client . data ( ) - > tabGroup ( ) - > activatePrev ( ) ;
2012-01-12 10:42:55 +04:00
else if ( direction = = 2 )
2012-08-19 14:00:53 +04:00
m_client . data ( ) - > tabGroup ( ) - > activateNext ( ) ;
2011-01-30 17:34:42 +03:00
}
2009-11-15 06:24:04 +03:00
2012-01-12 10:42:55 +04:00
static QString shortCaption ( const QString & s )
2011-01-30 17:34:42 +03:00
{
2012-01-12 10:42:55 +04:00
if ( s . length ( ) < 64 )
return s ;
QString ss = s ;
2013-07-23 09:02:52 +04:00
return ss . replace ( 32 , s . length ( ) - 64 , QStringLiteral ( " ... " ) ) ;
2012-01-12 10:42:55 +04:00
}
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : rebuildTabListPopup ( )
2012-01-12 10:42:55 +04:00
{
2012-08-19 14:00:53 +04:00
Q_ASSERT ( m_switchToTabMenu ) ;
2012-01-12 10:42:55 +04:00
2012-08-19 14:00:53 +04:00
m_switchToTabMenu - > clear ( ) ;
2012-01-12 10:42:55 +04:00
// whatever happens "0x1" and "0x2" are no heap positions ;-)
2012-08-19 14:00:53 +04:00
m_switchToTabMenu - > addAction ( i18nc ( " Switch to tab -> Previous " , " Previous " ) ) - > setData ( 1 ) ;
m_switchToTabMenu - > addAction ( i18nc ( " Switch to tab -> Next " , " Next " ) ) - > setData ( 2 ) ;
2012-01-12 10:42:55 +04:00
2012-08-19 14:00:53 +04:00
m_switchToTabMenu - > addSeparator ( ) ;
2012-01-12 10:42:55 +04:00
2012-08-19 14:00:53 +04:00
for ( QList < Client * > : : const_iterator i = m_client . data ( ) - > tabGroup ( ) - > clients ( ) . constBegin ( ) ,
end = m_client . data ( ) - > tabGroup ( ) - > clients ( ) . constEnd ( ) ; i ! = end ; + + i ) {
if ( ( * i ) - > noBorder ( ) | | * i = = m_client . data ( ) - > tabGroup ( ) - > current ( ) )
2012-01-12 10:42:55 +04:00
continue ; // cannot tab there anyway
2012-08-19 14:00:53 +04:00
m_switchToTabMenu - > addAction ( shortCaption ( ( * i ) - > caption ( ) ) ) - > setData ( QVariant : : fromValue ( * i ) ) ;
2009-11-15 06:24:04 +03:00
}
2011-01-30 17:34:42 +03:00
}
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : entabPopupClient ( QAction * action )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
if ( m_client . isNull ( ) | | ! action - > data ( ) . isValid ( ) )
2012-01-12 10:42:55 +04:00
return ;
2015-03-06 13:33:51 +03:00
Client * other = dynamic_cast < Client * > ( action - > data ( ) . value < AbstractClient * > ( ) ) ;
2012-08-19 14:00:53 +04:00
if ( ! Workspace : : self ( ) - > clientList ( ) . contains ( other ) ) // might have been lost betwenn pop-up and selection
2012-01-12 10:42:55 +04:00
return ;
2015-03-06 13:33:51 +03:00
Client * c = dynamic_cast < Client * > ( m_client . data ( ) ) ;
if ( ! c ) {
return ;
}
c - > tabBehind ( other , true ) ;
2012-01-12 10:42:55 +04:00
if ( options - > focusPolicyIsReasonable ( ) )
2015-03-06 13:33:51 +03:00
Workspace : : self ( ) - > requestFocus ( c ) ;
2011-01-30 17:34:42 +03:00
}
2009-11-15 06:24:04 +03:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : rebuildTabGroupPopup ( )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
Q_ASSERT ( m_addTabsMenu ) ;
2012-01-12 10:42:55 +04:00
2012-08-19 14:00:53 +04:00
m_addTabsMenu - > clear ( ) ;
2012-01-12 10:42:55 +04:00
QList < Client * > handled ;
2012-08-19 14:00:53 +04:00
const ClientList & clientList = Workspace : : self ( ) - > clientList ( ) ;
for ( QList < Client * > : : const_iterator i = clientList . constBegin ( ) , end = clientList . constEnd ( ) ; i ! = end ; + + i ) {
if ( * i = = m_client . data ( ) | | ( * i ) - > noBorder ( ) )
2012-01-12 10:42:55 +04:00
continue ;
2012-08-19 14:00:53 +04:00
m_addTabsMenu - > addAction ( shortCaption ( ( * i ) - > caption ( ) ) ) - > setData ( QVariant : : fromValue ( * i ) ) ;
2012-01-12 10:42:55 +04:00
}
2013-03-24 01:20:35 +04:00
if ( m_addTabsMenu - > actions ( ) . isEmpty ( ) )
m_addTabsMenu - > addAction ( i18nc ( " There's no window available to be attached as tab to this one " , " None available " ) ) - > setEnabled ( false ) ;
2011-01-30 17:34:42 +03:00
}
2009-11-15 06:24:04 +03:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : initTabbingPopups ( )
2011-01-30 17:34:42 +03:00
{
2012-01-12 10:42:55 +04:00
bool needTabManagers = false ;
2012-08-19 14:00:53 +04:00
if ( m_client . data ( ) - > tabGroup ( ) & & m_client . data ( ) - > tabGroup ( ) - > count ( ) > 1 ) {
2012-01-12 10:42:55 +04:00
needTabManagers = true ;
2012-08-19 14:00:53 +04:00
if ( ! m_switchToTabMenu ) {
m_switchToTabMenu = new QMenu ( i18n ( " Switch to Tab " ) , m_menu ) ;
2014-03-27 19:48:25 +04:00
connect ( m_switchToTabMenu , & QMenu : : triggered , this , & UserActionsMenu : : selectPopupClientTab ) ;
connect ( m_switchToTabMenu , & QMenu : : aboutToShow , this , & UserActionsMenu : : rebuildTabListPopup ) ;
2012-08-19 14:00:53 +04:00
m_menu - > insertMenu ( m_removeFromTabGroup , m_switchToTabMenu ) ;
2009-11-15 06:24:04 +03:00
}
2012-01-12 10:42:55 +04:00
} else {
2012-08-19 14:00:53 +04:00
delete m_switchToTabMenu ;
m_switchToTabMenu = 0 ;
2012-01-12 10:42:55 +04:00
}
2012-08-19 14:00:53 +04:00
if ( ! m_addTabsMenu ) {
2013-05-15 22:55:49 +04:00
m_addTabsMenu = new QMenu ( i18n ( " &Attach as tab to " ) , m_menu ) ;
2014-03-27 19:48:25 +04:00
connect ( m_addTabsMenu , & QMenu : : triggered , this , & UserActionsMenu : : entabPopupClient ) ;
connect ( m_addTabsMenu , & QMenu : : aboutToShow , this , & UserActionsMenu : : rebuildTabGroupPopup ) ;
2012-08-19 14:00:53 +04:00
m_menu - > insertMenu ( m_removeFromTabGroup , m_addTabsMenu ) ;
2009-11-15 06:24:04 +03:00
}
2012-01-12 10:42:55 +04:00
2014-03-26 21:06:03 +04:00
m_addTabsMenu - > menuAction ( ) - > setEnabled ( ! m_client . data ( ) - > isFullScreen ( ) ) ;
2012-08-19 14:00:53 +04:00
m_removeFromTabGroup - > setVisible ( needTabManagers ) ;
m_closeTabGroup - > setVisible ( needTabManagers ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : initDesktopPopup ( )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
if ( m_desktopMenu )
2007-04-29 21:35:43 +04:00
return ;
2012-08-19 14:00:53 +04:00
m_desktopMenu = new QMenu ( m_menu ) ;
2014-03-27 19:48:25 +04:00
connect ( m_desktopMenu , & QMenu : : triggered , this , & UserActionsMenu : : slotSendToDesktop ) ;
connect ( m_desktopMenu , & QMenu : : aboutToShow , this , & UserActionsMenu : : desktopPopupAboutToShow ) ;
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
QAction * action = m_desktopMenu - > menuAction ( ) ;
2009-07-01 19:16:26 +04:00
// set it as the first item
2012-08-19 14:00:53 +04:00
m_menu - > insertAction ( m_minimizeOperation , action ) ;
2012-03-23 11:03:09 +04:00
action - > setText ( i18n ( " Move To &Desktop " ) ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : initScreenPopup ( )
2012-08-18 00:32:06 +04:00
{
2012-08-19 14:00:53 +04:00
if ( m_screenMenu ) {
2012-08-18 00:32:06 +04:00
return ;
}
2012-08-19 14:00:53 +04:00
m_screenMenu = new QMenu ( m_menu ) ;
2014-03-27 19:48:25 +04:00
connect ( m_screenMenu , & QMenu : : triggered , this , & UserActionsMenu : : slotSendToScreen ) ;
connect ( m_screenMenu , & QMenu : : aboutToShow , this , & UserActionsMenu : : screenPopupAboutToShow ) ;
2012-08-18 00:32:06 +04:00
2012-08-19 14:00:53 +04:00
QAction * action = m_screenMenu - > menuAction ( ) ;
2012-08-18 00:32:06 +04:00
// set it as the first item after desktop
2012-08-19 14:00:53 +04:00
m_menu - > insertAction ( m_activityMenu ? m_activityMenu - > menuAction ( ) : m_minimizeOperation , action ) ;
2012-08-18 00:32:06 +04:00
action - > setText ( i18n ( " Move To &Screen " ) ) ;
}
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : initActivityPopup ( )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
if ( m_activityMenu )
2010-05-12 00:30:20 +04:00
return ;
2012-08-19 14:00:53 +04:00
m_activityMenu = new QMenu ( m_menu ) ;
2014-03-27 19:48:25 +04:00
connect ( m_activityMenu , & QMenu : : triggered , this , & UserActionsMenu : : slotToggleOnActivity ) ;
connect ( m_activityMenu , & QMenu : : aboutToShow , this , & UserActionsMenu : : activityPopupAboutToShow ) ;
2010-05-12 00:30:20 +04:00
2012-08-19 14:00:53 +04:00
QAction * action = m_activityMenu - > menuAction ( ) ;
2010-05-12 00:30:20 +04:00
// set it as the first item
2012-08-19 14:00:53 +04:00
m_menu - > insertAction ( m_minimizeOperation , action ) ;
2011-01-30 17:34:42 +03:00
action - > setText ( i18n ( " Ac&tivities " ) ) ; //FIXME is that a good string?
}
2010-05-12 00:30:20 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : desktopPopupAboutToShow ( )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
if ( ! m_desktopMenu )
2007-04-29 21:35:43 +04:00
return ;
2012-11-16 11:23:47 +04:00
const VirtualDesktopManager * vds = VirtualDesktopManager : : self ( ) ;
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
m_desktopMenu - > clear ( ) ;
2013-10-14 09:25:27 +04:00
m_desktopMenu - > setPalette ( m_client . data ( ) - > palette ( ) ) ;
2012-08-19 14:00:53 +04:00
QActionGroup * group = new QActionGroup ( m_desktopMenu ) ;
QAction * action = m_desktopMenu - > addAction ( i18n ( " &All Desktops " ) ) ;
2011-01-30 17:34:42 +03:00
action - > setData ( 0 ) ;
action - > setCheckable ( true ) ;
2012-03-23 11:11:55 +04:00
group - > addAction ( action ) ;
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
if ( ! m_client . isNull ( ) & & m_client . data ( ) - > isOnAllDesktops ( ) )
2011-01-30 17:34:42 +03:00
action - > setChecked ( true ) ;
2012-08-19 14:00:53 +04:00
m_desktopMenu - > addSeparator ( ) ;
2007-04-29 21:35:43 +04:00
2012-11-16 11:23:47 +04:00
const uint BASE = 10 ;
for ( uint i = 1 ; i < = vds - > count ( ) ; + + i ) {
2013-07-23 09:02:52 +04:00
QString basic_name ( QStringLiteral ( " %1 %2 " ) ) ;
2011-01-30 17:34:42 +03:00
if ( i < BASE ) {
2015-11-05 17:14:06 +03:00
basic_name . prepend ( QLatin1Char ( ' & ' ) ) ;
2007-04-29 21:35:43 +04:00
}
2015-11-05 17:14:06 +03:00
action = m_desktopMenu - > addAction ( basic_name . arg ( i ) . arg ( vds - > name ( i ) . replace ( QLatin1Char ( ' & ' ) , QStringLiteral ( " && " ) ) ) ) ;
2011-01-30 17:34:42 +03:00
action - > setData ( i ) ;
action - > setCheckable ( true ) ;
2012-03-23 11:11:55 +04:00
group - > addAction ( action ) ;
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
if ( ! m_client . isNull ( ) & &
2012-11-16 11:23:47 +04:00
! m_client . data ( ) - > isOnAllDesktops ( ) & & m_client . data ( ) - > isOnDesktop ( i ) )
2011-01-30 17:34:42 +03:00
action - > setChecked ( true ) ;
2007-04-29 21:35:43 +04:00
}
2012-04-29 19:32:34 +04:00
2012-08-19 14:00:53 +04:00
m_desktopMenu - > addSeparator ( ) ;
action = m_desktopMenu - > addAction ( i18nc ( " Create a new desktop and move there the window " , " &New Desktop " ) ) ;
2012-11-16 11:23:47 +04:00
action - > setData ( vds - > count ( ) + 1 ) ;
2012-04-29 19:32:34 +04:00
2012-11-16 11:23:47 +04:00
if ( vds - > count ( ) > = vds - > maximum ( ) )
2012-04-29 19:32:34 +04:00
action - > setEnabled ( false ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : screenPopupAboutToShow ( )
2012-08-18 00:32:06 +04:00
{
2012-08-19 14:00:53 +04:00
if ( ! m_screenMenu ) {
2012-08-18 00:32:06 +04:00
return ;
}
2012-08-19 14:00:53 +04:00
m_screenMenu - > clear ( ) ;
2013-10-14 09:25:27 +04:00
m_screenMenu - > setPalette ( m_client . data ( ) - > palette ( ) ) ;
2012-08-19 14:00:53 +04:00
QActionGroup * group = new QActionGroup ( m_screenMenu ) ;
2012-08-18 00:32:06 +04:00
2013-04-03 14:19:27 +04:00
for ( int i = 0 ; i < screens ( ) - > count ( ) ; + + i ) {
2012-08-18 00:32:06 +04:00
// assumption: there are not more than 9 screens attached.
2015-05-19 09:37:13 +03:00
QAction * action = m_screenMenu - > addAction ( i18nc ( " @item:inmenu List of all Screens to send a window to. First argument is a number, second the output identifier. E.g. Screen 1 (HDMI1) " ,
" Screen &%1 (%2) " , ( i + 1 ) , screens ( ) - > name ( i ) ) ) ;
2012-08-18 00:32:06 +04:00
action - > setData ( i ) ;
action - > setCheckable ( true ) ;
2012-08-19 14:00:53 +04:00
if ( ! m_client . isNull ( ) & & i = = m_client . data ( ) - > screen ( ) ) {
2012-08-18 00:32:06 +04:00
action - > setChecked ( true ) ;
}
group - > addAction ( action ) ;
}
}
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : activityPopupAboutToShow ( )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
if ( ! m_activityMenu )
2010-05-12 00:30:20 +04:00
return ;
2012-02-26 14:38:16 +04:00
# ifdef KWIN_BUILD_ACTIVITIES
2015-07-07 12:48:42 +03:00
if ( ! Activities : : self ( ) ) {
return ;
}
2012-08-19 14:00:53 +04:00
m_activityMenu - > clear ( ) ;
2013-10-14 09:25:27 +04:00
m_activityMenu - > setPalette ( m_client . data ( ) - > palette ( ) ) ;
2012-08-19 14:00:53 +04:00
QAction * action = m_activityMenu - > addAction ( i18n ( " &All Activities " ) ) ;
2011-01-30 17:34:42 +03:00
action - > setData ( QString ( ) ) ;
action - > setCheckable ( true ) ;
2014-05-01 18:22:04 +04:00
static QPointer < QActionGroup > allActivitiesGroup ;
2014-02-06 21:39:07 +04:00
if ( ! allActivitiesGroup ) {
allActivitiesGroup = new QActionGroup ( m_activityMenu ) ;
}
allActivitiesGroup - > addAction ( action ) ;
2010-05-12 00:30:20 +04:00
2012-08-19 14:00:53 +04:00
if ( ! m_client . isNull ( ) & & m_client . data ( ) - > isOnAllActivities ( ) )
2011-01-30 17:34:42 +03:00
action - > setChecked ( true ) ;
2012-08-19 14:00:53 +04:00
m_activityMenu - > addSeparator ( ) ;
2010-05-12 00:30:20 +04:00
2013-04-04 18:14:12 +04:00
foreach ( const QString & id , Activities : : self ( ) - > running ( ) ) {
2011-11-05 02:23:52 +04:00
KActivities : : Info activity ( id ) ;
2010-11-01 22:53:22 +03:00
QString name = activity . name ( ) ;
2010-05-12 00:30:20 +04:00
name . replace ( ' & ' , " && " ) ;
2013-03-25 00:57:26 +04:00
QWidgetAction * action = new QWidgetAction ( m_activityMenu ) ;
QCheckBox * box = new QCheckBox ( name , m_activityMenu ) ;
action - > setDefaultWidget ( box ) ;
const QString icon = activity . icon ( ) ;
if ( ! icon . isEmpty ( ) )
2013-09-06 17:12:35 +04:00
box - > setIcon ( QIcon : : fromTheme ( icon ) ) ;
2013-03-25 00:57:26 +04:00
box - > setBackgroundRole ( m_activityMenu - > backgroundRole ( ) ) ;
box - > setForegroundRole ( m_activityMenu - > foregroundRole ( ) ) ;
box - > setPalette ( m_activityMenu - > palette ( ) ) ;
2014-03-27 19:48:25 +04:00
connect ( box , & QCheckBox : : clicked , action , & QAction : : triggered ) ;
2013-03-25 00:57:26 +04:00
m_activityMenu - > addAction ( action ) ;
2011-01-30 17:34:42 +03:00
action - > setData ( id ) ;
2010-05-12 00:30:20 +04:00
2012-08-19 14:00:53 +04:00
if ( ! m_client . isNull ( ) & &
! m_client . data ( ) - > isOnAllActivities ( ) & & m_client . data ( ) - > isOnActivity ( id ) )
2013-03-25 00:57:26 +04:00
box - > setChecked ( true ) ;
2010-05-12 00:30:20 +04:00
}
2012-02-26 14:38:16 +04:00
# endif
2011-01-30 17:34:42 +03:00
}
2010-05-12 00:30:20 +04:00
2012-08-19 14:00:53 +04:00
void UserActionsMenu : : slotWindowOperation ( QAction * action )
{
if ( ! action - > data ( ) . isValid ( ) )
return ;
Options : : WindowOperation op = static_cast < Options : : WindowOperation > ( action - > data ( ) . toInt ( ) ) ;
2015-03-06 13:33:51 +03:00
QWeakPointer < AbstractClient > c = ( ! m_client . isNull ( ) ) ? m_client : QWeakPointer < AbstractClient > ( Workspace : : self ( ) - > activeClient ( ) ) ;
2012-08-19 14:00:53 +04:00
if ( c . isNull ( ) )
return ;
QString type ;
switch ( op ) {
case Options : : FullScreenOp :
if ( ! c . data ( ) - > isFullScreen ( ) & & c . data ( ) - > userCanSetFullScreen ( ) )
2013-07-23 09:02:52 +04:00
type = QStringLiteral ( " fullscreenaltf3 " ) ;
2012-08-19 14:00:53 +04:00
break ;
case Options : : NoBorderOp :
if ( ! c . data ( ) - > noBorder ( ) & & c . data ( ) - > userCanSetNoBorder ( ) )
2013-07-23 09:02:52 +04:00
type = QStringLiteral ( " noborderaltf3 " ) ;
2012-08-19 14:00:53 +04:00
break ;
default :
break ;
} ;
if ( ! type . isEmpty ( ) )
helperDialog ( type , c ) ;
2013-08-19 14:15:42 +04:00
// need to delay performing the window operation as we need to have the
// user actions menu closed before we destroy the decoration. Otherwise Qt crashes
2014-12-02 15:50:26 +03:00
qRegisterMetaType < Options : : WindowOperation > ( ) ;
2013-08-19 14:15:42 +04:00
QMetaObject : : invokeMethod ( workspace ( ) , " performWindowOperation " ,
Qt : : QueuedConnection ,
2015-03-06 12:05:40 +03:00
Q_ARG ( KWin : : AbstractClient * , c . data ( ) ) ,
2014-12-02 12:39:38 +03:00
Q_ARG ( Options : : WindowOperation , op ) ) ;
2012-08-19 14:00:53 +04:00
}
void UserActionsMenu : : slotSendToDesktop ( QAction * action )
{
2012-11-16 11:23:47 +04:00
bool ok = false ;
uint desk = action - > data ( ) . toUInt ( & ok ) ;
if ( ! ok ) {
return ;
}
2015-03-12 15:50:50 +03:00
if ( m_client . isNull ( ) )
2012-08-19 14:00:53 +04:00
return ;
Workspace * ws = Workspace : : self ( ) ;
2012-11-16 11:23:47 +04:00
VirtualDesktopManager * vds = VirtualDesktopManager : : self ( ) ;
2012-08-19 14:00:53 +04:00
if ( desk = = 0 ) {
// the 'on_all_desktops' menu entry
m_client . data ( ) - > setOnAllDesktops ( ! m_client . data ( ) - > isOnAllDesktops ( ) ) ;
return ;
2012-11-16 11:23:47 +04:00
} else if ( desk > vds - > count ( ) ) {
vds - > setCount ( desk ) ;
2012-08-19 14:00:53 +04:00
}
2015-03-12 15:50:50 +03:00
ws - > sendClientToDesktop ( m_client . data ( ) , desk , false ) ;
2012-08-19 14:00:53 +04:00
}
void UserActionsMenu : : slotSendToScreen ( QAction * action )
{
const int screen = action - > data ( ) . toInt ( ) ;
if ( m_client . isNull ( ) ) {
return ;
}
2013-04-03 14:19:27 +04:00
if ( screen > = screens ( ) - > count ( ) ) {
2012-08-19 14:00:53 +04:00
return ;
}
2013-04-03 14:19:27 +04:00
Workspace : : self ( ) - > sendClientToScreen ( m_client . data ( ) , screen ) ;
2012-08-19 14:00:53 +04:00
}
void UserActionsMenu : : slotToggleOnActivity ( QAction * action )
{
2013-04-04 18:14:12 +04:00
# ifdef KWIN_BUILD_ACTIVITIES
2015-07-07 12:48:42 +03:00
if ( ! Activities : : self ( ) ) {
return ;
}
2012-08-19 14:00:53 +04:00
QString activity = action - > data ( ) . toString ( ) ;
if ( m_client . isNull ( ) )
return ;
if ( activity . isEmpty ( ) ) {
// the 'on_all_activities' menu entry
m_client . data ( ) - > setOnAllActivities ( ! m_client . data ( ) - > isOnAllActivities ( ) ) ;
return ;
}
2015-03-06 13:33:51 +03:00
Client * c = dynamic_cast < Client * > ( m_client . data ( ) ) ;
if ( ! c ) {
return ;
}
Activities : : self ( ) - > toggleClientOnActivity ( c , activity , false ) ;
2013-03-25 00:57:26 +04:00
if ( m_activityMenu & & m_activityMenu - > isVisible ( ) & & m_activityMenu - > actions ( ) . count ( ) ) {
2014-02-06 21:39:07 +04:00
const bool isOnAll = m_client . data ( ) - > isOnAllActivities ( ) ;
m_activityMenu - > actions ( ) . at ( 0 ) - > setChecked ( isOnAll ) ;
if ( isOnAll ) {
// toggleClientOnActivity interprets "on all" as "on none" and
// susequent toggling ("off") would move the client to only that activity.
// bug #330838 -> set all but "on all" off to "force proper usage"
for ( int i = 1 ; i < m_activityMenu - > actions ( ) . count ( ) ; + + i ) {
if ( QWidgetAction * qwa = qobject_cast < QWidgetAction * > ( m_activityMenu - > actions ( ) . at ( i ) ) ) {
if ( QCheckBox * qcb = qobject_cast < QCheckBox * > ( qwa - > defaultWidget ( ) ) ) {
qcb - > setChecked ( false ) ;
}
}
}
}
2013-03-25 00:57:26 +04:00
}
2014-11-21 18:48:39 +03:00
# else
Q_UNUSED ( action )
2013-04-04 18:14:12 +04:00
# endif
2012-08-19 14:00:53 +04:00
}
2013-04-25 19:21:54 +04:00
//****************************************
// ShortcutDialog
//****************************************
ShortcutDialog : : ShortcutDialog ( const QKeySequence & cut )
: _shortcut ( cut )
{
2013-12-12 17:17:26 +04:00
m_ui . setupUi ( this ) ;
m_ui . keySequenceEdit - > setKeySequence ( cut ) ;
m_ui . warning - > hide ( ) ;
2013-04-25 19:21:54 +04:00
// Listen to changed shortcuts
2013-12-12 17:17:26 +04:00
connect ( m_ui . keySequenceEdit , & QKeySequenceEdit : : editingFinished , this , & ShortcutDialog : : keySequenceChanged ) ;
connect ( m_ui . clearButton , & QToolButton : : clicked , [ this ] {
_shortcut = QKeySequence ( ) ;
} ) ;
m_ui . keySequenceEdit - > setFocus ( ) ;
2013-04-25 19:21:54 +04:00
2013-08-19 14:44:30 +04:00
setWindowFlags ( Qt : : Popup | Qt : : X11BypassWindowManagerHint ) ;
2013-04-25 19:21:54 +04:00
}
void ShortcutDialog : : accept ( )
{
QKeySequence seq = shortcut ( ) ;
if ( ! seq . isEmpty ( ) ) {
if ( seq [ 0 ] = = Qt : : Key_Escape ) {
reject ( ) ;
return ;
}
if ( seq [ 0 ] = = Qt : : Key_Space
| | ( seq [ 0 ] & Qt : : KeyboardModifierMask ) = = 0 ) {
// clear
2013-12-12 17:17:26 +04:00
m_ui . keySequenceEdit - > clear ( ) ;
2013-08-19 14:44:30 +04:00
QDialog : : accept ( ) ;
2013-04-25 19:21:54 +04:00
return ;
}
}
2013-08-19 14:44:30 +04:00
QDialog : : accept ( ) ;
2013-04-25 19:21:54 +04:00
}
void ShortcutDialog : : done ( int r )
{
2013-08-19 14:44:30 +04:00
QDialog : : done ( r ) ;
2013-04-25 19:21:54 +04:00
emit dialogDone ( r = = Accepted ) ;
}
2013-12-12 17:17:26 +04:00
void ShortcutDialog : : keySequenceChanged ( )
2013-04-25 19:21:54 +04:00
{
activateWindow ( ) ; // where is the kbd focus lost? cause of popup state?
2013-12-12 17:17:26 +04:00
QKeySequence seq = m_ui . keySequenceEdit - > keySequence ( ) ;
2013-04-25 19:21:54 +04:00
if ( _shortcut = = seq )
return ; // don't try to update the same
if ( seq . isEmpty ( ) ) { // clear
_shortcut = seq ;
return ;
}
2013-12-12 17:17:26 +04:00
if ( seq . count ( ) > 1 ) {
seq = QKeySequence ( seq [ 0 ] ) ;
m_ui . keySequenceEdit - > setKeySequence ( seq ) ;
}
2013-04-25 19:21:54 +04:00
// Check if the key sequence is used currently
QString sc = seq . toString ( ) ;
// NOTICE - seq.toString() & the entries in "conflicting" randomly get invalidated after the next call (if no sc has been set & conflicting isn't empty?!)
QList < KGlobalShortcutInfo > conflicting = KGlobalAccel : : getGlobalShortcutsByKey ( seq ) ;
if ( ! conflicting . isEmpty ( ) ) {
const KGlobalShortcutInfo & conflict = conflicting . at ( 0 ) ;
2013-12-12 17:17:26 +04:00
m_ui . warning - > setText ( i18nc ( " '%1' is a keyboard shortcut like 'ctrl+w' " ,
2013-04-25 19:21:54 +04:00
" <b>%1</b> is already in use " , sc ) ) ;
2013-12-12 17:17:26 +04:00
m_ui . warning - > setToolTip ( i18nc ( " keyboard shortcut '%1' is used by action '%2' in application '%3' " ,
2013-04-25 19:21:54 +04:00
" <b>%1</b> is used by %2 in %3 " , sc , conflict . friendlyName ( ) , conflict . componentFriendlyName ( ) ) ) ;
2013-12-12 17:17:26 +04:00
m_ui . warning - > show ( ) ;
m_ui . keySequenceEdit - > setKeySequence ( shortcut ( ) ) ;
2013-04-25 19:21:54 +04:00
} else if ( seq ! = _shortcut ) {
2013-12-12 17:17:26 +04:00
m_ui . warning - > hide ( ) ;
if ( QPushButton * ok = m_ui . buttonBox - > button ( QDialogButtonBox : : Ok ) )
2013-04-25 19:21:54 +04:00
ok - > setFocus ( ) ;
}
_shortcut = seq ;
}
QKeySequence ShortcutDialog : : shortcut ( ) const
{
return _shortcut ;
}
2012-08-19 14:00:53 +04:00
//****************************************
// Workspace
//****************************************
void Workspace : : slotIncreaseWindowOpacity ( )
{
if ( ! active_client ) {
return ;
}
active_client - > setOpacity ( qMin ( active_client - > opacity ( ) + 0.05 , 1.0 ) ) ;
}
void Workspace : : slotLowerWindowOpacity ( )
{
if ( ! active_client ) {
return ;
}
active_client - > setOpacity ( qMax ( active_client - > opacity ( ) - 0.05 , 0.05 ) ) ;
}
2007-04-29 21:35:43 +04:00
void Workspace : : closeActivePopup ( )
2011-01-30 17:34:42 +03:00
{
if ( active_popup ) {
2007-04-29 21:35:43 +04:00
active_popup - > close ( ) ;
active_popup = NULL ;
active_popup_client = NULL ;
}
2012-08-19 14:00:53 +04:00
m_userActionsMenu - > close ( ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2013-09-09 11:41:37 +04:00
template < typename Slot >
void Workspace : : initShortcut ( const QString & actionName , const QString & description , const QKeySequence & shortcut , Slot slot , const QVariant & data )
2017-09-24 11:10:52 +03:00
{
initShortcut ( actionName , description , shortcut , this , slot , data ) ;
}
template < typename T , typename Slot >
void Workspace : : initShortcut ( const QString & actionName , const QString & description , const QKeySequence & shortcut , T * receiver , Slot slot , const QVariant & data )
2013-09-09 11:41:37 +04:00
{
2013-12-10 13:01:13 +04:00
QAction * a = new QAction ( this ) ;
2016-09-13 14:02:20 +03:00
a - > setProperty ( " componentName " , QStringLiteral ( KWIN_NAME ) ) ;
2013-12-10 13:01:13 +04:00
a - > setObjectName ( actionName ) ;
2013-09-09 11:41:37 +04:00
a - > setText ( description ) ;
if ( data . isValid ( ) ) {
a - > setData ( data ) ;
}
KGlobalAccel : : self ( ) - > setDefaultShortcut ( a , QList < QKeySequence > ( ) < < shortcut ) ;
KGlobalAccel : : self ( ) - > setShortcut ( a , QList < QKeySequence > ( ) < < shortcut ) ;
2017-09-24 11:10:52 +03:00
input ( ) - > registerShortcut ( shortcut , a , receiver , slot ) ;
2013-09-09 11:41:37 +04:00
}
2007-04-29 21:35:43 +04:00
/*!
Create the global accel object \ c keys .
*/
void Workspace : : initShortcuts ( )
2011-01-30 17:34:42 +03:00
{
2007-04-29 21:35:43 +04:00
# define IN_KWIN
# include "kwinbindings.cpp"
2011-06-30 15:02:30 +04:00
# ifdef KWIN_BUILD_TABBOX
2013-12-10 12:34:11 +04:00
TabBox : : TabBox : : self ( ) - > initShortcuts ( ) ;
2011-07-20 15:25:00 +04:00
# endif
2013-12-10 12:11:16 +04:00
VirtualDesktopManager : : self ( ) - > initShortcuts ( ) ;
2012-08-19 14:00:53 +04:00
m_userActionsMenu - > discard ( ) ; // so that it's recreated next time
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2015-03-06 11:03:08 +03:00
void Workspace : : setupWindowShortcut ( AbstractClient * c )
2011-01-30 17:34:42 +03:00
{
assert ( client_keys_dialog = = NULL ) ;
2009-10-05 10:59:10 +04:00
// TODO: PORT ME (KGlobalAccel related)
//keys->setEnabled( false );
//disable_shortcuts_keys->setEnabled( false );
//client_keys->setEnabled( false );
2013-09-06 12:31:38 +04:00
client_keys_dialog = new ShortcutDialog ( c - > shortcut ( ) ) ;
2007-04-29 21:35:43 +04:00
client_keys_client = c ;
2014-03-27 19:48:25 +04:00
connect ( client_keys_dialog , & ShortcutDialog : : dialogDone , this , & Workspace : : setupWindowShortcutDone ) ;
2011-01-30 17:34:42 +03:00
QRect r = clientArea ( ScreenArea , c ) ;
2007-04-29 21:35:43 +04:00
QSize size = client_keys_dialog - > sizeHint ( ) ;
QPoint pos = c - > pos ( ) + c - > clientPos ( ) ;
2011-01-30 17:34:42 +03:00
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 ) ;
2007-04-29 21:35:43 +04:00
client_keys_dialog - > show ( ) ;
active_popup = client_keys_dialog ;
active_popup_client = c ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2011-01-30 17:34:42 +03:00
void Workspace : : setupWindowShortcutDone ( bool ok )
{
2007-11-01 22:24:35 +03:00
// keys->setEnabled( true );
// disable_shortcuts_keys->setEnabled( true );
// client_keys->setEnabled( true );
2011-01-30 17:34:42 +03:00
if ( ok )
2013-09-06 12:31:38 +04:00
client_keys_client - > setShortcut ( client_keys_dialog - > shortcut ( ) . toString ( ) ) ;
2007-04-29 21:35:43 +04:00
closeActivePopup ( ) ;
2008-06-01 15:36:07 +04:00
client_keys_dialog - > deleteLater ( ) ;
2007-04-29 21:35:43 +04:00
client_keys_dialog = NULL ;
client_keys_client = NULL ;
2013-02-10 15:53:09 +04:00
if ( active_client )
2013-04-26 11:47:45 +04:00
active_client - > takeFocus ( ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2017-07-21 21:22:56 +03:00
void Workspace : : clientShortcutUpdated ( AbstractClient * c )
2011-01-30 17:34:42 +03:00
{
2013-07-23 09:02:52 +04:00
QString key = QStringLiteral ( " _k_session:%1 " ) . arg ( c - > window ( ) ) ;
2013-12-10 13:15:23 +04:00
QAction * action = findChild < QAction * > ( key ) ;
2011-01-30 17:34:42 +03:00
if ( ! c - > shortcut ( ) . isEmpty ( ) ) {
if ( action = = NULL ) { // new shortcut
2013-12-10 13:15:23 +04:00
action = new QAction ( this ) ;
2017-07-20 20:14:07 +03:00
kwinApp ( ) - > platform ( ) - > setupActionForGlobalAccel ( action ) ;
2016-09-13 14:02:20 +03:00
action - > setProperty ( " componentName " , QStringLiteral ( KWIN_NAME ) ) ;
2013-12-10 13:15:23 +04:00
action - > setObjectName ( key ) ;
2011-01-30 17:34:42 +03:00
action - > setText ( i18n ( " Activate Window (%1) " , c - > caption ( ) ) ) ;
2017-07-20 20:07:25 +03:00
connect ( action , & QAction : : triggered , c , std : : bind ( & Workspace : : activateClient , this , c , true ) ) ;
2011-01-30 17:34:42 +03:00
}
2008-10-01 00:44:40 +04:00
2008-06-01 15:36:07 +04:00
// no autoloading, since it's configured explicitly here and is not meant to be reused
// (the key is the window id anyway, which is kind of random)
2013-09-06 12:31:38 +04:00
KGlobalAccel : : self ( ) - > setShortcut ( action , QList < QKeySequence > ( ) < < c - > shortcut ( ) ,
2013-08-19 15:51:29 +04:00
KGlobalAccel : : NoAutoloading ) ;
action - > setEnabled ( true ) ;
2011-01-30 17:34:42 +03:00
} else {
2013-08-19 15:51:29 +04:00
KGlobalAccel : : self ( ) - > removeAllShortcuts ( action ) ;
2011-01-30 17:34:42 +03:00
delete action ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2015-03-06 12:05:40 +03:00
void Workspace : : performWindowOperation ( AbstractClient * c , Options : : WindowOperation op )
2011-01-30 17:34:42 +03:00
{
if ( ! c )
2007-04-29 21:35:43 +04:00
return ;
2011-01-30 17:34:42 +03:00
if ( op = = Options : : MoveOp | | op = = Options : : UnrestrictedMoveOp )
2013-02-26 11:45:44 +04:00
Cursor : : setPos ( c - > geometry ( ) . center ( ) ) ;
2011-01-30 17:34:42 +03:00
if ( op = = Options : : ResizeOp | | op = = Options : : UnrestrictedResizeOp )
2013-02-26 11:45:44 +04:00
Cursor : : setPos ( c - > geometry ( ) . bottomRight ( ) ) ;
2011-01-30 17:34:42 +03:00
switch ( op ) {
case Options : : MoveOp :
2014-03-19 17:45:27 +04:00
c - > performMouseCommand ( Options : : MouseMove , Cursor : : pos ( ) ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : UnrestrictedMoveOp :
2014-03-19 17:45:27 +04:00
c - > performMouseCommand ( Options : : MouseUnrestrictedMove , Cursor : : pos ( ) ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : ResizeOp :
2014-03-19 17:45:27 +04:00
c - > performMouseCommand ( Options : : MouseResize , Cursor : : pos ( ) ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : UnrestrictedResizeOp :
2014-03-19 17:45:27 +04:00
c - > performMouseCommand ( Options : : MouseUnrestrictedResize , Cursor : : pos ( ) ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : CloseOp :
2012-07-14 13:11:02 +04:00
QMetaObject : : invokeMethod ( c , " closeWindow " , Qt : : QueuedConnection ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : MaximizeOp :
2014-12-02 15:49:08 +03:00
c - > maximize ( c - > maximizeMode ( ) = = MaximizeFull
? MaximizeRestore : MaximizeFull ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : HMaximizeOp :
2014-12-02 15:49:08 +03:00
c - > maximize ( c - > maximizeMode ( ) ^ MaximizeHorizontal ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : VMaximizeOp :
2014-12-02 15:49:08 +03:00
c - > maximize ( c - > maximizeMode ( ) ^ MaximizeVertical ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : RestoreOp :
2014-12-02 15:49:08 +03:00
c - > maximize ( MaximizeRestore ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : MinimizeOp :
c - > minimize ( ) ;
break ;
case Options : : ShadeOp :
2014-03-19 17:45:27 +04:00
c - > performMouseCommand ( Options : : MouseShade , Cursor : : pos ( ) ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : OnAllDesktopsOp :
c - > setOnAllDesktops ( ! c - > isOnAllDesktops ( ) ) ;
break ;
case Options : : FullScreenOp :
c - > setFullScreen ( ! c - > isFullScreen ( ) , true ) ;
break ;
case Options : : NoBorderOp :
c - > setNoBorder ( ! c - > noBorder ( ) ) ;
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 ( ) )
2007-04-29 21:35:43 +04:00
lowerClient ( c ) ;
2011-01-30 17:34:42 +03:00
break ;
}
case Options : : OperationsOp :
2014-03-19 17:45:27 +04:00
c - > performMouseCommand ( Options : : MouseShade , Cursor : : pos ( ) ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : WindowRulesOp :
2013-04-26 16:40:35 +04:00
RuleBook : : self ( ) - > edit ( c , false ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : ApplicationRulesOp :
2013-04-26 16:40:35 +04:00
RuleBook : : self ( ) - > edit ( c , true ) ;
2011-01-30 17:34:42 +03:00
break ;
case Options : : SetupWindowShortcutOp :
setupWindowShortcut ( c ) ;
break ;
case Options : : LowerOp :
lowerClient ( c ) ;
break ;
2012-01-12 10:42:55 +04:00
case Options : : TabDragOp : // Handled by decoration itself
2011-01-30 17:34:42 +03:00
case Options : : NoOp :
break ;
2012-01-12 10:42:55 +04:00
case Options : : RemoveTabFromGroupOp :
2012-08-25 20:20:34 +04:00
if ( c - > untab ( c - > geometry ( ) . translated ( cascadeOffset ( c ) ) ) & & options - > focusPolicyIsReasonable ( ) )
2015-03-12 15:55:32 +03:00
takeActivity ( c , ActivityFocus | ActivityRaise ) ;
2011-01-30 17:34:42 +03:00
break ;
2012-01-12 10:42:55 +04:00
case Options : : ActivateNextTabOp :
if ( c - > tabGroup ( ) )
c - > tabGroup ( ) - > activateNext ( ) ;
2011-01-30 17:34:42 +03:00
break ;
2012-01-12 10:42:55 +04:00
case Options : : ActivatePreviousTabOp :
if ( c - > tabGroup ( ) )
c - > tabGroup ( ) - > activatePrev ( ) ;
2011-01-30 17:34:42 +03:00
break ;
2012-01-12 10:42:55 +04:00
case Options : : CloseTabGroupOp :
c - > tabGroup ( ) - > closeAll ( ) ;
2012-07-13 12:13:38 +04:00
break ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2009-11-17 10:17:49 +03:00
/**
* Called by the decoration in the new API to determine what buttons the user has configured for
* window tab dragging and the operations menu .
*/
2011-01-30 17:34:42 +03:00
Options : : WindowOperation Client : : mouseButtonToWindowOperation ( Qt : : MouseButtons button )
{
2009-11-17 10:17:49 +03:00
Options : : MouseCommand com = Options : : MouseNothing ;
bool active = isActive ( ) ;
2011-01-30 17:34:42 +03:00
if ( ! wantsInput ( ) ) // we cannot be active, use it anyway
2009-11-17 10:17:49 +03:00
active = true ;
2011-01-30 17:34:42 +03:00
if ( button = = Qt : : LeftButton )
2009-11-17 10:17:49 +03:00
com = active ? options - > commandActiveTitlebar1 ( ) : options - > commandInactiveTitlebar1 ( ) ;
2011-01-30 17:34:42 +03:00
else if ( button = = Qt : : MidButton )
2009-11-17 10:17:49 +03:00
com = active ? options - > commandActiveTitlebar2 ( ) : options - > commandInactiveTitlebar2 ( ) ;
2011-01-30 17:34:42 +03:00
else if ( button = = Qt : : RightButton )
2009-11-17 10:17:49 +03:00
com = active ? options - > commandActiveTitlebar3 ( ) : options - > commandInactiveTitlebar3 ( ) ;
// TODO: Complete the list
2012-01-12 10:42:55 +04:00
if ( com = = Options : : MouseDragTab )
return Options : : TabDragOp ;
2011-01-30 17:34:42 +03:00
if ( com = = Options : : MouseOperationsMenu )
2009-11-17 10:17:49 +03:00
return Options : : OperationsOp ;
return Options : : NoOp ;
2011-01-30 17:34:42 +03:00
}
2009-11-17 10:17:49 +03:00
2007-04-29 21:35:43 +04:00
/*!
Performs a mouse command on this client ( see options . h )
*/
2014-03-20 16:39:00 +04:00
bool Client : : performMouseCommand ( Options : : MouseCommand command , const QPoint & globalPos )
2011-01-30 17:34:42 +03:00
{
2007-04-29 21:35:43 +04:00
bool replay = false ;
2011-01-30 17:34:42 +03:00
switch ( command ) {
case Options : : MouseShade :
toggleShade ( ) ;
cancelShadeHoverTimer ( ) ;
break ;
case Options : : MouseSetShade :
setShade ( ShadeNormal ) ;
cancelShadeHoverTimer ( ) ;
break ;
case Options : : MouseUnsetShade :
setShade ( ShadeNone ) ;
cancelShadeHoverTimer ( ) ;
break ;
2015-07-09 17:08:01 +03:00
default :
return AbstractClient : : performMouseCommand ( command , globalPos ) ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
return replay ;
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotActivateAttentionWindow ( )
2011-01-30 17:34:42 +03:00
{
if ( attention_chain . count ( ) > 0 )
activateClient ( attention_chain . first ( ) ) ;
}
2007-04-29 21:35:43 +04:00
2012-11-16 11:23:47 +04:00
static uint senderValue ( QObject * sender )
2011-01-30 17:34:42 +03:00
{
2011-02-16 21:23:54 +03:00
QAction * act = qobject_cast < QAction * > ( sender ) ;
2012-11-16 11:23:47 +04:00
bool ok = false ; uint i = - 1 ;
2011-02-16 21:23:54 +03:00
if ( act )
i = act - > data ( ) . toUInt ( & ok ) ;
if ( ok )
return i ;
return - 1 ;
}
2012-02-21 21:42:09 +04:00
# define USABLE_ACTIVE_CLIENT (active_client && !(active_client->isDesktop() || active_client->isDock()))
2007-04-29 21:35:43 +04:00
2017-07-21 17:10:14 +03:00
void Workspace : : slotWindowToDesktop ( uint i )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT ) {
if ( i < 1 )
return ;
2012-11-16 11:23:47 +04:00
if ( i > = 1 & & i < = VirtualDesktopManager : : self ( ) - > count ( ) )
2012-02-17 02:44:00 +04:00
sendClientToDesktop ( active_client , i , true ) ;
}
2011-01-30 17:34:42 +03:00
}
2013-03-23 23:44:10 +04:00
static bool screenSwitchImpossible ( )
{
2013-04-03 14:19:27 +04:00
if ( ! screens ( ) - > isCurrentFollowsMouse ( ) )
2013-03-23 23:44:10 +04:00
return false ;
QStringList args ;
2013-07-23 09:02:52 +04:00
args < < QStringLiteral ( " --passivepopup " ) < < i18n ( " The window manager is configured to consider the screen with the mouse on it as active one. \n "
" Therefore it is not possible to switch to a screen explicitly. " ) < < QStringLiteral ( " 20 " ) ;
KProcess : : startDetached ( QStringLiteral ( " kdialog " ) , args ) ;
2013-03-23 23:44:10 +04:00
return true ;
}
2011-02-16 21:23:54 +03:00
void Workspace : : slotSwitchToScreen ( )
2011-01-30 17:34:42 +03:00
{
2013-03-23 23:44:10 +04:00
if ( screenSwitchImpossible ( ) )
return ;
2011-02-16 21:23:54 +03:00
const int i = senderValue ( sender ( ) ) ;
if ( i > - 1 )
setCurrentScreen ( i ) ;
2011-01-30 17:34:42 +03:00
}
2007-05-07 17:13:48 +04:00
void Workspace : : slotSwitchToNextScreen ( )
2011-01-30 17:34:42 +03:00
{
2013-03-23 23:44:10 +04:00
if ( screenSwitchImpossible ( ) )
return ;
2013-04-03 14:19:27 +04:00
setCurrentScreen ( ( screens ( ) - > current ( ) + 1 ) % screens ( ) - > count ( ) ) ;
2011-01-30 17:34:42 +03:00
}
2007-05-07 17:13:48 +04:00
2013-05-19 16:23:49 +04:00
void Workspace : : slotSwitchToPrevScreen ( )
{
if ( screenSwitchImpossible ( ) )
return ;
setCurrentScreen ( ( screens ( ) - > current ( ) + screens ( ) - > count ( ) - 1 ) % screens ( ) - > count ( ) ) ;
}
2011-02-16 21:23:54 +03:00
void Workspace : : slotWindowToScreen ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT ) {
const int i = senderValue ( sender ( ) ) ;
if ( i < 0 )
return ;
2013-04-03 14:19:27 +04:00
if ( i > = 0 & & i < = screens ( ) - > count ( ) ) {
2012-02-17 02:44:00 +04:00
sendClientToScreen ( active_client , i ) ;
}
2007-05-07 17:13:48 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-05-07 17:13:48 +04:00
void Workspace : : slotWindowToNextScreen ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
2013-04-03 14:19:27 +04:00
sendClientToScreen ( active_client , ( active_client - > screen ( ) + 1 ) % screens ( ) - > count ( ) ) ;
2011-01-30 17:34:42 +03:00
}
2007-05-07 17:13:48 +04:00
2013-05-19 16:23:49 +04:00
void Workspace : : slotWindowToPrevScreen ( )
{
if ( USABLE_ACTIVE_CLIENT )
sendClientToScreen ( active_client , ( active_client - > screen ( ) + screens ( ) - > count ( ) - 1 ) % screens ( ) - > count ( ) ) ;
}
2007-04-29 21:35:43 +04:00
/*!
Maximizes the popup client
*/
void Workspace : : slotWindowMaximize ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : MaximizeOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Maximizes the popup client vertically
*/
void Workspace : : slotWindowMaximizeVertical ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : VMaximizeOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Maximizes the popup client horiozontally
*/
void Workspace : : slotWindowMaximizeHorizontal ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : HMaximizeOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Minimizes the popup client
*/
void Workspace : : slotWindowMinimize ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : MinimizeOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Shades / unshades the popup client respectively
*/
void Workspace : : slotWindowShade ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : ShadeOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Raises the popup client
*/
void Workspace : : slotWindowRaise ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
raiseClient ( active_client ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Lowers the popup client
*/
void Workspace : : slotWindowLower ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT ) {
lowerClient ( active_client ) ;
2009-01-28 13:03:37 +03:00
// As this most likely makes the window no longer visible change the
// keyboard focus to the next available window.
//activateNextClient( c ); // Doesn't work when we lower a child window
2012-02-22 02:55:55 +04:00
if ( active_client - > isActive ( ) & & options - > focusPolicyIsReasonable ( ) ) {
2012-03-08 03:25:08 +04:00
if ( options - > isNextFocusPrefersMouse ( ) ) {
2016-02-18 12:28:00 +03:00
AbstractClient * next = clientUnderMouse ( active_client - > screen ( ) ) ;
2012-02-22 02:55:55 +04:00
if ( next & & next ! = active_client )
requestFocus ( next , false ) ;
} else {
2012-11-16 11:23:47 +04:00
activateClient ( topClientOnDesktop ( VirtualDesktopManager : : self ( ) - > current ( ) , - 1 ) ) ;
2012-02-22 02:55:55 +04:00
}
}
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Does a toggle - raise - and - lower on the popup client ;
*/
void Workspace : : slotWindowRaiseOrLower ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
raiseOrLowerClient ( active_client ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowOnAllDesktops ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
active_client - > setOnAllDesktops ( ! active_client - > isOnAllDesktops ( ) ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowFullScreen ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : FullScreenOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowNoBorder ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : NoBorderOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowAbove ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : KeepAboveOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowBelow ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : KeepBelowOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotSetupWindowShortcut ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : SetupWindowShortcutOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2009-09-12 12:01:44 +04:00
/*!
Toggles show desktop
*/
void Workspace : : slotToggleShowDesktop ( )
2011-01-30 17:34:42 +03:00
{
setShowingDesktop ( ! showingDesktop ( ) ) ;
}
2009-09-12 12:01:44 +04:00
2012-11-16 11:23:47 +04:00
template < typename Direction >
2015-03-06 17:17:13 +03:00
void windowToDesktop ( AbstractClient * c )
2012-11-16 11:23:47 +04:00
{
VirtualDesktopManager * vds = VirtualDesktopManager : : self ( ) ;
Workspace * ws = Workspace : : self ( ) ;
Direction functor ;
// TODO: why is options->isRollOverDesktops() not honored?
2016-11-10 16:02:14 +03:00
const auto desktop = functor ( nullptr , true ) ;
2012-11-16 11:23:47 +04:00
if ( c & & ! c - > isDesktop ( )
& & ! c - > isDock ( ) ) {
ws - > setClientIsMoving ( c ) ;
vds - > setCurrent ( desktop ) ;
ws - > setClientIsMoving ( NULL ) ;
}
}
2007-04-29 21:35:43 +04:00
/*!
Move window to next desktop
*/
void Workspace : : slotWindowToNextDesktop ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
windowToNextDesktop ( active_client ) ;
2011-01-30 17:34:42 +03:00
}
2008-06-02 23:52:02 +04:00
2015-03-06 17:17:13 +03:00
void Workspace : : windowToNextDesktop ( AbstractClient * c )
2011-01-30 17:34:42 +03:00
{
2012-11-16 11:23:47 +04:00
windowToDesktop < DesktopNext > ( c ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Move window to previous desktop
*/
void Workspace : : slotWindowToPreviousDesktop ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
windowToPreviousDesktop ( active_client ) ;
2011-01-30 17:34:42 +03:00
}
2008-06-02 23:52:02 +04:00
2015-03-06 17:17:13 +03:00
void Workspace : : windowToPreviousDesktop ( AbstractClient * c )
2011-01-30 17:34:42 +03:00
{
2012-11-16 11:23:47 +04:00
windowToDesktop < DesktopPrevious > ( c ) ;
}
template < typename Direction >
void activeClientToDesktop ( )
{
VirtualDesktopManager * vds = VirtualDesktopManager : : self ( ) ;
Workspace * ws = Workspace : : self ( ) ;
const int current = vds - > current ( ) ;
Direction functor ;
const int d = functor ( current , options - > isRollOverDesktops ( ) ) ;
if ( d = = current ) {
return ;
2007-04-29 21:35:43 +04:00
}
2012-11-16 11:23:47 +04:00
ws - > setClientIsMoving ( ws - > activeClient ( ) ) ;
vds - > setCurrent ( d ) ;
ws - > setClientIsMoving ( NULL ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowToDesktopRight ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT ) {
2012-11-16 11:23:47 +04:00
activeClientToDesktop < DesktopRight > ( ) ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowToDesktopLeft ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT ) {
2012-11-16 11:23:47 +04:00
activeClientToDesktop < DesktopLeft > ( ) ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowToDesktopUp ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT ) {
2012-11-16 11:23:47 +04:00
activeClientToDesktop < DesktopAbove > ( ) ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
void Workspace : : slotWindowToDesktopDown ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT ) {
2012-11-16 11:23:47 +04:00
activeClientToDesktop < DesktopBelow > ( ) ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2012-01-12 10:42:55 +04:00
void Workspace : : slotActivateNextTab ( )
2011-01-30 17:34:42 +03:00
{
2012-01-12 10:42:55 +04:00
if ( active_client & & active_client - > tabGroup ( ) )
active_client - > tabGroup ( ) - > activateNext ( ) ;
2011-01-30 17:34:42 +03:00
}
2009-11-15 06:24:04 +03:00
2012-01-12 10:42:55 +04:00
void Workspace : : slotActivatePrevTab ( )
2011-01-30 17:34:42 +03:00
{
2012-01-12 10:42:55 +04:00
if ( active_client & & active_client - > tabGroup ( ) )
active_client - > tabGroup ( ) - > activatePrev ( ) ;
2011-01-30 17:34:42 +03:00
}
2009-11-15 06:24:04 +03:00
2012-01-12 10:42:55 +04:00
void Workspace : : slotUntab ( )
2011-01-30 17:34:42 +03:00
{
2012-01-12 10:42:55 +04:00
if ( active_client )
2012-08-25 20:20:34 +04:00
active_client - > untab ( active_client - > geometry ( ) . translated ( cascadeOffset ( active_client ) ) ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Kill Window feature , similar to xkill
*/
void Workspace : : slotKillWindow ( )
2011-01-30 17:34:42 +03:00
{
2012-12-27 17:26:46 +04:00
if ( m_windowKiller . isNull ( ) ) {
m_windowKiller . reset ( new KillWindow ( ) ) ;
}
m_windowKiller - > start ( ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2009-10-03 17:09:38 +04:00
/*!
Switches to the nearest window in given direction
*/
2011-01-30 17:34:42 +03:00
void Workspace : : switchWindow ( Direction direction )
{
if ( ! active_client )
2009-10-03 17:09:38 +04:00
return ;
2015-03-12 14:08:54 +03:00
AbstractClient * c = active_client ;
Cycle between windows of the same desktop on switch
Summary:
When switching virtual desktops using shortcuts, the behavior is to
switch to a virtual desktop in the opposite direction if the current
one is on the edges of the layout. For example, in a one row layout with
4 virtual desktops, "Switch One Desktop to the Left" while in virtual
desktop # 1 will send the user to virtual desktop # 4. Likewise, in a 3
rows layout with 9 virtual desktops, "Switch One Desktop Down" while in
virtual desktop # 8 will lead the user to desktop # 2.
This patch uses the same behavior whilst changing windows using
"Switch to Window Above|Below|to the Right|to the Left".
For example, in a 3 display set-up (my set-up), the user would go from an
application in the rightmost position to an application in the leftmost
position using just one key combination: "Switch to Window to the Right".
Currently, the shortcuts are no-op in these cases (ie, trying "Switch to
Window to the Left" from the leftmost window has no outcome, which is
mostly accurate with the shortcut semantics but totally useless in behavior).
Reviewers: #vdg, #kwin, graesslin
Reviewed By: #kwin, graesslin
Subscribers: luebking, subdiff, colomar, graesslin, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D3602
2016-12-22 23:12:46 +03:00
int desktopNumber = c - > isOnAllDesktops ( ) ? VirtualDesktopManager : : self ( ) - > current ( ) : c - > desktop ( ) ;
2009-10-03 17:09:38 +04:00
// Centre of the active window
2011-01-30 17:34:42 +03:00
QPoint curPos ( c - > pos ( ) . x ( ) + c - > geometry ( ) . width ( ) / 2 ,
c - > pos ( ) . y ( ) + c - > geometry ( ) . height ( ) / 2 ) ;
2009-10-03 17:09:38 +04:00
Cycle between windows of the same desktop on switch
Summary:
When switching virtual desktops using shortcuts, the behavior is to
switch to a virtual desktop in the opposite direction if the current
one is on the edges of the layout. For example, in a one row layout with
4 virtual desktops, "Switch One Desktop to the Left" while in virtual
desktop # 1 will send the user to virtual desktop # 4. Likewise, in a 3
rows layout with 9 virtual desktops, "Switch One Desktop Down" while in
virtual desktop # 8 will lead the user to desktop # 2.
This patch uses the same behavior whilst changing windows using
"Switch to Window Above|Below|to the Right|to the Left".
For example, in a 3 display set-up (my set-up), the user would go from an
application in the rightmost position to an application in the leftmost
position using just one key combination: "Switch to Window to the Right".
Currently, the shortcuts are no-op in these cases (ie, trying "Switch to
Window to the Left" from the leftmost window has no outcome, which is
mostly accurate with the shortcut semantics but totally useless in behavior).
Reviewers: #vdg, #kwin, graesslin
Reviewed By: #kwin, graesslin
Subscribers: luebking, subdiff, colomar, graesslin, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D3602
2016-12-22 23:12:46 +03:00
if ( ! switchWindow ( c , direction , curPos , desktopNumber ) ) {
auto opposite = [ & ] {
switch ( direction ) {
case DirectionNorth :
return QPoint ( curPos . x ( ) , screens ( ) - > geometry ( ) . height ( ) ) ;
case DirectionSouth :
return QPoint ( curPos . x ( ) , 0 ) ;
case DirectionEast :
return QPoint ( 0 , curPos . y ( ) ) ;
case DirectionWest :
return QPoint ( screens ( ) - > geometry ( ) . width ( ) , curPos . y ( ) ) ;
default :
Q_UNREACHABLE ( ) ;
}
} ;
switchWindow ( c , direction , opposite ( ) , desktopNumber ) ;
}
}
bool Workspace : : switchWindow ( AbstractClient * c , Direction direction , QPoint curPos , int d )
{
2017-06-19 19:17:46 +03:00
AbstractClient * switchTo = nullptr ;
Cycle between windows of the same desktop on switch
Summary:
When switching virtual desktops using shortcuts, the behavior is to
switch to a virtual desktop in the opposite direction if the current
one is on the edges of the layout. For example, in a one row layout with
4 virtual desktops, "Switch One Desktop to the Left" while in virtual
desktop # 1 will send the user to virtual desktop # 4. Likewise, in a 3
rows layout with 9 virtual desktops, "Switch One Desktop Down" while in
virtual desktop # 8 will lead the user to desktop # 2.
This patch uses the same behavior whilst changing windows using
"Switch to Window Above|Below|to the Right|to the Left".
For example, in a 3 display set-up (my set-up), the user would go from an
application in the rightmost position to an application in the leftmost
position using just one key combination: "Switch to Window to the Right".
Currently, the shortcuts are no-op in these cases (ie, trying "Switch to
Window to the Left" from the leftmost window has no outcome, which is
mostly accurate with the shortcut semantics but totally useless in behavior).
Reviewers: #vdg, #kwin, graesslin
Reviewed By: #kwin, graesslin
Subscribers: luebking, subdiff, colomar, graesslin, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D3602
2016-12-22 23:12:46 +03:00
int bestScore = 0 ;
2012-04-08 12:07:35 +04:00
ToplevelList clist = stackingOrder ( ) ;
for ( ToplevelList : : Iterator i = clist . begin ( ) ; i ! = clist . end ( ) ; + + i ) {
2017-06-19 19:17:46 +03:00
auto client = qobject_cast < AbstractClient * > ( * i ) ;
2012-04-08 12:07:35 +04:00
if ( ! client ) {
continue ;
}
if ( client - > wantsTabFocus ( ) & & * i ! = c & &
2015-01-28 18:56:19 +03:00
client - > isOnDesktop ( d ) & & ! client - > isMinimized ( ) & & ( * i ) - > isOnCurrentActivity ( ) ) {
2009-10-03 17:09:38 +04:00
// Centre of the other window
2012-04-08 12:07:35 +04:00
QPoint other ( client - > pos ( ) . x ( ) + client - > geometry ( ) . width ( ) / 2 ,
client - > pos ( ) . y ( ) + client - > geometry ( ) . height ( ) / 2 ) ;
2009-10-03 17:09:38 +04:00
int distance ;
int offset ;
2011-01-30 17:34:42 +03:00
switch ( direction ) {
case DirectionNorth :
distance = curPos . y ( ) - other . y ( ) ;
offset = qAbs ( other . x ( ) - curPos . x ( ) ) ;
break ;
case DirectionEast :
distance = other . x ( ) - curPos . x ( ) ;
offset = qAbs ( other . y ( ) - curPos . y ( ) ) ;
break ;
case DirectionSouth :
distance = other . y ( ) - curPos . y ( ) ;
offset = qAbs ( other . x ( ) - curPos . x ( ) ) ;
break ;
case DirectionWest :
distance = curPos . x ( ) - other . x ( ) ;
offset = qAbs ( other . y ( ) - curPos . y ( ) ) ;
break ;
default :
distance = - 1 ;
offset = - 1 ;
}
2009-10-03 17:09:38 +04:00
2011-01-30 17:34:42 +03:00
if ( distance > 0 ) {
2009-10-03 17:09:38 +04:00
// Inverse score
2011-01-30 17:34:42 +03:00
int score = distance + offset + ( ( offset * offset ) / distance ) ;
if ( score < bestScore | | ! switchTo ) {
2012-04-08 12:07:35 +04:00
switchTo = client ;
2009-10-03 17:09:38 +04:00
bestScore = score ;
}
}
}
}
2012-03-16 03:13:29 +04:00
if ( switchTo ) {
if ( switchTo - > tabGroup ( ) )
switchTo = switchTo - > tabGroup ( ) - > current ( ) ;
2011-01-30 17:34:42 +03:00
activateClient ( switchTo ) ;
2012-03-16 03:13:29 +04:00
}
Cycle between windows of the same desktop on switch
Summary:
When switching virtual desktops using shortcuts, the behavior is to
switch to a virtual desktop in the opposite direction if the current
one is on the edges of the layout. For example, in a one row layout with
4 virtual desktops, "Switch One Desktop to the Left" while in virtual
desktop # 1 will send the user to virtual desktop # 4. Likewise, in a 3
rows layout with 9 virtual desktops, "Switch One Desktop Down" while in
virtual desktop # 8 will lead the user to desktop # 2.
This patch uses the same behavior whilst changing windows using
"Switch to Window Above|Below|to the Right|to the Left".
For example, in a 3 display set-up (my set-up), the user would go from an
application in the rightmost position to an application in the leftmost
position using just one key combination: "Switch to Window to the Right".
Currently, the shortcuts are no-op in these cases (ie, trying "Switch to
Window to the Left" from the leftmost window has no outcome, which is
mostly accurate with the shortcut semantics but totally useless in behavior).
Reviewers: #vdg, #kwin, graesslin
Reviewed By: #kwin, graesslin
Subscribers: luebking, subdiff, colomar, graesslin, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D3602
2016-12-22 23:12:46 +03:00
return switchTo ;
2011-01-30 17:34:42 +03:00
}
2009-10-03 17:09:38 +04:00
2007-04-29 21:35:43 +04:00
/*!
Shows the window operations popup menu for the activeClient ( )
*/
void Workspace : : slotWindowOperations ( )
2011-01-30 17:34:42 +03:00
{
if ( ! active_client )
2007-04-29 21:35:43 +04:00
return ;
QPoint pos = active_client - > pos ( ) + active_client - > clientPos ( ) ;
2013-05-03 21:13:12 +04:00
showWindowMenu ( QRect ( pos , pos ) , active_client ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2015-03-06 17:33:13 +03:00
void Workspace : : showWindowMenu ( const QRect & pos , AbstractClient * cl )
2011-01-30 17:34:42 +03:00
{
2012-08-19 14:00:53 +04:00
m_userActionsMenu - > show ( pos , cl ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2017-01-11 12:21:03 +03:00
void Workspace : : showApplicationMenu ( const QRect & pos , AbstractClient * c , int actionId )
{
ApplicationMenu : : self ( ) - > showApplicationMenu ( c - > geometry ( ) . topLeft ( ) + pos . bottomLeft ( ) , c , actionId ) ;
}
2007-04-29 21:35:43 +04:00
/*!
Closes the popup client
*/
void Workspace : : slotWindowClose ( )
2011-01-30 17:34:42 +03:00
{
2009-09-13 15:36:45 +04:00
// TODO: why?
// if ( tab_box->isVisible())
// return;
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : CloseOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Starts keyboard move mode for the popup client
*/
void Workspace : : slotWindowMove ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : UnrestrictedMoveOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
/*!
Starts keyboard resize mode for the popup client
*/
void Workspace : : slotWindowResize ( )
2011-01-30 17:34:42 +03:00
{
2012-02-17 02:44:00 +04:00
if ( USABLE_ACTIVE_CLIENT )
performWindowOperation ( active_client , Options : : UnrestrictedResizeOp ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2012-02-17 02:44:00 +04:00
# undef USABLE_ACTIVE_CLIENT
2017-07-21 21:22:56 +03:00
void AbstractClient : : setShortcut ( const QString & _cut )
2011-01-30 17:34:42 +03:00
{
QString cut = rules ( ) - > checkShortcut ( _cut ) ;
2017-07-21 21:22:56 +03:00
auto updateShortcut = [ this ] ( const QKeySequence & cut = QKeySequence ( ) ) {
if ( _shortcut = = cut )
return ;
_shortcut = cut ;
setShortcutInternal ( ) ;
} ;
if ( cut . isEmpty ( ) ) {
updateShortcut ( ) ;
return ;
}
2013-11-12 03:20:38 +04:00
if ( cut = = shortcut ( ) . toString ( ) ) {
return ; // no change
}
2007-04-29 21:35:43 +04:00
// Format:
// base+(abcdef)<space>base+(abcdef)
2013-02-13 16:57:21 +04:00
// E.g. Alt+Ctrl+(ABCDEF);Meta+X,Meta+(ABCDEF)
2015-11-05 17:14:06 +03:00
if ( ! cut . contains ( QLatin1Char ( ' ( ' ) ) & & ! cut . contains ( QLatin1Char ( ' ) ' ) ) & & ! cut . contains ( QLatin1String ( " - " ) ) ) {
2013-09-06 12:31:38 +04:00
if ( workspace ( ) - > shortcutAvailable ( cut , this ) )
2017-07-21 21:22:56 +03:00
updateShortcut ( QKeySequence ( cut ) ) ;
2007-04-29 21:35:43 +04:00
else
2017-07-21 21:22:56 +03:00
updateShortcut ( ) ;
2007-04-29 21:35:43 +04:00
return ;
2011-01-30 17:34:42 +03:00
}
2013-09-06 12:31:38 +04:00
QList < QKeySequence > keys ;
2013-07-23 09:02:52 +04:00
QStringList groups = cut . split ( QStringLiteral ( " - " ) ) ;
2011-01-30 17:34:42 +03:00
for ( QStringList : : ConstIterator it = groups . constBegin ( ) ;
it ! = groups . constEnd ( ) ;
+ + it ) {
2013-07-23 09:02:52 +04:00
QRegExp reg ( QStringLiteral ( " (.* \\ +) \ \ ( ( . * ) \ \ ) " )) ;
2011-01-30 17:34:42 +03:00
if ( reg . indexIn ( * it ) > - 1 ) {
QString base = reg . cap ( 1 ) ;
QString list = reg . cap ( 2 ) ;
for ( int i = 0 ;
i < list . length ( ) ;
+ + i ) {
2013-09-06 12:31:38 +04:00
QKeySequence c ( base + list [ i ] ) ;
2011-01-30 17:34:42 +03:00
if ( ! c . isEmpty ( ) )
keys . append ( c ) ;
2007-04-29 21:35:43 +04:00
}
2013-02-13 16:55:08 +04:00
} else {
// regexp doesn't match, so it should be a normal shortcut
2013-09-06 12:31:38 +04:00
QKeySequence c ( * it ) ;
2013-02-13 16:55:08 +04:00
if ( ! c . isEmpty ( ) ) {
keys . append ( c ) ;
}
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
}
2013-09-06 12:31:38 +04:00
for ( auto it = keys . constBegin ( ) ;
2011-01-30 17:34:42 +03:00
it ! = keys . constEnd ( ) ;
+ + it ) {
if ( _shortcut = = * it ) // current one is in the list
2007-04-29 21:35:43 +04:00
return ;
2011-01-30 17:34:42 +03:00
}
2013-09-06 12:31:38 +04:00
for ( auto it = keys . constBegin ( ) ;
2011-01-30 17:34:42 +03:00
it ! = keys . constEnd ( ) ;
+ + it ) {
if ( workspace ( ) - > shortcutAvailable ( * it , this ) ) {
2017-07-21 21:22:56 +03:00
updateShortcut ( * it ) ;
2007-04-29 21:35:43 +04:00
return ;
}
}
2017-07-21 21:22:56 +03:00
updateShortcut ( ) ;
2011-01-30 17:34:42 +03:00
}
2007-04-29 21:35:43 +04:00
2017-07-21 21:22:56 +03:00
void AbstractClient : : setShortcutInternal ( )
{
2017-08-03 08:11:40 +03:00
updateCaption ( ) ;
2017-07-21 21:22:56 +03:00
workspace ( ) - > clientShortcutUpdated ( this ) ;
}
void Client : : setShortcutInternal ( )
2011-01-30 17:34:42 +03:00
{
2007-04-29 21:35:43 +04:00
updateCaption ( ) ;
2008-09-30 16:03:20 +04:00
#if 0
2011-01-30 17:34:42 +03:00
workspace ( ) - > clientShortcutUpdated ( this ) ;
2008-09-30 16:03:20 +04:00
# else
// Workaround for kwin<->kglobalaccel deadlock, when KWin has X grab and the kded
// kglobalaccel module tries to create the key grab. KWin should preferably grab
// they keys itself anyway :(.
2017-07-20 20:07:25 +03:00
QTimer : : singleShot ( 0 , this , std : : bind ( & Workspace : : clientShortcutUpdated , workspace ( ) , this ) ) ;
2008-09-30 16:03:20 +04:00
# endif
2011-01-30 17:34:42 +03:00
}
2008-09-30 16:03:20 +04:00
2017-07-21 21:22:56 +03:00
bool Workspace : : shortcutAvailable ( const QKeySequence & cut , AbstractClient * ignore ) const
2011-01-30 17:34:42 +03:00
{
2013-11-12 03:20:38 +04:00
if ( ignore & & cut = = ignore - > shortcut ( ) )
return true ;
2013-02-13 16:53:45 +04:00
2013-09-06 12:31:38 +04:00
if ( ! KGlobalAccel : : getGlobalShortcutsByKey ( cut ) . isEmpty ( ) ) {
return false ;
2013-02-13 16:53:45 +04:00
}
2017-07-21 21:22:56 +03:00
for ( auto it = m_allClients . constBegin ( ) ;
it ! = m_allClients . constEnd ( ) ;
2011-01-30 17:34:42 +03:00
+ + it ) {
if ( ( * it ) ! = ignore & & ( * it ) - > shortcut ( ) = = cut )
2008-06-02 23:52:02 +04:00
return false ;
2007-04-29 21:35:43 +04:00
}
2011-01-30 17:34:42 +03:00
return true ;
}
2007-04-29 21:35:43 +04:00
} // namespace