diff --git a/app/view/effects.cpp b/app/view/effects.cpp index 91d1bc77..89debbd8 100644 --- a/app/view/effects.cpp +++ b/app/view/effects.cpp @@ -1,576 +1,552 @@ /* * 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 . */ #include "effects.h" // local #include "panelshadows_p.h" #include "view.h" #include "settings/primaryconfigview.h" #include "../../liblatte2/types.h" // Qt #include // KDE #include #include namespace Latte { namespace ViewPart { Effects::Effects(Latte::View *parent) : QObject(parent), m_view(parent) { init(); } Effects::~Effects() { } void Effects::init() { connect(this, &Effects::backgroundOpacityChanged, this, &Effects::updateEffects); connect(this, &Effects::drawEffectsChanged, this, &Effects::updateEffects); connect(this, &Effects::rectChanged, this, &Effects::updateEffects); connect(this, &Effects::settingsMaskSubtractedChanged, this, &Effects::updateMask); connect(this, &Effects::drawShadowsChanged, this, [&]() { if (m_view->behaveAsPlasmaPanel()) { updateEnabledBorders(); } }); connect(m_view, &Latte::View::alignmentChanged, this, &Effects::updateEnabledBorders); connect(m_view, &Latte::View::behaveAsPlasmaPanelChanged, this, &Effects::updateEffects); connect(m_view, &Latte::View::behaveAsPlasmaPanelChanged, this, &Effects::updateShadows); connect(m_view, &Latte::View::configWindowGeometryChanged, this, &Effects::updateMask); - - connect(m_view, &QQuickWindow::widthChanged, this, [&]() { - if (m_view->behaveAsPlasmaPanel() && m_view->formFactor() == Plasma::Types::Vertical) { - updateMaskThickness(); - } - }); - connect(m_view, &QQuickWindow::heightChanged, this, [&]() { - if (m_view->behaveAsPlasmaPanel() && m_view->formFactor() == Plasma::Types::Horizontal) { - updateMaskThickness(); - } - }); } bool Effects::animationsBlocked() const { return m_animationsBlocked; } void Effects::setAnimationsBlocked(bool blocked) { if (m_animationsBlocked == blocked) { return; } m_animationsBlocked = blocked; emit animationsBlockedChanged(); } bool Effects::drawShadows() const { return m_drawShadows; } void Effects::setDrawShadows(bool draw) { if (m_drawShadows == draw) { return; } m_drawShadows = draw; if (m_view->behaveAsPlasmaPanel() && m_drawShadows) { PanelShadows::self()->addWindow(m_view, m_enabledBorders); } else { PanelShadows::self()->removeWindow(m_view); } emit drawShadowsChanged(); } bool Effects::drawEffects() const { return m_drawEffects; } void Effects::setDrawEffects(bool draw) { if (m_drawEffects == draw) { return; } m_drawEffects = draw; emit drawEffectsChanged(); } bool Effects::forceDrawCenteredBorders() const { return m_forceDrawCenteredBorders; } void Effects::setForceDrawCenteredBorders(bool draw) { if (m_forceDrawCenteredBorders == draw) { return; } m_forceDrawCenteredBorders = draw; } int Effects::backgroundOpacity() const { return m_backgroundOpacity; } void Effects::setBackgroundOpacity(int opacity) { if (m_backgroundOpacity == opacity) { return; } m_backgroundOpacity = opacity; emit backgroundOpacityChanged(); } int Effects::editShadow() const { return m_editShadow; } void Effects::setEditShadow(int shadow) { if (m_editShadow == shadow) { return; } m_editShadow = shadow; emit editShadowChanged(); } int Effects::innerShadow() const { return m_innerShadow; } void Effects::setInnerShadow(int shadow) { if (m_innerShadow == shadow) return; m_innerShadow = shadow; emit innerShadowChanged(); } bool Effects::settingsMaskSubtracted() const { return m_settingsMaskSubtracted; } void Effects::setSettingsMaskSubtracted(bool enabled) { if (m_settingsMaskSubtracted == enabled) { return; } m_settingsMaskSubtracted = enabled; emit settingsMaskSubtractedChanged(); } int Effects::maskThickness() const { - return m_maskThickness; -} - -void Effects::setMaskThickness(const int &thickness) -{ - if (m_maskThickness == thickness) { - return; - } - - m_maskThickness = thickness; - emit maskThicknessChanged(); -} - -void Effects::updateMaskThickness() -{ - if (m_mask.isNull() || m_mask.width() == 0 || m_mask.height() == 0) { - setMaskThickness(m_view->formFactor() == Plasma::Types::Horizontal ? m_view->height() : m_view->width()); + if (m_view->mask().isEmpty()) { + return m_view->formFactor() == Plasma::Types::Horizontal ? m_view->width() : m_view->height(); } switch (m_view->location()) { case Plasma::Types::TopEdge: - setMaskThickness(m_mask.bottom()); + return m_view->mask().boundingRect().bottom(); break; case Plasma::Types::LeftEdge: - setMaskThickness(m_mask.right()); + return m_view->mask().boundingRect().right(); break; case Plasma::Types::RightEdge: - setMaskThickness(m_mask.left()); + return m_view->mask().boundingRect().left(); break; case Plasma::Types::BottomEdge: - setMaskThickness(m_mask.top()); + return m_view->mask().boundingRect().top(); + break; + + default: + return 64; break; } } QRegion Effects::subtrackedMaskFromWindow(QRegion initialRegion, QQuickView *window) { QRegion subtractedMask = initialRegion; int start; int length; if (m_view->formFactor() == Plasma::Types::Horizontal) { if (KWindowSystem::isPlatformX11()) { start = window->x(); length = window->width(); } else { start = m_view->x(); length = m_view->width(); } } else { if (KWindowSystem::isPlatformX11()) { start = window->y(); length = window->height(); } else { start = m_view->y(); length = m_view->height(); } } if (m_settingsMaskSubtracted && window) { QRect windowMask; //! we need to subtrack the mask areas that overlap with underlying window switch (m_view->location()) { case Plasma::Types::TopEdge: windowMask.setTopLeft(QPoint(start - m_view->x(), m_mask.y() + m_mask.height() - m_editShadow)); windowMask.setSize(QSize(length, m_editShadow)); break; case Plasma::Types::LeftEdge: windowMask.setTopLeft(QPoint(m_mask.right() + 1 - m_editShadow, start - m_view->y())); windowMask.setSize(QSize(m_editShadow, length)); break; case Plasma::Types::RightEdge: windowMask.setTopLeft(QPoint(m_mask.x(), start - m_view->y())); windowMask.setSize(QSize(m_editShadow, length)); break; case Plasma::Types::BottomEdge: windowMask.setTopLeft(QPoint(start - m_view->x(), m_mask.y())); windowMask.setSize(QSize(length, m_editShadow)); break; default: break; } subtractedMask = subtractedMask.subtracted(windowMask); } return subtractedMask; } QRegion Effects::subtractedMask() { QRegion subMask = m_mask; if (m_settingsMaskSubtracted && m_view->configView()) { subMask = subtrackedMaskFromWindow(subMask, m_view->configView()); ViewPart::PrimaryConfigView *primaryConfig = qobject_cast(m_view->configView()); if (primaryConfig && m_view->formFactor() == Plasma::Types::Horizontal && primaryConfig->secondaryWindow()) { subMask = subtrackedMaskFromWindow(subMask, primaryConfig->secondaryWindow()); } } return subMask; } QRect Effects::rect() const { return m_rect; } void Effects::setRect(QRect area) { if (KWindowSystem::compositingActive()) { QRect inWindowRect = area.intersected(QRect(0, 0, m_view->width(), m_view->height())); if (m_rect == inWindowRect) { return; } m_rect = inWindowRect; } else { if (m_rect == area) { return; } m_rect = area; } emit rectChanged(); } QRect Effects::mask() const { return m_mask; } void Effects::setMask(QRect area) { - if (m_mask == area) { + if (m_mask == area) return; - } m_mask = area; updateMask(); - updateMaskThickness(); // qDebug() << "dock mask set:" << m_mask; emit maskChanged(); } void Effects::forceMaskRedraw() { if (m_background) { delete m_background; } m_background = new Plasma::FrameSvg(this); m_background->setImagePath(QStringLiteral("widgets/panel-background")); m_background->setEnabledBorders(m_enabledBorders); updateMask(); } void Effects::updateMask() { if (KWindowSystem::compositingActive()) { if (m_view->behaveAsPlasmaPanel()) { m_view->setMask(QRect()); } else { m_view->setMask(subtractedMask()); } } else { //! this is used when compositing is disabled and provides //! the correct way for the mask to be painted in order for //! rounded corners to be shown correctly //! the enabledBorders check was added because there was cases //! that the mask region wasn't calculated correctly after location changes if (!m_background) { if (m_background && m_background->enabledBorders() != m_enabledBorders) { delete m_background; } m_background = new Plasma::FrameSvg(this); } if (m_background->imagePath() != "widgets/panel-background") { m_background->setImagePath(QStringLiteral("widgets/panel-background")); } m_background->setEnabledBorders(m_enabledBorders); m_background->resizeFrame(m_mask.size()); QRegion fixedMask = m_background->mask(); fixedMask.translate(m_mask.x(), m_mask.y()); //! fix for KF5.32 that return empty QRegion's for the mask if (fixedMask.isEmpty()) { fixedMask = QRegion(m_mask); } m_view->setMask(fixedMask); } } void Effects::clearShadows() { PanelShadows::self()->removeWindow(m_view); } void Effects::updateShadows() { if (m_view->behaveAsPlasmaPanel() && drawShadows()) { PanelShadows::self()->addWindow(m_view, enabledBorders()); } else { PanelShadows::self()->removeWindow(m_view); } } void Effects::updateEffects() { //! Don't apply any effect before the wayland surface is created under wayland //! https://bugs.kde.org/show_bug.cgi?id=392890 if (KWindowSystem::isPlatformWayland() && !m_view->surface()) { return; } if (!m_view->behaveAsPlasmaPanel()) { if (m_drawEffects && !m_rect.isNull() && !m_rect.isEmpty()) { //! this is used when compositing is disabled and provides //! the correct way for the mask to be painted in order for //! rounded corners to be shown correctly if (!m_background) { m_background = new Plasma::FrameSvg(this); } if (m_background->imagePath() != "widgets/panel-background") { m_background->setImagePath(QStringLiteral("widgets/panel-background")); } m_background->setEnabledBorders(m_enabledBorders); m_background->resizeFrame(m_rect.size()); QRegion fixedMask = m_background->mask(); fixedMask.translate(m_rect.x(), m_rect.y()); //! fix1, for KF5.32 that return empty QRegion's for the mask if (fixedMask.isEmpty()) { fixedMask = QRegion(m_rect); } KWindowEffects::enableBlurBehind(m_view->winId(), true, fixedMask); bool drawBackgroundEffect = m_theme.backgroundContrastEnabled() && (m_backgroundOpacity == 100); //based on Breeze Dark theme behavior the enableBackgroundContrast even though it does accept //a QRegion it uses only the first rect. The bug was that for Breeze Dark there was a line //at the dock bottom that was distinguishing it from other themes KWindowEffects::enableBackgroundContrast(m_view->winId(), drawBackgroundEffect, m_theme.backgroundContrast(), m_theme.backgroundIntensity(), m_theme.backgroundSaturation(), fixedMask.boundingRect()); } else { KWindowEffects::enableBlurBehind(m_view->winId(), false); KWindowEffects::enableBackgroundContrast(m_view->winId(), false); } } else if (m_view->behaveAsPlasmaPanel() && m_drawEffects) { KWindowEffects::enableBlurBehind(m_view->winId(), true); bool drawBackgroundEffect = m_theme.backgroundContrastEnabled() && (m_backgroundOpacity == 100); KWindowEffects::enableBackgroundContrast(m_view->winId(), drawBackgroundEffect, m_theme.backgroundContrast(), m_theme.backgroundIntensity(), m_theme.backgroundSaturation()); } else { KWindowEffects::enableBlurBehind(m_view->winId(), false); KWindowEffects::enableBackgroundContrast(m_view->winId(), false); } } //!BEGIN draw panel shadows outside the dock window Plasma::FrameSvg::EnabledBorders Effects::enabledBorders() const { return m_enabledBorders; } void Effects::updateEnabledBorders() { if (!m_view->screen()) { return; } Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; switch (m_view->location()) { case Plasma::Types::TopEdge: borders &= ~Plasma::FrameSvg::TopBorder; break; case Plasma::Types::LeftEdge: borders &= ~Plasma::FrameSvg::LeftBorder; break; case Plasma::Types::RightEdge: borders &= ~Plasma::FrameSvg::RightBorder; break; case Plasma::Types::BottomEdge: borders &= ~Plasma::FrameSvg::BottomBorder; break; default: break; } if ((m_view->location() == Plasma::Types::LeftEdge || m_view->location() == Plasma::Types::RightEdge)) { if (m_view->maxLength() == 1 && m_view->alignment() == Latte::Types::Justify && !m_forceDrawCenteredBorders) { borders &= ~Plasma::FrameSvg::TopBorder; borders &= ~Plasma::FrameSvg::BottomBorder; } if (m_view->alignment() == Latte::Types::Top && !m_forceDrawCenteredBorders && m_view->offset() == 0) { borders &= ~Plasma::FrameSvg::TopBorder; } if (m_view->alignment() == Latte::Types::Bottom && !m_forceDrawCenteredBorders && m_view->offset() == 0) { borders &= ~Plasma::FrameSvg::BottomBorder; } } if (m_view->location() == Plasma::Types::TopEdge || m_view->location() == Plasma::Types::BottomEdge) { if (m_view->maxLength() == 1 && m_view->alignment() == Latte::Types::Justify) { borders &= ~Plasma::FrameSvg::LeftBorder; borders &= ~Plasma::FrameSvg::RightBorder; } if (m_view->alignment() == Latte::Types::Left && m_view->offset() == 0) { borders &= ~Plasma::FrameSvg::LeftBorder; } if (m_view->alignment() == Latte::Types::Right && m_view->offset() == 0) { borders &= ~Plasma::FrameSvg::RightBorder; } } if (m_enabledBorders != borders) { m_enabledBorders = borders; emit enabledBordersChanged(); } if (!m_view->behaveAsPlasmaPanel() || !m_drawShadows) { PanelShadows::self()->removeWindow(m_view); } else { PanelShadows::self()->setEnabledBorders(m_view, borders); } } //!END draw panel shadows outside the dock window } } diff --git a/app/view/effects.h b/app/view/effects.h index 0207dc8d..673c066b 100644 --- a/app/view/effects.h +++ b/app/view/effects.h @@ -1,155 +1,151 @@ /* * 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 . */ #ifndef EFFECTS_H #define EFFECTS_H // Qt #include #include #include #include // Plasma #include #include namespace Latte { class View; } namespace Latte { namespace ViewPart { class Effects: public QObject { Q_OBJECT Q_PROPERTY(bool animationsBlocked READ animationsBlocked NOTIFY animationsBlockedChanged) Q_PROPERTY(bool drawShadows READ drawShadows WRITE setDrawShadows NOTIFY drawShadowsChanged) Q_PROPERTY(bool drawEffects READ drawEffects WRITE setDrawEffects NOTIFY drawEffectsChanged) Q_PROPERTY(bool settingsMaskSubtracted READ settingsMaskSubtracted WRITE setSettingsMaskSubtracted NOTIFY settingsMaskSubtractedChanged) //! thickness shadow size when is drawn inside the window from qml Q_PROPERTY(int backgroundOpacity READ backgroundOpacity WRITE setBackgroundOpacity NOTIFY backgroundOpacityChanged) Q_PROPERTY(int editShadow READ editShadow WRITE setEditShadow NOTIFY editShadowChanged) Q_PROPERTY(int innerShadow READ innerShadow WRITE setInnerShadow NOTIFY innerShadowChanged) Q_PROPERTY(QRect mask READ mask WRITE setMask NOTIFY maskChanged) Q_PROPERTY(QRect rect READ rect WRITE setRect NOTIFY rectChanged) Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged) public: Effects(Latte::View *parent); virtual ~Effects(); bool animationsBlocked() const; void setAnimationsBlocked(bool blocked); bool drawShadows() const; void setDrawShadows(bool draw); bool drawEffects() const; void setDrawEffects(bool draw); bool forceDrawCenteredBorders() const; void setForceDrawCenteredBorders(bool draw); bool settingsMaskSubtracted() const; void setSettingsMaskSubtracted(bool enabled); int backgroundOpacity() const; void setBackgroundOpacity(int opacity); int editShadow() const; void setEditShadow(int shadow); int innerShadow() const; void setInnerShadow(int shadow); int maskThickness() const; - void setMaskThickness(const int &thickness); QRect mask() const; void setMask(QRect area); QRect rect() const; void setRect(QRect area); Plasma::FrameSvg::EnabledBorders enabledBorders() const; public slots: Q_INVOKABLE void forceMaskRedraw(); void clearShadows(); void updateShadows(); void updateEffects(); void updateEnabledBorders(); void updateMask(); signals: void animationsBlockedChanged(); void backgroundOpacityChanged(); void drawShadowsChanged(); void drawEffectsChanged(); void editShadowChanged(); void enabledBordersChanged(); void maskChanged(); - void maskThicknessChanged(); void innerShadowChanged(); void rectChanged(); void settingsMaskSubtractedChanged(); private slots: void init(); - void updateMaskThickness(); private: QRegion subtractedMask(); QRegion subtrackedMaskFromWindow(QRegion initialRegion, QQuickView *window); private: bool m_animationsBlocked{false}; bool m_drawShadows{true}; bool m_drawEffects{false}; bool m_forceDrawCenteredBorders{false}; bool m_settingsMaskSubtracted{false}; int m_backgroundOpacity{100}; int m_editShadow{0}; int m_innerShadow{0}; - int m_maskThickness{64}; QRect m_rect; QRect m_mask; QPointer m_view; Plasma::Theme m_theme; //only for the mask on disabled compositing, not to actually paint Plasma::FrameSvg *m_background{nullptr}; //only for the mask, not to actually paint Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders}; }; } } #endif diff --git a/app/view/visibilitymanager.cpp b/app/view/visibilitymanager.cpp index c5d53b05..105d3139 100644 --- a/app/view/visibilitymanager.cpp +++ b/app/view/visibilitymanager.cpp @@ -1,768 +1,763 @@ /* * 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 "effects.h" #include "positioner.h" #include "screenedgeghostwindow.h" #include "view.h" #include "windowstracker/currentscreentracker.h" #include "../lattecorona.h" #include "../screenpool.h" #include "../layouts/manager.h" #include "../wm/abstractwindowinterface.h" #include "../../liblatte2/extras.h" // Qt #include // KDE #include #include #include 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::slideInFinished, this, &VisibilityManager::updateHiddenState); connect(this, &VisibilityManager::slideOutFinished, this, &VisibilityManager::updateHiddenState); if (m_latteView) { connect(m_latteView, &Latte::View::eventTriggered, this, &VisibilityManager::viewEventManager); connect(m_latteView, &Latte::View::absoluteGeometryChanged, this, [&]() { if (m_mode == Types::AlwaysVisible && m_latteView->screen()) { updateStrutsBasedOnLayoutsAndActivities(); } }); connect(m_latteView->windowsTracker(), &WindowsTracker::activeWindowDraggingStarted, this, &VisibilityManager::activeWindowDraggingStarted); } if (m_corona) { connect(this, &VisibilityManager::modeChanged, this, [&]() { emit m_corona->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) { // qDebug() << "must be shown"; emit mustBeShown(); } }); connect(&m_timerHide, &QTimer::timeout, this, [&]() { if (!m_blockHiding && !m_isHidden && !m_dragEnter) { // qDebug() << "must be hide"; emit mustBeHide(); } }); restoreConfig(); } VisibilityManager::~VisibilityManager() { qDebug() << "VisibilityManager deleting..."; m_wm->removeViewStruts(*m_latteView); if (m_edgeGhostWindow) { m_edgeGhostWindow->deleteLater(); } } Types::Visibility VisibilityManager::mode() const { return m_mode; } 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; if (mode != Types::AlwaysVisible && mode != Types::WindowsGoBelow) { //set wayland visibility mode if (m_latteView->surface()) { m_latteView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::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; } else { //set wayland visibility mode if (m_latteView->surface()) { m_latteView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::AutoHide); } } switch (m_mode) { case Types::AlwaysVisible: { if (m_latteView->containment() && m_latteView->screen()) { updateStrutsBasedOnLayoutsAndActivities(); } - m_connections[base] = connect(m_latteView->effects(), &ViewPart::Effects::maskThicknessChanged, this, [&]() { - updateStrutsBasedOnLayoutsAndActivities(); - }); - m_connections[base+1] = connect(m_corona->layoutsManager(), &Layouts::Manager::currentLayoutNameChanged, this, [&]() { + m_connections[base] = connect(m_corona->layoutsManager(), &Layouts::Manager::currentLayoutNameChanged, this, [&]() { if (m_corona && m_corona->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { updateStrutsBasedOnLayoutsAndActivities(true); } }); - m_connections[base+2] = connect(m_latteView, &Latte::View::activitiesChanged, this, [&]() { + m_connections[base+1] = connect(m_latteView, &Latte::View::activitiesChanged, this, [&]() { if (m_corona && m_corona->layoutsManager()->memoryUsage() == Types::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; 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() == Types::MultipleLayouts && m_latteView->layout() && !m_latteView->positioner()->inLocationChangeAnimation() && m_latteView->layout()->isCurrent()); if (m_corona->layoutsManager()->memoryUsage() == Types::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 visibleThickness = qMin(m_latteView->effects()->maskThickness(), m_latteView->normalThickness()); - qDebug() << " VISIBLE THICKNESS ::: " << visibleThickness; - switch (m_latteView->location()) { - case Plasma::Types::TopEdge: { - calcs = QRect(m_latteView->x(), m_latteView->y(), m_latteView->width(), visibleThickness); - break; - } + case Plasma::Types::TopEdge: { + calcs = QRect(m_latteView->x(), m_latteView->y(), m_latteView->width(), visibleThickness); + break; + } - case Plasma::Types::BottomEdge: { - int y = m_latteView->y() + m_latteView->height() - visibleThickness; - calcs = QRect(m_latteView->x(), y, m_latteView->width(), visibleThickness); - break; - } + case Plasma::Types::BottomEdge: { + int y = m_latteView->y() + m_latteView->height() - visibleThickness; + calcs = QRect(m_latteView->x(), y, m_latteView->width(), visibleThickness); + break; + } - case Plasma::Types::LeftEdge: { - calcs = QRect(m_latteView->x(), m_latteView->y(), visibleThickness, m_latteView->height()); - break; - } + case Plasma::Types::LeftEdge: { + calcs = QRect(m_latteView->x(), m_latteView->y(), visibleThickness, m_latteView->height()); + break; + } - case Plasma::Types::RightEdge: { - int x = m_latteView->x() + m_latteView->width() - visibleThickness; - calcs = QRect(x, m_latteView->y(), visibleThickness, m_latteView->height()); - break; - } + case Plasma::Types::RightEdge: { + int x = m_latteView->x() + m_latteView->width() - visibleThickness; + calcs = QRect(x, m_latteView->y(), visibleThickness, 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::isHidden() const { return m_isHidden; } void VisibilityManager::setIsHidden(bool isHidden) { if (m_isHidden == isHidden) return; if (m_blockHiding && isHidden) { qWarning() << "isHidden property is blocked, ignoring update"; return; } m_isHidden = isHidden; updateGhostWindowState(); emit isHiddenChanged(); } bool VisibilityManager::blockHiding() const { return m_blockHiding; } void VisibilityManager::setBlockHiding(bool blockHiding) { if (m_blockHiding == blockHiding) { return; } m_blockHiding = blockHiding; // qDebug() << "blockHiding:" << blockHiding; if (m_blockHiding) { m_timerHide.stop(); if (m_isHidden) { emit mustBeShown(); } } else { updateHiddenState(); } emit blockHidingChanged(); } int VisibilityManager::timerShow() const { return m_timerShow.interval(); } void VisibilityManager::setTimerShow(int msec) { m_timerShow.setInterval(msec); emit timerShowChanged(); } int VisibilityManager::timerHide() const { return m_timerHide.interval(); } void VisibilityManager::setTimerHide(int msec) { m_timerHide.setInterval(msec); emit timerHideChanged(); } bool VisibilityManager::supportsKWinEdges() const { return (m_edgeGhostWindow != nullptr); } void VisibilityManager::updateGhostWindowState() { if (supportsKWinEdges()) { bool inCurrentLayout = (m_corona->layoutsManager()->memoryUsage() == Types::SingleLayout || (m_corona->layoutsManager()->memoryUsage() == Types::MultipleLayouts && m_latteView->layout() && !m_latteView->positioner()->inLocationChangeAnimation() && m_latteView->layout()->name() == m_corona->layoutsManager()->currentLayoutName())); if (inCurrentLayout) { m_wm->setEdgeStateFor(m_edgeGhostWindow, m_isHidden); } else { m_wm->setEdgeStateFor(m_edgeGhostWindow, false); } } } void VisibilityManager::hide() { if (KWindowSystem::isPlatformX11()) { m_latteView->setVisible(false); } } void VisibilityManager::show() { if (KWindowSystem::isPlatformX11()) { m_latteView->setVisible(true); } } void VisibilityManager::raiseView(bool raise) { if (m_blockHiding) 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(); }); } void VisibilityManager::updateHiddenState() { if (m_dragEnter) return; switch (m_mode) { case Types::AutoHide: 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); } } void VisibilityManager::activeWindowDraggingStarted() { setContainsMouse(false); updateHiddenState(); } 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); } 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(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 = static_cast(m_latteView->containment()->config().readEntry("visibility", static_cast(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; } auto fMode = static_cast(m_latteView->containment()->config().readEntry("visibility", static_cast(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(); if (contains && m_mode != Types::AlwaysVisible) { raiseView(true); } } void VisibilityManager::viewEventManager(QEvent *ev) { switch (ev->type()) { case QEvent::Enter: setContainsMouse(true); break; case QEvent::Leave: setContainsMouse(false); break; case QEvent::DragEnter: m_dragEnter = true; if (m_isHidden) 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(); updateKWinEdgesSupport(); } void VisibilityManager::updateKWinEdgesSupport() { if (m_mode == Types::AutoHide || m_mode == Types::DodgeActive || m_mode == Types::DodgeAllWindows || m_mode == Types::DodgeMaximized) { if (m_enableKWinEdgesFromUser) { createEdgeGhostWindow(); } else if (!m_enableKWinEdgesFromUser) { deleteEdgeGhostWindow(); } } else if (m_mode == Types::AlwaysVisible || m_mode == Types::WindowsGoBelow) { deleteEdgeGhostWindow(); } } void VisibilityManager::createEdgeGhostWindow() { if (!m_edgeGhostWindow) { m_edgeGhostWindow = new ScreenEdgeGhostWindow(m_latteView); m_wm->setViewExtraFlags(*m_edgeGhostWindow); connect(m_edgeGhostWindow, &ScreenEdgeGhostWindow::containsMouseChanged, this, [ = ](bool contains) { if (contains) { raiseView(true); } else { m_timerShow.stop(); updateGhostWindowState(); } }); m_connectionsKWinEdges[0] = connect(m_wm, &WindowSystem::AbstractWindowInterface::currentActivityChanged, this, [&]() { bool inCurrentLayout = (m_corona->layoutsManager()->memoryUsage() == Types::SingleLayout || (m_corona->layoutsManager()->memoryUsage() == Types::MultipleLayouts && m_latteView->layout() && !m_latteView->positioner()->inLocationChangeAnimation() && m_latteView->layout()->name() == m_corona->layoutsManager()->currentLayoutName())); if (m_edgeGhostWindow) { if (inCurrentLayout) { m_wm->setEdgeStateFor(m_edgeGhostWindow, m_isHidden); } else { m_wm->setEdgeStateFor(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(); } } //! END: VisibilityManager implementation } }