#include "visibilitymanager.h" #include "abstractinterface.h" #include "xwindowinterface.h" #include "plasmaquick/containmentview.h" #include "../liblattedock/dock.h" #include #include VisibilityManager::VisibilityManager(PlasmaQuick::ContainmentView *view) : QObject(view), m_disableHiding(false), m_isAutoHidden(false), m_isDockWindowType(true), m_isHovered(false), m_secondInitPass(false), m_windowIsInAttention(false), m_childrenLength(-1), m_view(view) { // m_windowSystem = new WindowSystem(this); // connect(m_windowSystem, SIGNAL(compositingChanged()), this, SLOT(compositingChanged())); m_interface = new NowDock::XWindowInterface(m_view); connect(m_interface, SIGNAL(windowInAttention(bool)), this, SLOT(setWindowInAttention(bool))); connect(m_interface, SIGNAL(activeWindowChanged()), this, SLOT(activeWindowChanged())); m_interface->setDockToAllDesktops(); //fixes a bug in plasma-framework with wrong popups placement m_interface->setDockNumber(2); // connect(this, SIGNAL(screenChanged(QScreen *)), this, SLOT(screenChanged(QScreen *))); // setPanelScreen(screen()); m_updateStateTimer.setSingleShot(true); m_updateStateTimer.setInterval(900); connect(&m_updateStateTimer, &QTimer::timeout, this, &VisibilityManager::updateState); m_initTimer.setSingleShot(true); m_initTimer.setInterval(400); connect(&m_initTimer, &QTimer::timeout, this, &VisibilityManager::initWindow); connect(this, SIGNAL(panelVisibilityChanged()), this, SLOT(updateVisibilityFlags())); setPanelVisibility(Latte::Dock::DodgeActive); // updateVisibilityFlags(); // connect(this, SIGNAL(locationChanged()), this, SLOT(updateWindowPosition())); connect(this, SIGNAL(windowInAttentionChanged()), this, SLOT(updateState())); initialize(); } VisibilityManager::~VisibilityManager() { } void VisibilityManager::setContainment(Plasma::Containment *containment) { if (containment == m_containment) { return; } m_containment = containment; // setVisibility(mode); } Latte::Dock::Visibility VisibilityManager::panelVisibility() const { return m_panelVisibility; } void VisibilityManager::setPanelVisibility(Latte::Dock::Visibility state) { if (m_panelVisibility == state) { return; } m_panelVisibility = state; emit panelVisibilityChanged(); } bool VisibilityManager::isAutoHidden() const { return m_isAutoHidden; } void VisibilityManager::setIsAutoHidden(bool state) { if (m_isAutoHidden == state) { return; } m_isAutoHidden = state; emit isAutoHiddenChanged(); } bool VisibilityManager::windowInAttention() const { return m_windowIsInAttention; } void VisibilityManager::setWindowInAttention(bool state) { if (m_windowIsInAttention == state) { return; } m_windowIsInAttention = state; emit windowInAttentionChanged(); } bool VisibilityManager::disableHiding() const { return m_disableHiding; } void VisibilityManager::setDisableHiding(bool value) { if (m_disableHiding == value) { return; } m_disableHiding = value; emit disableHidingChanged(); if (!m_disableHiding) { m_updateStateTimer.start(); } } bool VisibilityManager::isDockWindowType() const { return m_isDockWindowType; } void VisibilityManager::setIsDockWindowType(bool state) { if (m_isDockWindowType == state) { return; } m_isDockWindowType = state; updateVisibilityFlags(); emit isDockWindowTypeChanged(); m_updateStateTimer.start(); } bool VisibilityManager::isHovered() const { return m_isHovered; } void VisibilityManager::setIsHovered(bool state) { if (m_isHovered == state) { return; } m_isHovered = state; emit isHoveredChanged(); } void VisibilityManager::setMaskArea(QRect area) { m_interface->setMaskArea(area); } /*******************************/ void VisibilityManager::initialize() { m_secondInitPass = true; m_initTimer.start(); } void VisibilityManager::initWindow() { updateVisibilityFlags(); // updateWindowPosition(); // The initialization phase makes two passes because // changing the window style and type wants a small delay // and afterwards the second pass positions them correctly if (m_secondInitPass) { m_initTimer.start(); m_secondInitPass = false; } } /*void VisibilityManager::updateWindowPosition() { //setPanelScreen(screen()); // qDebug() << "updateWindowPosition: start..."; if (!transientParent() || !transientParent()->screen()) { // qDebug() << "updateWindowPosition: break transient..."; return; } // qDebug() << "updateWindowPosition: transientParent setting screen position..."; setPanelScreen(transientParent()->screen()); if (!m_screen || m_screenGeometry.isNull()) { // qDebug() << "updateWindowPosition: break m_screen..."; return; } // qDebug() << "updateWindowPosition: check passed..."; // qDebug() << m_screen->geometry().x() << " - " << m_screen->geometry().y() << " - " << m_screen->geometry().width() << " - " << m_screen->geometry().height(); if (m_location == Plasma::Types::BottomEdge) { setX(m_screenGeometry.x()); setY(m_screenGeometry.y()+m_screenGeometry.height() - height()); } else if (m_location == Plasma::Types::TopEdge) { setX(m_screenGeometry.x()); setY(m_screenGeometry.y()); } else if (m_location == Plasma::Types::LeftEdge) { setX(m_screenGeometry.x()); setY(m_screenGeometry.y()); } else if (m_location == Plasma::Types::RightEdge) { setX(m_screenGeometry.x()+m_screenGeometry.width() - width()); setY(m_screenGeometry.y()); } ///FIXME: in come cases the below can not catch up and this may be the reason //that on start up in some cases dock's contents are not shown, //needs a timer maybe? /*if (m_screen != screen()) { setScreen(m_screen); }*/ //} void VisibilityManager::updateVisibilityFlags() { m_interface->setDockToAllDesktops(); /* if ((m_panelVisibility == AutoHide)||(m_isDockWindowType)) { m_updateStateTimer.setInterval(2500); } else { m_updateStateTimer.setInterval(1500); }*/ m_interface->setDockDefaultFlags(m_isDockWindowType); // updateWindowPosition(); if (!m_isDockWindowType) { showOnTop(); } m_updateStateTimer.start(); } /* * It is used from the m_updateStateTimer in order to check the dock's * visibility and trigger events and actions which are needed to * respond accordingly */ void VisibilityManager::updateState() { // qDebug() << "in update state disableHiding:" <desktopIsActive() && m_interface->dockIntersectsActiveWindow()) { if (m_interface->dockIsOnTop() || (m_isDockWindowType && !m_isAutoHidden)) { // qDebug() << m_isHovered << " - " << m_windowIsInAttention << " - "<< m_disableHiding; if (!m_isHovered && !m_windowIsInAttention && !m_disableHiding) { // qDebug() << "must be lowered...."; emit mustBeLowered(); //showNormal(); } } else { if (m_windowIsInAttention) { if (!m_isDockWindowType || (m_isDockWindowType && m_isAutoHidden)) { emit mustBeRaised(); //showOnTop(); } } } } else { if (!m_interface->activeIsDialog()) { if ((!m_interface->desktopIsActive() && m_interface->dockIsCovered()) || (m_isDockWindowType && m_isAutoHidden)) { // qDebug() << "must be raised...."; emit mustBeRaised(); } else { showOnTop(); } } } break; case Latte::Dock::DodgeMaximized: if (!m_interface->desktopIsActive() && m_interface->activeIsMaximized() && m_interface->dockIntersectsActiveWindow()) { if (m_interface->dockIsOnTop() || (m_isDockWindowType && !m_isAutoHidden)) { if (!m_isHovered && !m_windowIsInAttention && !m_disableHiding) { emit mustBeLowered(); //showNormal(); } } else { if (m_windowIsInAttention) { if (!m_isDockWindowType || (m_isDockWindowType && m_isAutoHidden)) { emit mustBeRaised(); //showOnTop(); } } } } else { if ((!m_interface->desktopIsActive() && m_interface->dockIsCovered()) || (m_isDockWindowType && m_isAutoHidden)) { emit mustBeRaised(); } else { showOnTop(); } } break; /* case Latte::Dock::LetWindowsCover: //this is not supported in clean Dock Window Types such as in wayland case if (m_isDockWindowType) { return; } if (!m_isHovered && m_interface->dockIsOnTop()) { if (m_interface->dockIsCovering()) { if (!m_disableHiding) { emit mustBeLowered(); } } else { showOnBottom(); } } else if (m_windowIsInAttention) { if (!m_interface->dockIsOnTop()) { if (m_interface->dockIsCovered()) { emit mustBeRaised(); } else { showOnTop(); } } } break; case LatteDock::Types::WindowsGoBelow: //Do nothing, the dock is OnTop state in every case break;*/ case Latte::Dock::AutoHide: if (m_windowIsInAttention && m_isAutoHidden) { emit mustBeRaised(); } else if (!m_isHovered && !m_disableHiding) { emit mustBeLowered(); } break; case Latte::Dock::AlwaysVisible: //Do nothing, the dock in OnTop state in every case break; } } void VisibilityManager::showOnTop() { // qDebug() << "reached make top..."; m_interface->showDockOnTop(); } void VisibilityManager::showNormal() { // qDebug() << "reached make normal..."; m_interface->showDockAsNormal(); } void VisibilityManager::showOnBottom() { // qDebug() << "reached make bottom..."; m_interface->showDockOnBottom(); } /***************/ void VisibilityManager::activeWindowChanged() { // if ((m_panelVisibility == LatteDock::Types::WindowsGoBelow) if ((m_panelVisibility == Latte::Dock::AlwaysVisible) || (m_panelVisibility == Latte::Dock::AutoHide)) { return; } //this check is important because otherwise the signals are so often //that the timer is never triggered if (!m_updateStateTimer.isActive()) { m_updateStateTimer.start(); } } //It is used in order to trigger a beautiful slide in effect when //the dock is totally hidden underneath void VisibilityManager::showOnTopCheck() { if ((m_panelVisibility == Latte::Dock::DodgeActive) || (m_panelVisibility == Latte::Dock::DodgeMaximized)) { //|| (m_panelVisibility == Latte::Dock::LetWindowsCover)) { if (m_interface->dockIsCovered(true)) { m_updateStateTimer.stop(); setIsHovered(true); emit mustBeRaisedImmediately(); } else { showOnTop(); } } } bool VisibilityManager::event(QEvent *event) { if (!event) { return false; } if ((event->type() == QEvent::Enter) && !m_isHovered) { m_updateStateTimer.stop(); setIsHovered(true); if ((m_panelVisibility == Latte::Dock::AutoHide) || (m_isDockWindowType)) { if (m_isAutoHidden) { emit mustBeRaised(); } } else { showOnTop(); } } else if (event->type() == QEvent::Leave) { setIsHovered(false); // if ((m_panelVisibility != LatteDock::Types::WindowsGoBelow) && if (m_panelVisibility != Latte::Dock::AlwaysVisible) { m_updateStateTimer.start(); } } return true; }