File indexing completed on 2024-12-22 05:15:19
0001 /* 0002 SPDX-FileCopyrightText: 2015 Eike Hein <hein@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "dashboardwindow.h" 0008 0009 #include <QCoreApplication> 0010 #include <QIcon> 0011 #include <QScreen> 0012 0013 #include <KWayland/Client/connection_thread.h> 0014 #include <KWayland/Client/plasmashell.h> 0015 #include <KWayland/Client/registry.h> 0016 #include <KWayland/Client/surface.h> 0017 #include <KWindowEffects> 0018 #include <KWindowSystem> 0019 #include <KX11Extras> 0020 0021 DashboardWindow::DashboardWindow(QQuickItem *parent) 0022 : QQuickWindow(parent ? parent->window() : nullptr) 0023 , m_mainItem(nullptr) 0024 , m_visualParentItem(nullptr) 0025 , m_visualParentWindow(nullptr) 0026 { 0027 setFlags(Qt::FramelessWindowHint); 0028 0029 setIcon(QIcon::fromTheme(QStringLiteral("plasma"))); 0030 0031 connect(&m_theme, &Plasma::Theme::themeChanged, this, &DashboardWindow::updateTheme); 0032 0033 if (KWindowSystem::isPlatformWayland()) { 0034 KWayland::Client::ConnectionThread *connection = KWayland::Client::ConnectionThread::fromApplication(this); 0035 Q_ASSERT(connection); 0036 0037 KWayland::Client::Registry *registry = new KWayland::Client::Registry(this); 0038 registry->create(connection); 0039 0040 connect(registry, &KWayland::Client::Registry::plasmaShellAnnounced, this, [this, registry](quint32 name, quint32 version) { 0041 m_plasmashell = registry->createPlasmaShell(name, version, this); 0042 }); 0043 0044 registry->setup(); 0045 connection->roundtrip(); 0046 } 0047 } 0048 0049 DashboardWindow::~DashboardWindow() 0050 { 0051 } 0052 0053 QQuickItem *DashboardWindow::mainItem() const 0054 { 0055 return m_mainItem; 0056 } 0057 0058 void DashboardWindow::setMainItem(QQuickItem *item) 0059 { 0060 if (m_mainItem != item) { 0061 if (m_mainItem) { 0062 m_mainItem->setVisible(false); 0063 } 0064 0065 m_mainItem = item; 0066 0067 if (m_mainItem) { 0068 m_mainItem->setVisible(isVisible()); 0069 m_mainItem->setParentItem(contentItem()); 0070 } 0071 0072 Q_EMIT mainItemChanged(); 0073 } 0074 } 0075 0076 QQuickItem *DashboardWindow::visualParent() const 0077 { 0078 return m_visualParentItem; 0079 } 0080 0081 void DashboardWindow::setVisualParent(QQuickItem *item) 0082 { 0083 if (m_visualParentItem != item) { 0084 if (m_visualParentItem) { 0085 disconnect(m_visualParentItem.data(), &QQuickItem::windowChanged, this, &DashboardWindow::visualParentWindowChanged); 0086 } 0087 0088 m_visualParentItem = item; 0089 0090 if (m_visualParentItem) { 0091 if (m_visualParentItem->window()) { 0092 visualParentWindowChanged(m_visualParentItem->window()); 0093 } 0094 0095 connect(m_visualParentItem.data(), &QQuickItem::windowChanged, this, &DashboardWindow::visualParentWindowChanged); 0096 } 0097 0098 Q_EMIT visualParentChanged(); 0099 } 0100 } 0101 0102 QColor DashboardWindow::backgroundColor() const 0103 { 0104 return color(); 0105 } 0106 0107 void DashboardWindow::setBackgroundColor(const QColor &c) 0108 { 0109 if (color() != c) { 0110 setColor(c); 0111 0112 Q_EMIT backgroundColorChanged(); 0113 } 0114 } 0115 0116 QQuickItem *DashboardWindow::keyEventProxy() const 0117 { 0118 return m_keyEventProxy; 0119 } 0120 0121 void DashboardWindow::setKeyEventProxy(QQuickItem *item) 0122 { 0123 if (m_keyEventProxy != item) { 0124 m_keyEventProxy = item; 0125 0126 Q_EMIT keyEventProxyChanged(); 0127 } 0128 } 0129 0130 void DashboardWindow::toggle() 0131 { 0132 if (isVisible()) { 0133 close(); 0134 } else { 0135 resize(screen()->size()); 0136 showFullScreen(); 0137 KX11Extras::forceActiveWindow(winId()); 0138 } 0139 } 0140 0141 bool DashboardWindow::event(QEvent *event) 0142 { 0143 if (event->type() == QEvent::PlatformSurface) { 0144 const QPlatformSurfaceEvent *pSEvent = static_cast<QPlatformSurfaceEvent *>(event); 0145 0146 if (pSEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { 0147 if (KWindowSystem::isPlatformX11()) { 0148 KX11Extras::setState(winId(), NET::SkipTaskbar | NET::SkipPager | NET::SkipSwitcher); 0149 } else { 0150 if (m_plasmashell) { 0151 auto *surface = KWayland::Client::Surface::fromQtWinId(winId()); 0152 auto *plasmashellSurface = KWayland::Client::PlasmaShellSurface::get(surface); 0153 0154 if (!plasmashellSurface) { 0155 plasmashellSurface = m_plasmashell->createSurface(surface, this); 0156 } 0157 0158 plasmashellSurface->setSkipSwitcher(true); 0159 plasmashellSurface->setSkipTaskbar(true); 0160 } 0161 } 0162 } 0163 } else if (event->type() == QEvent::Show) { 0164 updateTheme(); 0165 0166 if (m_mainItem) { 0167 m_mainItem->setVisible(true); 0168 } 0169 } else if (event->type() == QEvent::Hide) { 0170 if (m_mainItem) { 0171 m_mainItem->setVisible(false); 0172 } 0173 } else if (event->type() == QEvent::FocusOut) { 0174 if (isVisible()) { 0175 KX11Extras::forceActiveWindow(winId()); 0176 } 0177 } 0178 0179 return QQuickWindow::event(event); 0180 } 0181 0182 void DashboardWindow::keyPressEvent(QKeyEvent *e) 0183 { 0184 if (e->key() == Qt::Key_Escape) { 0185 Q_EMIT keyEscapePressed(); 0186 0187 return; 0188 // clang-format off 0189 } else if (m_keyEventProxy && !m_keyEventProxy->hasActiveFocus() 0190 && !(e->key() == Qt::Key_Home) 0191 && !(e->key() == Qt::Key_End) 0192 && !(e->key() == Qt::Key_Left) 0193 && !(e->key() == Qt::Key_Up) 0194 && !(e->key() == Qt::Key_Right) 0195 && !(e->key() == Qt::Key_Down) 0196 && !(e->key() == Qt::Key_PageUp) 0197 && !(e->key() == Qt::Key_PageDown) 0198 && !(e->key() == Qt::Key_Enter) 0199 && !(e->key() == Qt::Key_Return) 0200 && !(e->key() == Qt::Key_Menu) 0201 && !(e->key() == Qt::Key_Tab) 0202 && !(e->key() == Qt::Key_Backtab)) { 0203 // clang-format on 0204 QPointer<QQuickItem> previousFocusItem = activeFocusItem(); 0205 0206 m_keyEventProxy->forceActiveFocus(); 0207 QEvent *eventCopy = new QKeyEvent(e->type(), 0208 e->key(), 0209 e->modifiers(), 0210 e->nativeScanCode(), 0211 e->nativeVirtualKey(), 0212 e->nativeModifiers(), 0213 e->text(), 0214 e->isAutoRepeat(), 0215 e->count()); 0216 QCoreApplication::postEvent(this, eventCopy); 0217 0218 // We _need_ to do it twice to make sure the event ping-pong needed 0219 // for delivery happens before we sap focus again. 0220 QCoreApplication::processEvents(); 0221 QCoreApplication::processEvents(); 0222 0223 if (previousFocusItem) { 0224 previousFocusItem->forceActiveFocus(); 0225 } 0226 0227 return; 0228 } 0229 0230 QQuickWindow::keyPressEvent(e); 0231 } 0232 0233 void DashboardWindow::updateTheme() 0234 { 0235 KWindowEffects::enableBlurBehind(this, true); 0236 } 0237 0238 void DashboardWindow::visualParentWindowChanged(QQuickWindow *window) 0239 { 0240 if (m_visualParentWindow) { 0241 disconnect(m_visualParentWindow.data(), &QQuickWindow::screenChanged, this, &DashboardWindow::visualParentScreenChanged); 0242 } 0243 0244 m_visualParentWindow = window; 0245 0246 if (m_visualParentWindow) { 0247 visualParentScreenChanged(m_visualParentWindow->screen()); 0248 0249 connect(m_visualParentWindow.data(), &QQuickWindow::screenChanged, this, &DashboardWindow::visualParentScreenChanged); 0250 } 0251 } 0252 0253 void DashboardWindow::visualParentScreenChanged(QScreen *screen) 0254 { 0255 if (screen) { 0256 setScreen(screen); 0257 setGeometry(screen->geometry()); 0258 } 0259 }