File indexing completed on 2024-02-25 17:23:44

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
0006     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #pragma once
0012 
0013 #include <config-kwin.h>
0014 #include <kwinglobals.h>
0015 
0016 #include <KSharedConfig>
0017 #include <memory>
0018 // Qt
0019 #include <QAbstractNativeEventFilter>
0020 #include <QApplication>
0021 #include <QProcessEnvironment>
0022 
0023 class KPluginMetaData;
0024 class QCommandLineParser;
0025 
0026 namespace KWin
0027 {
0028 
0029 class OutputBackend;
0030 class Session;
0031 class X11EventFilter;
0032 class PluginManager;
0033 class InputMethod;
0034 class ColorManager;
0035 class ScreenLockerWatcher;
0036 class TabletModeManager;
0037 class XwaylandInterface;
0038 class Edge;
0039 class ScreenEdges;
0040 class Outline;
0041 class OutlineVisual;
0042 class Compositor;
0043 class WorkspaceScene;
0044 class Window;
0045 
0046 class XcbEventFilter : public QAbstractNativeEventFilter
0047 {
0048 public:
0049 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0050     bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override;
0051 #else
0052     bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
0053 #endif
0054 };
0055 
0056 class X11EventFilterContainer : public QObject
0057 {
0058     Q_OBJECT
0059 
0060 public:
0061     explicit X11EventFilterContainer(X11EventFilter *filter);
0062 
0063     X11EventFilter *filter() const;
0064 
0065 private:
0066     X11EventFilter *m_filter;
0067 };
0068 
0069 class KWIN_EXPORT Application : public QApplication
0070 {
0071     Q_OBJECT
0072     Q_PROPERTY(quint32 x11Time READ x11Time WRITE setX11Time)
0073     Q_PROPERTY(quint32 x11RootWindow READ x11RootWindow CONSTANT)
0074     Q_PROPERTY(void *x11Connection READ x11Connection NOTIFY x11ConnectionChanged)
0075     Q_PROPERTY(KSharedConfigPtr config READ config WRITE setConfig)
0076     Q_PROPERTY(KSharedConfigPtr kxkbConfig READ kxkbConfig WRITE setKxkbConfig)
0077 public:
0078     /**
0079      * @brief This enum provides the various operation modes of KWin depending on the available
0080      * Windowing Systems at startup. For example whether KWin only talks to X11 or also to a Wayland
0081      * Compositor.
0082      *
0083      */
0084     enum OperationMode {
0085         /**
0086          * @brief KWin uses only X11 for managing windows and compositing
0087          */
0088         OperationModeX11,
0089         /**
0090          * @brief KWin uses only Wayland
0091          */
0092         OperationModeWaylandOnly,
0093         /**
0094          * @brief KWin uses Wayland and controls a nested Xwayland server.
0095          */
0096         OperationModeXwayland
0097     };
0098     Q_ENUM(OperationMode)
0099     ~Application() override;
0100 
0101     void setConfigLock(bool lock);
0102 
0103     KSharedConfigPtr config() const
0104     {
0105         return m_config;
0106     }
0107     void setConfig(KSharedConfigPtr config)
0108     {
0109         m_config = std::move(config);
0110     }
0111 
0112     KSharedConfigPtr kxkbConfig() const
0113     {
0114         return m_kxkbConfig;
0115     }
0116     void setKxkbConfig(KSharedConfigPtr config)
0117     {
0118         m_kxkbConfig = std::move(config);
0119     }
0120 
0121     void start();
0122     /**
0123      * @brief The operation mode used by KWin.
0124      *
0125      * @return OperationMode
0126      */
0127     OperationMode operationMode() const;
0128     void setOperationMode(OperationMode mode);
0129     bool shouldUseWaylandForCompositing() const;
0130 
0131     void setupTranslator();
0132     void setupCommandLine(QCommandLineParser *parser);
0133     void processCommandLine(QCommandLineParser *parser);
0134 
0135     void registerEventFilter(X11EventFilter *filter);
0136     void unregisterEventFilter(X11EventFilter *filter);
0137     bool dispatchEvent(xcb_generic_event_t *event);
0138 
0139     xcb_timestamp_t x11Time() const
0140     {
0141         return m_x11Time;
0142     }
0143     enum class TimestampUpdate {
0144         OnlyIfLarger,
0145         Always
0146     };
0147     void setX11Time(xcb_timestamp_t timestamp, TimestampUpdate force = TimestampUpdate::OnlyIfLarger)
0148     {
0149         if ((timestamp > m_x11Time || force == TimestampUpdate::Always) && timestamp != 0) {
0150             m_x11Time = timestamp;
0151         }
0152     }
0153     /**
0154      * Queries the current X11 time stamp of the X server.
0155      */
0156     void updateXTime();
0157     void updateX11Time(xcb_generic_event_t *event);
0158 
0159     static void setCrashCount(int count);
0160     static bool wasCrash();
0161     void resetCrashesCount();
0162 
0163     /**
0164      * Creates the KAboutData object for the KWin instance and registers it as
0165      * KAboutData::setApplicationData.
0166      */
0167     static void createAboutData();
0168 
0169     /**
0170      * @returns the X11 root window.
0171      */
0172     xcb_window_t x11RootWindow() const
0173     {
0174         return m_rootWindow;
0175     }
0176 
0177     /**
0178      * @returns the X11 xcb connection
0179      */
0180     xcb_connection_t *x11Connection() const
0181     {
0182         return m_connection;
0183     }
0184 
0185     /**
0186      * Inheriting classes should use this method to set the X11 root window
0187      * before accessing any X11 specific code pathes.
0188      */
0189     void setX11RootWindow(xcb_window_t root)
0190     {
0191         m_rootWindow = root;
0192     }
0193     /**
0194      * Inheriting classes should use this method to set the xcb connection
0195      * before accessing any X11 specific code pathes.
0196      */
0197     void setX11Connection(xcb_connection_t *c)
0198     {
0199         m_connection = c;
0200     }
0201 
0202     qreal xwaylandScale() const
0203     {
0204         return m_xwaylandScale;
0205     }
0206 
0207     void setXwaylandScale(qreal scale);
0208 
0209 #if KWIN_BUILD_ACTIVITIES
0210     bool usesKActivities() const
0211     {
0212         return m_useKActivities;
0213     }
0214     void setUseKActivities(bool use)
0215     {
0216         m_useKActivities = use;
0217     }
0218 #endif
0219 
0220     QProcessEnvironment processStartupEnvironment() const;
0221     void setProcessStartupEnvironment(const QProcessEnvironment &environment);
0222 
0223     OutputBackend *outputBackend() const
0224     {
0225         return m_outputBackend.get();
0226     }
0227     void setOutputBackend(std::unique_ptr<OutputBackend> &&backend);
0228 
0229     Session *session() const
0230     {
0231         return m_session.get();
0232     }
0233     void setSession(std::unique_ptr<Session> &&session);
0234     void setFollowLocale1(bool follow)
0235     {
0236         m_followLocale1 = follow;
0237     }
0238     bool followLocale1() const
0239     {
0240         return m_followLocale1;
0241     }
0242 
0243     bool isTerminating() const
0244     {
0245         return m_terminating;
0246     }
0247 
0248     void installNativeX11EventFilter();
0249     void removeNativeX11EventFilter();
0250 
0251     void createAtoms();
0252     void destroyAtoms();
0253 
0254     virtual std::unique_ptr<Edge> createScreenEdge(ScreenEdges *parent);
0255     virtual void createPlatformCursor(QObject *parent = nullptr);
0256     virtual std::unique_ptr<OutlineVisual> createOutline(Outline *outline);
0257     virtual void createEffectsHandler(Compositor *compositor, WorkspaceScene *scene);
0258 
0259     static void setupMalloc();
0260     static void setupLocalizedString();
0261 
0262     PluginManager *pluginManager() const;
0263     InputMethod *inputMethod() const;
0264     ColorManager *colorManager() const;
0265     virtual XwaylandInterface *xwayland() const;
0266 #if KWIN_BUILD_SCREENLOCKER
0267     ScreenLockerWatcher *screenLockerWatcher() const;
0268 #endif
0269 
0270     /**
0271      * Starts an interactive window selection process.
0272      *
0273      * Once the user selected a window the @p callback is invoked with the selected Window as
0274      * argument. In case the user cancels the interactive window selection or selecting a window is currently
0275      * not possible (e.g. screen locked) the @p callback is invoked with a @c nullptr argument.
0276      *
0277      * During the interactive window selection the cursor is turned into a crosshair cursor unless
0278      * @p cursorName is provided. The argument @p cursorName is a QByteArray instead of Qt::CursorShape
0279      * to support the "pirate" cursor for kill window which is not wrapped by Qt::CursorShape.
0280      *
0281      * The default implementation forwards to InputRedirection.
0282      *
0283      * @param callback The function to invoke once the interactive window selection ends
0284      * @param cursorName The optional name of the cursor shape to use, default is crosshair
0285      */
0286     virtual void startInteractiveWindowSelection(std::function<void(KWin::Window *)> callback, const QByteArray &cursorName = QByteArray());
0287 
0288     /**
0289      * Starts an interactive position selection process.
0290      *
0291      * Once the user selected a position on the screen the @p callback is invoked with
0292      * the selected point as argument. In case the user cancels the interactive position selection
0293      * or selecting a position is currently not possible (e.g. screen locked) the @p callback
0294      * is invoked with a point at @c -1 as x and y argument.
0295      *
0296      * During the interactive window selection the cursor is turned into a crosshair cursor.
0297      *
0298      * The default implementation forwards to InputRedirection.
0299      *
0300      * @param callback The function to invoke once the interactive position selection ends
0301      */
0302     virtual void startInteractivePositionSelection(std::function<void(const QPoint &)> callback);
0303 
0304     /**
0305      * Returns a PlatformCursorImage. By default this is created by softwareCursor and
0306      * softwareCursorHotspot. An implementing subclass can use this to provide a better
0307      * suited PlatformCursorImage.
0308      *
0309      * @see softwareCursor
0310      * @see softwareCursorHotspot
0311      * @since 5.9
0312      */
0313     virtual PlatformCursorImage cursorImage() const;
0314 
0315 Q_SIGNALS:
0316     void x11ConnectionChanged();
0317     void x11ConnectionAboutToBeDestroyed();
0318     void xwaylandScaleChanged();
0319     void workspaceCreated();
0320     void virtualTerminalCreated();
0321     void started();
0322 
0323 protected:
0324     Application(OperationMode mode, int &argc, char **argv);
0325     virtual void performStartup() = 0;
0326 
0327     void notifyKSplash();
0328     void notifyStarted();
0329     void createInput();
0330     void createWorkspace();
0331     void createOptions();
0332     void createPlugins();
0333     void createColorManager();
0334     void createInputMethod();
0335     void createTabletModeManager();
0336     void destroyInput();
0337     void destroyWorkspace();
0338     void destroyCompositor();
0339     void destroyPlugins();
0340     void destroyColorManager();
0341     void destroyInputMethod();
0342     void destroyPlatform();
0343 
0344     void setTerminating()
0345     {
0346         m_terminating = true;
0347     }
0348 
0349 protected:
0350     static int crashes;
0351 
0352 private:
0353     QList<QPointer<X11EventFilterContainer>> m_eventFilters;
0354     QList<QPointer<X11EventFilterContainer>> m_genericEventFilters;
0355     std::unique_ptr<XcbEventFilter> m_eventFilter;
0356     bool m_followLocale1 = false;
0357     bool m_configLock;
0358     KSharedConfigPtr m_config;
0359     KSharedConfigPtr m_kxkbConfig;
0360     OperationMode m_operationMode;
0361     xcb_timestamp_t m_x11Time = XCB_TIME_CURRENT_TIME;
0362     xcb_window_t m_rootWindow = XCB_WINDOW_NONE;
0363     xcb_connection_t *m_connection = nullptr;
0364 #if KWIN_BUILD_ACTIVITIES
0365     bool m_useKActivities = true;
0366 #endif
0367     std::unique_ptr<Session> m_session;
0368     std::unique_ptr<OutputBackend> m_outputBackend;
0369     bool m_terminating = false;
0370     qreal m_xwaylandScale = 1;
0371     QProcessEnvironment m_processEnvironment;
0372     std::unique_ptr<PluginManager> m_pluginManager;
0373     std::unique_ptr<InputMethod> m_inputMethod;
0374     std::unique_ptr<ColorManager> m_colorManager;
0375     std::unique_ptr<TabletModeManager> m_tabletModeManager;
0376 #if KWIN_BUILD_SCREENLOCKER
0377     std::unique_ptr<ScreenLockerWatcher> m_screenLockerWatcher;
0378 #endif
0379 };
0380 
0381 inline static Application *kwinApp()
0382 {
0383     Q_ASSERT(qobject_cast<Application *>(QCoreApplication::instance()));
0384 
0385     return static_cast<Application *>(QCoreApplication::instance());
0386 }
0387 
0388 } // namespace