File indexing completed on 2024-04-14 05:24:49

0001 /*
0002     SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmailbox.org>
0003     SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "infoview.h"
0009 
0010 // local
0011 #include <config-latte.h>
0012 #include "wm/abstractwindowinterface.h"
0013 #include "view/panelshadows_p.h"
0014 
0015 // Qt
0016 #include <QQuickItem>
0017 #include <QQmlContext>
0018 #include <QQmlEngine>
0019 #include <QScreen>
0020 
0021 // KDE
0022 #include <KLocalizedContext>
0023 #include <KDeclarative/KDeclarative>
0024 #include <KWindowSystem>
0025 #include <KWayland/Client/plasmashell.h>
0026 #include <KWayland/Client/surface.h>
0027 
0028 // Plasma
0029 #include <Plasma/Package>
0030 
0031 namespace Latte {
0032 
0033 InfoView::InfoView(Latte::Corona *corona, QString message, QScreen *screen, QWindow *parent)
0034     : QQuickView(parent),
0035       m_corona(corona),
0036       m_message(message),
0037       m_screen(screen)
0038 {
0039     m_id = QString::number(qrand() % 1000);
0040 
0041     setTitle(validTitle());
0042 
0043     setupWaylandIntegration();
0044 
0045     setResizeMode(QQuickView::SizeViewToRootObject);
0046     setColor(QColor(Qt::transparent));
0047     setDefaultAlphaBuffer(true);
0048 
0049     setIcon(qGuiApp->windowIcon());
0050 
0051     setScreen(screen);
0052     setFlags(wFlags());
0053 
0054     if (KWindowSystem::isPlatformX11()) {
0055         m_trackedWindowId = winId();
0056         m_corona->wm()->registerIgnoredWindow(m_trackedWindowId);
0057     } else {
0058         connect(m_corona->wm(), &WindowSystem::AbstractWindowInterface::latteWindowAdded, this, &InfoView::updateWaylandId);
0059     }
0060 
0061     init();
0062 }
0063 
0064 InfoView::~InfoView()
0065 {
0066     PanelShadows::self()->removeWindow(this);
0067 
0068     qDebug() << "InfoView deleting ...";
0069 
0070     if (m_shellSurface) {
0071         delete m_shellSurface;
0072         m_shellSurface = nullptr;
0073     }
0074 }
0075 
0076 void InfoView::init()
0077 {
0078     rootContext()->setContextProperty(QStringLiteral("infoWindow"), this);
0079 
0080     KDeclarative::KDeclarative kdeclarative;
0081     kdeclarative.setDeclarativeEngine(engine());
0082     kdeclarative.setTranslationDomain(QStringLiteral("latte-dock"));
0083     kdeclarative.setupContext();
0084     kdeclarative.setupEngine(engine());
0085 
0086     auto source = QUrl::fromLocalFile(m_corona->kPackage().filePath("infoviewui"));
0087     setSource(source);
0088 
0089     rootObject()->setProperty("message", m_message);
0090 
0091     syncGeometry();
0092 }
0093 
0094 QString InfoView::validTitle() const
0095 {
0096     return "#layoutinfowindow#" + m_id;
0097 }
0098 
0099 Plasma::FrameSvg::EnabledBorders InfoView::enabledBorders() const
0100 {
0101     return m_borders;
0102 }
0103 
0104 
0105 inline Qt::WindowFlags InfoView::wFlags() const
0106 {
0107     return (flags() | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) & ~Qt::WindowDoesNotAcceptFocus;
0108 }
0109 
0110 void InfoView::syncGeometry()
0111 {
0112     const QSize size(rootObject()->width(), rootObject()->height());
0113     const auto sGeometry = screen()->geometry();
0114 
0115     setMaximumSize(size);
0116     setMinimumSize(size);
0117     resize(size);
0118 
0119     QPoint position{sGeometry.center().x() - size.width() / 2, sGeometry.center().y() - size.height() / 2 };
0120 
0121     setPosition(position);
0122 
0123     if (m_shellSurface) {
0124         m_shellSurface->setPosition(position);
0125     }
0126 }
0127 
0128 void InfoView::showEvent(QShowEvent *ev)
0129 {
0130     QQuickWindow::showEvent(ev);
0131 
0132     m_corona->wm()->setViewExtraFlags(this);
0133     setFlags(wFlags());
0134 
0135     m_corona->wm()->enableBlurBehind(*this);
0136 
0137     syncGeometry();
0138 
0139     QTimer::singleShot(400, this, &InfoView::syncGeometry);
0140 
0141     PanelShadows::self()->addWindow(this);
0142     PanelShadows::self()->setEnabledBorders(this, m_borders);
0143 }
0144 
0145 void InfoView::updateWaylandId()
0146 {
0147     Latte::WindowSystem::WindowId newId = m_corona->wm()->winIdFor("latte-dock", validTitle());
0148 
0149     if (m_trackedWindowId != newId) {
0150         if (!m_trackedWindowId.isNull()) {
0151             m_corona->wm()->unregisterIgnoredWindow(m_trackedWindowId);
0152         }
0153 
0154         m_trackedWindowId = newId;
0155         m_corona->wm()->registerIgnoredWindow(m_trackedWindowId);
0156     }
0157 }
0158 
0159 void InfoView::setupWaylandIntegration()
0160 {
0161     if (m_shellSurface) {
0162         // already setup
0163         return;
0164     }
0165 
0166     if (m_corona) {
0167         using namespace KWayland::Client;
0168         PlasmaShell *interface = m_corona->waylandCoronaInterface();
0169 
0170         if (!interface) {
0171             return;
0172         }
0173 
0174         Surface *s = Surface::fromWindow(this);
0175 
0176         if (!s) {
0177             return;
0178         }
0179 
0180         qDebug() << "wayland dock window surface was created...";
0181 
0182         m_shellSurface = interface->createSurface(s, this);
0183         m_corona->wm()->setViewExtraFlags(m_shellSurface);
0184     }
0185 }
0186 
0187 bool InfoView::event(QEvent *e)
0188 {
0189     if (e->type() == QEvent::PlatformSurface) {
0190         if (auto pe = dynamic_cast<QPlatformSurfaceEvent *>(e)) {
0191             switch (pe->surfaceEventType()) {
0192                 case QPlatformSurfaceEvent::SurfaceCreated:
0193 
0194                     if (m_shellSurface) {
0195                         break;
0196                     }
0197 
0198                     setupWaylandIntegration();
0199                     break;
0200 
0201                 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
0202                     if (m_shellSurface) {
0203                         delete m_shellSurface;
0204                         m_shellSurface = nullptr;
0205                     }
0206 
0207                     PanelShadows::self()->removeWindow(this);
0208                     break;
0209             }
0210         }
0211     }
0212 
0213     return QQuickWindow::event(e);
0214 }
0215 
0216 void InfoView::setOnActivities(QStringList activities)
0217 {
0218     KWindowSystem::setOnActivities(winId(), activities);
0219 }
0220 
0221 }
0222 // kate: indent-mode cstyle; indent-width 4; replace-tabs on;