mirror of
https://github.com/KDE/latte-dock.git
synced 2024-12-24 17:33:50 +03:00
REFACTOR:Introduce WM:WindowsTracker
--this is a single and very important class that handles all windows tracking and management for ALL VIEWS at ALL ACTIVE LAYOUTS
This commit is contained in:
parent
945c6e50e2
commit
a5168c3a2a
@ -25,6 +25,7 @@
|
||||
#include "../lattecorona.h"
|
||||
#include "../layouts/manager.h"
|
||||
#include "../wm/schemecolors.h"
|
||||
#include "../wm/windowstracker.h"
|
||||
#include "../../liblatte2/types.h"
|
||||
|
||||
namespace Latte {
|
||||
@ -38,395 +39,113 @@ WindowsTracker::WindowsTracker(Latte::View *parent)
|
||||
|
||||
m_corona = qobject_cast<Latte::Corona *>(m_latteView->corona());
|
||||
m_wm = m_corona->wm();
|
||||
|
||||
init();
|
||||
m_wm->windowsTracker()->addView(m_latteView);
|
||||
}
|
||||
|
||||
WindowsTracker::~WindowsTracker()
|
||||
{
|
||||
qDebug() << "WindowsTracker removing...";
|
||||
m_wm->windowsTracker()->removeView(m_latteView);
|
||||
}
|
||||
|
||||
void WindowsTracker::init()
|
||||
{
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::enabledChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit enabledChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::activeWindowMaximizedChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit activeWindowMaximizedChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::activeWindowTouchingChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit activeWindowTouchingChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::existsWindowActiveChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit existsWindowActiveChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::existsWindowMaximizedChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit existsWindowMaximizedChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::existsWindowTouchingChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit existsWindowTouchingChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::activeWindowSchemeChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit activeWindowSchemeChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_wm->windowsTracker(), &WindowSystem::WindowsTracker::touchingWindowSchemeChanged, this, [&](const Latte::View *view) {
|
||||
if (m_latteView == view) {
|
||||
emit touchingWindowSchemeChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool WindowsTracker::activeWindowMaximized() const
|
||||
{
|
||||
return m_activeWindowIsMaximizedFlag;
|
||||
}
|
||||
|
||||
void WindowsTracker::setActiveWindowMaximized(bool activeMaximized)
|
||||
{
|
||||
if (m_activeWindowIsMaximizedFlag == activeMaximized) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_activeWindowIsMaximizedFlag = activeMaximized;
|
||||
emit activeWindowMaximizedChanged();
|
||||
return m_wm->windowsTracker()->activeWindowMaximized(m_latteView);
|
||||
}
|
||||
|
||||
bool WindowsTracker::activeWindowTouching() const
|
||||
{
|
||||
return m_activeWindowIsTouchingFlag;
|
||||
}
|
||||
|
||||
void WindowsTracker::setActiveWindowTouching(bool activeTouching)
|
||||
{
|
||||
if (m_activeWindowIsTouchingFlag == activeTouching) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_activeWindowIsTouchingFlag = activeTouching;
|
||||
emit activeWindowTouchingChanged();
|
||||
return m_wm->windowsTracker()->activeWindowTouching(m_latteView);
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowActive() const
|
||||
{
|
||||
return m_windowIsActiveFlag;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowActive(bool windowActive)
|
||||
{
|
||||
if (m_windowIsActiveFlag == windowActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_windowIsActiveFlag = windowActive;
|
||||
emit existsWindowActiveChanged();
|
||||
return m_wm->windowsTracker()->existsWindowActive(m_latteView);
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowMaximized() const
|
||||
{
|
||||
return m_windowIsMaximizedFlag;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowMaximized(bool windowMaximized)
|
||||
{
|
||||
if (m_windowIsMaximizedFlag == windowMaximized) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_windowIsMaximizedFlag = windowMaximized;
|
||||
emit existsWindowMaximizedChanged();
|
||||
return m_wm->windowsTracker()->existsWindowMaximized(m_latteView);
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowTouching() const
|
||||
{
|
||||
return m_windowIsTouchingFlag;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowTouching(bool windowTouching)
|
||||
{
|
||||
if (m_windowIsTouchingFlag == windowTouching) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_windowIsTouchingFlag = windowTouching;
|
||||
emit existsWindowTouchingChanged();
|
||||
return m_wm->windowsTracker()->existsWindowTouching(m_latteView);
|
||||
}
|
||||
|
||||
WindowSystem::SchemeColors *WindowsTracker::activeWindowScheme() const
|
||||
{
|
||||
return m_activeScheme;
|
||||
}
|
||||
|
||||
void WindowsTracker::setActiveWindowScheme(WindowSystem::SchemeColors *scheme)
|
||||
{
|
||||
if (m_activeScheme == scheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_activeScheme = scheme;
|
||||
|
||||
emit activeWindowSchemeChanged();
|
||||
return m_wm->windowsTracker()->activeWindowScheme(m_latteView);
|
||||
}
|
||||
|
||||
WindowSystem::SchemeColors *WindowsTracker::touchingWindowScheme() const
|
||||
{
|
||||
return m_touchingScheme;
|
||||
}
|
||||
|
||||
void WindowsTracker::setTouchingWindowScheme(WindowSystem::SchemeColors *scheme)
|
||||
{
|
||||
if (m_touchingScheme == scheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_touchingScheme = scheme;
|
||||
|
||||
emit touchingWindowSchemeChanged();
|
||||
return m_wm->windowsTracker()->touchingWindowScheme(m_latteView);
|
||||
}
|
||||
|
||||
bool WindowsTracker::enabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
return m_wm->windowsTracker()->enabled(m_latteView);
|
||||
}
|
||||
|
||||
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::AbstractWindowInterface::windowChanged, this, [&](WindowSystem::WindowId wid) {
|
||||
m_windows[wid] = m_wm->requestInfo(wid);
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[2] = connect(m_wm, &WindowSystem::AbstractWindowInterface::windowRemoved, this, [&](WindowSystem::WindowId wid) {
|
||||
m_windows.remove(wid);
|
||||
});
|
||||
|
||||
m_connections[3] = connect(m_wm, &WindowSystem::AbstractWindowInterface::windowAdded, this, [&](WindowSystem::WindowId wid) {
|
||||
m_windows.insert(wid, m_wm->requestInfo(wid));
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[4] = connect(m_wm, &WindowSystem::AbstractWindowInterface::activeWindowChanged, this, [&](WindowSystem::WindowId wid) {
|
||||
if (m_windows.contains(m_lastActiveWindowWid)) {
|
||||
m_windows[m_lastActiveWindowWid] = m_wm->requestInfo(m_lastActiveWindowWid);
|
||||
}
|
||||
|
||||
m_windows[wid] = m_wm->requestInfo(wid);
|
||||
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[5] = connect(m_wm, &WindowSystem::AbstractWindowInterface::currentDesktopChanged, this, [&] {
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
m_connections[6] = connect(m_wm, &WindowSystem::AbstractWindowInterface::currentActivityChanged, this, [&] {
|
||||
if (m_corona->layoutsManager()->memoryUsage() == Types::MultipleLayouts) {
|
||||
//! this is needed in MultipleLayouts because there is a chance that multiple
|
||||
//! layouts are providing different available screen geometries in different Activities
|
||||
updateAvailableScreenGeometry();
|
||||
}
|
||||
|
||||
updateFlags();
|
||||
});
|
||||
|
||||
updateAvailableScreenGeometry();
|
||||
updateFlags();
|
||||
} else {
|
||||
// clear mode
|
||||
for (auto &c : m_connections) {
|
||||
disconnect(c);
|
||||
}
|
||||
|
||||
m_windows.clear();
|
||||
|
||||
setActiveWindowTouching(false);
|
||||
setExistsWindowMaximized(false);
|
||||
setExistsWindowTouching(false);
|
||||
}
|
||||
|
||||
emit enabledChanged();
|
||||
m_wm->windowsTracker()->setEnabled(m_latteView, active);
|
||||
}
|
||||
|
||||
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 foundActive{false};
|
||||
bool foundActiveInCurScreen{false};
|
||||
bool foundActiveTouchInCurScreen{false};
|
||||
bool foundTouchInCurScreen{false};
|
||||
bool foundMaximizedInCurScreen{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};
|
||||
|
||||
WindowSystem::WindowId maxWinId;
|
||||
WindowSystem::WindowId activeWinId;
|
||||
WindowSystem::WindowId touchWinId;
|
||||
WindowSystem::WindowId activeTouchWinId;
|
||||
|
||||
for (const auto &winfo : m_windows) {
|
||||
if (winfo.isPlasmaDesktop() || !inCurrentDesktopActivity(winfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isActive(winfo)) {
|
||||
foundActive = true;
|
||||
m_lastActiveWindowWid = winfo.wid();
|
||||
}
|
||||
|
||||
if (isActiveInCurrentScreen(winfo)) {
|
||||
foundActiveInCurScreen = true;
|
||||
activeWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (isTouchingViewEdge(winfo) || isTouchingView(winfo)) {
|
||||
if (winfo.isActive()) {
|
||||
foundActiveTouchInCurScreen = true;
|
||||
activeTouchWinId = winfo.wid();
|
||||
|
||||
if (isMaximizedInCurrentScreen(winfo)) {
|
||||
//! active maximized windows have higher priority than the rest maximized windows
|
||||
foundMaximizedInCurScreen = true;
|
||||
maxWinId = winfo.wid();
|
||||
}
|
||||
} else {
|
||||
foundTouchInCurScreen = true;
|
||||
touchWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (!foundMaximizedInCurScreen && isMaximizedInCurrentScreen(winfo)) {
|
||||
foundMaximizedInCurScreen = true;
|
||||
maxWinId = winfo.wid();
|
||||
}
|
||||
}
|
||||
|
||||
if (!existsFaultyWindow && winfo.geometry() == QRect(0, 0, 0, 0)) {
|
||||
existsFaultyWindow = true;
|
||||
}
|
||||
|
||||
//qDebug() << "window geometry ::: " << winfo.geometry();
|
||||
}
|
||||
|
||||
if (existsFaultyWindow) {
|
||||
cleanupFaultyWindows();
|
||||
}
|
||||
|
||||
//! HACK: KWin Effects such as ShowDesktop have no way to be identified and as such
|
||||
//! create issues with identifying properly touching and maximized windows. BUT when
|
||||
//! they are enabled then NO ACTIVE window is found. This is a way to identify these
|
||||
//! effects trigerring and disable the touch flags.
|
||||
//! BUG: 404483
|
||||
//! Disabled because it has fault identifications, e.g. when a window is maximized and
|
||||
//! Latte or Plasma are showing their View settings
|
||||
//foundMaximizedInCurScreen = foundMaximizedInCurScreen && foundActive;
|
||||
//foundTouchInCurScreen = foundTouchInCurScreen && foundActive;
|
||||
|
||||
//! assign flags
|
||||
setExistsWindowActive(foundActiveInCurScreen);
|
||||
setActiveWindowTouching(foundActiveTouchInCurScreen);
|
||||
setActiveWindowMaximized(maxWinId.toInt()>0 && (maxWinId == activeTouchWinId));
|
||||
setExistsWindowMaximized(foundMaximizedInCurScreen);
|
||||
setExistsWindowTouching(foundTouchInCurScreen || foundActiveTouchInCurScreen);
|
||||
|
||||
//! update color schemes for active and touching windows
|
||||
setActiveWindowScheme(foundActiveInCurScreen ? m_wm->schemeForWindow(activeWinId) : nullptr);
|
||||
|
||||
if (foundActiveTouchInCurScreen) {
|
||||
setTouchingWindowScheme(m_wm->schemeForWindow(activeTouchWinId));
|
||||
} else if (foundMaximizedInCurScreen) {
|
||||
setTouchingWindowScheme(m_wm->schemeForWindow(maxWinId));
|
||||
} else if (foundTouchInCurScreen) {
|
||||
setTouchingWindowScheme(m_wm->schemeForWindow(touchWinId));
|
||||
} else {
|
||||
setTouchingWindowScheme(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsTracker::inCurrentDesktopActivity(const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && m_wm->isOnCurrentDesktop(winfo.wid()) && m_wm->isOnCurrentActivity(winfo.wid()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::intersects(const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
return (!winfo.isMinimized() && !winfo.isShaded() && winfo.geometry().intersects(m_latteView->absoluteGeometry()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isActive(const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && winfo.isActive() && !winfo.isMinimized());
|
||||
}
|
||||
|
||||
bool WindowsTracker::isActiveInCurrentScreen(const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && winfo.isActive() && !winfo.isMinimized()
|
||||
&& m_availableScreenGeometry.contains(winfo.geometry().center()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isMaximizedInCurrentScreen(const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
auto viewIntersectsMaxVert = [&]() noexcept -> bool {
|
||||
return ((winfo.isMaxVert()
|
||||
|| (m_latteView->screen() && m_latteView->screen()->availableSize().height() <= winfo.geometry().height()))
|
||||
&& intersects(winfo));
|
||||
};
|
||||
|
||||
auto viewIntersectsMaxHoriz = [&]() noexcept -> bool {
|
||||
return ((winfo.isMaxHoriz()
|
||||
|| (m_latteView->screen() && m_latteView->screen()->availableSize().width() <= winfo.geometry().width()))
|
||||
&& intersects(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
|
||||
return (winfo.isValid() && !winfo.isMinimized()
|
||||
&& (winfo.isMaximized() || viewIntersectsMaxVert() || viewIntersectsMaxHoriz())
|
||||
&& m_availableScreenGeometry.contains(winfo.geometry().center()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isTouchingView(const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && intersects(winfo));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isTouchingViewEdge(const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
if (winfo.isValid() && !winfo.isMinimized()) {
|
||||
bool touchingViewEdge{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) {
|
||||
touchingViewEdge = (winfo.geometry().y() == m_availableScreenGeometry.y());
|
||||
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
|
||||
touchingViewEdge = (winfo.geometry().bottom() == m_availableScreenGeometry.bottom());
|
||||
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
|
||||
touchingViewEdge = (winfo.geometry().x() == m_availableScreenGeometry.x());
|
||||
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
|
||||
touchingViewEdge = (winfo.geometry().right() == m_availableScreenGeometry.right());
|
||||
}
|
||||
}
|
||||
|
||||
return touchingViewEdge;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WindowsTracker::cleanupFaultyWindows()
|
||||
{
|
||||
for (const 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)
|
||||
@ -436,13 +155,7 @@ void WindowsTracker::setWindowOnActivities(QWindow &window, const QStringList &a
|
||||
|
||||
void WindowsTracker::requestToggleMaximizeForActiveWindow()
|
||||
{
|
||||
WindowSystem::WindowInfoWrap actInfo;
|
||||
|
||||
if (m_windows.contains(m_lastActiveWindowWid)) {
|
||||
actInfo = m_windows[m_lastActiveWindowWid];
|
||||
} else {
|
||||
actInfo = m_wm->requestInfoActive();
|
||||
}
|
||||
WindowSystem::WindowInfoWrap actInfo = m_wm->windowsTracker()->lastActiveWindowInfo(m_latteView);
|
||||
|
||||
//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())) {
|
||||
@ -452,13 +165,7 @@ void WindowsTracker::requestToggleMaximizeForActiveWindow()
|
||||
|
||||
void WindowsTracker::requestMoveActiveWindow(int localX, int localY)
|
||||
{
|
||||
WindowSystem::WindowInfoWrap actInfo;
|
||||
|
||||
if (m_windows.contains(m_lastActiveWindowWid)) {
|
||||
actInfo = m_windows[m_lastActiveWindowWid];
|
||||
} else {
|
||||
actInfo = m_wm->requestInfoActive();
|
||||
}
|
||||
WindowSystem::WindowInfoWrap actInfo = m_wm->windowsTracker()->lastActiveWindowInfo(m_latteView);
|
||||
|
||||
//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())) {
|
||||
@ -478,13 +185,7 @@ void WindowsTracker::requestMoveActiveWindow(int localX, int localY)
|
||||
|
||||
bool WindowsTracker::activeWindowCanBeDragged()
|
||||
{
|
||||
WindowSystem::WindowInfoWrap actInfo;
|
||||
|
||||
if (m_windows.contains(m_lastActiveWindowWid)) {
|
||||
actInfo = m_windows[m_lastActiveWindowWid];
|
||||
} else {
|
||||
actInfo = m_wm->requestInfoActive();
|
||||
}
|
||||
WindowSystem::WindowInfoWrap actInfo = m_wm->windowsTracker()->lastActiveWindowInfo(m_latteView);
|
||||
|
||||
//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())) {
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
// local
|
||||
#include "../wm/abstractwindowinterface.h"
|
||||
#include "../wm/windowinfowrap.h"
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
@ -86,50 +85,13 @@ public slots:
|
||||
Q_INVOKABLE bool activeWindowCanBeDragged();
|
||||
|
||||
private:
|
||||
void setActiveWindowMaximized(bool activeMaximized);
|
||||
void setActiveWindowTouching(bool activeTouching);
|
||||
void setExistsWindowActive(bool windowActive);
|
||||
void setExistsWindowMaximized(bool windowMaximized);
|
||||
void setExistsWindowTouching(bool windowTouching);
|
||||
void setActiveWindowScheme(WindowSystem::SchemeColors *scheme);
|
||||
void setTouchingWindowScheme(WindowSystem::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 intersects(const WindowSystem::WindowInfoWrap &winfo);
|
||||
bool inCurrentDesktopActivity(const WindowSystem::WindowInfoWrap &winfo);
|
||||
bool isActive(const WindowSystem::WindowInfoWrap &winfo);
|
||||
bool isActiveInCurrentScreen(const WindowSystem::WindowInfoWrap &winfo);
|
||||
bool isMaximizedInCurrentScreen(const WindowSystem::WindowInfoWrap &winfo);
|
||||
bool isTouchingViewEdge(const WindowSystem::WindowInfoWrap &winfo);
|
||||
bool isTouchingView(const WindowSystem::WindowInfoWrap &winfo);
|
||||
void init();
|
||||
|
||||
private:
|
||||
bool m_enabled{false};
|
||||
bool m_activeWindowIsMaximizedFlag{false};
|
||||
bool m_activeWindowIsTouchingFlag{false};
|
||||
bool m_windowIsActiveFlag{false};
|
||||
bool m_windowIsTouchingFlag{false};
|
||||
bool m_windowIsMaximizedFlag{false};
|
||||
|
||||
QRect m_availableScreenGeometry;
|
||||
|
||||
WindowSystem::WindowId m_lastActiveWindowWid;
|
||||
|
||||
std::array<QMetaObject::Connection, 7> m_connections;
|
||||
QMap<WindowSystem::WindowId, WindowSystem::WindowInfoWrap> m_windows;
|
||||
|
||||
Latte::Corona *m_corona{nullptr};
|
||||
Latte::View *m_latteView{nullptr};
|
||||
|
||||
WindowSystem::AbstractWindowInterface *m_wm;
|
||||
|
||||
WindowSystem::SchemeColors *m_activeScheme{nullptr};
|
||||
WindowSystem::SchemeColors *m_touchingScheme{nullptr};
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ set(lattedock-app_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schemecolors.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/waylandinterface.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/windowinfowrap.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/windowstracker.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xwindowinterface.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
@ -20,6 +20,10 @@
|
||||
|
||||
#include "abstractwindowinterface.h"
|
||||
|
||||
// local
|
||||
#include "windowstracker.h"
|
||||
#include "../lattecorona.h"
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
#include <QDir>
|
||||
@ -35,6 +39,9 @@ namespace WindowSystem {
|
||||
AbstractWindowInterface::AbstractWindowInterface(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_corona = qobject_cast<Latte::Corona *>(parent);
|
||||
m_windowsTracker = new WindowsTracker(this);
|
||||
|
||||
updateDefaultScheme();
|
||||
|
||||
connect(this, &AbstractWindowInterface::windowRemoved, this, [&](WindowId wid) {
|
||||
@ -66,6 +73,8 @@ AbstractWindowInterface::~AbstractWindowInterface()
|
||||
m_schemes.take("kdeglobals");
|
||||
qDeleteAll(m_schemes);
|
||||
m_schemes.clear();
|
||||
|
||||
m_windowsTracker->deleteLater();
|
||||
}
|
||||
|
||||
//! Scheme support for windows
|
||||
@ -89,6 +98,11 @@ void AbstractWindowInterface::updateDefaultScheme()
|
||||
}
|
||||
}
|
||||
|
||||
Latte::Corona *AbstractWindowInterface::corona()
|
||||
{
|
||||
return m_corona;
|
||||
}
|
||||
|
||||
SchemeColors *AbstractWindowInterface::schemeForWindow(WindowId wid)
|
||||
{
|
||||
if (!m_windowScheme.contains(wid)) {
|
||||
@ -100,6 +114,11 @@ SchemeColors *AbstractWindowInterface::schemeForWindow(WindowId wid)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WindowsTracker *AbstractWindowInterface::windowsTracker()
|
||||
{
|
||||
return m_windowsTracker;
|
||||
}
|
||||
|
||||
void AbstractWindowInterface::setColorSchemeForWindow(WindowId wid, QString scheme)
|
||||
{
|
||||
if (scheme == "kdeglobals" && !m_windowScheme.contains(wid)) {
|
||||
|
@ -47,6 +47,13 @@
|
||||
// Plasma
|
||||
#include <Plasma>
|
||||
|
||||
namespace Latte {
|
||||
class Corona;
|
||||
namespace WindowSystem {
|
||||
class WindowsTracker;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Latte {
|
||||
namespace WindowSystem {
|
||||
|
||||
@ -94,7 +101,9 @@ public:
|
||||
virtual bool windowCanBeDragged(WindowId wid) const = 0;
|
||||
virtual WindowId winIdFor(QString appId, QRect geometry) const = 0;
|
||||
|
||||
Latte::Corona *corona();
|
||||
SchemeColors *schemeForWindow(WindowId wId);
|
||||
WindowsTracker *windowsTracker();
|
||||
void setColorSchemeForWindow(WindowId wId, QString scheme);
|
||||
|
||||
signals:
|
||||
@ -118,6 +127,9 @@ private:
|
||||
|
||||
//! window id and its corresponding scheme file
|
||||
QMap<WindowId, QString> m_windowScheme;
|
||||
|
||||
Latte::Corona *m_corona;
|
||||
WindowsTracker *m_windowsTracker;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -18,3 +18,492 @@
|
||||
*/
|
||||
|
||||
#include "windowstracker.h"
|
||||
|
||||
// local
|
||||
#include "abstractwindowinterface.h"
|
||||
#include "schemecolors.h"
|
||||
#include "../lattecorona.h"
|
||||
#include "../layouts/manager.h"
|
||||
#include "../view/view.h"
|
||||
#include "../view/positioner.h"
|
||||
#include "../../liblatte2/types.h"
|
||||
|
||||
namespace Latte {
|
||||
namespace WindowSystem {
|
||||
|
||||
WindowsTracker::WindowsTracker(AbstractWindowInterface *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_wm = parent;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
WindowsTracker::~WindowsTracker()
|
||||
{
|
||||
}
|
||||
|
||||
void WindowsTracker::init()
|
||||
{
|
||||
connect(m_wm->corona(), &Plasma::Corona::availableScreenRectChanged, this, &WindowsTracker::updateAvailableScreenGeometries);
|
||||
|
||||
connect(m_wm, &AbstractWindowInterface::windowChanged, this, [&](WindowId wid) {
|
||||
m_windows[wid] = m_wm->requestInfo(wid);
|
||||
updateViewsHints();
|
||||
});
|
||||
|
||||
connect(m_wm, &AbstractWindowInterface::windowRemoved, this, [&](WindowId wid) {
|
||||
m_windows.remove(wid);
|
||||
updateViewsHints();
|
||||
});
|
||||
|
||||
connect(m_wm, &AbstractWindowInterface::windowAdded, this, [&](WindowId wid) {
|
||||
if (!m_windows.contains(wid)) {
|
||||
m_windows.insert(wid, m_wm->requestInfo(wid));
|
||||
}
|
||||
updateViewsHints();
|
||||
});
|
||||
|
||||
connect(m_wm, &AbstractWindowInterface::activeWindowChanged, this, [&](WindowId wid) {
|
||||
for (const auto view : m_views.keys()) {
|
||||
WindowId lastWinId = m_views[view].lastActiveWindow;
|
||||
if (m_windows.contains(lastWinId)) {
|
||||
m_windows[lastWinId] = m_wm->requestInfo(lastWinId);
|
||||
}
|
||||
}
|
||||
|
||||
m_windows[wid] = m_wm->requestInfo(wid);
|
||||
updateViewsHints();
|
||||
});
|
||||
|
||||
connect(m_wm, &AbstractWindowInterface::currentDesktopChanged, this, [&] {
|
||||
updateViewsHints();
|
||||
});
|
||||
|
||||
connect(m_wm, &AbstractWindowInterface::currentActivityChanged, this, [&] {
|
||||
if (m_wm->corona()->layoutsManager()->memoryUsage() == Types::MultipleLayouts) {
|
||||
//! this is needed in MultipleLayouts because there is a chance that multiple
|
||||
//! layouts are providing different available screen geometries in different Activities
|
||||
updateAvailableScreenGeometries();
|
||||
}
|
||||
|
||||
updateViewsHints();
|
||||
});
|
||||
}
|
||||
|
||||
void WindowsTracker::addView(Latte::View *view)
|
||||
{
|
||||
if (m_views.contains(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewHints hints;
|
||||
m_views[view] = hints;
|
||||
|
||||
updateAvailableScreenGeometries();
|
||||
updateHints(view);
|
||||
}
|
||||
|
||||
void WindowsTracker::removeView(Latte::View *view)
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views.remove(view);
|
||||
}
|
||||
|
||||
//! Views Properties And Hints
|
||||
|
||||
bool WindowsTracker::enabled(Latte::View *view)
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_views[view].enabled;
|
||||
}
|
||||
|
||||
void WindowsTracker::setEnabled(Latte::View *view, const bool enabled)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].enabled == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].enabled = enabled;
|
||||
|
||||
if (enabled) {
|
||||
updateHints(view);
|
||||
} else {
|
||||
//! INITIALIZE ALL HINTS !!!
|
||||
}
|
||||
|
||||
emit enabledChanged(view);
|
||||
}
|
||||
|
||||
bool WindowsTracker::activeWindowMaximized(Latte::View *view) const
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_views[view].activeWindowMaximized;
|
||||
}
|
||||
|
||||
void WindowsTracker::setActiveWindowMaximized(Latte::View *view, bool activeMaximized)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].activeWindowMaximized == activeMaximized) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].activeWindowMaximized = activeMaximized;
|
||||
emit activeWindowMaximizedChanged(view);
|
||||
}
|
||||
|
||||
bool WindowsTracker::activeWindowTouching(Latte::View *view) const
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_views[view].activeWindowTouching;
|
||||
}
|
||||
|
||||
void WindowsTracker::setActiveWindowTouching(Latte::View *view, bool activeTouching)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].activeWindowTouching == activeTouching) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].activeWindowTouching = activeTouching;
|
||||
emit activeWindowTouchingChanged(view);
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowActive(Latte::View *view) const
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_views[view].existsWindowActive;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowActive(Latte::View *view, bool windowActive)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].existsWindowActive == windowActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].existsWindowActive = windowActive;
|
||||
emit existsWindowActiveChanged(view);
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowMaximized(Latte::View *view) const
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_views[view].existsWindowMaximized;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowMaximized(Latte::View *view, bool windowMaximized)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].existsWindowMaximized == windowMaximized) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].existsWindowMaximized = windowMaximized;
|
||||
emit existsWindowMaximizedChanged(view);
|
||||
}
|
||||
|
||||
bool WindowsTracker::existsWindowTouching(Latte::View *view) const
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_views[view].existsWindowTouching;
|
||||
}
|
||||
|
||||
void WindowsTracker::setExistsWindowTouching(Latte::View *view, bool windowTouching)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].existsWindowTouching == windowTouching) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].existsWindowTouching = windowTouching;
|
||||
emit existsWindowTouchingChanged(view);
|
||||
}
|
||||
|
||||
SchemeColors *WindowsTracker::activeWindowScheme(Latte::View *view) const
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_views[view].activeWindowScheme;
|
||||
}
|
||||
|
||||
void WindowsTracker::setActiveWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].activeWindowScheme == scheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].activeWindowScheme = scheme;
|
||||
emit activeWindowSchemeChanged(view);
|
||||
}
|
||||
|
||||
SchemeColors *WindowsTracker::touchingWindowScheme(Latte::View *view) const
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_views[view].touchingWindowScheme;
|
||||
}
|
||||
|
||||
void WindowsTracker::setTouchingWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme)
|
||||
{
|
||||
if (!m_views.contains(view) || m_views[view].touchingWindowScheme == scheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_views[view].touchingWindowScheme = scheme;
|
||||
emit touchingWindowSchemeChanged(view);
|
||||
}
|
||||
|
||||
WindowInfoWrap WindowsTracker::lastActiveWindowInfo(Latte::View *view)
|
||||
{
|
||||
WindowInfoWrap info;
|
||||
if (!m_views.contains(view)) {
|
||||
return info;
|
||||
}
|
||||
|
||||
if (!m_windows.contains(m_views[view].lastActiveWindow)) {
|
||||
m_views[view].lastActiveWindow = info.wid();
|
||||
return info;
|
||||
}
|
||||
|
||||
return m_wm->requestInfo(m_views[view].lastActiveWindow);
|
||||
}
|
||||
|
||||
//! Windows Criteria Functions
|
||||
|
||||
bool WindowsTracker::inCurrentDesktopActivity(const WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && m_wm->isOnCurrentDesktop(winfo.wid()) && m_wm->isOnCurrentActivity(winfo.wid()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::intersects(Latte::View *view, const WindowInfoWrap &winfo)
|
||||
{
|
||||
return (!winfo.isMinimized() && !winfo.isShaded() && winfo.geometry().intersects(view->absoluteGeometry()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isActive(const WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && winfo.isActive() && !winfo.isMinimized());
|
||||
}
|
||||
|
||||
bool WindowsTracker::isActiveInViewScreen(Latte::View *view, const WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && winfo.isActive() && !winfo.isMinimized()
|
||||
&& m_views[view].availableScreenGeometry.contains(winfo.geometry().center()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isMaximizedInViewScreen(Latte::View *view, const WindowInfoWrap &winfo)
|
||||
{
|
||||
auto viewIntersectsMaxVert = [&]() noexcept -> bool {
|
||||
return ((winfo.isMaxVert()
|
||||
|| (view->screen() && view->screen()->availableSize().height() <= winfo.geometry().height()))
|
||||
&& intersects(view, winfo));
|
||||
};
|
||||
|
||||
auto viewIntersectsMaxHoriz = [&]() noexcept -> bool {
|
||||
return ((winfo.isMaxHoriz()
|
||||
|| (view->screen() && view->screen()->availableSize().width() <= winfo.geometry().width()))
|
||||
&& intersects(view, 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
|
||||
return (winfo.isValid() && !winfo.isMinimized()
|
||||
&& (winfo.isMaximized() || viewIntersectsMaxVert() || viewIntersectsMaxHoriz())
|
||||
&& m_views[view].availableScreenGeometry.contains(winfo.geometry().center()));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isTouchingView(Latte::View *view, const WindowSystem::WindowInfoWrap &winfo)
|
||||
{
|
||||
return (winfo.isValid() && intersects(view, winfo));
|
||||
}
|
||||
|
||||
bool WindowsTracker::isTouchingViewEdge(Latte::View *view, const WindowInfoWrap &winfo)
|
||||
{
|
||||
if (winfo.isValid() && !winfo.isMinimized()) {
|
||||
bool touchingViewEdge{false};
|
||||
|
||||
QRect screenGeometry = view->screenGeometry();
|
||||
QRect availableScreenGeometry = m_views[view].availableScreenGeometry;
|
||||
|
||||
bool inCurrentScreen{screenGeometry.contains(winfo.geometry().topLeft()) || screenGeometry.contains(winfo.geometry().bottomRight())};
|
||||
|
||||
if (inCurrentScreen) {
|
||||
if (view->location() == Plasma::Types::TopEdge) {
|
||||
touchingViewEdge = (winfo.geometry().y() == availableScreenGeometry.y());
|
||||
} else if (view->location() == Plasma::Types::BottomEdge) {
|
||||
touchingViewEdge = (winfo.geometry().bottom() == availableScreenGeometry.bottom());
|
||||
} else if (view->location() == Plasma::Types::LeftEdge) {
|
||||
touchingViewEdge = (winfo.geometry().x() == availableScreenGeometry.x());
|
||||
} else if (view->location() == Plasma::Types::RightEdge) {
|
||||
touchingViewEdge = (winfo.geometry().right() == availableScreenGeometry.right());
|
||||
}
|
||||
}
|
||||
|
||||
return touchingViewEdge;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WindowsTracker::cleanupFaultyWindows()
|
||||
{
|
||||
for (const 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WindowsTracker::updateAvailableScreenGeometries()
|
||||
{
|
||||
for (const auto view : m_views.keys()) {
|
||||
if (m_views[view].enabled) {
|
||||
int currentScrId = view->positioner()->currentScreenId();
|
||||
QRect tempAvailableScreenGeometry = m_wm->corona()->availableScreenRectWithCriteria(currentScrId, {Types::AlwaysVisible}, {});
|
||||
|
||||
if (tempAvailableScreenGeometry != m_views[view].availableScreenGeometry) {
|
||||
m_views[view].availableScreenGeometry = tempAvailableScreenGeometry;
|
||||
|
||||
updateHints(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsTracker::updateViewsHints()
|
||||
{
|
||||
for (const auto view : m_views.keys()) {
|
||||
if (m_views[view].enabled) {
|
||||
updateHints(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsTracker::updateHints(Latte::View *view)
|
||||
{
|
||||
if (!m_views.contains(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool foundActive{false};
|
||||
bool foundActiveInCurScreen{false};
|
||||
bool foundActiveTouchInCurScreen{false};
|
||||
bool foundTouchInCurScreen{false};
|
||||
bool foundMaximizedInCurScreen{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 activeWinId;
|
||||
WindowId touchWinId;
|
||||
WindowId activeTouchWinId;
|
||||
|
||||
for (const auto &winfo : m_windows) {
|
||||
if (winfo.isPlasmaDesktop() || !inCurrentDesktopActivity(winfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isActive(winfo)) {
|
||||
foundActive = true;
|
||||
}
|
||||
|
||||
if (isActiveInViewScreen(view, winfo)) {
|
||||
m_views[view].lastActiveWindow = winfo.wid();
|
||||
foundActiveInCurScreen = true;
|
||||
activeWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (isTouchingViewEdge(view, winfo) || isTouchingView(view, winfo)) {
|
||||
if (winfo.isActive()) {
|
||||
foundActiveTouchInCurScreen = true;
|
||||
activeTouchWinId = winfo.wid();
|
||||
|
||||
if (isMaximizedInViewScreen(view, winfo)) {
|
||||
//! active maximized windows have higher priority than the rest maximized windows
|
||||
foundMaximizedInCurScreen = true;
|
||||
maxWinId = winfo.wid();
|
||||
}
|
||||
} else {
|
||||
foundTouchInCurScreen = true;
|
||||
touchWinId = winfo.wid();
|
||||
}
|
||||
|
||||
if (!foundMaximizedInCurScreen && isMaximizedInViewScreen(view, winfo)) {
|
||||
foundMaximizedInCurScreen = true;
|
||||
maxWinId = winfo.wid();
|
||||
}
|
||||
}
|
||||
|
||||
if (!existsFaultyWindow && winfo.geometry() == QRect(0, 0, 0, 0)) {
|
||||
existsFaultyWindow = true;
|
||||
}
|
||||
|
||||
//qDebug() << "window geometry ::: " << winfo.geometry();
|
||||
}
|
||||
|
||||
if (existsFaultyWindow) {
|
||||
cleanupFaultyWindows();
|
||||
}
|
||||
|
||||
//! HACK: KWin Effects such as ShowDesktop have no way to be identified and as such
|
||||
//! create issues with identifying properly touching and maximized windows. BUT when
|
||||
//! they are enabled then NO ACTIVE window is found. This is a way to identify these
|
||||
//! effects trigerring and disable the touch flags.
|
||||
//! BUG: 404483
|
||||
//! Disabled because it has fault identifications, e.g. when a window is maximized and
|
||||
//! Latte or Plasma are showing their View settings
|
||||
//foundMaximizedInCurScreen = foundMaximizedInCurScreen && foundActive;
|
||||
//foundTouchInCurScreen = foundTouchInCurScreen && foundActive;
|
||||
|
||||
//! assign flags
|
||||
setExistsWindowActive(view, foundActiveInCurScreen);
|
||||
setActiveWindowTouching(view, foundActiveTouchInCurScreen);
|
||||
setActiveWindowMaximized(view, (maxWinId.toInt()>0 && (maxWinId == activeTouchWinId)));
|
||||
setExistsWindowMaximized(view, foundMaximizedInCurScreen);
|
||||
setExistsWindowTouching(view, (foundTouchInCurScreen || foundActiveTouchInCurScreen));
|
||||
|
||||
//! update color schemes for active and touching windows
|
||||
setActiveWindowScheme(view, (foundActiveInCurScreen ? m_wm->schemeForWindow(activeWinId) : nullptr));
|
||||
|
||||
if (foundActiveTouchInCurScreen) {
|
||||
setTouchingWindowScheme(view, m_wm->schemeForWindow(activeTouchWinId));
|
||||
} else if (foundMaximizedInCurScreen) {
|
||||
setTouchingWindowScheme(view, m_wm->schemeForWindow(maxWinId));
|
||||
} else if (foundTouchInCurScreen) {
|
||||
setTouchingWindowScheme(view, m_wm->schemeForWindow(touchWinId));
|
||||
} else {
|
||||
setTouchingWindowScheme(view, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,16 +20,105 @@
|
||||
#ifndef WINDOWSYSTEMWINDOWSTRACKER_H
|
||||
#define WINDOWSYSTEMWINDOWSTRACKER_H
|
||||
|
||||
// local
|
||||
#include "windowinfowrap.h"
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
|
||||
namespace Latte {
|
||||
class View;
|
||||
namespace WindowSystem {
|
||||
class AbstractWindowInterface;
|
||||
class SchemeColors;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Latte {
|
||||
namespace WindowSystem {
|
||||
|
||||
struct ViewHints {
|
||||
bool enabled{false};
|
||||
bool activeWindowMaximized{false};
|
||||
bool activeWindowTouching{false};
|
||||
bool existsWindowActive{false};
|
||||
bool existsWindowMaximized{false};
|
||||
bool existsWindowTouching{false};
|
||||
QRect availableScreenGeometry;
|
||||
WindowId lastActiveWindow;
|
||||
SchemeColors *activeWindowScheme{nullptr};
|
||||
SchemeColors *touchingWindowScheme{nullptr};
|
||||
};
|
||||
|
||||
class WindowsTracker : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WindowsTracker(AbstractWindowInterface *parent);
|
||||
~WindowsTracker() override;
|
||||
|
||||
void addView(Latte::View *view);
|
||||
void removeView(Latte::View *view);
|
||||
|
||||
bool enabled(Latte::View *view);
|
||||
void setEnabled(Latte::View *view, const bool enabled);
|
||||
|
||||
bool activeWindowMaximized(Latte::View *view) const;
|
||||
bool activeWindowTouching(Latte::View *view) const;
|
||||
bool existsWindowActive(Latte::View *view) const;
|
||||
bool existsWindowMaximized(Latte::View *view) const;
|
||||
bool existsWindowTouching(Latte::View *view) const;
|
||||
SchemeColors *activeWindowScheme(Latte::View *view) const;
|
||||
SchemeColors *touchingWindowScheme(Latte::View *view) const;
|
||||
WindowInfoWrap lastActiveWindowInfo(Latte::View *view);
|
||||
|
||||
signals:
|
||||
void enabledChanged(const Latte::View *view);
|
||||
void activeWindowMaximizedChanged(const Latte::View *view);
|
||||
void activeWindowTouchingChanged(const Latte::View *view);
|
||||
void existsWindowActiveChanged(const Latte::View *view);
|
||||
void existsWindowMaximizedChanged(const Latte::View *view);
|
||||
void existsWindowTouchingChanged(const Latte::View *view);
|
||||
void activeWindowSchemeChanged(const Latte::View *view);
|
||||
void touchingWindowSchemeChanged(const Latte::View *view);
|
||||
|
||||
private slots:
|
||||
void updateAvailableScreenGeometries();
|
||||
|
||||
private:
|
||||
void init();
|
||||
void cleanupFaultyWindows();
|
||||
|
||||
void updateViewsHints();
|
||||
void updateHints(Latte::View *view);
|
||||
|
||||
void setActiveWindowMaximized(Latte::View *view, bool activeMaximized);
|
||||
void setActiveWindowTouching(Latte::View *view, bool activeTouching);
|
||||
void setExistsWindowActive(Latte::View *view, bool windowActive);
|
||||
void setExistsWindowMaximized(Latte::View *view, bool windowMaximized);
|
||||
void setExistsWindowTouching(Latte::View *view, bool windowTouching);
|
||||
void setActiveWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme);
|
||||
void setTouchingWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme);
|
||||
|
||||
bool inCurrentDesktopActivity(const WindowInfoWrap &winfo);
|
||||
bool intersects(Latte::View *view, const WindowInfoWrap &winfo);
|
||||
bool isActive(const WindowInfoWrap &winfo);
|
||||
bool isActiveInViewScreen(Latte::View *view, const WindowInfoWrap &winfo);
|
||||
bool isMaximizedInViewScreen(Latte::View *view, const WindowInfoWrap &winfo);
|
||||
bool isTouchingView(Latte::View *view, const WindowSystem::WindowInfoWrap &winfo);
|
||||
bool isTouchingViewEdge(Latte::View *view, const WindowInfoWrap &winfo);
|
||||
|
||||
private:
|
||||
AbstractWindowInterface *m_wm;
|
||||
QHash<Latte::View *, ViewHints> m_views;
|
||||
QMap<WindowId, WindowInfoWrap > m_windows;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user