1 /*
2     KWin - the KDE window manager
3     This file is part of the KDE project.
4 
5     SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
6 
7     SPDX-License-Identifier: GPL-2.0-or-later
8 */
9 #ifndef KWIN_WAYLAND_SERVER_H
10 #define KWIN_WAYLAND_SERVER_H
11 
12 #include <kwinglobals.h>
13 #include "keyboard_input.h"
14 
15 #include <QObject>
16 
17 class QThread;
18 class QProcess;
19 class QWindow;
20 
21 namespace KWayland
22 {
23 namespace Client
24 {
25 class ConnectionThread;
26 class EventQueue;
27 class Registry;
28 class Compositor;
29 class Seat;
30 class DataDeviceManager;
31 class Surface;
32 }
33 }
34 namespace KWaylandServer
35 {
36 class AppMenuManagerInterface;
37 class ClientConnection;
38 class CompositorInterface;
39 class Display;
40 class DataDeviceInterface;
41 class IdleInterface;
42 class InputMethodV1Interface;
43 class SeatInterface;
44 class DataDeviceManagerInterface;
45 class ServerSideDecorationManagerInterface;
46 class ServerSideDecorationPaletteManagerInterface;
47 class SurfaceInterface;
48 class OutputInterface;
49 class PlasmaShellInterface;
50 class PlasmaWindowActivationFeedbackInterface;
51 class PlasmaVirtualDesktopManagementInterface;
52 class PlasmaWindowManagementInterface;
53 class OutputManagementV2Interface;
54 class XdgForeignV2Interface;
55 class XdgOutputManagerV1Interface;
56 class KeyStateInterface;
57 class LinuxDmaBufV1ClientBufferIntegration;
58 class LinuxDmaBufV1ClientBuffer;
59 class TabletManagerV2Interface;
60 class KeyboardShortcutsInhibitManagerV1Interface;
61 class XdgDecorationManagerV1Interface;
62 }
63 
64 
65 namespace KWin
66 {
67 
68 class AbstractClient;
69 class AbstractOutput;
70 class Toplevel;
71 class XdgPopupClient;
72 class XdgSurfaceClient;
73 class XdgToplevelClient;
74 class AbstractWaylandOutput;
75 class WaylandOutput;
76 class WaylandOutputDevice;
77 
78 class KWIN_EXPORT WaylandServer : public QObject
79 {
80     Q_OBJECT
81 
82 public:
83     enum class InitializationFlag {
84         NoOptions = 0x0,
85         LockScreen = 0x1,
86         NoLockScreenIntegration = 0x2,
87         NoGlobalShortcuts = 0x4
88     };
89 
90     Q_DECLARE_FLAGS(InitializationFlags, InitializationFlag)
91 
92     ~WaylandServer() override;
93     bool init(const QString &socketName, InitializationFlags flags = InitializationFlag::NoOptions);
94     bool init(InitializationFlags flags = InitializationFlag::NoOptions);
95 
96     bool start();
97     void terminateClientConnections();
98 
display()99     KWaylandServer::Display *display() const
100     {
101         return m_display;
102     }
compositor()103     KWaylandServer::CompositorInterface *compositor() const
104     {
105         return m_compositor;
106     }
seat()107     KWaylandServer::SeatInterface *seat() const
108     {
109         return m_seat;
110     }
tabletManagerV2()111     KWaylandServer::TabletManagerV2Interface *tabletManagerV2() const
112     {
113         return m_tabletManagerV2;
114     }
dataDeviceManager()115     KWaylandServer::DataDeviceManagerInterface *dataDeviceManager() const
116     {
117         return m_dataDeviceManager;
118     }
plasmaActivationFeedback()119     KWaylandServer::PlasmaWindowActivationFeedbackInterface *plasmaActivationFeedback() const
120     {
121         return m_plasmaActivationFeedback;
122     }
virtualDesktopManagement()123     KWaylandServer::PlasmaVirtualDesktopManagementInterface *virtualDesktopManagement() const
124     {
125         return m_virtualDesktopManagement;
126     }
windowManagement()127     KWaylandServer::PlasmaWindowManagementInterface *windowManagement() const
128     {
129         return m_windowManagement;
130     }
decorationManager()131     KWaylandServer::ServerSideDecorationManagerInterface *decorationManager() const {
132         return m_decorationManager;
133     }
xdgOutputManagerV1()134     KWaylandServer::XdgOutputManagerV1Interface *xdgOutputManagerV1() const {
135         return m_xdgOutputManagerV1;
136     }
keyboardShortcutsInhibitManager()137     KWaylandServer::KeyboardShortcutsInhibitManagerV1Interface *keyboardShortcutsInhibitManager() const
138     {
139         return m_keyboardShortcutsInhibitManager;
140     }
141 
142     bool isKeyboardShortcutsInhibited() const;
143 
144     KWaylandServer::LinuxDmaBufV1ClientBufferIntegration *linuxDmabuf();
145 
inputMethod()146     KWaylandServer::InputMethodV1Interface *inputMethod() const {
147         return m_inputMethod;
148     }
149 
clients()150     QList<AbstractClient *> clients() const {
151         return m_clients;
152     }
153     void removeClient(AbstractClient *c);
154     AbstractClient *findClient(const KWaylandServer::SurfaceInterface *surface) const;
155     XdgToplevelClient *findXdgToplevelClient(KWaylandServer::SurfaceInterface *surface) const;
156     XdgSurfaceClient *findXdgSurfaceClient(KWaylandServer::SurfaceInterface *surface) const;
157 
158     /**
159      * @returns a transient parent of a surface imported with the foreign protocol, if any
160      */
161     KWaylandServer::SurfaceInterface *findForeignTransientForSurface(KWaylandServer::SurfaceInterface *surface);
162 
163     /**
164      * @returns file descriptor for Xwayland to connect to.
165      */
166     int createXWaylandConnection();
167     void destroyXWaylandConnection();
168 
169     /**
170      * @returns file descriptor to the input method server's socket.
171      */
172     int createInputMethodConnection();
173     void destroyInputMethodConnection();
174 
175     /**
176      * @returns true if screen is locked.
177      */
178     bool isScreenLocked() const;
179     /**
180      * @returns whether integration with KScreenLocker is available.
181      */
182     bool hasScreenLockerIntegration() const;
183 
184     /**
185      * @returns whether any kind of global shortcuts are supported.
186      */
187     bool hasGlobalShortcutSupport() const;
188 
189     void createInternalConnection();
190     void initPlatform();
191     void initWorkspace();
192 
193     KWaylandServer::ClientConnection *xWaylandConnection() const;
inputMethodConnection()194     KWaylandServer::ClientConnection *inputMethodConnection() const {
195         return m_inputMethodServerConnection;
196     }
internalConnection()197     KWaylandServer::ClientConnection *internalConnection() const {
198         return m_internalConnection.server;
199     }
screenLockerClientConnection()200     KWaylandServer::ClientConnection *screenLockerClientConnection() const {
201         return m_screenLockerClientConnection;
202     }
internalCompositor()203     KWayland::Client::Compositor *internalCompositor() {
204         return m_internalConnection.compositor;
205     }
internalSeat()206     KWayland::Client::Seat *internalSeat() {
207         return m_internalConnection.seat;
208     }
internalDataDeviceManager()209     KWayland::Client::DataDeviceManager *internalDataDeviceManager() {
210         return m_internalConnection.ddm;
211     }
internalClientConection()212     KWayland::Client::ConnectionThread *internalClientConection() {
213         return m_internalConnection.client;
214     }
internalClientRegistry()215     KWayland::Client::Registry *internalClientRegistry() {
216         return m_internalConnection.registry;
217     }
218     void dispatch();
219 
220     /**
221      * Struct containing information for a created Wayland connection through a
222      * socketpair.
223      */
224     struct SocketPairConnection {
225         /**
226          * ServerSide Connection
227          */
228         KWaylandServer::ClientConnection *connection = nullptr;
229         /**
230          * client-side file descriptor for the socket
231          */
232         int fd = -1;
233     };
234     /**
235      * Creates a Wayland connection using a socket pair.
236      */
237     SocketPairConnection createConnection();
238 
239     void simulateUserActivity();
240     void updateKeyState(KWin::Xkb::LEDs leds);
241 
linuxDmabufBuffers()242     QSet<KWaylandServer::LinuxDmaBufV1ClientBuffer*> linuxDmabufBuffers() const {
243         return m_linuxDmabufBuffers;
244     }
addLinuxDmabufBuffer(KWaylandServer::LinuxDmaBufV1ClientBuffer * buffer)245     void addLinuxDmabufBuffer(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer) {
246         m_linuxDmabufBuffers << buffer;
247     }
removeLinuxDmabufBuffer(KWaylandServer::LinuxDmaBufV1ClientBuffer * buffer)248     void removeLinuxDmabufBuffer(KWaylandServer::LinuxDmaBufV1ClientBuffer *buffer) {
249         m_linuxDmabufBuffers.remove(buffer);
250     }
251 
252     AbstractWaylandOutput *findOutput(KWaylandServer::OutputInterface *output) const;
253 
254     /**
255      * Returns the first socket name that can be used to connect to this server.
256      * For a full list, use display()->socketNames()
257      */
258     QString socketName() const;
259 
260 Q_SIGNALS:
261     void shellClientAdded(KWin::AbstractClient *);
262     void shellClientRemoved(KWin::AbstractClient *);
263     void terminatingInternalClientConnection();
264     void initialized();
265     void foreignTransientChanged(KWaylandServer::SurfaceInterface *child);
266 
267 private:
268     int createScreenLockerConnection();
269     void shellClientShown(Toplevel *t);
270     void destroyInternalConnection();
271     void initScreenLocker();
272     void registerXdgGenericClient(AbstractClient *client);
273     void registerXdgToplevelClient(XdgToplevelClient *client);
274     void registerXdgPopupClient(XdgPopupClient *client);
275     void registerShellClient(AbstractClient *client);
276     void handleOutputAdded(AbstractOutput *output);
277     void handleOutputRemoved(AbstractOutput *output);
278     void handleOutputEnabled(AbstractOutput *output);
279     void handleOutputDisabled(AbstractOutput *output);
280     KWaylandServer::Display *m_display = nullptr;
281     KWaylandServer::CompositorInterface *m_compositor = nullptr;
282     KWaylandServer::SeatInterface *m_seat = nullptr;
283     KWaylandServer::TabletManagerV2Interface *m_tabletManagerV2 = nullptr;
284     KWaylandServer::DataDeviceManagerInterface *m_dataDeviceManager = nullptr;
285     KWaylandServer::PlasmaShellInterface *m_plasmaShell = nullptr;
286     KWaylandServer::PlasmaWindowActivationFeedbackInterface *m_plasmaActivationFeedback = nullptr;
287     KWaylandServer::PlasmaWindowManagementInterface *m_windowManagement = nullptr;
288     KWaylandServer::PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr;
289     KWaylandServer::ServerSideDecorationManagerInterface *m_decorationManager = nullptr;
290     KWaylandServer::OutputManagementV2Interface *m_outputManagement = nullptr;
291     KWaylandServer::AppMenuManagerInterface *m_appMenuManager = nullptr;
292     KWaylandServer::ServerSideDecorationPaletteManagerInterface *m_paletteManager = nullptr;
293     KWaylandServer::IdleInterface *m_idle = nullptr;
294     KWaylandServer::XdgOutputManagerV1Interface *m_xdgOutputManagerV1 = nullptr;
295     KWaylandServer::XdgDecorationManagerV1Interface *m_xdgDecorationManagerV1 = nullptr;
296     KWaylandServer::LinuxDmaBufV1ClientBufferIntegration *m_linuxDmabuf = nullptr;
297     KWaylandServer::KeyboardShortcutsInhibitManagerV1Interface *m_keyboardShortcutsInhibitManager = nullptr;
298     QSet<KWaylandServer::LinuxDmaBufV1ClientBuffer*> m_linuxDmabufBuffers;
299     QPointer<KWaylandServer::ClientConnection> m_xwaylandConnection;
300     KWaylandServer::InputMethodV1Interface *m_inputMethod = nullptr;
301     KWaylandServer::ClientConnection *m_inputMethodServerConnection = nullptr;
302     KWaylandServer::ClientConnection *m_screenLockerClientConnection = nullptr;
303     struct {
304         KWaylandServer::ClientConnection *server = nullptr;
305         KWayland::Client::ConnectionThread *client = nullptr;
306         KWayland::Client::EventQueue *eventQueue = nullptr;
307         QThread *clientThread = nullptr;
308         KWayland::Client::Registry *registry = nullptr;
309         KWayland::Client::Compositor *compositor = nullptr;
310         KWayland::Client::Seat *seat = nullptr;
311         KWayland::Client::DataDeviceManager *ddm = nullptr;
312         bool interfacesAnnounced = false;
313 
314     } m_internalConnection;
315     KWaylandServer::XdgForeignV2Interface *m_XdgForeign = nullptr;
316     KWaylandServer::KeyStateInterface *m_keyState = nullptr;
317     QList<AbstractClient *> m_clients;
318     InitializationFlags m_initFlags;
319     QHash<AbstractWaylandOutput *, WaylandOutput *> m_waylandOutputs;
320     QHash<AbstractWaylandOutput *, WaylandOutputDevice *> m_waylandOutputDevices;
321     KWIN_SINGLETON(WaylandServer)
322 };
323 
324 inline
waylandServer()325 WaylandServer *waylandServer() {
326     return WaylandServer::self();
327 }
328 
329 } // namespace KWin
330 
331 #endif
332 
333