diff --git a/app/view/windowstracker.cpp b/app/view/windowstracker.cpp index 10cb8e5e..b9345e57 100644 --- a/app/view/windowstracker.cpp +++ b/app/view/windowstracker.cpp @@ -1,199 +1,200 @@ /* * Copyright 2019 Michail Vourlakos * * 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 . */ #include "windowstracker.h" // local #include "positioner.h" #include "view.h" #include "../lattecorona.h" #include "../layouts/manager.h" #include "../wm/schemecolors.h" #include "../wm/tracker/windows.h" +#include "../wm/tracker/lastactivewindow.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(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::Tracker::Windows::enabledChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit enabledChanged(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::activeWindowMaximizedChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit activeWindowMaximizedChanged(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::activeWindowTouchingChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit activeWindowTouchingChanged(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::existsWindowActiveChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit existsWindowActiveChanged(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::existsWindowMaximizedChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit existsWindowMaximizedChanged(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::existsWindowTouchingChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit existsWindowTouchingChanged(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::activeWindowSchemeChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit activeWindowSchemeChanged(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::touchingWindowSchemeChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit touchingWindowSchemeChanged(); } }); } bool WindowsTracker::activeWindowMaximized() const { return m_wm->windowsTracker()->activeWindowMaximized(m_latteView); } bool WindowsTracker::activeWindowTouching() const { return m_wm->windowsTracker()->activeWindowTouching(m_latteView); } bool WindowsTracker::existsWindowActive() const { return m_wm->windowsTracker()->existsWindowActive(m_latteView); } bool WindowsTracker::existsWindowMaximized() const { return m_wm->windowsTracker()->existsWindowMaximized(m_latteView); } bool WindowsTracker::existsWindowTouching() const { return m_wm->windowsTracker()->existsWindowTouching(m_latteView); } WindowSystem::SchemeColors *WindowsTracker::activeWindowScheme() const { return m_wm->windowsTracker()->activeWindowScheme(m_latteView); } WindowSystem::SchemeColors *WindowsTracker::touchingWindowScheme() const { return m_wm->windowsTracker()->touchingWindowScheme(m_latteView); } bool WindowsTracker::enabled() const { return m_wm->windowsTracker()->enabled(m_latteView); } void WindowsTracker::setEnabled(bool active) { m_wm->windowsTracker()->setEnabled(m_latteView, active); } //! Window Functions void WindowsTracker::setWindowOnActivities(QWindow &window, const QStringList &activities) { m_wm->setWindowOnActivities(window, activities); } void WindowsTracker::requestToggleMaximizeForActiveWindow() { - WindowSystem::WindowInfoWrap actInfo = m_wm->windowsTracker()->lastActiveWindowInfo(m_latteView); + Latte::WindowSystem::Tracker::LastActiveWindow *actInfo = m_wm->windowsTracker()->lastActiveWindow(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())) { - m_wm->requestToggleMaximized(actInfo.wid()); + if (actInfo && !actInfo->geometry().isNull() && m_latteView->screenGeometry().contains(actInfo->geometry().center())) { + m_wm->requestToggleMaximized(actInfo->winId()); } } void WindowsTracker::requestMoveActiveWindow(int localX, int localY) { - WindowSystem::WindowInfoWrap actInfo = m_wm->windowsTracker()->lastActiveWindowInfo(m_latteView); + Latte::WindowSystem::Tracker::LastActiveWindow *actInfo = m_wm->windowsTracker()->lastActiveWindow(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())) { + if (actInfo && !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); + m_wm->requestMoveWindow(actInfo->winId(), globalPoint); //! This timer is needed because otherwise the mouse position //! in the dragged window changes to TopLeft corner - QTimer::singleShot(250, this, [&, actInfo, globalPoint]() { + QTimer::singleShot(250, this, [&]() { m_wm->releaseMouseEventFor(m_latteView->winId()); }); emit activeWindowDraggingStarted(); } } bool WindowsTracker::activeWindowCanBeDragged() { - WindowSystem::WindowInfoWrap actInfo = m_wm->windowsTracker()->lastActiveWindowInfo(m_latteView); + Latte::WindowSystem::Tracker::LastActiveWindow *actInfo = m_wm->windowsTracker()->lastActiveWindow(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())) { - return m_wm->windowCanBeDragged(actInfo.wid()); + if (actInfo && !actInfo->geometry().isNull() && m_latteView->screenGeometry().contains(actInfo->geometry().center())) { + return m_wm->windowCanBeDragged(actInfo->winId()); } return false; } } } diff --git a/app/wm/tracker/CMakeLists.txt b/app/wm/tracker/CMakeLists.txt index ef25c188..fd7e7745 100644 --- a/app/wm/tracker/CMakeLists.txt +++ b/app/wm/tracker/CMakeLists.txt @@ -1,6 +1,8 @@ set(lattedock-app_SRCS ${lattedock-app_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/lastactivewindow.cpp ${CMAKE_CURRENT_SOURCE_DIR}/windows.cpp ${CMAKE_CURRENT_SOURCE_DIR}/schemes.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/trackedinfo.cpp PARENT_SCOPE ) diff --git a/app/wm/tracker/lastactivewindow.cpp b/app/wm/tracker/lastactivewindow.cpp new file mode 100644 index 00000000..e202391b --- /dev/null +++ b/app/wm/tracker/lastactivewindow.cpp @@ -0,0 +1,77 @@ +/* +* Copyright 2019 Michail Vourlakos +* +* 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 . +*/ + +#include "lastactivewindow.h" + +//local +#include "trackedinfo.h" + +namespace Latte { +namespace WindowSystem { +namespace Tracker { + + +LastActiveWindow::LastActiveWindow(TrackedInfo *parent) + : QObject(parent) +{ +} + +LastActiveWindow::~LastActiveWindow() +{ +} + +QRect LastActiveWindow::geometry() const +{ + return m_geometry; +} + +void LastActiveWindow::setGeometry(QRect geometry) +{ + if (m_geometry == geometry) { + return; + } + + m_geometry = geometry; + emit geometryChanged(); +} + +QVariant LastActiveWindow::winId() const +{ + return m_winId; +} + +void LastActiveWindow::setWinId(QVariant winId) +{ + if (m_winId == winId) { + return; + } + + m_winId = winId; + emit winIdChanged(); +} + +void LastActiveWindow::setInformation(const WindowInfoWrap &info) +{ + setWinId(info.wid()); + setGeometry(info.geometry()); +} + +} +} +} diff --git a/app/wm/tracker/lastactivewindow.h b/app/wm/tracker/lastactivewindow.h new file mode 100644 index 00000000..c69f5264 --- /dev/null +++ b/app/wm/tracker/lastactivewindow.h @@ -0,0 +1,76 @@ +/* +* Copyright 2019 Michail Vourlakos +* +* 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 . +*/ + +#ifndef WINDOWSYSTEMLASTACTIVEWINDOW_H +#define WINDOWSYSTEMLASTACTIVEWINDOW_H + +// local +#include "../windowinfowrap.h" + +// Qt +#include +#include + +namespace Latte { +namespace WindowSystem { +namespace Tracker { +class TrackedInfo; +} +} +} + + +namespace Latte { +namespace WindowSystem { +namespace Tracker { + +class LastActiveWindow : public QObject { + Q_OBJECT + + Q_PROPERTY(QVariant winId READ winId NOTIFY winIdChanged) + +public: + LastActiveWindow(TrackedInfo *parent); + ~LastActiveWindow() override; + + QRect geometry() const; + QVariant winId() const; + + + void setInformation(const WindowInfoWrap &info); + +signals: + void geometryChanged(); + void winIdChanged(); + +private: + void setGeometry(QRect geometry); + void setWinId(QVariant winId); + +private: + QRect m_geometry; + QVariant m_winId; + +}; + +} +} +} + +#endif diff --git a/app/wm/tracker/trackedinfo.cpp b/app/wm/tracker/trackedinfo.cpp new file mode 100644 index 00000000..3f9b4397 --- /dev/null +++ b/app/wm/tracker/trackedinfo.cpp @@ -0,0 +1,183 @@ +/* +* Copyright 2019 Michail Vourlakos +* +* 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 . +*/ + +#include "trackedinfo.h" + +//local +#include "windows.h" +#include "../schemecolors.h" + +namespace Latte { +namespace WindowSystem { +namespace Tracker { + + +TrackedInfo::TrackedInfo(Tracker::Windows *parent) + : QObject(parent) +{ + m_lastActiveWindow = new LastActiveWindow(this); + + emit lastActiveWindowChanged(); +} + +TrackedInfo::~TrackedInfo() +{ + if (m_lastActiveWindow) { + auto law = m_lastActiveWindow; + m_lastActiveWindow = nullptr; + emit lastActiveWindowChanged(); + + law->deleteLater(); + } +} + +bool TrackedInfo::enabled() const +{ + return m_enabled; +} + +void TrackedInfo::setEnabled(bool enabled) +{ + if (m_enabled == enabled) { + return; + } + + m_enabled = enabled; +} + +bool TrackedInfo::activeWindowMaximized() const +{ + return m_activeWindowMaximized; +} + +void TrackedInfo::setActiveWindowMaximized(bool activeMaximized) +{ + if (m_activeWindowMaximized == activeMaximized) { + return; + } + + m_activeWindowMaximized = activeMaximized; +} + +bool TrackedInfo::activeWindowTouching() const +{ + return m_activeWindowTouching; +} + +void TrackedInfo::setActiveWindowTouching(bool touching) +{ + if (m_activeWindowTouching == touching) { + return; + } + + m_activeWindowTouching = touching; +} + +bool TrackedInfo::existsWindowActive() const +{ + return m_existsWindowActive; +} + +void TrackedInfo::setExistsWindowActive(bool exists) +{ + if (m_existsWindowActive == exists) { + return; + } + + m_existsWindowActive = exists; +} + +bool TrackedInfo::existsWindowMaximized() const +{ + return m_existsWindowMaximized; +} + +void TrackedInfo::setExistsWindowMaximized(bool maximized) +{ + if (m_existsWindowMaximized == maximized) { + return; + } + + m_existsWindowMaximized = maximized; +} + +bool TrackedInfo::existsWindowTouching() const +{ + return m_existsWindowTouching; +} + +void TrackedInfo::setExistsWindowTouching(bool touching) +{ + if (m_existsWindowTouching == touching) { + return; + } + + m_existsWindowTouching = touching; +} + +QRect TrackedInfo::availableScreenGeometry() const +{ + return m_availableScreenGeometry; +} + +void TrackedInfo::setAvailableScreenGeometry(QRect geometry) +{ + if (m_availableScreenGeometry == geometry) { + return; + } + + m_availableScreenGeometry = geometry; +} + +LastActiveWindow *TrackedInfo::lastActiveWindow() const +{ + return m_lastActiveWindow; +} + +SchemeColors *TrackedInfo::activeWindowScheme() const +{ + return m_activeWindowScheme; +} + +void TrackedInfo::setActiveWindowScheme(SchemeColors *scheme) +{ + if (m_activeWindowScheme == scheme) { + return; + } + + m_activeWindowScheme = scheme; +} + +SchemeColors *TrackedInfo::touchingWindowScheme() const +{ + return m_touchingWindowScheme; +} + +void TrackedInfo::setTouchingWindowScheme(SchemeColors *scheme) +{ + if (m_touchingWindowScheme == scheme) { + return; + } + + m_touchingWindowScheme = scheme; +} + +} +} +} diff --git a/app/wm/tracker/trackedinfo.h b/app/wm/tracker/trackedinfo.h new file mode 100644 index 00000000..175992ed --- /dev/null +++ b/app/wm/tracker/trackedinfo.h @@ -0,0 +1,120 @@ +/* +* Copyright 2019 Michail Vourlakos +* +* 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 . +*/ + +#ifndef WINDOWSYSTEMTRACKEDINFO_H +#define WINDOWSYSTEMTRACKEDINFO_H + +// local +#include "lastactivewindow.h" +#include "../windowinfowrap.h" + +// Qt +#include +#include + +namespace Latte { +namespace WindowSystem { +class SchemeColors; +namespace Tracker { +class Windows; +} +} +} + + +namespace Latte { +namespace WindowSystem { +namespace Tracker { +/* + * + * 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 TrackedInfo : public QObject { + Q_OBJECT + + Q_PROPERTY(Latte::WindowSystem::Tracker::LastActiveWindow *activeWindow READ lastActiveWindow NOTIFY lastActiveWindowChanged) + +public: + TrackedInfo(Tracker::Windows *parent); + ~TrackedInfo() override; + + bool enabled() const; + void setEnabled(bool enabled); + + bool activeWindowMaximized() const; + void setActiveWindowMaximized(bool activeMaximized); + + bool activeWindowTouching() const; + void setActiveWindowTouching(bool touching); + + bool existsWindowActive() const; + void setExistsWindowActive(bool exists); + + bool existsWindowMaximized() const; + void setExistsWindowMaximized(bool maximized); + + bool existsWindowTouching() const; + void setExistsWindowTouching(bool touching); + + QRect availableScreenGeometry() const; + void setAvailableScreenGeometry(QRect geometry); + + LastActiveWindow *lastActiveWindow() const; + + SchemeColors *activeWindowScheme() const; + void setActiveWindowScheme(SchemeColors *scheme); + + SchemeColors *touchingWindowScheme() const; + void setTouchingWindowScheme(SchemeColors *scheme); + +signals: + void lastActiveWindowChanged(); + +private: + bool m_enabled; + bool m_activeWindowMaximized; + bool m_activeWindowTouching; + bool m_existsWindowActive; + bool m_existsWindowMaximized; + bool m_existsWindowTouching; + + QRect m_availableScreenGeometry; + + LastActiveWindow *m_lastActiveWindow{nullptr}; + + SchemeColors *m_activeWindowScheme{nullptr}; + SchemeColors *m_touchingWindowScheme{nullptr}; +}; + +} +} +} + +#endif diff --git a/app/wm/tracker/windows.cpp b/app/wm/tracker/windows.cpp index 1aba1095..dcd06aaf 100644 --- a/app/wm/tracker/windows.cpp +++ b/app/wm/tracker/windows.cpp @@ -1,533 +1,537 @@ /* * Copyright 2019 Michail Vourlakos * * 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 . */ #include "windows.h" // local +#include "lastactivewindow.h" #include "schemes.h" +#include "trackedinfo.h" #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 { namespace Tracker { Windows::Windows(AbstractWindowInterface *parent) : QObject(parent) { m_wm = parent; init(); } Windows::~Windows() { + //! clear all the m_views tracking information + for (QHash::iterator i=m_views.begin(); i!=m_views.end(); ++i) { + i.value()->deleteLater(); + m_views[i.key()] = nullptr; + } + + m_views.clear(); } void Windows::init() { connect(m_wm->corona(), &Plasma::Corona::availableScreenRectChanged, this, &Windows::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; + WindowId lastWinId = m_views[view]->lastActiveWindow()->winId(); if (m_windows.contains(lastWinId)) { m_windows[lastWinId] = m_wm->requestInfo(lastWinId); + m_views[view]->lastActiveWindow()->setInformation(m_windows[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 Windows::initViewHints(Latte::View *view) { if (!m_views.contains(view)) { return; } setActiveWindowMaximized(view, false); setActiveWindowTouching(view, false); setExistsWindowActive(view, false); setExistsWindowTouching(view, false); setExistsWindowMaximized(view, false); setActiveWindowScheme(view, nullptr); setTouchingWindowScheme(view, nullptr); } void Windows::addView(Latte::View *view) { if (m_views.contains(view)) { return; } - ViewHints hints; - m_views[view] = hints; + m_views[view] = new TrackedInfo(this); updateAvailableScreenGeometries(); updateHints(view); } void Windows::removeView(Latte::View *view) { if (!m_views.contains(view)) { return; } + m_views[view]->deleteLater(); m_views.remove(view); } //! Views Properties And Hints bool Windows::enabled(Latte::View *view) { if (!m_views.contains(view)) { return false; } - return m_views[view].enabled; + return m_views[view]->enabled(); } void Windows::setEnabled(Latte::View *view, const bool enabled) { - if (!m_views.contains(view) || m_views[view].enabled == enabled) { + if (!m_views.contains(view) || m_views[view]->enabled() == enabled) { return; } - m_views[view].enabled = enabled; + m_views[view]->setEnabled(enabled); if (enabled) { updateHints(view); } else { initViewHints(view); } emit enabledChanged(view); } bool Windows::activeWindowMaximized(Latte::View *view) const { if (!m_views.contains(view)) { return false; } - return m_views[view].activeWindowMaximized; + return m_views[view]->activeWindowMaximized(); } void Windows::setActiveWindowMaximized(Latte::View *view, bool activeMaximized) { - if (!m_views.contains(view) || m_views[view].activeWindowMaximized == activeMaximized) { + if (!m_views.contains(view) || m_views[view]->activeWindowMaximized() == activeMaximized) { return; } - m_views[view].activeWindowMaximized = activeMaximized; + m_views[view]->setActiveWindowMaximized(activeMaximized); emit activeWindowMaximizedChanged(view); } bool Windows::activeWindowTouching(Latte::View *view) const { if (!m_views.contains(view)) { return false; } - return m_views[view].activeWindowTouching; + return m_views[view]->activeWindowTouching(); } void Windows::setActiveWindowTouching(Latte::View *view, bool activeTouching) { - if (!m_views.contains(view) || m_views[view].activeWindowTouching == activeTouching) { + if (!m_views.contains(view) || m_views[view]->activeWindowTouching() == activeTouching) { return; } - m_views[view].activeWindowTouching = activeTouching; + m_views[view]->setActiveWindowTouching(activeTouching); emit activeWindowTouchingChanged(view); } bool Windows::existsWindowActive(Latte::View *view) const { if (!m_views.contains(view)) { return false; } - return m_views[view].existsWindowActive; + return m_views[view]->existsWindowActive(); } void Windows::setExistsWindowActive(Latte::View *view, bool windowActive) { - if (!m_views.contains(view) || m_views[view].existsWindowActive == windowActive) { + if (!m_views.contains(view) || m_views[view]->existsWindowActive() == windowActive) { return; } - m_views[view].existsWindowActive = windowActive; + m_views[view]->setExistsWindowActive(windowActive); emit existsWindowActiveChanged(view); } bool Windows::existsWindowMaximized(Latte::View *view) const { if (!m_views.contains(view)) { return false; } - return m_views[view].existsWindowMaximized; + return m_views[view]->existsWindowMaximized(); } void Windows::setExistsWindowMaximized(Latte::View *view, bool windowMaximized) { - if (!m_views.contains(view) || m_views[view].existsWindowMaximized == windowMaximized) { + if (!m_views.contains(view) || m_views[view]->existsWindowMaximized() == windowMaximized) { return; } - m_views[view].existsWindowMaximized = windowMaximized; + m_views[view]->setExistsWindowMaximized(windowMaximized); emit existsWindowMaximizedChanged(view); } bool Windows::existsWindowTouching(Latte::View *view) const { if (!m_views.contains(view)) { return false; } - return m_views[view].existsWindowTouching; + return m_views[view]->existsWindowTouching(); } void Windows::setExistsWindowTouching(Latte::View *view, bool windowTouching) { - if (!m_views.contains(view) || m_views[view].existsWindowTouching == windowTouching) { + if (!m_views.contains(view) || m_views[view]->existsWindowTouching() == windowTouching) { return; } - m_views[view].existsWindowTouching = windowTouching; + m_views[view]->setExistsWindowTouching(windowTouching); emit existsWindowTouchingChanged(view); } SchemeColors *Windows::activeWindowScheme(Latte::View *view) const { if (!m_views.contains(view)) { return nullptr; } - return m_views[view].activeWindowScheme; + return m_views[view]->activeWindowScheme(); } void Windows::setActiveWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme) { - if (!m_views.contains(view) || m_views[view].activeWindowScheme == scheme) { + if (!m_views.contains(view) || m_views[view]->activeWindowScheme() == scheme) { return; } - m_views[view].activeWindowScheme = scheme; + m_views[view]->setActiveWindowScheme(scheme); emit activeWindowSchemeChanged(view); } SchemeColors *Windows::touchingWindowScheme(Latte::View *view) const { if (!m_views.contains(view)) { return nullptr; } - return m_views[view].touchingWindowScheme; + return m_views[view]->touchingWindowScheme(); } void Windows::setTouchingWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme) { - if (!m_views.contains(view) || m_views[view].touchingWindowScheme == scheme) { + if (!m_views.contains(view) || m_views[view]->touchingWindowScheme() == scheme) { return; } - m_views[view].touchingWindowScheme = scheme; + m_views[view]->setTouchingWindowScheme(scheme); emit touchingWindowSchemeChanged(view); } -WindowInfoWrap Windows::lastActiveWindowInfo(Latte::View *view) +LastActiveWindow *Windows::lastActiveWindow(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 nullptr; } - return m_wm->requestInfo(m_views[view].lastActiveWindow); + return m_views[view]->lastActiveWindow(); } //! Windows Criteria Functions bool Windows::inCurrentDesktopActivity(const WindowInfoWrap &winfo) { return (winfo.isValid() && m_wm->isOnCurrentDesktop(winfo.wid()) && m_wm->isOnCurrentActivity(winfo.wid())); } bool Windows::intersects(Latte::View *view, const WindowInfoWrap &winfo) { return (!winfo.isMinimized() && !winfo.isShaded() && winfo.geometry().intersects(view->absoluteGeometry())); } bool Windows::isActive(const WindowInfoWrap &winfo) { return (winfo.isValid() && winfo.isActive() && !winfo.isMinimized()); } bool Windows::isActiveInViewScreen(Latte::View *view, const WindowInfoWrap &winfo) { return (winfo.isValid() && winfo.isActive() && !winfo.isMinimized() - && m_views[view].availableScreenGeometry.contains(winfo.geometry().center())); + && m_views[view]->availableScreenGeometry().contains(winfo.geometry().center())); } bool Windows::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())); + && m_views[view]->availableScreenGeometry().contains(winfo.geometry().center())); } bool Windows::isTouchingView(Latte::View *view, const WindowSystem::WindowInfoWrap &winfo) { return (winfo.isValid() && intersects(view, winfo)); } bool Windows::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; + 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 Windows::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 Windows::updateAvailableScreenGeometries() { for (const auto view : m_views.keys()) { - if (m_views[view].enabled) { + 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; + if (tempAvailableScreenGeometry != m_views[view]->availableScreenGeometry()) { + m_views[view]->setAvailableScreenGeometry(tempAvailableScreenGeometry); updateHints(view); } } } } void Windows::updateViewsHints() { for (const auto view : m_views.keys()) { - if (m_views[view].enabled) { + if (m_views[view]->enabled()) { updateHints(view); } } } void Windows::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(); + m_views[view]->lastActiveWindow()->setInformation(winfo); 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->schemesTracker()->schemeForWindow(activeWinId) : nullptr)); if (foundActiveTouchInCurScreen) { setTouchingWindowScheme(view, m_wm->schemesTracker()->schemeForWindow(activeTouchWinId)); } else if (foundMaximizedInCurScreen) { setTouchingWindowScheme(view, m_wm->schemesTracker()->schemeForWindow(maxWinId)); } else if (foundTouchInCurScreen) { setTouchingWindowScheme(view, m_wm->schemesTracker()->schemeForWindow(touchWinId)); } else { setTouchingWindowScheme(view, nullptr); } //! Debug //qDebug() << "TRACKING | SCREEN: " << view->positioner()->currentScreenId() << " , EDGE:" << view->location() << " , ENABLED:" << enabled(view); //qDebug() << "TRACKING | activeWindowTouching: " << foundActiveTouchInCurScreen << " ,activeWindowMaximized: " << activeWindowMaximized(view); //qDebug() << "TRACKING | existsWindowActive: " << foundActiveInCurScreen << " , existsWindowMaximized:" << existsWindowMaximized(view) // << " , existsWindowTouching:"< * * 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 . */ #ifndef WINDOWSYSTEMWINDOWSTRACKER_H #define WINDOWSYSTEMWINDOWSTRACKER_H // local #include "../windowinfowrap.h" // Qt #include #include #include namespace Latte { class View; namespace WindowSystem { class AbstractWindowInterface; class SchemeColors; +namespace Tracker { +class LastActiveWindow; +class TrackedInfo; +} } } namespace Latte { namespace WindowSystem { namespace Tracker { -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 Windows : public QObject { Q_OBJECT public: Windows(AbstractWindowInterface *parent); ~Windows() 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); + LastActiveWindow *lastActiveWindow(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 initViewHints(Latte::View *view); 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 m_views; + QHash m_views; QMap m_windows; }; } } } #endif