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 <kdecorationfactory.h>
# 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
# ifdef KWIN_BUILD_KAPPMENU
# include "appmenu.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"
2013-04-08 10:31:16 +00:00
# include "decorations.h"
2013-04-25 14:08:39 +00:00
# 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"
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
# ifdef KWIN_BUILD_SCREENEDGES
# include "screenedge.h"
# endif
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"
2014-03-13 15:21:04 +00:00
# if HAVE_WAYLAND
2013-06-17 08:28:31 +00:00
# include "wayland_backend.h"
# endif
2013-04-25 14:08:39 +00:00
# include "xcbutils.h"
2013-08-28 12:10:51 +00:00
# include "main.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>
# include <KWindowInfo>
# include <KWindowSystem>
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 ;
if ( Client * c = Workspace : : self ( ) - > activeClient ( ) ) {
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
2011-01-30 14:34:42 +00:00
Workspace : : Workspace ( bool restore )
: 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 )
, 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 )
, block_showing_desktop ( 0 )
, 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 )
, forced_global_mouse_grab ( false )
{
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 ) ;
2012-11-09 12:44:50 +00:00
# ifdef KWIN_BUILD_KAPPMENU
2013-03-15 15:49:20 +00:00
ApplicationMenu : : create ( this ) ;
2012-11-09 12:44:50 +00:00
# endif
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-06-26 12:32:03 +00:00
InputRedirection : : create ( this ) ;
2013-06-17 08:28:31 +00:00
// start the Wayland Backend - will only be created if WAYLAND_DISPLAY is present
2014-03-13 15:21:04 +00:00
# if HAVE_WAYLAND
2013-06-17 08:28:31 +00:00
Wayland : : WaylandBackend : : create ( this ) ;
2013-07-01 06:37:59 +00:00
if ( kwinApp ( ) - > operationMode ( ) ! = Application : : OperationModeX11 ) {
connect ( this , SIGNAL ( stackingOrderChanged ( ) ) , input ( ) , SLOT ( updatePointerWindow ( ) ) ) ;
}
2013-06-17 08:28:31 +00:00
# endif
2013-02-19 10:25:46 +00:00
// start the cursor support
Cursor : : create ( this ) ;
2013-04-04 14:14:12 +00:00
# ifdef KWIN_BUILD_ACTIVITIES
Activities * activities = Activities : : create ( this ) ;
connect ( activities , SIGNAL ( currentChanged ( QString ) ) , SLOT ( updateCurrentActivity ( QString ) ) ) ;
# 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
// get screen support
Screens * screens = Screens : : create ( this ) ;
connect ( screens , SIGNAL ( changed ( ) ) , SLOT ( desktopResized ( ) ) ) ;
2012-04-12 17:42:49 +00:00
options - > loadConfig ( ) ;
options - > loadCompositingConfig ( false ) ;
2013-04-08 10:31:16 +00:00
DecorationPlugin : : create ( this ) ;
2013-04-30 12:55:06 +00:00
ColorMapper * colormaps = new ColorMapper ( this ) ;
connect ( this , SIGNAL ( clientActivated ( KWin : : Client * ) ) , colormaps , SLOT ( update ( ) ) ) ;
2007-04-29 17:35:43 +00:00
delayFocusTimer = 0 ;
2011-01-30 14:34:42 +00:00
if ( restore )
2008-12-18 13:50:57 +00:00
loadSessionInfo ( ) ;
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
2013-08-19 08:52:22 +00:00
Xcb : : selectInput ( rootWindow ( ) ,
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
) ;
2007-04-29 17:35:43 +00:00
2013-01-25 09:15:00 +00:00
# ifdef KWIN_BUILD_SCREENEDGES
ScreenEdges : : create ( this ) ;
# endif
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
XRenderUtils : : init ( connection ( ) , rootWindow ( ) ) ;
2013-04-05 07:41:25 +00:00
m_compositor = Compositor : : create ( this ) ;
2012-08-23 11:42:59 +00:00
connect ( this , SIGNAL ( currentDesktopChanged ( int , KWin : : Client * ) ) , m_compositor , SLOT ( addRepaintFull ( ) ) ) ;
2013-08-23 12:50:39 +00:00
connect ( m_compositor , & Compositor : : compositingToggled , decorationPlugin ( ) , & DecorationPlugin : : compositingToggled ) ;
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
2013-09-04 14:10:36 +00:00
KSharedConfigPtr config = KSharedConfig : : openConfig ( ) ;
2013-04-03 10:19:27 +00:00
Screens * screens = Screens : : self ( ) ;
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 ( ) ) ) ;
2011-07-07 16:29:11 +00:00
# ifdef KWIN_BUILD_SCREENEDGES
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 ( ) ) ) ;
2013-01-31 16:25:03 +00:00
connect ( this , SIGNAL ( clientActivated ( KWin : : Client * ) ) , screenEdges , SIGNAL ( checkBlocking ( ) ) ) ;
2011-07-07 16:29:11 +00:00
# endif
2007-04-29 17:35:43 +00:00
2012-11-20 16:26:50 +00:00
FocusChain * focusChain = FocusChain : : create ( this ) ;
connect ( this , SIGNAL ( clientRemoved ( KWin : : Client * ) ) , focusChain , SLOT ( remove ( KWin : : Client * ) ) ) ;
connect ( this , SIGNAL ( clientActivated ( KWin : : Client * ) ) , focusChain , SLOT ( setActiveClient ( KWin : : Client * ) ) ) ;
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 ) ;
2007-04-29 17:35:43 +00:00
int initial_desktop ;
2013-08-28 11:50:52 +00:00
if ( ! qApp - > isSessionRestored ( ) )
2007-04-29 17:35:43 +00:00
initial_desktop = client_info . currentDesktop ( ) ;
2011-01-30 14:34:42 +00:00
else {
2013-08-28 11:50:52 +00:00
# if KWIN_QT5_PORTING
2011-01-30 14:34:42 +00:00
KConfigGroup group ( kapp - > sessionConfig ( ) , " Session " ) ;
initial_desktop = group . readEntry ( " desktop " , 1 ) ;
2013-08-28 11:50:52 +00:00
# else
initial_desktop = 1 ;
# endif
2011-01-30 14:34:42 +00:00
}
2012-11-16 07:23:47 +00:00
if ( ! VirtualDesktopManager : : self ( ) - > setCurrent ( initial_desktop ) )
VirtualDesktopManager : : self ( ) - > setCurrent ( 1 ) ;
2012-02-26 10:38:16 +00:00
# ifdef KWIN_BUILD_ACTIVITIES
2013-04-04 14:14:12 +00:00
Activities : : self ( ) - > update ( false , true ) ;
2012-02-26 10:38:16 +00:00
# endif
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 ( ) ) {
2013-01-07 13:10:00 +00:00
fixPositionAfterCrash ( wins [ i ] , windowGeometries [ i ] . data ( ) ) ;
}
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
Client * new_active_client = NULL ;
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
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
{
2011-08-21 19:50:23 +00:00
delete m_compositor ;
2012-08-27 17:45:01 +00:00
m_compositor = NULL ;
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 ) ;
desktops . removeAll ( c ) ;
2011-01-30 14:34:42 +00:00
}
2011-11-01 20:20:31 +00:00
for ( UnmanagedList : : iterator it = unmanaged . begin ( ) , end = unmanaged . end ( ) ; it ! = end ; + + it )
2012-04-22 07:27:53 +00:00
( * it ) - > release ( true ) ;
2013-09-10 07:33:07 +00:00
xcb_delete_property ( connection ( ) , rootWindow ( ) , atoms - > kwin_running ) ;
2007-04-29 17:35:43 +00:00
2013-04-26 12:40:35 +00:00
delete RuleBook : : self ( ) ;
2013-09-04 14:10:36 +00:00
KSharedConfig : : openConfig ( ) - > 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();
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
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 ( ) ;
2012-08-23 11:42:59 +00:00
connect ( c , SIGNAL ( needsRepaint ( ) ) , m_compositor , SLOT ( scheduleRepaint ( ) ) ) ;
connect ( c , SIGNAL ( activeChanged ( ) ) , m_compositor , SLOT ( checkUnredirect ( ) ) ) ;
connect ( c , SIGNAL ( fullScreenChanged ( ) ) , m_compositor , SLOT ( checkUnredirect ( ) ) ) ;
connect ( c , SIGNAL ( geometryChanged ( ) ) , m_compositor , SLOT ( checkUnredirect ( ) ) ) ;
connect ( c , SIGNAL ( geometryShapeChanged ( KWin : : Toplevel * , QRect ) ) , m_compositor , SLOT ( checkUnredirect ( ) ) ) ;
connect ( c , SIGNAL ( blockingCompositingChanged ( KWin : : Client * ) ) , m_compositor , SLOT ( updateCompositeBlocking ( KWin : : Client * ) ) ) ;
2013-01-31 16:25:03 +00:00
# ifdef KWIN_BUILD_SCREENEDGES
connect ( c , SIGNAL ( clientFullScreenSet ( KWin : : Client * , bool , bool ) ) , ScreenEdges : : self ( ) , SIGNAL ( checkBlocking ( ) ) ) ;
# endif
2013-11-17 20:45:21 +00:00
connect ( c , SIGNAL ( desktopPresenceChanged ( KWin : : Client * , int ) ) , SIGNAL ( desktopPresenceChanged ( KWin : : Client * , int ) ) , Qt : : QueuedConnection ) ;
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
2014-02-12 17:23:29 +00:00
KWindowInfo info ( c - > window ( ) , NET : : WMAllProperties , NET : : WM2WindowClass ) ;
2011-01-30 14:34:42 +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 ) ;
}
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
2012-11-09 12:44:50 +00:00
# ifdef KWIN_BUILD_KAPPMENU
2013-03-15 15:49:20 +00:00
if ( ApplicationMenu : : self ( ) - > hasMenu ( c - > window ( ) ) )
2012-11-09 12:44:50 +00:00
c - > setAppMenuAvailable ( ) ;
# 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 ) ;
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 ) ;
showing_desktop_clients . 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 ;
const Client * 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 ;
}
2011-01-30 14:34:42 +00:00
client = client - > transientFor ( ) ;
}
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 ) {
2012-04-08 08:07:35 +00:00
const ClientList 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 ;
2011-01-30 14:34:42 +00:00
for ( ClientList : : ConstIterator it2 = mainclients . constBegin ( ) ;
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
{
2013-09-02 11:14:39 +00:00
qDebug ( ) < < " Workspace::slotReconfigure() " ;
2007-04-29 17:35:43 +00:00
reconfigureTimer . stop ( ) ;
2010-10-26 14:43:29 +00:00
bool borderlessMaximizedWindows = options - > borderlessMaximizedWindows ( ) ;
2013-09-04 14:10:36 +00:00
KSharedConfig : : openConfig ( ) - > 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-08 10:31:16 +00:00
DecorationPlugin * deco = DecorationPlugin : : self ( ) ;
2013-08-23 10:36:30 +00:00
if ( ! deco - > isDisabled ( ) & & deco - > reset ( ) ) {
2013-08-23 11:07:52 +00:00
deco - > recreateDecorations ( ) ;
2013-04-08 10:31:16 +00:00
deco - > destroyPreviousPlugin ( ) ;
2013-08-23 11:07:52 +00:00
connect ( deco - > factory ( ) , & KDecorationFactory : : recreateDecorations , deco , & DecorationPlugin : : recreateDecorations ) ;
2011-01-30 14:34:42 +00:00
} else {
2014-03-20 08:17:50 +00:00
foreach ( Client * c , clients ) {
c - > checkBorderSizes ( true ) ;
2012-01-12 06:42:55 +00:00
c - > triggerDecorationRepaint ( ) ;
2014-03-20 08:17:50 +00:00
}
2011-01-30 14:34:42 +00:00
}
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 ) {
if ( ( * it ) - > maximizeMode ( ) = = MaximizeFull )
2010-10-26 14:43:29 +00:00
( * it ) - > checkNoBorder ( ) ;
}
2011-01-30 14:34:42 +00:00
}
2010-10-26 14:43:29 +00:00
2013-04-09 06:11:58 +00:00
if ( ! deco - > isDisabled ( ) ) {
2013-04-29 10:17:42 +00:00
rootInfo ( ) - > setSupported ( NET : : WM2FrameOverlap , deco - > factory ( ) - > supports ( AbilityExtendIntoClientArea ) ) ;
2011-04-28 13:56:50 +00:00
} else {
2013-04-29 10:17:42 +00:00
rootInfo ( ) - > setSupported ( NET : : WM2FrameOverlap , false ) ;
2011-04-28 13:56:50 +00:00
}
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 :
QList < Window > obscuring_windows ;
static QList < Window > * cached ;
static unsigned int max_cache_size ;
} ;
2007-04-29 17:35:43 +00:00
QList < Window > * ObscuringWindows : : cached = 0 ;
unsigned int ObscuringWindows : : max_cache_size = 0 ;
2011-01-30 14:34:42 +00:00
void ObscuringWindows : : create ( Client * c )
{
if ( cached = = 0 )
2007-04-29 17:35:43 +00:00
cached = new QList < Window > ;
Window obs_win ;
XWindowChanges chngs ;
int mask = CWSibling | CWStackMode ;
2011-01-30 14:34:42 +00:00
if ( cached - > count ( ) > 0 ) {
cached - > removeAll ( obs_win = cached - > first ( ) ) ;
2007-04-29 17:35:43 +00:00
chngs . x = c - > x ( ) ;
chngs . y = c - > y ( ) ;
chngs . width = c - > width ( ) ;
chngs . height = c - > height ( ) ;
mask | = CWX | CWY | CWWidth | CWHeight ;
2011-01-30 14:34:42 +00:00
} else {
2007-04-29 17:35:43 +00:00
XSetWindowAttributes a ;
a . background_pixmap = None ;
a . override_redirect = True ;
2011-01-30 14:34:42 +00:00
obs_win = XCreateWindow ( display ( ) , rootWindow ( ) , c - > x ( ) , c - > y ( ) ,
c - > width ( ) , c - > height ( ) , 0 , CopyFromParent , InputOutput ,
CopyFromParent , CWBackPixmap | CWOverrideRedirect , & a ) ;
}
2007-04-29 17:35:43 +00:00
chngs . sibling = c - > frameId ( ) ;
chngs . stack_mode = Below ;
2011-01-30 14:34:42 +00:00
XConfigureWindow ( display ( ) , obs_win , mask , & chngs ) ;
XMapWindow ( display ( ) , obs_win ) ;
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 ;
for ( QList < Window > : : ConstIterator it = obscuring_windows . constBegin ( ) ;
it ! = obscuring_windows . constEnd ( ) ;
+ + it ) {
XUnmapWindow ( display ( ) , * it ) ;
if ( cached - > count ( ) < int ( max_cache_size ) )
cached - > prepend ( * it ) ;
2007-04-29 17:35:43 +00:00
else
2011-01-30 14:34:42 +00:00
XDestroyWindow ( display ( ) , * 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 )
{
+ + block_showing_desktop ;
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 ( ) ;
}
- - block_showing_desktop ;
if ( showingDesktop ( ) ) // Do this only after desktop change to avoid flicker
resetShowingDesktop ( false ) ;
}
void Workspace : : activateClientOnNewDesktop ( uint desktop )
{
Client * c = NULL ;
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
2012-11-16 07:23:47 +00:00
Client * Workspace : : findClientToActivateOnDesktop ( uint desktop )
{
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
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
+ + block_showing_desktop ; //FIXME should I be using that?
// 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
- - block_showing_desktop ;
//FIXME not sure if I should do this either
if ( showingDesktop ( ) ) // Do this only after desktop change to avoid flicker
resetShowingDesktop ( false ) ;
2010-05-11 20:30:20 +00:00
// Restore the focus on this desktop
- - block_focus ;
Client * c = 0 ;
//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
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
*/
2011-01-30 14:34:42 +00:00
void Workspace : : sendClientToDesktop ( Client * c , int desk , bool dont_activate )
{
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
2011-01-30 14:34:42 +00:00
ClientList transients_stacking_order = ensureStackingOrder ( c - > transients ( ) ) ;
for ( ClientList : : ConstIterator 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
*
*/
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 ;
}
2011-01-30 14:34:42 +00:00
void Workspace : : sendClientToScreen ( Client * c , int screen )
{
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
2011-01-30 14:34:42 +00:00
void Workspace : : requestDelayFocus ( Client * c )
{
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 )
{
2013-04-29 10:17:42 +00:00
rootInfo ( ) - > setShowingDesktop ( showing ) ;
2007-04-29 17:35:43 +00:00
showing_desktop = showing ;
+ + block_showing_desktop ;
2011-01-30 14:34:42 +00:00
if ( showing_desktop ) {
2007-04-29 17:35:43 +00:00
showing_desktop_clients . clear ( ) ;
+ + block_focus ;
2012-04-08 08:07:35 +00:00
ToplevelList cls = stackingOrder ( ) ;
2008-12-18 13:50:57 +00:00
// Find them first, then minimize, otherwise transients may get minimized with the window
2007-04-29 17:35:43 +00:00
// they're transient for
2012-04-08 08:07:35 +00:00
for ( ToplevelList : : ConstIterator it = cls . constBegin ( ) ;
2011-01-30 14:34:42 +00:00
it ! = cls . constEnd ( ) ;
2012-04-08 08:07:35 +00:00
+ + it ) {
Client * c = qobject_cast < Client * > ( * it ) ;
if ( ! c ) {
continue ;
}
if ( c - > isOnCurrentActivity ( ) & & c - > isOnCurrentDesktop ( ) & & c - > isShown ( true ) & & ! c - > isSpecialWindow ( ) )
showing_desktop_clients . prepend ( c ) ; // Topmost first to reduce flicker
}
2011-01-30 14:34:42 +00:00
for ( ClientList : : ConstIterator it = showing_desktop_clients . constBegin ( ) ;
it ! = showing_desktop_clients . constEnd ( ) ;
+ + it )
2007-04-29 17:35:43 +00:00
( * it ) - > minimize ( ) ;
- - block_focus ;
2012-11-16 07:23:47 +00:00
if ( Client * desk = findDesktop ( true , VirtualDesktopManager : : self ( ) - > current ( ) ) )
2011-01-30 14:34:42 +00:00
requestFocus ( desk ) ;
} else {
for ( ClientList : : ConstIterator it = showing_desktop_clients . constBegin ( ) ;
it ! = showing_desktop_clients . constEnd ( ) ;
+ + it )
2007-04-29 17:35:43 +00:00
( * it ) - > unminimize ( ) ;
2011-01-30 14:34:42 +00:00
if ( showing_desktop_clients . count ( ) > 0 )
requestFocus ( showing_desktop_clients . first ( ) ) ;
2007-04-29 17:35:43 +00:00
showing_desktop_clients . clear ( ) ;
}
2011-01-30 14:34:42 +00:00
- - block_showing_desktop ;
}
2007-04-29 17:35:43 +00:00
2008-12-18 13:50:57 +00:00
/**
* Following Kicker ' s behavior :
* Changing a virtual desktop resets the state and shows the windows again .
* Unminimizing a window resets the state but keeps the windows hidden ( except
* the one that was unminimized ) .
* A new window resets the state and shows the windows again , with the new window
* being active . Due to popular demand ( # 67406 ) by people who apparently
* don ' t see a difference between " show desktop " and " minimize all " , this is not
* true if " showDesktopIsMinimizeAll " is set in kwinrc . In such case showing
* a new window resets the state but doesn ' t show windows .
*/
2011-01-30 14:34:42 +00:00
void Workspace : : resetShowingDesktop ( bool keep_hidden )
{
if ( block_showing_desktop > 0 )
2007-04-29 17:35:43 +00:00
return ;
2013-04-29 10:17:42 +00:00
rootInfo ( ) - > setShowingDesktop ( false ) ;
2007-04-29 17:35:43 +00:00
showing_desktop = false ;
+ + block_showing_desktop ;
2011-01-30 14:34:42 +00:00
if ( ! keep_hidden ) {
for ( ClientList : : ConstIterator it = showing_desktop_clients . constBegin ( ) ;
it ! = showing_desktop_clients . constEnd ( ) ;
+ + it )
2007-04-29 17:35:43 +00:00
( * it ) - > unminimize ( ) ;
2011-01-30 14:34:42 +00:00
}
2007-04-29 17:35:43 +00:00
showing_desktop_clients . clear ( ) ;
- - block_showing_desktop ;
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 ;
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 ( ) ) ) ;
support . append ( QStringLiteral ( " \n \n " ) ) ;
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 ;
}
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 ( ) ;
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 ;
}
2013-07-23 05:02:52 +00:00
support . append ( QLatin1String ( property . name ( ) ) + QStringLiteral ( " : " ) + options - > property ( property . name ( ) ) . toString ( ) + QStringLiteral ( " \n " ) ) ;
2012-03-04 14:13:22 +00:00
}
2013-01-21 08:04:06 +00:00
# ifdef KWIN_BUILD_SCREENEDGES
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 ;
}
2013-07-23 05:02:52 +00:00
support . append ( QLatin1String ( property . name ( ) ) + QStringLiteral ( " : " ) + ScreenEdges : : self ( ) - > property ( property . name ( ) ) . toString ( ) + QStringLiteral ( " \n " ) ) ;
2013-01-21 08:04:06 +00:00
}
# endif
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 " ) ) ;
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Number of Screens: %1 \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 ) ;
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Screen %1 Geometry: %2,%3,%4x%5 \n " )
2013-01-12 08:54:24 +00:00
. arg ( i )
. arg ( geo . x ( ) )
. arg ( geo . y ( ) )
. arg ( geo . width ( ) )
. arg ( geo . height ( ) ) ) ;
}
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " \n Decoration \n " ) ) ;
support . append ( QStringLiteral ( " ========== \n " ) ) ;
2013-05-27 10:26:44 +00:00
support . append ( decorationPlugin ( ) - > supportInformation ( ) ) ;
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 : {
# ifdef KWIN_HAVE_OPENGLES
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Compositing Type: OpenGL ES 2.0 \n " ) ) ;
2012-03-04 14:13:22 +00:00
# else
2013-07-23 05:02:52 +00:00
support . append ( QStringLiteral ( " Compositing Type: OpenGL \n " ) ) ;
2012-03-04 14:13:22 +00:00
# endif
GLPlatform * platform = GLPlatform : : instance ( ) ;
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 " ) ) ;
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 ;
}
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 ;
}
2007-04-29 17:35:43 +00:00
} // namespace
# include "workspace.moc"