File indexing completed on 2024-04-28 05:31:06

0001 /*
0002     SPDX-FileCopyrightText: 2018 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "screenedgeghostwindow.h"
0007 
0008 // local
0009 #include "../view.h"
0010 #include "../positioner.h"
0011 
0012 // Qt
0013 #include <QDebug>
0014 #include <QSurfaceFormat>
0015 #include <QQuickView>
0016 #include <QTimer>
0017 
0018 // KDE
0019 #include <KWayland/Client/plasmashell.h>
0020 #include <KWayland/Client/surface.h>
0021 #include <KWindowSystem>
0022 
0023 // X11
0024 #include <NETWM>
0025 
0026 namespace Latte {
0027 namespace ViewPart {
0028 
0029 ScreenEdgeGhostWindow::ScreenEdgeGhostWindow(Latte::View *view) :
0030     SubWindow(view, QString("Screen Ghost Window"))
0031 {
0032     if (m_debugMode) {
0033         m_showColor = QColor("purple");
0034         m_hideColor = QColor("blue");
0035     } else {
0036         m_showColor = QColor(Qt::transparent);
0037         m_hideColor = QColor(Qt::transparent);
0038 
0039         m_showColor.setAlpha(0);
0040         m_hideColor.setAlpha(1);
0041     }
0042 
0043     setColor(m_showColor);
0044 
0045     connect(m_latteView->positioner(), &Latte::ViewPart::Positioner::slideOffsetChanged, this, &ScreenEdgeGhostWindow::updateGeometry);
0046 
0047     //! this timer is used in order to avoid fast enter/exit signals during first
0048     //! appearing after edge activation
0049     m_delayedMouseTimer.setSingleShot(true);
0050     m_delayedMouseTimer.setInterval(50);
0051     connect(&m_delayedMouseTimer, &QTimer::timeout, this, [this]() {
0052         if (m_delayedContainsMouse) {
0053             setContainsMouse(true);
0054         } else {
0055             setContainsMouse(false);
0056         }
0057     });
0058 
0059     updateGeometry();
0060     hideWithMask();
0061 }
0062 
0063 ScreenEdgeGhostWindow::~ScreenEdgeGhostWindow()
0064 {
0065 }
0066 
0067 QString ScreenEdgeGhostWindow::validTitlePrefix() const
0068 {
0069     return QString("#subghostedge#");
0070 }
0071 
0072 void ScreenEdgeGhostWindow::updateGeometry()
0073 {
0074     if (m_latteView->positioner()->slideOffset() != 0) {
0075         return;
0076     }
0077 
0078     QRect newGeometry = m_latteView->absoluteGeometry();
0079 
0080     if (KWindowSystem::compositingActive()) {
0081         m_thickness = 6;
0082     } else {
0083         m_thickness = 2;
0084     }
0085 
0086     int length{30};
0087     int lengthDifference{0};
0088 
0089     if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
0090         //! set minimum length to be 25% of screen width
0091         length = qMax(m_latteView->screenGeometry().width()/4,qMin(m_latteView->absoluteGeometry().width(), m_latteView->screenGeometry().width() - 1));
0092         lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().width()) / 2;
0093     } else {
0094         //! set minimum length to be 25% of screen height
0095         length = qMax(m_latteView->screenGeometry().height()/4,qMin(m_latteView->absoluteGeometry().height(), m_latteView->screenGeometry().height() - 1));
0096         lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().height()) / 2;
0097     }
0098 
0099     if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
0100         int leftF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left() - lengthDifference);
0101         int rightF = qMax(m_latteView->screenGeometry().left(), qMin(m_latteView->screenGeometry().right(), m_latteView->absoluteGeometry().right() + lengthDifference));
0102         newGeometry.setLeft(leftF);
0103         newGeometry.setRight(rightF);
0104     } else {
0105         int topF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top() - lengthDifference);
0106         int bottomF = qMax(m_latteView->screenGeometry().top(), qMin(m_latteView->screenGeometry().bottom(), m_latteView->absoluteGeometry().bottom() + lengthDifference));
0107         newGeometry.setTop(topF);
0108         newGeometry.setBottom(bottomF);
0109     }
0110 
0111     if (m_latteView->location() == Plasma::Types::BottomEdge) {
0112         newGeometry.moveTop(m_latteView->screenGeometry().bottom() - m_thickness);
0113     } else if (m_latteView->location() == Plasma::Types::TopEdge) {
0114         newGeometry.moveTop(m_latteView->screenGeometry().top());
0115     } else if (m_latteView->location() == Plasma::Types::LeftEdge) {
0116         newGeometry.moveLeft(m_latteView->screenGeometry().left());
0117     } else if (m_latteView->location() == Plasma::Types::RightEdge) {        
0118         newGeometry.moveLeft(m_latteView->screenGeometry().right() - m_thickness);
0119     }
0120 
0121     if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
0122         newGeometry.setHeight(m_thickness + 1);
0123     } else {
0124         newGeometry.setWidth(m_thickness + 1);
0125     }
0126 
0127     m_calculatedGeometry = newGeometry;
0128     emit calculatedGeometryChanged();
0129 }
0130 
0131 bool ScreenEdgeGhostWindow::containsMouse() const
0132 {
0133     return m_containsMouse;
0134 }
0135 
0136 void ScreenEdgeGhostWindow::setContainsMouse(bool contains)
0137 {
0138     if (m_containsMouse == contains) {
0139         return;
0140     }
0141 
0142     m_containsMouse = contains;
0143     emit containsMouseChanged(contains);
0144 }
0145 
0146 bool ScreenEdgeGhostWindow::event(QEvent *e)
0147 {
0148     if (e->type() == QEvent::DragEnter || e->type() == QEvent::DragMove) {
0149         if (!m_containsMouse) {
0150             m_delayedContainsMouse = false;
0151             m_delayedMouseTimer.stop();
0152             setContainsMouse(true);
0153             emit dragEntered();
0154         }
0155     } else if (e->type() == QEvent::Enter) {
0156         m_delayedContainsMouse = true;
0157         if (!m_delayedMouseTimer.isActive()) {
0158             m_delayedMouseTimer.start();
0159         }
0160     } else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave) {
0161         m_delayedContainsMouse = false;
0162         if (!m_delayedMouseTimer.isActive()) {
0163             m_delayedMouseTimer.start();
0164         }
0165     }
0166 
0167     return SubWindow::event(e);
0168 }
0169 
0170 }
0171 }