diff --git a/app/view/windowstracker/currentscreentracker.cpp b/app/view/windowstracker/currentscreentracker.cpp index 7e8fe79b..872f3a98 100644 --- a/app/view/windowstracker/currentscreentracker.cpp +++ b/app/view/windowstracker/currentscreentracker.cpp @@ -1,178 +1,202 @@ /* * 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 "currentscreentracker.h" // local #include "../view.h" #include "../../wm/schemecolors.h" #include "../../wm/tracker/lastactivewindow.h" #include "../../wm/tracker/windowstracker.h" namespace Latte { namespace ViewPart { namespace TrackerPart { CurrentScreenTracker::CurrentScreenTracker(WindowsTracker *parent) : QObject(parent), m_latteView(parent->view()), m_wm(parent->wm()) { init(); } CurrentScreenTracker::~CurrentScreenTracker() { m_wm->windowsTracker()->removeView(m_latteView); } void CurrentScreenTracker::init() { if (lastActiveWindow()) { initSignalsForInformation(); } connect(m_latteView, &Latte::View::layoutChanged, this, [&]() { if (m_latteView->layout()) { initSignalsForInformation(); } }); connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::informationAnnounced, this, [&](const Latte::View *view) { if (m_latteView == view) { initSignalsForInformation(); } }); 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::activeWindowTouchingEdgeChanged, this, [&](const Latte::View *view) { + if (m_latteView == view) { + emit activeWindowTouchingEdgeChanged(); + } + }); + 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::existsWindowTouchingEdgeChanged, this, [&](const Latte::View *view) { + if (m_latteView == view) { + emit existsWindowTouchingEdgeChanged(); + } + }); + connect(m_wm->windowsTracker(), &WindowSystem::Tracker::Windows::isTouchingBusyVerticalViewChanged, this, [&](const Latte::View *view) { if (m_latteView == view) { emit isTouchingBusyVerticalViewChanged(); } }); 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(); } }); } void CurrentScreenTracker::initSignalsForInformation() { emit lastActiveWindowChanged(); emit activeWindowMaximizedChanged(); emit activeWindowTouchingChanged(); + emit activeWindowTouchingEdgeChanged(); emit existsWindowActiveChanged(); emit existsWindowMaximizedChanged(); emit existsWindowTouchingChanged(); + emit existsWindowTouchingEdgeChanged(); emit activeWindowSchemeChanged(); emit touchingWindowSchemeChanged(); } bool CurrentScreenTracker::activeWindowMaximized() const { return m_wm->windowsTracker()->activeWindowMaximized(m_latteView); } bool CurrentScreenTracker::activeWindowTouching() const { return m_wm->windowsTracker()->activeWindowTouching(m_latteView); } +bool CurrentScreenTracker::activeWindowTouchingEdge() const +{ + return m_wm->windowsTracker()->activeWindowTouchingEdge(m_latteView); +} + bool CurrentScreenTracker::existsWindowActive() const { return m_wm->windowsTracker()->existsWindowActive(m_latteView); } bool CurrentScreenTracker::existsWindowMaximized() const { return m_wm->windowsTracker()->existsWindowMaximized(m_latteView); } bool CurrentScreenTracker::existsWindowTouching() const { return m_wm->windowsTracker()->existsWindowTouching(m_latteView); } +bool CurrentScreenTracker::existsWindowTouchingEdge() const +{ + return m_wm->windowsTracker()->existsWindowTouchingEdge(m_latteView); +} + bool CurrentScreenTracker::isTouchingBusyVerticalView() const { return m_wm->windowsTracker()->isTouchingBusyVerticalView(m_latteView); } WindowSystem::SchemeColors *CurrentScreenTracker::activeWindowScheme() const { return m_wm->windowsTracker()->activeWindowScheme(m_latteView); } WindowSystem::SchemeColors *CurrentScreenTracker::touchingWindowScheme() const { return m_wm->windowsTracker()->touchingWindowScheme(m_latteView); } WindowSystem::Tracker::LastActiveWindow *CurrentScreenTracker::lastActiveWindow() { return m_wm->windowsTracker()->lastActiveWindow(m_latteView); } //! Window Functions void CurrentScreenTracker::requestMoveLastWindow(int localX, int localY) { m_wm->windowsTracker()->lastActiveWindow(m_latteView)->requestMove(m_latteView, localX, localY); } } } } diff --git a/app/view/windowstracker/currentscreentracker.h b/app/view/windowstracker/currentscreentracker.h index bc205073..afd6e01a 100644 --- a/app/view/windowstracker/currentscreentracker.h +++ b/app/view/windowstracker/currentscreentracker.h @@ -1,110 +1,116 @@ /* * 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 WINDOWSCURRENTSCREENTRACKER_H #define WINDOWSCURRENTSCREENTRACKER_H // local #include "../../wm/abstractwindowinterface.h" // Qt #include namespace Latte{ class View; namespace ViewPart { class WindowsTracker; } namespace WindowSystem { class AbstractWindowInterface; class SchemeColors; namespace Tracker { class LastActiveWindow; } } } namespace Latte { namespace ViewPart { namespace TrackerPart { class CurrentScreenTracker : public QObject { Q_OBJECT Q_PROPERTY(bool activeWindowMaximized READ activeWindowMaximized NOTIFY activeWindowMaximizedChanged) Q_PROPERTY(bool activeWindowTouching READ activeWindowTouching NOTIFY activeWindowTouchingChanged) + Q_PROPERTY(bool activeWindowTouchingEdge READ activeWindowTouchingEdge NOTIFY activeWindowTouchingEdgeChanged) Q_PROPERTY(bool existsWindowActive READ existsWindowActive NOTIFY existsWindowActiveChanged) Q_PROPERTY(bool existsWindowMaximized READ existsWindowMaximized NOTIFY existsWindowMaximizedChanged) Q_PROPERTY(bool existsWindowTouching READ existsWindowTouching NOTIFY existsWindowTouchingChanged) + Q_PROPERTY(bool existsWindowTouchingEdge READ existsWindowTouchingEdge NOTIFY existsWindowTouchingEdgeChanged) Q_PROPERTY(bool isTouchingBusyVerticalView READ isTouchingBusyVerticalView NOTIFY isTouchingBusyVerticalViewChanged) Q_PROPERTY(Latte::WindowSystem::SchemeColors *activeWindowScheme READ activeWindowScheme NOTIFY activeWindowSchemeChanged) Q_PROPERTY(Latte::WindowSystem::SchemeColors *touchingWindowScheme READ touchingWindowScheme NOTIFY touchingWindowSchemeChanged) Q_PROPERTY(Latte::WindowSystem::Tracker::LastActiveWindow *lastActiveWindow READ lastActiveWindow NOTIFY lastActiveWindowChanged) public: explicit CurrentScreenTracker(WindowsTracker *parent); virtual ~CurrentScreenTracker(); bool activeWindowMaximized() const; bool activeWindowTouching() const; + bool activeWindowTouchingEdge() const; bool existsWindowActive() const; bool existsWindowMaximized() const; bool existsWindowTouching() const; + bool existsWindowTouchingEdge() const; bool isTouchingBusyVerticalView() const; WindowSystem::SchemeColors *activeWindowScheme() const; WindowSystem::SchemeColors *touchingWindowScheme() const; WindowSystem::Tracker::LastActiveWindow *lastActiveWindow(); public slots: Q_INVOKABLE void requestMoveLastWindow(int localX, int localY); signals: void activeWindowMaximizedChanged(); void activeWindowTouchingChanged(); + void activeWindowTouchingEdgeChanged(); void existsWindowActiveChanged(); void existsWindowMaximizedChanged(); void existsWindowTouchingChanged(); + void existsWindowTouchingEdgeChanged(); void isTouchingBusyVerticalViewChanged(); void activeWindowSchemeChanged(); void touchingWindowSchemeChanged(); void lastActiveWindowChanged(); private slots: void initSignalsForInformation(); private: void init(); private: Latte::View *m_latteView{nullptr}; WindowSystem::AbstractWindowInterface *m_wm{nullptr}; }; } } } #endif diff --git a/app/wm/tracker/trackedviewinfo.cpp b/app/wm/tracker/trackedviewinfo.cpp index 693a66fd..290db7e4 100644 --- a/app/wm/tracker/trackedviewinfo.cpp +++ b/app/wm/tracker/trackedviewinfo.cpp @@ -1,132 +1,160 @@ /* * 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 "trackedviewinfo.h" //local #include "windowstracker.h" #include "../schemecolors.h" #include "../../view/view.h" namespace Latte { namespace WindowSystem { namespace Tracker { TrackedViewInfo::TrackedViewInfo(Tracker::Windows *tracker, Latte::View *view) : TrackedGeneralInfo(tracker) , m_view(view) { m_activities = m_view->activities(); connect(m_view, &Latte::View::activitiesChanged, this, [&]() { m_activities = m_view->activities(); updateTrackingCurrentActivity(); }); } TrackedViewInfo::~TrackedViewInfo() { } bool TrackedViewInfo::activeWindowTouching() const { return m_activeWindowTouching; } void TrackedViewInfo::setActiveWindowTouching(bool touching) { if (m_activeWindowTouching == touching) { return; } m_activeWindowTouching = touching; } bool TrackedViewInfo::existsWindowTouching() const { return m_existsWindowTouching; } void TrackedViewInfo::setExistsWindowTouching(bool touching) { if (m_existsWindowTouching == touching) { return; } m_existsWindowTouching = touching; } +bool TrackedViewInfo::activeWindowTouchingEdge() const +{ + return m_activeWindowTouchingEdge; +} + +void TrackedViewInfo::setActiveWindowTouchingEdge(bool touching) +{ + if (m_activeWindowTouchingEdge == touching) { + return; + } + + m_activeWindowTouchingEdge = touching; +} + +bool TrackedViewInfo::existsWindowTouchingEdge() const +{ + return m_existsWindowTouchingEdge; +} + +void TrackedViewInfo::setExistsWindowTouchingEdge(bool touching) +{ + if (m_existsWindowTouchingEdge == touching) { + return; + } + + m_existsWindowTouchingEdge = touching; +} + bool TrackedViewInfo::isTouchingBusyVerticalView() const { return m_isTouchingBusyVerticalView; } void TrackedViewInfo::setIsTouchingBusyVerticalView(bool touching) { if (m_isTouchingBusyVerticalView == touching) { return; } m_isTouchingBusyVerticalView = touching; } QRect TrackedViewInfo::availableScreenGeometry() const { return m_availableScreenGeometry; } void TrackedViewInfo::setAvailableScreenGeometry(QRect geometry) { if (m_availableScreenGeometry == geometry) { return; } m_availableScreenGeometry = geometry; } SchemeColors *TrackedViewInfo::touchingWindowScheme() const { return m_touchingWindowScheme; } void TrackedViewInfo::setTouchingWindowScheme(SchemeColors *scheme) { if (m_touchingWindowScheme == scheme) { return; } m_touchingWindowScheme = scheme; } Latte::View *TrackedViewInfo::view() const { return m_view; } bool TrackedViewInfo::isTracking(const WindowInfoWrap &winfo) const { return TrackedGeneralInfo::isTracking(winfo) && m_availableScreenGeometry.contains(winfo.geometry().center()); } } } } diff --git a/app/wm/tracker/trackedviewinfo.h b/app/wm/tracker/trackedviewinfo.h index 6ddaa6ab..0dde781f 100644 --- a/app/wm/tracker/trackedviewinfo.h +++ b/app/wm/tracker/trackedviewinfo.h @@ -1,88 +1,96 @@ /* * 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 WINDOWSYSTEMTRACKEDVIEWINFO_H #define WINDOWSYSTEMTRACKEDVIEWINFO_H // local #include "trackedgeneralinfo.h" #include "../windowinfowrap.h" // Qt #include #include namespace Latte { class View; namespace WindowSystem { class SchemeColors; namespace Tracker { class Windows; } } } namespace Latte { namespace WindowSystem { namespace Tracker { class TrackedViewInfo : public TrackedGeneralInfo { Q_OBJECT public: TrackedViewInfo(Tracker::Windows *tracker, Latte::View *view); ~TrackedViewInfo() override; bool activeWindowTouching() const; void setActiveWindowTouching(bool touching); bool existsWindowTouching() const; void setExistsWindowTouching(bool touching); + bool activeWindowTouchingEdge() const; + void setActiveWindowTouchingEdge(bool touching); + + bool existsWindowTouchingEdge() const; + void setExistsWindowTouchingEdge(bool touching); + bool isTouchingBusyVerticalView() const; void setIsTouchingBusyVerticalView(bool touching); QRect availableScreenGeometry() const; void setAvailableScreenGeometry(QRect geometry); SchemeColors *touchingWindowScheme() const; void setTouchingWindowScheme(SchemeColors *scheme); Latte::View *view() const; bool isTracking(const WindowInfoWrap &winfo) const override; private: bool m_activeWindowTouching{false}; bool m_existsWindowTouching{false}; + bool m_activeWindowTouchingEdge{false}; + bool m_existsWindowTouchingEdge{false}; bool m_isTouchingBusyVerticalView{false}; QRect m_availableScreenGeometry; SchemeColors *m_touchingWindowScheme{nullptr}; Latte::View *m_view{nullptr}; }; } } } #endif diff --git a/app/wm/tracker/windowstracker.cpp b/app/wm/tracker/windowstracker.cpp index 52f13df1..0dbec586 100644 --- a/app/wm/tracker/windowstracker.cpp +++ b/app/wm/tracker/windowstracker.cpp @@ -1,1057 +1,1119 @@ /* * 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 "lastactivewindow.h" #include "schemes.h" #include "trackedlayoutinfo.h" #include "trackedviewinfo.h" #include "../abstractwindowinterface.h" #include "../schemecolors.h" #include "../../apptypes.h" #include "../../lattecorona.h" #include "../../layout/genericlayout.h" #include "../../layouts/manager.h" #include "../../view/view.h" #include "../../view/positioner.h" namespace Latte { namespace WindowSystem { namespace Tracker { Windows::Windows(AbstractWindowInterface *parent) : QObject(parent) { m_wm = parent; m_extraViewHintsTimer.setInterval(600); m_extraViewHintsTimer.setSingleShot(true); connect(&m_extraViewHintsTimer, &QTimer::timeout, this, &Windows::updateExtraViewHints); //! delayed application data m_updateApplicationDataTimer.setInterval(1500); m_updateApplicationDataTimer.setSingleShot(true); connect(&m_updateApplicationDataTimer, &QTimer::timeout, this, &Windows::updateApplicationData); 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(); //! clear all the m_layouts tracking layouts for (QHash::iterator i=m_layouts.begin(); i!=m_layouts.end(); ++i) { i.value()->deleteLater(); m_layouts[i.key()] = nullptr; } m_layouts.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); updateAllHints(); emit windowChanged(wid); }); connect(m_wm, &AbstractWindowInterface::windowRemoved, this, [&](WindowId wid) { m_windows.remove(wid); //! application data m_initializedApplicationData.removeAll(wid); m_delayedApplicationData.removeAll(wid); updateAllHints(); emit windowRemoved(wid); }); connect(m_wm, &AbstractWindowInterface::windowAdded, this, [&](WindowId wid) { if (!m_windows.contains(wid)) { m_windows.insert(wid, m_wm->requestInfo(wid)); } updateAllHints(); }); connect(m_wm, &AbstractWindowInterface::activeWindowChanged, this, [&](WindowId wid) { //! for some reason this is needed in order to update properly activeness values //! when the active window changes the previous active windows should be also updated for (const auto view : m_views.keys()) { WindowId lastWinId = m_views[view]->lastActiveWindow()->winId(); if ((lastWinId) != wid && m_windows.contains(lastWinId)) { m_windows[lastWinId] = m_wm->requestInfo(lastWinId); } } m_windows[wid] = m_wm->requestInfo(wid); updateAllHints(); emit activeWindowChanged(wid); }); connect(m_wm, &AbstractWindowInterface::currentDesktopChanged, this, [&] { updateAllHints(); }); connect(m_wm, &AbstractWindowInterface::currentActivityChanged, this, [&] { if (m_wm->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { //! this is needed in MultipleLayouts because there is a chance that multiple //! layouts are providing different available screen geometries in different Activities updateAvailableScreenGeometries(); } updateAllHints(); }); } void Windows::initLayoutHints(Latte::Layout::GenericLayout *layout) { if (!m_layouts.contains(layout)) { return; } setActiveWindowMaximized(layout, false); setExistsWindowActive(layout, false); setExistsWindowMaximized(layout, false); setActiveWindowScheme(layout, nullptr); } void Windows::initViewHints(Latte::View *view) { if (!m_views.contains(view)) { return; } setActiveWindowMaximized(view, false); setActiveWindowTouching(view, false); + setActiveWindowTouchingEdge(view, false); setExistsWindowActive(view, false); setExistsWindowTouching(view, false); + setExistsWindowTouchingEdge(view, false); setExistsWindowMaximized(view, false); setIsTouchingBusyVerticalView(view, false); setActiveWindowScheme(view, nullptr); setTouchingWindowScheme(view, nullptr); } AbstractWindowInterface *Windows::wm() { return m_wm; } void Windows::addView(Latte::View *view) { if (m_views.contains(view)) { return; } m_views[view] = new TrackedViewInfo(this, view); updateAvailableScreenGeometries(); //! Consider Layouts addRelevantLayout(view); connect(view, &Latte::View::layoutChanged, this, [&, view]() { addRelevantLayout(view); }); connect(view, &Latte::View::isTouchingBottomViewAndIsBusyChanged, this, &Windows::updateExtraViewHints); connect(view, &Latte::View::isTouchingTopViewAndIsBusyChanged, this, &Windows::updateExtraViewHints); updateAllHints(); emit informationAnnounced(view); } void Windows::removeView(Latte::View *view) { if (!m_views.contains(view)) { return; } m_views[view]->deleteLater(); m_views.remove(view); updateRelevantLayouts(); } void Windows::addRelevantLayout(Latte::View *view) { if (view->layout()) { bool initializing {false}; if (!m_layouts.contains(view->layout())) { initializing = true; m_layouts[view->layout()] = new TrackedLayoutInfo(this, view->layout()); } //! Update always the AllScreens tracking because there is a chance a view delayed to be assigned in a layout //! and that could create a state the AllScreens tracking will be disabled if there is a View requesting //! tracking and one that it does not during startup updateRelevantLayouts(); if (initializing) { updateHints(view->layout()); emit informationAnnouncedForLayout(view->layout()); } } } void Windows::updateRelevantLayouts() { QList orphanedLayouts; //! REMOVE Orphaned Relevant layouts that have been removed or they don't contain any Views anymore for (QHash::iterator i=m_layouts.begin(); i!=m_layouts.end(); ++i) { bool hasView{false}; for (QHash::iterator j=m_views.begin(); j!=m_views.end(); ++j) { if (j.key() && i.key() && i.key() == j.key()->layout()) { hasView = true; break; } } if (!hasView) { if (i.value()) { i.value()->deleteLater(); } orphanedLayouts << i.key(); } } for(const auto &layout : orphanedLayouts) { m_layouts.remove(layout); } //! UPDATE Enabled layout window tracking based on the Views that are requesting windows tracking for (QHash::iterator i=m_layouts.begin(); i!=m_layouts.end(); ++i) { bool hasViewEnabled{false}; for (QHash::iterator j=m_views.begin(); j!=m_views.end(); ++j) { if (i.key() == j.key()->layout() && j.value()->enabled()) { hasViewEnabled = true; break; } } if (i.value()) { i.value()->setEnabled(hasViewEnabled); if (!hasViewEnabled) { initLayoutHints(i.key()); } } } } //! Views Properties And Hints bool Windows::enabled(Latte::View *view) { if (!m_views.contains(view)) { return false; } return m_views[view]->enabled(); } void Windows::setEnabled(Latte::View *view, const bool enabled) { if (!m_views.contains(view) || m_views[view]->enabled() == enabled) { return; } m_views[view]->setEnabled(enabled); if (enabled) { updateHints(view); } else { initViewHints(view); } updateRelevantLayouts(); emit enabledChanged(view); } bool Windows::activeWindowMaximized(Latte::View *view) const { if (!m_views.contains(view)) { return false; } return m_views[view]->activeWindowMaximized(); } void Windows::setActiveWindowMaximized(Latte::View *view, bool activeMaximized) { if (!m_views.contains(view) || m_views[view]->activeWindowMaximized() == activeMaximized) { return; } 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(); } void Windows::setActiveWindowTouching(Latte::View *view, bool activeTouching) { if (!m_views.contains(view) || m_views[view]->activeWindowTouching() == activeTouching) { return; } m_views[view]->setActiveWindowTouching(activeTouching); emit activeWindowTouchingChanged(view); } +bool Windows::activeWindowTouchingEdge(Latte::View *view) const +{ + if (!m_views.contains(view)) { + return false; + } + + return m_views[view]->activeWindowTouchingEdge(); +} + +void Windows::setActiveWindowTouchingEdge(Latte::View *view, bool activeTouchingEdge) +{ + if (!m_views.contains(view) || m_views[view]->activeWindowTouchingEdge() == activeTouchingEdge) { + return; + } + + m_views[view]->setActiveWindowTouchingEdge(activeTouchingEdge); + emit activeWindowTouchingEdgeChanged(view); +} + bool Windows::existsWindowActive(Latte::View *view) const { if (!m_views.contains(view)) { return false; } return m_views[view]->existsWindowActive(); } void Windows::setExistsWindowActive(Latte::View *view, bool windowActive) { if (!m_views.contains(view) || m_views[view]->existsWindowActive() == windowActive) { return; } 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(); } void Windows::setExistsWindowMaximized(Latte::View *view, bool windowMaximized) { if (!m_views.contains(view) || m_views[view]->existsWindowMaximized() == windowMaximized) { return; } 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(); } void Windows::setExistsWindowTouching(Latte::View *view, bool windowTouching) { if (!m_views.contains(view) || m_views[view]->existsWindowTouching() == windowTouching) { return; } m_views[view]->setExistsWindowTouching(windowTouching); emit existsWindowTouchingChanged(view); } +bool Windows::existsWindowTouchingEdge(Latte::View *view) const +{ + if (!m_views.contains(view)) { + return false; + } + + return m_views[view]->existsWindowTouchingEdge(); +} + +void Windows::setExistsWindowTouchingEdge(Latte::View *view, bool windowTouchingEdge) +{ + if (!m_views.contains(view) || m_views[view]->existsWindowTouchingEdge() == windowTouchingEdge) { + return; + } + + m_views[view]->setExistsWindowTouchingEdge(windowTouchingEdge); + emit existsWindowTouchingEdgeChanged(view); +} + + bool Windows::isTouchingBusyVerticalView(Latte::View *view) const { if (!m_views.contains(view)) { return false; } return m_views[view]->isTouchingBusyVerticalView(); } void Windows::setIsTouchingBusyVerticalView(Latte::View *view, bool viewTouching) { if (!m_views.contains(view) || m_views[view]->isTouchingBusyVerticalView() == viewTouching) { return; } m_views[view]->setIsTouchingBusyVerticalView(viewTouching); emit isTouchingBusyVerticalViewChanged(view); } SchemeColors *Windows::activeWindowScheme(Latte::View *view) const { if (!m_views.contains(view)) { return nullptr; } return m_views[view]->activeWindowScheme(); } void Windows::setActiveWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme) { if (!m_views.contains(view) || m_views[view]->activeWindowScheme() == scheme) { return; } 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(); } void Windows::setTouchingWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme) { if (!m_views.contains(view) || m_views[view]->touchingWindowScheme() == scheme) { return; } m_views[view]->setTouchingWindowScheme(scheme); emit touchingWindowSchemeChanged(view); } LastActiveWindow *Windows::lastActiveWindow(Latte::View *view) { if (!m_views.contains(view)) { return nullptr; } return m_views[view]->lastActiveWindow(); } //! Layouts bool Windows::enabled(Latte::Layout::GenericLayout *layout) { if (!m_layouts.contains(layout)) { return false; } return m_layouts[layout]->enabled(); } bool Windows::activeWindowMaximized(Latte::Layout::GenericLayout *layout) const { if (!m_layouts.contains(layout)) { return false; } return m_layouts[layout]->activeWindowMaximized(); } void Windows::setActiveWindowMaximized(Latte::Layout::GenericLayout *layout, bool activeMaximized) { if (!m_layouts.contains(layout) || m_layouts[layout]->activeWindowMaximized() == activeMaximized) { return; } m_layouts[layout]->setActiveWindowMaximized(activeMaximized); emit activeWindowMaximizedChangedForLayout(layout); } bool Windows::existsWindowActive(Latte::Layout::GenericLayout *layout) const { if (!m_layouts.contains(layout)) { return false; } return m_layouts[layout]->existsWindowActive(); } void Windows::setExistsWindowActive(Latte::Layout::GenericLayout *layout, bool windowActive) { if (!m_layouts.contains(layout) || m_layouts[layout]->existsWindowActive() == windowActive) { return; } m_layouts[layout]->setExistsWindowActive(windowActive); emit existsWindowActiveChangedForLayout(layout); } bool Windows::existsWindowMaximized(Latte::Layout::GenericLayout *layout) const { if (!m_layouts.contains(layout)) { return false; } return m_layouts[layout]->existsWindowMaximized(); } void Windows::setExistsWindowMaximized(Latte::Layout::GenericLayout *layout, bool windowMaximized) { if (!m_layouts.contains(layout) || m_layouts[layout]->existsWindowMaximized() == windowMaximized) { return; } m_layouts[layout]->setExistsWindowMaximized(windowMaximized); emit existsWindowMaximizedChangedForLayout(layout); } SchemeColors *Windows::activeWindowScheme(Latte::Layout::GenericLayout *layout) const { if (!m_layouts.contains(layout)) { return nullptr; } return m_layouts[layout]->activeWindowScheme(); } void Windows::setActiveWindowScheme(Latte::Layout::GenericLayout *layout, WindowSystem::SchemeColors *scheme) { if (!m_layouts.contains(layout) || m_layouts[layout]->activeWindowScheme() == scheme) { return; } m_layouts[layout]->setActiveWindowScheme(scheme); emit activeWindowSchemeChangedForLayout(layout); } LastActiveWindow *Windows::lastActiveWindow(Latte::Layout::GenericLayout *layout) { if (!m_layouts.contains(layout)) { return nullptr; } return m_layouts[layout]->lastActiveWindow(); } //! Windows bool Windows::isValidFor(const WindowId &wid) const { if (!m_windows.contains(wid)) { return false; } return m_windows[wid].isValid(); } QIcon Windows::iconFor(const WindowId &wid) { if (!m_windows.contains(wid)) { return QIcon(); } if (m_windows[wid].icon().isNull()) { AppData data = m_wm->appDataFor(wid); QIcon icon = data.icon; if (icon.isNull()) { icon = m_wm->iconFor(wid); } m_windows[wid].setIcon(icon); return icon; } return m_windows[wid].icon(); } QString Windows::appNameFor(const WindowId &wid) { if (!m_windows.contains(wid)) { return QString(); } if(!m_initializedApplicationData.contains(wid) && !m_delayedApplicationData.contains(wid)) { m_delayedApplicationData.append(wid); m_updateApplicationDataTimer.start(); } if (m_windows[wid].appName().isEmpty()) { AppData data = m_wm->appDataFor(wid); m_windows[wid].setAppName(data.name); return data.name; } return m_windows[wid].appName(); } void Windows::updateApplicationData() { if (m_delayedApplicationData.count() > 0) { for(int i=0; iappDataFor(wid); QIcon icon = data.icon; if (icon.isNull()) { icon = m_wm->iconFor(wid); } m_windows[wid].setIcon(icon); m_windows[wid].setAppName(data.name); m_initializedApplicationData.append(wid); emit applicationDataChanged(wid); } } } m_delayedApplicationData.clear(); } WindowInfoWrap Windows::infoFor(const WindowId &wid) const { if (!m_windows.contains(wid)) { return WindowInfoWrap(); } return m_windows[wid]; } //! Windows Criteria Functions 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())); } bool Windows::isMaximizedInViewScreen(Latte::View *view, 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 return (winfo.isValid() && !winfo.isMinimized() && !winfo.isShaded() && winfo.isMaximized() && 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 inViewThicknessEdge{false}; bool inViewLengthBoundaries{false}; QRect screenGeometry = view->screenGeometry(); bool inCurrentScreen{screenGeometry.contains(winfo.geometry().topLeft()) || screenGeometry.contains(winfo.geometry().bottomRight())}; if (inCurrentScreen) { if (view->location() == Plasma::Types::TopEdge) { inViewThicknessEdge = (winfo.geometry().y() == view->absoluteGeometry().bottom() + 1); } else if (view->location() == Plasma::Types::BottomEdge) { inViewThicknessEdge = (winfo.geometry().bottom() == view->absoluteGeometry().top() - 1); } else if (view->location() == Plasma::Types::LeftEdge) { inViewThicknessEdge = (winfo.geometry().x() == view->absoluteGeometry().right() + 1); } else if (view->location() == Plasma::Types::RightEdge) { inViewThicknessEdge = (winfo.geometry().right() == view->absoluteGeometry().left() - 1); } if (view->formFactor() == Plasma::Types::Horizontal) { int yCenter = view->absoluteGeometry().center().y(); QPoint leftChecker(winfo.geometry().left(), yCenter); QPoint rightChecker(winfo.geometry().right(), yCenter); bool fulloverlap = (winfo.geometry().left()<=view->absoluteGeometry().left()) && (winfo.geometry().right()>=view->absoluteGeometry().right()); inViewLengthBoundaries = fulloverlap || view->absoluteGeometry().contains(leftChecker) || view->absoluteGeometry().contains(rightChecker); } else if (view->formFactor() == Plasma::Types::Vertical) { int xCenter = view->absoluteGeometry().center().x(); QPoint topChecker(xCenter, winfo.geometry().top()); QPoint bottomChecker(xCenter, winfo.geometry().bottom()); bool fulloverlap = (winfo.geometry().top()<=view->absoluteGeometry().top()) && (winfo.geometry().bottom()>=view->absoluteGeometry().bottom()); inViewLengthBoundaries = fulloverlap || view->absoluteGeometry().contains(topChecker) || view->absoluteGeometry().contains(bottomChecker); } } return (inViewThicknessEdge && inViewLengthBoundaries); } return false; } void Windows::cleanupFaultyWindows() { for (const auto &key : m_windows.keys()) { auto winfo = m_windows[key]; //! garbage windows removing if (winfo.wid()<=0 || 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()) { int currentScrId = view->positioner()->currentScreenId(); QRect tempAvailableScreenGeometry = m_wm->corona()->availableScreenRectWithCriteria(currentScrId, QString(), m_ignoreModes, {}); if (tempAvailableScreenGeometry != m_views[view]->availableScreenGeometry()) { m_views[view]->setAvailableScreenGeometry(tempAvailableScreenGeometry); updateHints(view); } } } } void Windows::updateAllHints() { for (const auto view : m_views.keys()) { updateHints(view); } for (const auto layout : m_layouts.keys()) { updateHints(layout); } if (!m_extraViewHintsTimer.isActive()) { m_extraViewHintsTimer.start(); } } void Windows::updateExtraViewHints() { for (const auto horView : m_views.keys()) { if (!m_views.contains(horView) || !m_views[horView]->enabled() || !m_views[horView]->isTrackingCurrentActivity()) { continue; } if (horView->formFactor() == Plasma::Types::Horizontal) { bool touchingBusyVerticalView{false}; for (const auto verView : m_views.keys()) { if (!m_views.contains(verView) || !m_views[verView]->enabled() || !m_views[verView]->isTrackingCurrentActivity()) { continue; } bool sameScreen = (verView->positioner()->currentScreenId() == horView->positioner()->currentScreenId()); if (verView->formFactor() == Plasma::Types::Vertical && sameScreen) { bool topTouch = verView->isTouchingTopViewAndIsBusy() && horView->location() == Plasma::Types::TopEdge; bool bottomTouch = verView->isTouchingBottomViewAndIsBusy() && horView->location() == Plasma::Types::BottomEdge; if (topTouch || bottomTouch) { touchingBusyVerticalView = true; break; } } } //qDebug() << " Touching Busy Vertical View :: " << horView->location() << " - " << horView->positioner()->currentScreenId() << " :: " << touchingBusyVerticalView; setIsTouchingBusyVerticalView(horView, touchingBusyVerticalView); } } } void Windows::updateHints(Latte::View *view) { if (!m_views.contains(view) || !m_views[view]->enabled() || !m_views[view]->isTrackingCurrentActivity()) { return; } bool foundActive{false}; bool foundActiveInCurScreen{false}; bool foundActiveTouchInCurScreen{false}; + bool foundActiveEdgeTouchInCurScreen{false}; bool foundTouchInCurScreen{false}; + bool foundTouchEdgeInCurScreen{false}; bool foundMaximizedInCurScreen{false}; bool foundActiveGroupTouchInCurScreen{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 touchEdgeWinId; WindowId activeTouchWinId; + WindowId activeTouchEdgeWinId; //qDebug() << " -- TRACKING REPORT (SCREEN)--"; //! First Pass for (const auto &winfo : m_windows) { if (!existsFaultyWindow && (winfo.wid()<=0 || winfo.geometry() == QRect(0, 0, 0, 0))) { existsFaultyWindow = true; } if ( !m_wm->inCurrentDesktopActivity(winfo) || m_wm->hasBlockedTracking(winfo.wid()) || winfo.isMinimized()) { continue; } //qDebug() << " _ _ _ "; //qDebug() << "TRACKING | WINDOW INFO :: " << winfo.wid() << " _ " << winfo.appName() << " _ " << winfo.geometry() << " _ " << winfo.display(); if (isActive(winfo)) { foundActive = true; } if (isActiveInViewScreen(view, winfo)) { foundActiveInCurScreen = true; activeWinId = winfo.wid(); } //! Maximized windows flags if ((winfo.isActive() && isMaximizedInViewScreen(view, winfo)) //! active maximized windows have higher priority than the rest maximized windows || (!foundMaximizedInCurScreen && isMaximizedInViewScreen(view, winfo))) { foundMaximizedInCurScreen = true; maxWinId = winfo.wid(); } //! Touching windows flags bool touchingViewEdge = isTouchingViewEdge(view, winfo); bool touchingView = isTouchingView(view, winfo); - if (touchingViewEdge || touchingView) { + if (touchingView) { if (winfo.isActive()) { foundActiveTouchInCurScreen = true; activeTouchWinId = winfo.wid(); } else { foundTouchInCurScreen = true; touchWinId = winfo.wid(); } } + if (touchingViewEdge) { + if (winfo.isActive()) { + foundActiveEdgeTouchInCurScreen = true; + activeTouchEdgeWinId = winfo.wid(); + } else { + foundTouchEdgeInCurScreen = true; + touchEdgeWinId = winfo.wid(); + } + } + //qDebug() << "TRACKING | ACTIVE:"<< foundActive << " ACT_CUR_SCR:" << foundTouchInCurScreen << " MAXIM:"<inCurrentDesktopActivity(winfo) || m_wm->hasBlockedTracking(winfo.wid()) || winfo.isMinimized()) { continue; } bool inActiveGroup = (winfo.wid() == mainWindowId || winfo.parentId() == mainWindowId); //! consider only windows that belong to active window group meaning the main window //! and its children if (!inActiveGroup) { continue; } - if (isTouchingViewEdge(view, winfo) || isTouchingView(view, winfo)) { + if (isTouchingView(view, winfo)) { foundActiveGroupTouchInCurScreen = true; break; } } } //! 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 || foundActiveGroupTouchInCurScreen); + setActiveWindowTouchingEdge(view, foundActiveEdgeTouchInCurScreen); setActiveWindowMaximized(view, (maxWinId.toInt()>0 && (maxWinId == activeTouchWinId))); setExistsWindowMaximized(view, foundMaximizedInCurScreen); setExistsWindowTouching(view, (foundTouchInCurScreen || foundActiveTouchInCurScreen || foundActiveGroupTouchInCurScreen)); + setExistsWindowTouchingEdge(view, (foundActiveEdgeTouchInCurScreen || foundTouchEdgeInCurScreen)); //! 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 (foundActiveEdgeTouchInCurScreen) { + setTouchingWindowScheme(view, m_wm->schemesTracker()->schemeForWindow(activeTouchEdgeWinId)); } else if (foundMaximizedInCurScreen) { setTouchingWindowScheme(view, m_wm->schemesTracker()->schemeForWindow(maxWinId)); } else if (foundTouchInCurScreen) { setTouchingWindowScheme(view, m_wm->schemesTracker()->schemeForWindow(touchWinId)); + } else if (foundTouchEdgeInCurScreen) { + setTouchingWindowScheme(view, m_wm->schemesTracker()->schemeForWindow(touchEdgeWinId)); } else { setTouchingWindowScheme(view, nullptr); } //! update LastActiveWindow if (foundActiveInCurScreen) { m_views[view]->setActiveWindow(activeWinId); } //! Debug //qDebug() << "TRACKING | _________ FINAL RESULTS ________"; //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:"<enabled() || !m_layouts[layout]->isTrackingCurrentActivity()) { return; } bool foundActive{false}; bool foundActiveMaximized{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 activeWinId; WindowId maxWinId; for (const auto &winfo : m_windows) { if (!existsFaultyWindow && (winfo.wid()<=0 || winfo.geometry() == QRect(0, 0, 0, 0))) { existsFaultyWindow = true; } if (!m_wm->inCurrentDesktopActivity(winfo) || m_wm->hasBlockedTracking(winfo.wid()) || winfo.isMinimized()) { continue; } if (isActive(winfo)) { foundActive = true; activeWinId = winfo.wid(); if (winfo.isMaximized() && !winfo.isMinimized()) { foundActiveMaximized = true; maxWinId = winfo.wid(); } } if (!foundActiveMaximized && winfo.isMaximized() && !winfo.isMinimized()) { foundMaximized = true; maxWinId = winfo.wid(); } //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(layout, foundActive); setActiveWindowMaximized(layout, foundActiveMaximized); setExistsWindowMaximized(layout, foundActiveMaximized || foundMaximized); //! update color schemes for active and touching windows setActiveWindowScheme(layout, (foundActive ? m_wm->schemesTracker()->schemeForWindow(activeWinId) : nullptr)); //! update LastActiveWindow if (foundActive) { m_layouts[layout]->setActiveWindow(activeWinId); } //! Debug //qDebug() << " -- TRACKING REPORT (LAYOUT) --"; //qDebug() << "TRACKING | LAYOUT: " << layout->name() << " , ENABLED:" << enabled(layout); //qDebug() << "TRACKING | existsActiveWindow: " << foundActive << " ,activeWindowMaximized: " << foundActiveMaximized; //qDebug() << "TRACKING | existsWindowMaximized: " << existsWindowMaximized(layout); } } } } diff --git a/app/wm/tracker/windowstracker.h b/app/wm/tracker/windowstracker.h index 3e4aadcb..dfef081e 100644 --- a/app/wm/tracker/windowstracker.h +++ b/app/wm/tracker/windowstracker.h @@ -1,203 +1,209 @@ /* * 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 WINDOWSYSTEMWINDOWSTRACKER_H #define WINDOWSYSTEMWINDOWSTRACKER_H // local #include #include "../windowinfowrap.h" // Qt #include #include #include #include namespace Latte { class View; namespace Layout { class GenericLayout; } namespace WindowSystem { class AbstractWindowInterface; class SchemeColors; namespace Tracker { class LastActiveWindow; class TrackedLayoutInfo; class TrackedViewInfo; } } } namespace Latte { namespace WindowSystem { namespace Tracker { class Windows : public QObject { Q_OBJECT public: Windows(AbstractWindowInterface *parent); ~Windows() override; void addView(Latte::View *view); void removeView(Latte::View *view); //! Views Tracking (current screen specific) 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 activeWindowTouchingEdge(Latte::View *view) const; bool existsWindowActive(Latte::View *view) const; bool existsWindowMaximized(Latte::View *view) const; bool existsWindowTouching(Latte::View *view) const; + bool existsWindowTouchingEdge(Latte::View *view) const; bool isTouchingBusyVerticalView(Latte::View *view) const; SchemeColors *activeWindowScheme(Latte::View *view) const; SchemeColors *touchingWindowScheme(Latte::View *view) const; LastActiveWindow *lastActiveWindow(Latte::View *view); //! Layouts Tracking (all screens) bool enabled(Latte::Layout::GenericLayout *layout); bool activeWindowMaximized(Latte::Layout::GenericLayout *layout) const; bool existsWindowActive(Latte::Layout::GenericLayout *layout) const; bool existsWindowMaximized(Latte::Layout::GenericLayout *layout) const; SchemeColors *activeWindowScheme(Latte::Layout::GenericLayout *layout) const; LastActiveWindow *lastActiveWindow(Latte::Layout::GenericLayout *layout); //! Windows management bool isValidFor(const WindowId &wid) const; QIcon iconFor(const WindowId &wid); QString appNameFor(const WindowId &wid); WindowInfoWrap infoFor(const WindowId &wid) const; AbstractWindowInterface *wm(); signals: //! Views void enabledChanged(const Latte::View *view); void activeWindowMaximizedChanged(const Latte::View *view); void activeWindowTouchingChanged(const Latte::View *view); + void activeWindowTouchingEdgeChanged(const Latte::View *view); void existsWindowActiveChanged(const Latte::View *view); void existsWindowMaximizedChanged(const Latte::View *view); void existsWindowTouchingChanged(const Latte::View *view); + void existsWindowTouchingEdgeChanged(const Latte::View *view); void isTouchingBusyVerticalViewChanged(const Latte::View *view); void activeWindowSchemeChanged(const Latte::View *view); void touchingWindowSchemeChanged(const Latte::View *view); void informationAnnounced(const Latte::View *view); //! Layouts void enabledChangedForLayout(const Latte::Layout::GenericLayout *layout); void activeWindowMaximizedChangedForLayout(const Latte::Layout::GenericLayout *layout); void existsWindowActiveChangedForLayout(const Latte::Layout::GenericLayout *layout); void existsWindowMaximizedChangedForLayout(const Latte::Layout::GenericLayout *layout); void activeWindowSchemeChangedForLayout(const Latte::Layout::GenericLayout *layout); void informationAnnouncedForLayout(const Latte::Layout::GenericLayout *layout); //! overloading WM signals in order to update first m_windows and afterwards //! inform consumers for window changes void activeWindowChanged(const WindowId &wid); void windowChanged(const WindowId &wid); void windowRemoved(const WindowId &wid); void applicationDataChanged(const WindowId &wid); private slots: void updateAvailableScreenGeometries(); void addRelevantLayout(Latte::View *view); void updateApplicationData(); void updateRelevantLayouts(); void updateExtraViewHints(); private: void init(); void initLayoutHints(Latte::Layout::GenericLayout *layout); void initViewHints(Latte::View *view); void cleanupFaultyWindows(); void updateAllHints(); //! Views void updateHints(Latte::View *view); void updateHints(Latte::Layout::GenericLayout *layout); void setActiveWindowMaximized(Latte::View *view, bool activeMaximized); void setActiveWindowTouching(Latte::View *view, bool activeTouching); + void setActiveWindowTouchingEdge(Latte::View *view, bool activeTouchingEdge); void setExistsWindowActive(Latte::View *view, bool windowActive); void setExistsWindowMaximized(Latte::View *view, bool windowMaximized); void setExistsWindowTouching(Latte::View *view, bool windowTouching); + void setExistsWindowTouchingEdge(Latte::View *view, bool windowTouchingEdge); void setIsTouchingBusyVerticalView(Latte::View *view, bool viewTouching); void setActiveWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme); void setTouchingWindowScheme(Latte::View *view, WindowSystem::SchemeColors *scheme); //! Layouts void setActiveWindowMaximized(Latte::Layout::GenericLayout *layout, bool activeMaximized); void setExistsWindowActive(Latte::Layout::GenericLayout *layout, bool windowActive); void setExistsWindowMaximized(Latte::Layout::GenericLayout *layout, bool windowMaximized); void setActiveWindowScheme(Latte::Layout::GenericLayout *layout, WindowSystem::SchemeColors *scheme); //! Windows 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: //! a timer in order to not overload the views extra hints checking because it is not //! really needed that often QTimer m_extraViewHintsTimer; AbstractWindowInterface *m_wm; QHash m_views; QHash m_layouts; //! Accept only ALWAYSVISIBLE visibility mode QList m_ignoreModes{ Latte::Types::AutoHide, Latte::Types::DodgeActive, Latte::Types::DodgeMaximized, Latte::Types::DodgeAllWindows, Latte::Types::WindowsGoBelow, Latte::Types::WindowsCanCover, Latte::Types::WindowsAlwaysCover, Latte::Types::SideBar }; QMap m_windows; //! Some applications delay their application name/icon identification //! such as Libreoffice that updates its StartupWMClass after //! its startup QTimer m_updateApplicationDataTimer; QList m_delayedApplicationData; QList m_initializedApplicationData; }; } } } #endif diff --git a/containment/package/contents/ui/colorizer/Manager.qml b/containment/package/contents/ui/colorizer/Manager.qml index 10a080fd..a263fcac 100644 --- a/containment/package/contents/ui/colorizer/Manager.qml +++ b/containment/package/contents/ui/colorizer/Manager.qml @@ -1,207 +1,207 @@ /* * Copyright 2018 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 . */ import QtQuick 2.7 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.private.containment 0.1 as LatteContainment import "../../code/ColorizerTools.js" as ColorizerTools Loader{ id: manager //! the loader loads the backgroundTracker component active: root.themeColors === LatteContainment.Types.SmartThemeColors readonly property bool backgroundIsBusy: item ? item.isBusy : false readonly property real originalThemeTextColorBrightness: ColorizerTools.colorBrightness(theme.textColor) readonly property color originalLightTextColor: originalThemeTextColorBrightness > 127.5 ? theme.textColor : theme.backgroundColor readonly property real themeTextColorBrightness: ColorizerTools.colorBrightness(textColor) readonly property real backgroundColorBrightness: ColorizerTools.colorBrightness(backgroundColor) readonly property color minimizedDotColor: themeTextColorBrightness > 127.5 ? Qt.darker(textColor, 1.7) : Qt.lighter(textColor, 8) readonly property color focusGlowColor: Qt.hsva(buttonFocusColor.h, buttonFocusColor.s, 1.0, 1.0) readonly property color outlineColorBase: backgroundColor readonly property real outlineColorBaseBrightness: ColorizerTools.colorBrightness(outlineColorBase) readonly property color outlineColor: { if (!root.panelOutline) { return backgroundColor; } if (outlineColorBaseBrightness > 127.5) { return Qt.darker(outlineColorBase, 1.5); } else { return Qt.lighter(outlineColorBase, 2.2); } } readonly property bool editModeTextColorIsBright: ColorizerTools.colorBrightness(editModeTextColor) > 127.5 readonly property color editModeTextColor: latteView && latteView.layout ? latteView.layout.textColor : "white" readonly property bool mustBeShown: (applyTheme && applyTheme !== theme) || (root.inConfigureAppletsMode && (root.themeColors === LatteContainment.Types.SmartThemeColors)) readonly property real currentBackgroundBrightness: item ? item.currentBrightness : -1000 readonly property bool applyingWindowColors: (root.windowColors === LatteContainment.Types.ActiveWindowColors && latteView && latteView.windowsTracker && selectedWindowsTracker.activeWindowScheme) || (root.windowColors === LatteContainment.Types.TouchingWindowColors && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.touchingWindowScheme) property QtObject applyTheme: { if (!graphicsSystem.isAccelerated) { return theme; } if (latteView && latteView.windowsTracker && !root.hasExpandedApplet) { if (root.windowColors === LatteContainment.Types.ActiveWindowColors && selectedWindowsTracker.activeWindowScheme) { return selectedWindowsTracker.activeWindowScheme; } if (root.windowColors === LatteContainment.Types.TouchingWindowColors && latteView.windowsTracker.currentScreen.touchingWindowScheme) { //! we must track touching windows and when they are not ative //! the active window scheme is used for convenience - if (latteView.windowsTracker.currentScreen.existsWindowTouching - && !latteView.windowsTracker.currentScreen.activeWindowTouching + if (latteView.windowsTracker.currentScreen.existsWindowTouching || latteView.windowsTracker.currentScreen.existsWindowTouchingEdge + && !(latteView.windowsTracker.currentScreen.activeWindowTouching || latteView.windowsTracker.currentScreen.activeWindowTouchingEdge) && latteView.windowsTracker.currentScreen.activeWindowScheme) { return latteView.windowsTracker.currentScreen.activeWindowScheme; } return latteView.windowsTracker.currentScreen.touchingWindowScheme; } } if (themeExtended) { if (root.userShowPanelBackground && root.plasmaBackgroundForPopups && root.hasExpandedApplet /*for expanded popups when it is enabled*/ || root.plasmaStyleBusyForTouchingBusyVerticalView || (root.themeColors === LatteContainment.Types.SmartThemeColors /*for Smart theming that Windows colors are not used and the user wants solidness at some cases*/ && root.windowColors === LatteContainment.Types.NoneWindowColors && root.forceSolidPanel) ) { /* plasma style*/ return theme; } if (root.themeColors === LatteContainment.Types.ReverseThemeColors) { return themeExtended.isLightTheme ? themeExtended.darkTheme : themeExtended.lightTheme; } if (root.themeColors === LatteContainment.Types.SmartThemeColors) { //! Smart Colors Case if (!root.forcePanelForBusyBackground) { //! simple case that not a busy background is applied return currentBackgroundBrightness > 127.5 ? themeExtended.lightTheme : themeExtended.darkTheme; } else { //! Smart + Busy background case var themeContrastedTextColor = currentBackgroundBrightness > 127.5 ? themeExtended.lightTheme : themeExtended.darkTheme; var themeContrastedBackground = currentBackgroundBrightness > 127.5 ? themeExtended.darkTheme : themeExtended.lightTheme; if (root.panelTransparency < 35) { //! textColor should be better to provide the needed contrast return themeContrastedTextColor; } else if (root.panelTransparency >= 35 && root.panelTransparency <= 70) { //! provide a dark case scenario at all cases return themeExtended.darkTheme; } else { //! default plasma theme should be better for panel transparency > 70 return theme; } } } } return theme; } property color applyColor: textColor readonly property color backgroundColor:applyTheme.backgroundColor readonly property color textColor: { if (latteView && latteView.layout && root.inConfigureAppletsMode && LatteCore.WindowSystem.compositingActive && root.panelTransparency<40 && (root.themeColors === LatteContainment.Types.SmartThemeColors)) { return latteView.layout.textColor; } return applyTheme.textColor; } readonly property color inactiveBackgroundColor: applyTheme === theme ? theme.backgroundColor : applyTheme.inactiveBackgroundColor readonly property color inactiveTextColor: applyTheme === theme ? theme.textColor : applyTheme.inactiveTextColor readonly property color highlightColor: applyTheme.highlightColor readonly property color highlightedTextColor: applyTheme.highlightedTextColor readonly property color positiveTextColor: applyTheme.positiveTextColor readonly property color neutralTextColor: applyTheme.neutralTextColor readonly property color negativeTextColor: applyTheme.negativeTextColor readonly property color buttonTextColor: applyTheme.buttonTextColor readonly property color buttonBackgroundColor: applyTheme.buttonBackgroundColor readonly property color buttonHoverColor: applyTheme.buttonHoverColor readonly property color buttonFocusColor: applyTheme.buttonFocusColor readonly property string scheme: { if (root.inConfigureAppletsMode && (root.themeColors === LatteContainment.Types.SmartThemeColors)) { if (!LatteCore.WindowSystem.compositingActive && applyTheme !== theme) { return applyTheme.schemeFile; } //! in edit mode (that is shown the edit visual without opacity) //! take care the applets that need a proper color scheme to paint themselves if ((editModeTextColorIsBright && themeExtended.isLightTheme) || (!editModeTextColorIsBright && !themeExtended.isLightTheme)) { if (themeExtended.darkTheme === themeExtended.defaultTheme) { console.log("light theme... : " + themeExtended.isLightTheme); return themeExtended.lightTheme.schemeFile; } else { console.log("dark theme... : " + themeExtended.isDarkTheme); return themeExtended.darkTheme.schemeFile; } } else { console.log("default theme... : " + themeExtended.isLightTheme); return themeExtended.defaultTheme.schemeFile; } } if (applyTheme===theme || !mustBeShown) { if (themeExtended) { return themeExtended.defaultTheme.schemeFile; } else { return "kdeglobals"; } } return applyTheme.schemeFile; } sourceComponent: LatteApp.BackgroundTracker { activity: viewLayout ? viewLayout.lastUsedActivity : "" location: plasmoid.location screenName: latteView && latteView.positioner ? latteView.positioner.currentScreenName : "" } } diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index df6e31f5..74a746f1 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1693 +1,1697 @@ /* * Copyright 2016 Smith AR * 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 . */ import QtQuick 2.8 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.private.containment 0.1 as LatteContainment import "abilities" as Ability import "applet" as Applet import "colorizer" as Colorizer import "editmode" as EditMode import "indicators" as Indicators import "layouts" as Layouts import "./background" as Background import "./debug" as Debug import "../code/LayoutManager.js" as LayoutManager Item { id: root objectName: "containmentViewLayout" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical LayoutMirroring.childrenInherit: true //// BEGIN SIGNALS signal destroyInternalViewSplitters(); signal emptyAreasWheel(QtObject wheel); signal separatorsUpdated(); signal signalActivateEntryAtIndex(int entryIndex); signal signalNewInstanceForEntryAtIndex(int entryIndex); signal updateEffectsArea(); signal updateIndexes(); signal broadcastedToApplet(string pluginName, string action, variant value); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeLayouter: Qt.application.arguments.indexOf("--layouter")>=0 property bool debugModeLocalGeometry: Qt.application.arguments.indexOf("--localgeometry")>=0 property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0 property bool debugModeTimers: Qt.application.arguments.indexOf("--timers")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool debugModeOverloadedIcons: Qt.application.arguments.indexOf("--overloaded-icons")>=0 readonly property int version: LatteCore.Environment.makeVersion(0,9,4) property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!LatteCore.WindowSystem.compositingActive) { //! In NOCOMPOSITING mode VIEWS should behave as real windows and that way //! we gain also the snapping features from KWin return true; } if (!latteView || !latteView.visibility) { return false; } if (screenEdgeMarginEnabled && plasmoid.configuration.fittsLawIsRequested) { //! dont use when floating views are requesting Fitt's Law return false; } var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); return (visibilityManager.panelIsBiggerFromIconSize && (parabolic.factor.maxZoom === 1.0) && (plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) && !root.editMode && !visibilityManager.inLocationAnimation); } readonly property bool behaveAsDockWithMask: !behaveAsPlasmaPanel readonly property bool viewIsAvailable: latteView && latteView.visibility && latteView.effects property int viewType: { var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); if ((plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) && (plasmoid.configuration.useThemePanel) && (plasmoid.configuration.panelSize === 100) && (parabolic.factor.maxZoom === 1.0)) { return LatteCore.Types.PanelView; } return LatteCore.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) readonly property bool ignoreRegularFilesDragging: !root.editMode && (dragInfo.computationsAreValid || foreDropArea.dragInfo.computationsAreValid) && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers readonly property Item dragInfo: Item { property bool entered: backDropArea.dragInfo.entered || foreDropArea.dragInfo.entered property bool isTask: backDropArea.dragInfo.isTask || foreDropArea.dragInfo.isTask property bool isPlasmoid: backDropArea.dragInfo.isPlasmoid || foreDropArea.dragInfo.isPlasmoid property bool isSeparator: backDropArea.dragInfo.isSeparator || foreDropArea.dragInfo.isSeparator property bool isLatteTasks: backDropArea.dragInfo.isLatteTasks || foreDropArea.dragInfo.isLatteTasks property bool onlyLaunchers: backDropArea.dragInfo.onlyLaunchers || foreDropArea.dragInfo.onlyLaunchers // onIsPlasmoidChanged: console.log("isPlasmoid :: " + backDropArea.dragInfo.isPlasmoid + " _ " + foreDropArea.dragInfo.isPlasmoid ); // onEnteredChanged: console.log("entered :: " + backDropArea.dragInfo.entered + " _ " + foreDropArea.dragInfo.entered ); } property bool containsOnlyPlasmaTasks: false //this is flag to indicate when from tasks only a plasma based one is found property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && LatteCore.WindowSystem.compositingActive property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel && !visibilityManager.inTempHiding property bool editMode: editModeVisual.inEditMode property bool windowIsTouching: latteView && latteView.windowsTracker - && (latteView.windowsTracker.currentScreen.activeWindowTouching || hasExpandedApplet) + && (latteView.windowsTracker.currentScreen.activeWindowTouching + || latteView.windowsTracker.currentScreen.activeWindowTouchingEdge + || hasExpandedApplet) property bool forceSolidPanel: (latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && userShowPanelBackground && ( (plasmoid.configuration.solidBackgroundForMaximized && !(hasExpandedApplet && !plasmaBackgroundForPopups) - && latteView.windowsTracker.currentScreen.existsWindowTouching) + && (latteView.windowsTracker.currentScreen.existsWindowTouching + || latteView.windowsTracker.currentScreen.existsWindowTouchingEdge)) || (hasExpandedApplet && plasmaBackgroundForPopups) )) || solidBusyForTouchingBusyVerticalView || plasmaStyleBusyForTouchingBusyVerticalView || !LatteCore.WindowSystem.compositingActive property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && !forceSolidPanel - && !latteView.windowsTracker.currentScreen.existsWindowTouching + && !(latteView.windowsTracker.currentScreen.existsWindowTouching + || latteView.windowsTracker.currentScreen.existsWindowTouchingEdge) && !(windowColors === LatteContainment.Types.ActiveWindowColors && selectedWindowsTracker.existsWindowActive) property bool forcePanelForBusyBackground: userShowPanelBackground && (root.themeColors === LatteContainment.Types.SmartThemeColors) && ( (root.forceTransparentPanel && colorizerManager.backgroundIsBusy) || normalBusyForTouchingBusyVerticalView ) property bool normalBusyForTouchingBusyVerticalView: (latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers isBusy transparency*/ && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized /*&& !plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups*/) property bool solidBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case /*(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups)*/ property bool plasmaStyleBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case //(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmaBackgroundForPopups)*/ property bool hideThickScreenGap: screenEdgeMarginEnabled && plasmoid.configuration.hideScreenGapForMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.existsWindowMaximized property bool hideLengthScreenGaps: hideThickScreenGap && (latteView.visibility.mode === LatteCore.Types.AlwaysVisible || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && plasmoid.configuration.maxLength>85 && !root.editMode property int themeColors: plasmoid.configuration.themeColors property int windowColors: plasmoid.configuration.windowColors property bool colorizerEnabled: themeColors !== LatteContainment.Types.PlasmaThemeColors || windowColors !== LatteContainment.Types.NoneWindowColors property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups readonly property bool hasExpandedApplet: latteView && latteView.extendedInterface.hasExpandedApplet; readonly property bool hasUserSpecifiedBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? true : false readonly property bool inConfigureAppletsMode: root.editMode && (plasmoid.configuration.inConfigureAppletsMode || !LatteCore.WindowSystem.compositingActive) readonly property bool parabolicEffectEnabled: parabolic.factor.zoom>1 && !inConfigureAppletsMode property bool dockIsShownCompletely: !(dockIsHidden || inSlidingIn || inSlidingOut) && !root.editMode property bool closeActiveWindowEnabled: plasmoid.configuration.closeActiveWindowEnabled property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled property bool immutable: plasmoid.immutable property bool inFullJustify: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (maxLengthPerCentage===100) property bool inSlidingIn: visibilityManager ? visibilityManager.inSlidingIn : false property bool inSlidingOut: visibilityManager ? visibilityManager.inSlidingOut : false property bool inStartup: true property bool isHalfShown: false //is used to disable the zoom hovering effect at sliding in-out the dock property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal property bool isReady: !(dockIsHidden || inSlidingIn || inSlidingOut) property bool isVertical: !isHorizontal property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions property bool onlyAddingStarup: true //is used for the initialization phase in startup where there aren't removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins property bool showLatteShortcutBadges: false property bool showAppletShortcutBadges: false property bool showMetaBadge: false property int applicationLauncherId: -1 //FIXME: possibly this is going to be the default behavior, this user choice //has been dropped from the Dock Configuration Window //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps property bool smallAutomaticIconJumps: true property bool userShowPanelBackground: LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true property bool useThemePanel: noApplets === 0 || !LatteCore.WindowSystem.compositingActive ? true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) property bool plasma515: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) property bool plasma518: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) readonly property int minAppletLengthInConfigure: 16 readonly property int maxJustifySplitterSize: 64 property int latteAppletPos: -1 property real minLengthPerCentage: plasmoid.configuration.minLength property real maxLengthPerCentage: hideLengthScreenGaps ? 100 : plasmoid.configuration.maxLength property int minLength: { if (root.panelAlignment === LatteCore.Types.Justify) { return maxLength; } if (root.isHorizontal) { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? width : width * (minLengthPerCentage/100) } else { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? height : height * (minLengthPerCentage/100) } } property int maxLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel ? width : width * (maxLengthPerCentage/100) } else { return behaveAsPlasmaPanel ? height : height * (maxLengthPerCentage/100) } } property int scrollAction: plasmoid.configuration.scrollAction property bool panelOutline: plasmoid.configuration.panelOutline property int panelEdgeSpacing: Math.max(background.lengthMargins, 1.5*appShadowSize) property int panelTransparency: plasmoid.configuration.panelTransparency //user set property bool panelShadowsActive: { if (!userShowPanelBackground) { return false; } if (inConfigureAppletsMode) { return plasmoid.configuration.panelShadows; } var forcedNoShadows = (plasmoid.configuration.panelShadows && disablePanelShadowMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.activeWindowMaximized); if (forcedNoShadows) { return false; } var transparencyCheck = (blurEnabled || (!blurEnabled && background.currentOpacity>20)); //! Draw shadows for isBusy state only when current panelTransparency is greater than 10% if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && transparencyCheck) { return true; } if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !forcedNoShadows) { return true; } if (hasExpandedApplet && plasmaBackgroundForPopups) { return true; } return false; } property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 property int appShadowSize: enableShadows ? (0.5*metrics.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 property int appShadowSizeOriginal: enableShadows ? (0.5*metrics.maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 property string appChosenShadowColor: { if (plasmoid.configuration.shadowColorType === LatteContainment.Types.ThemeColorShadow) { var strC = String(theme.textColor); return strC.indexOf("#") === 0 ? strC.substr(1) : strC; } else if (plasmoid.configuration.shadowColorType === LatteContainment.Types.UserColorShadow) { return plasmoid.configuration.shadowColor; } // default shadow color return "080808"; } property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + appChosenShadowColor property string appShadowColorSolid: "#" + appChosenShadowColor property int offset: { if (behaveAsPlasmaPanel) { return 0; } if (root.isHorizontal) { return width * (plasmoid.configuration.offset/100); } else { height * (plasmoid.configuration.offset/100) } } property int editShadow: { if (!LatteCore.WindowSystem.compositingActive) { return 0; } else if (latteView && latteView.screenGeometry) { return latteView.screenGeometry.height/90; } else { return 7; } } property bool screenEdgeMarginEnabled: plasmoid.configuration.screenEdgeMargin >= 0 && !plasmoid.configuration.shrinkThickMargins property int widthMargins: root.isVertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int heightMargins: root.isHorizontal ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int panelAlignment: plasmoid.configuration.alignment readonly property string plasmoidName: "org.kde.latte.plasmoid" property var badgesForActivate: { if (!shortcutsEngine) { return ['1','2','3','4','5','6','7','8','9','0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']; } return shortcutsEngine.badgesForActivate; } property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet readonly property alias animations: _animations readonly property alias background: _background readonly property alias autosize: _autosize readonly property alias indexer: _indexer readonly property alias indicatorsManager: indicators readonly property alias layouter: _layouter readonly property alias metrics: _metrics readonly property alias parabolic: _parabolic readonly property alias parabolicManager: _parabolicManager readonly property alias maskManager: visibilityManager readonly property alias layoutsContainerItem: layoutsContainer readonly property alias latteView: _interfaces.view readonly property alias layoutsManager: _interfaces.layoutsManager readonly property alias shortcutsEngine: _interfaces.globalShortcuts readonly property alias themeExtended: _interfaces.themeExtended readonly property alias universalSettings: _interfaces.universalSettings readonly property QtObject viewLayout: latteView && latteView.layout ? latteView.layout : null readonly property QtObject selectedWindowsTracker: { if (latteView && latteView.windowsTracker) { switch(plasmoid.configuration.activeWindowFilter) { case LatteContainment.Types.ActiveInCurrentScreen: return latteView.windowsTracker.currentScreen; case LatteContainment.Types.ActiveFromAllScreens: return latteView.windowsTracker.allScreens; } } return null; } // TO BE DELETED, if not needed: property int counter:0; ///BEGIN properties provided to Latte Plasmoid //shadows for applets, it should be removed as the appleitems don't need it any more property bool badges3DStyle: universalSettings ? universalSettings.badges3DStyle : true property bool enableShadows: plasmoid.configuration.appletShadowsEnabled property bool dockIsHidden: latteView && latteView.visibility ? latteView.visibility.isHidden : true property bool titleTooltips: plasmoid.configuration.titleTooltips property bool unifiedGlobalShortcuts: true property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property color minimizedDotColor: colorizerManager.minimizedDotColor ///END properties from latteApplet Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground //// BEGIN properties in functions property int noApplets: { var count1 = 0; var count2 = 0; count1 = layoutsContainer.mainLayout.children.length; var tempLength = layoutsContainer.mainLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.mainLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count1--; } count2 = layoutsContainer.endLayout.children.length; tempLength = layoutsContainer.endLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.endLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count2--; } return (count1 + count2); } ///The index of user's current icon size property int currentIconIndex:{ for(var i=iconsArray.length-1; i>=0; --i){ if(iconsArray[i] === metrics.iconSize){ return i; } } return 3; } //// END properties in functions ////////////////END properties //// BEGIN OF Behaviors Behavior on offset { enabled: editModeVisual.editAnimationInFullThickness NumberAnimation { id: offsetAnimation duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } //// END OF Behaviors //////////////START OF CONNECTIONS onEditModeChanged: { if (!editMode) { layouter.updateSizeForAppletsInFill(); } //! This is used in case the dndspacer has been left behind //! e.g. the user drops a folder and a context menu is appearing //! but the user decides to not make a choice for the applet type if (dndSpacer.parent !== root) { dndSpacer.parent = root; } } onInConfigureAppletsModeChanged: { updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup onPanelAlignmentChanged: { if (!root.editMode) { return; } if (root.editMode/*!inConfigureAppletsMode*/){ if (panelAlignment===LatteCore.Types.Justify) { addInternalViewSplitters(); splitMainLayoutToLayouts(); } else { joinLayoutsToMainLayout(); root.destroyInternalViewSplitters(); } } LayoutManager.save(); updateIndexes(); } onLatteViewChanged: { if (latteView) { if (latteView.positioner) { latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); } if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); } updateContainsOnlyPlasmaTasks(); } } Connections { target: latteView onPositionerChanged: { if (latteView.positioner) { latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); } } onVisibilityChanged: { if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); } } } onMaxLengthChanged: { layouter.updateSizeForAppletsInFill(); } onToolBoxChanged: { if (toolBox) { toolBox.visible = false; } } onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.alignment === LatteCore.Types.Left) plasmoid.configuration.alignment = LatteCore.Types.Top; else if (plasmoid.configuration.alignment === LatteCore.Types.Right) plasmoid.configuration.alignment = LatteCore.Types.Bottom; } else { if (plasmoid.configuration.alignment === LatteCore.Types.Top) plasmoid.configuration.alignment = LatteCore.Types.Left; else if (plasmoid.configuration.alignment === LatteCore.Types.Bottom) plasmoid.configuration.alignment = LatteCore.Types.Right; } } Component.onCompleted: { // currentLayout.isLayoutHorizontal = isHorizontal LayoutManager.plasmoid = plasmoid; LayoutManager.root = root; LayoutManager.layout = layoutsContainer.mainLayout; LayoutManager.layoutS = layoutsContainer.startLayout; LayoutManager.layoutE = layoutsContainer.endLayout; LayoutManager.lastSpacer = lastSpacer; LayoutManager.metrics = metrics; upgrader_v010_alignment(); LayoutManager.restore(); plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; inStartupTimer.start(); } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); layouter.appletsInParentChange = true; if (latteView) { if (latteView.positioner) { latteView.positioner.hideDockDuringLocationChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); } if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); var flexibleFound = false; for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var applet = layoutsContainer.mainLayout.children[i].applet; if (applet && ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) && applet.visible) { flexibleFound = true; break } } if (!flexibleFound) { lastSpacer.parent = layoutsContainer.mainLayout; } LayoutManager.save(); updateIndexes(); updateContainsOnlyPlasmaTasks(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { // console.log("applets------"); for (var i = 0; i < plasmoid.applets.length; ++i) { // console.log("applet:"+i); plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("editmode/ConfigOverlay.qml"); if (component.status == Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay"); console.log(component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { if (dragOverlay) { dragOverlay.visible = false; dragOverlay.destroy(); } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; ///Set Preferred Sizes/// ///Notice: they are set here because if they are set with a binding ///they break the !immutable experience, the latteView becomes too small ///to add applets /* if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin); } } else { if (root.isHorizontal) { root.Layout.preferredWidth = Screen.width; } else { root.Layout.preferredHeight = Screen.height; } }*/ visibilityManager.updateMaskArea(); } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function addApplet(applet, x, y) { var container = appletContainerComponent.createObject(dndSpacer.parent) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller container.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) }) addContainerInLayout(container, applet, x, y); updateContainsOnlyPlasmaTasks(); } function addContainerInLayout(container, applet, x, y){ // Is there a DND placeholder? Replace it! if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { LayoutManager.insertBeforeForLayout(dndSpacer.parent, dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates2(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = null; container.animationsEnabled = false; if (lastSpacer.parent === layoutsContainer.mainLayout) { before = lastSpacer; } // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. if (applet.pluginName == "org.kde.plasma.icon") { var middle = layoutsContainer.mainLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // Otherwise if lastSpacer is here, enqueue before it. } if (before) { LayoutManager.insertBefore(before, container); // Fall through to adding at the end. } else { container.parent = layoutsContainer.mainLayout; } } //Important, removes the first children of the layoutsContainer.mainLayout after the first //applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplitters(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitter(plasmoid.configuration.splitterPosition); addInternalViewSplitter(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitter(pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var container = appletContainerComponent.createObject(root); container.internalSplitterId = splittersCount+1; container.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(layoutsContainer.mainLayout, container, pos); } else { LayoutManager.insertAtIndex(layoutsContainer.mainLayout, container, Math.floor(layouter.mainLayout.count / 2)); } } } //! it is used in order to check the right click position //! the only way to take into account the visual appearance //! of the applet (including its spacers) function appletContainsPos(appletId, pos){ for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { var child = layoutsContainer.startLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var child = layoutsContainer.mainLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { var child = layoutsContainer.endLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } return false; } function checkLastSpacer() { lastSpacer.parent = root var expands = false; if (isHorizontal) { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillWidth) { expands = true; } } } else { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillHeight) { expands = true; } } } if (!expands) { lastSpacer.parent = layoutsContainer.mainLayout } } function containmentActions(){ return latteView.containmentActions(); } function decimalToHex(d, padding) { var hex = Number(d).toString(16); padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; while (hex.length < padding) { hex = "0" + hex; } return hex; } function internalViewSplittersCount(){ var splitters = 0; for (var container in layoutsContainer.startLayout.children) { var item = layoutsContainer.startLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } return splitters; } function layoutManager() { return LayoutManager; } function layoutManagerInsertBefore(place, item) { LayoutManager.insertBefore(place, item); } function layoutManagerInsertAfter(place, item) { LayoutManager.insertAfter(place, item); } function layoutManagerSave() { LayoutManager.save(); } function layoutManagerSaveOptions() { LayoutManager.saveOptions(); } function mouseInCanBeHoveredApplet(){ var applets = layoutsContainer.startLayout.children; for(var i=0; i=0; --i){ if(iconsArray[i] === size){ return true; } } return false; } function slotPreviewsShown(){ if (latteView) { latteView.extendedInterface.deactivateApplets(); } } function updateContainsOnlyPlasmaTasks() { if (latteView) { root.containsOnlyPlasmaTasks = (latteView.tasksPresent() && !latteApplet); } else { root.containsOnlyPlasmaTasks = false; } } function layoutManagerMoveAppletsBasedOnJustifyAlignment() { if (plasmoid.configuration.alignment !== 10) { return; } layouter.appletsInParentChange = true; var splitter = -1; var startChildrenLength = layoutsContainer.startLayout.children.length; //! Check if there is a splitter inside start layout after the user was dragging its applets for (var i=0; i=0) { for (var i=startChildrenLength-1; i>=splitter; --i){ var item = layoutsContainer.startLayout.children[i]; LayoutManager.insertAtIndex(layoutsContainer.mainLayout, item, 0); } } var splitter2 = -1; var endChildrenLength = layoutsContainer.endLayout.children.length; //! Check if there is a splitter inside endlayout after the user was dragging its applets for (var i=0; i=0) { for (var i=0; i<=splitter2; ++i){ var item = layoutsContainer.endLayout.children[0]; item.parent = layoutsContainer.mainLayout; } } //! Validate applets positioning and move applets out of splitters to start/endlayouts accordingly splitMainLayoutToLayouts(); layouter.appletsInParentChange = false; } function splitMainLayoutToLayouts() { if (internalViewSplittersCount() === 2) { layouter.appletsInParentChange = true; console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); var splitter = -1; var splitter2 = -1; var totalChildren = layoutsContainer.mainLayout.children.length; for (var i=0; i=0 && splitter2 === -1) { splitter2 = i; } } // console.log("update layouts 1:"+splitter + " - "+splitter2); if (splitter > 0) { for (var i=0; i 0) { splitter2 = splitter2 - splitter; // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = layoutsContainer.mainLayout.children.length; for (var i=totalChildren-1; i>=splitter2+1; --i){ var item = layoutsContainer.mainLayout.children[i]; LayoutManager.insertAtIndex(layoutsContainer.endLayout, item, 0); } } layouter.appletsInParentChange = false; } } function joinLayoutsToMainLayout() { layouter.appletsInParentChange = true; console.log("LAYOUTS: Moving applets from THREE to MAIN Layout mode..."); var totalChildren1 = layoutsContainer.mainLayout.children.length; for (var i=totalChildren1-1; i>=0; --i) { var item1 = layoutsContainer.mainLayout.children[0]; item1.parent = layoutsContainer.startLayout; } var totalChildren2 = layoutsContainer.endLayout.children.length; for (var i=totalChildren2-1; i>=0; --i) { var item2 = layoutsContainer.endLayout.children[0]; item2.parent = layoutsContainer.startLayout; } var totalChildrenL = layoutsContainer.startLayout.children.length; for (var i=totalChildrenL-1; i>=0; --i) { var itemL = layoutsContainer.startLayout.children[0]; itemL.parent = layoutsContainer.mainLayout; } layouter.appletsInParentChange = false; } function upgrader_v010_alignment() { //! IMPORTANT, special case because it needs to be loaded on Component constructor if (!plasmoid.configuration.alignmentUpgraded) { plasmoid.configuration.alignment = plasmoid.configuration.panelPosition; plasmoid.configuration.alignmentUpgraded = true; } } //END functions ////BEGIN interfaces Connections { target: LatteCore.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } ////END interfaces /////BEGIN: Title Tooltip/////////// PlasmaCore.Dialog{ id: titleTooltipDialog type: PlasmaCore.Dialog.Tooltip flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.ToolTip location: plasmoid.location mainItem: RowLayout{ Layout.fillWidth: true Layout.fillHeight: true PlasmaComponents.Label{ id:titleLbl Layout.leftMargin: 4 Layout.rightMargin: 4 Layout.topMargin: 2 Layout.bottomMargin: 2 text: titleTooltipDialog.title } } visible: false property string title: "" property bool activeItemHovered: false property Item activeItem: null property Item activeItemTooltipParent: null property string activeItemText: "" Component.onCompleted: { parabolic.sglClearZoom.connect(titleTooltipDialog.hide); } Component.onDestruction: { parabolic.sglClearZoom.disconnect(titleTooltipDialog.hide); } function hide(debug){ if (!root.titleTooltips) return; activeItemHovered = false; hideTitleTooltipTimer.start(); } function show(taskItem, text){ if (!root.titleTooltips || (latteApplet && latteApplet.contextMenu)){ return; } activeItemHovered = true; if (activeItem !== taskItem) { activeItem = taskItem; activeItemTooltipParent = taskItem.tooltipVisualParent; activeItemText = text; } if (isReady) { showTitleTooltipTimer.start(); } } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; if (latteApplet && latteApplet.windowPreviewIsShown) { latteApplet.hidePreview(); } visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) { titleTooltipDialog.update(); } if (titleTooltipDialog.visible) { titleTooltipCheckerToNotShowTimer.start(); } if (root.debugModeTimers) { console.log("containment timer: showTitleTooltipTimer called..."); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; } if (root.debugModeTimers) { console.log("containment timer: hideTitleTooltipTimer called..."); } } } //! Timer to fix #811, rare cases that both a window preview and context menu are //! shown Timer { id: titleTooltipCheckerToNotShowTimer interval: 250 onTriggered: { if (titleTooltipDialog.visible && latteApplet && (latteApplet.contextMenu || latteApplet.windowPreviewIsShown)) { titleTooltipDialog.visible = false; } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{ animations: _animations indexer: _indexer layouter: _layouter metrics: _metrics parabolic: _parabolic } } ParabolicManager{ id: _parabolicManager } Indicators.Manager{ id: indicators } Item { id: graphicsSystem readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software) && (GraphicsInfo.api !== GraphicsInfo.Unknown) } Upgrader { id: upgrader } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } ///////////////BEGIN UI elements //it is used to check if the mouse is outside the layoutsContainer borders, //so in that case the onLeave event behavior should be trigerred RootMouseArea{ id: rootMouseArea } Loader{ active: root.debugModeWindow sourceComponent: Debug.DebugWindow{} } EditMode.Visual{ id:editModeVisual // z: root.behaveAsPlasmaPanel ? 1 : 0 } Item { id: lastSpacer parent: layoutsContainer.mainLayout Layout.fillWidth: true Layout.fillHeight: true z:10 Rectangle{ anchors.fill: parent color: "transparent" border.color: "yellow" border.width: 1 } } Loader{ anchors.fill: parent active: root.debugMode z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.06 } } } VisibilityManager{ id: visibilityManager applets: layoutsContainer.applets } DragDropArea { id: backDropArea anchors.fill: parent readonly property bool higherPriority: latteView && latteView.containsDrag && ((root.dragInfo.isPlasmoid && root.dragInfo.isSeparator) || (foreDropArea.dragInfo.computationsAreValid && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers)) Item{ anchors.fill: layoutsContainer Background.MultiLayered{ id: _background } } Layouts.LayoutsContainer { id: layoutsContainer } DragDropArea { id: foreDropArea anchors.fill: parent visible: !backDropArea.higherPriority isForeground: true /* Rectangle { anchors.fill: parent color: "blue" opacity: 0.5 }*/ } } Colorizer.Manager { id: colorizerManager } Item { id: dndSpacer width: root.isHorizontal ? length : thickness height: root.isHorizontal ? thickness : length readonly property bool isDndSpacer: true readonly property int length: metrics.totals.length readonly property int thickness: metrics.totals.thickness + metrics.margin.screenEdge Layout.preferredWidth: width Layout.preferredHeight: height opacity: 0 z:1500 LatteComponents.AddItem{ id: dndSpacerAddItem width: root.isHorizontal ? parent.width : parent.width - metrics.margin.screenEdge height: root.isHorizontal ? parent.height - metrics.margin.screenEdge: parent.height states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: metrics.margin.screenEdge; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: metrics.margin.screenEdge; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } } ///////////////END UI elements ///////////////BEGIN ABILITIES Ability.Animations { id: _animations metrics: _metrics settings: universalSettings } Ability.AutoSize { id: _autosize layouts: layoutsContainer layouter: _layouter metrics: _metrics visibility: visibilityManager } Ability.Indexer { id: _indexer layouts: layoutsContainer } Ability.Layouter { id: _layouter animations: _animations indexer: _indexer layouts: layoutsContainer } Ability.Metrics { id: _metrics animations: _animations autosize: _autosize background: _background indicators: indicatorsManager } Ability.ParabolicEffect { id: _parabolic animations: _animations applets: layoutsContainer.applets view: latteView } LatteApp.Interfaces { id: _interfaces plasmoidInterface: plasmoid Component.onCompleted: { view.interfacesGraphicObj = _interfaces; } onViewChanged: { if (view) { view.interfacesGraphicObj = _interfaces; } } } ///////////////END ABILITIES ///////////////BEGIN TIMER elements //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer interval: 1500 repeat: false onTriggered: { if (inStartup) { visibilityManager.slotMustBeShown(); } } } ///////////////END TIMER elements Loader{ anchors.fill: parent active: root.debugModeLocalGeometry sourceComponent: Rectangle{ x: latteView.localGeometry.x y: latteView.localGeometry.y width: latteView.localGeometry.width height: latteView.localGeometry.height color: "blue" border.width: 2 border.color: "red" opacity: 0.35 } } }