File indexing completed on 2024-04-28 05:30:23

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