2007-11-27 19:40:25 +00:00
/********************************************************************
2007-04-29 17:35:43 +00:00
KWin - the KDE window manager
This file is part of the KDE project .
Copyright ( C ) 1999 , 2000 Matthias Ettrich < ettrich @ kde . org >
Copyright ( C ) 2003 Lubos Lunak < l . lunak @ kde . org >
2007-11-27 19:40:25 +00:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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>
2014-03-16 14:06:04 +00:00
# include <kwinxrenderutils.h>
2013-04-25 14:08:39 +00:00
// kwin
# ifdef KWIN_BUILD_ACTIVITIES
# include "activities.h"
# endif
# include "atoms.h"
2007-04-29 17:35:43 +00:00
# include "client.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"
2014-08-15 07:30:08 +00:00
# include "logind.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"
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"
2012-04-12 13:19:38 +00:00
# include "scripting/scripting.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"
2015-03-04 08:21:10 +00:00
# include "shell_client.h"
# 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"
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>
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
2013-04-30 12:55:06 +00:00
ColorMapper : : ColorMapper ( QObject * parent )
: QObject ( parent )
, m_default ( defaultScreen ( ) - > default_colormap )
, m_installed ( defaultScreen ( ) - > default_colormap )
{
}
ColorMapper : : ~ ColorMapper ( )
{
}
void ColorMapper : : update ( )
{
xcb_colormap_t cmap = m_default ;
2015-03-06 12:37:56 +00:00
if ( Client * c = dynamic_cast < Client * > ( 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 ;
}
}
2008-12-18 13:50:57 +00:00
Workspace * Workspace : : _self = 0 ;
2007-04-29 17:35:43 +00:00
2015-05-01 14:55:15 +00:00
Workspace : : Workspace ( const QString & sessionKey )
2011-01-30 14:34:42 +00:00
: QObject ( 0 )
2012-08-27 17:45:01 +00:00
, m_compositor ( NULL )
2009-02-14 15:40:52 +00:00
// Unsorted
2011-01-30 14:34:42 +00:00
, active_popup ( NULL )
, active_popup_client ( NULL )
2015-05-01 14:55:15 +00:00
, m_initialDesktop ( 1 )
2011-01-30 14:34:42 +00:00
, active_client ( 0 )
, last_active_client ( 0 )
, most_recently_raised ( 0 )
, movingClient ( 0 )
, delayfocus_client ( 0 )
, force_restacking ( false )
, x_stacking_dirty ( true )
, showing_desktop ( false )
, was_user_interaction ( false )
, session_saving ( false )
, block_focus ( 0 )
2012-08-19 10:00:53 +00:00
, m_userActionsMenu ( new UserActionsMenu ( this ) )
2011-01-30 14:34:42 +00:00
, client_keys_dialog ( NULL )
, client_keys_client ( NULL )
, global_shortcuts_disabled_for_client ( false )
, workspaceInit ( true )
, startup ( 0 )
, set_active_client_recursion ( 0 )
, block_stacking_updates ( 0 )
{
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 ) ;
2007-04-29 17:35:43 +00:00
_self = this ;
2012-04-13 06:39:04 +00:00
// first initialize the extensions
2012-12-21 14:11:31 +00:00
Xcb : : Extensions : : self ( ) ;
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 ) {
connect ( activities , SIGNAL ( currentChanged ( QString ) ) , SLOT ( updateCurrentActivity ( QString ) ) ) ;
}
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 ) ;
2013-04-30 12:55:06 +00:00
ColorMapper * colormaps = new ColorMapper ( this ) ;
2015-03-06 12:58:24 +00:00
connect ( this , & Workspace : : clientActivated , colormaps , & ColorMapper : : update ) ;
2007-04-29 17:35:43 +00:00
delayFocusTimer = 0 ;
2015-05-01 14:55:15 +00:00
if ( ! sessionKey . isEmpty ( ) )
loadSessionInfo ( sessionKey ) ;
connect ( qApp , & QGuiApplication : : commitDataRequest , this , & Workspace : : commitData ) ;
connect ( qApp , & QGuiApplication : : saveStateRequest , this , & Workspace : : saveState ) ;
2007-04-29 17:35:43 +00:00
2013-04-26 12:40:35 +00:00
RuleBook : : create ( this ) - > load ( ) ;
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
// Call this before XSelectInput() on the root window
2007-04-29 17:35:43 +00:00
startup = new KStartupInfo (
2011-01-30 14:34:42 +00:00
KStartupInfo : : DisableKWinModule | KStartupInfo : : AnnounceSilenceChanges , this ) ;
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
// Select windowmanager privileges
2014-06-15 12:05:53 +00:00
selectWmInputEventMask ( ) ;
2007-04-29 17:35:43 +00:00
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 ) ;
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
2014-03-16 14:06:04 +00:00
// init XRenderUtils
2015-03-18 15:24:25 +00:00
if ( kwinApp ( ) - > operationMode ( ) = = Application : : OperationModeX11 ) {
XRenderUtils : : init ( connection ( ) , rootWindow ( ) ) ;
}
2015-02-23 14:57:00 +00:00
if ( Compositor : : self ( ) ) {
m_compositor = Compositor : : self ( ) ;
} else {
m_compositor = Compositor : : create ( this ) ;
}
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
new DBusInterface ( this ) ;
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
// Compatibility
2013-09-10 09:33:34 +00:00
int32_t data = 1 ;
xcb_change_property ( connection ( ) , XCB_PROP_MODE_APPEND , rootWindow ( ) , atoms - > kwin_running ,
atoms - > kwin_running , 32 , 1 , & data ) ;
2007-04-29 17:35:43 +00:00
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
{
2013-08-13 08:16:12 +00:00
updateXTime ( ) ; // Needed for proper initialization of user_time in Client ctor
2016-01-29 10:24:18 +00:00
KSharedConfigPtr config = kwinApp ( ) - > config ( ) ;
2015-02-20 13:53:03 +00:00
kwinApp ( ) - > createScreens ( ) ;
2013-04-03 10:19:27 +00:00
Screens * screens = Screens : : self ( ) ;
2015-04-22 06:25:37 +00:00
// get screen support
connect ( screens , SIGNAL ( changed ( ) ) , SLOT ( desktopResized ( ) ) ) ;
2013-09-04 14:10:36 +00:00
screens - > setConfig ( config ) ;
2013-04-03 10:19:27 +00:00
screens - > reconfigure ( ) ;
connect ( options , SIGNAL ( configChanged ( ) ) , screens , SLOT ( 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 ( ) ;
connect ( options , SIGNAL ( configChanged ( ) ) , screenEdges , SLOT ( reconfigure ( ) ) ) ;
connect ( VirtualDesktopManager : : self ( ) , SIGNAL ( layoutChanged ( int , int ) ) , screenEdges , SLOT ( 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 ) ;
2012-11-20 16:26:50 +00:00
connect ( VirtualDesktopManager : : self ( ) , SIGNAL ( countChanged ( uint , uint ) ) , focusChain , SLOT ( resize ( uint , uint ) ) ) ;
connect ( VirtualDesktopManager : : self ( ) , SIGNAL ( currentChanged ( uint , uint ) ) , focusChain , SLOT ( setCurrentDesktop ( uint , uint ) ) ) ;
connect ( options , SIGNAL ( separateScreenFocusChanged ( bool ) ) , focusChain , SLOT ( setSeparateScreenFocus ( bool ) ) ) ;
focusChain - > setSeparateScreenFocus ( options - > isSeparateScreenFocus ( ) ) ;
2013-04-30 11:06:46 +00:00
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 ( ) ;
2007-04-29 17:35:43 +00:00
2013-04-29 10:17:42 +00:00
RootInfo * rootInfo = RootInfo : : create ( ) ;
2007-04-29 17:35:43 +00:00
2012-11-16 07:23:47 +00:00
// create VirtualDesktopManager and perform dependency injection
VirtualDesktopManager * vds = VirtualDesktopManager : : self ( ) ;
connect ( vds , SIGNAL ( desktopsRemoved ( uint ) ) , SLOT ( moveClientsFromRemovedDesktops ( ) ) ) ;
connect ( vds , SIGNAL ( countChanged ( uint , uint ) ) , SLOT ( slotDesktopCountChanged ( uint , uint ) ) ) ;
connect ( vds , SIGNAL ( currentChanged ( uint , uint ) ) , SLOT ( slotCurrentDesktopChanged ( uint , uint ) ) ) ;
vds - > setNavigationWrappingAround ( options - > isRollOverDesktops ( ) ) ;
connect ( options , SIGNAL ( rollOverDesktopsChanged ( bool ) ) , vds , SLOT ( setNavigationWrappingAround ( bool ) ) ) ;
vds - > setRootInfo ( rootInfo ) ;
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 ( ) ;
2008-12-18 13:50:57 +00:00
// Extra NETRootInfo instance in Client mode is needed to get the values of the properties
2013-11-18 12:58:35 +00:00
NETRootInfo client_info ( connection ( ) , NET : : ActiveWindow | NET : : CurrentDesktop ) ;
2013-08-28 11:50:52 +00:00
if ( ! qApp - > isSessionRestored ( ) )
2015-05-01 14:55:15 +00:00
m_initialDesktop = client_info . currentDesktop ( ) ;
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
2011-01-30 14:34:42 +00:00
connect ( & reconfigureTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( slotReconfigure ( ) ) ) ;
connect ( & updateToolWindowsTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( 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 ( ) ) ) ;
2007-04-29 17:35:43 +00:00
active_client = NULL ;
2011-01-30 14:34:42 +00:00
rootInfo - > setActiveWindow ( None ) ;
2007-04-29 17:35:43 +00:00
focusToNull ( ) ;
2013-08-28 11:50:52 +00:00
if ( ! qApp - > isSessionRestored ( ) )
2008-12-18 13:50:57 +00:00
+ + block_focus ; // Because it will be set below
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
{
// Begin updates blocker block
StackingUpdatesBlocker blocker ( this ) ;
2007-04-29 17:35:43 +00:00
2013-01-07 13:10:00 +00:00
Xcb : : Tree tree ( rootWindow ( ) ) ;
xcb_window_t * wins = xcb_query_tree_children ( tree . data ( ) ) ;
2012-03-26 15:30:34 +00:00
2013-01-07 13:10:00 +00:00
QVector < Xcb : : WindowAttributes > windowAttributes ( tree - > children_len ) ;
QVector < Xcb : : WindowGeometry > windowGeometries ( tree - > children_len ) ;
2012-03-26 15:30:34 +00:00
// Request the attributes and geometries of all toplevel windows
for ( int i = 0 ; i < tree - > children_len ; i + + ) {
2013-01-07 13:10:00 +00:00
windowAttributes [ i ] = Xcb : : WindowAttributes ( wins [ i ] ) ;
windowGeometries [ i ] = Xcb : : WindowGeometry ( wins [ i ] ) ;
2012-03-26 15:30:34 +00:00
}
// Get the replies
for ( int i = 0 ; i < tree - > children_len ; i + + ) {
2013-01-07 13:10:00 +00:00
Xcb : : WindowAttributes attr ( windowAttributes . at ( i ) ) ;
2012-03-26 15:30:34 +00:00
2013-01-07 13:10:00 +00:00
if ( attr . isNull ( ) ) {
2007-04-29 17:35:43 +00:00
continue ;
2013-01-07 13:10:00 +00:00
}
2012-03-26 15:30:34 +00:00
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 ) {
2013-08-28 12:10:51 +00:00
if ( Application : : wasCrash ( ) ) {
2014-04-10 08:24:42 +00:00
fixPositionAfterCrash ( wins [ i ] , windowGeometries . at ( i ) . data ( ) ) ;
2013-01-07 13:10:00 +00:00
}
2012-03-26 15:30:34 +00:00
// ### This will request the attributes again
2011-01-30 14:34:42 +00:00
createClient ( wins [ i ] , true ) ;
2007-04-29 17:35:43 +00:00
}
2011-01-30 14:34:42 +00:00
}
2012-03-26 15:30:34 +00:00
2008-12-18 13:50:57 +00:00
// Propagate clients, will really happen at the end of the updates blocker block
2011-01-30 14:34:42 +00:00
updateStackingOrder ( true ) ;
2007-04-29 17:35:43 +00:00
2011-09-30 11:22:39 +00:00
saveOldScreenSizes ( ) ;
2007-04-29 17:35:43 +00:00
updateClientArea ( ) ;
2008-12-18 13:50:57 +00:00
// NETWM spec says we have to set it to (0,0) if we don't support it
2012-11-16 07:23:47 +00:00
NETPoint * viewports = new NETPoint [ VirtualDesktopManager : : self ( ) - > count ( ) ] ;
rootInfo - > setDesktopViewport ( VirtualDesktopManager : : self ( ) - > count ( ) , * viewports ) ;
2007-04-29 17:35:43 +00:00
delete [ ] viewports ;
2012-03-27 17:14:53 +00:00
QRect geom ;
2013-04-03 10:19:27 +00:00
for ( int i = 0 ; i < screens - > count ( ) ; i + + ) {
geom | = screens - > geometry ( i ) ;
2012-03-27 17:14:53 +00:00
}
2007-04-29 17:35:43 +00:00
NETSize desktop_geometry ;
desktop_geometry . width = geom . width ( ) ;
desktop_geometry . height = geom . height ( ) ;
2013-11-18 12:57:06 +00:00
rootInfo - > setDesktopGeometry ( desktop_geometry ) ;
2011-01-30 14:34:42 +00:00
setShowingDesktop ( false ) ;
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
} // End updates blocker block
2007-04-29 17:35:43 +00:00
2015-09-14 11:31:41 +00:00
AbstractClient * new_active_client = nullptr ;
2013-08-28 11:50:52 +00:00
if ( ! qApp - > isSessionRestored ( ) ) {
2007-04-29 17:35:43 +00:00
- - block_focus ;
2014-03-20 08:19:53 +00:00
new_active_client = findClient ( Predicate : : WindowMatch , client_info . activeWindow ( ) ) ;
2011-01-30 14:34:42 +00:00
}
if ( new_active_client = = NULL
& & activeClient ( ) = = NULL & & should_get_focus . count ( ) = = 0 ) {
// No client activated in manage()
if ( new_active_client = = NULL )
2012-11-16 07:23:47 +00:00
new_active_client = topClientOnDesktop ( VirtualDesktopManager : : self ( ) - > current ( ) , - 1 ) ;
2011-01-30 14:34:42 +00:00
if ( new_active_client = = NULL & & ! desktops . isEmpty ( ) )
2012-11-16 07:23:47 +00:00
new_active_client = findDesktop ( true , VirtualDesktopManager : : self ( ) - > current ( ) ) ;
2011-01-30 14:34:42 +00:00
}
if ( new_active_client ! = NULL )
activateClient ( new_active_client ) ;
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
2015-03-04 08:21:10 +00:00
if ( auto w = waylandServer ( ) ) {
connect ( w , & WaylandServer : : shellClientAdded , this ,
[ this ] ( ShellClient * c ) {
2016-07-01 14:03:13 +00:00
setupClientConnections ( c ) ;
2015-12-17 14:47:36 +00:00
c - > updateDecoration ( false ) ;
2015-10-01 15:24:03 +00:00
updateClientLayer ( c ) ;
2015-05-21 08:35:03 +00:00
if ( ! c - > isInternal ( ) ) {
2015-05-27 12:09:03 +00:00
QRect area = clientArea ( PlacementArea , Screens : : self ( ) - > current ( ) , c - > desktop ( ) ) ;
2015-10-01 06:44:26 +00:00
bool placementDone = false ;
if ( c - > isInitialPositionSet ( ) ) {
placementDone = true ;
}
if ( c - > isFullScreen ( ) ) {
placementDone = true ;
}
if ( ! placementDone ) {
2016-08-30 11:16:52 +00:00
c - > placeIn ( area ) ;
2015-06-09 17:10:56 +00:00
}
2015-09-18 11:44:54 +00:00
m_allClients . append ( c ) ;
2015-05-21 08:35:03 +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
}
2015-03-04 08:21:10 +00:00
x_stacking_dirty = true ;
updateStackingOrder ( true ) ;
2015-06-08 19:29:07 +00:00
updateClientArea ( ) ;
2015-06-11 01:22:50 +00:00
if ( c - > wantsInput ( ) ) {
activateClient ( c ) ;
}
2016-06-14 11:46:28 +00:00
connect ( c , & ShellClient : : windowShown , this ,
[ this , c ] {
updateClientLayer ( c ) ;
2016-08-08 12:55:26 +00:00
// TODO: when else should we send the client through placement?
if ( c - > hasTransientPlacementHint ( ) ) {
QRect area = clientArea ( PlacementArea , Screens : : self ( ) - > current ( ) , c - > desktop ( ) ) ;
2016-08-30 11:16:52 +00:00
c - > placeIn ( area ) ;
2016-08-08 12:55:26 +00:00
}
2016-06-14 11:46:28 +00:00
x_stacking_dirty = true ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
if ( c - > wantsInput ( ) ) {
activateClient ( c ) ;
}
}
) ;
2016-08-31 14:08:25 +00:00
connect ( c , & ShellClient : : windowHidden , this ,
[ this ] {
x_stacking_dirty = true ;
updateStackingOrder ( true ) ;
updateClientArea ( ) ;
}
) ;
2015-03-04 08:21:10 +00:00
}
) ;
connect ( w , & WaylandServer : : shellClientRemoved , this ,
2015-04-30 08:51:58 +00:00
[ this ] ( ShellClient * c ) {
2015-09-18 11:44:54 +00:00
m_allClients . removeAll ( c ) ;
2016-02-18 10:18:50 +00:00
if ( c = = delayfocus_client ) {
cancelDelayFocus ( ) ;
}
2015-04-30 11:48:59 +00:00
clientHidden ( c ) ;
2015-04-30 08:51:58 +00:00
emit clientRemoved ( c ) ;
2015-03-04 08:21:10 +00:00
x_stacking_dirty = true ;
updateStackingOrder ( true ) ;
2015-06-08 19:29:07 +00:00
updateClientArea ( ) ;
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
Workspace : : ~ Workspace ( )
2011-01-30 14:34:42 +00:00
{
blockStackingUpdates ( true ) ;
2008-12-18 13:50:57 +00:00
// TODO: grabXServer();
// Use stacking_order, so that kwin --replace keeps stacking order
2013-08-11 17:02:53 +00:00
const ToplevelList stack = stacking_order ;
// "mutex" the stackingorder, since anything trying to access it from now on will find
// many dangeling pointers and crash
stacking_order . clear ( ) ;
for ( ToplevelList : : const_iterator it = stack . constBegin ( ) , end = stack . constEnd ( ) ; it ! = end ; + + it ) {
Client * c = qobject_cast < Client * > ( const_cast < Toplevel * > ( * it ) ) ;
2012-04-08 08:07:35 +00:00
if ( ! c ) {
continue ;
}
2008-12-18 13:50:57 +00:00
// Only release the window
2012-04-08 08:07:35 +00:00
c - > releaseWindow ( true ) ;
2007-04-30 09:46:31 +00:00
// No removeClient() is called, it does more than just removing.
// However, remove from some lists to e.g. prevent performTransiencyCheck()
// from crashing.
2012-04-08 08:07:35 +00:00
clients . removeAll ( c ) ;
2015-09-18 11:44:54 +00:00
m_allClients . removeAll ( c ) ;
2012-04-08 08:07:35 +00:00
desktops . removeAll ( c ) ;
2011-01-30 14:34:42 +00:00
}
2016-05-09 14:01:49 +00:00
Client : : cleanupX11 ( ) ;
2011-11-01 20:20:31 +00:00
for ( UnmanagedList : : iterator it = unmanaged . begin ( ) , end = unmanaged . end ( ) ; it ! = end ; + + it )
2014-04-07 14:23:17 +00:00
( * it ) - > release ( ReleaseReason : : KWinShutsDown ) ;
2013-09-10 07:33:07 +00:00
xcb_delete_property ( connection ( ) , rootWindow ( ) , atoms - > kwin_running ) ;
2007-04-29 17:35:43 +00:00
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
2013-04-29 10:17:42 +00:00
RootInfo : : destroy ( ) ;
2007-04-29 17:35:43 +00:00
delete startup ;
2012-11-22 12:41:50 +00:00
delete Placement : : self ( ) ;
2007-11-01 19:24:35 +00:00
delete client_keys_dialog ;
2011-01-30 14:34:42 +00:00
foreach ( SessionInfo * s , session )
delete s ;
2008-12-18 13:50:57 +00:00
// TODO: ungrabXServer();
2016-06-01 08:21:19 +00:00
if ( kwinApp ( ) - > operationMode ( ) = = Application : : OperationModeX11 ) {
XRenderUtils : : cleanup ( ) ;
}
2012-12-21 14:11:31 +00:00
Xcb : : Extensions : : destroy ( ) ;
2007-04-29 17:35:43 +00:00
_self = 0 ;
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 , & Toplevel : : needsRepaint , m_compositor , & Compositor : : scheduleRepaint ) ;
connect ( c , & AbstractClient : : desktopPresenceChanged , this , & Workspace : : desktopPresenceChanged ) ;
}
2013-04-30 13:41:59 +00:00
Client * Workspace : : createClient ( xcb_window_t w , bool is_mapped )
2011-01-30 14:34:42 +00:00
{
StackingUpdatesBlocker blocker ( this ) ;
2013-05-08 11:39:06 +00:00
Client * c = new Client ( ) ;
2016-07-01 14:03:13 +00:00
setupClientConnections ( c ) ;
2012-08-23 11:42:59 +00:00
connect ( c , SIGNAL ( blockingCompositingChanged ( KWin : : Client * ) ) , m_compositor , SLOT ( updateCompositeBlocking ( KWin : : Client * ) ) ) ;
2013-01-31 16:25:03 +00:00
connect ( c , SIGNAL ( clientFullScreenSet ( KWin : : Client * , bool , bool ) ) , ScreenEdges : : self ( ) , SIGNAL ( checkBlocking ( ) ) ) ;
2012-10-15 16:57:21 +00:00
if ( ! c - > manage ( w , is_mapped ) ) {
2013-04-26 07:47:45 +00:00
Client : : deleteClient ( c ) ;
2012-10-15 16:57:21 +00:00
return NULL ;
}
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
{
2012-08-16 19:19:54 +00:00
if ( m_compositor & & m_compositor - > checkForOverlayWindow ( w ) )
2007-04-29 17:35:43 +00:00
return NULL ;
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 ) ;
2007-04-29 17:35:43 +00:00
return NULL ;
}
2012-08-23 11:42:59 +00:00
connect ( c , SIGNAL ( needsRepaint ( ) ) , m_compositor , SLOT ( scheduleRepaint ( ) ) ) ;
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 ;
}
2013-04-26 07:47:45 +00:00
void Workspace : : addClient ( Client * 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
if ( grp ! = NULL )
grp - > gotLeader ( c ) ;
if ( c - > isDesktop ( ) ) {
desktops . append ( c ) ;
if ( active_client = = NULL & & should_get_focus . isEmpty ( ) & & c - > isOnCurrentDesktop ( ) )
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
clients . append ( c ) ;
2015-09-18 11:44:54 +00:00
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
2008-08-24 10:35:45 +00:00
x_stacking_dirty = true ;
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
2011-01-30 14:34:42 +00:00
if ( activeClient ( ) = = NULL & & 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 ) ;
2007-04-30 09:47:59 +00:00
checkNonExistentClients ( ) ;
2011-06-30 11:02:30 +00:00
# ifdef KWIN_BUILD_TABBOX
2013-04-04 07:41:18 +00:00
if ( TabBox : : TabBox : : self ( ) - > isDisplayed ( ) )
TabBox : : TabBox : : self ( ) - > reset ( true ) ;
2011-06-30 11:02:30 +00:00
# endif
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
{
unmanaged . append ( c ) ;
2008-08-24 10:35:45 +00:00
x_stacking_dirty = true ;
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
2007-04-29 17:35:43 +00:00
*/
2013-04-26 07:47:45 +00:00
void Workspace : : removeClient ( Client * c )
2011-01-30 14:34:42 +00:00
{
2010-09-21 14:31:40 +00:00
emit clientRemoved ( 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
2012-12-29 14:36:55 +00:00
c - > untab ( QRect ( ) , true ) ;
2012-01-12 06:42:55 +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
2011-06-30 11:02:30 +00:00
# ifdef KWIN_BUILD_TABBOX
2013-04-04 07:41:18 +00:00
TabBox : : TabBox * tabBox = TabBox : : TabBox : : self ( ) ;
if ( tabBox - > isDisplayed ( ) & & tabBox - > currentClient ( ) = = c )
tabBox - > nextPrev ( true ) ;
2011-06-30 11:02:30 +00:00
# endif
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
Q_ASSERT ( clients . contains ( c ) | | desktops . 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 ) ;
2011-01-30 14:34:42 +00:00
desktops . removeAll ( c ) ;
2008-08-24 10:35:45 +00:00
x_stacking_dirty = true ;
2011-01-30 14:34:42 +00:00
attention_chain . removeAll ( c ) ;
Group * group = findGroup ( c - > window ( ) ) ;
if ( group ! = NULL )
2007-04-29 17:35:43 +00:00
group - > lostLeader ( ) ;
2011-01-30 14:34:42 +00:00
if ( c = = most_recently_raised )
2007-04-29 17:35:43 +00:00
most_recently_raised = 0 ;
2011-01-30 14:34:42 +00:00
should_get_focus . removeAll ( c ) ;
Q_ASSERT ( c ! = active_client ) ;
if ( c = = last_active_client )
2007-04-29 17:35:43 +00:00
last_active_client = 0 ;
2011-01-30 14:34:42 +00:00
if ( c = = delayfocus_client )
2007-04-29 17:35:43 +00:00
cancelDelayFocus ( ) ;
2011-01-30 14:34:42 +00:00
updateStackingOrder ( true ) ;
2007-04-29 17:35:43 +00:00
2011-06-30 11:02:30 +00:00
# ifdef KWIN_BUILD_TABBOX
2013-04-04 07:41:18 +00:00
if ( tabBox - > isDisplayed ( ) )
tabBox - > reset ( true ) ;
2011-06-30 11:02:30 +00:00
# endif
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-04-26 07:47:45 +00:00
void Workspace : : removeUnmanaged ( Unmanaged * c )
2011-01-30 14:34:42 +00:00
{
assert ( unmanaged . contains ( c ) ) ;
unmanaged . removeAll ( c ) ;
2013-07-01 06:37:59 +00:00
emit unmanagedRemoved ( c ) ;
2008-08-24 10:35:45 +00:00
x_stacking_dirty = true ;
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
{
assert ( ! deleted . contains ( c ) ) ;
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 ) ;
}
2008-08-24 10:35:45 +00:00
x_stacking_dirty = true ;
2012-08-23 11:42:59 +00:00
connect ( c , SIGNAL ( needsRepaint ( ) ) , m_compositor , SLOT ( scheduleRepaint ( ) ) ) ;
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
{
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 ) ;
2008-08-24 10:35:45 +00:00
x_stacking_dirty = true ;
2013-06-23 22:13:08 +00:00
if ( c - > wasClient ( ) & & m_compositor ) {
m_compositor - > updateCompositeBlocking ( ) ;
}
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 : : 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 ( ) ) {
2011-09-25 15:52:05 +00:00
for ( ClientList : : ConstIterator it = clients . constBegin ( ) ; it ! = clients . constEnd ( ) ; + + it )
2012-01-12 06:42:55 +00:00
if ( ! ( * it ) - > tabGroup ( ) | | ( * it ) - > tabGroup ( ) - > current ( ) = = * it )
2011-09-25 15:52:05 +00:00
( * it ) - > hideClient ( false ) ;
2007-04-29 17:35:43 +00:00
return ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
const Group * group = NULL ;
2015-03-12 11:08:54 +00:00
const Client * client = dynamic_cast < 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
2011-01-30 14:34:42 +00:00
while ( client ! = NULL ) {
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 ;
}
2015-09-11 09:37:40 +00:00
client = dynamic_cast < const 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?
2007-04-29 17:35:43 +00:00
ClientList to_show , to_hide ;
2012-04-08 08:07:35 +00:00
for ( ToplevelList : : ConstIterator it = stacking_order . constBegin ( ) ;
2011-01-30 14:34:42 +00:00
it ! = stacking_order . constEnd ( ) ;
+ + it ) {
2012-04-08 08:07:35 +00:00
Client * c = qobject_cast < Client * > ( * it ) ;
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 ( ) ) {
if ( c - > group ( ) - > members ( ) . count ( ) = = 1 ) // Has its own group, keep always visible
2007-04-29 17:35:43 +00:00
show = true ;
2012-04-08 08:07:35 +00:00
else if ( client ! = NULL & & 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 {
2012-04-08 08:07:35 +00:00
if ( group ! = NULL & & c - > group ( ) = = group )
2007-04-29 17:35:43 +00:00
show = true ;
2012-04-08 08:07:35 +00:00
else if ( client ! = NULL & & 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 ) {
for ( ClientList : : ConstIterator it = to_hide . constBegin ( ) ;
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
/**
* This D - Bus call is used by the compositing kcm . Since the reconfigure ( )
* D - Bus call delays the actual reconfiguring , it is not possible to immediately
* call compositingActive ( ) . Therefore the kcm will instead call this to ensure
* the reconfiguring has already happened .
*/
2008-12-08 05:08:31 +00:00
bool Workspace : : waitForCompositingSetup ( )
2011-01-30 14:34:42 +00:00
{
if ( reconfigureTimer . isActive ( ) ) {
2009-04-28 16:20:26 +00:00
reconfigureTimer . stop ( ) ;
slotReconfigure ( ) ;
2008-12-08 05:08:31 +00:00
}
2011-08-21 19:50:23 +00:00
if ( m_compositor ) {
2012-08-17 06:18:36 +00:00
return m_compositor - > isActive ( ) ;
2011-08-21 19:50:23 +00:00
}
return false ;
2011-01-30 14:34:42 +00:00
}
2008-12-08 05:08:31 +00:00
2008-12-18 13:50:57 +00:00
/**
* Reread settings
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 ( ) ;
2011-01-30 14:34:42 +00:00
for ( ClientList : : Iterator it = clients . begin ( ) ;
it ! = clients . end ( ) ;
+ + it ) {
( * it ) - > setupWindowRules ( true ) ;
2007-04-29 17:35:43 +00:00
( * it ) - > applyWindowRules ( ) ;
2013-04-26 12:40:35 +00:00
RuleBook : : self ( ) - > discardUsed ( * it , 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
2011-01-30 14:34:42 +00:00
for ( ClientList : : Iterator it = clients . begin ( ) ;
it ! = clients . end ( ) ;
+ + 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
2008-12-18 13:50:57 +00:00
/**
* During virt . desktop switching , desktop areas covered by windows that are
* going to be hidden are first obscured by new windows with no background
* ( i . e . transparent ) placed right below the windows . These invisible windows
* are removed after the switch is complete .
* Reduces desktop ( wallpaper ) repaints during desktop switching
*/
2007-04-29 17:35:43 +00:00
class ObscuringWindows
2011-01-30 14:34:42 +00:00
{
public :
~ ObscuringWindows ( ) ;
void create ( Client * c ) ;
private :
2014-04-25 12:24:52 +00:00
QList < xcb_window_t > obscuring_windows ;
static QList < xcb_window_t > * cached ;
2011-01-30 14:34:42 +00:00
static unsigned int max_cache_size ;
} ;
2007-04-29 17:35:43 +00:00
2014-04-25 12:24:52 +00:00
QList < xcb_window_t > * ObscuringWindows : : cached = nullptr ;
2007-04-29 17:35:43 +00:00
unsigned int ObscuringWindows : : max_cache_size = 0 ;
2011-01-30 14:34:42 +00:00
void ObscuringWindows : : create ( Client * c )
{
2014-04-25 12:24:52 +00:00
if ( ! cached )
cached = new QList < xcb_window_t > ;
Xcb : : Window obs_win ( XCB_WINDOW_NONE , false ) ;
2011-01-30 14:34:42 +00:00
if ( cached - > count ( ) > 0 ) {
2014-04-25 12:24:52 +00:00
obs_win . reset ( cached - > first ( ) , false ) ;
cached - > removeAll ( obs_win ) ;
obs_win . setGeometry ( c - > geometry ( ) ) ;
2011-01-30 14:34:42 +00:00
} else {
2014-04-25 12:24:52 +00:00
uint32_t values [ ] = { XCB_PIXMAP_NONE , true } ;
obs_win . create ( c - > geometry ( ) , XCB_WINDOW_CLASS_INPUT_OUTPUT , XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT , values ) ;
2011-01-30 14:34:42 +00:00
}
2014-04-25 12:24:52 +00:00
uint32_t values [ ] = { c - > frameId ( ) , XCB_STACK_MODE_BELOW } ;
xcb_configure_window ( connection ( ) , obs_win , XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE , values ) ;
obs_win . map ( ) ;
2011-01-30 14:34:42 +00:00
obscuring_windows . append ( obs_win ) ;
}
2007-04-29 17:35:43 +00:00
ObscuringWindows : : ~ ObscuringWindows ( )
2011-01-30 14:34:42 +00:00
{
max_cache_size = qMax ( int ( max_cache_size ) , obscuring_windows . count ( ) + 4 ) - 1 ;
2014-04-25 12:24:52 +00:00
for ( auto it = obscuring_windows . constBegin ( ) ;
2011-01-30 14:34:42 +00:00
it ! = obscuring_windows . constEnd ( ) ;
+ + it ) {
2014-04-25 12:24:52 +00:00
xcb_unmap_window ( connection ( ) , * it ) ;
2011-01-30 14:34:42 +00:00
if ( cached - > count ( ) < int ( max_cache_size ) )
cached - > prepend ( * it ) ;
2007-04-29 17:35:43 +00:00
else
2014-04-25 12:24:52 +00:00
xcb_destroy_window ( connection ( ) , * it ) ;
2007-04-29 17:35:43 +00:00
}
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 ) ;
2012-11-16 07:23:47 +00:00
updateClientVisibilityOnDesktopChange ( oldDesktop , newDesktop ) ;
// 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
2012-11-16 07:23:47 +00:00
void Workspace : : updateClientVisibilityOnDesktopChange ( uint oldDesktop , uint newDesktop )
{
ObscuringWindows obs_wins ;
for ( ToplevelList : : ConstIterator it = stacking_order . constBegin ( ) ;
it ! = stacking_order . constEnd ( ) ;
+ + it ) {
Client * c = qobject_cast < Client * > ( * it ) ;
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 ( ) ) {
if ( c - > isShown ( true ) & & c - > isOnDesktop ( oldDesktop ) & & ! compositing ( ) )
obs_wins . create ( c ) ;
( 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
2013-04-29 10:17:42 +00:00
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 ) {
Client * c = qobject_cast < Client * > ( 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 )
{
2015-03-12 11:08:54 +00:00
AbstractClient * c = NULL ;
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
2011-01-30 14:34:42 +00:00
if ( c = = NULL & & ! desktops . isEmpty ( ) )
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 )
2013-04-26 07:47:45 +00:00
setActiveClient ( NULL ) ;
2007-04-29 17:35:43 +00:00
2011-01-30 14:34:42 +00:00
if ( c )
requestFocus ( c ) ;
else if ( ! desktops . isEmpty ( ) )
2012-11-16 07:23:47 +00:00
requestFocus ( findDesktop ( true , desktop ) ) ;
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
{
if ( movingClient ! = NULL & & 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 ( ) ) {
ToplevelList : : const_iterator it = stackingOrder ( ) . constEnd ( ) ;
while ( it ! = stackingOrder ( ) . constBegin ( ) ) {
Client * client = qobject_cast < Client * > ( * ( - - it ) ) ;
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
2013-02-26 07:45:44 +00:00
if ( client - > geometry ( ) . contains ( Cursor : : 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
*/
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
2013-04-04 14:14:12 +00:00
ObscuringWindows obs_wins ;
2010-05-11 20:30:20 +00:00
2013-04-04 14:14:12 +00:00
const QString & old_activity = Activities : : self ( ) - > previous ( ) ;
2010-05-11 20:30:20 +00:00
2013-04-04 14:14:12 +00:00
for ( ToplevelList : : ConstIterator it = stacking_order . constBegin ( ) ;
it ! = stacking_order . constEnd ( ) ;
+ + it ) {
Client * c = qobject_cast < Client * > ( * it ) ;
if ( ! c ) {
continue ;
}
if ( ! c - > isOnActivity ( new_activity ) & & c ! = movingClient & & c - > isOnCurrentDesktop ( ) ) {
if ( c - > isShown ( true ) & & c - > isOnActivity ( old_activity ) & & ! compositing ( ) )
obs_wins . create ( c ) ;
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 ) {
Client * c = qobject_cast < Client * > ( stacking_order . at ( i ) ) ;
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 ;
2015-03-12 11:08:54 +00:00
AbstractClient * c = 0 ;
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 ;
2011-01-30 14:34:42 +00:00
if ( c = = NULL & & ! desktops . isEmpty ( ) )
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 )
2013-04-26 07:47:45 +00:00
setActiveClient ( NULL ) ;
2010-05-11 20:30:20 +00:00
2011-01-30 14:34:42 +00:00
if ( c )
requestFocus ( c ) ;
else if ( ! desktops . isEmpty ( ) )
2012-11-16 07:23:47 +00:00
requestFocus ( findDesktop ( true , VirtualDesktopManager : : self ( ) - > current ( ) ) ) ;
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 : : moveClientsFromRemovedDesktops ( )
2011-01-30 14:34:42 +00:00
{
2012-11-16 07:23:47 +00:00
for ( ClientList : : ConstIterator it = clients . constBegin ( ) ; it ! = clients . constEnd ( ) ; + + it ) {
if ( ! ( * it ) - > isOnAllDesktops ( ) & & ( * it ) - > desktop ( ) > static_cast < int > ( VirtualDesktopManager : : self ( ) - > count ( ) ) )
sendClientToDesktop ( * it , VirtualDesktopManager : : self ( ) - > count ( ) , true ) ;
}
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 : : 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 .
2007-04-29 17:35:43 +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
2015-03-06 16:31:47 +00:00
if ( Client * client = dynamic_cast < Client * > ( c ) ) {
// TODO: adjust transients for non-X11
2015-09-14 07:27:48 +00:00
auto transients_stacking_order = ensureStackingOrder ( client - > transients ( ) ) ;
for ( auto it = transients_stacking_order . constBegin ( ) ;
2015-03-06 16:31:47 +00:00
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
*
*/
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
2013-04-30 13:41:59 +00:00
void Workspace : : sendPingToWindow ( xcb_window_t window , xcb_timestamp_t timestamp )
2011-01-30 14:34:42 +00:00
{
2013-04-29 10:17:42 +00:00
rootInfo ( ) - > sendPing ( window , timestamp ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
/**
* Delayed focus functions
*/
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 ) ;
connect ( delayFocusTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( delayFocus ( ) ) ) ;
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 ;
delayFocusTimer = 0 ;
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
{
return startup - > checkStartup ( w , id , data ) = = KStartupInfo : : Match ;
}
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
2007-04-29 17:35:43 +00:00
*/
void Workspace : : focusToNull ( )
2011-01-30 14:34:42 +00:00
{
2013-04-30 11:06:46 +00:00
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 ;
2013-04-29 10:17:42 +00:00
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 ( ) ) {
if ( c - > isDock ( ) ) {
c - > updateLayer ( ) ;
} else if ( c - > isDesktop ( ) & & c - > isShown ( true ) ) {
c - > updateLayer ( ) ;
lowerClient ( c ) ;
if ( ! topDesk )
topDesk = c ;
2015-06-09 21:28:48 +00:00
if ( Client * client = qobject_cast < Client * > ( c ) ) {
foreach ( Client * cm , client - > group ( ) - > members ( ) ) {
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
if ( showing_desktop & & topDesk )
requestFocus ( topDesk ) ;
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 ;
2008-12-18 13:50:57 +00:00
// Update also Alt+LMB actions etc.
2011-01-30 14:34:42 +00:00
for ( ClientList : : ConstIterator it = clients . constBegin ( ) ;
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 "
" The following information should be used when requesting support on e.g. http://forum.kde.org. \n "
" 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 "
" like http://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 ;
case Application : : OperationModeWaylandAndX11 :
support . append ( QStringLiteral ( " Wayland and X11 " ) ) ;
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 ) ;
# endif
support . append ( QStringLiteral ( " HAVE_INPUT: " ) ) ;
# if HAVE_INPUT
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 ) ;
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 " ) ) ;
2015-03-24 07:54:03 +00:00
support . append ( QStringLiteral ( " X11 \n " ) ) ;
support . append ( QStringLiteral ( " === \n " ) ) ;
auto x11setup = xcb_get_setup ( connection ( ) ) ;
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 " ) ) ;
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 " ) ) ;
}
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 ) ) ;
support . append ( QStringLiteral ( " --------- \n " ) . arg ( i ) ) ;
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 ( ) ) ) ;
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 " ) ) ;
2013-09-24 09:28:38 +00:00
support . append ( QStringLiteral ( " Painting blocks for vertical retrace: " ) ) ;
2013-08-18 11:04:05 +00:00
if ( m_compositor - > scene ( ) - > blocksForRetrace ( ) )
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 " ) ) ;
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
}
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 ;
}
2011-08-21 19:50:23 +00:00
void Workspace : : slotToggleCompositing ( )
{
if ( m_compositor ) {
m_compositor - > slotToggleCompositing ( ) ;
}
}
2014-03-20 08:19:53 +00:00
Client * Workspace : : findClient ( std : : function < bool ( const Client * ) > func ) const
{
if ( Client * ret = Toplevel : : findInList ( clients , func ) ) {
return ret ;
}
if ( Client * ret = Toplevel : : findInList ( desktops , func ) ) {
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 ;
}
if ( Client * ret = Toplevel : : findInList ( desktops , func ) ) {
return ret ;
}
2016-05-09 12:48:10 +00:00
if ( waylandServer ( ) ) {
if ( AbstractClient * ret = Toplevel : : findInList ( waylandServer ( ) - > internalClients ( ) , func ) ) {
return ret ;
}
}
2015-12-04 08:53:18 +00:00
return nullptr ;
}
2014-03-20 06:52:18 +00:00
Unmanaged * Workspace : : findUnmanaged ( std : : function < bool ( const Unmanaged * ) > func ) const
{
return Toplevel : : findInList ( unmanaged , func ) ;
}
Unmanaged * Workspace : : findUnmanaged ( xcb_window_t w ) const
{
return findUnmanaged ( [ w ] ( const Unmanaged * u ) {
return u - > window ( ) = = w ;
} ) ;
}
2014-03-20 08:19:53 +00:00
Client * Workspace : : findClient ( Predicate predicate , xcb_window_t w ) const
{
switch ( predicate ) {
case Predicate : : WindowMatch :
return findClient ( [ w ] ( const Client * c ) {
return c - > window ( ) = = w ;
} ) ;
case Predicate : : WrapperIdMatch :
return findClient ( [ w ] ( const Client * c ) {
return c - > wrapperId ( ) = = w ;
} ) ;
case Predicate : : FrameIdMatch :
return findClient ( [ w ] ( const Client * c ) {
return c - > frameId ( ) = = w ;
} ) ;
case Predicate : : InputIdMatch :
return findClient ( [ w ] ( const Client * c ) {
return c - > inputId ( ) = = w ;
} ) ;
}
return nullptr ;
}
2015-02-09 15:07:30 +00:00
Toplevel * Workspace : : findToplevel ( std : : function < bool ( const Toplevel * ) > func ) const
{
if ( Client * ret = Toplevel : : findInList ( clients , func ) ) {
return ret ;
}
if ( Client * ret = Toplevel : : findInList ( desktops , func ) ) {
return ret ;
}
if ( Unmanaged * ret = Toplevel : : findInList ( unmanaged , func ) ) {
return ret ;
}
return nullptr ;
}
2016-08-30 13:47:59 +00:00
Toplevel * Workspace : : findToplevel ( QWindow * w ) const
{
if ( ! w ) {
return nullptr ;
}
if ( waylandServer ( ) ) {
if ( auto c = waylandServer ( ) - > findClient ( w ) ) {
return c ;
}
}
return findUnmanaged ( w - > winId ( ) ) ;
}
2015-03-05 11:41:15 +00:00
bool Workspace : : hasClient ( const AbstractClient * c )
{
if ( auto cc = dynamic_cast < const Client * > ( c ) ) {
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 ) ;
std : : for_each ( desktops . constBegin ( ) , desktops . constEnd ( ) , func ) ;
}
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 ( ) ) ;
} else {
return waylandServer ( ) - > findClient ( w ) ;
}
}
2007-04-29 17:35:43 +00:00
} // namespace