2020-04-13 10:09:12 +08:00
/********************************************************************
2020-04-14 20:25:59 +08:00
UKUI-KWin - the UKUI3.0 window manager
This file is part of the UKUI project
The ukui-kwin is forked from kwin
Copyright (C) 2014-2020 kylinos.cn
2020-04-13 10:09:12 +08:00
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Lucas Murray <lmurray@undefinedfire.com>
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
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/>.
*********************************************************************/
# include "virtualdesktops.h"
# include "input.h"
// KDE
# include <KConfigGroup>
# include <KGlobalAccel>
# include <KLocalizedString>
# include <NETWM>
# include <KWayland/Server/plasmavirtualdesktop_interface.h>
// Qt
# include <QAction>
# include <QUuid>
# include <algorithm>
# include <QDebug>
namespace KWin {
extern int screen_number ;
static bool s_loadingDesktopSettings = false ;
static QByteArray generateDesktopId ( )
{
return QUuid : : createUuid ( ) . toString ( QUuid : : WithoutBraces ) . toUtf8 ( ) ;
}
VirtualDesktop : : VirtualDesktop ( QObject * parent )
: QObject ( parent )
{
}
VirtualDesktop : : ~ VirtualDesktop ( )
{
emit aboutToBeDestroyed ( ) ;
}
void VirtualDesktopManager : : setVirtualDesktopManagement ( KWayland : : Server : : PlasmaVirtualDesktopManagementInterface * management )
{
using namespace KWayland : : Server ;
Q_ASSERT ( ! m_virtualDesktopManagement ) ;
m_virtualDesktopManagement = management ;
auto createPlasmaVirtualDesktop = [ this ] ( VirtualDesktop * desktop ) {
PlasmaVirtualDesktopInterface * pvd = m_virtualDesktopManagement - > createDesktop ( desktop - > id ( ) , desktop - > x11DesktopNumber ( ) - 1 ) ;
pvd - > setName ( desktop - > name ( ) ) ;
pvd - > sendDone ( ) ;
connect ( desktop , & VirtualDesktop : : nameChanged , pvd ,
[ desktop , pvd ] {
pvd - > setName ( desktop - > name ( ) ) ;
pvd - > sendDone ( ) ;
}
) ;
connect ( pvd , & PlasmaVirtualDesktopInterface : : activateRequested , this ,
[ this , desktop ] {
setCurrent ( desktop ) ;
}
) ;
} ;
connect ( this , & VirtualDesktopManager : : desktopCreated , m_virtualDesktopManagement , createPlasmaVirtualDesktop ) ;
connect ( this , & VirtualDesktopManager : : rowsChanged , m_virtualDesktopManagement ,
[ this ] ( uint rows ) {
m_virtualDesktopManagement - > setRows ( rows ) ;
m_virtualDesktopManagement - > sendDone ( ) ;
}
) ;
//handle removed: from VirtualDesktopManager to the wayland interface
connect ( this , & VirtualDesktopManager : : desktopRemoved , m_virtualDesktopManagement ,
[ this ] ( VirtualDesktop * desktop ) {
m_virtualDesktopManagement - > removeDesktop ( desktop - > id ( ) ) ;
}
) ;
//create a new desktop when the client asks to
connect ( m_virtualDesktopManagement , & PlasmaVirtualDesktopManagementInterface : : desktopCreateRequested , this ,
[ this ] ( const QString & name , quint32 position ) {
createVirtualDesktop ( position , name ) ;
}
) ;
//remove when the client asks to
connect ( m_virtualDesktopManagement , & PlasmaVirtualDesktopManagementInterface : : desktopRemoveRequested , this ,
[ this ] ( const QString & id ) {
//here there can be some nice kauthorized check?
//remove only from VirtualDesktopManager, the other connections will remove it from m_virtualDesktopManagement as well
removeVirtualDesktop ( id . toUtf8 ( ) ) ;
}
) ;
std : : for_each ( m_desktops . constBegin ( ) , m_desktops . constEnd ( ) , createPlasmaVirtualDesktop ) ;
//Now we are sure all ids are there
save ( ) ;
connect ( this , & VirtualDesktopManager : : currentChanged , m_virtualDesktopManagement ,
[ this ] ( ) {
for ( auto * deskInt : m_virtualDesktopManagement - > desktops ( ) ) {
if ( deskInt - > id ( ) = = currentDesktop ( ) - > id ( ) ) {
deskInt - > setActive ( true ) ;
} else {
deskInt - > setActive ( false ) ;
}
}
}
) ;
}
void VirtualDesktop : : setId ( const QByteArray & id )
{
Q_ASSERT ( m_id . isEmpty ( ) ) ;
m_id = id ;
}
void VirtualDesktop : : setX11DesktopNumber ( uint number )
{
//x11DesktopNumber can be changed now
if ( static_cast < uint > ( m_x11DesktopNumber ) = = number ) {
return ;
}
m_x11DesktopNumber = number ;
if ( m_x11DesktopNumber ! = 0 ) {
emit x11DesktopNumberChanged ( ) ;
}
}
void VirtualDesktop : : setName ( const QString & name )
{
if ( m_name = = name ) {
return ;
}
m_name = name ;
emit nameChanged ( ) ;
}
VirtualDesktopGrid : : VirtualDesktopGrid ( )
: m_size ( 1 , 2 ) // Default to tow rows
, m_grid ( QVector < QVector < VirtualDesktop * > > { QVector < VirtualDesktop * > { } , QVector < VirtualDesktop * > { } } )
{
}
VirtualDesktopGrid : : ~ VirtualDesktopGrid ( ) = default ;
void VirtualDesktopGrid : : update ( const QSize & size , Qt : : Orientation orientation , const QVector < VirtualDesktop * > & desktops )
{
// Set private variables
m_size = size ;
const uint width = size . width ( ) ;
const uint height = size . height ( ) ;
m_grid . clear ( ) ;
auto it = desktops . begin ( ) ;
auto end = desktops . end ( ) ;
if ( orientation = = Qt : : Horizontal ) {
for ( uint y = 0 ; y < height ; + + y ) {
QVector < VirtualDesktop * > row ;
for ( uint x = 0 ; x < width & & it ! = end ; + + x ) {
row < < * it ;
it + + ;
}
m_grid < < row ;
}
} else {
for ( uint y = 0 ; y < height ; + + y ) {
m_grid < < QVector < VirtualDesktop * > ( ) ;
}
for ( uint x = 0 ; x < width ; + + x ) {
for ( uint y = 0 ; y < height & & it ! = end ; + + y ) {
auto & row = m_grid [ y ] ;
row < < * it ;
it + + ;
}
}
}
}
QPoint VirtualDesktopGrid : : gridCoords ( uint id ) const
{
return gridCoords ( VirtualDesktopManager : : self ( ) - > desktopForX11Id ( id ) ) ;
}
QPoint VirtualDesktopGrid : : gridCoords ( VirtualDesktop * vd ) const
{
for ( int y = 0 ; y < m_grid . count ( ) ; + + y ) {
const auto & row = m_grid . at ( y ) ;
for ( int x = 0 ; x < row . count ( ) ; + + x ) {
if ( row . at ( x ) = = vd ) {
return QPoint ( x , y ) ;
}
}
}
return QPoint ( - 1 , - 1 ) ;
}
VirtualDesktop * VirtualDesktopGrid : : at ( const QPoint & coords ) const
{
if ( coords . y ( ) > = m_grid . count ( ) ) {
return nullptr ;
}
const auto & row = m_grid . at ( coords . y ( ) ) ;
if ( coords . x ( ) > = row . count ( ) ) {
return nullptr ;
}
return row . at ( coords . x ( ) ) ;
}
KWIN_SINGLETON_FACTORY_VARIABLE ( VirtualDesktopManager , s_manager )
VirtualDesktopManager : : VirtualDesktopManager ( QObject * parent )
: QObject ( parent )
, m_navigationWrapsAround ( false )
, m_rootInfo ( nullptr )
{
}
VirtualDesktopManager : : ~ VirtualDesktopManager ( )
{
s_manager = nullptr ;
}
void VirtualDesktopManager : : setRootInfo ( NETRootInfo * info )
{
m_rootInfo = info ;
// Nothing will be connected to rootInfo
if ( m_rootInfo ) {
for ( auto * vd : m_desktops ) {
m_rootInfo - > setDesktopName ( vd - > x11DesktopNumber ( ) , vd - > name ( ) . toUtf8 ( ) . data ( ) ) ;
}
}
}
QString VirtualDesktopManager : : name ( uint desktop ) const
{
if ( uint ( m_desktops . length ( ) ) > desktop - 1 ) {
return m_desktops [ desktop - 1 ] - > name ( ) ;
}
if ( ! m_rootInfo ) {
return defaultName ( desktop ) ;
}
return QString : : fromUtf8 ( m_rootInfo - > desktopName ( desktop ) ) ;
}
uint VirtualDesktopManager : : above ( uint id , bool wrap ) const
{
auto vd = above ( desktopForX11Id ( id ) , wrap ) ;
return vd ? vd - > x11DesktopNumber ( ) : 0 ;
}
VirtualDesktop * VirtualDesktopManager : : above ( VirtualDesktop * desktop , bool wrap ) const
{
Q_ASSERT ( m_current ) ;
if ( ! desktop ) {
desktop = m_current ;
}
QPoint coords = m_grid . gridCoords ( desktop ) ;
Q_ASSERT ( coords . x ( ) > = 0 ) ;
while ( true ) {
coords . ry ( ) - - ;
if ( coords . y ( ) < 0 ) {
if ( wrap ) {
coords . setY ( m_grid . height ( ) - 1 ) ;
} else {
return desktop ; // Already at the top-most desktop
}
}
if ( VirtualDesktop * vd = m_grid . at ( coords ) ) {
return vd ;
}
}
return nullptr ;
}
uint VirtualDesktopManager : : toRight ( uint id , bool wrap ) const
{
auto vd = toRight ( desktopForX11Id ( id ) , wrap ) ;
return vd ? vd - > x11DesktopNumber ( ) : 0 ;
}
VirtualDesktop * VirtualDesktopManager : : toRight ( VirtualDesktop * desktop , bool wrap ) const
{
Q_ASSERT ( m_current ) ;
if ( ! desktop ) {
desktop = m_current ;
}
QPoint coords = m_grid . gridCoords ( desktop ) ;
Q_ASSERT ( coords . x ( ) > = 0 ) ;
while ( true ) {
coords . rx ( ) + + ;
if ( coords . x ( ) > = m_grid . width ( ) ) {
if ( wrap ) {
coords . setX ( 0 ) ;
} else {
return desktop ; // Already at the right-most desktop
}
}
if ( VirtualDesktop * vd = m_grid . at ( coords ) ) {
return vd ;
}
}
return nullptr ;
}
uint VirtualDesktopManager : : below ( uint id , bool wrap ) const
{
auto vd = below ( desktopForX11Id ( id ) , wrap ) ;
return vd ? vd - > x11DesktopNumber ( ) : 0 ;
}
VirtualDesktop * VirtualDesktopManager : : below ( VirtualDesktop * desktop , bool wrap ) const
{
Q_ASSERT ( m_current ) ;
if ( ! desktop ) {
desktop = m_current ;
}
QPoint coords = m_grid . gridCoords ( desktop ) ;
Q_ASSERT ( coords . x ( ) > = 0 ) ;
while ( true ) {
coords . ry ( ) + + ;
if ( coords . y ( ) > = m_grid . height ( ) ) {
if ( wrap ) {
coords . setY ( 0 ) ;
} else {
// Already at the bottom-most desktop
return desktop ;
}
}
if ( VirtualDesktop * vd = m_grid . at ( coords ) ) {
return vd ;
}
}
return nullptr ;
}
uint VirtualDesktopManager : : toLeft ( uint id , bool wrap ) const
{
auto vd = toLeft ( desktopForX11Id ( id ) , wrap ) ;
return vd ? vd - > x11DesktopNumber ( ) : 0 ;
}
VirtualDesktop * VirtualDesktopManager : : toLeft ( VirtualDesktop * desktop , bool wrap ) const
{
Q_ASSERT ( m_current ) ;
if ( ! desktop ) {
desktop = m_current ;
}
QPoint coords = m_grid . gridCoords ( desktop ) ;
Q_ASSERT ( coords . x ( ) > = 0 ) ;
while ( true ) {
coords . rx ( ) - - ;
if ( coords . x ( ) < 0 ) {
if ( wrap ) {
coords . setX ( m_grid . width ( ) - 1 ) ;
} else {
return desktop ; // Already at the left-most desktop
}
}
if ( VirtualDesktop * vd = m_grid . at ( coords ) ) {
return vd ;
}
}
return nullptr ;
}
VirtualDesktop * VirtualDesktopManager : : next ( VirtualDesktop * desktop , bool wrap ) const
{
Q_ASSERT ( m_current ) ;
if ( ! desktop ) {
desktop = m_current ;
}
auto it = std : : find ( m_desktops . begin ( ) , m_desktops . end ( ) , desktop ) ;
Q_ASSERT ( it ! = m_desktops . end ( ) ) ;
it + + ;
if ( it = = m_desktops . end ( ) ) {
if ( wrap ) {
return m_desktops . first ( ) ;
} else {
return desktop ;
}
}
return * it ;
}
VirtualDesktop * VirtualDesktopManager : : previous ( VirtualDesktop * desktop , bool wrap ) const
{
Q_ASSERT ( m_current ) ;
if ( ! desktop ) {
desktop = m_current ;
}
auto it = std : : find ( m_desktops . begin ( ) , m_desktops . end ( ) , desktop ) ;
Q_ASSERT ( it ! = m_desktops . end ( ) ) ;
if ( it = = m_desktops . begin ( ) ) {
if ( wrap ) {
return m_desktops . last ( ) ;
} else {
return desktop ;
}
}
it - - ;
return * it ;
}
VirtualDesktop * VirtualDesktopManager : : desktopForX11Id ( uint id ) const
{
if ( id = = 0 | | id > count ( ) ) {
return nullptr ;
}
return m_desktops . at ( id - 1 ) ;
}
VirtualDesktop * VirtualDesktopManager : : desktopForId ( const QByteArray & id ) const
{
auto desk = std : : find_if (
m_desktops . constBegin ( ) ,
m_desktops . constEnd ( ) ,
[ id ] ( const VirtualDesktop * desk ) {
return desk - > id ( ) = = id ;
}
) ;
if ( desk ! = m_desktops . constEnd ( ) ) {
return * desk ;
}
return nullptr ;
}
VirtualDesktop * VirtualDesktopManager : : createVirtualDesktop ( uint position , const QString & name )
{
//too many, can't insert new ones
if ( ( uint ) m_desktops . count ( ) = = VirtualDesktopManager : : maximum ( ) ) {
return nullptr ;
}
position = qBound ( 0u , position , static_cast < uint > ( m_desktops . count ( ) ) ) ;
auto * vd = new VirtualDesktop ( this ) ;
vd - > setX11DesktopNumber ( position + 1 ) ;
vd - > setId ( generateDesktopId ( ) ) ;
vd - > setName ( name ) ;
connect ( vd , & VirtualDesktop : : nameChanged , this ,
[ this , vd ] ( ) {
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( vd - > x11DesktopNumber ( ) , vd - > name ( ) . toUtf8 ( ) . data ( ) ) ;
}
}
) ;
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( vd - > x11DesktopNumber ( ) , vd - > name ( ) . toUtf8 ( ) . data ( ) ) ;
}
m_desktops . insert ( position , vd ) ;
//update the id of displaced desktops
for ( uint i = position + 1 ; i < ( uint ) m_desktops . count ( ) ; + + i ) {
m_desktops [ i ] - > setX11DesktopNumber ( i + 1 ) ;
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( i + 1 , m_desktops [ i ] - > name ( ) . toUtf8 ( ) . data ( ) ) ;
}
}
save ( ) ;
updateRootInfo ( ) ;
emit desktopCreated ( vd ) ;
emit countChanged ( m_desktops . count ( ) - 1 , m_desktops . count ( ) ) ;
return vd ;
}
void VirtualDesktopManager : : removeVirtualDesktop ( const QByteArray & id )
{
//don't end up without any desktop
if ( m_desktops . count ( ) = = 1 ) {
return ;
}
auto desktop = desktopForId ( id ) ;
if ( ! desktop ) {
return ;
}
const uint oldCurrent = m_current - > x11DesktopNumber ( ) ;
const uint i = desktop - > x11DesktopNumber ( ) - 1 ;
m_desktops . remove ( i ) ;
for ( uint j = i ; j < ( uint ) m_desktops . count ( ) ; + + j ) {
m_desktops [ j ] - > setX11DesktopNumber ( j + 1 ) ;
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( j + 1 , m_desktops [ j ] - > name ( ) . toUtf8 ( ) . data ( ) ) ;
}
}
const uint newCurrent = qMin ( oldCurrent , ( uint ) m_desktops . count ( ) ) ;
m_current = m_desktops . at ( newCurrent - 1 ) ;
if ( oldCurrent ! = newCurrent ) {
emit currentChanged ( oldCurrent , newCurrent ) ;
}
save ( ) ;
updateRootInfo ( ) ;
emit desktopRemoved ( desktop ) ;
emit countChanged ( m_desktops . count ( ) + 1 , m_desktops . count ( ) ) ;
desktop - > deleteLater ( ) ;
}
uint VirtualDesktopManager : : current ( ) const
{
return m_current ? m_current - > x11DesktopNumber ( ) : 0 ;
}
VirtualDesktop * VirtualDesktopManager : : currentDesktop ( ) const
{
return m_current ;
}
bool VirtualDesktopManager : : setCurrent ( uint newDesktop )
{
if ( newDesktop < 1 | | newDesktop > count ( ) | | newDesktop = = current ( ) ) {
return false ;
}
auto d = desktopForX11Id ( newDesktop ) ;
Q_ASSERT ( d ) ;
return setCurrent ( d ) ;
}
bool VirtualDesktopManager : : setCurrent ( VirtualDesktop * newDesktop )
{
Q_ASSERT ( newDesktop ) ;
if ( m_current = = newDesktop ) {
return false ;
}
const uint oldDesktop = current ( ) ;
m_current = newDesktop ;
emit currentChanged ( oldDesktop , newDesktop - > x11DesktopNumber ( ) ) ;
return true ;
}
void VirtualDesktopManager : : setCount ( uint count )
{
count = qBound < uint > ( 1 , count , VirtualDesktopManager : : maximum ( ) ) ;
if ( count = = uint ( m_desktops . count ( ) ) ) {
// nothing to change
return ;
}
QList < VirtualDesktop * > newDesktops ;
const uint oldCount = m_desktops . count ( ) ;
//this explicit check makes it more readable
if ( ( uint ) m_desktops . count ( ) > count ) {
const auto desktopsToRemove = m_desktops . mid ( count ) ;
m_desktops . resize ( count ) ;
if ( m_current ) {
uint oldCurrent = current ( ) ;
uint newCurrent = qMin ( oldCurrent , count ) ;
m_current = m_desktops . at ( newCurrent - 1 ) ;
if ( oldCurrent ! = newCurrent ) {
emit currentChanged ( oldCurrent , newCurrent ) ;
}
}
for ( auto desktop : desktopsToRemove ) {
emit desktopRemoved ( desktop ) ;
desktop - > deleteLater ( ) ;
}
} else {
while ( uint ( m_desktops . count ( ) ) < count ) {
auto vd = new VirtualDesktop ( this ) ;
const int x11Number = m_desktops . count ( ) + 1 ;
vd - > setX11DesktopNumber ( x11Number ) ;
vd - > setName ( defaultName ( x11Number ) ) ;
if ( ! s_loadingDesktopSettings ) {
vd - > setId ( generateDesktopId ( ) ) ;
}
m_desktops < < vd ;
newDesktops < < vd ;
connect ( vd , & VirtualDesktop : : nameChanged , this ,
[ this , vd ] {
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( vd - > x11DesktopNumber ( ) , vd - > name ( ) . toUtf8 ( ) . data ( ) ) ;
}
}
) ;
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( vd - > x11DesktopNumber ( ) , vd - > name ( ) . toUtf8 ( ) . data ( ) ) ;
}
}
}
updateRootInfo ( ) ;
if ( ! s_loadingDesktopSettings ) {
save ( ) ;
}
for ( auto vd : newDesktops ) {
emit desktopCreated ( vd ) ;
}
emit countChanged ( oldCount , m_desktops . count ( ) ) ;
}
uint VirtualDesktopManager : : rows ( ) const
{
return m_rows ;
}
void VirtualDesktopManager : : setRows ( uint rows )
{
if ( rows = = 0 | | rows > count ( ) | | rows = = m_rows ) {
return ;
}
m_rows = rows ;
int columns = count ( ) / m_rows ;
if ( count ( ) % m_rows > 0 ) {
columns + + ;
}
if ( m_rootInfo ) {
m_rootInfo - > setDesktopLayout ( NET : : OrientationHorizontal , columns , m_rows , NET : : DesktopLayoutCornerTopLeft ) ;
m_rootInfo - > activate ( ) ;
}
updateLayout ( ) ;
//rowsChanged will be emitted by setNETDesktopLayout called by updateLayout
}
void VirtualDesktopManager : : updateRootInfo ( )
{
if ( ! m_rootInfo ) {
// Make sure the layout is still valid
updateLayout ( ) ;
return ;
}
const int n = count ( ) ;
m_rootInfo - > setNumberOfDesktops ( n ) ;
NETPoint * viewports = new NETPoint [ n ] ;
m_rootInfo - > setDesktopViewport ( n , * viewports ) ;
delete [ ] viewports ;
// Make sure the layout is still valid
updateLayout ( ) ;
}
void VirtualDesktopManager : : updateLayout ( )
{
m_rows = qMin ( m_rows , count ( ) ) ;
int columns = count ( ) / m_rows ;
Qt : : Orientation orientation = Qt : : Horizontal ;
if ( m_rootInfo ) {
// TODO: Is there a sane way to avoid overriding the existing grid?
columns = m_rootInfo - > desktopLayoutColumnsRows ( ) . width ( ) ;
m_rows = qMax ( 1 , m_rootInfo - > desktopLayoutColumnsRows ( ) . height ( ) ) ;
orientation = m_rootInfo - > desktopLayoutOrientation ( ) = = NET : : OrientationHorizontal ? Qt : : Horizontal : Qt : : Vertical ;
}
if ( columns = = 0 ) {
// Not given, set default layout
m_rows = count ( ) = = 1u ? 1 : 2 ;
columns = count ( ) / m_rows ;
}
setNETDesktopLayout ( orientation ,
columns , m_rows , 0 //rootInfo->desktopLayoutCorner() // Not really worth implementing right now.
) ;
}
void VirtualDesktopManager : : load ( )
{
s_loadingDesktopSettings = true ;
if ( ! m_config ) {
return ;
}
QString groupname ;
if ( screen_number = = 0 ) {
groupname = QStringLiteral ( " Desktops " ) ;
} else {
groupname = QStringLiteral ( " Desktops-screen-%1 " ) . arg ( screen_number ) ;
}
KConfigGroup group ( m_config , groupname ) ;
const int n = group . readEntry ( " Number " , 1 ) ;
setCount ( n ) ;
for ( int i = 1 ; i < = n ; i + + ) {
QString s = group . readEntry ( QStringLiteral ( " Name_%1 " ) . arg ( i ) , i18n ( " Desktop %1 " , i ) ) ;
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( i , s . toUtf8 ( ) . data ( ) ) ;
}
m_desktops [ i - 1 ] - > setName ( s . toUtf8 ( ) . data ( ) ) ;
const QString sId = group . readEntry ( QStringLiteral ( " Id_%1 " ) . arg ( i ) , QString ( ) ) ;
//load gets called 2 times, see workspace.cpp line 416 and BUG 385260
if ( m_desktops [ i - 1 ] - > id ( ) . isEmpty ( ) ) {
m_desktops [ i - 1 ] - > setId ( sId . isEmpty ( ) ? generateDesktopId ( ) : sId . toUtf8 ( ) ) ;
} else {
Q_ASSERT ( sId . isEmpty ( ) | | m_desktops [ i - 1 ] - > id ( ) = = sId . toUtf8 ( ) . data ( ) ) ;
}
// TODO: update desktop focus chain, why?
// m_desktopFocusChain.value()[i-1] = i;
}
int rows = group . readEntry < int > ( " Rows " , 2 ) ;
m_rows = qBound ( 1 , rows , n ) ;
if ( m_rootInfo ) {
// avoid weird cases like having 3 rows for 4 desktops, where the last row is unused
int columns = n / m_rows ;
if ( n % m_rows > 0 ) {
columns + + ;
}
m_rootInfo - > setDesktopLayout ( NET : : OrientationHorizontal , columns , m_rows , NET : : DesktopLayoutCornerTopLeft ) ;
m_rootInfo - > activate ( ) ;
}
s_loadingDesktopSettings = false ;
}
void VirtualDesktopManager : : save ( )
{
if ( s_loadingDesktopSettings ) {
return ;
}
if ( ! m_config ) {
return ;
}
QString groupname ;
if ( screen_number = = 0 ) {
groupname = QStringLiteral ( " Desktops " ) ;
} else {
groupname = QStringLiteral ( " Desktops-screen-%1 " ) . arg ( screen_number ) ;
}
KConfigGroup group ( m_config , groupname ) ;
for ( int i = count ( ) + 1 ; group . hasKey ( QStringLiteral ( " Id_%1 " ) . arg ( i ) ) ; i + + ) {
group . deleteEntry ( QStringLiteral ( " Id_%1 " ) . arg ( i ) ) ;
group . deleteEntry ( QStringLiteral ( " Name_%1 " ) . arg ( i ) ) ;
}
group . writeEntry ( " Number " , count ( ) ) ;
for ( uint i = 1 ; i < = count ( ) ; + + i ) {
QString s = name ( i ) ;
const QString defaultvalue = defaultName ( i ) ;
if ( s . isEmpty ( ) ) {
s = defaultvalue ;
if ( m_rootInfo ) {
m_rootInfo - > setDesktopName ( i , s . toUtf8 ( ) . data ( ) ) ;
}
}
if ( s ! = defaultvalue ) {
group . writeEntry ( QStringLiteral ( " Name_%1 " ) . arg ( i ) , s ) ;
} else {
QString currentvalue = group . readEntry ( QStringLiteral ( " Name_%1 " ) . arg ( i ) , QString ( ) ) ;
if ( currentvalue ! = defaultvalue ) {
group . deleteEntry ( QStringLiteral ( " Name_%1 " ) . arg ( i ) ) ;
}
}
group . writeEntry ( QStringLiteral ( " Id_%1 " ) . arg ( i ) , m_desktops [ i - 1 ] - > id ( ) ) ;
}
group . writeEntry ( " Rows " , m_rows ) ;
// Save to disk
group . sync ( ) ;
}
QString VirtualDesktopManager : : defaultName ( int desktop ) const
{
return i18n ( " Desktop %1 " , desktop ) ;
}
void VirtualDesktopManager : : setNETDesktopLayout ( Qt : : Orientation orientation , uint width , uint height , int startingCorner )
{
Q_UNUSED ( startingCorner ) ; // Not really worth implementing right now.
const uint count = m_desktops . count ( ) ;
// Calculate valid grid size
Q_ASSERT ( width > 0 | | height > 0 ) ;
if ( ( width < = 0 ) & & ( height > 0 ) ) {
width = ( count + height - 1 ) / height ;
} else if ( ( height < = 0 ) & & ( width > 0 ) ) {
height = ( count + width - 1 ) / width ;
}
while ( width * height < count ) {
if ( orientation = = Qt : : Horizontal ) {
+ + width ;
} else {
+ + height ;
}
}
m_rows = qMax ( 1u , height ) ;
m_grid . update ( QSize ( width , height ) , orientation , m_desktops ) ;
// TODO: why is there no call to m_rootInfo->setDesktopLayout?
emit layoutChanged ( width , height ) ;
emit rowsChanged ( height ) ;
}
void VirtualDesktopManager : : initShortcuts ( )
{
initSwitchToShortcuts ( ) ;
QAction * nextAction = addAction ( QStringLiteral ( " Switch to Next Desktop " ) , i18n ( " Switch to Next Desktop " ) , & VirtualDesktopManager : : slotNext ) ;
input ( ) - > registerTouchpadSwipeShortcut ( SwipeDirection : : Right , nextAction ) ;
QAction * previousAction = addAction ( QStringLiteral ( " Switch to Previous Desktop " ) , i18n ( " Switch to Previous Desktop " ) , & VirtualDesktopManager : : slotPrevious ) ;
input ( ) - > registerTouchpadSwipeShortcut ( SwipeDirection : : Left , previousAction ) ;
2020-07-03 16:38:22 +08:00
//将切换桌面快捷键修改为同ukwm切换方式,Qt::CTRL + Qt::ALT + Qt::Key_Right等
//并且KGlobalAccel::setGlobalShortcut注册不成功,采用addAction方式注册
//QAction *slotRightAction = addAction(QStringLiteral("Switch One Desktop to the Right"), i18n("Switch One Desktop to the Right"), &VirtualDesktopManager::slotRight);
//KGlobalAccel::setGlobalShortcut(slotRightAction, QKeySequence(Qt::CTRL + Qt::META + Qt::Key_Right));
const QString toDesktop1 = QStringLiteral ( " Switch One Desktop to the Right " ) ;
2020-09-04 10:01:07 +08:00
addAction ( toDesktop1 , i18n ( toDesktop1 . toStdString ( ) . c_str ( ) ) , QKeySequence ( Qt : : CTRL + Qt : : ALT + Qt : : Key_Right ) , & VirtualDesktopManager : : slotRight ) ;
2020-07-03 16:38:22 +08:00
//QAction *slotLeftAction = addAction(QStringLiteral("Switch One Desktop to the Left"), i18n("Switch One Desktop to the Left"), &VirtualDesktopManager::slotLeft);
//KGlobalAccel::setGlobalShortcut(slotLeftAction, QKeySequence(Qt::CTRL + Qt::META + Qt::Key_Left));
const QString toDesktop2 = QStringLiteral ( " Switch One Desktop to the Left " ) ;
2020-09-04 10:01:07 +08:00
addAction ( toDesktop2 , i18n ( toDesktop2 . toStdString ( ) . c_str ( ) ) , QKeySequence ( Qt : : CTRL + Qt : : ALT + Qt : : Key_Left ) , & VirtualDesktopManager : : slotLeft ) ;
2020-07-03 16:38:22 +08:00
//QAction *slotUpAction = addAction(QStringLiteral("Switch One Desktop Up"), i18n("Switch One Desktop Up"), &VirtualDesktopManager::slotUp);
//KGlobalAccel::setGlobalShortcut(slotUpAction, QKeySequence(Qt::CTRL + Qt::META + Qt::Key_Up));
const QString toDesktop3 = QStringLiteral ( " Switch One Desktop Up " ) ;
2020-09-04 10:01:07 +08:00
addAction ( toDesktop3 , i18n ( toDesktop3 . toStdString ( ) . c_str ( ) ) , QKeySequence ( Qt : : CTRL + Qt : : ALT + Qt : : Key_Up ) , & VirtualDesktopManager : : slotUp ) ;
2020-07-03 16:38:22 +08:00
//QAction *slotDownAction = addAction(QStringLiteral("Switch One Desktop Down"), i18n("Switch One Desktop Down"), &VirtualDesktopManager::slotDown);
//KGlobalAccel::setGlobalShortcut(slotDownAction, QKeySequence(Qt::CTRL + Qt::META + Qt::Key_Down));
const QString toDesktop4 = QStringLiteral ( " Switch One Desktop Down " ) ;
2020-09-04 10:01:07 +08:00
addAction ( toDesktop4 , i18n ( toDesktop4 . toStdString ( ) . c_str ( ) ) , QKeySequence ( Qt : : CTRL + Qt : : ALT + Qt : : Key_Down ) , & VirtualDesktopManager : : slotDown ) ;
2020-04-13 10:09:12 +08:00
// axis events
input ( ) - > registerAxisShortcut ( Qt : : ControlModifier | Qt : : AltModifier , PointerAxisDown ,
findChild < QAction * > ( QStringLiteral ( " Switch to Next Desktop " ) ) ) ;
input ( ) - > registerAxisShortcut ( Qt : : ControlModifier | Qt : : AltModifier , PointerAxisUp ,
findChild < QAction * > ( QStringLiteral ( " Switch to Previous Desktop " ) ) ) ;
}
void VirtualDesktopManager : : initSwitchToShortcuts ( )
{
const QString toDesktop = QStringLiteral ( " Switch to Desktop %1 " ) ;
const KLocalizedString toDesktopLabel = ki18n ( " Switch to Desktop %1 " ) ;
addAction ( toDesktop , toDesktopLabel , 1 , QKeySequence ( Qt : : CTRL + Qt : : Key_F1 ) , & VirtualDesktopManager : : slotSwitchTo ) ;
addAction ( toDesktop , toDesktopLabel , 2 , QKeySequence ( Qt : : CTRL + Qt : : Key_F2 ) , & VirtualDesktopManager : : slotSwitchTo ) ;
addAction ( toDesktop , toDesktopLabel , 3 , QKeySequence ( Qt : : CTRL + Qt : : Key_F3 ) , & VirtualDesktopManager : : slotSwitchTo ) ;
addAction ( toDesktop , toDesktopLabel , 4 , QKeySequence ( Qt : : CTRL + Qt : : Key_F4 ) , & VirtualDesktopManager : : slotSwitchTo ) ;
for ( uint i = 5 ; i < = maximum ( ) ; + + i ) {
addAction ( toDesktop , toDesktopLabel , i , QKeySequence ( ) , & VirtualDesktopManager : : slotSwitchTo ) ;
}
}
QAction * VirtualDesktopManager : : addAction ( const QString & name , const KLocalizedString & label , uint value , const QKeySequence & key , void ( VirtualDesktopManager : : * slot ) ( ) )
{
QAction * a = new QAction ( this ) ;
2020-04-13 11:09:57 +08:00
a - > setProperty ( " componentName " , QStringLiteral ( UKUI_KWIN_NAME ) ) ;
2020-04-13 10:09:12 +08:00
a - > setObjectName ( name . arg ( value ) ) ;
a - > setText ( label . subs ( value ) . toString ( ) ) ;
a - > setData ( value ) ;
KGlobalAccel : : setGlobalShortcut ( a , key ) ;
input ( ) - > registerShortcut ( key , a , this , slot ) ;
return a ;
}
2020-09-04 10:01:07 +08:00
QAction * VirtualDesktopManager : : addAction ( const QString & name , const QString & label , const QKeySequence & key , void ( VirtualDesktopManager : : * slot ) ( ) )
{
QAction * a = new QAction ( this ) ;
a - > setProperty ( " componentName " , QStringLiteral ( UKUI_KWIN_NAME ) ) ;
a - > setObjectName ( name ) ;
a - > setText ( label ) ;
KGlobalAccel : : setGlobalShortcut ( a , key ) ;
input ( ) - > registerShortcut ( key , a , this , slot ) ;
return a ;
}
2020-04-13 10:09:12 +08:00
QAction * VirtualDesktopManager : : addAction ( const QString & name , const QString & label , void ( VirtualDesktopManager : : * slot ) ( ) )
{
QAction * a = new QAction ( this ) ;
2020-04-13 11:09:57 +08:00
a - > setProperty ( " componentName " , QStringLiteral ( UKUI_KWIN_NAME ) ) ;
2020-04-13 10:09:12 +08:00
a - > setObjectName ( name ) ;
a - > setText ( label ) ;
KGlobalAccel : : setGlobalShortcut ( a , QKeySequence ( ) ) ;
input ( ) - > registerShortcut ( QKeySequence ( ) , a , this , slot ) ;
return a ;
}
void VirtualDesktopManager : : slotSwitchTo ( )
{
QAction * act = qobject_cast < QAction * > ( sender ( ) ) ;
if ( ! act ) {
return ;
}
bool ok = false ;
const uint i = act - > data ( ) . toUInt ( & ok ) ;
if ( ! ok ) {
return ;
}
setCurrent ( i ) ;
}
void VirtualDesktopManager : : setNavigationWrappingAround ( bool enabled )
{
if ( enabled = = m_navigationWrapsAround ) {
return ;
}
m_navigationWrapsAround = enabled ;
emit navigationWrappingAroundChanged ( ) ;
}
void VirtualDesktopManager : : slotDown ( )
{
moveTo < DesktopBelow > ( isNavigationWrappingAround ( ) ) ;
}
void VirtualDesktopManager : : slotLeft ( )
{
moveTo < DesktopLeft > ( isNavigationWrappingAround ( ) ) ;
}
void VirtualDesktopManager : : slotPrevious ( )
{
moveTo < DesktopPrevious > ( isNavigationWrappingAround ( ) ) ;
}
void VirtualDesktopManager : : slotNext ( )
{
moveTo < DesktopNext > ( isNavigationWrappingAround ( ) ) ;
}
void VirtualDesktopManager : : slotRight ( )
{
moveTo < DesktopRight > ( isNavigationWrappingAround ( ) ) ;
}
void VirtualDesktopManager : : slotUp ( )
{
moveTo < DesktopAbove > ( isNavigationWrappingAround ( ) ) ;
}
} // KWin