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

0001 /*
0002     SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "floatinggapwindow.h"
0007 
0008 // local
0009 #include "../view.h"
0010 
0011 // Qt
0012 #include <QDebug>
0013 #include <QSurfaceFormat>
0014 #include <QQuickView>
0015 #include <QTimer>
0016 
0017 // KDE
0018 #include <KWayland/Client/plasmashell.h>
0019 #include <KWayland/Client/surface.h>
0020 #include <KWindowSystem>
0021 
0022 // X11
0023 #include <NETWM>
0024 
0025 namespace Latte {
0026 namespace ViewPart {
0027 
0028 FloatingGapWindow::FloatingGapWindow(Latte::View *view) :
0029     SubWindow(view, QString("Floating Gap Window"))
0030 {
0031     if (m_debugMode) {
0032         m_showColor = QColor("green");
0033         m_hideColor = QColor("red");
0034     } else {
0035         m_showColor = QColor(Qt::transparent);
0036         m_hideColor = QColor(Qt::transparent);
0037 
0038         m_showColor.setAlpha(0);
0039         m_hideColor.setAlpha(1);
0040     }
0041 
0042     setColor(m_showColor);
0043 
0044     //! this timer is used in order to identify if mouse is still present in sensitive floating
0045     //! areas and in such case to prevent a real-floating view to hide itself
0046     m_asyncMouseTimer.setSingleShot(true);
0047     m_asyncMouseTimer.setInterval(200);
0048     connect(&m_asyncMouseTimer, &QTimer::timeout, this, [this]() {
0049         if (m_inAsyncContainsMouse && !m_containsMouse) {
0050             emit asyncContainsMouseChanged(false);
0051             hideWithMask();
0052             m_inAsyncContainsMouse = false;
0053         }
0054     });
0055 
0056 
0057     updateGeometry();
0058     hideWithMask();
0059 }
0060 
0061 FloatingGapWindow::~FloatingGapWindow()
0062 {
0063 }
0064 
0065 QString FloatingGapWindow::validTitlePrefix() const
0066 {
0067     return QString("#subfloatgap#");
0068 }
0069 
0070 void FloatingGapWindow::updateGeometry()
0071 {
0072     if (m_latteView->positioner()->slideOffset() != 0) {
0073         return;
0074     }
0075 
0076     QRect newGeometry;
0077 
0078     m_thickness = m_latteView->screenEdgeMargin();
0079 
0080     int length = m_latteView->formFactor() == Plasma::Types::Horizontal ? m_latteView->absoluteGeometry().width() : m_latteView->absoluteGeometry().height();
0081 
0082     if (m_latteView->location() == Plasma::Types::BottomEdge) {
0083         int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left());
0084         newGeometry.moveLeft(xF);
0085         newGeometry.moveTop(m_latteView->screenGeometry().bottom() - m_thickness);
0086     } else if (m_latteView->location() == Plasma::Types::TopEdge) {
0087         int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left());
0088         newGeometry.moveLeft(xF);
0089         newGeometry.moveTop(m_latteView->screenGeometry().top());
0090     } else if (m_latteView->location() == Plasma::Types::LeftEdge) {
0091         int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top());
0092         newGeometry.moveLeft(m_latteView->screenGeometry().left());
0093         newGeometry.moveTop(yF);
0094     } else if (m_latteView->location() == Plasma::Types::RightEdge) {
0095         int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top());
0096         newGeometry.moveLeft(m_latteView->screenGeometry().right() - m_thickness);
0097         newGeometry.moveTop(yF);
0098     }
0099 
0100     if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
0101         newGeometry.setWidth(length);
0102         newGeometry.setHeight(m_thickness + 1);
0103     } else {
0104         newGeometry.setWidth(m_thickness + 1);
0105         newGeometry.setHeight(length);
0106     }
0107 
0108     m_calculatedGeometry = newGeometry;
0109 
0110     emit calculatedGeometryChanged();
0111 }
0112 
0113 bool FloatingGapWindow::event(QEvent *e)
0114 {
0115     if (e->type() == QEvent::DragEnter || e->type() == QEvent::DragMove) {
0116         m_containsMouse = true;
0117 
0118     } else if (e->type() == QEvent::Enter) {
0119         m_containsMouse = true;
0120 
0121         triggerAsyncContainsMouseSignals();
0122     } else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave) {
0123         m_containsMouse = false;
0124 
0125         if (m_inAsyncContainsMouse) {
0126             m_asyncMouseTimer.stop();
0127             m_inAsyncContainsMouse = false;
0128             emit asyncContainsMouseChanged(true);
0129         }
0130     }
0131 
0132     return SubWindow::event(e);
0133 }
0134 
0135 void FloatingGapWindow::callAsyncContainsMouse()
0136 {
0137     m_inAsyncContainsMouse = true;
0138     m_asyncMouseTimer.start();
0139     showWithMask();
0140 }
0141 
0142 void FloatingGapWindow::triggerAsyncContainsMouseSignals()
0143 {
0144     if (!m_inAsyncContainsMouse) {
0145         return;
0146     }
0147 
0148     //! this function is called QEvent::Enter
0149     m_asyncMouseTimer.stop();
0150     hideWithMask();
0151 }
0152 
0153 }
0154 }