File indexing completed on 2024-09-08 10:54:00
0001 /* 0002 SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "widgetexplorerview.h" 0007 0008 // local 0009 #include "../panelshadows_p.h" 0010 #include "../view.h" 0011 #include "../../lattecorona.h" 0012 #include "../../wm/abstractwindowinterface.h" 0013 0014 // Qt 0015 #include <QQuickItem> 0016 #include <QScreen> 0017 0018 // KDE 0019 #include <KWindowEffects> 0020 #include <KWindowSystem> 0021 #include <KWayland/Client/plasmashell.h> 0022 0023 // Plasma 0024 #include <Plasma/Package> 0025 0026 namespace Latte { 0027 namespace ViewPart { 0028 0029 WidgetExplorerView::WidgetExplorerView(Latte::View *view) 0030 : SubConfigView(view, QString("#widgetexplorerview#"), true) 0031 { 0032 setResizeMode(QQuickView::SizeRootObjectToView); 0033 //!set flags early in order for wayland to initialize properly 0034 setFlags(wFlags()); 0035 0036 connect(this, &QQuickView::widthChanged, this, &WidgetExplorerView::updateEffects); 0037 connect(this, &QQuickView::heightChanged, this, &WidgetExplorerView::updateEffects); 0038 0039 connect(this, &QQuickView::statusChanged, [&](QQuickView::Status status) { 0040 if (status == QQuickView::Ready) { 0041 updateEffects(); 0042 } 0043 }); 0044 0045 setParentView(view); 0046 init(); 0047 } 0048 0049 void WidgetExplorerView::init() 0050 { 0051 SubConfigView::init(); 0052 0053 QByteArray tempFilePath = "widgetexplorerui"; 0054 0055 updateEnabledBorders(); 0056 0057 auto source = QUrl::fromLocalFile(m_latteView->containment()->corona()->kPackage().filePath(tempFilePath)); 0058 setSource(source); 0059 syncGeometry(); 0060 } 0061 0062 bool WidgetExplorerView::hideOnWindowDeactivate() const 0063 { 0064 return m_hideOnWindowDeactivate; 0065 } 0066 0067 void WidgetExplorerView::setHideOnWindowDeactivate(bool hide) 0068 { 0069 if (m_hideOnWindowDeactivate == hide) { 0070 return; 0071 } 0072 0073 m_hideOnWindowDeactivate = hide; 0074 emit hideOnWindowDeactivateChanged(); 0075 } 0076 0077 Qt::WindowFlags WidgetExplorerView::wFlags() const 0078 { 0079 return (flags() | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); 0080 } 0081 0082 QRect WidgetExplorerView::geometryWhenVisible() const 0083 { 0084 return m_geometryWhenVisible; 0085 } 0086 0087 void WidgetExplorerView::initParentView(Latte::View *view) 0088 { 0089 SubConfigView::initParentView(view); 0090 0091 rootContext()->setContextProperty(QStringLiteral("containmentFromView"), m_latteView->containment()); 0092 rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView); 0093 0094 updateEnabledBorders(); 0095 syncGeometry(); 0096 } 0097 0098 QRect WidgetExplorerView::availableScreenGeometry() const 0099 { 0100 int currentScrId = m_latteView->positioner()->currentScreenId(); 0101 0102 QList<Latte::Types::Visibility> ignoreModes{Latte::Types::SidebarOnDemand,Latte::Types::SidebarAutoHide}; 0103 0104 if (m_latteView->visibility() && m_latteView->visibility()->isSidebar()) { 0105 ignoreModes.removeAll(Latte::Types::SidebarOnDemand); 0106 ignoreModes.removeAll(Latte::Types::SidebarAutoHide); 0107 } 0108 0109 QString activityid = m_latteView->layout()->lastUsedActivity(); 0110 0111 return m_corona->availableScreenRectWithCriteria(currentScrId, activityid, ignoreModes, {}, false, true); 0112 } 0113 0114 void WidgetExplorerView::syncGeometry() 0115 { 0116 if (!m_latteView || !m_latteView->layout() || !m_latteView->containment() || !rootObject()) { 0117 return; 0118 } 0119 const QSize size(rootObject()->width(), rootObject()->height()); 0120 auto availGeometry = availableScreenGeometry(); 0121 0122 int margin = availGeometry.height() == m_latteView->screenGeometry().height() ? 100 : 0; 0123 auto geometry = QRect(availGeometry.x(), availGeometry.y(), size.width(), availGeometry.height()-margin); 0124 0125 updateEnabledBorders(); 0126 0127 if (m_geometryWhenVisible == geometry) { 0128 return; 0129 } 0130 0131 m_geometryWhenVisible = geometry; 0132 0133 setPosition(geometry.topLeft()); 0134 0135 if (m_shellSurface) { 0136 m_shellSurface->setPosition(geometry.topLeft()); 0137 } 0138 0139 setMaximumSize(geometry.size()); 0140 setMinimumSize(geometry.size()); 0141 resize(geometry.size()); 0142 } 0143 0144 void WidgetExplorerView::showEvent(QShowEvent *ev) 0145 { 0146 if (m_shellSurface) { 0147 //! under wayland it needs to be set again after its hiding 0148 m_shellSurface->setPosition(m_geometryWhenVisible.topLeft()); 0149 } 0150 0151 SubConfigView::showEvent(ev); 0152 0153 if (!m_latteView) { 0154 return; 0155 } 0156 0157 syncGeometry(); 0158 0159 requestActivate(); 0160 0161 m_screenSyncTimer.start(); 0162 QTimer::singleShot(400, this, &WidgetExplorerView::syncGeometry); 0163 0164 emit showSignal(); 0165 } 0166 0167 void WidgetExplorerView::focusOutEvent(QFocusEvent *ev) 0168 { 0169 Q_UNUSED(ev); 0170 0171 if (!m_latteView) { 0172 return; 0173 } 0174 0175 hideConfigWindow(); 0176 } 0177 0178 void WidgetExplorerView::updateEffects() 0179 { 0180 //! Don't apply any effect before the wayland surface is created under wayland 0181 //! https://bugs.kde.org/show_bug.cgi?id=392890 0182 if (KWindowSystem::isPlatformWayland() && !m_shellSurface) { 0183 return; 0184 } 0185 0186 if (!m_background) { 0187 m_background = new Plasma::FrameSvg(this); 0188 } 0189 0190 if (m_background->imagePath() != "dialogs/background") { 0191 m_background->setImagePath(QStringLiteral("dialogs/background")); 0192 } 0193 0194 m_background->setEnabledBorders(m_enabledBorders); 0195 m_background->resizeFrame(size()); 0196 0197 QRegion mask = m_background->mask(); 0198 0199 QRegion fixedMask = mask.isNull() ? QRegion(QRect(0,0,width(),height())) : mask; 0200 0201 if (!fixedMask.isEmpty()) { 0202 setMask(fixedMask); 0203 } else { 0204 setMask(QRegion()); 0205 } 0206 0207 if (KWindowSystem::compositingActive()) { 0208 KWindowEffects::enableBlurBehind(winId(), true, fixedMask); 0209 } else { 0210 KWindowEffects::enableBlurBehind(winId(), false); 0211 } 0212 } 0213 0214 void WidgetExplorerView::hideConfigWindow() 0215 { 0216 if (!m_hideOnWindowDeactivate) { 0217 return; 0218 } 0219 0220 deleteLater(); 0221 0222 /*QTimer::singleShot(100, [this]() { 0223 //! avoid crashes under wayland because some mouse events are sended after the surface is destroyed 0224 0225 if (m_shellSurface) { 0226 //!NOTE: Avoid crash in wayland environment with qt5.9 0227 close(); 0228 } else { 0229 hide(); 0230 } 0231 });*/ 0232 } 0233 0234 void WidgetExplorerView::syncSlideEffect() 0235 { 0236 if (!m_latteView || !m_latteView->containment()) { 0237 return; 0238 } 0239 0240 auto slideLocation = WindowSystem::AbstractWindowInterface::Slide::Left; 0241 0242 m_corona->wm()->slideWindow(*this, slideLocation); 0243 } 0244 0245 //!BEGIN borders 0246 void WidgetExplorerView::updateEnabledBorders() 0247 { 0248 if (!this->screen()) { 0249 return; 0250 } 0251 0252 Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; 0253 0254 if (!m_geometryWhenVisible.isEmpty()) { 0255 if (m_geometryWhenVisible.x() == m_latteView->screenGeometry().x()) { 0256 borders &= ~Plasma::FrameSvg::LeftBorder; 0257 } 0258 0259 if (m_geometryWhenVisible.y() == m_latteView->screenGeometry().y()) { 0260 borders &= ~Plasma::FrameSvg::TopBorder; 0261 } 0262 0263 if (m_geometryWhenVisible.height() == m_latteView->screenGeometry().height()) { 0264 borders &= ~Plasma::FrameSvg::BottomBorder; 0265 } 0266 } 0267 0268 if (m_enabledBorders != borders) { 0269 if (isVisible()) { 0270 m_enabledBorders = borders; 0271 } 0272 m_corona->dialogShadows()->addWindow(this, m_enabledBorders); 0273 0274 emit enabledBordersChanged(); 0275 } 0276 } 0277 0278 //!END borders 0279 0280 } 0281 } 0282