File indexing completed on 2025-04-20 10:59:46
0001 /* 0002 SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "subconfigview.h" 0007 0008 //local 0009 #include <config-latte.h> 0010 #include "../view.h" 0011 #include "../../lattecorona.h" 0012 #include "../../layouts/manager.h" 0013 #include "../../plasma/extended/theme.h" 0014 #include "../../settings/universalsettings.h" 0015 #include "../../shortcuts/globalshortcuts.h" 0016 #include "../../shortcuts/shortcutstracker.h" 0017 #include "../../wm/abstractwindowinterface.h" 0018 0019 // KDE 0020 #include <KLocalizedContext> 0021 #include <KDeclarative/KDeclarative> 0022 #include <KWayland/Client/plasmashell.h> 0023 #include <KWayland/Client/surface.h> 0024 #include <KWindowSystem> 0025 0026 namespace Latte { 0027 namespace ViewPart { 0028 0029 SubConfigView::SubConfigView(Latte::View *view, const QString &title, const bool &isNormalWindow) 0030 : QQuickView(nullptr), 0031 m_isNormalWindow(isNormalWindow) 0032 { 0033 m_corona = qobject_cast<Latte::Corona *>(view->containment()->corona()); 0034 0035 setupWaylandIntegration(); 0036 0037 if (KWindowSystem::isPlatformX11()) { 0038 m_corona->wm()->registerIgnoredWindow(winId()); 0039 } else { 0040 connect(this, &QWindow::windowTitleChanged, this, &SubConfigView::updateWaylandId); 0041 connect(m_corona->wm(), &WindowSystem::AbstractWindowInterface::latteWindowAdded, this, &SubConfigView::updateWaylandId); 0042 } 0043 0044 m_validTitle = title; 0045 setTitle(m_validTitle); 0046 0047 setScreen(view->screen()); 0048 setIcon(qGuiApp->windowIcon()); 0049 0050 if (!m_isNormalWindow) { 0051 setFlags(wFlags()); 0052 m_corona->wm()->setViewExtraFlags(this, true); 0053 } 0054 0055 m_screenSyncTimer.setSingleShot(true); 0056 m_screenSyncTimer.setInterval(100); 0057 0058 connections << connect(&m_screenSyncTimer, &QTimer::timeout, this, [this]() { 0059 if (!m_latteView) { 0060 return; 0061 } 0062 0063 setScreen(m_latteView->screen()); 0064 0065 if (KWindowSystem::isPlatformX11()) { 0066 if (m_isNormalWindow) { 0067 setFlags(wFlags()); 0068 m_corona->wm()->setViewExtraFlags(this, false, Latte::Types::NormalWindow); 0069 } 0070 } 0071 0072 syncGeometry(); 0073 }); 0074 0075 m_showTimer.setSingleShot(true); 0076 m_showTimer.setInterval(0); 0077 0078 connections << connect(&m_showTimer, &QTimer::timeout, this, [this]() { 0079 syncSlideEffect(); 0080 show(); 0081 }); 0082 } 0083 0084 SubConfigView::~SubConfigView() 0085 { 0086 qDebug() << validTitle() << " deleting..."; 0087 0088 m_corona->dialogShadows()->removeWindow(this); 0089 0090 m_corona->wm()->unregisterIgnoredWindow(KWindowSystem::isPlatformX11() ? winId() : m_waylandWindowId); 0091 0092 for (const auto &var : connections) { 0093 QObject::disconnect(var); 0094 } 0095 0096 for (const auto &var : viewconnections) { 0097 QObject::disconnect(var); 0098 } 0099 } 0100 0101 void SubConfigView::init() 0102 { 0103 qDebug() << validTitle() << " : initialization started..."; 0104 0105 setDefaultAlphaBuffer(true); 0106 setColor(Qt::transparent); 0107 0108 rootContext()->setContextProperty(QStringLiteral("viewConfig"), this); 0109 rootContext()->setContextProperty(QStringLiteral("shortcutsEngine"), m_corona->globalShortcuts()->shortcutsTracker()); 0110 0111 if (m_corona) { 0112 rootContext()->setContextProperty(QStringLiteral("universalSettings"), m_corona->universalSettings()); 0113 rootContext()->setContextProperty(QStringLiteral("layoutsManager"), m_corona->layoutsManager()); 0114 rootContext()->setContextProperty(QStringLiteral("themeExtended"), m_corona->themeExtended()); 0115 } 0116 0117 KDeclarative::KDeclarative kdeclarative; 0118 kdeclarative.setDeclarativeEngine(engine()); 0119 kdeclarative.setTranslationDomain(QStringLiteral("latte-dock")); 0120 kdeclarative.setupContext(); 0121 kdeclarative.setupEngine(engine()); 0122 0123 } 0124 0125 Qt::WindowFlags SubConfigView::wFlags() const 0126 { 0127 return (flags() | Qt::FramelessWindowHint) & ~Qt::WindowDoesNotAcceptFocus; 0128 } 0129 0130 QString SubConfigView::validTitle() const 0131 { 0132 return m_validTitle; 0133 } 0134 0135 Latte::WindowSystem::WindowId SubConfigView::trackedWindowId() 0136 { 0137 if (KWindowSystem::isPlatformWayland() && m_waylandWindowId.toInt() <= 0) { 0138 updateWaylandId(); 0139 } 0140 0141 return !KWindowSystem::isPlatformWayland() ? winId() : m_waylandWindowId; 0142 } 0143 0144 Latte::Corona *SubConfigView::corona() const 0145 { 0146 return m_corona; 0147 } 0148 0149 Latte::View *SubConfigView::parentView() const 0150 { 0151 return m_latteView; 0152 } 0153 0154 void SubConfigView::setParentView(Latte::View *view, const bool &immediate) 0155 { 0156 if (m_latteView == view) { 0157 return; 0158 } 0159 0160 initParentView(view); 0161 } 0162 0163 void SubConfigView::initParentView(Latte::View *view) 0164 { 0165 for (const auto &var : viewconnections) { 0166 QObject::disconnect(var); 0167 } 0168 0169 m_latteView = view; 0170 0171 viewconnections << connect(m_latteView->positioner(), &ViewPart::Positioner::canvasGeometryChanged, this, &SubConfigView::syncGeometry); 0172 0173 //! Assign app interfaces in be accessible through containment graphic item 0174 QQuickItem *containmentGraphicItem = qobject_cast<QQuickItem *>(m_latteView->containment()->property("_plasma_graphicObject").value<QObject *>()); 0175 rootContext()->setContextProperty(QStringLiteral("plasmoid"), containmentGraphicItem); 0176 rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView); 0177 } 0178 0179 void SubConfigView::requestActivate() 0180 { 0181 if (KWindowSystem::isPlatformWayland() && m_shellSurface) { 0182 updateWaylandId(); 0183 m_corona->wm()->requestActivate(m_waylandWindowId); 0184 } else { 0185 QQuickView::requestActivate(); 0186 } 0187 } 0188 0189 void SubConfigView::showAfter(int msecs) 0190 { 0191 if (isVisible()) { 0192 return; 0193 } 0194 0195 m_showTimer.setInterval(msecs); 0196 m_showTimer.start(); 0197 0198 } 0199 0200 void SubConfigView::syncSlideEffect() 0201 { 0202 if (!m_latteView || !m_latteView->containment()) { 0203 return; 0204 } 0205 0206 auto slideLocation = WindowSystem::AbstractWindowInterface::Slide::None; 0207 0208 switch (m_latteView->containment()->location()) { 0209 case Plasma::Types::TopEdge: 0210 slideLocation = WindowSystem::AbstractWindowInterface::Slide::Top; 0211 break; 0212 0213 case Plasma::Types::RightEdge: 0214 slideLocation = WindowSystem::AbstractWindowInterface::Slide::Right; 0215 break; 0216 0217 case Plasma::Types::BottomEdge: 0218 slideLocation = WindowSystem::AbstractWindowInterface::Slide::Bottom; 0219 break; 0220 0221 case Plasma::Types::LeftEdge: 0222 slideLocation = WindowSystem::AbstractWindowInterface::Slide::Left; 0223 break; 0224 0225 default: 0226 qDebug() << staticMetaObject.className() << "wrong location"; 0227 break; 0228 } 0229 0230 m_corona->wm()->slideWindow(*this, slideLocation); 0231 } 0232 0233 KWayland::Client::PlasmaShellSurface *SubConfigView::surface() 0234 { 0235 return m_shellSurface; 0236 } 0237 0238 void SubConfigView::setupWaylandIntegration() 0239 { 0240 if (m_shellSurface || !KWindowSystem::isPlatformWayland() || !m_latteView || !m_latteView->containment()) { 0241 // already setup 0242 return; 0243 } 0244 0245 if (m_corona) { 0246 using namespace KWayland::Client; 0247 PlasmaShell *interface = m_corona->waylandCoronaInterface(); 0248 0249 if (!interface) { 0250 return; 0251 } 0252 0253 Surface *s = Surface::fromWindow(this); 0254 0255 if (!s) { 0256 return; 0257 } 0258 0259 qDebug() << "wayland " << title() << " surface was created..."; 0260 0261 m_shellSurface = interface->createSurface(s, this); 0262 0263 if (m_isNormalWindow) { 0264 m_corona->wm()->setViewExtraFlags(m_shellSurface, false); 0265 } else { 0266 m_corona->wm()->setViewExtraFlags(m_shellSurface, true); 0267 } 0268 0269 updateWaylandId(); 0270 syncGeometry(); 0271 } 0272 } 0273 0274 void SubConfigView::showEvent(QShowEvent *ev) 0275 { 0276 QQuickView::showEvent(ev); 0277 0278 if (m_shellSurface) { 0279 //! readd shadows after hiding because the window shadows are not shown again after first showing 0280 m_corona->dialogShadows()->addWindow(this, m_enabledBorders); 0281 } 0282 } 0283 0284 bool SubConfigView::event(QEvent *e) 0285 { 0286 if (e->type() == QEvent::PlatformSurface) { 0287 if (auto pe = dynamic_cast<QPlatformSurfaceEvent *>(e)) { 0288 switch (pe->surfaceEventType()) { 0289 case QPlatformSurfaceEvent::SurfaceCreated: 0290 0291 if (m_shellSurface) { 0292 break; 0293 } 0294 0295 setupWaylandIntegration(); 0296 break; 0297 0298 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: 0299 if (m_shellSurface) { 0300 delete m_shellSurface; 0301 m_shellSurface = nullptr; 0302 qDebug() << "WAYLAND " << title() << " window surface was deleted..."; 0303 } 0304 0305 break; 0306 } 0307 } 0308 } 0309 0310 return QQuickView::event(e); 0311 } 0312 0313 void SubConfigView::updateWaylandId() 0314 { 0315 Latte::WindowSystem::WindowId newId = m_corona->wm()->winIdFor("latte-dock", validTitle()); 0316 0317 if (m_waylandWindowId != newId) { 0318 if (!m_waylandWindowId.isNull()) { 0319 m_corona->wm()->unregisterIgnoredWindow(m_waylandWindowId); 0320 } 0321 0322 m_waylandWindowId = newId; 0323 m_corona->wm()->registerIgnoredWindow(m_waylandWindowId); 0324 } 0325 } 0326 0327 Plasma::FrameSvg::EnabledBorders SubConfigView::enabledBorders() const 0328 { 0329 return m_enabledBorders; 0330 } 0331 0332 } 0333 }