2017-01-03 01:05:30 +03:00
/*
* Copyright 2016 Smith AR < audoban @ openmailbox . org >
* Michail Vourlakos < mvourlakos @ gmail . com >
*
* This file is part of Latte - Dock
*
* Latte - Dock 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 .
*
* Latte - Dock 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/>.
*/
2016-12-28 10:45:21 +03:00
# include "abstractwindowinterface.h"
2018-12-02 03:05:52 +03:00
2019-05-11 21:10:02 +03:00
// local
2019-05-31 14:52:16 +03:00
# include "tracker/schemes.h"
2019-07-16 20:58:48 +03:00
# include "tracker/windowstracker.h"
2019-05-11 21:10:02 +03:00
# include "../lattecorona.h"
2019-07-16 13:23:20 +03:00
// Qt
# include <QDebug>
2019-06-10 17:30:25 +03:00
// KDE
# include <KActivities/Controller>
2016-12-30 10:13:33 +03:00
2016-12-28 10:45:21 +03:00
namespace Latte {
2019-05-11 15:43:10 +03:00
namespace WindowSystem {
2016-12-28 10:45:21 +03:00
2019-11-22 01:25:43 +03:00
# define MAXPLASMAPANELTHICKNESS 96
2020-03-25 19:40:48 +03:00
# define MAXSIDEPANELTHICKNESS 512
2019-11-22 01:25:43 +03:00
2017-02-25 05:40:47 +03:00
AbstractWindowInterface : : AbstractWindowInterface ( QObject * parent )
: QObject ( parent )
2016-12-28 10:45:21 +03:00
{
2019-06-08 00:31:30 +03:00
m_activities = new KActivities : : Consumer ( this ) ;
m_currentActivity = m_activities - > currentActivity ( ) ;
2019-05-11 21:10:02 +03:00
m_corona = qobject_cast < Latte : : Corona * > ( parent ) ;
2019-05-31 14:52:16 +03:00
m_windowsTracker = new Tracker : : Windows ( this ) ;
m_schemesTracker = new Tracker : : Schemes ( this ) ;
2019-05-27 20:09:48 +03:00
2019-06-01 01:20:54 +03:00
rulesConfig = KSharedConfig : : openConfig ( QStringLiteral ( " taskmanagerrulesrc " ) ) ;
2019-05-27 20:09:48 +03:00
m_windowWaitingTimer . setInterval ( 150 ) ;
m_windowWaitingTimer . setSingleShot ( true ) ;
connect ( & m_windowWaitingTimer , & QTimer : : timeout , this , [ & ] ( ) {
WindowId wid = m_windowChangedWaiting ;
m_windowChangedWaiting = QVariant ( ) ;
emit windowChanged ( wid ) ;
} ) ;
2019-11-02 11:45:37 +03:00
connect ( this , & AbstractWindowInterface : : windowRemoved , this , & AbstractWindowInterface : : windowRemovedSlot ) ;
2019-11-22 01:25:43 +03:00
// connect(this, &AbstractWindowInterface::windowChanged, this, [&](WindowId wid) {
// qDebug() << "WINDOW CHANGED ::: " << wid;
// });
2019-06-08 00:31:30 +03:00
connect ( m_activities . data ( ) , & KActivities : : Consumer : : currentActivityChanged , this , [ & ] ( const QString & id ) {
m_currentActivity = id ;
emit currentActivityChanged ( ) ;
} ) ;
2016-12-28 10:45:21 +03:00
}
AbstractWindowInterface : : ~ AbstractWindowInterface ( )
{
2019-05-27 20:09:48 +03:00
m_windowWaitingTimer . stop ( ) ;
2019-05-12 02:17:22 +03:00
m_schemesTracker - > deleteLater ( ) ;
2019-05-11 21:10:02 +03:00
m_windowsTracker - > deleteLater ( ) ;
2016-12-28 10:45:21 +03:00
}
2020-03-25 19:40:48 +03:00
QString AbstractWindowInterface : : currentDesktop ( )
2019-06-08 00:31:30 +03:00
{
return m_currentDesktop ;
}
2020-03-25 19:40:48 +03:00
QString AbstractWindowInterface : : currentActivity ( )
2019-06-08 00:31:30 +03:00
{
return m_currentActivity ;
}
2019-05-11 21:10:02 +03:00
Latte : : Corona * AbstractWindowInterface : : corona ( )
{
return m_corona ;
}
2019-05-31 14:52:16 +03:00
Tracker : : Schemes * AbstractWindowInterface : : schemesTracker ( )
2018-10-14 13:54:09 +03:00
{
2019-05-12 02:17:22 +03:00
return m_schemesTracker ;
2018-10-14 13:54:09 +03:00
}
2019-06-01 02:43:30 +03:00
Tracker : : Windows * AbstractWindowInterface : : windowsTracker ( ) const
2019-05-11 21:10:02 +03:00
{
return m_windowsTracker ;
}
2020-03-25 19:40:48 +03:00
bool AbstractWindowInterface : : isIgnored ( const WindowId & wid ) const
2019-11-02 11:45:37 +03:00
{
return m_ignoredWindows . contains ( wid ) ;
}
2020-02-29 18:57:59 +03:00
bool AbstractWindowInterface : : isFullScreenWindow ( const QRect & wGeometry ) const
2019-11-02 11:45:37 +03:00
{
if ( wGeometry . isEmpty ( ) ) {
return false ;
}
for ( const auto scr : qGuiApp - > screens ( ) ) {
if ( wGeometry = = scr - > geometry ( ) ) {
return true ;
}
}
return false ;
}
bool AbstractWindowInterface : : isPlasmaPanel ( const QRect & wGeometry ) const
2019-11-22 01:25:43 +03:00
{
2019-11-02 11:45:37 +03:00
if ( wGeometry . isEmpty ( ) ) {
return false ;
}
2019-11-22 01:25:43 +03:00
bool isTouchingHorizontalEdge { false } ;
bool isTouchingVerticalEdge { false } ;
2019-11-02 11:45:37 +03:00
for ( const auto scr : qGuiApp - > screens ( ) ) {
if ( scr - > geometry ( ) . contains ( wGeometry . center ( ) ) ) {
2019-11-22 01:25:43 +03:00
if ( wGeometry . y ( ) = = scr - > geometry ( ) . y ( ) | | wGeometry . bottom ( ) = = scr - > geometry ( ) . bottom ( ) ) {
isTouchingHorizontalEdge = true ;
}
if ( wGeometry . left ( ) = = scr - > geometry ( ) . left ( ) | | wGeometry . right ( ) = = scr - > geometry ( ) . right ( ) ) {
isTouchingVerticalEdge = true ;
}
if ( isTouchingVerticalEdge & & isTouchingHorizontalEdge ) {
break ;
2019-11-02 11:45:37 +03:00
}
}
}
2019-11-22 01:25:43 +03:00
if ( ( isTouchingHorizontalEdge & & wGeometry . height ( ) < MAXPLASMAPANELTHICKNESS )
| | ( isTouchingVerticalEdge & & wGeometry . width ( ) < MAXPLASMAPANELTHICKNESS ) ) {
return true ;
}
2019-11-02 11:45:37 +03:00
return false ;
}
2020-03-25 19:40:48 +03:00
bool AbstractWindowInterface : : isSidepanel ( const QRect & wGeometry ) const
{
bool isVertical = wGeometry . height ( ) > wGeometry . width ( ) ;
int thickness = qMin ( wGeometry . width ( ) , wGeometry . height ( ) ) ;
int length = qMax ( wGeometry . width ( ) , wGeometry . height ( ) ) ;
QRect screenGeometry ;
for ( const auto scr : qGuiApp - > screens ( ) ) {
if ( scr - > geometry ( ) . contains ( wGeometry . center ( ) ) ) {
screenGeometry = scr - > geometry ( ) ;
break ;
}
}
bool thicknessIsAcccepted = isVertical & & ( ( thickness > MAXPLASMAPANELTHICKNESS ) & & ( thickness < MAXSIDEPANELTHICKNESS ) ) ;
bool lengthIsAccepted = isVertical & & ! screenGeometry . isEmpty ( ) & & ( length > 0.6 * screenGeometry . height ( ) ) ;
float sideRatio = ( float ) wGeometry . width ( ) / ( float ) wGeometry . height ( ) ;
return ( thicknessIsAcccepted & & lengthIsAccepted & & sideRatio < 0.4 ) ;
}
bool AbstractWindowInterface : : hasBlockedTracking ( const WindowId & wid ) const
{
return ( ! isWhitelistedWindow ( wid ) & & ( isRegisteredPlasmaIgnoredWindow ( wid ) | | isIgnored ( wid ) ) ) ;
}
bool AbstractWindowInterface : : isRegisteredPlasmaIgnoredWindow ( const WindowId & wid ) const
2019-11-02 11:45:37 +03:00
{
2020-02-29 18:57:59 +03:00
return m_plasmaIgnoredWindows . contains ( wid ) ;
2019-11-02 11:45:37 +03:00
}
2020-03-25 19:40:48 +03:00
bool AbstractWindowInterface : : isWhitelistedWindow ( const WindowId & wid ) const
{
return m_whitelistedWindows . contains ( wid ) ;
}
bool AbstractWindowInterface : : inCurrentDesktopActivity ( const WindowInfoWrap & winfo )
2019-11-13 15:23:43 +03:00
{
return ( winfo . isValid ( ) & & winfo . isOnDesktop ( currentDesktop ( ) ) & & winfo . isOnActivity ( currentActivity ( ) ) ) ;
}
2019-11-02 11:45:37 +03:00
2019-07-15 14:53:40 +03:00
//! Register Latte Ignored Windows in order to NOT be tracked
2019-07-13 14:51:26 +03:00
void AbstractWindowInterface : : registerIgnoredWindow ( WindowId wid )
{
2019-07-15 14:53:40 +03:00
if ( ! wid . isNull ( ) & & ! m_ignoredWindows . contains ( wid ) ) {
2019-07-13 14:51:26 +03:00
m_ignoredWindows . append ( wid ) ;
emit windowChanged ( wid ) ;
}
}
void AbstractWindowInterface : : unregisterIgnoredWindow ( WindowId wid )
{
2019-07-15 14:53:40 +03:00
if ( m_ignoredWindows . contains ( wid ) ) {
2019-07-13 14:51:26 +03:00
m_ignoredWindows . removeAll ( wid ) ;
emit windowRemoved ( wid ) ;
}
}
2020-02-29 18:57:59 +03:00
void AbstractWindowInterface : : registerPlasmaIgnoredWindow ( WindowId wid )
2019-11-02 11:45:37 +03:00
{
2020-02-29 18:57:59 +03:00
if ( ! wid . isNull ( ) & & ! m_plasmaIgnoredWindows . contains ( wid ) ) {
m_plasmaIgnoredWindows . append ( wid ) ;
2019-11-02 11:45:37 +03:00
emit windowChanged ( wid ) ;
}
}
2020-02-29 18:57:59 +03:00
void AbstractWindowInterface : : unregisterPlasmaIgnoredWindow ( WindowId wid )
2019-11-02 11:45:37 +03:00
{
2020-02-29 18:57:59 +03:00
if ( m_plasmaIgnoredWindows . contains ( wid ) ) {
m_plasmaIgnoredWindows . removeAll ( wid ) ;
2019-11-02 11:45:37 +03:00
}
}
2020-03-25 19:40:48 +03:00
void AbstractWindowInterface : : registerWhitelistedWindow ( WindowId wid )
{
if ( ! wid . isNull ( ) & & ! m_whitelistedWindows . contains ( wid ) ) {
m_whitelistedWindows . append ( wid ) ;
emit windowChanged ( wid ) ;
}
}
void AbstractWindowInterface : : unregisterWhitelistedWindow ( WindowId wid )
{
if ( m_whitelistedWindows . contains ( wid ) ) {
m_whitelistedWindows . removeAll ( wid ) ;
}
}
2019-11-02 11:45:37 +03:00
void AbstractWindowInterface : : windowRemovedSlot ( WindowId wid )
{
2020-02-29 18:57:59 +03:00
if ( m_plasmaIgnoredWindows . contains ( wid ) ) {
unregisterPlasmaIgnoredWindow ( wid ) ;
2019-11-02 11:45:37 +03:00
}
2020-03-25 19:40:48 +03:00
if ( m_ignoredWindows . contains ( wid ) ) {
unregisterIgnoredWindow ( wid ) ;
}
if ( m_whitelistedWindows . contains ( wid ) ) {
unregisterWhitelistedWindow ( wid ) ;
}
2019-11-02 11:45:37 +03:00
}
2019-07-13 14:51:26 +03:00
2019-06-10 17:30:25 +03:00
//! Activities switching
void AbstractWindowInterface : : switchToNextActivity ( )
{
QStringList runningActivities = m_activities - > activities ( KActivities : : Info : : State : : Running ) ;
if ( runningActivities . count ( ) < = 1 ) {
return ;
}
int curPos = runningActivities . indexOf ( m_currentActivity ) ;
int nextPos = curPos + 1 ;
if ( curPos = = runningActivities . count ( ) - 1 ) {
nextPos = 0 ;
}
KActivities : : Controller activitiesController ;
activitiesController . setCurrentActivity ( runningActivities . at ( nextPos ) ) ;
}
void AbstractWindowInterface : : switchToPreviousActivity ( )
{
QStringList runningActivities = m_activities - > activities ( KActivities : : Info : : State : : Running ) ;
if ( runningActivities . count ( ) < = 1 ) {
return ;
}
int curPos = runningActivities . indexOf ( m_currentActivity ) ;
int nextPos = curPos - 1 ;
if ( curPos = = 0 ) {
nextPos = runningActivities . count ( ) - 1 ;
}
KActivities : : Controller activitiesController ;
activitiesController . setCurrentActivity ( runningActivities . at ( nextPos ) ) ;
}
//! Delay window changed trigerring
2019-05-27 20:09:48 +03:00
void AbstractWindowInterface : : considerWindowChanged ( WindowId wid )
{
//! Consider if the windowChanged signal should be sent DIRECTLY or WAIT
if ( m_windowChangedWaiting = = wid & & m_windowWaitingTimer . isActive ( ) ) {
//! window should be sent later
m_windowWaitingTimer . start ( ) ;
return ;
}
if ( m_windowChangedWaiting ! = wid & & ! m_windowWaitingTimer . isActive ( ) ) {
//! window should be sent later
m_windowChangedWaiting = wid ;
m_windowWaitingTimer . start ( ) ;
}
if ( m_windowChangedWaiting ! = wid & & m_windowWaitingTimer . isActive ( ) ) {
m_windowWaitingTimer . stop ( ) ;
//! sent previous waiting window
2019-06-10 17:30:25 +03:00
emit windowChanged ( m_windowChangedWaiting ) ;
2019-05-27 20:09:48 +03:00
//! retrigger waiting for the upcoming window
m_windowChangedWaiting = wid ;
m_windowWaitingTimer . start ( ) ;
}
}
2016-12-28 10:45:21 +03:00
}
2019-05-11 15:43:10 +03:00
}
2017-02-25 05:40:47 +03:00