1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-11 13:18:13 +03:00
latte-dock/corona/visibilitymanager.cpp
2016-12-25 21:28:00 +02:00

451 lines
13 KiB
C++

#include "visibilitymanager.h"
#include "abstractinterface.h"
#include "xwindowinterface.h"
#include "plasmaquick/containmentview.h"
#include "../liblattedock/dock.h"
#include <QDebug>
#include <Plasma/Containment>
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:" <<m_disableHiding;
//update the dock behavior
switch (m_panelVisibility) {
case Latte::Dock::DodgeActive:
if (!m_interface->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;
}