File indexing completed on 2024-04-21 03:54:13

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 <QWaylandClientExtensionTemplate>
0012 #include <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         initialize();
0056     }
0057     ~ShortcutsInhibitManager() override
0058     {
0059         if (isInitialized()) {
0060             destroy();
0061         }
0062     }
0063 
0064     void startInhibition(QWindow *window)
0065     {
0066         if (m_inhibitions.contains(window)) {
0067             return;
0068         }
0069         QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface();
0070         if (!nativeInterface) {
0071             return;
0072         }
0073         auto seat = static_cast<wl_seat *>(nativeInterface->nativeResourceForIntegration("wl_seat"));
0074         auto surface = static_cast<wl_surface *>(nativeInterface->nativeResourceForWindow("surface", window));
0075         if (!seat || !surface) {
0076             return;
0077         }
0078         m_inhibitions[window].reset(new ShortcutsInhibitor(inhibit_shortcuts(surface, seat)));
0079     }
0080 
0081     bool isInhibited(QWindow *window) const
0082     {
0083         return m_inhibitions.contains(window);
0084     }
0085 
0086     void stopInhibition(QWindow *window)
0087     {
0088         m_inhibitions.remove(window);
0089     }
0090 
0091     QHash<QWindow *, QSharedPointer<ShortcutsInhibitor>> m_inhibitions;
0092 };
0093 
0094 static std::shared_ptr<ShortcutsInhibitManager> theManager()
0095 {
0096     static std::weak_ptr<ShortcutsInhibitManager> managerInstance;
0097     std::shared_ptr<ShortcutsInhibitManager> ret = managerInstance.lock();
0098     if (!ret) {
0099         ret = std::make_shared<ShortcutsInhibitManager>();
0100         managerInstance = ret;
0101     }
0102     return ret;
0103 }
0104 
0105 WaylandInhibition::WaylandInhibition(QWindow *window)
0106     : ShortcutInhibition()
0107     , m_window(window)
0108     , m_manager(theManager())
0109 {
0110 }
0111 
0112 WaylandInhibition::~WaylandInhibition() = default;
0113 
0114 bool WaylandInhibition::shortcutsAreInhibited() const
0115 {
0116     return m_manager->isInhibited(m_window);
0117 }
0118 
0119 void WaylandInhibition::enableInhibition()
0120 {
0121     m_manager->startInhibition(m_window);
0122 }
0123 
0124 void WaylandInhibition::disableInhibition()
0125 {
0126     m_manager->stopInhibition(m_window);
0127 }