diff --git a/app/view/visibilitymanager.cpp b/app/view/visibilitymanager.cpp index 837e3254..ff57a739 100644 --- a/app/view/visibilitymanager.cpp +++ b/app/view/visibilitymanager.cpp @@ -1,1026 +1,1026 @@ /* * 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 . */ #include "visibilitymanager.h" // local #include "positioner.h" #include "view.h" #include "helpers/floatinggapwindow.h" #include "helpers/screenedgeghostwindow.h" #include "windowstracker/currentscreentracker.h" #include "../apptypes.h" #include "../lattecorona.h" #include "../screenpool.h" #include "../layouts/manager.h" #include "../wm/abstractwindowinterface.h" // Qt #include // KDE #include #include #include //! Hide Timer can create cases that when it is low it does not allow the //! view to be show. For example !compositing+kwin_edges+hide inteval<50ms const int HIDEMINIMUMINTERVAL = 50; namespace Latte { namespace ViewPart { //! BEGIN: VisiblityManager implementation VisibilityManager::VisibilityManager(PlasmaQuick::ContainmentView *view) : QObject(view) { qDebug() << "VisibilityManager creating..."; m_latteView = qobject_cast(view); m_corona = qobject_cast(view->corona()); m_wm = m_corona->wm(); connect(this, &VisibilityManager::hidingIsBlockedChanged, this, &VisibilityManager::on_hidingIsBlockedChanged); connect(this, &VisibilityManager::slideOutFinished, this, &VisibilityManager::updateHiddenState); connect(this, &VisibilityManager::slideInFinished, this, &VisibilityManager::updateHiddenState); connect(this, &VisibilityManager::enableKWinEdgesChanged, this, &VisibilityManager::updateKWinEdgesSupport); connect(this, &VisibilityManager::modeChanged, this, &VisibilityManager::updateKWinEdgesSupport); if (m_latteView) { connect(m_latteView, &Latte::View::eventTriggered, this, &VisibilityManager::viewEventManager); connect(m_latteView, &Latte::View::behaveAsPlasmaPanelChanged , this, &VisibilityManager::updateKWinEdgesSupport); connect(m_latteView, &Latte::View::byPassWMChanged, this, &VisibilityManager::updateKWinEdgesSupport); connect(m_latteView, &Latte::View::inEditModeChanged, this, &VisibilityManager::initViewFlags); connect(m_latteView, &Latte::View::absoluteGeometryChanged, this, [&]() { if (m_mode == Types::AlwaysVisible && m_latteView->screen()) { updateStrutsBasedOnLayoutsAndActivities(); } }); //! Frame Extents connect(m_latteView, &Latte::View::headThicknessGapChanged , this, &VisibilityManager::on_publishFrameExtents); - connect(m_latteView, &Latte::View::locationChanged , this, &VisibilityManager::publishFrameExtents); + connect(m_latteView, &Latte::View::inEditModeChanged , this, &VisibilityManager::publishFrameExtents); connect(m_latteView, &Latte::View::screenEdgeMarginEnabledChanged, this, [&]() { if (!m_latteView->screenEdgeMarginEnabled()) { deleteFloatingGapWindow(); } }); connect(this, &VisibilityManager::modeChanged, this, [&]() { emit m_latteView->availableScreenRectChangedFrom(m_latteView); }); } m_timerStartUp.setInterval(5000); m_timerStartUp.setSingleShot(true); m_timerShow.setSingleShot(true); m_timerHide.setSingleShot(true); connect(&m_timerShow, &QTimer::timeout, this, [&]() { if (m_isHidden || m_isBelowLayer) { // qDebug() << "must be shown"; emit mustBeShown(); } }); connect(&m_timerHide, &QTimer::timeout, this, [&]() { if (!hidingIsBlocked() && !m_isHidden && !m_isBelowLayer && !m_dragEnter) { if (m_latteView->isFloatingWindow()) { //! first check if mouse is inside the floating gap checkMouseInFloatingArea(); } else { //! immediate call emit mustBeHide(); } } }); m_timerPublishFrameExtents.setInterval(2000); m_timerPublishFrameExtents.setSingleShot(true); connect(&m_timerPublishFrameExtents, &QTimer::timeout, this, &VisibilityManager::publishFrameExtents); restoreConfig(); } VisibilityManager::~VisibilityManager() { qDebug() << "VisibilityManager deleting..."; m_wm->removeViewStruts(*m_latteView); if (m_edgeGhostWindow) { m_edgeGhostWindow->deleteLater(); } if (m_floatingGapWindow) { m_floatingGapWindow->deleteLater(); } } Types::Visibility VisibilityManager::mode() const { return m_mode; } void VisibilityManager::initViewFlags() { if ((m_mode == Types::WindowsCanCover || m_mode == Types::WindowsAlwaysCover) && (!m_latteView->inEditMode())) { setViewOnBackLayer(); } else { setViewOnFrontLayer(); } } void VisibilityManager::setViewOnBackLayer() { m_wm->setViewExtraFlags(m_latteView, false, Types::WindowsAlwaysCover); setIsBelowLayer(true); } void VisibilityManager::setViewOnFrontLayer() { m_wm->setViewExtraFlags(m_latteView, true); setIsBelowLayer(false); } void VisibilityManager::setMode(Latte::Types::Visibility mode) { if (m_mode == mode) return; Q_ASSERT_X(mode != Types::None, staticMetaObject.className(), "set visibility to Types::None"); // clear mode for (auto &c : m_connections) { disconnect(c); } int base{0}; m_publishedStruts = QRect(); if (m_mode == Types::AlwaysVisible) { //! remove struts for old always visible mode m_wm->removeViewStruts(*m_latteView); } m_timerShow.stop(); m_timerHide.stop(); m_mode = mode; initViewFlags(); if (mode != Types::AlwaysVisible && mode != Types::WindowsGoBelow) { m_connections[0] = connect(m_wm, &WindowSystem::AbstractWindowInterface::currentDesktopChanged, this, [&] { if (m_raiseOnDesktopChange) { raiseViewTemporarily(); } }); m_connections[1] = connect(m_wm, &WindowSystem::AbstractWindowInterface::currentActivityChanged, this, [&]() { if (m_raiseOnActivityChange) { raiseViewTemporarily(); } else { updateHiddenState(); } }); base = 2; } switch (m_mode) { case Types::AlwaysVisible: { if (m_latteView->containment() && m_latteView->screen()) { updateStrutsBasedOnLayoutsAndActivities(); } m_connections[base] = connect(m_latteView, &Latte::View::normalThicknessChanged, this, [&]() { updateStrutsBasedOnLayoutsAndActivities(); }); m_connections[base+1] = connect(m_corona->layoutsManager(), &Layouts::Manager::currentLayoutNameChanged, this, [&]() { if (m_corona && m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { updateStrutsBasedOnLayoutsAndActivities(true); } }); m_connections[base+2] = connect(m_latteView, &Latte::View::activitiesChanged, this, [&]() { if (m_corona && m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { updateStrutsBasedOnLayoutsAndActivities(true); } }); raiseView(true); break; } case Types::AutoHide: { m_connections[base] = connect(this, &VisibilityManager::containsMouseChanged, this, [&]() { raiseView(m_containsMouse); }); raiseView(m_containsMouse); break; } case Types::DodgeActive: { m_connections[base] = connect(this, &VisibilityManager::containsMouseChanged , this, &VisibilityManager::dodgeActive); m_connections[base+1] = connect(m_latteView->windowsTracker()->currentScreen(), &TrackerPart::CurrentScreenTracker::activeWindowTouchingChanged , this, &VisibilityManager::dodgeActive); dodgeActive(); break; } case Types::DodgeMaximized: { m_connections[base] = connect(this, &VisibilityManager::containsMouseChanged , this, &VisibilityManager::dodgeMaximized); m_connections[base+1] = connect(m_latteView->windowsTracker()->currentScreen(), &TrackerPart::CurrentScreenTracker::activeWindowMaximizedChanged , this, &VisibilityManager::dodgeMaximized); dodgeMaximized(); break; } case Types::DodgeAllWindows: { m_connections[base] = connect(this, &VisibilityManager::containsMouseChanged , this, &VisibilityManager::dodgeAllWindows); m_connections[base+1] = connect(m_latteView->windowsTracker()->currentScreen(), &TrackerPart::CurrentScreenTracker::existsWindowTouchingChanged , this, &VisibilityManager::dodgeAllWindows); dodgeAllWindows(); break; } case Types::WindowsGoBelow: break; case Types::WindowsCanCover: m_connections[base] = connect(this, &VisibilityManager::containsMouseChanged, this, [&]() { if (m_containsMouse) { emit mustBeShown(); } else { raiseView(false); } }); raiseView(m_containsMouse); break; case Types::WindowsAlwaysCover: break; case Types::SideBar: m_connections[base] = connect(m_latteView, &Latte::View::inEditModeChanged, this, [&]() { if (!m_latteView->inEditMode()) { //! Give the time to View to change from !behaveAsPlasmaPanel to behaveAsPlasmaPanel //! if this is needed when changing to !inEditMode QTimer::singleShot(100, [this]() { toggleHiddenState(); }); } }); toggleHiddenState(); default: break; } m_latteView->containment()->config().writeEntry("visibility", static_cast(m_mode)); updateKWinEdgesSupport(); emit modeChanged(); } void VisibilityManager::updateStrutsBasedOnLayoutsAndActivities(bool forceUpdate) { bool multipleLayoutsAndCurrent = (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts && m_latteView->layout() && !m_latteView->positioner()->inLocationAnimation() && m_latteView->layout()->isCurrent()); if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout || multipleLayoutsAndCurrent) { QRect computedStruts = acceptableStruts(); if (m_publishedStruts != computedStruts || forceUpdate) { //! Force update is needed when very important events happen in DE and there is a chance //! that previously even though struts where sent the DE did not accept them. //! Such a case is when STOPPING an Activity and windows faulty become invisible even //! though they should not. In such case setting struts when the windows are hidden //! the struts do not take any effect m_publishedStruts = computedStruts; m_wm->setViewStruts(*m_latteView, m_publishedStruts, m_latteView->location()); } } else { m_publishedStruts = QRect(); m_wm->removeViewStruts(*m_latteView); } } QRect VisibilityManager::acceptableStruts() { QRect calcs; int screenEdgeMargin = (m_latteView->behaveAsPlasmaPanel() && m_latteView->screenEdgeMarginEnabled()) ? m_latteView->screenEdgeMargin() : 0; int shownThickness = m_latteView->normalThickness() + screenEdgeMargin; switch (m_latteView->location()) { case Plasma::Types::TopEdge: { calcs = QRect(m_latteView->x(), m_latteView->y(), m_latteView->width(), shownThickness); break; } case Plasma::Types::BottomEdge: { int y = m_latteView->y() + m_latteView->height() - shownThickness; calcs = QRect(m_latteView->x(), y, m_latteView->width(), shownThickness); break; } case Plasma::Types::LeftEdge: { calcs = QRect(m_latteView->x(), m_latteView->y(), shownThickness, m_latteView->height()); break; } case Plasma::Types::RightEdge: { int x = m_latteView->x() + m_latteView->width() - shownThickness; calcs = QRect(x, m_latteView->y(), shownThickness, m_latteView->height()); break; } } return calcs; } bool VisibilityManager::raiseOnDesktop() const { return m_raiseOnDesktopChange; } void VisibilityManager::setRaiseOnDesktop(bool enable) { if (enable == m_raiseOnDesktopChange) return; m_raiseOnDesktopChange = enable; emit raiseOnDesktopChanged(); } bool VisibilityManager::raiseOnActivity() const { return m_raiseOnActivityChange; } void VisibilityManager::setRaiseOnActivity(bool enable) { if (enable == m_raiseOnActivityChange) return; m_raiseOnActivityChange = enable; emit raiseOnActivityChanged(); } bool VisibilityManager::isBelowLayer() const { return m_isBelowLayer; } void VisibilityManager::setIsBelowLayer(bool below) { if (m_isBelowLayer == below) { return; } m_isBelowLayer = below; updateGhostWindowState(); emit isBelowLayerChanged(); } bool VisibilityManager::isHidden() const { return m_isHidden; } void VisibilityManager::setIsHidden(bool isHidden) { if (m_isHidden == isHidden) return; if (hidingIsBlocked() && isHidden) { qWarning() << "isHidden property is blocked, ignoring update"; return; } m_isHidden = isHidden; updateGhostWindowState(); emit isHiddenChanged(); } bool VisibilityManager::hidingIsBlocked() const { return (m_blockHidingEvents.count() > 0); } void VisibilityManager::addBlockHidingEvent(const QString &type) { if (m_blockHidingEvents.contains(type) || type.isEmpty()) { return; } //qDebug() << " {{ ++++ adding block hiding event :: " << type; bool prevHidingIsBlocked = hidingIsBlocked(); m_blockHidingEvents << type; if (prevHidingIsBlocked != hidingIsBlocked()) { emit hidingIsBlockedChanged(); } } void VisibilityManager::removeBlockHidingEvent(const QString &type) { if (!m_blockHidingEvents.contains(type) || type.isEmpty()) { return; } //qDebug() << " {{ ---- remove block hiding event :: " << type; bool prevHidingIsBlocked = hidingIsBlocked(); m_blockHidingEvents.removeAll(type); if (prevHidingIsBlocked != hidingIsBlocked()) { emit hidingIsBlockedChanged(); } } void VisibilityManager::on_hidingIsBlockedChanged() { if (hidingIsBlocked()) { m_timerHide.stop(); if (m_isHidden) { emit mustBeShown(); } } else { updateHiddenState(); } } void VisibilityManager::on_publishFrameExtents() { if (!m_timerPublishFrameExtents.isActive()) { m_timerPublishFrameExtents.start(); } } void VisibilityManager::publishFrameExtents() { if (m_frameExtentsHeadThicknessGap != m_latteView->headThicknessGap() || m_frameExtentsLocation != m_latteView->location()) { m_frameExtentsHeadThicknessGap = m_latteView->headThicknessGap(); m_frameExtentsLocation = m_latteView->location(); QMargins frameExtents; if (m_latteView->location() == Plasma::Types::LeftEdge) { frameExtents.setRight(m_frameExtentsHeadThicknessGap); } else if (m_latteView->location() == Plasma::Types::TopEdge) { frameExtents.setBottom(m_frameExtentsHeadThicknessGap); } else if (m_latteView->location() == Plasma::Types::RightEdge) { frameExtents.setLeft(m_frameExtentsHeadThicknessGap); } else { frameExtents.setTop(m_frameExtentsHeadThicknessGap); } qDebug() << " -> Frame Extents :: " << m_frameExtentsLocation << " __ " << " extents :: " << frameExtents; m_wm->setFrameExtents(m_latteView, frameExtents); } } int VisibilityManager::timerShow() const { return m_timerShow.interval(); } void VisibilityManager::setTimerShow(int msec) { if (m_timerShow.interval() == msec) { return; } m_timerShow.setInterval(msec); emit timerShowChanged(); } int VisibilityManager::timerHide() const { return m_timerHide.interval(); } void VisibilityManager::setTimerHide(int msec) { int interval = qMax(HIDEMINIMUMINTERVAL, msec); if (m_timerHide.interval() == interval) { return; } m_timerHide.setInterval(interval); emit timerHideChanged(); } bool VisibilityManager::supportsKWinEdges() const { return (m_edgeGhostWindow != nullptr); } void VisibilityManager::updateGhostWindowState() { if (supportsKWinEdges()) { bool inCurrentLayout = (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout || (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts && m_latteView->layout() && !m_latteView->positioner()->inLocationAnimation() && m_latteView->layout()->isCurrent())); if (inCurrentLayout) { if (m_mode == Latte::Types::WindowsCanCover) { m_wm->setActiveEdge(m_edgeGhostWindow, m_isBelowLayer && !m_containsMouse); } else { bool activated = (m_isHidden && !windowContainsMouse()); m_wm->setActiveEdge(m_edgeGhostWindow, activated); } } else { m_wm->setActiveEdge(m_edgeGhostWindow, false); } } } void VisibilityManager::hide() { if (KWindowSystem::isPlatformX11()) { m_lastMask = m_latteView->mask(); m_latteView->setMask(QRect(-1, -1, 1, 1)); } else { //! wayland case m_latteView->hide(); } } void VisibilityManager::show() { if (KWindowSystem::isPlatformX11()) { if (m_latteView->mask() == QRect(-1, -1 , 1, 1)) { m_latteView->setMask(m_lastMask); } } else { //! wayland case m_latteView->show(); } } void VisibilityManager::raiseView(bool raise) { if (hidingIsBlocked() || m_mode == Latte::Types::SideBar) return; if (raise) { m_timerHide.stop(); if (!m_timerShow.isActive()) { m_timerShow.start(); } } else if (!m_dragEnter) { m_timerShow.stop(); if (m_hideNow) { m_hideNow = false; emit mustBeHide(); } else if (!m_timerHide.isActive()) { m_timerHide.start(); } } } void VisibilityManager::raiseViewTemporarily() { if (m_raiseTemporarily) return; m_raiseTemporarily = true; m_timerHide.stop(); m_timerShow.stop(); if (m_isHidden) emit mustBeShown(); QTimer::singleShot(qBound(1800, 2 * m_timerHide.interval(), 3000), this, [&]() { m_raiseTemporarily = false; m_hideNow = true; updateHiddenState(); }); } bool VisibilityManager::isValidMode() const { return (m_mode != Types::None && m_mode != Types::NormalWindow); } void VisibilityManager::toggleHiddenState() { if (!m_latteView->inEditMode()) { if (m_mode == Latte::Types::SideBar) { if (m_blockHidingEvents.contains(Q_FUNC_INFO)) { removeBlockHidingEvent(Q_FUNC_INFO); } if (m_isHidden) { emit mustBeShown(); } else { emit mustBeHide(); } } else { if (!m_blockHidingEvents.contains(Q_FUNC_INFO)) { addBlockHidingEvent(Q_FUNC_INFO); } else { removeBlockHidingEvent(Q_FUNC_INFO); } } } } void VisibilityManager::updateHiddenState() { if (m_dragEnter) return; switch (m_mode) { case Types::AutoHide: case Types::WindowsCanCover: raiseView(m_containsMouse); break; case Types::DodgeActive: dodgeActive(); break; case Types::DodgeMaximized: dodgeMaximized(); break; case Types::DodgeAllWindows: dodgeAllWindows(); break; default: break; } } void VisibilityManager::applyActivitiesToHiddenWindows(const QStringList &activities) { if (m_edgeGhostWindow) { m_wm->setWindowOnActivities(*m_edgeGhostWindow, activities); } if (m_floatingGapWindow) { m_wm->setWindowOnActivities(*m_floatingGapWindow, activities); } } void VisibilityManager::dodgeActive() { if (m_raiseTemporarily) return; //!don't send false raiseView signal when containing mouse if (m_containsMouse) { raiseView(true); return; } raiseView(!m_latteView->windowsTracker()->currentScreen()->activeWindowTouching()); } void VisibilityManager::dodgeMaximized() { if (m_raiseTemporarily) return; //!don't send false raiseView signal when containing mouse if (m_containsMouse) { raiseView(true); return; } raiseView(!m_latteView->windowsTracker()->currentScreen()->activeWindowMaximized()); } void VisibilityManager::dodgeAllWindows() { if (m_raiseTemporarily) return; if (m_containsMouse) { raiseView(true); return; } bool windowIntersects{m_latteView->windowsTracker()->currentScreen()->activeWindowTouching() || m_latteView->windowsTracker()->currentScreen()->existsWindowTouching()}; raiseView(!windowIntersects); } void VisibilityManager::saveConfig() { if (!m_latteView->containment()) return; auto config = m_latteView->containment()->config(); config.writeEntry("enableKWinEdges", m_enableKWinEdgesFromUser); config.writeEntry("timerShow", m_timerShow.interval()); config.writeEntry("timerHide", m_timerHide.interval()); config.writeEntry("raiseOnDesktopChange", m_raiseOnDesktopChange); config.writeEntry("raiseOnActivityChange", m_raiseOnActivityChange); m_latteView->containment()->configNeedsSaving(); } void VisibilityManager::restoreConfig() { if (!m_latteView || !m_latteView->containment()){ return; } auto config = m_latteView->containment()->config(); m_timerShow.setInterval(config.readEntry("timerShow", 0)); m_timerHide.setInterval(qMax(HIDEMINIMUMINTERVAL, config.readEntry("timerHide", 700))); emit timerShowChanged(); emit timerHideChanged(); m_enableKWinEdgesFromUser = config.readEntry("enableKWinEdges", true); emit enableKWinEdgesChanged(); setRaiseOnDesktop(config.readEntry("raiseOnDesktopChange", false)); setRaiseOnActivity(config.readEntry("raiseOnActivityChange", false)); auto storedMode = (Types::Visibility)(m_latteView->containment()->config().readEntry("visibility", (int)(Types::DodgeActive))); if (storedMode == Types::AlwaysVisible) { qDebug() << "Loading visibility mode: Always Visible , on startup..."; setMode(Types::AlwaysVisible); } else { connect(&m_timerStartUp, &QTimer::timeout, this, [&]() { if (!m_latteView || !m_latteView->containment()) { return; } Types::Visibility fMode = (Types::Visibility)(m_latteView->containment()->config().readEntry("visibility", (int)(Types::DodgeActive))); qDebug() << "Loading visibility mode:" << fMode << " on startup..."; setMode(fMode); }); connect(m_latteView->containment(), &Plasma::Containment::userConfiguringChanged , this, [&](bool configuring) { if (configuring && m_timerStartUp.isActive()) m_timerStartUp.start(100); }); m_timerStartUp.start(); } connect(m_latteView->containment(), &Plasma::Containment::userConfiguringChanged , this, [&](bool configuring) { if (!configuring) { saveConfig(); } }); } bool VisibilityManager::containsMouse() const { return m_containsMouse; } void VisibilityManager::setContainsMouse(bool contains) { if (m_containsMouse == contains) { return; } m_containsMouse = contains; emit containsMouseChanged(); } bool VisibilityManager::windowContainsMouse() { return m_containsMouse || (m_edgeGhostWindow && m_edgeGhostWindow->containsMouse()); } void VisibilityManager::checkMouseInFloatingArea() { if (m_latteView->isFloatingWindow()) { if (!m_floatingGapWindow) { createFloatingGapWindow(); } m_floatingGapWindow->callAsyncContainsMouse(); } } void VisibilityManager::viewEventManager(QEvent *ev) { switch (ev->type()) { case QEvent::Enter: setContainsMouse(true); break; case QEvent::Leave: m_dragEnter = false; setContainsMouse(false); break; case QEvent::DragEnter: m_dragEnter = true; if (m_isHidden && m_mode != Latte::Types::SideBar) { emit mustBeShown(); } break; case QEvent::DragLeave: case QEvent::Drop: m_dragEnter = false; updateHiddenState(); break; default: break; } } //! KWin Edges Support functions bool VisibilityManager::enableKWinEdges() const { return m_enableKWinEdgesFromUser; } void VisibilityManager::setEnableKWinEdges(bool enable) { if (m_enableKWinEdgesFromUser == enable) { return; } m_enableKWinEdgesFromUser = enable; emit enableKWinEdgesChanged(); } void VisibilityManager::updateKWinEdgesSupport() { if ((m_mode == Types::AutoHide || m_mode == Types::DodgeActive || m_mode == Types::DodgeAllWindows || m_mode == Types::DodgeMaximized) && !m_latteView->byPassWM()) { if (m_enableKWinEdgesFromUser || m_latteView->behaveAsPlasmaPanel()) { createEdgeGhostWindow(); if (m_latteView->isFloatingWindow()) { createFloatingGapWindow(); } } else if (!m_enableKWinEdgesFromUser) { deleteEdgeGhostWindow(); deleteFloatingGapWindow(); } } else if (m_mode == Types::WindowsCanCover) { createEdgeGhostWindow(); } else { deleteEdgeGhostWindow(); deleteFloatingGapWindow(); } } void VisibilityManager::createEdgeGhostWindow() { if (!m_edgeGhostWindow) { m_edgeGhostWindow = new ScreenEdgeGhostWindow(m_latteView); connect(m_edgeGhostWindow, &ScreenEdgeGhostWindow::containsMouseChanged, this, [ = ](bool contains) { if (contains) { raiseView(true); } else { m_timerShow.stop(); updateGhostWindowState(); } }); connect(m_edgeGhostWindow, &ScreenEdgeGhostWindow::dragEntered, this, [&]() { if (m_isHidden) { emit mustBeShown(); } }); m_connectionsKWinEdges[0] = connect(m_wm, &WindowSystem::AbstractWindowInterface::currentActivityChanged, this, [&]() { bool inCurrentLayout = (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout || (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts && m_latteView->layout() && !m_latteView->positioner()->inLocationAnimation() && m_latteView->layout()->isCurrent())); if (m_edgeGhostWindow) { if (inCurrentLayout) { m_wm->setActiveEdge(m_edgeGhostWindow, m_isHidden); } else { m_wm->setActiveEdge(m_edgeGhostWindow, false); } } }); emit supportsKWinEdgesChanged(); } } void VisibilityManager::deleteEdgeGhostWindow() { if (m_edgeGhostWindow) { m_edgeGhostWindow->deleteLater(); m_edgeGhostWindow = nullptr; for (auto &c : m_connectionsKWinEdges) { disconnect(c); } emit supportsKWinEdgesChanged(); } } void VisibilityManager::createFloatingGapWindow() { if (!m_floatingGapWindow) { m_floatingGapWindow = new FloatingGapWindow(m_latteView); connect(m_floatingGapWindow, &FloatingGapWindow::asyncContainsMouseChanged, this, [ = ](bool contains) { if (contains) { if (m_latteView->isFloatingWindow() && !m_isHidden) { //! immediate call after contains mouse checks for mouse in sensitive floating areas updateHiddenState(); } } else { if (m_latteView->isFloatingWindow() && !m_isHidden) { //! immediate call after contains mouse checks for mouse in sensitive floating areas emit mustBeHide(); } } }); } } void VisibilityManager::deleteFloatingGapWindow() { if (m_floatingGapWindow) { m_floatingGapWindow->deleteLater(); m_floatingGapWindow = nullptr; } } bool VisibilityManager::supportsFloatingGap() const { return (m_floatingGapWindow != nullptr); } //! END: VisibilityManager implementation } } diff --git a/containment/package/contents/ui/VisibilityManager.qml b/containment/package/contents/ui/VisibilityManager.qml index 6f71a38a..971b8d21 100644 --- a/containment/package/contents/ui/VisibilityManager.qml +++ b/containment/package/contents/ui/VisibilityManager.qml @@ -1,1033 +1,1033 @@ /* * 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.1 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.containment 0.1 as LatteContainment Item{ id: manager anchors.fill: parent property QtObject window property bool debugManager: Qt.application.arguments.indexOf("--mask") >= 0 property bool blockUpdateMask: false property bool inForceHiding: false //is used when the docks are forced in hiding e.g. when changing layouts property bool normalState : false // this is being set from updateMaskArea property bool previousNormalState : false // this is only for debugging purposes property bool panelIsBiggerFromIconSize: root.useThemePanel && (background.totals.visualThickness >= (metrics.iconSize + metrics.margin.thickness)) property bool maskIsFloating: !root.behaveAsPlasmaPanel && !root.editMode && screenEdgeMarginEnabled && !plasmoid.configuration.fittsLawIsRequested && !inSlidingIn && !inSlidingOut property int maskFloatedGap: maskIsFloating ? Math.max(0, metrics.margin.screenEdge - background.shadows.headThickness) : 0 property int animationSpeed: LatteCore.WindowSystem.compositingActive ? (editModeVisual.inEditMode ? editModeVisual.speed * 0.8 : animations.speedFactor.normal * 1.62 * animations.duration.large) : 0 property bool inLocationAnimation: latteView && latteView.positioner && latteView.positioner.inLocationAnimation property bool inSlidingIn: false //necessary because of its init structure property alias inSlidingOut: slidingAnimationAutoHiddenOut.running property bool inTempHiding: false property bool inScreenEdgeInternalWindowSliding: root.behaveAsDockWithMask && hideThickScreenGap property int length: root.isVertical ? Screen.height : Screen.width //screenGeometry.height : screenGeometry.width property int slidingOutToPos: { if (root.behaveAsPlasmaPanel) { var edgeMargin = screenEdgeMarginEnabled ? plasmoid.configuration.screenEdgeMargin : 0 root.isHorizontal ? root.height + edgeMargin - 1 : root.width + edgeMargin - 1; } else { var topOrLeftEdge = ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)); return (topOrLeftEdge ? -thicknessNormal : thicknessNormal); } } property int finalScreenEdgeMargin: { //! is used for window geometry calculations if (!screenEdgeMarginEnabled || (hideThickScreenGap && metrics.margin.screenEdge === 0)) { /*window geometry is updated after the local screen margin animation was zeroed*/ return 0; } return plasmoid.configuration.screenEdgeMargin; } property int thicknessAutoHidden: LatteCore.WindowSystem.compositingActive ? 2 : 1 property int thicknessMid: finalScreenEdgeMargin + (1 + (0.65 * (parabolic.factor.maxZoom-1)))*(metrics.totals.thickness+extraZoomThickMask) //needed in some animations property int thicknessNormal: finalScreenEdgeMargin + Math.max(metrics.totals.thickness + extraNormalThickMask + 1, background.thickness + background.shadows.headThickness) property int thicknessZoom: finalScreenEdgeMargin + ((metrics.totals.thickness+extraZoomThickMask) * parabolic.factor.maxZoom) + 2 //it is used to keep thickness solid e.g. when iconSize changes from auto functions property int thicknessMidOriginal: finalScreenEdgeMargin + Math.max(thicknessNormalOriginal,extraNormalThickMask + (1 + (0.65 * (parabolic.factor.maxZoom-1)))*(metrics.maxIconSize+metrics.margin.maxThickness)) //needed in some animations property int thicknessNormalOriginal: finalScreenEdgeMargin + metrics.maxIconSize + (metrics.margin.maxThickness * 2) //this way we always have the same thickness published at all states /*property int thicknessNormalOriginal: !root.behaveAsPlasmaPanel || root.editMode ? thicknessNormalOriginalValue : background.thickness + background.shadows.headThickness*/ property int thicknessNormalOriginalValue: finalScreenEdgeMargin + metrics.maxIconSize + (metrics.margin.maxThickness * 2) + extraNormalThickMask + 1 property int thicknessZoomOriginal: finalScreenEdgeMargin + Math.max( ((metrics.maxIconSize+(metrics.margin.maxThickness * 2)) * parabolic.factor.maxZoom) + extraZoomThickMask + 2, background.thickness + background.shadows.headThickness, (LatteCore.WindowSystem.compositingActive ? thicknessEditMode + root.editShadow : thicknessEditMode)) //! is used from Panel in edit mode in order to provide correct masking property int thicknessEditMode: thicknessNormalOriginalValue + editModeVisual.settingsThickness //! when Latte behaves as Plasma panel property int thicknessAsPanel: metrics.totals.thickness //! is used to increase the mask thickness readonly property int marginBetweenContentsAndRuler: 10 property int extraNormalThickMask: Math.max(indicatorsExtraThickMask, shadowsExtraThickMask) property int extraZoomThickMask: Math.max(marginBetweenContentsAndRuler, indicatorsExtraThickMask, shadowsExtraThickMask) //! this is set from indicators when they need extra thickness mask size readonly property int indicatorsExtraThickMask: indicators.info.extraMaskThickness property int shadowsExtraThickMask: { if (LatteCore.WindowSystem.isPlatformWayland) { return 0; } //! 45% of max shadow size in px. var shadowMaxNeededMargin = 0.45 * root.appShadowSizeOriginal; var shadowOpacity = (plasmoid.configuration.shadowOpacity) / 100; //! +40% of shadow opacity in percentage shadowOpacity = shadowOpacity + shadowOpacity*0.4; //! This way we are trying to calculate how many pixels are needed in order for the shadow //! to be drawn correctly without being cut of from View::mask() under X11 shadowMaxNeededMargin = (shadowMaxNeededMargin * shadowOpacity); //! give some more space when items shadows are enabled and extremely big if (root.enableShadows && metrics.margin.maxThickness < shadowMaxNeededMargin) { return shadowMaxNeededMargin - metrics.margin.maxThickness; } return 0; } property Item applets: null Binding{ target: latteView property:"maxThickness" //! prevents updating window geometry during closing window in wayland and such fixes a crash when: latteView && !inTempHiding && !inForceHiding && !inScreenEdgeInternalWindowSliding value: root.behaveAsPlasmaPanel && !root.editMode ? thicknessAsPanel : thicknessZoomOriginal } property bool validIconSize: (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === autosize.iconSize) property bool inPublishingState: validIconSize && !inSlidingIn && !inSlidingOut && !inTempHiding && !inForceHiding Binding{ target: latteView property:"normalThickness" when: latteView && inPublishingState value: root.behaveAsPlasmaPanel && !root.editMode ? thicknessAsPanel : thicknessNormalOriginal } Binding{ target: latteView property:"editThickness" when: latteView value: thicknessEditMode } Binding { target: latteView property: "headThicknessGap" - when: latteView && !inTempHiding && !inForceHiding && !inScreenEdgeInternalWindowSliding && inPublishingState + when: latteView && !root.editMode && !editModeVisual.inEditMode && !inTempHiding && !inForceHiding && !inScreenEdgeInternalWindowSliding && inPublishingState value: { - if (root.behaveAsPlasmaPanel) { + if (root.behaveAsPlasmaPanel || root.viewType === LatteCore.Types.PanelView) { return 0; } return thicknessZoomOriginal - thicknessNormalOriginalValue; } } Binding{ target: latteView property: "type" when: latteView value: root.viewType } Binding{ target: latteView property: "behaveAsPlasmaPanel" when: latteView value: root.editMode ? false : root.behaveAsPlasmaPanel } Binding{ target: latteView property: "fontPixelSize" when: theme value: theme.defaultFont.pixelSize } Binding{ target: latteView property:"inEditMode" when: latteView value: root.editMode } Binding{ target: latteView property:"latteTasksArePresent" when: latteView value: latteApplet !== null } Binding{ target: latteView property: "maxLength" when: latteView value: maxLengthPerCentage/100 } Binding{ target: latteView property: "offset" when: latteView value: plasmoid.configuration.offset/100 } Binding{ target: latteView property: "screenEdgeMargin" when: latteView value: plasmoid.configuration.screenEdgeMargin } Binding{ target: latteView property: "screenEdgeMarginEnabled" when: latteView value: root.screenEdgeMarginEnabled && !root.hideThickScreenGap } Binding{ target: latteView property: "alignment" when: latteView value: root.panelAlignment } Binding{ target: latteView property: "isTouchingTopViewAndIsBusy" when: latteView value: { var isTouchingTopScreenEdge = (latteView.y === latteView.screenGeometry.y); var hasTopBorder = ((latteView.effects && (latteView.effects.enabledBorders & PlasmaCore.FrameSvg.TopBorder)) > 0); return root.isVertical && !latteView.visibility.isHidden && !isTouchingTopScreenEdge && !hasTopBorder && background.isShown; } } Binding{ target: latteView property: "isTouchingBottomViewAndIsBusy" when: latteView value: { var latteBottom = latteView.y + latteView.height; var screenBottom = latteView.screenGeometry.y + latteView.screenGeometry.height; var isTouchingBottomScreenEdge = (latteBottom === screenBottom); var hasBottomBorder = ((latteView.effects && (latteView.effects.enabledBorders & PlasmaCore.FrameSvg.BottomBorder)) > 0); return root.isVertical && !latteView.visibility.isHidden && !isTouchingBottomScreenEdge && !hasBottomBorder && background.isShown; } } //! View::Effects bindings Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "backgroundOpacity" when: latteView && latteView.effects value: background.currentOpacity } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "drawEffects" when: latteView && latteView.effects value: LatteCore.WindowSystem.compositingActive && !root.inConfigureAppletsMode && (((root.blurEnabled && root.useThemePanel) || (root.blurEnabled && root.forceSolidPanel && LatteCore.WindowSystem.compositingActive)) && (!root.inStartup || inForceHiding || inTempHiding)) } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "drawShadows" when: latteView && latteView.effects value: root.drawShadowsExternal && (!root.inStartup || inForceHiding || inTempHiding) && !(latteView && latteView.visibility.isHidden) } Binding{ target: latteView && latteView.effects ? latteView.effects : null property:"editShadow" when: latteView && latteView.effects value: root.editShadow } Binding{ target: latteView && latteView.effects ? latteView.effects : null property:"innerShadow" when: latteView && latteView.effects value: { if (editModeVisual.editAnimationEnded && !root.behaveAsPlasmaPanel) { return root.editShadow; } else { return background.shadows.headThickness; } } } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "settingsMaskSubtracted" when: latteView && latteView.effects value: { if (LatteCore.WindowSystem.compositingActive && root.editMode && editModeVisual.editAnimationEnded && (animations.needBothAxis.count === 0 || parabolic.factor.maxZoom===1) ) { return true; } else { return false; } } } //! View::Positioner bindings Binding{ target: latteView && latteView.positioner ? latteView.positioner : null property: "isStickedOnTopEdge" when: latteView && latteView.positioner value: plasmoid.configuration.isStickedOnTopEdge } Binding{ target: latteView && latteView.positioner ? latteView.positioner : null property: "isStickedOnBottomEdge" when: latteView && latteView.positioner value: plasmoid.configuration.isStickedOnBottomEdge } //! View::WindowsTracker bindings Binding{ target: latteView && latteView.windowsTracker ? latteView.windowsTracker : null property: "enabled" when: latteView && latteView.windowsTracker && latteView.visibility value: (latteView && latteView.visibility && !(latteView.visibility.mode === LatteCore.Types.AlwaysVisible /* Visibility */ || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow || latteView.visibility.mode === LatteCore.Types.AutoHide)) || applets.require.windowsTrackingCount > 0 /*Applets Need Windows Tracking */ || root.dragActiveWindowEnabled /*Dragging Active Window(Empty Areas)*/ || ((root.backgroundOnlyOnMaximized /*Dynamic Background */ || plasmoid.configuration.solidBackgroundForMaximized || root.disablePanelShadowMaximized || root.windowColors !== LatteContainment.Types.NoneWindowColors)) || (root.screenEdgeMarginsEnabled /*Dynamic Screen Edge Margin*/ && plasmoid.configuration.hideScreenGapForMaximized) } Connections{ target:root onEditModeChanged: { if (root.editMode) { visibilityManager.updateMaskArea(); } } } Connections{ target: background.totals onVisualLengthChanged: updateMaskArea(); onVisualThicknessChanged: updateMaskArea(); } Connections{ target: background.shadows onHeadThicknessChanged: updateMaskArea(); } Connections{ target: latteView ? latteView : null onXChanged: updateMaskArea(); onYChanged: updateMaskArea() onWidthChanged: updateMaskArea(); onHeightChanged: updateMaskArea(); } Connections{ target: animations.needBothAxis onCountChanged: updateMaskArea(); } Connections{ target: animations.needLength onCountChanged: updateMaskArea(); } Connections{ target: animations.needThickness onCountChanged: updateMaskArea(); } Connections{ target: layoutsManager onCurrentLayoutIsSwitching: { if (LatteCore.WindowSystem.compositingActive && latteView && latteView.layout && latteView.layout.name === layoutName) { manager.inTempHiding = true; manager.inForceHiding = true; parabolic.sglClearZoom(); manager.slotMustBeHide(); } } } Connections{ target: themeExtended ? themeExtended : null onRoundnessChanged: latteView.effects.forceMaskRedraw(); onThemeChanged: latteView.effects.forceMaskRedraw(); } onMaskIsFloatingChanged: updateMaskArea(); onNormalStateChanged: { if (normalState) { autosize.updateIconSize(); root.updateSizeForAppletsInFill(); } } onThicknessZoomOriginalChanged: updateMaskArea(); function slotContainsMouseChanged() { if(latteView.visibility.containsMouse && latteView.visibility.mode !== LatteCore.Types.SideBar) { updateMaskArea(); if (slidingAnimationAutoHiddenOut.running && !inTempHiding && !inForceHiding) { slotMustBeShown(); } } } function slotMustBeShown() { //! WindowsCanCover case if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { latteView.visibility.setViewOnFrontLayer(); return; } //! Normal Dodge/AutoHide case if (!slidingAnimationAutoHiddenIn.running && !inTempHiding && !inForceHiding){ slidingAnimationAutoHiddenIn.init(); } } function slotMustBeHide() { if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { latteView.visibility.setViewOnBackLayer(); return; } //! prevent sliding-in on startup if the dodge modes have sent a hide signal if (inStartupTimer.running && root.inStartup) { root.inStartup = false; } //! Normal Dodge/AutoHide case if((!slidingAnimationAutoHiddenOut.running && !latteView.visibility.blockHiding && (!latteView.visibility.containsMouse || latteView.visibility.mode === LatteCore.Types.SideBar)) || inForceHiding) { slidingAnimationAutoHiddenOut.init(); } } //! functions used for sliding out/in during location/screen changes function slotHideDockDuringLocationChange() { inTempHiding = true; blockUpdateMask = true; if(!slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.init(); } } function slotShowDockAfterLocationChange() { slidingAnimationAutoHiddenIn.init(); } function sendHideDockDuringLocationChangeFinished(){ blockUpdateMask = false; latteView.positioner.hideDockDuringLocationChangeFinished(); } function sendSlidingOutAnimationEnded() { latteView.visibility.hide(); latteView.visibility.isHidden = true; if (visibilityManager.debugManager) { console.log("hiding animation ended..."); } sendHideDockDuringLocationChangeFinished(); } ///test maskArea function updateMaskArea() { if (!latteView || blockUpdateMask) { return; } var localX = 0; var localY = 0; normalState = ((animations.needBothAxis.count === 0) && (animations.needLength.count === 0)) || (latteView.visibility.isHidden && !latteView.visibility.containsMouse && animations.needThickness.count === 0); // debug maskArea criteria if (debugManager) { console.log(animations.needBothAxis.count + ", " + animations.needLength.count + ", " + animations.needThickness.count + ", " + latteView.visibility.isHidden); if (previousNormalState !== normalState) { console.log("normal state changed to:" + normalState); previousNormalState = normalState; } } var tempLength = root.isHorizontal ? width : height; var tempThickness = root.isHorizontal ? height : width; var noCompositingEdit = !LatteCore.WindowSystem.compositingActive && root.editMode; if (LatteCore.WindowSystem.compositingActive || noCompositingEdit) { if (normalState) { //console.log("entered normal state..."); //count panel length //used when !compositing and in editMode if (noCompositingEdit) { tempLength = root.isHorizontal ? root.width : root.height; } else { tempLength = background.totals.visualLength; } tempThickness = thicknessNormal; if (animations.needThickness.count > 0) { tempThickness = LatteCore.WindowSystem.compositingActive ? thicknessZoom : thicknessNormal; } if (maskIsFloating) { tempThickness = tempThickness - maskFloatedGap; } if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } //configure x,y based on plasmoid position and root.panelAlignment(Alignment) if ((plasmoid.location === PlasmaCore.Types.BottomEdge) || (plasmoid.location === PlasmaCore.Types.TopEdge)) { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localY = latteView.height + tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localY = latteView.height - tempThickness - maskFloatedGap; } else { localY = latteView.height - tempThickness; } } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localY = -tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localY = maskFloatedGap; } else { localY = 0; } } if (noCompositingEdit) { localX = 0; } else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { localX = (latteView.width/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Left) { localX = background.offset; } else if (root.panelAlignment === LatteCore.Types.Center) { localX = (latteView.width/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Right) { localX = latteView.width - tempLength - background.offset; } } else if ((plasmoid.location === PlasmaCore.Types.LeftEdge) || (plasmoid.location === PlasmaCore.Types.RightEdge)){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localX = -tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localX = maskFloatedGap; } else { localX = 0; } } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localX = latteView.width + tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localX = latteView.width - tempThickness - maskFloatedGap; } else { localX = latteView.width - tempThickness; } } if (noCompositingEdit) { localY = 0; } else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { localY = (latteView.height/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Top) { localY = background.offset; } else if (root.panelAlignment === LatteCore.Types.Center) { localY = (latteView.height/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Bottom) { localY = latteView.height - tempLength - background.offset; } } if (latteView.visibility.isHidden && latteView && latteView.visibility.mode === LatteCore.Types.SideBar) { //!hide completely localX = -1; localY = -1; tempThickness = 1; tempLength = 1; } } else { // !inNormalState if(root.isHorizontal) tempLength = Screen.width; //screenGeometry.width; else tempLength = Screen.height; //screenGeometry.height; //grow only on length and not thickness var onlyLengthAnimation = (animations.needLength.count>0 && animations.needBothAxis.count === 0); if(onlyLengthAnimation) { //this is used to fix a bug with shadow showing when the animation of edit mode //is triggered tempThickness = editModeVisual.editAnimationEnded ? thicknessEditMode + root.editShadow : thicknessEditMode if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } else if (animations.needThickness.count > 0) { tempThickness = thicknessZoomOriginal; } } else{ //use all thickness space if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = LatteCore.WindowSystem.compositingActive ? thicknessAutoHidden : thicknessNormalOriginal; } else { tempThickness = !maskIsFloating ? thicknessZoomOriginal : thicknessZoomOriginal - maskFloatedGap; } } //configure the x,y position based on thickness if(plasmoid.location === PlasmaCore.Types.RightEdge) { localX = !maskIsFloating ? latteView.width - tempThickness : latteView.width - tempThickness - maskFloatedGap; if (localX < 0) { tempThickness = tempThickness + localX; localX = 0; } } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localY = !maskIsFloating ? latteView.height - tempThickness : latteView.height - tempThickness - maskFloatedGap; if (localY < 0) { tempThickness = tempThickness + localY; localY = 0; } } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localY = !maskIsFloating ? 0 : maskFloatedGap; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = !maskIsFloating ? 0 : maskFloatedGap; } } } // end of compositing calculations var maskArea = latteView.effects.mask; if (LatteCore.WindowSystem.compositingActive) { var maskLength = maskArea.width; //in Horizontal if (root.isVertical) { maskLength = maskArea.height; } var maskThickness = maskArea.height; //in Horizontal if (root.isVertical) { maskThickness = maskArea.width; } } else if (!noCompositingEdit){ //! no compositing case var overridesHidden = latteView.visibility.isHidden && !latteView.visibility.supportsKWinEdges; if (!overridesHidden) { localX = latteView.effects.rect.x; localY = latteView.effects.rect.y; } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localX = latteView.effects.rect.x; localY = root.height - thicknessAutoHidden; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localX = latteView.effects.rect.x; localY = 0; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = 0; localY = latteView.effects.rect.y; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localX = root.width - thicknessAutoHidden; localY = latteView.effects.rect.y; } } if (root.isHorizontal) { tempThickness = overridesHidden ? thicknessAutoHidden : latteView.effects.rect.height; tempLength = latteView.effects.rect.width; } else { tempThickness = overridesHidden ? thicknessAutoHidden : latteView.effects.rect.width; tempLength = latteView.effects.rect.height; } } // console.log("Not updating mask..."); if( maskArea.x !== localX || maskArea.y !== localY || maskLength !== tempLength || maskThickness !== tempThickness) { // console.log("Updating mask..."); var newMaskArea = Qt.rect(-1,-1,0,0); newMaskArea.x = localX; newMaskArea.y = localY; if (isHorizontal) { newMaskArea.width = tempLength; newMaskArea.height = tempThickness; } else { newMaskArea.width = tempThickness; newMaskArea.height = tempLength; } if (!LatteCore.WindowSystem.compositingActive) { latteView.effects.mask = newMaskArea; } else { if (latteView.behaveAsPlasmaPanel && !root.editMode) { latteView.effects.mask = Qt.rect(0,0,root.width,root.height); } else { latteView.effects.mask = newMaskArea; } } } var validIconSize = (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === autosize.iconSize); //console.log("reached updating geometry ::: "+dock.maskArea); if(inPublishingState && !latteView.visibility.isHidden && (normalState || root.editMode)) { //! Important: Local Geometry must not be updated when view ISHIDDEN //! because it breaks Dodge(s) modes in such case var localGeometry = Qt.rect(0, 0, root.width, root.height); //the shadows size must be removed from the maskArea //before updating the localDockGeometry if (!latteView.behaveAsPlasmaPanel || root.editMode) { var cleanThickness = metrics.totals.thickness; var edgeMargin = finalScreenEdgeMargin; if (plasmoid.location === PlasmaCore.Types.TopEdge) { localGeometry.x = latteView.effects.rect.x; // from effects area localGeometry.width = latteView.effects.rect.width; // from effects area localGeometry.y = edgeMargin; localGeometry.height = cleanThickness ; } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localGeometry.x = latteView.effects.rect.x; // from effects area localGeometry.width = latteView.effects.rect.width; // from effects area localGeometry.y = root.height - cleanThickness - edgeMargin; localGeometry.height = cleanThickness; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localGeometry.y = latteView.effects.rect.y; // from effects area localGeometry.height = latteView.effects.rect.height; // from effects area localGeometry.x = edgeMargin; localGeometry.width = cleanThickness; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localGeometry.y = latteView.effects.rect.y; // from effects area localGeometry.height = latteView.effects.rect.height; // from effects area localGeometry.x = root.width - cleanThickness - edgeMargin; localGeometry.width = cleanThickness; } //set the boundaries for latteView local geometry //qBound = qMax(min, qMin(value, max)). localGeometry.x = Math.max(0, Math.min(localGeometry.x, latteView.width)); localGeometry.y = Math.max(0, Math.min(localGeometry.y, latteView.height)); localGeometry.width = Math.min(localGeometry.width, latteView.width); localGeometry.height = Math.min(localGeometry.height, latteView.height); } //console.log("update geometry ::: "+localGeometry); latteView.localGeometry = localGeometry; } } Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Item{ anchors.fill:parent Rectangle{ id: windowBackground anchors.fill: parent border.color: "red" border.width: 1 color: "transparent" } Rectangle{ x: latteView ? latteView.effects.mask.x : -1 y: latteView ? latteView.effects.mask.y : -1 height: latteView ? latteView.effects.mask.height : 0 width: latteView ? latteView.effects.mask.width : 0 border.color: "green" border.width: 1 color: "transparent" } } } /***Hiding/Showing Animations*****/ //////////////// Animations - Slide In - Out SequentialAnimation{ id: slidingAnimationAutoHiddenOut ScriptAction{ script: { root.isHalfShown = true; } } PropertyAnimation { target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" to: { if (root.behaveAsPlasmaPanel) { return slidingOutToPos; } if (LatteCore.WindowSystem.compositingActive) { return slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return slidingOutToPos + 1; } else { return slidingOutToPos - 1; } } } duration: manager.animationSpeed easing.type: Easing.InQuad } ScriptAction{ script: { latteView.visibility.isHidden = true; if (root.behaveAsPlasmaPanel && latteView.positioner.slideOffset !== 0) { //! hide real panels when they slide-out latteView.visibility.hide(); } } } onStarted: { if (manager.debugManager) { console.log("hiding animation started..."); } } onStopped: { //! Trying to move the ending part of the signals at the end of editing animation if (!manager.inTempHiding) { manager.updateMaskArea(); } else { if (!editModeVisual.inEditMode) { manager.sendSlidingOutAnimationEnded(); } } latteView.visibility.slideOutFinished(); } function init() { if (manager.inLocationAnimation || !latteView.visibility.blockHiding) { start(); } } } SequentialAnimation{ id: slidingAnimationAutoHiddenIn PauseAnimation{ duration: manager.inTempHiding && animations.active ? 500 : 0 } PropertyAnimation { target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } ScriptAction{ script: { root.isHalfShown = false; root.inStartup = false; } } onStarted: { latteView.visibility.show(); if (manager.debugManager) { console.log("showing animation started..."); } } onStopped: { inSlidingIn = false; if (manager.inTempHiding) { manager.inTempHiding = false; autosize.updateIconSize(); } manager.inTempHiding = false; autosize.updateIconSize(); if (manager.debugManager) { console.log("showing animation ended..."); } latteView.visibility.slideInFinished(); //! this is needed in order to update dock absolute geometry correctly in the end AND //! when a floating dock is sliding-in through masking techniques updateMaskArea(); } function init() { inSlidingIn = true; if (slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.stop(); } latteView.visibility.isHidden = false; updateMaskArea(); start(); } } //! Slides Animations for FLOATING+BEHAVEASPLASMAPANEL when //! HIDETHICKSCREENCAP dynamically is enabled/disabled SequentialAnimation{ id: slidingInRealFloating PropertyAnimation { target: latteView.positioner property: "slideOffset" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } } SequentialAnimation{ id: slidingOutRealFloating PropertyAnimation { target: latteView.positioner property: "slideOffset" to: plasmoid.configuration.screenEdgeMargin duration: manager.animationSpeed easing.type: Easing.InQuad } } Connections { target: root onHideThickScreenGapChanged: { if (root.behaveAsPlasmaPanel && !latteView.visibility.isHidden && !inSlidingIn && !inSlidingOut && !inStartup) { if (hideThickScreenGap) { latteView.positioner.inSlideAnimation = true; slidingInRealFloating.stop(); slidingOutRealFloating.start(); } else { slidingOutRealFloating.stop(); slidingInRealFloating.start(); latteView.positioner.inSlideAnimation = false; } } } } }