File indexing completed on 2024-05-05 16:09:10
0001 /* 0002 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0003 SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de> 0004 */ 0005 0006 #include "waylandinhibition_p.h" 0007 0008 #include <QDebug> 0009 #include <QGuiApplication> 0010 #include <QSharedPointer> 0011 #include <QtWaylandClient/QWaylandClientExtensionTemplate> 0012 #include <QtWaylandClient/QtWaylandClientVersion> 0013 #include <qpa/qplatformnativeinterface.h> 0014 0015 #include "qwayland-keyboard-shortcuts-inhibit-unstable-v1.h" 0016 0017 class ShortcutsInhibitor : public QtWayland::zwp_keyboard_shortcuts_inhibitor_v1 0018 { 0019 public: 0020 ShortcutsInhibitor(::zwp_keyboard_shortcuts_inhibitor_v1 *id) 0021 : QtWayland::zwp_keyboard_shortcuts_inhibitor_v1(id) 0022 { 0023 } 0024 0025 ~ShortcutsInhibitor() override 0026 { 0027 destroy(); 0028 } 0029 0030 void zwp_keyboard_shortcuts_inhibitor_v1_active() override 0031 { 0032 m_active = true; 0033 } 0034 0035 void zwp_keyboard_shortcuts_inhibitor_v1_inactive() override 0036 { 0037 m_active = false; 0038 } 0039 0040 bool isActive() const 0041 { 0042 return m_active; 0043 } 0044 0045 private: 0046 bool m_active = false; 0047 }; 0048 0049 class ShortcutsInhibitManager : public QWaylandClientExtensionTemplate<ShortcutsInhibitManager>, public QtWayland::zwp_keyboard_shortcuts_inhibit_manager_v1 0050 { 0051 public: 0052 ShortcutsInhibitManager() 0053 : QWaylandClientExtensionTemplate<ShortcutsInhibitManager>(1) 0054 { 0055 #if QTWAYLANDCLIENT_VERSION >= QT_VERSION_CHECK(6, 2, 0) 0056 initialize(); 0057 #else 0058 // QWaylandClientExtensionTemplate invokes this with a QueuedConnection but we want shortcuts 0059 // to be inhibited immediately. 0060 QMetaObject::invokeMethod(this, "addRegistryListener"); 0061 #endif 0062 } 0063 ~ShortcutsInhibitManager() override 0064 { 0065 if (isInitialized()) { 0066 destroy(); 0067 } 0068 } 0069 0070 void startInhibition(QWindow *window) 0071 { 0072 if (m_inhibitions.contains(window)) { 0073 return; 0074 } 0075 QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface(); 0076 if (!nativeInterface) { 0077 return; 0078 } 0079 auto seat = static_cast<wl_seat *>(nativeInterface->nativeResourceForIntegration("wl_seat")); 0080 auto surface = static_cast<wl_surface *>(nativeInterface->nativeResourceForWindow("surface", window)); 0081 if (!seat || !surface) { 0082 return; 0083 } 0084 m_inhibitions[window].reset(new ShortcutsInhibitor(inhibit_shortcuts(surface, seat))); 0085 } 0086 0087 bool isInhibited(QWindow *window) const 0088 { 0089 return m_inhibitions.contains(window); 0090 } 0091 0092 void stopInhibition(QWindow *window) 0093 { 0094 m_inhibitions.remove(window); 0095 } 0096 0097 QHash<QWindow *, QSharedPointer<ShortcutsInhibitor>> m_inhibitions; 0098 }; 0099 0100 static std::shared_ptr<ShortcutsInhibitManager> theManager() 0101 { 0102 static std::weak_ptr<ShortcutsInhibitManager> managerInstance; 0103 std::shared_ptr<ShortcutsInhibitManager> ret = managerInstance.lock(); 0104 if (!ret) { 0105 ret = std::make_shared<ShortcutsInhibitManager>(); 0106 managerInstance = ret; 0107 } 0108 return ret; 0109 } 0110 0111 WaylandInhibition::WaylandInhibition(QWindow *window) 0112 : ShortcutInhibition() 0113 , m_window(window) 0114 , m_manager(theManager()) 0115 { 0116 } 0117 0118 WaylandInhibition::~WaylandInhibition() = default; 0119 0120 bool WaylandInhibition::shortcutsAreInhibited() const 0121 { 0122 return m_manager->isInhibited(m_window); 0123 } 0124 0125 void WaylandInhibition::enableInhibition() 0126 { 0127 m_manager->startInhibition(m_window); 0128 } 0129 0130 void WaylandInhibition::disableInhibition() 0131 { 0132 m_manager->stopInhibition(m_window); 0133 }