2020-08-02 22:22:19 +00:00
/*
KWin - the KDE window manager
This file is part of the KDE project .
2007-04-29 17:35:43 +00:00
2020-08-02 22:22:19 +00:00
SPDX - FileCopyrightText : 1999 , 2000 Matthias Ettrich < ettrich @ kde . org >
SPDX - FileCopyrightText : 2003 Lubos Lunak < l . lunak @ kde . org >
SPDX - FileCopyrightText : 2019 Vlad Zahorodnii < vlad . zahorodnii @ kde . org >
2007-04-29 17:35:43 +00:00
2020-08-02 22:22:19 +00:00
SPDX - License - Identifier : GPL - 2.0 - or - later
*/
2013-04-25 14:08:39 +00:00
// own
2007-04-29 17:35:43 +00:00
# include "workspace.h"
2013-04-25 14:08:39 +00:00
// kwin libs
# include <kwinglplatform.h>
// kwin
# ifdef KWIN_BUILD_ACTIVITIES
# include "activities.h"
# endif
2017-01-11 09:21:03 +00:00
# include "appmenu.h"
2013-04-25 14:08:39 +00:00
# include "atoms.h"
2019-09-24 08:48:08 +00:00
# include "x11client.h"
2011-08-21 19:50:23 +00:00
# include "composite.h"
2013-04-25 14:08:39 +00:00
# include "cursor.h"
# include "dbusinterface.h"
# include "deleted.h"
# include "effects.h"
2012-11-20 16:26:50 +00:00
# include "focuschain.h"
2013-04-25 14:08:39 +00:00
# include "group.h"
2013-06-26 08:15:20 +00:00
# include "input.h"
2019-08-26 07:44:04 +00:00
# include "internal_client.h"
2017-08-17 19:12:28 +00:00
# include "moving_client_x11_filter.h"
2013-04-08 12:30:55 +00:00
# include "killwindow.h"
2013-04-26 08:41:24 +00:00
# include "netinfo.h"
2011-04-28 09:16:27 +00:00
# include "outline.h"
2013-04-25 14:08:39 +00:00
# include "placement.h"
2020-11-07 19:34:55 +00:00
# include "pluginmanager.h"
2007-04-29 17:35:43 +00:00
# include "rules.h"
2013-01-21 08:04:06 +00:00
# include "screenedge.h"
2013-04-25 14:08:39 +00:00
# include "screens.h"
2017-11-07 19:12:51 +00:00
# include "platform.h"
2012-04-12 13:19:38 +00:00
# include "scripting/scripting.h"
2020-04-27 11:01:17 +00:00
# include "syncalarmx11filter.h"
2013-04-25 14:08:39 +00:00
# ifdef KWIN_BUILD_TABBOX
# include "tabbox.h"
2013-03-15 15:49:20 +00:00
# endif
2013-04-25 14:08:39 +00:00
# include "unmanaged.h"
# include "useractions.h"
# include "virtualdesktops.h"
2017-08-17 17:10:45 +00:00
# include "was_user_interaction_x11_filter.h"
2015-03-04 08:21:10 +00:00
# include "wayland_server.h"
2013-04-25 14:08:39 +00:00
# include "xcbutils.h"
2013-08-28 12:10:51 +00:00
# include "main.h"
2014-07-22 11:11:19 +00:00
# include "decorations/decorationbridge.h"
2020-04-27 18:44:12 +00:00
# include "xwaylandclient.h"
2013-04-25 14:08:39 +00:00
// KDE
2014-03-17 15:24:10 +00:00
# include <KConfig>
# include <KConfigGroup>
# include <KLocalizedString>
# include <KStartupInfo>
2013-04-25 14:08:39 +00:00
// Qt
# include <QtConcurrentRun>
2020-10-30 15:32:49 +00:00
2007-04-29 17:35:43 +00:00
namespace KWin
{
extern int screen_number ;
2013-01-12 08:54:24 +00:00
extern bool is_multihead ;
2007-04-29 17:35:43 +00:00
2020-09-22 08:53:17 +00:00
X11EventFilterContainer : : X11EventFilterContainer ( X11EventFilter * filter )
: m_filter ( filter )
{
}
X11EventFilter * X11EventFilterContainer : : filter ( ) const
{
return m_filter ;
}
2013-04-30 12:55:06 +00:00
ColorMapper : : ColorMapper ( QObject * parent )
: QObject ( parent )
2020-07-28 07:58:35 +00:00
, m_default ( kwinApp ( ) - > x11DefaultScreen ( ) - > default_colormap )
, m_installed ( kwinApp ( ) - > x11DefaultScreen ( ) - > default_colormap )
2013-04-30 12:55:06 +00:00
{
}
ColorMapper : : ~ ColorMapper ( )
{
}
void ColorMapper : : update ( )
{
xcb_colormap_t cmap = m_default ;
2019-09-24 08:48:08 +00:00
if ( X11Client * c = dynamic_cast < X11Client * > ( Workspace : : self ( ) - > activeClient ( ) ) ) {
2013-04-30 12:55:06 +00:00
if ( c - > colormap ( ) ! = XCB_COLORMAP_NONE ) {
cmap = c - > colormap ( ) ;
}
}
if ( cmap ! = m_installed ) {
xcb_install_colormap ( connection ( ) , cmap ) ;
m_installed = cmap ;
}
}
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
Workspace * Workspace : : _self = nullptr ;
2007-04-29 17:35:43 +00:00
2020-04-02 11:44:27 +00:00
Workspace : : Workspace ( )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
: QObject ( nullptr )
, m_compositor ( nullptr )
2009-02-14 15:40:52 +00:00
// Unsorted
2020-09-09 13:31:19 +00:00
, m_quickTileCombineTimer ( nullptr )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
, active_popup ( nullptr )
, active_popup_client ( nullptr )
2015-05-01 14:55:15 +00:00
, m_initialDesktop ( 1 )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
, active_client ( nullptr )
, last_active_client ( nullptr )
, most_recently_raised ( nullptr )
, movingClient ( nullptr )
, delayfocus_client ( nullptr )
2011-01-30 14:34:42 +00:00
, force_restacking ( false )
, showing_desktop ( false )
, was_user_interaction ( false )
, block_focus ( 0 )
2012-08-19 10:00:53 +00:00
, m_userActionsMenu ( new UserActionsMenu ( this ) )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
, client_keys_dialog ( nullptr )
, client_keys_client ( nullptr )
2011-01-30 14:34:42 +00:00
, global_shortcuts_disabled_for_client ( false )
, workspaceInit ( true )
, set_active_client_recursion ( 0 )
, block_stacking_updates ( 0 )
2020-08-26 17:24:02 +00:00
, m_sessionManager ( new SessionManager ( this ) )
2011-01-30 14:34:42 +00:00
{
2012-04-12 17:42:49 +00:00
// If KWin was already running it saved its configuration after loosing the selection -> Reread
QFuture < void > reparseConfigFuture = QtConcurrent : : run ( options , & Options : : reparseConfiguration ) ;
2017-01-11 09:21:03 +00:00
ApplicationMenu : : create ( this ) ;
2007-04-29 17:35:43 +00:00
_self = this ;
2012-04-13 06:39:04 +00:00
2013-04-04 14:14:12 +00:00
# ifdef KWIN_BUILD_ACTIVITIES
2015-07-07 09:48:42 +00:00
Activities * activities = nullptr ;
2015-11-24 08:01:46 +00:00
if ( kwinApp ( ) - > usesKActivities ( ) ) {
2015-07-07 09:48:42 +00:00
activities = Activities : : create ( this ) ;
}
if ( activities ) {
2020-09-23 18:39:59 +00:00
connect ( activities , & Activities : : currentChanged , this , & Workspace : : updateCurrentActivity ) ;
2015-07-07 09:48:42 +00:00
}
2013-04-04 14:14:12 +00:00
# endif
2012-04-12 17:42:49 +00:00
// PluginMgr needs access to the config file, so we need to wait for it for finishing
reparseConfigFuture . waitForFinished ( ) ;
2013-06-16 11:56:28 +00:00
2012-04-12 17:42:49 +00:00
options - > loadConfig ( ) ;
options - > loadCompositingConfig ( false ) ;
2007-04-29 17:35:43 +00:00
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
delayFocusTimer = nullptr ;
2007-04-29 17:35:43 +00:00
2020-06-12 13:50:24 +00:00
m_quickTileCombineTimer = new QTimer ( this ) ;
m_quickTileCombineTimer - > setSingleShot ( true ) ;
2013-04-26 12:40:35 +00:00
RuleBook : : create ( this ) - > load ( ) ;
2007-04-29 17:35:43 +00:00
2020-03-24 12:39:55 +00:00
kwinApp ( ) - > createScreens ( ) ;
2013-01-25 09:15:00 +00:00
ScreenEdges : : create ( this ) ;
2012-11-17 10:50:59 +00:00
// VirtualDesktopManager needs to be created prior to init shortcuts
// and prior to TabBox, due to TabBox connecting to signals
// actual initialization happens in init()
VirtualDesktopManager : : create ( this ) ;
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
//dbus interface
new VirtualDesktopManagerDBusInterface ( VirtualDesktopManager : : self ( ) ) ;
2012-11-17 10:50:59 +00:00
2011-06-30 11:02:30 +00:00
# ifdef KWIN_BUILD_TABBOX
2011-03-06 11:15:16 +00:00
// need to create the tabbox before compositing scene is setup
2013-04-04 07:41:18 +00:00
TabBox : : TabBox : : create ( this ) ;
2011-06-30 11:02:30 +00:00
# endif
2011-10-29 14:55:56 +00:00
2015-02-23 14:57:00 +00:00
if ( Compositor : : self ( ) ) {
m_compositor = Compositor : : self ( ) ;
} else {
2019-08-07 17:33:20 +00:00
Q_ASSERT ( kwinApp ( ) - > operationMode ( ) = = Application : : OperationMode : : OperationModeX11 ) ;
m_compositor = X11Compositor : : create ( this ) ;
2015-02-23 14:57:00 +00:00
}
2015-03-06 11:38:07 +00:00
connect ( this , & Workspace : : currentDesktopChanged , m_compositor , & Compositor : : addRepaintFull ) ;
2016-01-29 11:59:39 +00:00
connect ( m_compositor , & QObject : : destroyed , this , [ this ] { m_compositor = nullptr ; } ) ;
2014-07-22 11:11:19 +00:00
2014-10-30 08:01:06 +00:00
auto decorationBridge = Decoration : : DecorationBridge : : create ( this ) ;
decorationBridge - > init ( ) ;
connect ( this , & Workspace : : configChanged , decorationBridge , & Decoration : : DecorationBridge : : reconfigure ) ;
2012-08-30 06:20:26 +00:00
2020-04-02 11:44:27 +00:00
connect ( m_sessionManager , & SessionManager : : loadSessionRequested , this , & Workspace : : loadSessionInfo ) ;
connect ( m_sessionManager , & SessionManager : : prepareSessionSaveRequested , this , [ this ] ( const QString & name ) {
storeSession ( name , SMSavePhase0 ) ;
} ) ;
connect ( m_sessionManager , & SessionManager : : finishSessionSaveRequested , this , [ this ] ( const QString & name ) {
storeSession ( name , SMSavePhase2 ) ;
} ) ;
2012-08-30 06:20:26 +00:00
new DBusInterface ( this ) ;
2013-04-25 06:14:34 +00:00
Outline : : create ( this ) ;
2011-07-13 16:48:56 +00:00
initShortcuts ( ) ;
2007-04-29 17:35:43 +00:00
init ( ) ;
2011-07-24 20:56:55 +00:00
}
2007-04-29 17:35:43 +00:00
void Workspace : : init ( )
2011-01-30 14:34:42 +00:00
{
2016-01-29 10:24:18 +00:00
KSharedConfigPtr config = kwinApp ( ) - > config ( ) ;
2013-04-03 10:19:27 +00:00
Screens * screens = Screens : : self ( ) ;
2015-04-22 06:25:37 +00:00
// get screen support
2020-09-23 18:39:59 +00:00
connect ( screens , & Screens : : changed , this , & Workspace : : desktopResized ) ;
2013-09-04 14:10:36 +00:00
screens - > setConfig ( config ) ;
2013-04-03 10:19:27 +00:00
screens - > reconfigure ( ) ;
2020-09-23 18:39:59 +00:00
connect ( options , & Options : : configChanged , screens , & Screens : : reconfigure ) ;
2013-01-25 09:15:00 +00:00
ScreenEdges * screenEdges = ScreenEdges : : self ( ) ;
2013-09-04 14:10:36 +00:00
screenEdges - > setConfig ( config ) ;
2013-01-25 09:15:00 +00:00
screenEdges - > init ( ) ;
2020-09-23 18:39:59 +00:00
connect ( options , & Options : : configChanged , screenEdges , & ScreenEdges : : reconfigure ) ;
connect ( VirtualDesktopManager : : self ( ) , & VirtualDesktopManager : : layoutChanged , screenEdges , & ScreenEdges : : updateLayout ) ;
2015-03-06 12:58:24 +00:00
connect ( this , & Workspace : : clientActivated , screenEdges , & ScreenEdges : : checkBlocking ) ;
2007-04-29 17:35:43 +00:00
2012-11-20 16:26:50 +00:00
FocusChain * focusChain = FocusChain : : create ( this ) ;
2015-03-05 09:24:54 +00:00
connect ( this , & Workspace : : clientRemoved , focusChain , & FocusChain : : remove ) ;
connect ( this , & Workspace : : clientActivated , focusChain , & FocusChain : : setActiveClient ) ;
2020-09-23 18:39:59 +00:00
connect ( VirtualDesktopManager : : self ( ) , & VirtualDesktopManager : : countChanged , focusChain , & FocusChain : : resize ) ;
connect ( VirtualDesktopManager : : self ( ) , & VirtualDesktopManager : : currentChanged , focusChain , & FocusChain : : setCurrentDesktop ) ;
connect ( options , & Options : : separateScreenFocusChanged , focusChain , & FocusChain : : setSeparateScreenFocus ) ;
2012-11-20 16:26:50 +00:00
focusChain - > setSeparateScreenFocus ( options - > isSeparateScreenFocus ( ) ) ;
2012-11-16 07:23:47 +00:00
// create VirtualDesktopManager and perform dependency injection
VirtualDesktopManager * vds = VirtualDesktopManager : : self ( ) ;
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
connect ( vds , & VirtualDesktopManager : : desktopRemoved , this ,
[ this ] ( KWin : : VirtualDesktop * desktop ) {
//Wayland
if ( kwinApp ( ) - > operationMode ( ) = = Application : : OperationModeWaylandOnly | |
kwinApp ( ) - > operationMode ( ) = = Application : : OperationModeXwayland ) {
for ( auto it = m_allClients . constBegin ( ) ; it ! = m_allClients . constEnd ( ) ; + + it ) {
2018-12-14 11:05:53 +00:00
if ( ! ( * it ) - > desktops ( ) . contains ( desktop ) ) {
continue ;
}
if ( ( * it ) - > desktops ( ) . count ( ) > 1 ) {
( * it ) - > leaveDesktop ( desktop ) ;
} else {
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
sendClientToDesktop ( * it , qMin ( desktop - > x11DesktopNumber ( ) , VirtualDesktopManager : : self ( ) - > count ( ) ) , true ) ;
}
}
//X11
} else {
for ( auto it = m_allClients . constBegin ( ) ; it ! = m_allClients . constEnd ( ) ; + + it ) {
if ( ! ( * it ) - > isOnAllDesktops ( ) & & ( ( * it ) - > desktop ( ) > static_cast < int > ( VirtualDesktopManager : : self ( ) - > count ( ) ) ) ) {
sendClientToDesktop ( * it , VirtualDesktopManager : : self ( ) - > count ( ) , true ) ;
}
}
}
}
) ;
2020-09-23 18:39:59 +00:00
connect ( vds , & VirtualDesktopManager : : countChanged , this , & Workspace : : slotDesktopCountChanged ) ;
connect ( vds , & VirtualDesktopManager : : currentChanged , this , & Workspace : : slotCurrentDesktopChanged ) ;
2012-11-16 07:23:47 +00:00
vds - > setNavigationWrappingAround ( options - > isRollOverDesktops ( ) ) ;
2020-09-23 18:39:59 +00:00
connect ( options , & Options : : rollOverDesktopsChanged , vds , & VirtualDesktopManager : : setNavigationWrappingAround ) ;
2013-09-04 14:10:36 +00:00
vds - > setConfig ( config ) ;
2012-05-01 16:34:38 +00:00
2012-05-26 19:06:40 +00:00
// Now we know how many desktops we'll have, thus we initialize the positioning object
2012-11-22 12:41:50 +00:00
Placement : : create ( this ) ;
2012-05-26 19:06:40 +00:00
2012-11-16 07:23:47 +00:00
// positioning object needs to be created before the virtual desktops are loaded.
vds - > load ( ) ;
vds - > updateLayout ( ) ;
[wayland] Use the new plasma virtual desktop protocol
Summary:
implement virtual desktop support for Wayland.
use the new virtual desktop protocol from D12820
The VirtualDesktopManager class needed some big change in order
to accomodate it, which is where most changes are.
Other than that, it's mostly connections to wire up
VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl)
Depends on D12820
Other notable detail, is the client visibility updated to reflect the presence
of the client in the plasmavirtualdesktop.
(and the unSetDesktop concept)
Test Plan: used a bit a plasma session together with D12820, D13748 and D13746
Reviewers: #plasma, #kwin, graesslin, davidedmundson
Reviewed By: #plasma, #kwin, davidedmundson
Subscribers: hein, zzag, davidedmundson, kwin
Tags: #kwin
Maniphest Tasks: T4457
Differential Revision: https://phabricator.kde.org/D13887
2018-10-29 22:29:15 +00:00
//makes sure any autogenerated id is saved, necessary as in case of xwayland, load will be called 2 times
// load is needed to be called again when starting xwayalnd to sync to RootInfo, see BUG 385260
vds - > save ( ) ;
2012-11-16 07:23:47 +00:00
2015-05-01 14:55:15 +00:00
if ( ! VirtualDesktopManager : : self ( ) - > setCurrent ( m_initialDesktop ) )
2012-11-16 07:23:47 +00:00
VirtualDesktopManager : : self ( ) - > setCurrent ( 1 ) ;
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
reconfigureTimer . setSingleShot ( true ) ;
updateToolWindowsTimer . setSingleShot ( true ) ;
2007-04-29 17:35:43 +00:00
2020-09-23 18:39:59 +00:00
connect ( & reconfigureTimer , & QTimer : : timeout , this , & Workspace : : slotReconfigure ) ;
connect ( & updateToolWindowsTimer , & QTimer : : timeout , this , & Workspace : : slotUpdateToolWindows ) ;
2007-04-29 17:35:43 +00:00
2013-12-06 09:00:44 +00:00
// TODO: do we really need to reconfigure everything when fonts change?
// maybe just reconfigure the decorations? Move this into libkdecoration?
QDBusConnection : : sessionBus ( ) . connect ( QString ( ) ,
QStringLiteral ( " /KDEPlatformTheme " ) ,
QStringLiteral ( " org.kde.KDEPlatformTheme " ) ,
QStringLiteral ( " refreshFonts " ) ,
this , SLOT ( reconfigure ( ) ) ) ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
active_client = nullptr ;
2007-04-29 17:35:43 +00:00
2020-07-20 08:07:08 +00:00
// We want to have some xcb connection while tearing down X11 components. We don't really
// care if the xcb connection is broken or has an error.
connect ( kwinApp ( ) , & Application : : x11ConnectionChanged , this , & Workspace : : initializeX11 ) ;
connect ( kwinApp ( ) , & Application : : x11ConnectionAboutToBeDestroyed , this , & Workspace : : cleanupX11 ) ;
initializeX11 ( ) ;
2009-09-08 20:01:08 +00:00
2013-04-04 07:11:17 +00:00
Scripting : : create ( this ) ;
2012-04-12 13:19:38 +00:00
2020-03-04 07:55:26 +00:00
if ( auto server = waylandServer ( ) ) {
connect ( server , & WaylandServer : : shellClientAdded , this , & Workspace : : addShellClient ) ;
connect ( server , & WaylandServer : : shellClientRemoved , this , & Workspace : : removeShellClient ) ;
2015-03-04 08:21:10 +00:00
}
2008-12-18 13:50:57 +00:00
// SELI TODO: This won't work with unreasonable focus policies,
2007-04-29 17:35:43 +00:00
// and maybe in rare cases also if the selected client doesn't
// want focus
workspaceInit = false ;
2008-12-18 13:50:57 +00:00
2012-04-13 09:27:50 +00:00
// broadcast that Workspace is ready, but first process all events.
QMetaObject : : invokeMethod ( this , " workspaceInitialized " , Qt : : QueuedConnection ) ;
2008-12-18 13:50:57 +00:00
// TODO: ungrabXServer()
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2020-07-20 08:07:08 +00:00
void Workspace : : initializeX11 ( )
2017-09-20 18:02:02 +00:00
{
if ( ! kwinApp ( ) - > x11Connection ( ) ) {
return ;
}
atoms - > retrieveHelpers ( ) ;
// first initialize the extensions
Xcb : : Extensions : : self ( ) ;
2020-07-20 08:07:08 +00:00
m_colorMapper . reset ( new ColorMapper ( this ) ) ;
connect ( this , & Workspace : : clientActivated , m_colorMapper . data ( ) , & ColorMapper : : update ) ;
2017-09-20 18:02:02 +00:00
// Call this before XSelectInput() on the root window
2020-07-20 08:07:08 +00:00
m_startup . reset ( new KStartupInfo (
KStartupInfo : : DisableKWinModule | KStartupInfo : : AnnounceSilenceChanges , this ) ) ;
2017-09-20 18:02:02 +00:00
// Select windowmanager privileges
selectWmInputEventMask ( ) ;
// Compatibility
int32_t data = 1 ;
xcb_change_property ( connection ( ) , XCB_PROP_MODE_APPEND , rootWindow ( ) , atoms - > kwin_running ,
atoms - > kwin_running , 32 , 1 , & data ) ;
if ( kwinApp ( ) - > operationMode ( ) = = Application : : OperationModeX11 ) {
m_wasUserInteractionFilter . reset ( new WasUserInteractionX11Filter ) ;
m_movingClientFilter . reset ( new MovingClientX11Filter ) ;
}
2020-04-27 11:01:17 +00:00
if ( Xcb : : Extensions : : self ( ) - > isSyncAvailable ( ) ) {
m_syncAlarmFilter . reset ( new SyncAlarmX11Filter ) ;
}
2017-09-20 18:02:02 +00:00
updateXTime ( ) ; // Needed for proper initialization of user_time in Client ctor
const uint32_t nullFocusValues [ ] = { true } ;
m_nullFocus . reset ( new Xcb : : Window ( QRect ( - 1 , - 1 , 1 , 1 ) , XCB_WINDOW_CLASS_INPUT_ONLY , XCB_CW_OVERRIDE_REDIRECT , nullFocusValues ) ) ;
m_nullFocus - > map ( ) ;
RootInfo * rootInfo = RootInfo : : create ( ) ;
2017-10-01 13:37:41 +00:00
const auto vds = VirtualDesktopManager : : self ( ) ;
vds - > setRootInfo ( rootInfo ) ;
2020-07-15 15:49:54 +00:00
rootInfo - > activate ( ) ;
2017-09-20 18:02:02 +00:00
// TODO: only in X11 mode
// Extra NETRootInfo instance in Client mode is needed to get the values of the properties
NETRootInfo client_info ( connection ( ) , NET : : ActiveWindow | NET : : CurrentDesktop ) ;
2019-03-04 14:09:55 +00:00
if ( ! qApp - > isSessionRestored ( ) ) {
2017-09-20 18:02:02 +00:00
m_initialDesktop = client_info . currentDesktop ( ) ;
2019-03-04 14:09:55 +00:00
vds - > setCurrent ( m_initialDesktop ) ;
}
2017-09-20 18:02:02 +00:00
// TODO: better value
2020-12-10 08:54:14 +00:00
rootInfo - > setActiveWindow ( XCB_WINDOW_NONE ) ;
2017-09-20 18:02:02 +00:00
focusToNull ( ) ;
if ( ! qApp - > isSessionRestored ( ) )
+ + block_focus ; // Because it will be set below
{
// Begin updates blocker block
StackingUpdatesBlocker blocker ( this ) ;
Xcb : : Tree tree ( rootWindow ( ) ) ;
xcb_window_t * wins = xcb_query_tree_children ( tree . data ( ) ) ;
QVector < Xcb : : WindowAttributes > windowAttributes ( tree - > children_len ) ;
QVector < Xcb : : WindowGeometry > windowGeometries ( tree - > children_len ) ;
// Request the attributes and geometries of all toplevel windows
for ( int i = 0 ; i < tree - > children_len ; i + + ) {
windowAttributes [ i ] = Xcb : : WindowAttributes ( wins [ i ] ) ;
windowGeometries [ i ] = Xcb : : WindowGeometry ( wins [ i ] ) ;
}
// Get the replies
for ( int i = 0 ; i < tree - > children_len ; i + + ) {
Xcb : : WindowAttributes attr ( windowAttributes . at ( i ) ) ;
if ( attr . isNull ( ) ) {
continue ;
}
if ( attr - > override_redirect ) {
if ( attr - > map_state = = XCB_MAP_STATE_VIEWABLE & &
attr - > _class ! = XCB_WINDOW_CLASS_INPUT_ONLY )
// ### This will request the attributes again
createUnmanaged ( wins [ i ] ) ;
} else if ( attr - > map_state ! = XCB_MAP_STATE_UNMAPPED ) {
if ( Application : : wasCrash ( ) ) {
fixPositionAfterCrash ( wins [ i ] , windowGeometries . at ( i ) . data ( ) ) ;
}
// ### This will request the attributes again
createClient ( wins [ i ] , true ) ;
}
}
// Propagate clients, will really happen at the end of the updates blocker block
updateStackingOrder ( true ) ;
saveOldScreenSizes ( ) ;
updateClientArea ( ) ;
// NETWM spec says we have to set it to (0,0) if we don't support it
NETPoint * viewports = new NETPoint [ VirtualDesktopManager : : self ( ) - > count ( ) ] ;
rootInfo - > setDesktopViewport ( VirtualDesktopManager : : self ( ) - > count ( ) , * viewports ) ;
delete [ ] viewports ;
QRect geom ;
for ( int i = 0 ; i < screens ( ) - > count ( ) ; i + + ) {
geom | = screens ( ) - > geometry ( i ) ;
}
NETSize desktop_geometry ;
desktop_geometry . width = geom . width ( ) ;
desktop_geometry . height = geom . height ( ) ;
rootInfo - > setDesktopGeometry ( desktop_geometry ) ;
setShowingDesktop ( false ) ;
} // End updates blocker block
// TODO: only on X11?
AbstractClient * new_active_client = nullptr ;
if ( ! qApp - > isSessionRestored ( ) ) {
- - block_focus ;
new_active_client = findClient ( Predicate : : WindowMatch , client_info . activeWindow ( ) ) ;
}
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( new_active_client = = nullptr
& & activeClient ( ) = = nullptr & & should_get_focus . count ( ) = = 0 ) {
2017-09-20 18:02:02 +00:00
// No client activated in manage()
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( new_active_client = = nullptr )
2017-09-20 18:02:02 +00:00
new_active_client = topClientOnDesktop ( VirtualDesktopManager : : self ( ) - > current ( ) , - 1 ) ;
2020-05-08 07:45:30 +00:00
if ( new_active_client = = nullptr )
2017-09-20 18:02:02 +00:00
new_active_client = findDesktop ( true , VirtualDesktopManager : : self ( ) - > current ( ) ) ;
}
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( new_active_client ! = nullptr )
2017-09-20 18:02:02 +00:00
activateClient ( new_active_client ) ;
}
2020-07-20 08:07:08 +00:00
void Workspace : : cleanupX11 ( )
2011-01-30 14:34:42 +00:00
{
2020-07-20 08:07:08 +00:00
// We expect that other components will unregister their X11 event filters after the
// connection to the X server has been lost.
2008-12-18 13:50:57 +00:00
2020-07-20 08:07:08 +00:00
StackingUpdatesBlocker blocker ( this ) ;
2008-12-18 13:50:57 +00:00
2020-07-20 08:07:08 +00:00
// Use stacking_order, so that kwin --replace keeps stacking order.
const QList < X11Client * > orderedClients = ensureStackingOrder ( clients ) ;
for ( X11Client * client : orderedClients ) {
client - > releaseWindow ( true ) ;
unconstrained_stacking_order . removeOne ( client ) ;
stacking_order . removeOne ( client ) ;
}
2013-08-11 17:02:53 +00:00
2020-10-09 15:58:51 +00:00
// We need a shadow copy because windows get removed as we go through them.
const QList < Unmanaged * > unmanaged = m_unmanaged ;
for ( Unmanaged * overrideRedirect : unmanaged ) {
2020-07-20 08:07:08 +00:00
overrideRedirect - > release ( ReleaseReason : : KWinShutsDown ) ;
unconstrained_stacking_order . removeOne ( overrideRedirect ) ;
stacking_order . removeOne ( overrideRedirect ) ;
2011-01-30 14:34:42 +00:00
}
2020-07-20 08:07:08 +00:00
manual_overlays . clear ( ) ;
VirtualDesktopManager * desktopManager = VirtualDesktopManager : : self ( ) ;
desktopManager - > setRootInfo ( nullptr ) ;
2019-09-24 08:48:08 +00:00
X11Client : : cleanupX11 ( ) ;
2020-07-20 08:07:08 +00:00
RootInfo : : destroy ( ) ;
Xcb : : Extensions : : destroy ( ) ;
if ( xcb_connection_t * connection = kwinApp ( ) - > x11Connection ( ) ) {
xcb_delete_property ( connection , kwinApp ( ) - > x11RootWindow ( ) , atoms - > kwin_running ) ;
}
m_colorMapper . reset ( ) ;
m_movingClientFilter . reset ( ) ;
m_startup . reset ( ) ;
m_nullFocus . reset ( ) ;
m_syncAlarmFilter . reset ( ) ;
m_wasUserInteractionFilter . reset ( ) ;
m_xStackingQueryTree . reset ( ) ;
}
Workspace : : ~ Workspace ( )
{
blockStackingUpdates ( true ) ;
cleanupX11 ( ) ;
2019-09-10 07:40:36 +00:00
if ( waylandServer ( ) ) {
2020-03-04 07:55:26 +00:00
const QList < AbstractClient * > shellClients = waylandServer ( ) - > clients ( ) ;
for ( AbstractClient * client : shellClients ) {
2020-02-19 15:22:23 +00:00
client - > destroyClient ( ) ;
2019-09-10 07:40:36 +00:00
}
}
2020-10-09 15:58:51 +00:00
// We need a shadow copy because clients get removed as we go through them.
const QList < InternalClient * > internalClients = m_internalClients ;
for ( InternalClient * client : internalClients ) {
2019-08-26 07:44:04 +00:00
client - > destroyClient ( ) ;
}
2016-08-18 09:44:48 +00:00
for ( auto it = deleted . begin ( ) ; it ! = deleted . end ( ) ; ) {
emit deletedRemoved ( * it ) ;
it = deleted . erase ( it ) ;
}
2013-04-26 12:40:35 +00:00
delete RuleBook : : self ( ) ;
2016-01-29 10:24:18 +00:00
kwinApp ( ) - > config ( ) - > sync ( ) ;
2007-04-29 17:35:43 +00:00
2012-11-22 12:41:50 +00:00
delete Placement : : self ( ) ;
2007-11-01 19:24:35 +00:00
delete client_keys_dialog ;
2020-03-27 13:25:02 +00:00
qDeleteAll ( session ) ;
2008-12-18 13:50:57 +00:00
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
_self = nullptr ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2016-07-01 14:03:13 +00:00
void Workspace : : setupClientConnections ( AbstractClient * c )
{
connect ( c , & AbstractClient : : desktopPresenceChanged , this , & Workspace : : desktopPresenceChanged ) ;
2017-10-04 19:02:16 +00:00
connect ( c , & AbstractClient : : minimizedChanged , this , std : : bind ( & Workspace : : clientMinimizedChanged , this , c ) ) ;
2016-07-01 14:03:13 +00:00
}
2019-09-24 08:48:08 +00:00
X11Client * Workspace : : createClient ( xcb_window_t w , bool is_mapped )
2011-01-30 14:34:42 +00:00
{
StackingUpdatesBlocker blocker ( this ) ;
2020-04-27 18:44:12 +00:00
X11Client * c = nullptr ;
if ( kwinApp ( ) - > operationMode ( ) = = Application : : OperationModeX11 ) {
c = new X11Client ( ) ;
} else {
c = new XwaylandClient ( ) ;
}
2016-07-01 14:03:13 +00:00
setupClientConnections ( c ) ;
[x11] Fix crash during tear down
Summary:
Any call made to a virtual method in constructor/destructor of a base
class won't go to a derived class because the base class may access
uninitialized or destroyed resources.
For example, let's consider the following two classes
class Base {
public:
Base() { foo()->bar(); }
virtual ~Base() { foo()->bar(); }
virtual Foo* foo() const { return nullptr; }
};
class Derived : public Base {
public:
Derived() : mFoo(new Foo) {}
~Derived() override { delete mFoo; }
Foo* foo() const override { return mFoo; }
private:
Foo* mFoo;
};
When an instance of Derived class is created, constructors will run in
the following order:
Base()
Derived()
It's not safe to dispatch foo() method call to Derived class because
constructor of Derived hasn't initialized yet mFoo.
Same story with destructors, they'll run in the following order:
~Derived()
~Base()
It's not safe to dispatch foo() method call in the destructor of Base
class to Derived class because mFoo was deleted.
So, what does that weird C++ behavior has something to do with KWin? Well,
recently Compositor class was split into two classes - WaylandCompositor,
and X11Compositor. Some functionality from X11 doesn't make sense on
Wayland. Therefore methods that implement that stuff were "purified," i.e.
they became pure virtual methods. Unfortunately, when Compositor tears
down it may call pure virtual methods on itself. Given that those calls
cannot be dispatched to X11Compositor or WaylandCompositor, the only
choice that C++ runtime has is to throw an exception.
The fix for this very delicate problem is very simple - do not call virtual
methods from constructors and the destructor. Avoid doing that if you can!
This change moves Compositor::updateClientCompositeBlocking to X11Compositor
so it longer has to be a virtual method. Also, it kind of doesn't make sense
to keep it in base Compositor class because compositing can be blocked only
on X11.
BUG: 411049
Test Plan: KWin no longer crashes when running kwin_x11 --replace command.
Reviewers: #kwin, romangg
Reviewed By: #kwin, romangg
Subscribers: anthonyfieroni, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23098
2019-08-30 16:28:50 +00:00
if ( X11Compositor * compositor = X11Compositor : : self ( ) ) {
2019-09-24 08:48:08 +00:00
connect ( c , & X11Client : : blockingCompositingChanged , compositor , & X11Compositor : : updateClientCompositeBlocking ) ;
[x11] Fix crash during tear down
Summary:
Any call made to a virtual method in constructor/destructor of a base
class won't go to a derived class because the base class may access
uninitialized or destroyed resources.
For example, let's consider the following two classes
class Base {
public:
Base() { foo()->bar(); }
virtual ~Base() { foo()->bar(); }
virtual Foo* foo() const { return nullptr; }
};
class Derived : public Base {
public:
Derived() : mFoo(new Foo) {}
~Derived() override { delete mFoo; }
Foo* foo() const override { return mFoo; }
private:
Foo* mFoo;
};
When an instance of Derived class is created, constructors will run in
the following order:
Base()
Derived()
It's not safe to dispatch foo() method call to Derived class because
constructor of Derived hasn't initialized yet mFoo.
Same story with destructors, they'll run in the following order:
~Derived()
~Base()
It's not safe to dispatch foo() method call in the destructor of Base
class to Derived class because mFoo was deleted.
So, what does that weird C++ behavior has something to do with KWin? Well,
recently Compositor class was split into two classes - WaylandCompositor,
and X11Compositor. Some functionality from X11 doesn't make sense on
Wayland. Therefore methods that implement that stuff were "purified," i.e.
they became pure virtual methods. Unfortunately, when Compositor tears
down it may call pure virtual methods on itself. Given that those calls
cannot be dispatched to X11Compositor or WaylandCompositor, the only
choice that C++ runtime has is to throw an exception.
The fix for this very delicate problem is very simple - do not call virtual
methods from constructors and the destructor. Avoid doing that if you can!
This change moves Compositor::updateClientCompositeBlocking to X11Compositor
so it longer has to be a virtual method. Also, it kind of doesn't make sense
to keep it in base Compositor class because compositing can be blocked only
on X11.
BUG: 411049
Test Plan: KWin no longer crashes when running kwin_x11 --replace command.
Reviewers: #kwin, romangg
Reviewed By: #kwin, romangg
Subscribers: anthonyfieroni, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23098
2019-08-30 16:28:50 +00:00
}
2020-09-23 18:39:59 +00:00
connect ( c , & X11Client : : clientFullScreenSet , ScreenEdges : : self ( ) , & ScreenEdges : : checkBlocking ) ;
2012-10-15 16:57:21 +00:00
if ( ! c - > manage ( w , is_mapped ) ) {
2019-09-24 08:48:08 +00:00
X11Client : : deleteClient ( c ) ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
return nullptr ;
2012-10-15 16:57:21 +00:00
}
2013-04-26 07:47:45 +00:00
addClient ( c ) ;
2007-04-29 17:35:43 +00:00
return c ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2013-04-30 13:41:59 +00:00
Unmanaged * Workspace : : createUnmanaged ( xcb_window_t w )
2011-01-30 14:34:42 +00:00
{
2019-09-05 07:51:47 +00:00
if ( X11Compositor * compositor = X11Compositor : : self ( ) ) {
if ( compositor - > checkForOverlayWindow ( w ) ) {
return nullptr ;
}
}
2013-05-08 11:39:06 +00:00
Unmanaged * c = new Unmanaged ( ) ;
2011-01-30 14:34:42 +00:00
if ( ! c - > track ( w ) ) {
2013-04-26 07:47:45 +00:00
Unmanaged : : deleteUnmanaged ( c ) ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
return nullptr ;
2007-04-29 17:35:43 +00:00
}
2013-04-26 07:47:45 +00:00
addUnmanaged ( c ) ;
2011-02-25 21:06:02 +00:00
emit unmanagedAdded ( c ) ;
2011-01-30 14:34:42 +00:00
return c ;
}
2019-09-24 08:48:08 +00:00
void Workspace : : addClient ( X11Client * c )
2011-01-30 14:34:42 +00:00
{
Group * grp = findGroup ( c - > window ( ) ) ;
2007-04-29 17:35:43 +00:00
2010-09-21 14:31:40 +00:00
emit clientAdded ( c ) ;
2011-01-30 14:34:42 +00:00
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( grp ! = nullptr )
2011-01-30 14:34:42 +00:00
grp - > gotLeader ( c ) ;
if ( c - > isDesktop ( ) ) {
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( active_client = = nullptr & & should_get_focus . isEmpty ( ) & & c - > isOnCurrentDesktop ( ) )
2011-01-30 14:34:42 +00:00
requestFocus ( c ) ; // TODO: Make sure desktop is active after startup if there's no other window active
} else {
2012-11-20 16:26:50 +00:00
FocusChain : : self ( ) - > update ( c , FocusChain : : Update ) ;
2011-01-30 14:34:42 +00:00
}
2020-05-08 07:45:30 +00:00
clients . append ( c ) ;
m_allClients . append ( c ) ;
2011-01-30 14:34:42 +00:00
if ( ! unconstrained_stacking_order . contains ( c ) )
unconstrained_stacking_order . append ( c ) ; // Raise if it hasn't got any stacking position yet
if ( ! stacking_order . contains ( c ) ) // It'll be updated later, and updateToolWindows() requires
stacking_order . append ( c ) ; // c to be in stacking_order
2017-06-21 04:56:53 +00:00
markXStackingOrderAsDirty ( ) ;
2008-12-18 13:50:57 +00:00
updateClientArea ( ) ; // This cannot be in manage(), because the client got added only now
2011-01-30 14:34:42 +00:00
updateClientLayer ( c ) ;
if ( c - > isDesktop ( ) ) {
raiseClient ( c ) ;
2008-12-18 13:50:57 +00:00
// If there's no active client, make this desktop the active one
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( activeClient ( ) = = nullptr & & should_get_focus . count ( ) = = 0 )
2012-11-16 07:23:47 +00:00
activateClient ( findDesktop ( true , VirtualDesktopManager : : self ( ) - > current ( ) ) ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
c - > checkActiveModal ( ) ;
2011-01-30 14:34:42 +00:00
checkTransients ( c - > window ( ) ) ; // SELI TODO: Does this really belong here?
updateStackingOrder ( true ) ; // Propagate new client
if ( c - > isUtility ( ) | | c - > isMenu ( ) | | c - > isToolbar ( ) )
updateToolWindows ( true ) ;
2019-07-29 18:24:09 +00:00
updateTabbox ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2013-04-26 07:47:45 +00:00
void Workspace : : addUnmanaged ( Unmanaged * c )
2011-01-30 14:34:42 +00:00
{
2020-10-09 15:49:32 +00:00
m_unmanaged . append ( c ) ;
2017-06-21 04:56:53 +00:00
markXStackingOrderAsDirty ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
/**
* Destroys the client \ a c
2019-07-29 18:58:33 +00:00
*/
2019-09-24 08:48:08 +00:00
void Workspace : : removeClient ( X11Client * c )
2011-01-30 14:34:42 +00:00
{
2007-04-29 17:35:43 +00:00
if ( c = = active_popup_client )
closeActivePopup ( ) ;
2012-08-19 10:00:53 +00:00
if ( m_userActionsMenu - > isMenuClient ( c ) ) {
m_userActionsMenu - > close ( ) ;
}
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
if ( client_keys_client = = c )
setupWindowShortcutDone ( false ) ;
if ( ! c - > shortcut ( ) . isEmpty ( ) ) {
c - > setShortcut ( QString ( ) ) ; // Remove from client_keys
clientShortcutUpdated ( c ) ; // Needed, since this is otherwise delayed by setShortcut() and wouldn't run
}
2007-04-29 17:35:43 +00:00
2020-05-08 07:45:30 +00:00
Q_ASSERT ( clients . contains ( c ) ) ;
2010-04-25 16:43:14 +00:00
// TODO: if marked client is removed, notify the marked list
2011-01-30 14:34:42 +00:00
clients . removeAll ( c ) ;
2015-09-18 11:44:54 +00:00
m_allClients . removeAll ( c ) ;
2017-06-21 04:56:53 +00:00
markXStackingOrderAsDirty ( ) ;
2011-01-30 14:34:42 +00:00
attention_chain . removeAll ( c ) ;
Group * group = findGroup ( c - > window ( ) ) ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( group ! = nullptr )
2007-04-29 17:35:43 +00:00
group - > lostLeader ( ) ;
2011-01-30 14:34:42 +00:00
if ( c = = most_recently_raised )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
most_recently_raised = nullptr ;
2011-01-30 14:34:42 +00:00
should_get_focus . removeAll ( c ) ;
2020-07-20 08:07:08 +00:00
if ( c = = active_client )
active_client = nullptr ;
2011-01-30 14:34:42 +00:00
if ( c = = last_active_client )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
last_active_client = nullptr ;
2011-01-30 14:34:42 +00:00
if ( c = = delayfocus_client )
2007-04-29 17:35:43 +00:00
cancelDelayFocus ( ) ;
[x11] Emit clientRemoved after client was removed
Summary:
Currently, there is a guarantee that a client, which is about to be removed,
is no longer in the stacking order(both in constrained and unconstrained)
when Workspace::removeClient is called. However, because the client gets
removed from m_allClients after clientRemoved is emitted, it can be
re-inserted back into the stacking order.
In general, the pattern is to do some work and then notify others about
what you've done by emitting a signal. In the case of Workspace::removeClient,
we emit clientRemoved way before the client actually gets removed.
CCBUG: 392412
CCBUG: 400854
Test Plan:
* Enable the following script:
```lang=js
workspace.clientAdded.connect(function (client) {
if (client.skipTaskbar || client.modal || client.transient) {
return;
}
workspace.desktops = workspace.desktops + 1;
workspace.currentDesktop = workspace.desktops;
client.desktop = workspace.currentDesktop;
});
workspace.clientRemoved.connect(function (client) {
if (client.skipTaskbar || client.modal || client.transient) {
return;
}
workspace.desktops = workspace.desktops - 1;
});
```
* Open an app, close the app.
Reviewers: #kwin, graesslin
Reviewed By: #kwin, graesslin
Subscribers: graesslin, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D17069
2018-11-20 20:06:42 +00:00
emit clientRemoved ( c ) ;
2011-01-30 14:34:42 +00:00
updateStackingOrder ( true ) ;
2007-04-29 17:35:43 +00:00
updateClientArea ( ) ;
2019-07-29 18:24:09 +00:00
updateTabbox ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2013-04-26 07:47:45 +00:00
void Workspace : : removeUnmanaged ( Unmanaged * c )
2011-01-30 14:34:42 +00:00
{
2020-10-09 15:49:32 +00:00
Q_ASSERT ( m_unmanaged . contains ( c ) ) ;
m_unmanaged . removeAll ( c ) ;
2013-07-01 06:37:59 +00:00
emit unmanagedRemoved ( c ) ;
2017-06-21 04:56:53 +00:00
markXStackingOrderAsDirty ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2013-04-26 07:47:45 +00:00
void Workspace : : addDeleted ( Deleted * c , Toplevel * orig )
2011-01-30 14:34:42 +00:00
{
2019-08-31 14:28:37 +00:00
Q_ASSERT ( ! deleted . contains ( c ) ) ;
2011-01-30 14:34:42 +00:00
deleted . append ( c ) ;
2012-04-09 09:06:44 +00:00
const int unconstraintedIndex = unconstrained_stacking_order . indexOf ( orig ) ;
if ( unconstraintedIndex ! = - 1 ) {
unconstrained_stacking_order . replace ( unconstraintedIndex , c ) ;
} else {
unconstrained_stacking_order . append ( c ) ;
}
const int index = stacking_order . indexOf ( orig ) ;
if ( index ! = - 1 ) {
stacking_order . replace ( index , c ) ;
} else {
stacking_order . append ( c ) ;
}
2017-06-21 04:56:53 +00:00
markXStackingOrderAsDirty ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2013-04-26 07:47:45 +00:00
void Workspace : : removeDeleted ( Deleted * c )
2011-01-30 14:34:42 +00:00
{
2019-08-31 14:28:37 +00:00
Q_ASSERT ( deleted . contains ( c ) ) ;
2011-02-27 09:47:42 +00:00
emit deletedRemoved ( c ) ;
2011-01-30 14:34:42 +00:00
deleted . removeAll ( c ) ;
2012-04-09 09:06:44 +00:00
unconstrained_stacking_order . removeAll ( c ) ;
stacking_order . removeAll ( c ) ;
2017-06-21 04:56:53 +00:00
markXStackingOrderAsDirty ( ) ;
[x11] Fix crash during tear down
Summary:
Any call made to a virtual method in constructor/destructor of a base
class won't go to a derived class because the base class may access
uninitialized or destroyed resources.
For example, let's consider the following two classes
class Base {
public:
Base() { foo()->bar(); }
virtual ~Base() { foo()->bar(); }
virtual Foo* foo() const { return nullptr; }
};
class Derived : public Base {
public:
Derived() : mFoo(new Foo) {}
~Derived() override { delete mFoo; }
Foo* foo() const override { return mFoo; }
private:
Foo* mFoo;
};
When an instance of Derived class is created, constructors will run in
the following order:
Base()
Derived()
It's not safe to dispatch foo() method call to Derived class because
constructor of Derived hasn't initialized yet mFoo.
Same story with destructors, they'll run in the following order:
~Derived()
~Base()
It's not safe to dispatch foo() method call in the destructor of Base
class to Derived class because mFoo was deleted.
So, what does that weird C++ behavior has something to do with KWin? Well,
recently Compositor class was split into two classes - WaylandCompositor,
and X11Compositor. Some functionality from X11 doesn't make sense on
Wayland. Therefore methods that implement that stuff were "purified," i.e.
they became pure virtual methods. Unfortunately, when Compositor tears
down it may call pure virtual methods on itself. Given that those calls
cannot be dispatched to X11Compositor or WaylandCompositor, the only
choice that C++ runtime has is to throw an exception.
The fix for this very delicate problem is very simple - do not call virtual
methods from constructors and the destructor. Avoid doing that if you can!
This change moves Compositor::updateClientCompositeBlocking to X11Compositor
so it longer has to be a virtual method. Also, it kind of doesn't make sense
to keep it in base Compositor class because compositing can be blocked only
on X11.
BUG: 411049
Test Plan: KWin no longer crashes when running kwin_x11 --replace command.
Reviewers: #kwin, romangg
Reviewed By: #kwin, romangg
Subscribers: anthonyfieroni, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23098
2019-08-30 16:28:50 +00:00
if ( ! c - > wasClient ( ) ) {
return ;
}
if ( X11Compositor * compositor = X11Compositor : : self ( ) ) {
compositor - > updateClientCompositeBlocking ( ) ;
2013-06-23 22:13:08 +00:00
}
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2020-03-04 07:55:26 +00:00
void Workspace : : addShellClient ( AbstractClient * client )
{
setupClientConnections ( client ) ;
updateClientLayer ( client ) ;
2020-08-19 07:31:38 +00:00
if ( client - > isPlaceable ( ) ) {
const QRect area = clientArea ( PlacementArea , Screens : : self ( ) - > current ( ) , client - > desktop ( ) ) ;
bool placementDone = false ;
if ( client - > isFullScreen ( ) ) {
placementDone = true ;
}
if ( client - > maximizeMode ( ) = = MaximizeMode : : MaximizeFull ) {
placementDone = true ;
}
if ( client - > rules ( ) - > checkPosition ( invalidPoint , true ) ! = invalidPoint ) {
placementDone = true ;
}
if ( ! placementDone ) {
client - > placeIn ( area ) ;
}
2020-03-04 07:55:26 +00:00
}
m_allClients . append ( client ) ;
if ( ! unconstrained_stacking_order . contains ( client ) ) {
unconstrained_stacking_order . append ( client ) ; // Raise if it hasn't got any stacking position yet
}
if ( ! stacking_order . contains ( client ) ) { // It'll be updated later, and updateToolWindows() requires
stacking_order . append ( client ) ; // client to be in stacking_order
}
markXStackingOrderAsDirty ( ) ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
if ( client - > wantsInput ( ) & & ! client - > isMinimized ( ) ) {
activateClient ( client ) ;
}
updateTabbox ( ) ;
connect ( client , & AbstractClient : : windowShown , this , [ this , client ] {
updateClientLayer ( client ) ;
markXStackingOrderAsDirty ( ) ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
if ( client - > wantsInput ( ) ) {
activateClient ( client ) ;
}
} ) ;
connect ( client , & AbstractClient : : windowHidden , this , [ this ] {
// TODO: update tabbox if it's displayed
markXStackingOrderAsDirty ( ) ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
} ) ;
2020-07-22 18:35:41 +00:00
emit clientAdded ( client ) ;
2020-03-04 07:55:26 +00:00
}
void Workspace : : removeShellClient ( AbstractClient * client )
{
2020-07-20 08:07:08 +00:00
clientHidden ( client ) ;
2020-03-04 07:55:26 +00:00
m_allClients . removeAll ( client ) ;
if ( client = = most_recently_raised ) {
most_recently_raised = nullptr ;
}
if ( client = = delayfocus_client ) {
cancelDelayFocus ( ) ;
}
2020-07-20 08:07:08 +00:00
if ( client = = active_client ) {
active_client = nullptr ;
}
2020-03-04 07:55:26 +00:00
if ( client = = last_active_client ) {
last_active_client = nullptr ;
}
if ( client_keys_client = = client ) {
setupWindowShortcutDone ( false ) ;
}
if ( ! client - > shortcut ( ) . isEmpty ( ) ) {
client - > setShortcut ( QString ( ) ) ; // Remove from client_keys
}
emit clientRemoved ( client ) ;
markXStackingOrderAsDirty ( ) ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
updateTabbox ( ) ;
}
2011-01-30 14:34:42 +00:00
void Workspace : : updateToolWindows ( bool also_hide )
{
2008-12-18 13:50:57 +00:00
// TODO: What if Client's transiency/group changes? should this be called too? (I'm paranoid, am I not?)
2012-02-20 09:25:13 +00:00
if ( ! options - > isHideUtilityWindowsForInactive ( ) ) {
Drop some custom list typedefs
Summary:
Qt has its own thing where a type might also have corresponding list
alias, e.g. QObject and QObjectList, QWidget and QWidgetList. I don't
know why Qt does that, maybe for some historical reasons, but what
matters is that we copy this pattern here in KWin. While this pattern
might be useful with some long list types, for example
QList<QWeakPointer<TabBoxClient>> TabBoxClientList
in general, it causes more harm than good. For example, we've got two
new client types, do we need corresponding list typedefs for them? If
no, why do we have ClientList and so on?
Another problem with these typedefs is that you need to include utils.h
header in order to use them. A better way to handle such things is to
just forward declare a client class (if that's possible) and use it
directly with QList or QVector. This way translation units don't get
"bloated" with utils.h stuff for no apparent reason.
So, in order to make code more consistent and easier to follow, this
change drops some of our custom typedefs. Namely ConstClientList,
ClientList, DeletedList, UnmanagedList, ToplevelList, and GroupList.
Test Plan: Compiles.
Reviewers: #kwin
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24950
2019-10-16 09:11:04 +00:00
for ( auto it = clients . constBegin ( ) ; it ! = clients . constEnd ( ) ; + + it )
2019-09-14 08:58:12 +00:00
( * it ) - > hideClient ( false ) ;
2007-04-29 17:35:43 +00:00
return ;
2011-01-30 14:34:42 +00:00
}
2018-12-31 17:57:13 +00:00
const Group * group = nullptr ;
auto client = active_client ;
2008-12-18 13:50:57 +00:00
// Go up in transiency hiearchy, if the top is found, only tool transients for the top mainwindow
// will be shown; if a group transient is group, all tools in the group will be shown
2018-12-31 17:57:13 +00:00
while ( client ! = nullptr ) {
2011-01-30 14:34:42 +00:00
if ( ! client - > isTransient ( ) )
2007-04-29 17:35:43 +00:00
break ;
2011-01-30 14:34:42 +00:00
if ( client - > groupTransient ( ) ) {
2007-04-29 17:35:43 +00:00
group = client - > group ( ) ;
break ;
}
2018-12-31 17:57:13 +00:00
client = client - > transientFor ( ) ;
2011-01-30 14:34:42 +00:00
}
2008-12-18 13:50:57 +00:00
// Use stacking order only to reduce flicker, it doesn't matter if block_stacking_updates == 0,
// I.e. if it's not up to date
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
// SELI TODO: But maybe it should - what if a new client has been added that's not in stacking order yet?
2018-12-31 17:57:13 +00:00
QVector < AbstractClient * > to_show , to_hide ;
Drop some custom list typedefs
Summary:
Qt has its own thing where a type might also have corresponding list
alias, e.g. QObject and QObjectList, QWidget and QWidgetList. I don't
know why Qt does that, maybe for some historical reasons, but what
matters is that we copy this pattern here in KWin. While this pattern
might be useful with some long list types, for example
QList<QWeakPointer<TabBoxClient>> TabBoxClientList
in general, it causes more harm than good. For example, we've got two
new client types, do we need corresponding list typedefs for them? If
no, why do we have ClientList and so on?
Another problem with these typedefs is that you need to include utils.h
header in order to use them. A better way to handle such things is to
just forward declare a client class (if that's possible) and use it
directly with QList or QVector. This way translation units don't get
"bloated" with utils.h stuff for no apparent reason.
So, in order to make code more consistent and easier to follow, this
change drops some of our custom typedefs. Namely ConstClientList,
ClientList, DeletedList, UnmanagedList, ToplevelList, and GroupList.
Test Plan: Compiles.
Reviewers: #kwin
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24950
2019-10-16 09:11:04 +00:00
for ( auto it = stacking_order . constBegin ( ) ;
2011-01-30 14:34:42 +00:00
it ! = stacking_order . constEnd ( ) ;
+ + it ) {
2018-12-31 17:57:13 +00:00
auto c = qobject_cast < AbstractClient * > ( * it ) ;
2012-04-08 08:07:35 +00:00
if ( ! c ) {
continue ;
}
if ( c - > isUtility ( ) | | c - > isMenu ( ) | | c - > isToolbar ( ) ) {
2007-04-29 17:35:43 +00:00
bool show = true ;
2012-04-08 08:07:35 +00:00
if ( ! c - > isTransient ( ) ) {
2018-12-31 17:57:13 +00:00
if ( ! c - > group ( ) | | c - > group ( ) - > members ( ) . count ( ) = = 1 ) // Has its own group, keep always visible
2007-04-29 17:35:43 +00:00
show = true ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
else if ( client ! = nullptr & & c - > group ( ) = = client - > group ( ) )
2007-04-29 17:35:43 +00:00
show = true ;
else
show = false ;
2011-01-30 14:34:42 +00:00
} else {
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( group ! = nullptr & & c - > group ( ) = = group )
2007-04-29 17:35:43 +00:00
show = true ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
else if ( client ! = nullptr & & client - > hasTransient ( c , true ) )
2007-04-29 17:35:43 +00:00
show = true ;
else
show = false ;
2011-01-30 14:34:42 +00:00
}
if ( ! show & & also_hide ) {
2015-09-11 13:55:23 +00:00
const auto mainclients = c - > mainClients ( ) ;
2008-12-18 13:50:57 +00:00
// Don't hide utility windows which are standalone(?) or
2007-04-29 17:35:43 +00:00
// have e.g. kicker as mainwindow
2011-01-30 14:34:42 +00:00
if ( mainclients . isEmpty ( ) )
2007-04-29 17:35:43 +00:00
show = true ;
2015-09-11 13:55:23 +00:00
for ( auto it2 = mainclients . constBegin ( ) ;
2011-01-30 14:34:42 +00:00
it2 ! = mainclients . constEnd ( ) ;
+ + it2 ) {
2013-06-28 18:31:04 +00:00
if ( ( * it2 ) - > isSpecialWindow ( ) )
2007-04-29 17:35:43 +00:00
show = true ;
}
2011-01-30 14:34:42 +00:00
if ( ! show )
2012-04-08 08:07:35 +00:00
to_hide . append ( c ) ;
2007-04-29 17:35:43 +00:00
}
2011-01-30 14:34:42 +00:00
if ( show )
2012-04-08 08:07:35 +00:00
to_show . append ( c ) ;
2011-01-30 14:34:42 +00:00
}
} // First show new ones, then hide
for ( int i = to_show . size ( ) - 1 ;
i > = 0 ;
- - i ) // From topmost
2008-12-18 13:50:57 +00:00
// TODO: Since this is in stacking order, the order of taskbar entries changes :(
2011-01-30 14:34:42 +00:00
to_show . at ( i ) - > hideClient ( false ) ;
if ( also_hide ) {
2018-12-31 17:57:13 +00:00
for ( auto it = to_hide . constBegin ( ) ;
2011-01-30 14:34:42 +00:00
it ! = to_hide . constEnd ( ) ;
+ + it ) // From bottommost
( * it ) - > hideClient ( true ) ;
2007-04-29 17:35:43 +00:00
updateToolWindowsTimer . stop ( ) ;
2011-01-30 14:34:42 +00:00
} else // setActiveClient() is after called with NULL client, quickly followed
// by setting a new client, which would result in flickering
2010-12-31 13:44:17 +00:00
resetUpdateToolWindowsTimer ( ) ;
2011-01-30 14:34:42 +00:00
}
2010-12-31 13:44:17 +00:00
void Workspace : : resetUpdateToolWindowsTimer ( )
2011-01-30 14:34:42 +00:00
{
updateToolWindowsTimer . start ( 200 ) ;
}
2007-04-29 17:35:43 +00:00
void Workspace : : slotUpdateToolWindows ( )
2011-01-30 14:34:42 +00:00
{
updateToolWindows ( true ) ;
}
2007-04-29 17:35:43 +00:00
2008-01-30 16:08:23 +00:00
void Workspace : : slotReloadConfig ( )
2011-01-30 14:34:42 +00:00
{
2008-12-18 13:50:57 +00:00
reconfigure ( ) ;
2011-01-30 14:34:42 +00:00
}
2012-11-09 12:44:50 +00:00
2007-04-29 17:35:43 +00:00
void Workspace : : reconfigure ( )
2011-01-30 14:34:42 +00:00
{
reconfigureTimer . start ( 200 ) ;
}
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
/**
* Reread settings
2019-07-29 18:58:33 +00:00
*/
2007-04-29 17:35:43 +00:00
void Workspace : : slotReconfigure ( )
2011-01-30 14:34:42 +00:00
{
2014-12-05 10:42:15 +00:00
qCDebug ( KWIN_CORE ) < < " Workspace::slotReconfigure() " ;
2007-04-29 17:35:43 +00:00
reconfigureTimer . stop ( ) ;
2010-10-26 14:43:29 +00:00
bool borderlessMaximizedWindows = options - > borderlessMaximizedWindows ( ) ;
2016-01-29 10:24:18 +00:00
kwinApp ( ) - > config ( ) - > reparseConfiguration ( ) ;
2013-08-23 10:36:30 +00:00
options - > updateSettings ( ) ;
2008-11-25 01:45:09 +00:00
2011-07-13 09:36:49 +00:00
emit configChanged ( ) ;
2012-08-19 10:00:53 +00:00
m_userActionsMenu - > discard ( ) ;
2011-01-30 14:34:42 +00:00
updateToolWindows ( true ) ;
2007-04-29 17:35:43 +00:00
2013-04-26 12:40:35 +00:00
RuleBook : : self ( ) - > load ( ) ;
2020-08-20 19:41:58 +00:00
for ( AbstractClient * client : m_allClients ) {
if ( client - > supportsWindowRules ( ) ) {
client - > evaluateWindowRules ( ) ;
RuleBook : : self ( ) - > discardUsed ( client , false ) ;
}
2011-01-30 14:34:42 +00:00
}
2010-04-25 16:43:14 +00:00
2011-01-30 14:34:42 +00:00
if ( borderlessMaximizedWindows ! = options - > borderlessMaximizedWindows ( ) & &
! options - > borderlessMaximizedWindows ( ) ) {
2010-10-26 14:43:29 +00:00
// in case borderless maximized windows option changed and new option
// is to have borders, we need to unset the borders for all maximized windows
2017-10-01 19:48:57 +00:00
for ( auto it = m_allClients . begin ( ) ;
it ! = m_allClients . end ( ) ;
2011-01-30 14:34:42 +00:00
+ + it ) {
2014-12-02 12:49:08 +00:00
if ( ( * it ) - > maximizeMode ( ) = = MaximizeFull )
2010-10-26 14:43:29 +00:00
( * it ) - > checkNoBorder ( ) ;
}
2011-01-30 14:34:42 +00:00
}
}
2007-04-29 17:35:43 +00:00
2012-11-16 07:23:47 +00:00
void Workspace : : slotCurrentDesktopChanged ( uint oldDesktop , uint newDesktop )
2011-01-30 14:34:42 +00:00
{
2007-04-29 17:35:43 +00:00
closeActivePopup ( ) ;
+ + block_focus ;
2011-01-30 14:34:42 +00:00
StackingUpdatesBlocker blocker ( this ) ;
2017-10-01 07:51:09 +00:00
updateClientVisibilityOnDesktopChange ( newDesktop ) ;
2012-11-16 07:23:47 +00:00
// Restore the focus on this desktop
- - block_focus ;
2007-04-29 17:35:43 +00:00
2012-11-16 07:23:47 +00:00
activateClientOnNewDesktop ( newDesktop ) ;
emit currentDesktopChanged ( oldDesktop , movingClient ) ;
}
2007-04-29 17:35:43 +00:00
2017-10-01 07:51:09 +00:00
void Workspace : : updateClientVisibilityOnDesktopChange ( uint newDesktop )
2012-11-16 07:23:47 +00:00
{
Drop some custom list typedefs
Summary:
Qt has its own thing where a type might also have corresponding list
alias, e.g. QObject and QObjectList, QWidget and QWidgetList. I don't
know why Qt does that, maybe for some historical reasons, but what
matters is that we copy this pattern here in KWin. While this pattern
might be useful with some long list types, for example
QList<QWeakPointer<TabBoxClient>> TabBoxClientList
in general, it causes more harm than good. For example, we've got two
new client types, do we need corresponding list typedefs for them? If
no, why do we have ClientList and so on?
Another problem with these typedefs is that you need to include utils.h
header in order to use them. A better way to handle such things is to
just forward declare a client class (if that's possible) and use it
directly with QList or QVector. This way translation units don't get
"bloated" with utils.h stuff for no apparent reason.
So, in order to make code more consistent and easier to follow, this
change drops some of our custom typedefs. Namely ConstClientList,
ClientList, DeletedList, UnmanagedList, ToplevelList, and GroupList.
Test Plan: Compiles.
Reviewers: #kwin
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24950
2019-10-16 09:11:04 +00:00
for ( auto it = stacking_order . constBegin ( ) ;
2012-11-16 07:23:47 +00:00
it ! = stacking_order . constEnd ( ) ;
+ + it ) {
2019-09-24 08:48:08 +00:00
X11Client * c = qobject_cast < X11Client * > ( * it ) ;
2012-11-16 07:23:47 +00:00
if ( ! c ) {
continue ;
2011-01-30 14:34:42 +00:00
}
2012-11-16 07:23:47 +00:00
if ( ! c - > isOnDesktop ( newDesktop ) & & c ! = movingClient & & c - > isOnCurrentActivity ( ) ) {
( c ) - > updateVisibility ( ) ;
2012-04-08 08:07:35 +00:00
}
2011-01-30 14:34:42 +00:00
}
2012-11-16 07:23:47 +00:00
// Now propagate the change, after hiding, before showing
2017-08-07 04:57:37 +00:00
if ( rootInfo ( ) ) {
rootInfo ( ) - > setCurrentDesktop ( VirtualDesktopManager : : self ( ) - > current ( ) ) ;
}
2007-04-29 17:35:43 +00:00
2012-11-16 07:23:47 +00:00
if ( movingClient & & ! movingClient - > isOnDesktop ( newDesktop ) ) {
movingClient - > setDesktop ( newDesktop ) ;
}
2011-08-22 11:53:03 +00:00
2012-11-16 07:23:47 +00:00
for ( int i = stacking_order . size ( ) - 1 ; i > = 0 ; - - i ) {
2019-09-24 08:48:08 +00:00
X11Client * c = qobject_cast < X11Client * > ( stacking_order . at ( i ) ) ;
2011-01-30 14:34:42 +00:00
if ( ! c ) {
2012-11-16 07:23:47 +00:00
continue ;
2007-04-29 17:35:43 +00:00
}
2012-11-16 07:23:47 +00:00
if ( c - > isOnDesktop ( newDesktop ) & & c - > isOnCurrentActivity ( ) )
c - > updateVisibility ( ) ;
}
if ( showingDesktop ( ) ) // Do this only after desktop change to avoid flicker
2015-02-18 00:37:45 +00:00
setShowingDesktop ( false ) ;
2012-11-16 07:23:47 +00:00
}
void Workspace : : activateClientOnNewDesktop ( uint desktop )
{
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
AbstractClient * c = nullptr ;
2012-11-16 07:23:47 +00:00
if ( options - > focusPolicyIsReasonable ( ) ) {
c = findClientToActivateOnDesktop ( desktop ) ;
2011-01-30 14:34:42 +00:00
}
2008-12-18 13:50:57 +00:00
// If "unreasonable focus policy" and active_client is on_all_desktops and
// under mouse (Hence == old_active_client), conserve focus.
// (Thanks to Volker Schatz <V.Schatz at thphys.uni-heidelberg.de>)
2011-01-30 14:34:42 +00:00
else if ( active_client & & active_client - > isShown ( true ) & & active_client - > isOnCurrentDesktop ( ) )
2008-12-18 13:50:57 +00:00
c = active_client ;
2007-04-29 17:35:43 +00:00
2020-05-08 07:45:30 +00:00
if ( ! c )
2012-11-16 07:23:47 +00:00
c = findDesktop ( true , desktop ) ;
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
if ( c ! = active_client )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
setActiveClient ( nullptr ) ;
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
if ( c )
requestFocus ( c ) ;
2007-04-29 17:35:43 +00:00
else
focusToNull ( ) ;
2012-11-16 07:23:47 +00:00
}
2007-04-29 17:35:43 +00:00
2015-03-12 11:08:54 +00:00
AbstractClient * Workspace : : findClientToActivateOnDesktop ( uint desktop )
2012-11-16 07:23:47 +00:00
{
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
if ( movingClient ! = nullptr & & active_client = = movingClient & &
2012-11-20 16:26:50 +00:00
FocusChain : : self ( ) - > contains ( active_client , desktop ) & &
2012-11-16 07:23:47 +00:00
active_client - > isShown ( true ) & & active_client - > isOnCurrentDesktop ( ) ) {
// A requestFocus call will fail, as the client is already active
return active_client ;
}
// from actiavtion.cpp
if ( options - > isNextFocusPrefersMouse ( ) ) {
Drop some custom list typedefs
Summary:
Qt has its own thing where a type might also have corresponding list
alias, e.g. QObject and QObjectList, QWidget and QWidgetList. I don't
know why Qt does that, maybe for some historical reasons, but what
matters is that we copy this pattern here in KWin. While this pattern
might be useful with some long list types, for example
QList<QWeakPointer<TabBoxClient>> TabBoxClientList
in general, it causes more harm than good. For example, we've got two
new client types, do we need corresponding list typedefs for them? If
no, why do we have ClientList and so on?
Another problem with these typedefs is that you need to include utils.h
header in order to use them. A better way to handle such things is to
just forward declare a client class (if that's possible) and use it
directly with QList or QVector. This way translation units don't get
"bloated" with utils.h stuff for no apparent reason.
So, in order to make code more consistent and easier to follow, this
change drops some of our custom typedefs. Namely ConstClientList,
ClientList, DeletedList, UnmanagedList, ToplevelList, and GroupList.
Test Plan: Compiles.
Reviewers: #kwin
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24950
2019-10-16 09:11:04 +00:00
auto it = stackingOrder ( ) . constEnd ( ) ;
2012-11-16 07:23:47 +00:00
while ( it ! = stackingOrder ( ) . constBegin ( ) ) {
2021-01-26 16:52:59 +00:00
AbstractClient * client = qobject_cast < AbstractClient * > ( * ( - - it ) ) ;
2012-11-16 07:23:47 +00:00
if ( ! client ) {
continue ;
}
2007-04-29 17:35:43 +00:00
2012-11-16 07:23:47 +00:00
if ( ! ( client - > isShown ( false ) & & client - > isOnDesktop ( desktop ) & &
2013-04-03 10:19:27 +00:00
client - > isOnCurrentActivity ( ) & & client - > isOnActiveScreen ( ) ) )
2012-11-16 07:23:47 +00:00
continue ;
2007-04-29 17:35:43 +00:00
2020-04-02 16:18:01 +00:00
if ( client - > frameGeometry ( ) . contains ( Cursors : : self ( ) - > mouse ( ) - > pos ( ) ) ) {
2012-11-16 07:23:47 +00:00
if ( ! client - > isDesktop ( ) )
return client ;
break ; // unconditional break - we do not pass the focus to some client below an unusable one
}
}
}
2012-11-20 16:26:50 +00:00
return FocusChain : : self ( ) - > getForActivation ( desktop ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2010-05-11 20:30:20 +00:00
/**
* Updates the current activity when it changes
* do * not * call this directly ; it does not set the activity .
*
* Shows / Hides windows according to the stacking order
2019-07-29 18:58:33 +00:00
*/
2012-04-12 19:52:44 +00:00
2010-05-11 20:30:20 +00:00
void Workspace : : updateCurrentActivity ( const QString & new_activity )
2011-01-30 14:34:42 +00:00
{
2013-04-04 14:14:12 +00:00
# ifdef KWIN_BUILD_ACTIVITIES
2015-07-07 09:48:42 +00:00
if ( ! Activities : : self ( ) ) {
return ;
}
2010-05-11 20:30:20 +00:00
//closeActivePopup();
+ + block_focus ;
// TODO: Q_ASSERT( block_stacking_updates == 0 ); // Make sure stacking_order is up to date
2011-01-30 14:34:42 +00:00
StackingUpdatesBlocker blocker ( this ) ;
2010-05-11 20:30:20 +00:00
2013-04-04 14:14:12 +00:00
// Optimized Desktop switching: unmapping done from back to front
// mapping done from front to back => less exposure events
//Notify::raise((Notify::Event) (Notify::DesktopChange+new_desktop));
2010-05-11 20:30:20 +00:00
Drop some custom list typedefs
Summary:
Qt has its own thing where a type might also have corresponding list
alias, e.g. QObject and QObjectList, QWidget and QWidgetList. I don't
know why Qt does that, maybe for some historical reasons, but what
matters is that we copy this pattern here in KWin. While this pattern
might be useful with some long list types, for example
QList<QWeakPointer<TabBoxClient>> TabBoxClientList
in general, it causes more harm than good. For example, we've got two
new client types, do we need corresponding list typedefs for them? If
no, why do we have ClientList and so on?
Another problem with these typedefs is that you need to include utils.h
header in order to use them. A better way to handle such things is to
just forward declare a client class (if that's possible) and use it
directly with QList or QVector. This way translation units don't get
"bloated" with utils.h stuff for no apparent reason.
So, in order to make code more consistent and easier to follow, this
change drops some of our custom typedefs. Namely ConstClientList,
ClientList, DeletedList, UnmanagedList, ToplevelList, and GroupList.
Test Plan: Compiles.
Reviewers: #kwin
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24950
2019-10-16 09:11:04 +00:00
for ( auto it = stacking_order . constBegin ( ) ;
2013-04-04 14:14:12 +00:00
it ! = stacking_order . constEnd ( ) ;
+ + it ) {
2019-09-24 08:48:08 +00:00
X11Client * c = qobject_cast < X11Client * > ( * it ) ;
2013-04-04 14:14:12 +00:00
if ( ! c ) {
continue ;
}
if ( ! c - > isOnActivity ( new_activity ) & & c ! = movingClient & & c - > isOnCurrentDesktop ( ) ) {
c - > updateVisibility ( ) ;
2012-04-08 08:07:35 +00:00
}
2013-04-04 14:14:12 +00:00
}
2010-05-11 20:30:20 +00:00
2013-04-04 14:14:12 +00:00
// Now propagate the change, after hiding, before showing
//rootInfo->setCurrentDesktop( currentDesktop() );
2010-05-11 20:30:20 +00:00
2013-04-04 14:14:12 +00:00
/* TODO someday enable dragging windows to other activities
if ( movingClient & & ! movingClient - > isOnDesktop ( new_desktop ) )
{
movingClient - > setDesktop ( new_desktop ) ;
*/
2010-05-11 20:30:20 +00:00
2013-04-04 14:14:12 +00:00
for ( int i = stacking_order . size ( ) - 1 ; i > = 0 ; - - i ) {
2019-09-24 08:48:08 +00:00
X11Client * c = qobject_cast < X11Client * > ( stacking_order . at ( i ) ) ;
2013-04-04 14:14:12 +00:00
if ( ! c ) {
continue ;
2012-04-08 08:07:35 +00:00
}
2013-04-04 14:14:12 +00:00
if ( c - > isOnActivity ( new_activity ) )
c - > updateVisibility ( ) ;
2011-01-30 14:34:42 +00:00
}
2010-05-11 20:30:20 +00:00
2013-04-04 14:14:12 +00:00
//FIXME not sure if I should do this either
if ( showingDesktop ( ) ) // Do this only after desktop change to avoid flicker
2015-02-18 00:37:45 +00:00
setShowingDesktop ( false ) ;
2013-04-04 14:14:12 +00:00
2010-05-11 20:30:20 +00:00
// Restore the focus on this desktop
- - block_focus ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
AbstractClient * c = nullptr ;
2010-05-11 20:30:20 +00:00
//FIXME below here is a lot of focuschain stuff, probably all wrong now
2011-01-30 14:34:42 +00:00
if ( options - > focusPolicyIsReasonable ( ) ) {
// Search in focus chain
2012-11-20 16:26:50 +00:00
c = FocusChain : : self ( ) - > getForActivation ( VirtualDesktopManager : : self ( ) - > current ( ) ) ;
2011-01-30 14:34:42 +00:00
}
2010-05-11 20:30:20 +00:00
// If "unreasonable focus policy" and active_client is on_all_desktops and
// under mouse (Hence == old_active_client), conserve focus.
// (Thanks to Volker Schatz <V.Schatz at thphys.uni-heidelberg.de>)
2011-01-30 14:34:42 +00:00
else if ( active_client & & active_client - > isShown ( true ) & & active_client - > isOnCurrentDesktop ( ) & & active_client - > isOnCurrentActivity ( ) )
2010-05-11 20:30:20 +00:00
c = active_client ;
2020-05-08 07:45:30 +00:00
if ( ! c )
2012-11-16 07:23:47 +00:00
c = findDesktop ( true , VirtualDesktopManager : : self ( ) - > current ( ) ) ;
2010-05-11 20:30:20 +00:00
2011-01-30 14:34:42 +00:00
if ( c ! = active_client )
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
setActiveClient ( nullptr ) ;
2010-05-11 20:30:20 +00:00
2011-01-30 14:34:42 +00:00
if ( c )
requestFocus ( c ) ;
2010-05-11 20:30:20 +00:00
else
focusToNull ( ) ;
// Not for the very first time, only if something changed and there are more than 1 desktops
2011-01-30 14:34:42 +00:00
//if ( effects != NULL && old_desktop != 0 && old_desktop != new_desktop )
2010-05-11 20:30:20 +00:00
// static_cast<EffectsHandlerImpl*>( effects )->desktopChanged( old_desktop );
2011-08-21 19:50:23 +00:00
if ( compositing ( ) & & m_compositor )
m_compositor - > addRepaintFull ( ) ;
2013-04-04 14:14:12 +00:00
# else
Q_UNUSED ( new_activity )
# endif
2011-01-30 14:34:42 +00:00
}
2010-09-24 12:03:22 +00:00
2012-11-16 07:23:47 +00:00
void Workspace : : slotDesktopCountChanged ( uint previousCount , uint newCount )
2011-01-30 14:34:42 +00:00
{
2012-11-17 10:50:59 +00:00
Q_UNUSED ( previousCount )
2012-11-22 12:41:50 +00:00
Placement : : self ( ) - > reinitCascading ( 0 ) ;
2007-04-29 17:35:43 +00:00
2012-11-16 07:23:47 +00:00
resetClientAreas ( newCount ) ;
}
2009-04-06 16:09:34 +00:00
2012-11-16 07:23:47 +00:00
void Workspace : : resetClientAreas ( uint desktopCount )
{
// Make it +1, so that it can be accessed as [1..numberofdesktops]
workarea . clear ( ) ;
workarea . resize ( desktopCount + 1 ) ;
restrictedmovearea . clear ( ) ;
restrictedmovearea . resize ( desktopCount + 1 ) ;
screenarea . clear ( ) ;
updateClientArea ( true ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2014-06-15 12:05:53 +00:00
void Workspace : : selectWmInputEventMask ( )
{
uint32_t presentMask = 0 ;
Xcb : : WindowAttributes attr ( rootWindow ( ) ) ;
if ( ! attr . isNull ( ) ) {
presentMask = attr - > your_event_mask ;
}
Xcb : : selectInput ( rootWindow ( ) ,
presentMask |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_PROPERTY_CHANGE |
XCB_EVENT_MASK_COLOR_MAP_CHANGE |
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
XCB_EVENT_MASK_FOCUS_CHANGE | // For NotifyDetailNone
XCB_EVENT_MASK_EXPOSURE
) ;
}
2008-12-18 13:50:57 +00:00
/**
* Sends client \ a c to desktop \ a desk .
*
* Takes care of transients as well .
2019-07-29 18:58:33 +00:00
*/
2015-03-06 16:31:47 +00:00
void Workspace : : sendClientToDesktop ( AbstractClient * c , int desk , bool dont_activate )
2011-01-30 14:34:42 +00:00
{
2012-11-16 07:23:47 +00:00
if ( ( desk < 1 & & desk ! = NET : : OnAllDesktops ) | | desk > static_cast < int > ( VirtualDesktopManager : : self ( ) - > count ( ) ) )
2011-02-16 18:23:54 +00:00
return ;
2010-04-25 16:43:14 +00:00
int old_desktop = c - > desktop ( ) ;
2011-01-30 14:34:42 +00:00
bool was_on_desktop = c - > isOnDesktop ( desk ) | | c - > isOnAllDesktops ( ) ;
c - > setDesktop ( desk ) ;
if ( c - > desktop ( ) ! = desk ) // No change or desktop forced
2007-04-29 17:35:43 +00:00
return ;
desk = c - > desktop ( ) ; // Client did range checking
2011-01-30 14:34:42 +00:00
2012-11-16 07:23:47 +00:00
if ( c - > isOnDesktop ( VirtualDesktopManager : : self ( ) - > current ( ) ) ) {
2011-01-30 14:34:42 +00:00
if ( c - > wantsTabFocus ( ) & & options - > focusPolicyIsReasonable ( ) & &
! was_on_desktop & & // for stickyness changes
! dont_activate )
requestFocus ( c ) ;
2007-04-29 17:35:43 +00:00
else
2011-01-30 14:34:42 +00:00
restackClientUnderActive ( c ) ;
} else
raiseClient ( c ) ;
2007-04-29 17:35:43 +00:00
2011-09-29 15:52:19 +00:00
c - > checkWorkspacePosition ( QRect ( ) , old_desktop ) ;
2010-04-25 16:43:14 +00:00
2018-12-12 17:25:51 +00:00
auto transients_stacking_order = ensureStackingOrder ( c - > transients ( ) ) ;
for ( auto it = transients_stacking_order . constBegin ( ) ;
it ! = transients_stacking_order . constEnd ( ) ;
+ + it )
sendClientToDesktop ( * it , desk , dont_activate ) ;
2007-04-29 17:35:43 +00:00
updateClientArea ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2013-02-12 23:40:11 +00:00
/**
* checks whether the X Window with the input focus is on our X11 screen
* if the window cannot be determined or inspected , resturn depends on whether there ' s actually
* more than one screen
*
* this is NOT in any way related to XRandR multiscreen
*
2019-07-29 18:58:33 +00:00
*/
2013-02-12 23:40:11 +00:00
extern bool is_multihead ; // main.cpp
bool Workspace : : isOnCurrentHead ( )
{
if ( ! is_multihead ) {
return true ;
}
Xcb : : CurrentInput currentInput ;
if ( currentInput . window ( ) = = XCB_WINDOW_NONE ) {
return ! is_multihead ;
}
Xcb : : WindowGeometry geometry ( currentInput . window ( ) ) ;
if ( geometry . isNull ( ) ) { // should not happen
return ! is_multihead ;
}
return rootWindow ( ) = = geometry - > root ;
}
2015-03-06 07:36:29 +00:00
void Workspace : : sendClientToScreen ( AbstractClient * c , int screen )
2011-01-30 14:34:42 +00:00
{
2013-11-17 16:37:46 +00:00
c - > sendToScreen ( screen ) ;
2011-01-30 14:34:42 +00:00
}
2007-05-07 13:13:48 +00:00
2008-12-18 13:50:57 +00:00
/**
* Delayed focus functions
2019-07-29 18:58:33 +00:00
*/
2007-04-29 17:35:43 +00:00
void Workspace : : delayFocus ( )
2011-01-30 14:34:42 +00:00
{
requestFocus ( delayfocus_client ) ;
2007-04-29 17:35:43 +00:00
cancelDelayFocus ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2016-02-18 10:18:50 +00:00
void Workspace : : requestDelayFocus ( AbstractClient * c )
2011-01-30 14:34:42 +00:00
{
2011-12-06 13:22:21 +00:00
delayfocus_client = c ;
delete delayFocusTimer ;
2011-01-30 14:34:42 +00:00
delayFocusTimer = new QTimer ( this ) ;
2020-09-23 18:39:59 +00:00
connect ( delayFocusTimer , & QTimer : : timeout , this , & Workspace : : delayFocus ) ;
2011-01-30 14:34:42 +00:00
delayFocusTimer - > setSingleShot ( true ) ;
2012-02-20 09:25:13 +00:00
delayFocusTimer - > start ( options - > delayFocusInterval ( ) ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
void Workspace : : cancelDelayFocus ( )
2011-01-30 14:34:42 +00:00
{
2007-04-29 17:35:43 +00:00
delete delayFocusTimer ;
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
delayFocusTimer = nullptr ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2013-04-30 13:41:59 +00:00
bool Workspace : : checkStartupNotification ( xcb_window_t w , KStartupInfoId & id , KStartupInfoData & data )
2011-01-30 14:34:42 +00:00
{
2020-07-20 08:07:08 +00:00
return m_startup - > checkStartup ( w , id , data ) = = KStartupInfo : : Match ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
/**
* Puts the focus on a dummy window
* Just using XSetInputFocus ( ) with None would block keyboard input
2019-07-29 18:58:33 +00:00
*/
2007-04-29 17:35:43 +00:00
void Workspace : : focusToNull ( )
2011-01-30 14:34:42 +00:00
{
2017-09-20 18:02:02 +00:00
if ( m_nullFocus ) {
m_nullFocus - > focus ( ) ;
}
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
void Workspace : : setShowingDesktop ( bool showing )
{
2015-03-28 23:08:32 +00:00
const bool changed = showing ! = showing_desktop ;
2017-08-03 15:15:00 +00:00
if ( rootInfo ( ) & & changed ) {
rootInfo ( ) - > setShowingDesktop ( showing ) ;
}
2007-04-29 17:35:43 +00:00
showing_desktop = showing ;
2015-04-17 23:03:07 +00:00
2015-06-09 21:28:48 +00:00
AbstractClient * topDesk = nullptr ;
2015-04-17 23:03:07 +00:00
{ // for the blocker RAII
StackingUpdatesBlocker blocker ( this ) ; // updateLayer & lowerClient would invalidate stacking_order
for ( int i = stacking_order . count ( ) - 1 ; i > - 1 ; - - i ) {
2015-06-09 21:28:48 +00:00
AbstractClient * c = qobject_cast < AbstractClient * > ( stacking_order . at ( i ) ) ;
2015-05-13 20:31:22 +00:00
if ( c & & c - > isOnCurrentDesktop ( ) ) {
2019-04-16 08:06:41 +00:00
if ( c - > isDock ( ) ) {
2015-05-13 20:31:22 +00:00
c - > updateLayer ( ) ;
} else if ( c - > isDesktop ( ) & & c - > isShown ( true ) ) {
c - > updateLayer ( ) ;
lowerClient ( c ) ;
if ( ! topDesk )
topDesk = c ;
2018-12-31 17:57:13 +00:00
if ( auto group = c - > group ( ) ) {
2019-09-24 08:48:08 +00:00
foreach ( X11Client * cm , group - > members ( ) ) {
2015-06-09 21:28:48 +00:00
cm - > updateLayer ( ) ;
}
2015-05-13 21:10:19 +00:00
}
2015-05-13 20:31:22 +00:00
}
2015-04-17 23:03:07 +00:00
}
2011-01-30 14:34:42 +00:00
}
2015-04-17 23:03:07 +00:00
} // ~StackingUpdatesBlocker
2017-06-28 15:20:18 +00:00
if ( showing_desktop & & topDesk ) {
2015-04-17 23:03:07 +00:00
requestFocus ( topDesk ) ;
2017-06-28 15:20:18 +00:00
} else if ( ! showing_desktop & & changed ) {
const auto client = FocusChain : : self ( ) - > getForActivation ( VirtualDesktopManager : : self ( ) - > current ( ) ) ;
if ( client ) {
activateClient ( client ) ;
}
}
2015-03-28 23:08:32 +00:00
if ( changed )
emit showingDesktopChanged ( showing ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
void Workspace : : disableGlobalShortcutsForClient ( bool disable )
{
if ( global_shortcuts_disabled_for_client = = disable )
2007-04-29 17:35:43 +00:00
return ;
2013-12-06 09:28:42 +00:00
QDBusMessage message = QDBusMessage : : createMethodCall ( QStringLiteral ( " org.kde.kglobalaccel " ) ,
QStringLiteral ( " /kglobalaccel " ) ,
QStringLiteral ( " org.kde.KGlobalAccel " ) ,
QStringLiteral ( " blockGlobalShortcuts " ) ) ;
message . setArguments ( QList < QVariant > ( ) < < disable ) ;
QDBusConnection : : sessionBus ( ) . asyncCall ( message ) ;
global_shortcuts_disabled_for_client = disable ;
2020-05-06 09:17:44 +00:00
// Update also Meta+LMB actions etc.
Drop some custom list typedefs
Summary:
Qt has its own thing where a type might also have corresponding list
alias, e.g. QObject and QObjectList, QWidget and QWidgetList. I don't
know why Qt does that, maybe for some historical reasons, but what
matters is that we copy this pattern here in KWin. While this pattern
might be useful with some long list types, for example
QList<QWeakPointer<TabBoxClient>> TabBoxClientList
in general, it causes more harm than good. For example, we've got two
new client types, do we need corresponding list typedefs for them? If
no, why do we have ClientList and so on?
Another problem with these typedefs is that you need to include utils.h
header in order to use them. A better way to handle such things is to
just forward declare a client class (if that's possible) and use it
directly with QList or QVector. This way translation units don't get
"bloated" with utils.h stuff for no apparent reason.
So, in order to make code more consistent and easier to follow, this
change drops some of our custom typedefs. Namely ConstClientList,
ClientList, DeletedList, UnmanagedList, ToplevelList, and GroupList.
Test Plan: Compiles.
Reviewers: #kwin
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D24950
2019-10-16 09:11:04 +00:00
for ( auto it = clients . constBegin ( ) ;
2011-01-30 14:34:42 +00:00
it ! = clients . constEnd ( ) ;
+ + it )
2007-04-29 17:35:43 +00:00
( * it ) - > updateMouseGrab ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2012-03-04 14:13:22 +00:00
QString Workspace : : supportInformation ( ) const
{
QString support ;
2015-03-23 15:02:12 +00:00
const QString yes = QStringLiteral ( " yes \n " ) ;
const QString no = QStringLiteral ( " no \n " ) ;
2012-03-04 14:13:22 +00:00
support . append ( ki18nc ( " Introductory text shown in the support information. " ,
" KWin Support Information: \n "
2018-12-11 06:14:55 +00:00
" The following information should be used when requesting support on e.g. https://forum.kde.org. \n "
2012-03-04 14:13:22 +00:00
" It provides information about the currently running instance, which options are used, \n "
" what OpenGL driver and which effects are running. \n "
" Please post the information provided underneath this introductory text to a paste bin service \n "
2019-03-25 18:11:15 +00:00
" like https://paste.kde.org instead of pasting into support threads. \n " ) . toString ( ) ) ;
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n ========================== \n \n " ) ) ;
2012-03-04 14:13:22 +00:00
// all following strings are intended for support. They need to be pasted to e.g forums.kde.org
// it is expected that the support will happen in English language or that the people providing
// help understand English. Because of that all texts are not translated
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Version \n " ) ) ;
support . append ( QStringLiteral ( " ======= \n " ) ) ;
support . append ( QStringLiteral ( " KWin version: " ) ) ;
support . append ( QStringLiteral ( KWIN_VERSION_STRING ) ) ;
support . append ( QStringLiteral ( " \n " ) ) ;
support . append ( QStringLiteral ( " Qt Version: " ) ) ;
support . append ( QString : : fromUtf8 ( qVersion ( ) ) ) ;
2015-02-02 08:28:14 +00:00
support . append ( QStringLiteral ( " \n " ) ) ;
support . append ( QStringLiteral ( " Qt compile version: %1 \n " ) . arg ( QStringLiteral ( QT_VERSION_STR ) ) ) ;
support . append ( QStringLiteral ( " XCB compile version: %1 \n \n " ) . arg ( QStringLiteral ( XCB_VERSION_STRING ) ) ) ;
2013-06-25 06:52:08 +00:00
support . append ( QStringLiteral ( " Operation Mode: " ) ) ;
switch ( kwinApp ( ) - > operationMode ( ) ) {
case Application : : OperationModeX11 :
support . append ( QStringLiteral ( " X11 only " ) ) ;
break ;
2017-09-30 13:09:06 +00:00
case Application : : OperationModeWaylandOnly :
support . append ( QStringLiteral ( " Wayland Only " ) ) ;
2013-06-25 06:52:08 +00:00
break ;
2015-01-09 15:00:16 +00:00
case Application : : OperationModeXwayland :
support . append ( QStringLiteral ( " Xwayland " ) ) ;
break ;
2013-06-25 06:52:08 +00:00
}
2014-05-15 07:14:46 +00:00
support . append ( QStringLiteral ( " \n \n " ) ) ;
2015-03-23 15:02:12 +00:00
support . append ( QStringLiteral ( " Build Options \n " ) ) ;
support . append ( QStringLiteral ( " ============= \n " ) ) ;
support . append ( QStringLiteral ( " KWIN_BUILD_DECORATIONS: " ) ) ;
# ifdef KWIN_BUILD_DECORATIONS
support . append ( yes ) ;
# else
support . append ( no ) ;
# endif
support . append ( QStringLiteral ( " KWIN_BUILD_TABBOX: " ) ) ;
# ifdef KWIN_BUILD_TABBOX
support . append ( yes ) ;
# else
support . append ( no ) ;
# endif
support . append ( QStringLiteral ( " KWIN_BUILD_ACTIVITIES: " ) ) ;
# ifdef KWIN_BUILD_ACTIVITIES
support . append ( yes ) ;
# else
support . append ( no ) ;
2015-04-09 12:49:32 +00:00
# endif
support . append ( QStringLiteral ( " HAVE_DRM: " ) ) ;
# if HAVE_DRM
support . append ( yes ) ;
# else
support . append ( no ) ;
2015-04-10 08:44:07 +00:00
# endif
support . append ( QStringLiteral ( " HAVE_GBM: " ) ) ;
# if HAVE_GBM
support . append ( yes ) ;
# else
support . append ( no ) ;
[platforms/drm] EGLStream DRM Backend Initial Implementation
Summary:
This is the initial implementation of a DRM backend based on the EGLDevice,
EGLOutput, and EGLStream extensions, supporting NVIDIA graphics hardware using
their proprietary driver. The new backend will be used if the environment
variable KWIN_DRM_USE_EGL_STREAMS is set. On initialization, it will attempt to
create an EGLDevice based on the DRM device currently in use and create
EGLOutputs and EGLStreams for any attached displays. These are used to control
presentation of the final composited frame. Additionally, it will register the
wl_eglstream_controller Wayland interface so that native EGL windows created by
clients can be attached to an EGLStream allowing buffer contents to be shared
with the compositor as a GL texture.
At this time there are two known bugs in the NVIDIA driver's EGL implementation
affecting desktop functionality. The first can result in tooltip windows drawn
by plasmashell to contain incorrect contents. The second prevents KWayland from
being able to query the format of EGLStream-backed buffers which interferes
with the blur effect. Fixes for both of these are currently in development and
should appear in an upcoming NVIDIA driver release.
Additionally, hardware cursors are currently not supported with this backend.
Enabling them causes the desktop to intermittently hang for several seconds.
This is also likely a bug in the NVIDIA DRM-KMS implementation but the root
cause is still under investigation.
Test Plan:
On a system with an NVIDIA graphics card running a recent release of their
proprietary driver
* Ensure the nvidia_drm kernel module is loaded with the option "modeset=1"
("# cat /sys/module/nvidia_drm/parameters/modeset" should print "Y")
* Ensure EGL external platform support is installed
https://github.com/NVIDIA/eglexternalplatform
* Ensure KWin was build with the CMake option
KWIN_BUILD_EGL_STREAM_BACKEND=ON (this is the default)
* Start a plasma wayland session with the environment variable
KWIN_DRM_USE_EGL_STREAMS set
* Ensure output from KWin OpenGL initialization indicates the NVIDIA EGL
driver is in use (as opposed to Mesa / llvmpipe).
* Desktop should be fully functional and perform smoothly.
Reviewers: #kwin, romangg, davidedmundson
Reviewed By: #kwin, romangg, davidedmundson
Subscribers: kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D18570
2019-04-15 14:26:22 +00:00
# endif
support . append ( QStringLiteral ( " HAVE_EGL_STREAMS: " ) ) ;
# if HAVE_EGL_STREAMS
support . append ( yes ) ;
# else
support . append ( no ) ;
2015-03-23 15:02:12 +00:00
# endif
support . append ( QStringLiteral ( " HAVE_X11_XCB: " ) ) ;
# if HAVE_X11_XCB
support . append ( yes ) ;
# else
support . append ( no ) ;
2015-10-30 10:50:31 +00:00
# endif
support . append ( QStringLiteral ( " HAVE_EPOXY_GLX: " ) ) ;
# if HAVE_EPOXY_GLX
support . append ( yes ) ;
# else
support . append ( no ) ;
2015-11-30 07:34:52 +00:00
# endif
support . append ( QStringLiteral ( " HAVE_WAYLAND_EGL: " ) ) ;
# if HAVE_WAYLAND_EGL
support . append ( yes ) ;
# else
support . append ( no ) ;
2015-03-23 15:02:12 +00:00
# endif
support . append ( QStringLiteral ( " \n " ) ) ;
2017-11-01 14:09:40 +00:00
if ( auto c = kwinApp ( ) - > x11Connection ( ) ) {
support . append ( QStringLiteral ( " X11 \n " ) ) ;
support . append ( QStringLiteral ( " === \n " ) ) ;
auto x11setup = xcb_get_setup ( c ) ;
support . append ( QStringLiteral ( " Vendor: %1 \n " ) . arg ( QString : : fromUtf8 ( QByteArray : : fromRawData ( xcb_setup_vendor ( x11setup ) , xcb_setup_vendor_length ( x11setup ) ) ) ) ) ;
support . append ( QStringLiteral ( " Vendor Release: %1 \n " ) . arg ( x11setup - > release_number ) ) ;
support . append ( QStringLiteral ( " Protocol Version/Revision: %1/%2 \n " ) . arg ( x11setup - > protocol_major_version ) . arg ( x11setup - > protocol_minor_version ) ) ;
const auto extensions = Xcb : : Extensions : : self ( ) - > extensions ( ) ;
for ( const auto & e : extensions ) {
support . append ( QStringLiteral ( " %1: %2; Version: 0x%3 \n " ) . arg ( QString : : fromUtf8 ( e . name ) )
. arg ( e . present ? yes . trimmed ( ) : no . trimmed ( ) )
. arg ( QString : : number ( e . version , 16 ) ) ) ;
}
support . append ( QStringLiteral ( " \n " ) ) ;
2015-03-24 07:54:03 +00:00
}
2014-12-08 15:14:05 +00:00
if ( auto bridge = Decoration : : DecorationBridge : : self ( ) ) {
support . append ( QStringLiteral ( " Decoration \n " ) ) ;
support . append ( QStringLiteral ( " ========== \n " ) ) ;
support . append ( bridge - > supportInformation ( ) ) ;
support . append ( QStringLiteral ( " \n " ) ) ;
}
2017-11-07 19:12:51 +00:00
support . append ( QStringLiteral ( " Platform \n " ) ) ;
support . append ( QStringLiteral ( " ========== \n " ) ) ;
support . append ( kwinApp ( ) - > platform ( ) - > supportInformation ( ) ) ;
support . append ( QStringLiteral ( " \n " ) ) ;
2020-10-28 19:06:16 +00:00
const Cursor * cursor = Cursors : : self ( ) - > mouse ( ) ;
support . append ( QLatin1String ( " Cursor \n " ) ) ;
support . append ( QLatin1String ( " ====== \n " ) ) ;
support . append ( QLatin1String ( " themeName: " ) + cursor - > themeName ( ) + QLatin1Char ( ' \n ' ) ) ;
support . append ( QLatin1String ( " themeSize: " ) + QString : : number ( cursor - > themeSize ( ) ) + QLatin1Char ( ' \n ' ) ) ;
support . append ( QLatin1Char ( ' \n ' ) ) ;
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Options \n " ) ) ;
support . append ( QStringLiteral ( " ======= \n " ) ) ;
2012-03-04 14:13:22 +00:00
const QMetaObject * metaOptions = options - > metaObject ( ) ;
2014-12-08 15:46:54 +00:00
auto printProperty = [ ] ( const QVariant & variant ) {
if ( variant . type ( ) = = QVariant : : Size ) {
const QSize & s = variant . toSize ( ) ;
return QStringLiteral ( " %1x%2 " ) . arg ( QString : : number ( s . width ( ) ) ) . arg ( QString : : number ( s . height ( ) ) ) ;
}
if ( QLatin1String ( variant . typeName ( ) ) = = QLatin1String ( " KWin::OpenGLPlatformInterface " ) | |
QLatin1String ( variant . typeName ( ) ) = = QLatin1String ( " KWin::Options::WindowOperation " ) ) {
return QString : : number ( variant . toInt ( ) ) ;
}
return variant . toString ( ) ;
} ;
2012-03-04 14:13:22 +00:00
for ( int i = 0 ; i < metaOptions - > propertyCount ( ) ; + + i ) {
const QMetaProperty property = metaOptions - > property ( i ) ;
2013-07-23 05:02:52 +00:00
if ( QLatin1String ( property . name ( ) ) = = QLatin1String ( " objectName " ) ) {
2012-03-04 14:13:22 +00:00
continue ;
}
2014-12-08 15:46:54 +00:00
support . append ( QStringLiteral ( " %1: %2 \n " ) . arg ( property . name ( ) ) . arg ( printProperty ( options - > property ( property . name ( ) ) ) ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n Screen Edges \n " ) ) ;
support . append ( QStringLiteral ( " ============ \n " ) ) ;
2013-01-25 09:15:00 +00:00
const QMetaObject * metaScreenEdges = ScreenEdges : : self ( ) - > metaObject ( ) ;
2013-01-21 08:04:06 +00:00
for ( int i = 0 ; i < metaScreenEdges - > propertyCount ( ) ; + + i ) {
const QMetaProperty property = metaScreenEdges - > property ( i ) ;
2013-07-23 05:02:52 +00:00
if ( QLatin1String ( property . name ( ) ) = = QLatin1String ( " objectName " ) ) {
2013-01-21 08:04:06 +00:00
continue ;
}
2014-12-08 15:46:54 +00:00
support . append ( QStringLiteral ( " %1: %2 \n " ) . arg ( property . name ( ) ) . arg ( printProperty ( ScreenEdges : : self ( ) - > property ( property . name ( ) ) ) ) ) ;
2013-01-21 08:04:06 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n Screens \n " ) ) ;
support . append ( QStringLiteral ( " ======= \n " ) ) ;
support . append ( QStringLiteral ( " Multi-Head: " ) ) ;
2013-01-12 08:54:24 +00:00
if ( is_multihead ) {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " yes \n " ) ) ;
support . append ( QStringLiteral ( " Head: %1 \n " ) . arg ( screen_number ) ) ;
2013-01-12 08:54:24 +00:00
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " no \n " ) ) ;
2013-01-12 08:54:24 +00:00
}
2013-09-24 09:28:38 +00:00
support . append ( QStringLiteral ( " Active screen follows mouse: " ) ) ;
2013-08-18 11:04:05 +00:00
if ( screens ( ) - > isCurrentFollowsMouse ( ) )
2013-09-24 09:28:38 +00:00
support . append ( QStringLiteral ( " yes \n " ) ) ;
2013-08-18 11:04:05 +00:00
else
2013-09-24 09:28:38 +00:00
support . append ( QStringLiteral ( " no \n " ) ) ;
2015-05-19 07:19:45 +00:00
support . append ( QStringLiteral ( " Number of Screens: %1 \n \n " ) . arg ( screens ( ) - > count ( ) ) ) ;
2013-04-03 10:19:27 +00:00
for ( int i = 0 ; i < screens ( ) - > count ( ) ; + + i ) {
const QRect geo = screens ( ) - > geometry ( i ) ;
2015-05-19 07:19:45 +00:00
support . append ( QStringLiteral ( " Screen %1: \n " ) . arg ( i ) ) ;
2017-11-11 17:59:56 +00:00
support . append ( QStringLiteral ( " --------- \n " ) ) ;
2015-05-19 07:19:45 +00:00
support . append ( QStringLiteral ( " Name: %1 \n " ) . arg ( screens ( ) - > name ( i ) ) ) ;
support . append ( QStringLiteral ( " Geometry: %1,%2,%3x%4 \n " )
2013-01-12 08:54:24 +00:00
. arg ( geo . x ( ) )
. arg ( geo . y ( ) )
. arg ( geo . width ( ) )
. arg ( geo . height ( ) ) ) ;
2017-11-07 19:12:12 +00:00
support . append ( QStringLiteral ( " Scale: %1 \n " ) . arg ( screens ( ) - > scale ( i ) ) ) ;
2015-05-19 07:19:45 +00:00
support . append ( QStringLiteral ( " Refresh Rate: %1 \n \n " ) . arg ( screens ( ) - > refreshRate ( i ) ) ) ;
2013-01-12 08:54:24 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n Compositing \n " ) ) ;
support . append ( QStringLiteral ( " =========== \n " ) ) ;
2012-03-04 14:13:22 +00:00
if ( effects ) {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Compositing is active \n " ) ) ;
2012-03-04 14:13:22 +00:00
switch ( effects - > compositingType ( ) ) {
2012-09-20 09:33:32 +00:00
case OpenGL2Compositing :
2012-03-04 14:13:22 +00:00
case OpenGLCompositing : {
GLPlatform * platform = GLPlatform : : instance ( ) ;
2015-10-30 12:18:30 +00:00
if ( platform - > isGLES ( ) ) {
support . append ( QStringLiteral ( " Compositing Type: OpenGL ES 2.0 \n " ) ) ;
} else {
support . append ( QStringLiteral ( " Compositing Type: OpenGL \n " ) ) ;
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " OpenGL vendor string: " ) + QString : : fromUtf8 ( platform - > glVendorString ( ) ) + QStringLiteral ( " \n " ) ) ;
support . append ( QStringLiteral ( " OpenGL renderer string: " ) + QString : : fromUtf8 ( platform - > glRendererString ( ) ) + QStringLiteral ( " \n " ) ) ;
support . append ( QStringLiteral ( " OpenGL version string: " ) + QString : : fromUtf8 ( platform - > glVersionString ( ) ) + QStringLiteral ( " \n " ) ) ;
2014-04-22 07:28:39 +00:00
support . append ( QStringLiteral ( " OpenGL platform interface: " ) ) ;
switch ( platform - > platformInterface ( ) ) {
case GlxPlatformInterface :
support . append ( QStringLiteral ( " GLX " ) ) ;
break ;
case EglPlatformInterface :
support . append ( QStringLiteral ( " EGL " ) ) ;
break ;
default :
support . append ( QStringLiteral ( " UNKNOWN " ) ) ;
}
support . append ( QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
2013-05-22 07:18:05 +00:00
if ( platform - > supports ( LimitedGLSL ) | | platform - > supports ( GLSL ) )
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " OpenGL shading language version string: " ) + QString : : fromUtf8 ( platform - > glShadingLanguageVersionString ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Driver: " ) + GLPlatform : : driverToString ( platform - > driver ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
if ( ! platform - > isMesaDriver ( ) )
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Driver version: " ) + GLPlatform : : versionToString ( platform - > driverVersion ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " GPU class: " ) + GLPlatform : : chipClassToString ( platform - > chipClass ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " OpenGL version: " ) + GLPlatform : : versionToString ( platform - > glVersion ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
2013-05-22 07:18:05 +00:00
if ( platform - > supports ( LimitedGLSL ) | | platform - > supports ( GLSL ) )
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " GLSL version: " ) + GLPlatform : : versionToString ( platform - > glslVersion ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
if ( platform - > isMesaDriver ( ) )
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Mesa version: " ) + GLPlatform : : versionToString ( platform - > mesaVersion ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
if ( platform - > serverVersion ( ) > 0 )
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " X server version: " ) + GLPlatform : : versionToString ( platform - > serverVersion ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
if ( platform - > kernelVersion ( ) > 0 )
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Linux kernel version: " ) + GLPlatform : : versionToString ( platform - > kernelVersion ( ) ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Direct rendering: " ) ) ;
support . append ( QStringLiteral ( " Requires strict binding: " ) ) ;
2012-03-04 14:13:22 +00:00
if ( ! platform - > isLooseBinding ( ) ) {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " yes \n " ) ) ;
2012-03-04 14:13:22 +00:00
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " no \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " GLSL shaders: " ) ) ;
2012-03-04 14:13:22 +00:00
if ( platform - > supports ( GLSL ) ) {
if ( platform - > supports ( LimitedGLSL ) ) {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " limited \n " ) ) ;
2012-03-04 14:13:22 +00:00
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " yes \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " no \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Texture NPOT support: " ) ) ;
2012-03-04 14:13:22 +00:00
if ( platform - > supports ( TextureNPOT ) ) {
if ( platform - > supports ( LimitedNPOT ) ) {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " limited \n " ) ) ;
2012-03-04 14:13:22 +00:00
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " yes \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " no \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Virtual Machine: " ) ) ;
2012-10-13 08:33:38 +00:00
if ( platform - > isVirtualMachine ( ) ) {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " yes \n " ) ) ;
2012-10-13 08:33:38 +00:00
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " no \n " ) ) ;
2012-10-13 08:33:38 +00:00
}
2012-03-04 14:13:22 +00:00
2014-02-25 10:02:32 +00:00
support . append ( QStringLiteral ( " OpenGL 2 Shaders are used \n " ) ) ;
2012-03-04 14:13:22 +00:00
break ;
}
case XRenderCompositing :
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Compositing Type: XRender \n " ) ) ;
2012-03-04 14:13:22 +00:00
break ;
2013-06-21 08:03:31 +00:00
case QPainterCompositing :
support . append ( " Compositing Type: QPainter \n " ) ;
break ;
2012-03-04 14:13:22 +00:00
case NoCompositing :
default :
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Something is really broken, neither OpenGL nor XRender is used " ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n Loaded Effects: \n " ) ) ;
support . append ( QStringLiteral ( " --------------- \n " ) ) ;
2012-08-30 06:20:26 +00:00
foreach ( const QString & effect , static_cast < EffectsHandlerImpl * > ( effects ) - > loadedEffects ( ) ) {
2013-07-23 05:02:52 +00:00
support . append ( effect + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n Currently Active Effects: \n " ) ) ;
support . append ( QStringLiteral ( " ------------------------- \n " ) ) ;
2012-08-30 06:20:26 +00:00
foreach ( const QString & effect , static_cast < EffectsHandlerImpl * > ( effects ) - > activeEffects ( ) ) {
2013-07-23 05:02:52 +00:00
support . append ( effect + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n Effect Settings: \n " ) ) ;
support . append ( QStringLiteral ( " ---------------- \n " ) ) ;
2012-08-30 06:20:26 +00:00
foreach ( const QString & effect , static_cast < EffectsHandlerImpl * > ( effects ) - > loadedEffects ( ) ) {
support . append ( static_cast < EffectsHandlerImpl * > ( effects ) - > supportInformation ( effect ) ) ;
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n " ) ) ;
2012-08-11 09:24:37 +00:00
}
2020-11-07 19:34:55 +00:00
support . append ( QLatin1String ( " \n Loaded Plugins: \n " ) ) ;
support . append ( QLatin1String ( " --------------- \n " ) ) ;
QStringList loadedPlugins = PluginManager : : self ( ) - > loadedPlugins ( ) ;
loadedPlugins . sort ( ) ;
for ( const QString & plugin : qAsConst ( loadedPlugins ) ) {
support . append ( plugin + QLatin1Char ( ' \n ' ) ) ;
}
support . append ( QLatin1String ( " \n Available Plugins: \n " ) ) ;
support . append ( QLatin1String ( " ------------------ \n " ) ) ;
QStringList availablePlugins = PluginManager : : self ( ) - > availablePlugins ( ) ;
availablePlugins . sort ( ) ;
for ( const QString & plugin : qAsConst ( availablePlugins ) ) {
support . append ( plugin + QLatin1Char ( ' \n ' ) ) ;
}
2012-03-04 14:13:22 +00:00
} else {
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Compositing is not active \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
return support ;
}
2019-09-24 08:48:08 +00:00
X11Client * Workspace : : findClient ( std : : function < bool ( const X11Client * ) > func ) const
2014-03-20 08:19:53 +00:00
{
2019-09-24 08:48:08 +00:00
if ( X11Client * ret = Toplevel : : findInList ( clients , func ) ) {
2014-03-20 08:19:53 +00:00
return ret ;
}
return nullptr ;
}
2015-12-04 08:53:18 +00:00
AbstractClient * Workspace : : findAbstractClient ( std : : function < bool ( const AbstractClient * ) > func ) const
{
if ( AbstractClient * ret = Toplevel : : findInList ( m_allClients , func ) ) {
return ret ;
}
2019-08-26 07:44:04 +00:00
if ( InternalClient * ret = Toplevel : : findInList ( m_internalClients , func ) ) {
return ret ;
2016-05-09 12:48:10 +00:00
}
2015-12-04 08:53:18 +00:00
return nullptr ;
}
2020-07-21 13:33:03 +00:00
AbstractClient * Workspace : : findAbstractClient ( const QUuid & internalId ) const
{
return qobject_cast < AbstractClient * > ( findToplevel ( internalId ) ) ;
}
2014-03-20 06:52:18 +00:00
Unmanaged * Workspace : : findUnmanaged ( std : : function < bool ( const Unmanaged * ) > func ) const
{
2020-10-09 15:49:32 +00:00
return Toplevel : : findInList ( m_unmanaged , func ) ;
2014-03-20 06:52:18 +00:00
}
Unmanaged * Workspace : : findUnmanaged ( xcb_window_t w ) const
{
return findUnmanaged ( [ w ] ( const Unmanaged * u ) {
return u - > window ( ) = = w ;
} ) ;
}
2019-09-24 08:48:08 +00:00
X11Client * Workspace : : findClient ( Predicate predicate , xcb_window_t w ) const
2014-03-20 08:19:53 +00:00
{
switch ( predicate ) {
case Predicate : : WindowMatch :
2019-09-24 08:48:08 +00:00
return findClient ( [ w ] ( const X11Client * c ) {
2014-03-20 08:19:53 +00:00
return c - > window ( ) = = w ;
} ) ;
case Predicate : : WrapperIdMatch :
2019-09-24 08:48:08 +00:00
return findClient ( [ w ] ( const X11Client * c ) {
2014-03-20 08:19:53 +00:00
return c - > wrapperId ( ) = = w ;
} ) ;
case Predicate : : FrameIdMatch :
2019-09-24 08:48:08 +00:00
return findClient ( [ w ] ( const X11Client * c ) {
2014-03-20 08:19:53 +00:00
return c - > frameId ( ) = = w ;
} ) ;
case Predicate : : InputIdMatch :
2019-09-24 08:48:08 +00:00
return findClient ( [ w ] ( const X11Client * c ) {
2014-03-20 08:19:53 +00:00
return c - > inputId ( ) = = w ;
} ) ;
}
return nullptr ;
}
2015-02-09 15:07:30 +00:00
Toplevel * Workspace : : findToplevel ( std : : function < bool ( const Toplevel * ) > func ) const
{
2020-07-22 17:09:06 +00:00
if ( auto * ret = Toplevel : : findInList ( m_allClients , func ) ) {
2015-02-09 15:07:30 +00:00
return ret ;
}
2020-10-09 15:49:32 +00:00
if ( Unmanaged * ret = Toplevel : : findInList ( m_unmanaged , func ) ) {
2015-02-09 15:07:30 +00:00
return ret ;
}
2019-08-26 07:44:04 +00:00
if ( InternalClient * ret = Toplevel : : findInList ( m_internalClients , func ) ) {
return ret ;
2016-08-30 13:47:59 +00:00
}
2019-08-26 07:44:04 +00:00
return nullptr ;
2016-08-30 13:47:59 +00:00
}
2020-07-23 11:13:22 +00:00
Toplevel * Workspace : : findToplevel ( const QUuid & internalId ) const
{
return findToplevel ( [ internalId ] ( const KWin : : Toplevel * l ) - > bool {
return internalId = = l - > internalId ( ) ;
} ) ;
}
2019-11-29 19:12:11 +00:00
void Workspace : : forEachToplevel ( std : : function < void ( Toplevel * ) > func )
{
std : : for_each ( m_allClients . constBegin ( ) , m_allClients . constEnd ( ) , func ) ;
std : : for_each ( deleted . constBegin ( ) , deleted . constEnd ( ) , func ) ;
2020-10-09 15:49:32 +00:00
std : : for_each ( m_unmanaged . constBegin ( ) , m_unmanaged . constEnd ( ) , func ) ;
2019-11-29 19:12:11 +00:00
std : : for_each ( m_internalClients . constBegin ( ) , m_internalClients . constEnd ( ) , func ) ;
}
2015-03-05 11:41:15 +00:00
bool Workspace : : hasClient ( const AbstractClient * c )
{
2019-09-24 08:48:08 +00:00
if ( auto cc = dynamic_cast < const X11Client * > ( c ) ) {
2015-03-05 11:41:15 +00:00
return hasClient ( cc ) ;
2016-03-04 07:37:56 +00:00
} else {
return findAbstractClient ( [ c ] ( const AbstractClient * test ) {
return test = = c ;
} ) ! = nullptr ;
2015-03-05 11:41:15 +00:00
}
return false ;
}
2015-12-17 14:49:32 +00:00
void Workspace : : forEachAbstractClient ( std : : function < void ( AbstractClient * ) > func )
{
std : : for_each ( m_allClients . constBegin ( ) , m_allClients . constEnd ( ) , func ) ;
2019-08-26 07:44:04 +00:00
std : : for_each ( m_internalClients . constBegin ( ) , m_internalClients . constEnd ( ) , func ) ;
2015-12-17 14:49:32 +00:00
}
2016-03-04 08:42:33 +00:00
Toplevel * Workspace : : findInternal ( QWindow * w ) const
{
if ( ! w ) {
return nullptr ;
}
if ( kwinApp ( ) - > operationMode ( ) = = Application : : OperationModeX11 ) {
return findUnmanaged ( w - > winId ( ) ) ;
}
2019-08-26 07:44:04 +00:00
for ( InternalClient * client : m_internalClients ) {
if ( client - > internalWindow ( ) = = w ) {
return client ;
}
}
return nullptr ;
2016-03-04 08:42:33 +00:00
}
2019-06-22 10:00:56 +00:00
bool Workspace : : compositing ( ) const
{
2019-09-05 16:06:03 +00:00
return m_compositor & & m_compositor - > scene ( ) ;
2019-06-22 10:00:56 +00:00
}
2017-06-21 04:56:53 +00:00
void Workspace : : markXStackingOrderAsDirty ( )
{
2017-09-17 07:26:24 +00:00
m_xStackingDirty = true ;
2020-10-14 15:04:57 +00:00
if ( kwinApp ( ) - > x11Connection ( ) & & ! kwinApp ( ) - > isClosingX11Connection ( ) ) {
2017-09-17 07:26:24 +00:00
m_xStackingQueryTree . reset ( new Xcb : : Tree ( kwinApp ( ) - > x11RootWindow ( ) ) ) ;
}
2017-06-21 04:56:53 +00:00
}
2017-08-17 17:10:45 +00:00
void Workspace : : setWasUserInteraction ( )
{
if ( was_user_interaction ) {
return ;
}
was_user_interaction = true ;
// might be called from within the filter, so delay till we now the filter returned
QTimer : : singleShot ( 0 , this ,
[ this ] {
m_wasUserInteractionFilter . reset ( ) ;
}
) ;
}
2019-07-29 18:24:09 +00:00
void Workspace : : updateTabbox ( )
{
# ifdef KWIN_BUILD_TABBOX
2019-07-29 20:28:12 +00:00
TabBox : : TabBox * tabBox = TabBox : : TabBox : : self ( ) ;
2019-09-24 15:10:06 +00:00
if ( tabBox - > isDisplayed ( ) ) {
2019-07-29 20:28:12 +00:00
tabBox - > reset ( true ) ;
2019-07-29 18:24:09 +00:00
}
# endif
}
2019-08-26 07:44:04 +00:00
void Workspace : : addInternalClient ( InternalClient * client )
{
m_internalClients . append ( client ) ;
setupClientConnections ( client ) ;
client - > updateLayer ( ) ;
2020-09-23 13:24:10 +00:00
if ( client - > isPlaceable ( ) ) {
const QRect area = clientArea ( PlacementArea , screens ( ) - > current ( ) , client - > desktop ( ) ) ;
client - > placeIn ( area ) ;
2019-08-26 07:44:04 +00:00
}
2007-04-29 17:35:43 +00:00
2019-08-26 07:44:04 +00:00
markXStackingOrderAsDirty ( ) ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
emit internalClientAdded ( client ) ;
}
void Workspace : : removeInternalClient ( InternalClient * client )
{
m_internalClients . removeOne ( client ) ;
markXStackingOrderAsDirty ( ) ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
emit internalClientRemoved ( client ) ;
}
2019-12-03 10:14:43 +00:00
Group * Workspace : : findGroup ( xcb_window_t leader ) const
{
Q_ASSERT ( leader ! = XCB_WINDOW_NONE ) ;
for ( auto it = groups . constBegin ( ) ;
it ! = groups . constEnd ( ) ;
+ + it )
if ( ( * it ) - > leader ( ) = = leader )
return * it ;
return nullptr ;
}
// Client is group transient, but has no group set. Try to find
// group with windows with the same client leader.
Group * Workspace : : findClientLeaderGroup ( const X11Client * c ) const
{
Group * ret = nullptr ;
for ( auto it = clients . constBegin ( ) ;
it ! = clients . constEnd ( ) ;
+ + it ) {
if ( * it = = c )
continue ;
if ( ( * it ) - > wmClientLeader ( ) = = c - > wmClientLeader ( ) ) {
if ( ret = = nullptr | | ret = = ( * it ) - > group ( ) )
ret = ( * it ) - > group ( ) ;
else {
// There are already two groups with the same client leader.
// This most probably means the app uses group transients without
// setting group for its windows. Merging the two groups is a bad
// hack, but there's no really good solution for this case.
QList < X11Client * > old_group = ( * it ) - > group ( ) - > members ( ) ;
// old_group autodeletes when being empty
for ( int pos = 0 ;
pos < old_group . count ( ) ;
+ + pos ) {
X11Client * tmp = old_group [ pos ] ;
if ( tmp ! = c )
tmp - > changeClientLeaderGroup ( ret ) ;
}
}
}
}
return ret ;
}
void Workspace : : updateMinimizedOfTransients ( AbstractClient * c )
{
// if mainwindow is minimized or shaded, minimize transients too
if ( c - > isMinimized ( ) ) {
for ( auto it = c - > transients ( ) . constBegin ( ) ;
it ! = c - > transients ( ) . constEnd ( ) ;
+ + it ) {
if ( ( * it ) - > isModal ( ) )
continue ; // there's no reason to hide modal dialogs with the main client
// but to keep them to eg. watch progress or whatever
if ( ! ( * it ) - > isMinimized ( ) ) {
( * it ) - > minimize ( ) ;
updateMinimizedOfTransients ( ( * it ) ) ;
}
}
if ( c - > isModal ( ) ) { // if a modal dialog is minimized, minimize its mainwindow too
foreach ( AbstractClient * c2 , c - > mainClients ( ) )
c2 - > minimize ( ) ;
}
} else {
// else unmiminize the transients
for ( auto it = c - > transients ( ) . constBegin ( ) ;
it ! = c - > transients ( ) . constEnd ( ) ;
+ + it ) {
if ( ( * it ) - > isMinimized ( ) ) {
( * it ) - > unminimize ( ) ;
updateMinimizedOfTransients ( ( * it ) ) ;
}
}
if ( c - > isModal ( ) ) {
foreach ( AbstractClient * c2 , c - > mainClients ( ) )
c2 - > unminimize ( ) ;
}
}
}
/**
* Sets the client \ a c ' s transient windows ' on_all_desktops property to \ a on_all_desktops .
*/
void Workspace : : updateOnAllDesktopsOfTransients ( AbstractClient * c )
{
for ( auto it = c - > transients ( ) . constBegin ( ) ;
it ! = c - > transients ( ) . constEnd ( ) ;
+ + it ) {
if ( ( * it ) - > isOnAllDesktops ( ) ! = c - > isOnAllDesktops ( ) )
( * it ) - > setOnAllDesktops ( c - > isOnAllDesktops ( ) ) ;
}
}
// A new window has been mapped. Check if it's not a mainwindow for some already existing transient window.
void Workspace : : checkTransients ( xcb_window_t w )
{
for ( auto it = clients . constBegin ( ) ;
it ! = clients . constEnd ( ) ;
+ + it )
( * it ) - > checkTransient ( w ) ;
}
2020-01-13 18:57:07 +00:00
/**
* Resizes the workspace after an XRANDR screen size change
*/
void Workspace : : desktopResized ( )
{
QRect geom = screens ( ) - > geometry ( ) ;
if ( rootInfo ( ) ) {
NETSize desktop_geometry ;
desktop_geometry . width = geom . width ( ) ;
desktop_geometry . height = geom . height ( ) ;
rootInfo ( ) - > setDesktopGeometry ( desktop_geometry ) ;
}
updateClientArea ( ) ;
saveOldScreenSizes ( ) ; // after updateClientArea(), so that one still uses the previous one
// TODO: emit a signal instead and remove the deep function calls into edges and effects
ScreenEdges : : self ( ) - > recreateEdges ( ) ;
if ( effects ) {
static_cast < EffectsHandlerImpl * > ( effects ) - > desktopResized ( geom . size ( ) ) ;
}
}
void Workspace : : saveOldScreenSizes ( )
{
olddisplaysize = screens ( ) - > displaySize ( ) ;
oldscreensizes . clear ( ) ;
for ( int i = 0 ;
i < screens ( ) - > count ( ) ;
+ + i )
oldscreensizes . append ( screens ( ) - > geometry ( i ) ) ;
}
2020-08-17 13:14:20 +00:00
/**
* Whether or not the window has a strut that expands through the invisible area of
* an xinerama setup where the monitors are not the same resolution .
*/
static bool hasOffscreenXineramaStrut ( AbstractClient * client )
{
// Get strut as a QRegion
QRegion region ;
region + = client - > strutRect ( StrutAreaTop ) ;
region + = client - > strutRect ( StrutAreaRight ) ;
region + = client - > strutRect ( StrutAreaBottom ) ;
region + = client - > strutRect ( StrutAreaLeft ) ;
// Remove all visible areas so that only the invisible remain
for ( int i = 0 ; i < screens ( ) - > count ( ) ; i + + ) {
region - = screens ( ) - > geometry ( i ) ;
}
// If there's anything left then we have an offscreen strut
return ! region . isEmpty ( ) ;
}
QRect Workspace : : adjustClientArea ( AbstractClient * client , const QRect & area ) const
{
QRect adjustedArea = area ;
QRect strutLeft = client - > strutRect ( StrutAreaLeft ) ;
QRect strutRight = client - > strutRect ( StrutAreaRight ) ;
QRect strutTop = client - > strutRect ( StrutAreaTop ) ;
QRect strutBottom = client - > strutRect ( StrutAreaBottom ) ;
QRect screenArea = clientArea ( ScreenArea , client ) ;
// HACK: workarea handling is not xinerama aware, so if this strut
// reserves place at a xinerama edge that's inside the virtual screen,
// ignore the strut for workspace setting.
if ( area = = QRect ( QPoint ( 0 , 0 ) , screens ( ) - > displaySize ( ) ) ) {
if ( strutLeft . left ( ) < screenArea . left ( ) ) {
strutLeft = QRect ( ) ;
}
if ( strutRight . right ( ) > screenArea . right ( ) ) {
strutRight = QRect ( ) ;
}
if ( strutTop . top ( ) < screenArea . top ( ) ) {
strutTop = QRect ( ) ;
}
if ( strutBottom . bottom ( ) < screenArea . bottom ( ) ) {
strutBottom = QRect ( ) ;
}
}
// Handle struts at xinerama edges that are inside the virtual screen.
// They're given in virtual screen coordinates, make them affect only
// their xinerama screen.
strutLeft . setLeft ( qMax ( strutLeft . left ( ) , screenArea . left ( ) ) ) ;
strutRight . setRight ( qMin ( strutRight . right ( ) , screenArea . right ( ) ) ) ;
strutTop . setTop ( qMax ( strutTop . top ( ) , screenArea . top ( ) ) ) ;
strutBottom . setBottom ( qMin ( strutBottom . bottom ( ) , screenArea . bottom ( ) ) ) ;
if ( strutLeft . intersects ( area ) ) {
adjustedArea . setLeft ( strutLeft . right ( ) + 1 ) ;
}
if ( strutRight . intersects ( area ) ) {
adjustedArea . setRight ( strutRight . left ( ) - 1 ) ;
}
if ( strutTop . intersects ( area ) ) {
adjustedArea . setTop ( strutTop . bottom ( ) + 1 ) ;
}
if ( strutBottom . intersects ( area ) ) {
adjustedArea . setBottom ( strutBottom . top ( ) - 1 ) ;
}
return adjustedArea ;
}
2020-01-13 18:57:07 +00:00
/**
* Updates the current client areas according to the current clients .
*
* If the area changes or force is @ c true , the new areas are propagated to the world .
*
* The client area is the area that is available for clients ( that
* which is not taken by windows like panels , the top - of - screen menu
* etc ) .
*
* @ see clientArea ( )
*/
void Workspace : : updateClientArea ( bool force )
{
const Screens * s = Screens : : self ( ) ;
int nscreens = s - > count ( ) ;
const int numberOfDesktops = VirtualDesktopManager : : self ( ) - > count ( ) ;
QVector < QRect > new_wareas ( numberOfDesktops + 1 ) ;
QVector < StrutRects > new_rmoveareas ( numberOfDesktops + 1 ) ;
QVector < QVector < QRect > > new_sareas ( numberOfDesktops + 1 ) ;
QVector < QRect > screens ( nscreens ) ;
QRect desktopArea ;
for ( int i = 0 ; i < nscreens ; i + + ) {
desktopArea | = s - > geometry ( i ) ;
}
for ( int iS = 0 ;
iS < nscreens ;
iS + + ) {
screens [ iS ] = s - > geometry ( iS ) ;
}
for ( int i = 1 ;
i < = numberOfDesktops ;
+ + i ) {
new_wareas [ i ] = desktopArea ;
new_sareas [ i ] . resize ( nscreens ) ;
for ( int iS = 0 ;
iS < nscreens ;
iS + + )
new_sareas [ i ] [ iS ] = screens [ iS ] ;
}
2020-08-17 13:14:20 +00:00
for ( AbstractClient * client : qAsConst ( m_allClients ) ) {
if ( ! client - > hasStrut ( ) ) {
2020-01-13 18:57:07 +00:00
continue ;
2020-08-17 13:14:20 +00:00
}
QRect r = adjustClientArea ( client , desktopArea ) ;
2020-11-20 20:01:26 +00:00
// This happens sometimes when the workspace size changes and the
// struted clients haven't repositioned yet
if ( ! r . isValid ( ) ) {
continue ;
}
2020-01-13 18:57:07 +00:00
// sanity check that a strut doesn't exclude a complete screen geometry
// this is a violation to EWMH, as KWin just ignores the strut
for ( int i = 0 ; i < Screens : : self ( ) - > count ( ) ; i + + ) {
if ( ! r . intersects ( Screens : : self ( ) - > geometry ( i ) ) ) {
qCDebug ( KWIN_CORE ) < < " Adjusted client area would exclude a complete screen, ignore " ;
r = desktopArea ;
break ;
}
}
2020-08-17 13:14:20 +00:00
StrutRects strutRegion = client - > strutRects ( ) ;
const QRect clientsScreenRect = KWin : : screens ( ) - > geometry ( client - > screen ( ) ) ;
2020-01-13 18:57:07 +00:00
for ( auto strut = strutRegion . begin ( ) ; strut ! = strutRegion . end ( ) ; strut + + ) {
* strut = StrutRect ( ( * strut ) . intersected ( clientsScreenRect ) , ( * strut ) . area ( ) ) ;
}
// Ignore offscreen xinerama struts. These interfere with the larger monitors on the setup
// and should be ignored so that applications that use the work area to work out where
// windows can go can use the entire visible area of the larger monitors.
// This goes against the EWMH description of the work area but it is a toss up between
// having unusable sections of the screen (Which can be quite large with newer monitors)
// or having some content appear offscreen (Relatively rare compared to other).
2020-08-17 13:14:20 +00:00
bool hasOffscreenStrut = hasOffscreenXineramaStrut ( client ) ;
2020-01-13 18:57:07 +00:00
2020-08-17 13:14:20 +00:00
if ( client - > isOnAllDesktops ( ) ) {
2020-01-13 18:57:07 +00:00
for ( int i = 1 ;
i < = numberOfDesktops ;
+ + i ) {
2020-08-17 13:14:20 +00:00
if ( ! hasOffscreenStrut )
2020-01-13 18:57:07 +00:00
new_wareas [ i ] = new_wareas [ i ] . intersected ( r ) ;
new_rmoveareas [ i ] + = strutRegion ;
for ( int iS = 0 ;
iS < nscreens ;
iS + + ) {
const auto geo = new_sareas [ i ] [ iS ] . intersected (
2020-08-17 13:14:20 +00:00
adjustClientArea ( client , screens [ iS ] ) ) ;
2020-01-13 18:57:07 +00:00
// ignore the geometry if it results in the screen getting removed completely
if ( ! geo . isEmpty ( ) ) {
new_sareas [ i ] [ iS ] = geo ;
}
}
}
} else {
2020-08-17 13:14:20 +00:00
if ( ! hasOffscreenStrut )
new_wareas [ client - > desktop ( ) ] = new_wareas [ client - > desktop ( ) ] . intersected ( r ) ;
new_rmoveareas [ client - > desktop ( ) ] + = strutRegion ;
2020-01-13 18:57:07 +00:00
for ( int iS = 0 ;
iS < nscreens ;
iS + + ) {
// qDebug() << "adjusting new_sarea: " << screens[ iS ];
2020-08-17 13:14:20 +00:00
const auto geo = new_sareas [ client - > desktop ( ) ] [ iS ] . intersected (
adjustClientArea ( client , screens [ iS ] ) ) ;
2020-01-13 18:57:07 +00:00
// ignore the geometry if it results in the screen getting removed completely
if ( ! geo . isEmpty ( ) ) {
2020-08-17 13:14:20 +00:00
new_sareas [ client - > desktop ( ) ] [ iS ] = geo ;
2020-01-13 18:57:07 +00:00
}
}
}
}
#if 0
for ( int i = 1 ;
i < = numberOfDesktops ( ) ;
+ + i ) {
for ( int iS = 0 ;
iS < nscreens ;
iS + + )
qCDebug ( KWIN_CORE ) < < " new_sarea: " < < new_sareas [ i ] [ iS ] ;
}
# endif
bool changed = force ;
if ( screenarea . isEmpty ( ) )
changed = true ;
for ( int i = 1 ;
! changed & & i < = numberOfDesktops ;
+ + i ) {
if ( workarea [ i ] ! = new_wareas [ i ] )
changed = true ;
if ( restrictedmovearea [ i ] ! = new_rmoveareas [ i ] )
changed = true ;
if ( screenarea [ i ] . size ( ) ! = new_sareas [ i ] . size ( ) )
changed = true ;
for ( int iS = 0 ;
! changed & & iS < nscreens ;
iS + + )
if ( new_sareas [ i ] [ iS ] ! = screenarea [ i ] [ iS ] )
changed = true ;
}
if ( changed ) {
workarea = new_wareas ;
oldrestrictedmovearea = restrictedmovearea ;
restrictedmovearea = new_rmoveareas ;
screenarea = new_sareas ;
if ( rootInfo ( ) ) {
NETRect r ;
for ( int i = 1 ; i < = numberOfDesktops ; i + + ) {
r . pos . x = workarea [ i ] . x ( ) ;
r . pos . y = workarea [ i ] . y ( ) ;
r . size . width = workarea [ i ] . width ( ) ;
r . size . height = workarea [ i ] . height ( ) ;
rootInfo ( ) - > setWorkArea ( i , r ) ;
}
}
for ( auto it = m_allClients . constBegin ( ) ;
it ! = m_allClients . constEnd ( ) ;
2020-08-06 15:23:03 +00:00
+ + it ) {
2020-08-19 07:31:38 +00:00
( * it ) - > checkWorkspacePosition ( ) ;
2020-08-06 15:23:03 +00:00
}
2020-01-13 18:57:07 +00:00
oldrestrictedmovearea . clear ( ) ; // reset, no longer valid or needed
}
}
void Workspace : : updateClientArea ( )
{
updateClientArea ( false ) ;
}
/**
* Returns the area available for clients . This is the desktop
* geometry minus windows on the dock . Placement algorithms should
* refer to this rather than Screens : : geometry .
*/
QRect Workspace : : clientArea ( clientAreaOption opt , int screen , int desktop ) const
{
if ( desktop = = NETWinInfo : : OnAllDesktops | | desktop = = 0 )
desktop = VirtualDesktopManager : : self ( ) - > current ( ) ;
if ( screen = = - 1 )
screen = screens ( ) - > current ( ) ;
const QSize displaySize = screens ( ) - > displaySize ( ) ;
QRect sarea , warea ;
if ( is_multihead ) {
sarea = ( ! screenarea . isEmpty ( )
& & screen < screenarea [ desktop ] . size ( ) ) // screens may be missing during KWin initialization or screen config changes
? screenarea [ desktop ] [ screen_number ]
: screens ( ) - > geometry ( screen_number ) ;
warea = workarea [ desktop ] . isNull ( )
? screens ( ) - > geometry ( screen_number )
: workarea [ desktop ] ;
} else {
sarea = ( ! screenarea . isEmpty ( )
& & screen < screenarea [ desktop ] . size ( ) ) // screens may be missing during KWin initialization or screen config changes
? screenarea [ desktop ] [ screen ]
: screens ( ) - > geometry ( screen ) ;
warea = workarea [ desktop ] . isNull ( )
? QRect ( 0 , 0 , displaySize . width ( ) , displaySize . height ( ) )
: workarea [ desktop ] ;
}
switch ( opt ) {
case MaximizeArea :
case PlacementArea :
return sarea ;
case MaximizeFullArea :
case FullScreenArea :
case MovementArea :
case ScreenArea :
if ( is_multihead )
return screens ( ) - > geometry ( screen_number ) ;
else
return screens ( ) - > geometry ( screen ) ;
case WorkArea :
if ( is_multihead )
return sarea ;
else
return warea ;
case FullArea :
return QRect ( 0 , 0 , displaySize . width ( ) , displaySize . height ( ) ) ;
}
abort ( ) ;
}
2021-02-19 13:59:01 +00:00
QRect Workspace : : clientArea ( clientAreaOption opt , const AbstractOutput * output , int desktop ) const
{
return clientArea ( opt , kwinApp ( ) - > platform ( ) - > enabledOutputs ( ) . indexOf ( output ) , desktop ) ;
}
2020-01-13 18:57:07 +00:00
QRect Workspace : : clientArea ( clientAreaOption opt , const QPoint & p , int desktop ) const
{
return clientArea ( opt , screens ( ) - > number ( p ) , desktop ) ;
}
QRect Workspace : : clientArea ( clientAreaOption opt , const AbstractClient * c ) const
{
return clientArea ( opt , c - > frameGeometry ( ) . center ( ) , c - > desktop ( ) ) ;
}
QRegion Workspace : : restrictedMoveArea ( int desktop , StrutAreas areas ) const
{
if ( desktop = = NETWinInfo : : OnAllDesktops | | desktop = = 0 )
desktop = VirtualDesktopManager : : self ( ) - > current ( ) ;
QRegion region ;
foreach ( const StrutRect & rect , restrictedmovearea [ desktop ] )
if ( areas & rect . area ( ) )
region + = rect ;
return region ;
}
bool Workspace : : inUpdateClientArea ( ) const
{
return ! oldrestrictedmovearea . isEmpty ( ) ;
}
QRegion Workspace : : previousRestrictedMoveArea ( int desktop , StrutAreas areas ) const
{
if ( desktop = = NETWinInfo : : OnAllDesktops | | desktop = = 0 )
desktop = VirtualDesktopManager : : self ( ) - > current ( ) ;
QRegion region ;
foreach ( const StrutRect & rect , oldrestrictedmovearea . at ( desktop ) )
if ( areas & rect . area ( ) )
region + = rect ;
return region ;
}
QVector < QRect > Workspace : : previousScreenSizes ( ) const
{
return oldscreensizes ;
}
int Workspace : : oldDisplayWidth ( ) const
{
return olddisplaysize . width ( ) ;
}
int Workspace : : oldDisplayHeight ( ) const
{
return olddisplaysize . height ( ) ;
}
/**
* Client \ a c is moved around to position \ a pos . This gives the
* workspace the opportunity to interveniate and to implement
* snap - to - windows functionality .
*
* The parameter \ a snapAdjust is a multiplier used to calculate the
* effective snap zones . When 1.0 , it means that the snap zones will be
* used without change .
*/
QPoint Workspace : : adjustClientPosition ( AbstractClient * c , QPoint pos , bool unrestricted , double snapAdjust )
{
QSize borderSnapZone ( options - > borderSnapZone ( ) , options - > borderSnapZone ( ) ) ;
QRect maxRect ;
int guideMaximized = MaximizeRestore ;
if ( c - > maximizeMode ( ) ! = MaximizeRestore ) {
maxRect = clientArea ( MaximizeArea , pos + c - > rect ( ) . center ( ) , c - > desktop ( ) ) ;
QRect geo = c - > frameGeometry ( ) ;
if ( c - > maximizeMode ( ) & MaximizeHorizontal & & ( geo . x ( ) = = maxRect . left ( ) | | geo . right ( ) = = maxRect . right ( ) ) ) {
guideMaximized | = MaximizeHorizontal ;
borderSnapZone . setWidth ( qMax ( borderSnapZone . width ( ) + 2 , maxRect . width ( ) / 16 ) ) ;
}
if ( c - > maximizeMode ( ) & MaximizeVertical & & ( geo . y ( ) = = maxRect . top ( ) | | geo . bottom ( ) = = maxRect . bottom ( ) ) ) {
guideMaximized | = MaximizeVertical ;
borderSnapZone . setHeight ( qMax ( borderSnapZone . height ( ) + 2 , maxRect . height ( ) / 16 ) ) ;
}
}
if ( options - > windowSnapZone ( ) | | ! borderSnapZone . isNull ( ) | | options - > centerSnapZone ( ) ) {
const bool sOWO = options - > isSnapOnlyWhenOverlapping ( ) ;
const int screen = screens ( ) - > number ( pos + c - > rect ( ) . center ( ) ) ;
if ( maxRect . isNull ( ) )
maxRect = clientArea ( MovementArea , screen , c - > desktop ( ) ) ;
const int xmin = maxRect . left ( ) ;
const int xmax = maxRect . right ( ) + 1 ; //desk size
const int ymin = maxRect . top ( ) ;
const int ymax = maxRect . bottom ( ) + 1 ;
const int cx ( pos . x ( ) ) ;
const int cy ( pos . y ( ) ) ;
const int cw ( c - > width ( ) ) ;
const int ch ( c - > height ( ) ) ;
const int rx ( cx + cw ) ;
const int ry ( cy + ch ) ; //these don't change
int nx ( cx ) , ny ( cy ) ; //buffers
int deltaX ( xmax ) ;
int deltaY ( ymax ) ; //minimum distance to other clients
int lx , ly , lrx , lry ; //coords and size for the comparison client, l
// border snap
const int snapX = borderSnapZone . width ( ) * snapAdjust ; //snap trigger
const int snapY = borderSnapZone . height ( ) * snapAdjust ;
if ( snapX | | snapY ) {
QRect geo = c - > frameGeometry ( ) ;
QMargins frameMargins = c - > frameMargins ( ) ;
// snap to titlebar / snap to window borders on inner screen edges
AbstractClient : : Position titlePos = c - > titlebarPosition ( ) ;
if ( frameMargins . left ( ) & & ( titlePos = = AbstractClient : : PositionLeft | | ( c - > maximizeMode ( ) & MaximizeHorizontal ) | |
screens ( ) - > intersecting ( geo . translated ( maxRect . x ( ) - ( frameMargins . left ( ) + geo . x ( ) ) , 0 ) ) > 1 ) ) {
frameMargins . setLeft ( 0 ) ;
}
if ( frameMargins . right ( ) & & ( titlePos = = AbstractClient : : PositionRight | | ( c - > maximizeMode ( ) & MaximizeHorizontal ) | |
screens ( ) - > intersecting ( geo . translated ( maxRect . right ( ) + frameMargins . right ( ) - geo . right ( ) , 0 ) ) > 1 ) ) {
frameMargins . setRight ( 0 ) ;
}
if ( frameMargins . top ( ) & & ( titlePos = = AbstractClient : : PositionTop | | ( c - > maximizeMode ( ) & MaximizeVertical ) | |
screens ( ) - > intersecting ( geo . translated ( 0 , maxRect . y ( ) - ( frameMargins . top ( ) + geo . y ( ) ) ) ) > 1 ) ) {
frameMargins . setTop ( 0 ) ;
}
if ( frameMargins . bottom ( ) & & ( titlePos = = AbstractClient : : PositionBottom | | ( c - > maximizeMode ( ) & MaximizeVertical ) | |
screens ( ) - > intersecting ( geo . translated ( 0 , maxRect . bottom ( ) + frameMargins . bottom ( ) - geo . bottom ( ) ) ) > 1 ) ) {
frameMargins . setBottom ( 0 ) ;
}
if ( ( sOWO ? ( cx < xmin ) : true ) & & ( qAbs ( xmin - cx ) < snapX ) ) {
deltaX = xmin - cx ;
nx = xmin - frameMargins . left ( ) ;
}
if ( ( sOWO ? ( rx > xmax ) : true ) & & ( qAbs ( rx - xmax ) < snapX ) & & ( qAbs ( xmax - rx ) < deltaX ) ) {
deltaX = rx - xmax ;
nx = xmax - cw + frameMargins . right ( ) ;
}
if ( ( sOWO ? ( cy < ymin ) : true ) & & ( qAbs ( ymin - cy ) < snapY ) ) {
deltaY = ymin - cy ;
ny = ymin - frameMargins . top ( ) ;
}
if ( ( sOWO ? ( ry > ymax ) : true ) & & ( qAbs ( ry - ymax ) < snapY ) & & ( qAbs ( ymax - ry ) < deltaY ) ) {
deltaY = ry - ymax ;
ny = ymax - ch + frameMargins . bottom ( ) ;
}
}
// windows snap
int snap = options - > windowSnapZone ( ) * snapAdjust ;
if ( snap ) {
for ( auto l = m_allClients . constBegin ( ) ; l ! = m_allClients . constEnd ( ) ; + + l ) {
if ( ( * l ) = = c )
continue ;
if ( ( * l ) - > isMinimized ( ) )
continue ; // is minimized
if ( ! ( * l ) - > isShown ( false ) )
continue ;
if ( ! ( ( * l ) - > isOnDesktop ( c - > desktop ( ) ) | | c - > isOnDesktop ( ( * l ) - > desktop ( ) ) ) )
continue ; // wrong virtual desktop
if ( ! ( * l ) - > isOnCurrentActivity ( ) )
continue ; // wrong activity
2021-01-20 12:25:42 +00:00
if ( ( * l ) - > isDesktop ( ) | | ( * l ) - > isSplash ( ) | | ( * l ) - > isNotification ( ) | |
( * l ) - > isCriticalNotification ( ) | | ( * l ) - > isOnScreenDisplay ( ) )
2020-01-13 18:57:07 +00:00
continue ;
lx = ( * l ) - > x ( ) ;
ly = ( * l ) - > y ( ) ;
lrx = lx + ( * l ) - > width ( ) ;
lry = ly + ( * l ) - > height ( ) ;
if ( ! ( guideMaximized & MaximizeHorizontal ) & &
( ( ( cy < = lry ) & & ( cy > = ly ) ) | | ( ( ry > = ly ) & & ( ry < = lry ) ) | | ( ( cy < = ly ) & & ( ry > = lry ) ) ) ) {
if ( ( sOWO ? ( cx < lrx ) : true ) & & ( qAbs ( lrx - cx ) < snap ) & & ( qAbs ( lrx - cx ) < deltaX ) ) {
deltaX = qAbs ( lrx - cx ) ;
nx = lrx ;
}
if ( ( sOWO ? ( rx > lx ) : true ) & & ( qAbs ( rx - lx ) < snap ) & & ( qAbs ( rx - lx ) < deltaX ) ) {
deltaX = qAbs ( rx - lx ) ;
nx = lx - cw ;
}
}
if ( ! ( guideMaximized & MaximizeVertical ) & &
( ( ( cx < = lrx ) & & ( cx > = lx ) ) | | ( ( rx > = lx ) & & ( rx < = lrx ) ) | | ( ( cx < = lx ) & & ( rx > = lrx ) ) ) ) {
if ( ( sOWO ? ( cy < lry ) : true ) & & ( qAbs ( lry - cy ) < snap ) & & ( qAbs ( lry - cy ) < deltaY ) ) {
deltaY = qAbs ( lry - cy ) ;
ny = lry ;
}
//if ( (qAbs( ry-ly ) < snap) && (qAbs( ry - ly ) < deltaY ))
if ( ( sOWO ? ( ry > ly ) : true ) & & ( qAbs ( ry - ly ) < snap ) & & ( qAbs ( ry - ly ) < deltaY ) ) {
deltaY = qAbs ( ry - ly ) ;
ny = ly - ch ;
}
}
// Corner snapping
if ( ! ( guideMaximized & MaximizeVertical ) & & ( nx = = lrx | | nx + cw = = lx ) ) {
if ( ( sOWO ? ( ry > lry ) : true ) & & ( qAbs ( lry - ry ) < snap ) & & ( qAbs ( lry - ry ) < deltaY ) ) {
deltaY = qAbs ( lry - ry ) ;
ny = lry - ch ;
}
if ( ( sOWO ? ( cy < ly ) : true ) & & ( qAbs ( cy - ly ) < snap ) & & ( qAbs ( cy - ly ) < deltaY ) ) {
deltaY = qAbs ( cy - ly ) ;
ny = ly ;
}
}
if ( ! ( guideMaximized & MaximizeHorizontal ) & & ( ny = = lry | | ny + ch = = ly ) ) {
if ( ( sOWO ? ( rx > lrx ) : true ) & & ( qAbs ( lrx - rx ) < snap ) & & ( qAbs ( lrx - rx ) < deltaX ) ) {
deltaX = qAbs ( lrx - rx ) ;
nx = lrx - cw ;
}
if ( ( sOWO ? ( cx < lx ) : true ) & & ( qAbs ( cx - lx ) < snap ) & & ( qAbs ( cx - lx ) < deltaX ) ) {
deltaX = qAbs ( cx - lx ) ;
nx = lx ;
}
}
}
}
// center snap
snap = options - > centerSnapZone ( ) * snapAdjust ; //snap trigger
if ( snap ) {
int diffX = qAbs ( ( xmin + xmax ) / 2 - ( cx + cw / 2 ) ) ;
int diffY = qAbs ( ( ymin + ymax ) / 2 - ( cy + ch / 2 ) ) ;
if ( diffX < snap & & diffY < snap & & diffX < deltaX & & diffY < deltaY ) {
// Snap to center of screen
nx = ( xmin + xmax ) / 2 - cw / 2 ;
ny = ( ymin + ymax ) / 2 - ch / 2 ;
} else if ( options - > borderSnapZone ( ) ) {
// Enhance border snap
if ( ( nx = = xmin | | nx = = xmax - cw ) & & diffY < snap & & diffY < deltaY ) {
// Snap to vertical center on screen edge
ny = ( ymin + ymax ) / 2 - ch / 2 ;
} else if ( ( ( unrestricted ? ny = = ymin : ny < = ymin ) | | ny = = ymax - ch ) & &
diffX < snap & & diffX < deltaX ) {
// Snap to horizontal center on screen edge
nx = ( xmin + xmax ) / 2 - cw / 2 ;
}
}
}
pos = QPoint ( nx , ny ) ;
}
return pos ;
}
QRect Workspace : : adjustClientSize ( AbstractClient * c , QRect moveResizeGeom , int mode )
{
//adapted from adjustClientPosition on 29May2004
//this function is called when resizing a window and will modify
//the new dimensions to snap to other windows/borders if appropriate
if ( options - > windowSnapZone ( ) | | options - > borderSnapZone ( ) ) { // || options->centerSnapZone )
const bool sOWO = options - > isSnapOnlyWhenOverlapping ( ) ;
const QRect maxRect = clientArea ( MovementArea , c - > rect ( ) . center ( ) , c - > desktop ( ) ) ;
const int xmin = maxRect . left ( ) ;
const int xmax = maxRect . right ( ) ; //desk size
const int ymin = maxRect . top ( ) ;
const int ymax = maxRect . bottom ( ) ;
const int cx ( moveResizeGeom . left ( ) ) ;
const int cy ( moveResizeGeom . top ( ) ) ;
const int rx ( moveResizeGeom . right ( ) ) ;
const int ry ( moveResizeGeom . bottom ( ) ) ;
int newcx ( cx ) , newcy ( cy ) ; //buffers
int newrx ( rx ) , newry ( ry ) ;
int deltaX ( xmax ) ;
int deltaY ( ymax ) ; //minimum distance to other clients
int lx , ly , lrx , lry ; //coords and size for the comparison client, l
// border snap
int snap = options - > borderSnapZone ( ) ; //snap trigger
if ( snap ) {
deltaX = int ( snap ) ;
deltaY = int ( snap ) ;
# define SNAP_BORDER_TOP \
if ( ( sOWO ? ( newcy < ymin ) : true ) & & ( qAbs ( ymin - newcy ) < deltaY ) ) \
{ \
deltaY = qAbs ( ymin - newcy ) ; \
newcy = ymin ; \
}
# define SNAP_BORDER_BOTTOM \
if ( ( sOWO ? ( newry > ymax ) : true ) & & ( qAbs ( ymax - newry ) < deltaY ) ) \
{ \
deltaY = qAbs ( ymax - newcy ) ; \
newry = ymax ; \
}
# define SNAP_BORDER_LEFT \
if ( ( sOWO ? ( newcx < xmin ) : true ) & & ( qAbs ( xmin - newcx ) < deltaX ) ) \
{ \
deltaX = qAbs ( xmin - newcx ) ; \
newcx = xmin ; \
}
# define SNAP_BORDER_RIGHT \
if ( ( sOWO ? ( newrx > xmax ) : true ) & & ( qAbs ( xmax - newrx ) < deltaX ) ) \
{ \
deltaX = qAbs ( xmax - newrx ) ; \
newrx = xmax ; \
}
switch ( mode ) {
case AbstractClient : : PositionBottomRight :
SNAP_BORDER_BOTTOM
SNAP_BORDER_RIGHT
break ;
case AbstractClient : : PositionRight :
SNAP_BORDER_RIGHT
break ;
case AbstractClient : : PositionBottom :
SNAP_BORDER_BOTTOM
break ;
case AbstractClient : : PositionTopLeft :
SNAP_BORDER_TOP
SNAP_BORDER_LEFT
break ;
case AbstractClient : : PositionLeft :
SNAP_BORDER_LEFT
break ;
case AbstractClient : : PositionTop :
SNAP_BORDER_TOP
break ;
case AbstractClient : : PositionTopRight :
SNAP_BORDER_TOP
SNAP_BORDER_RIGHT
break ;
case AbstractClient : : PositionBottomLeft :
SNAP_BORDER_BOTTOM
SNAP_BORDER_LEFT
break ;
default :
abort ( ) ;
break ;
}
}
// windows snap
snap = options - > windowSnapZone ( ) ;
if ( snap ) {
deltaX = int ( snap ) ;
deltaY = int ( snap ) ;
for ( auto l = m_allClients . constBegin ( ) ; l ! = m_allClients . constEnd ( ) ; + + l ) {
if ( ( * l ) - > isOnDesktop ( VirtualDesktopManager : : self ( ) - > current ( ) ) & &
! ( * l ) - > isMinimized ( )
& & ( * l ) ! = c ) {
lx = ( * l ) - > x ( ) - 1 ;
ly = ( * l ) - > y ( ) - 1 ;
lrx = ( * l ) - > x ( ) + ( * l ) - > width ( ) ;
lry = ( * l ) - > y ( ) + ( * l ) - > height ( ) ;
# define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \
( ( newry > = ly ) & & ( newry < = lry ) ) | | \
( ( newcy < = ly ) & & ( newry > = lry ) ) )
# define WITHIN_WIDTH ( (( cx <= lrx ) && ( cx >= lx )) || \
( ( rx > = lx ) & & ( rx < = lrx ) ) | | \
( ( cx < = lx ) & & ( rx > = lrx ) ) )
# define SNAP_WINDOW_TOP if ( (sOWO?(newcy<lry):true) \
& & WITHIN_WIDTH \
& & ( qAbs ( lry - newcy ) < deltaY ) ) { \
deltaY = qAbs ( lry - newcy ) ; \
newcy = lry ; \
}
# define SNAP_WINDOW_BOTTOM if ( (sOWO?(newry>ly):true) \
& & WITHIN_WIDTH \
& & ( qAbs ( ly - newry ) < deltaY ) ) { \
deltaY = qAbs ( ly - newry ) ; \
newry = ly ; \
}
# define SNAP_WINDOW_LEFT if ( (sOWO?(newcx<lrx):true) \
& & WITHIN_HEIGHT \
& & ( qAbs ( lrx - newcx ) < deltaX ) ) { \
deltaX = qAbs ( lrx - newcx ) ; \
newcx = lrx ; \
}
# define SNAP_WINDOW_RIGHT if ( (sOWO?(newrx>lx):true) \
& & WITHIN_HEIGHT \
& & ( qAbs ( lx - newrx ) < deltaX ) ) \
{ \
deltaX = qAbs ( lx - newrx ) ; \
newrx = lx ; \
}
# define SNAP_WINDOW_C_TOP if ( (sOWO?(newcy<ly):true) \
& & ( newcx = = lrx | | newrx = = lx ) \
& & qAbs ( ly - newcy ) < deltaY ) { \
deltaY = qAbs ( ly - newcy + 1 ) ; \
newcy = ly + 1 ; \
}
# define SNAP_WINDOW_C_BOTTOM if ( (sOWO?(newry>lry):true) \
& & ( newcx = = lrx | | newrx = = lx ) \
& & qAbs ( lry - newry ) < deltaY ) { \
deltaY = qAbs ( lry - newry - 1 ) ; \
newry = lry - 1 ; \
}
# define SNAP_WINDOW_C_LEFT if ( (sOWO?(newcx<lx):true) \
& & ( newcy = = lry | | newry = = ly ) \
& & qAbs ( lx - newcx ) < deltaX ) { \
deltaX = qAbs ( lx - newcx + 1 ) ; \
newcx = lx + 1 ; \
}
# define SNAP_WINDOW_C_RIGHT if ( (sOWO?(newrx>lrx):true) \
& & ( newcy = = lry | | newry = = ly ) \
& & qAbs ( lrx - newrx ) < deltaX ) { \
deltaX = qAbs ( lrx - newrx - 1 ) ; \
newrx = lrx - 1 ; \
}
switch ( mode ) {
case AbstractClient : : PositionBottomRight :
SNAP_WINDOW_BOTTOM
SNAP_WINDOW_RIGHT
SNAP_WINDOW_C_BOTTOM
SNAP_WINDOW_C_RIGHT
break ;
case AbstractClient : : PositionRight :
SNAP_WINDOW_RIGHT
SNAP_WINDOW_C_RIGHT
break ;
case AbstractClient : : PositionBottom :
SNAP_WINDOW_BOTTOM
SNAP_WINDOW_C_BOTTOM
break ;
case AbstractClient : : PositionTopLeft :
SNAP_WINDOW_TOP
SNAP_WINDOW_LEFT
SNAP_WINDOW_C_TOP
SNAP_WINDOW_C_LEFT
break ;
case AbstractClient : : PositionLeft :
SNAP_WINDOW_LEFT
SNAP_WINDOW_C_LEFT
break ;
case AbstractClient : : PositionTop :
SNAP_WINDOW_TOP
SNAP_WINDOW_C_TOP
break ;
case AbstractClient : : PositionTopRight :
SNAP_WINDOW_TOP
SNAP_WINDOW_RIGHT
SNAP_WINDOW_C_TOP
SNAP_WINDOW_C_RIGHT
break ;
case AbstractClient : : PositionBottomLeft :
SNAP_WINDOW_BOTTOM
SNAP_WINDOW_LEFT
SNAP_WINDOW_C_BOTTOM
SNAP_WINDOW_C_LEFT
break ;
default :
abort ( ) ;
break ;
}
}
}
}
// center snap
//snap = options->centerSnapZone;
//if (snap)
// {
// // Don't resize snap to center as it interferes too much
// // There are two ways of implementing this if wanted:
// // 1) Snap only to the same points that the move snap does, and
// // 2) Snap to the horizontal and vertical center lines of the screen
// }
moveResizeGeom = QRect ( QPoint ( newcx , newcy ) , QPoint ( newrx , newry ) ) ;
}
return moveResizeGeom ;
}
/**
* Marks the client as being moved or resized by the user .
*/
void Workspace : : setMoveResizeClient ( AbstractClient * c )
{
Q_ASSERT ( ! c | | ! movingClient ) ; // Catch attempts to move a second
// window while still moving the first one.
movingClient = c ;
if ( movingClient )
+ + block_focus ;
else
- - block_focus ;
}
// When kwin crashes, windows will not be gravitated back to their original position
// and will remain offset by the size of the decoration. So when restarting, fix this
// (the property with the size of the frame remains on the window after the crash).
void Workspace : : fixPositionAfterCrash ( xcb_window_t w , const xcb_get_geometry_reply_t * geometry )
{
NETWinInfo i ( connection ( ) , w , rootWindow ( ) , NET : : WMFrameExtents , NET : : Properties2 ( ) ) ;
NETStrut frame = i . frameExtents ( ) ;
if ( frame . left ! = 0 | | frame . top ! = 0 ) {
// left and top needed due to narrowing conversations restrictions in C++11
const uint32_t left = frame . left ;
const uint32_t top = frame . top ;
const uint32_t values [ ] = { geometry - > x - left , geometry - > y - top } ;
xcb_configure_window ( connection ( ) , w , XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y , values ) ;
}
}
2019-08-26 07:44:04 +00:00
} // namespace