1 /*
2     KWin - the KDE window manager
3     This file is part of the KDE project.
4 
5     SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
7 
8     SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 
11 #ifndef MAIN_H
12 #define MAIN_H
13 
14 #include <kwinglobals.h>
15 #include <config-kwin.h>
16 
17 #include <KSharedConfig>
18 // Qt
19 #include <QApplication>
20 #include <QAbstractNativeEventFilter>
21 #include <QProcessEnvironment>
22 
23 class KPluginMetaData;
24 class QCommandLineParser;
25 
26 namespace KWin
27 {
28 
29 class Platform;
30 class X11EventFilter;
31 
32 class XcbEventFilter : public QAbstractNativeEventFilter
33 {
34 public:
35     bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override;
36 };
37 
38 class X11EventFilterContainer : public QObject
39 {
40     Q_OBJECT
41 
42 public:
43     explicit X11EventFilterContainer(X11EventFilter *filter);
44 
45     X11EventFilter *filter() const;
46 
47 private:
48     X11EventFilter *m_filter;
49 };
50 
51 class KWIN_EXPORT Application : public  QApplication
52 {
53     Q_OBJECT
54     Q_PROPERTY(quint32 x11Time READ x11Time WRITE setX11Time)
55     Q_PROPERTY(quint32 x11RootWindow READ x11RootWindow CONSTANT)
56     Q_PROPERTY(void *x11Connection READ x11Connection NOTIFY x11ConnectionChanged)
57     Q_PROPERTY(int x11ScreenNumber READ x11ScreenNumber CONSTANT)
58     Q_PROPERTY(KSharedConfigPtr config READ config WRITE setConfig)
59     Q_PROPERTY(KSharedConfigPtr kxkbConfig READ kxkbConfig WRITE setKxkbConfig)
60 public:
61     /**
62      * @brief This enum provides the various operation modes of KWin depending on the available
63      * Windowing Systems at startup. For example whether KWin only talks to X11 or also to a Wayland
64      * Compositor.
65      *
66      */
67     enum OperationMode {
68         /**
69          * @brief KWin uses only X11 for managing windows and compositing
70          */
71         OperationModeX11,
72         /**
73          * @brief KWin uses only Wayland
74          */
75         OperationModeWaylandOnly,
76         /**
77          * @brief KWin uses Wayland and controls a nested Xwayland server.
78          */
79         OperationModeXwayland
80     };
81     ~Application() override;
82 
83     void setConfigLock(bool lock);
84 
config()85     KSharedConfigPtr config() const {
86         return m_config;
87     }
setConfig(KSharedConfigPtr config)88     void setConfig(KSharedConfigPtr config) {
89         m_config = std::move(config);
90     }
91 
kxkbConfig()92     KSharedConfigPtr kxkbConfig() const {
93         return m_kxkbConfig;
94     }
setKxkbConfig(KSharedConfigPtr config)95     void setKxkbConfig(KSharedConfigPtr config) {
96         m_kxkbConfig = std::move(config);
97     }
98 
99     void start();
100     /**
101      * @brief The operation mode used by KWin.
102      *
103      * @return OperationMode
104      */
105     OperationMode operationMode() const;
106     void setOperationMode(OperationMode mode);
107     bool shouldUseWaylandForCompositing() const;
108 
109     void setupTranslator();
110     void setupCommandLine(QCommandLineParser *parser);
111     void processCommandLine(QCommandLineParser *parser);
112 
113     void registerEventFilter(X11EventFilter *filter);
114     void unregisterEventFilter(X11EventFilter *filter);
115     bool dispatchEvent(xcb_generic_event_t *event);
116 
x11Time()117     xcb_timestamp_t x11Time() const {
118         return m_x11Time;
119     }
120     enum class TimestampUpdate {
121         OnlyIfLarger,
122         Always
123     };
124     void setX11Time(xcb_timestamp_t timestamp, TimestampUpdate force = TimestampUpdate::OnlyIfLarger) {
125         if ((timestamp > m_x11Time || force == TimestampUpdate::Always) && timestamp != 0) {
126             m_x11Time = timestamp;
127         }
128     }
129     void updateX11Time(xcb_generic_event_t *event);
130     void createScreens();
131 
132     static void setCrashCount(int count);
133     static bool wasCrash();
134     void resetCrashesCount();
135 
136     /**
137      * Creates the KAboutData object for the KWin instance and registers it as
138      * KAboutData::setApplicationData.
139      */
140     static void createAboutData();
141 
142     /**
143      * @returns the X11 Screen number. If not applicable it's set to @c -1.
144      */
145     static int x11ScreenNumber();
146     /**
147      * Sets the X11 screen number of this KWin instance to @p screenNumber.
148      */
149     static void setX11ScreenNumber(int screenNumber);
150     /**
151      * @returns whether this is a multi head setup on X11.
152      */
153     static bool isX11MultiHead();
154     /**
155      * Sets whether this is a multi head setup on X11.
156      */
157     static void setX11MultiHead(bool multiHead);
158 
159     /**
160      * @returns the X11 root window.
161      */
x11RootWindow()162     xcb_window_t x11RootWindow() const {
163         return m_rootWindow;
164     }
165 
166     /**
167      * @returns the X11 xcb connection
168      */
x11Connection()169     xcb_connection_t *x11Connection() const {
170         return m_connection;
171     }
172 
173     /**
174      * @returns the X11 default screen
175      */
x11DefaultScreen()176     xcb_screen_t *x11DefaultScreen() const {
177         return m_defaultScreen;
178     }
179 
180     /**
181      * Returns @c true if we're in the middle of destroying the X11 connection.
182      */
isClosingX11Connection()183     bool isClosingX11Connection() const {
184         return m_isClosingX11Connection;
185     }
186 
187 #ifdef KWIN_BUILD_ACTIVITIES
usesKActivities()188     bool usesKActivities() const {
189         return m_useKActivities;
190     }
setUseKActivities(bool use)191     void setUseKActivities(bool use) {
192         m_useKActivities = use;
193     }
194 #endif
195 
196     virtual QProcessEnvironment processStartupEnvironment() const;
197 
198     void initPlatform(const KPluginMetaData &plugin);
platform()199     Platform *platform() const {
200         return m_platform;
201     }
202 
isTerminating()203     bool isTerminating() const {
204         return m_terminating;
205     }
206 
207     static void setupMalloc();
208     static void setupLocalizedString();
209 
210     static bool usesLibinput();
211     static void setUseLibinput(bool use);
212 
213 Q_SIGNALS:
214     void x11ConnectionChanged();
215     void x11ConnectionAboutToBeDestroyed();
216     void workspaceCreated();
217     void screensCreated();
218     void platformCreated();
219     void virtualTerminalCreated();
220     void started();
221 
222 protected:
223     Application(OperationMode mode, int &argc, char **argv);
224     virtual void performStartup() = 0;
225 
226     void notifyKSplash();
227     void notifyStarted();
228     void createInput();
229     void createWorkspace();
230     void createAtoms();
231     void createOptions();
232     void createPlugins();
233     void createColorManager();
234     void installNativeX11EventFilter();
235     void removeNativeX11EventFilter();
236     void destroyInput();
237     void destroyWorkspace();
238     void destroyCompositor();
239     void destroyPlugins();
240     void destroyColorManager();
241     /**
242      * Inheriting classes should use this method to set the X11 root window
243      * before accessing any X11 specific code pathes.
244      */
setX11RootWindow(xcb_window_t root)245     void setX11RootWindow(xcb_window_t root) {
246         m_rootWindow = root;
247     }
248     /**
249      * Inheriting classes should use this method to set the xcb connection
250      * before accessing any X11 specific code pathes.
251      */
setX11Connection(xcb_connection_t * c)252     void setX11Connection(xcb_connection_t *c) {
253         m_connection = c;
254     }
255     /**
256      * Inheriting classes should use this method to set the default screen
257      * before accessing any X11 specific code pathes.
258      */
setX11DefaultScreen(xcb_screen_t * screen)259     void setX11DefaultScreen(xcb_screen_t *screen) {
260         m_defaultScreen = screen;
261     }
262     void destroyAtoms();
263     void destroyPlatform();
264 
setTerminating()265     void setTerminating() {
266         m_terminating = true;
267     }
setClosingX11Connection(bool set)268     void setClosingX11Connection(bool set) {
269         m_isClosingX11Connection = set;
270     }
271 
272 protected:
273     static int crashes;
274 
275 private:
276     QList<QPointer<X11EventFilterContainer>> m_eventFilters;
277     QList<QPointer<X11EventFilterContainer>> m_genericEventFilters;
278     QScopedPointer<XcbEventFilter> m_eventFilter;
279     bool m_configLock;
280     KSharedConfigPtr m_config;
281     KSharedConfigPtr m_kxkbConfig;
282     OperationMode m_operationMode;
283     xcb_timestamp_t m_x11Time = XCB_TIME_CURRENT_TIME;
284     xcb_window_t m_rootWindow = XCB_WINDOW_NONE;
285     xcb_connection_t *m_connection = nullptr;
286     xcb_screen_t *m_defaultScreen = nullptr;
287 #ifdef KWIN_BUILD_ACTIVITIES
288     bool m_useKActivities = true;
289 #endif
290     Platform *m_platform = nullptr;
291     bool m_terminating = false;
292     bool m_isClosingX11Connection = false;
293 };
294 
kwinApp()295 inline static Application *kwinApp()
296 {
297     return static_cast<Application*>(QCoreApplication::instance());
298 }
299 
300 namespace Xwl
301 {
302 class Xwayland;
303 }
304 
305 class KWIN_EXPORT ApplicationWaylandAbstract : public Application
306 {
307     Q_OBJECT
308 public:
309     ~ApplicationWaylandAbstract() override = 0;
310 protected:
311     friend class Xwl::Xwayland;
312 
313     ApplicationWaylandAbstract(OperationMode mode, int &argc, char **argv);
setProcessStartupEnvironment(const QProcessEnvironment & environment)314     virtual void setProcessStartupEnvironment(const QProcessEnvironment &environment) {
315         Q_UNUSED(environment);
316     }
startSession()317     virtual void startSession() {}
318 };
319 
320 
321 } // namespace
322 
323 #endif
324