File indexing completed on 2025-03-16 11:22:51
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 }