mirror of
https://github.com/KDE/latte-dock.git
synced 2024-12-23 13:33:50 +03:00
refactor:move window functions to its own class
--all windows related functions present at visibility manager are moved at their own class WindowsTracker
This commit is contained in:
parent
a7bfff0b96
commit
78096b4181
@ -31,6 +31,7 @@ set(lattedock-app_SRCS
|
||||
view/screenedgeghostwindow.cpp
|
||||
view/view.cpp
|
||||
view/visibilitymanager.cpp
|
||||
view/windowstracker.cpp
|
||||
view/settings/primaryconfigview.cpp
|
||||
view/settings/secondaryconfigview.cpp
|
||||
wm/abstractwindowinterface.cpp
|
||||
|
@ -119,6 +119,10 @@ View::View(Plasma::Corona *corona, QScreen *targetScreen, bool byPassWM)
|
||||
});
|
||||
}
|
||||
|
||||
if (!m_windowsTracker) {
|
||||
m_windowsTracker = new ViewPart::WindowsTracker(this);
|
||||
}
|
||||
|
||||
connect(this->containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), SLOT(statusChanged(Plasma::Types::ItemStatus)));
|
||||
}, Qt::DirectConnection);
|
||||
|
||||
@ -167,8 +171,13 @@ View::~View()
|
||||
delete m_effects;
|
||||
}
|
||||
|
||||
if (m_visibility)
|
||||
if (m_windowsTracker) {
|
||||
delete m_windowsTracker;
|
||||
}
|
||||
|
||||
if (m_visibility) {
|
||||
delete m_visibility;
|
||||
}
|
||||
}
|
||||
|
||||
void View::init()
|
||||
@ -227,8 +236,8 @@ void View::disconnectSensitiveSignals()
|
||||
disconnect(corona(), &Plasma::Corona::availableScreenRectChanged, this, &View::availableScreenRectChanged);
|
||||
setManagedLayout(nullptr);
|
||||
|
||||
if (visibility()) {
|
||||
visibility()->setEnabledDynamicBackground(false);
|
||||
if (m_windowsTracker) {
|
||||
m_windowsTracker->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -658,15 +667,15 @@ void View::applyActivitiesToWindows()
|
||||
{
|
||||
if (m_visibility) {
|
||||
QStringList activities = m_managedLayout->appliedActivities();
|
||||
m_visibility->setWindowOnActivities(*this, activities);
|
||||
m_windowsTracker->setWindowOnActivities(*this, activities);
|
||||
|
||||
if (m_configView) {
|
||||
m_visibility->setWindowOnActivities(*m_configView, activities);
|
||||
m_windowsTracker->setWindowOnActivities(*m_configView, activities);
|
||||
|
||||
auto configView = qobject_cast<ViewPart::PrimaryConfigView *>(m_configView);
|
||||
|
||||
if (configView && configView->secondaryWindow()) {
|
||||
m_visibility->setWindowOnActivities(*configView->secondaryWindow(), activities);
|
||||
m_windowsTracker->setWindowOnActivities(*configView->secondaryWindow(), activities);
|
||||
}
|
||||
}
|
||||
|
||||
@ -906,6 +915,11 @@ ViewPart::VisibilityManager *View::visibility() const
|
||||
return m_visibility;
|
||||
}
|
||||
|
||||
ViewPart::WindowsTracker *View::windowsTracker() const
|
||||
{
|
||||
return m_windowsTracker;
|
||||
}
|
||||
|
||||
bool View::event(QEvent *e)
|
||||
{
|
||||
if (!m_inDelete) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "effects.h"
|
||||
#include "positioner.h"
|
||||
#include "visibilitymanager.h"
|
||||
#include "windowstracker.h"
|
||||
#include "settings/primaryconfigview.h"
|
||||
#include "../shortcuts/globalshortcuts.h"
|
||||
#include "../layout/layout.h"
|
||||
@ -94,6 +95,7 @@ class View : public PlasmaQuick::ContainmentView
|
||||
Q_PROPERTY(Layout *managedLayout READ managedLayout WRITE setManagedLayout NOTIFY managedLayoutChanged)
|
||||
Q_PROPERTY(Latte::ViewPart::Positioner *positioner READ positioner NOTIFY positionerChanged)
|
||||
Q_PROPERTY(Latte::ViewPart::VisibilityManager *visibility READ visibility NOTIFY visibilityChanged)
|
||||
Q_PROPERTY(Latte::ViewPart::WindowsTracker *windowsTracker READ windowsTracker NOTIFY windowsTrackerChanged)
|
||||
|
||||
Q_PROPERTY(QRect absoluteGeometry READ absGeometry NOTIFY absGeometryChanged)
|
||||
Q_PROPERTY(QRect localGeometry READ localGeometry WRITE setLocalGeometry NOTIFY localGeometryChanged)
|
||||
@ -159,6 +161,7 @@ public:
|
||||
ViewPart::Effects *effects() const;
|
||||
ViewPart::Positioner *positioner() const;
|
||||
ViewPart::VisibilityManager *visibility() const;
|
||||
ViewPart::WindowsTracker *windowsTracker() const;
|
||||
|
||||
Layout *managedLayout() const;
|
||||
void setManagedLayout(Layout *layout);
|
||||
@ -226,9 +229,10 @@ signals:
|
||||
void normalThicknessChanged();
|
||||
void offsetChanged();
|
||||
void onPrimaryChanged();
|
||||
void visibilityChanged();
|
||||
void positionerChanged();
|
||||
void screenGeometryChanged();
|
||||
void visibilityChanged();
|
||||
void windowsTrackerChanged();
|
||||
void xChanged();
|
||||
void yChanged();
|
||||
|
||||
@ -277,6 +281,7 @@ private:
|
||||
QPointer<ViewPart::Effects> m_effects;
|
||||
QPointer<ViewPart::Positioner> m_positioner;
|
||||
QPointer<ViewPart::VisibilityManager> m_visibility;
|
||||
QPointer<ViewPart::WindowsTracker> m_windowsTracker;
|
||||
|
||||
//! Connections to release and bound for the managed layout
|
||||
std::array<QMetaObject::Connection, 5> connectionsManagedLayout;
|
||||
|
@ -113,7 +113,7 @@ void VisibilityManager::setMode(Latte::Types::Visibility mode)
|
||||
disconnect(c);
|
||||
}
|
||||
|
||||
if (m_mode != Types::DodgeAllWindows && !enabledDynamicBackgroundFlag) {
|
||||
if (m_mode != Types::DodgeAllWindows) {
|
||||
windows.clear();
|
||||
}
|
||||
|
||||
@ -469,11 +469,6 @@ void VisibilityManager::setViewGeometry(const QRect &geometry)
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityManager::setWindowOnActivities(QWindow &window, const QStringList &activities)
|
||||
{
|
||||
wm->setWindowOnActivities(window, activities);
|
||||
}
|
||||
|
||||
void VisibilityManager::applyActivitiesToHiddenWindows(const QStringList &activities)
|
||||
{
|
||||
if (edgeGhostWindow) {
|
||||
@ -750,235 +745,6 @@ void VisibilityManager::cleanupFaultyWindows()
|
||||
}
|
||||
}
|
||||
|
||||
//! Dynamic Background functions
|
||||
bool VisibilityManager::enabledDynamicBackground() const
|
||||
{
|
||||
return enabledDynamicBackgroundFlag;
|
||||
}
|
||||
|
||||
void VisibilityManager::setEnabledDynamicBackground(bool active)
|
||||
{
|
||||
if (enabledDynamicBackgroundFlag == active) {
|
||||
return;
|
||||
}
|
||||
|
||||
enabledDynamicBackgroundFlag = active;
|
||||
|
||||
if (active) {
|
||||
if (m_mode != Types::DodgeAllWindows) {
|
||||
for (const auto &wid : wm->windows()) {
|
||||
windows.insert(wid, wm->requestInfo(wid));
|
||||
}
|
||||
}
|
||||
|
||||
connectionsDynBackground[0] = connect(m_latteView->corona(), &Plasma::Corona::availableScreenRectChanged,
|
||||
this, &VisibilityManager::updateAvailableScreenGeometry);
|
||||
|
||||
connectionsDynBackground[1] = connect(wm, &WindowSystem::windowChanged, this, [&](WindowId wid) {
|
||||
windows[wid] = wm->requestInfo(wid);
|
||||
updateDynamicBackgroundWindowFlags();
|
||||
});
|
||||
|
||||
connectionsDynBackground[2] = connect(wm, &WindowSystem::windowRemoved, this, [&](WindowId wid) {
|
||||
windows.remove(wid);
|
||||
});
|
||||
|
||||
connectionsDynBackground[3] = connect(wm, &WindowSystem::windowAdded, this, [&](WindowId wid) {
|
||||
windows.insert(wid, wm->requestInfo(wid));
|
||||
updateDynamicBackgroundWindowFlags();
|
||||
});
|
||||
|
||||
connectionsDynBackground[4] = connect(wm, &WindowSystem::activeWindowChanged, this, [&](WindowId wid) {
|
||||
if (windows.contains(lastActiveWindowWid)) {
|
||||
windows[lastActiveWindowWid] = wm->requestInfo(lastActiveWindowWid);
|
||||
}
|
||||
|
||||
windows[wid] = wm->requestInfo(wid);
|
||||
lastActiveWindowWid = wid;
|
||||
|
||||
updateDynamicBackgroundWindowFlags();
|
||||
});
|
||||
|
||||
connectionsDynBackground[5] = connect(wm, &WindowSystem::currentDesktopChanged, this, [&] {
|
||||
updateDynamicBackgroundWindowFlags();
|
||||
});
|
||||
|
||||
connectionsDynBackground[6] = connect(wm, &WindowSystem::currentActivityChanged, this, [&] {
|
||||
updateDynamicBackgroundWindowFlags();
|
||||
});
|
||||
|
||||
updateAvailableScreenGeometry();
|
||||
updateDynamicBackgroundWindowFlags();
|
||||
} else {
|
||||
// clear mode
|
||||
for (auto &c : connectionsDynBackground) {
|
||||
disconnect(c);
|
||||
}
|
||||
|
||||
if (m_mode != Types::DodgeAllWindows) {
|
||||
windows.clear();
|
||||
}
|
||||
|
||||
// ATTENTION: this was creating a crash under wayland environment through the blur effect
|
||||
// setExistsWindowMaximized(false);
|
||||
// setExistsWindowTouching(false);
|
||||
}
|
||||
|
||||
emit enabledDynamicBackgroundChanged();
|
||||
}
|
||||
|
||||
bool VisibilityManager::existsWindowMaximized() const
|
||||
{
|
||||
return windowIsMaximizedFlag;
|
||||
}
|
||||
|
||||
void VisibilityManager::setExistsWindowMaximized(bool windowMaximized)
|
||||
{
|
||||
if (windowIsMaximizedFlag == windowMaximized) {
|
||||
return;
|
||||
}
|
||||
|
||||
windowIsMaximizedFlag = windowMaximized;
|
||||
|
||||
emit existsWindowMaximizedChanged();
|
||||
}
|
||||
|
||||
bool VisibilityManager::existsWindowTouching() const
|
||||
{
|
||||
return windowIsTouchingFlag;
|
||||
}
|
||||
|
||||
void VisibilityManager::setExistsWindowTouching(bool windowTouching)
|
||||
{
|
||||
if (windowIsTouchingFlag == windowTouching) {
|
||||
return;
|
||||
}
|
||||
|
||||
windowIsTouchingFlag = windowTouching;
|
||||
|
||||
emit existsWindowTouchingChanged();
|
||||
}
|
||||
|
||||
SchemeColors *VisibilityManager::touchingWindowScheme() const
|
||||
{
|
||||
return touchingScheme;
|
||||
}
|
||||
|
||||
void VisibilityManager::setTouchingWindowScheme(SchemeColors *scheme)
|
||||
{
|
||||
if (touchingScheme == scheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
touchingScheme = scheme;
|
||||
|
||||
emit touchingWindowSchemeChanged();
|
||||
}
|
||||
|
||||
void VisibilityManager::updateAvailableScreenGeometry()
|
||||
{
|
||||
if (!m_latteView || !m_latteView->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int currentScrId = m_latteView->positioner()->currentScreenId();
|
||||
QRect tempAvailableScreenGeometry = m_corona->availableScreenRectWithCriteria(currentScrId, {Types::AlwaysVisible}, {});
|
||||
|
||||
if (tempAvailableScreenGeometry != availableScreenGeometry) {
|
||||
availableScreenGeometry = tempAvailableScreenGeometry;
|
||||
|
||||
updateDynamicBackgroundWindowFlags();
|
||||
}
|
||||
}
|
||||
|
||||
bool VisibilityManager::isMaximizedInCurrentScreen(const WindowInfoWrap &winfo)
|
||||
{
|
||||
//! updated implementation to identify the screen that the maximized window is present
|
||||
//! in order to avoid: https://bugs.kde.org/show_bug.cgi?id=397700
|
||||
|
||||
if (winfo.isValid() && !winfo.isMinimized() && wm->isOnCurrentDesktop(winfo.wid()) && wm->isOnCurrentActivity(winfo.wid())) {
|
||||
if (winfo.isMaximized() && availableScreenGeometry.contains(winfo.geometry().center())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VisibilityManager::isTouchingPanelEdge(const WindowInfoWrap &winfo)
|
||||
{
|
||||
if (winfo.isValid() && !winfo.isMinimized() && wm->isOnCurrentDesktop(winfo.wid()) && wm->isOnCurrentActivity(winfo.wid())) {
|
||||
bool touchingPanelEdge{false};
|
||||
|
||||
QRect screenGeometry = m_latteView->screenGeometry();
|
||||
bool inCurrentScreen{screenGeometry.contains(winfo.geometry().topLeft()) || screenGeometry.contains(winfo.geometry().bottomRight())};
|
||||
|
||||
if (inCurrentScreen) {
|
||||
if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().y() == availableScreenGeometry.y());
|
||||
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().bottom() == availableScreenGeometry.bottom());
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().x() == availableScreenGeometry.x());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().right() == availableScreenGeometry.right());
|
||||
}
|
||||
}
|
||||
|
||||
return touchingPanelEdge;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void VisibilityManager::updateDynamicBackgroundWindowFlags()
|
||||
{
|
||||
bool foundTouch{false};
|
||||
bool foundMaximized{false};
|
||||
|
||||
//! the notification window is not sending a remove signal and creates windows of geometry (0x0 0,0),
|
||||
//! maybe a garbage collector here is a good idea!!!
|
||||
bool existsFaultyWindow{false};
|
||||
WindowId maxWinId;
|
||||
WindowId touchWinId;
|
||||
|
||||
for (const auto &winfo : windows) {
|
||||
if (isMaximizedInCurrentScreen(winfo)) {
|
||||
foundMaximized = true;
|
||||
maxWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (winfo.isActive() && (isTouchingPanelEdge(winfo) || (intersects(winfo)))) {
|
||||
foundTouch = true;
|
||||
touchWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (!existsFaultyWindow && winfo.geometry() == QRect(0, 0, 0, 0)) {
|
||||
existsFaultyWindow = true;
|
||||
}
|
||||
|
||||
//qDebug() << "window geometry ::: " << winfo.geometry();
|
||||
}
|
||||
|
||||
if (existsFaultyWindow) {
|
||||
cleanupFaultyWindows();
|
||||
}
|
||||
|
||||
setExistsWindowMaximized(foundMaximized);
|
||||
setExistsWindowTouching(foundTouch);
|
||||
|
||||
//! update color scheme for touching window
|
||||
|
||||
if (foundTouch) {
|
||||
//! first the touching one because that would mean it is active
|
||||
setTouchingWindowScheme(wm->schemeForWindow(touchWinId));
|
||||
} else if (foundMaximized) {
|
||||
setTouchingWindowScheme(wm->schemeForWindow(maxWinId));
|
||||
} else {
|
||||
setTouchingWindowScheme(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
//! KWin Edges Support functions
|
||||
bool VisibilityManager::enableKWinEdges() const
|
||||
{
|
||||
@ -1062,50 +828,6 @@ void VisibilityManager::deleteEdgeGhostWindow()
|
||||
}
|
||||
}
|
||||
|
||||
//! Window Functions
|
||||
void VisibilityManager::requestToggleMaximizeForActiveWindow()
|
||||
{
|
||||
WindowInfoWrap actInfo = wm->requestInfoActive();
|
||||
|
||||
//active window can be toggled only when it is in the same screen
|
||||
if (actInfo.isValid() && !actInfo.geometry().isNull() && m_latteView->screenGeometry().contains(actInfo.geometry().center())) {
|
||||
wm->requestToggleMaximized(actInfo.wid());
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityManager::requestMoveActiveWindow(int localX, int localY)
|
||||
{
|
||||
WindowInfoWrap actInfo = wm->requestInfoActive();
|
||||
|
||||
//active window can be dragged only when it is in the same screen
|
||||
if (actInfo.isValid() && !actInfo.geometry().isNull() && m_latteView->screenGeometry().contains(actInfo.geometry().center())) {
|
||||
QPoint globalPoint{m_latteView->x() + localX, m_latteView->y() + localY};
|
||||
|
||||
wm->requestMoveWindow(actInfo.wid(), globalPoint);
|
||||
|
||||
//! This timer is needed because otherwise the mouse position
|
||||
//! in the dragged window changes to TopLeft corner
|
||||
QTimer::singleShot(250, this, [&, actInfo, globalPoint]() {
|
||||
wm->releaseMouseEventFor(m_latteView->winId());
|
||||
});
|
||||
|
||||
setContainsMouse(false);
|
||||
updateHiddenState();
|
||||
}
|
||||
}
|
||||
|
||||
bool VisibilityManager::activeWindowCanBeDragged()
|
||||
{
|
||||
WindowInfoWrap actInfo = wm->requestInfoActive();
|
||||
|
||||
//active window can be dragged only when it is in the same screen
|
||||
if (actInfo.isValid() && !actInfo.geometry().isNull() && m_latteView->screenGeometry().contains(actInfo.geometry().center())) {
|
||||
return wm->windowCanBeDragged(actInfo.wid());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! END: VisibilityManager implementation
|
||||
|
||||
}
|
||||
|
@ -57,12 +57,6 @@ class VisibilityManager : public QObject
|
||||
Q_PROPERTY(bool blockHiding READ blockHiding WRITE setBlockHiding NOTIFY blockHidingChanged)
|
||||
Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
|
||||
|
||||
//! Dynamic Background Feature (needed options)
|
||||
Q_PROPERTY(bool enabledDynamicBackground READ enabledDynamicBackground WRITE setEnabledDynamicBackground NOTIFY enabledDynamicBackgroundChanged)
|
||||
Q_PROPERTY(bool existsWindowMaximized READ existsWindowMaximized NOTIFY existsWindowMaximizedChanged)
|
||||
Q_PROPERTY(bool existsWindowTouching READ existsWindowTouching NOTIFY existsWindowTouchingChanged)
|
||||
Q_PROPERTY(SchemeColors *touchingWindowScheme READ touchingWindowScheme NOTIFY touchingWindowSchemeChanged)
|
||||
|
||||
//! KWin Edges Support Options
|
||||
Q_PROPERTY(bool enableKWinEdges READ enableKWinEdges WRITE setEnableKWinEdges NOTIFY enableKWinEdgesChanged)
|
||||
Q_PROPERTY(bool supportsKWinEdges READ supportsKWinEdges NOTIFY supportsKWinEdgesChanged)
|
||||
@ -77,7 +71,6 @@ public:
|
||||
Latte::Types::Visibility mode() const;
|
||||
void setMode(Latte::Types::Visibility mode);
|
||||
|
||||
void setWindowOnActivities(QWindow &window, const QStringList &activities);
|
||||
void applyActivitiesToHiddenWindows(const QStringList &activities);
|
||||
|
||||
bool raiseOnDesktop() const;
|
||||
@ -100,14 +93,7 @@ public:
|
||||
int timerHide() const;
|
||||
void setTimerHide(int msec);
|
||||
|
||||
//! Dynamic Background functions
|
||||
bool enabledDynamicBackground() const;
|
||||
void setEnabledDynamicBackground(bool active);
|
||||
|
||||
bool existsWindowMaximized() const;
|
||||
bool existsWindowTouching() const;
|
||||
|
||||
SchemeColors *touchingWindowScheme() const;
|
||||
bool intersects(const WindowInfoWrap &winfo);
|
||||
|
||||
//! KWin Edges Support functions
|
||||
bool enableKWinEdges() const;
|
||||
@ -115,11 +101,6 @@ public:
|
||||
|
||||
bool supportsKWinEdges() const;
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE void requestToggleMaximizeForActiveWindow();
|
||||
Q_INVOKABLE void requestMoveActiveWindow(int localX, int localY);
|
||||
Q_INVOKABLE bool activeWindowCanBeDragged();
|
||||
|
||||
signals:
|
||||
void mustBeShown();
|
||||
void mustBeHide();
|
||||
@ -134,11 +115,6 @@ signals:
|
||||
void timerHideChanged();
|
||||
void touchingWindowSchemeChanged();
|
||||
|
||||
//! Dynamic Background signals (from options)
|
||||
void enabledDynamicBackgroundChanged();
|
||||
void existsWindowMaximizedChanged();
|
||||
void existsWindowTouchingChanged();
|
||||
|
||||
//! KWin Edges Support signals
|
||||
void enableKWinEdgesChanged();
|
||||
void supportsKWinEdgesChanged();
|
||||
@ -158,13 +134,6 @@ private:
|
||||
//! this is a garbage collector to collect such windows in order to not break the windows array validity.
|
||||
void cleanupFaultyWindows();
|
||||
|
||||
//! Dynamic Background Feature
|
||||
void setExistsWindowMaximized(bool windowMaximized);
|
||||
void setExistsWindowTouching(bool windowTouching);
|
||||
void setTouchingWindowScheme(SchemeColors *scheme);
|
||||
void updateAvailableScreenGeometry();
|
||||
void updateDynamicBackgroundWindowFlags();
|
||||
|
||||
//! KWin Edges Support functions
|
||||
void createEdgeGhostWindow();
|
||||
void deleteEdgeGhostWindow();
|
||||
@ -178,10 +147,6 @@ private:
|
||||
void dodgeWindows(WindowId id);
|
||||
void checkAllWindows();
|
||||
|
||||
bool intersects(const WindowInfoWrap &winfo);
|
||||
bool isMaximizedInCurrentScreen(const WindowInfoWrap &winfo);
|
||||
bool isTouchingPanelEdge(const WindowInfoWrap &winfo);
|
||||
|
||||
void updateStrutsBasedOnLayoutsAndActivities();
|
||||
void viewEventManager(QEvent *ev);
|
||||
|
||||
@ -205,16 +170,6 @@ private:
|
||||
bool raiseOnActivityChange{false};
|
||||
bool hideNow{false};
|
||||
|
||||
//! Dynamic Background flags and needed information
|
||||
bool enabledDynamicBackgroundFlag{false};
|
||||
bool windowIsTouchingFlag{false};
|
||||
bool windowIsMaximizedFlag{false};
|
||||
QRect availableScreenGeometry;
|
||||
std::array<QMetaObject::Connection, 7> connectionsDynBackground;
|
||||
WindowId lastActiveWindowWid;
|
||||
SchemeColors *touchingScheme{nullptr};
|
||||
|
||||
|
||||
//! KWin Edges
|
||||
bool enableKWinEdgesFromUser{true};
|
||||
std::array<QMetaObject::Connection, 1> connectionsKWinEdges;
|
||||
|
331
app/view/windowstracker.cpp
Normal file
331
app/view/windowstracker.cpp
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright 2019 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/>.
|
||||
*/
|
||||
|
||||
#include "windowstracker.h"
|
||||
|
||||
// local
|
||||
#include "positioner.h"
|
||||
#include "view.h"
|
||||
#include "../lattecorona.h"
|
||||
#include "../../liblatte2/types.h"
|
||||
|
||||
namespace Latte {
|
||||
namespace ViewPart {
|
||||
|
||||
WindowsTracker::WindowsTracker(Latte::View *parent)
|
||||
: QObject(parent),
|
||||
m_latteView(parent)
|
||||
{
|
||||
qDebug() << "WindowsTracker creating...";
|
||||
|
||||
m_corona = qobject_cast<Latte::Corona *>(m_latteView->corona());
|
||||
m_wm = m_corona->wm();
|
||||
}
|
||||
|
||||
WindowsTracker::~WindowsTracker()
|
||||
{
|
||||
qDebug() << "WindowsTracker removing...";
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowMaximized() const
|
||||
{
|
||||
return m_windowIsMaximizedFlag;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowMaximized(bool windowMaximized)
|
||||
{
|
||||
if (m_windowIsMaximizedFlag == windowMaximized) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_windowIsMaximizedFlag = windowMaximized;
|
||||
|
||||
emit existsWindowMaximizedChanged();
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowTouching() const
|
||||
{
|
||||
return m_windowIsTouchingFlag;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowTouching(bool windowTouching)
|
||||
{
|
||||
if (m_windowIsTouchingFlag == windowTouching) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_windowIsTouchingFlag = windowTouching;
|
||||
|
||||
emit existsWindowTouchingChanged();
|
||||
}
|
||||
|
||||
SchemeColors *WindowsTracker::touchingWindowScheme() const
|
||||
{
|
||||
return m_touchingScheme;
|
||||
}
|
||||
|
||||
void WindowsTracker::setTouchingWindowScheme(SchemeColors *scheme)
|
||||
{
|
||||
if (m_touchingScheme == scheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_touchingScheme = scheme;
|
||||
|
||||
emit touchingWindowSchemeChanged();
|
||||
}
|
||||
|
||||
bool WindowsTracker::enabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void WindowsTracker::setEnabled(bool active)
|
||||
{
|
||||
if (m_enabled == active) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_enabled = active;
|
||||
|
||||
if (m_enabled) {
|
||||
m_windows.clear();
|
||||
|
||||
for (const auto &wid : m_wm->windows()) {
|
||||
m_windows.insert(wid, m_wm->requestInfo(wid));
|
||||
}
|
||||
|
||||
m_connections[0] = connect(m_corona, &Plasma::Corona::availableScreenRectChanged,
|
||||
this, &WindowsTracker::updateAvailableScreenGeometry);
|
||||
|
||||
m_connections[1] = connect(m_wm, &WindowSystem::windowChanged, this, [&](WindowId wid) {
|
||||
m_windows[wid] = m_wm->requestInfo(wid);
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[2] = connect(m_wm, &WindowSystem::windowRemoved, this, [&](WindowId wid) {
|
||||
m_windows.remove(wid);
|
||||
});
|
||||
|
||||
m_connections[3] = connect(m_wm, &WindowSystem::windowAdded, this, [&](WindowId wid) {
|
||||
m_windows.insert(wid, m_wm->requestInfo(wid));
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[4] = connect(m_wm, &WindowSystem::activeWindowChanged, this, [&](WindowId wid) {
|
||||
if (m_windows.contains(m_lastActiveWindowWid)) {
|
||||
m_windows[m_lastActiveWindowWid] = m_wm->requestInfo(m_lastActiveWindowWid);
|
||||
}
|
||||
|
||||
m_windows[wid] = m_wm->requestInfo(wid);
|
||||
m_lastActiveWindowWid = wid;
|
||||
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[5] = connect(m_wm, &WindowSystem::currentDesktopChanged, this, [&] {
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[6] = connect(m_wm, &WindowSystem::currentActivityChanged, this, [&] {
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
updateAvailableScreenGeometry();
|
||||
updateFlags();
|
||||
} else {
|
||||
// clear mode
|
||||
for (auto &c : m_connections) {
|
||||
disconnect(c);
|
||||
}
|
||||
|
||||
m_windows.clear();
|
||||
}
|
||||
|
||||
emit enabledChanged();
|
||||
}
|
||||
|
||||
void WindowsTracker::updateAvailableScreenGeometry()
|
||||
{
|
||||
if (!m_latteView || !m_latteView->containment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int currentScrId = m_latteView->positioner()->currentScreenId();
|
||||
QRect tempAvailableScreenGeometry = m_corona->availableScreenRectWithCriteria(currentScrId, {Types::AlwaysVisible}, {});
|
||||
|
||||
if (tempAvailableScreenGeometry != m_availableScreenGeometry) {
|
||||
m_availableScreenGeometry = tempAvailableScreenGeometry;
|
||||
|
||||
updateFlags();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsTracker::updateFlags()
|
||||
{
|
||||
bool foundTouch{false};
|
||||
bool foundMaximized{false};
|
||||
|
||||
//! the notification window is not sending a remove signal and creates windows of geometry (0x0 0,0),
|
||||
//! maybe a garbage collector here is a good idea!!!
|
||||
bool existsFaultyWindow{false};
|
||||
WindowId maxWinId;
|
||||
WindowId touchWinId;
|
||||
|
||||
for (const auto &winfo : m_windows) {
|
||||
if (isMaximizedInCurrentScreen(winfo)) {
|
||||
foundMaximized = true;
|
||||
maxWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (winfo.isActive() && (isTouchingPanelEdge(winfo) || (m_latteView->visibility()->intersects(winfo)))) {
|
||||
foundTouch = true;
|
||||
touchWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (!existsFaultyWindow && winfo.geometry() == QRect(0, 0, 0, 0)) {
|
||||
existsFaultyWindow = true;
|
||||
}
|
||||
|
||||
//qDebug() << "window geometry ::: " << winfo.geometry();
|
||||
}
|
||||
|
||||
if (existsFaultyWindow) {
|
||||
cleanupFaultyWindows();
|
||||
}
|
||||
|
||||
setExistsWindowMaximized(foundMaximized);
|
||||
setExistsWindowTouching(foundTouch);
|
||||
|
||||
//! update color scheme for touching window
|
||||
|
||||
if (foundTouch) {
|
||||
//! first the touching one because that would mean it is active
|
||||
setTouchingWindowScheme(m_wm->schemeForWindow(touchWinId));
|
||||
} else if (foundMaximized) {
|
||||
setTouchingWindowScheme(m_wm->schemeForWindow(maxWinId));
|
||||
} else {
|
||||
setTouchingWindowScheme(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsTracker::isMaximizedInCurrentScreen(const WindowInfoWrap &winfo)
|
||||
{
|
||||
//! updated implementation to identify the screen that the maximized window is present
|
||||
//! in order to avoid: https://bugs.kde.org/show_bug.cgi?id=397700
|
||||
|
||||
if (winfo.isValid() && !winfo.isMinimized() && m_wm->isOnCurrentDesktop(winfo.wid()) && m_wm->isOnCurrentActivity(winfo.wid())) {
|
||||
if (winfo.isMaximized() && m_availableScreenGeometry.contains(winfo.geometry().center())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WindowsTracker::isTouchingPanelEdge(const WindowInfoWrap &winfo)
|
||||
{
|
||||
if (winfo.isValid() && !winfo.isMinimized() && m_wm->isOnCurrentDesktop(winfo.wid()) && m_wm->isOnCurrentActivity(winfo.wid())) {
|
||||
bool touchingPanelEdge{false};
|
||||
|
||||
QRect screenGeometry = m_latteView->screenGeometry();
|
||||
bool inCurrentScreen{screenGeometry.contains(winfo.geometry().topLeft()) || screenGeometry.contains(winfo.geometry().bottomRight())};
|
||||
|
||||
if (inCurrentScreen) {
|
||||
if (m_latteView->location() == Plasma::Types::TopEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().y() == m_availableScreenGeometry.y());
|
||||
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().bottom() == m_availableScreenGeometry.bottom());
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().x() == m_availableScreenGeometry.x());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
touchingPanelEdge = (winfo.geometry().right() == m_availableScreenGeometry.right());
|
||||
}
|
||||
}
|
||||
|
||||
return touchingPanelEdge;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WindowsTracker::cleanupFaultyWindows()
|
||||
{
|
||||
foreach (auto key, m_windows.keys()) {
|
||||
auto winfo = m_windows[key];
|
||||
|
||||
//! garbage windows removing
|
||||
if (winfo.geometry() == QRect(0, 0, 0, 0)) {
|
||||
//qDebug() << "Faulty Geometry ::: " << winfo.wid();
|
||||
m_windows.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Window Functions
|
||||
void WindowsTracker::setWindowOnActivities(QWindow &window, const QStringList &activities)
|
||||
{
|
||||
m_wm->setWindowOnActivities(window, activities);
|
||||
}
|
||||
|
||||
void WindowsTracker::requestToggleMaximizeForActiveWindow()
|
||||
{
|
||||
WindowInfoWrap actInfo = m_wm->requestInfoActive();
|
||||
|
||||
//active window can be toggled only when it is in the same screen
|
||||
if (actInfo.isValid() && !actInfo.geometry().isNull() && m_latteView->screenGeometry().contains(actInfo.geometry().center())) {
|
||||
m_wm->requestToggleMaximized(actInfo.wid());
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsTracker::requestMoveActiveWindow(int localX, int localY)
|
||||
{
|
||||
WindowInfoWrap actInfo = m_wm->requestInfoActive();
|
||||
|
||||
//active window can be dragged only when it is in the same screen
|
||||
if (actInfo.isValid() && !actInfo.geometry().isNull() && m_latteView->screenGeometry().contains(actInfo.geometry().center())) {
|
||||
QPoint globalPoint{m_latteView->x() + localX, m_latteView->y() + localY};
|
||||
|
||||
m_wm->requestMoveWindow(actInfo.wid(), globalPoint);
|
||||
|
||||
//! This timer is needed because otherwise the mouse position
|
||||
//! in the dragged window changes to TopLeft corner
|
||||
QTimer::singleShot(250, this, [&, actInfo, globalPoint]() {
|
||||
m_wm->releaseMouseEventFor(m_latteView->winId());
|
||||
});
|
||||
|
||||
// setContainsMouse(false);
|
||||
// updateHiddenState();
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsTracker::activeWindowCanBeDragged()
|
||||
{
|
||||
WindowInfoWrap actInfo = m_wm->requestInfoActive();
|
||||
|
||||
//active window can be dragged only when it is in the same screen
|
||||
if (actInfo.isValid() && !actInfo.geometry().isNull() && m_latteView->screenGeometry().contains(actInfo.geometry().center())) {
|
||||
return m_wm->windowCanBeDragged(actInfo.wid());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
108
app/view/windowstracker.h
Normal file
108
app/view/windowstracker.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2019 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/>.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWSTRACKER_H
|
||||
#define WINDOWSTRACKER_H
|
||||
|
||||
// local
|
||||
#include "../schemecolors.h"
|
||||
#include "../wm/abstractwindowinterface.h"
|
||||
#include "../wm/windowinfowrap.h"
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
namespace Latte{
|
||||
class AbstractWindowInterface;
|
||||
class Corona;
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace Latte {
|
||||
namespace ViewPart {
|
||||
|
||||
class WindowsTracker : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
Q_PROPERTY(bool existsWindowMaximized READ existsWindowMaximized NOTIFY existsWindowMaximizedChanged)
|
||||
Q_PROPERTY(bool existsWindowTouching READ existsWindowTouching NOTIFY existsWindowTouchingChanged)
|
||||
Q_PROPERTY(SchemeColors *touchingWindowScheme READ touchingWindowScheme NOTIFY touchingWindowSchemeChanged)
|
||||
|
||||
public:
|
||||
explicit WindowsTracker(Latte::View *parent);
|
||||
virtual ~WindowsTracker();
|
||||
|
||||
bool enabled() const;
|
||||
void setEnabled(bool active);
|
||||
|
||||
bool existsWindowMaximized() const;
|
||||
bool existsWindowTouching() const;
|
||||
|
||||
SchemeColors *touchingWindowScheme() const;
|
||||
|
||||
void setWindowOnActivities(QWindow &window, const QStringList &activities);
|
||||
|
||||
signals:
|
||||
void enabledChanged();
|
||||
void existsWindowMaximizedChanged();
|
||||
void existsWindowTouchingChanged();
|
||||
void touchingWindowSchemeChanged();
|
||||
|
||||
public slots:
|
||||
Q_INVOKABLE void requestToggleMaximizeForActiveWindow();
|
||||
Q_INVOKABLE void requestMoveActiveWindow(int localX, int localY);
|
||||
Q_INVOKABLE bool activeWindowCanBeDragged();
|
||||
|
||||
private:
|
||||
void setExistsWindowMaximized(bool windowMaximized);
|
||||
void setExistsWindowTouching(bool windowTouching);
|
||||
void setTouchingWindowScheme(SchemeColors *scheme);
|
||||
void updateAvailableScreenGeometry();
|
||||
void updateFlags();
|
||||
|
||||
//! the notification window is not sending a remove signal and creates windows of geometry (0x0 0,0),
|
||||
//! this is a garbage collector to collect such windows in order to not break the windows array validity.
|
||||
void cleanupFaultyWindows();
|
||||
|
||||
bool isMaximizedInCurrentScreen(const WindowInfoWrap &winfo);
|
||||
bool isTouchingPanelEdge(const WindowInfoWrap &winfo);
|
||||
|
||||
private:
|
||||
bool m_enabled{false};
|
||||
bool m_windowIsTouchingFlag{false};
|
||||
bool m_windowIsMaximizedFlag{false};
|
||||
|
||||
QRect m_availableScreenGeometry;
|
||||
|
||||
WindowId m_lastActiveWindowWid;
|
||||
|
||||
std::array<QMetaObject::Connection, 7> m_connections;
|
||||
QMap<WindowId, WindowInfoWrap> m_windows;
|
||||
|
||||
SchemeColors *m_touchingScheme{nullptr};
|
||||
|
||||
Latte::AbstractWindowInterface *m_wm;
|
||||
Latte::Corona *m_corona{nullptr};
|
||||
Latte::View *m_latteView{nullptr};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user