1/* swc: libswc/swc.c
2 *
3 * Copyright (c) 2013-2020 Michael Forney
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "swc.h"
25#include "bindings.h"
26#include "compositor.h"
27#include "data_device_manager.h"
28#ifdef ENABLE_DRM
29#include "drm.h"
30#else
31#include "fb.h"
32#endif
33#include "event.h"
34#include "internal.h"
35#include "kde_decoration.h"
36#include "keyboard.h"
37#include "launch.h"
38#include "layer_shell.h"
39#include "panel_manager.h"
40#include "pointer.h"
41#include "screen.h"
42#include "seat.h"
43#include "select.h"
44#include "shell.h"
45#include "shm.h"
46#include "snap.h"
47#include "subcompositor.h"
48#include "util.h"
49#include "window.h"
50#include "xdg_decoration.h"
51#include "xdg_output.h"
52#include "xdg_shell.h"
53#ifdef ENABLE_XWAYLAND
54#include "xserver.h"
55#endif
56
57extern struct swc_launch swc_launch;
58extern const struct swc_bindings swc_bindings;
59extern struct swc_compositor swc_compositor;
60#ifdef ENABLE_DRM
61extern struct swc_drm swc_drm;
62#endif
63#ifdef ENABLE_XWAYLAND
64extern struct swc_xserver swc_xserver;
65#endif
66
67extern struct pointer_handler screens_pointer_handler;
68
69struct swc swc = {
70 .bindings = &swc_bindings,
71 .compositor = &swc_compositor,
72#ifdef ENABLE_DRM
73 .drm = &swc_drm,
74#endif
75#ifdef ENABLE_XWAYLAND
76 .xserver = &swc_xserver,
77#endif
78};
79
80static void
81setup_compositor(void)
82{
83 pixman_region32_t pointer_region;
84 struct screen *screen;
85 struct swc_rectangle *geom;
86
87 wl_list_insert(&swc.seat->keyboard->handlers,
88 &swc.bindings->keyboard_handler->link);
89 wl_list_insert(&swc.seat->pointer->handlers,
90 &swc.bindings->pointer_handler->link);
91 wl_list_insert(&swc.seat->pointer->handlers,
92 &swc.compositor->pointer_handler->link);
93 wl_list_insert(&swc.seat->pointer->handlers, &screens_pointer_handler.link);
94 wl_signal_add(&swc.seat->pointer->focus.event_signal,
95 &window_enter_listener);
96
97 /* Calculate pointer region */
98 pixman_region32_init(&pointer_region);
99
100 wl_list_for_each(screen, &swc.screens, link)
101 {
102 geom = &screen->base.geometry;
103 pixman_region32_union_rect(&pointer_region, &pointer_region, geom->x,
104 geom->y, geom->width, geom->height);
105 }
106
107 pointer_set_region(swc.seat->pointer, &pointer_region);
108 pixman_region32_fini(&pointer_region);
109}
110
111void
112swc_activate(void)
113{
114 swc.active = true;
115 send_event(&swc.event_signal, SWC_EVENT_ACTIVATED, NULL);
116 if (swc.manager->activate) {
117 swc.manager->activate();
118 }
119}
120
121void
122swc_deactivate(void)
123{
124 swc.active = false;
125 send_event(&swc.event_signal, SWC_EVENT_DEACTIVATED, NULL);
126 if (swc.manager->deactivate) {
127 swc.manager->deactivate();
128 }
129}
130
131EXPORT bool
132swc_cursor_position(int32_t *x, int32_t *y)
133{
134 if (x) {
135 *x = 0;
136 }
137 if (y) {
138 *y = 0;
139 }
140
141 if (!swc.seat || !swc.seat->pointer) {
142 return false;
143 }
144
145 if (x) {
146 *x = swc.seat->pointer->x;
147 }
148 if (y) {
149 *y = swc.seat->pointer->y;
150 }
151
152 return true;
153}
154
155EXPORT bool
156swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop,
157 const struct swc_manager *manager)
158{
159 swc.display = display;
160 swc.event_loop =
161 event_loop ? event_loop : wl_display_get_event_loop(display);
162 swc.manager = manager;
163 const char *default_seat = "seat0";
164 wl_signal_init(&swc.event_signal);
165
166 if (!launch_initialize()) {
167 ERROR("Could not connect to swc-launch\n");
168 goto error0;
169 }
170
171 if (!
172#ifdef ENABLE_DRM
173 drm_initialize()
174#else
175 fb_initialize()
176#endif
177 ) {
178 ERROR("Could not initialize video backend\n");
179 goto error1;
180 }
181
182 swc.shm = shm_create(display);
183 if (!swc.shm) {
184 ERROR("Could not initialize SHM\n");
185 goto error2;
186 }
187
188 if (!bindings_initialize()) {
189 ERROR("Could not initialize bindings\n");
190 goto error3;
191 }
192
193 swc.subcompositor = subcompositor_create(display);
194 if (!swc.subcompositor) {
195 ERROR("Could not initialize subcompositor\n");
196 goto error4;
197 }
198
199 if (!screens_initialize()) {
200 ERROR("Could not initialize screens\n");
201 goto error5;
202 }
203
204 if (!compositor_initialize()) {
205 ERROR("Could not initialize compositor\n");
206 goto error6;
207 }
208
209 swc.data_device_manager = data_device_manager_create(display);
210 if (!swc.data_device_manager) {
211 ERROR("Could not initialize data device manager\n");
212 goto error7;
213 }
214
215 swc.seat = seat_create(display, default_seat);
216 if (!swc.seat) {
217 ERROR("Could not initialize seat\n");
218 goto error8;
219 }
220
221 swc.shell = shell_create(display);
222 if (!swc.shell) {
223 ERROR("Could not initialize shell\n");
224 goto error9;
225 }
226
227 swc.xdg_shell = xdg_shell_create(display);
228 if (!swc.xdg_shell) {
229 ERROR("Could not initialize XDG shell\n");
230 goto error10;
231 }
232
233 swc.xdg_decoration_manager = xdg_decoration_manager_create(display);
234 if (!swc.xdg_decoration_manager) {
235 ERROR("Could not initialize XDG decoration manager\n");
236 goto error11;
237 }
238
239 swc.kde_decoration_manager = kde_decoration_manager_create(display);
240 if (!swc.kde_decoration_manager) {
241 ERROR("Could not initialize KDE decoration manager\n");
242 goto error12;
243 }
244
245 swc.layer_shell = layer_shell_create(display);
246 if (!swc.layer_shell) {
247 ERROR("Could not initialize layer shell\n");
248 goto error13;
249 }
250
251 swc.panel_manager = panel_manager_create(display);
252 if (!swc.panel_manager) {
253 ERROR("Could not initialize panel manager\n");
254 goto error14;
255 }
256
257 swc.snap_manager = snap_manager_create(display);
258 if (!swc.snap_manager) {
259 ERROR("Could not initialize snap manager\n");
260 goto error15;
261 }
262
263#ifdef ENABLE_XWAYLAND
264 if (!xserver_initialize()) {
265 ERROR("Could not initialize xwayland\n");
266 goto error16;
267 }
268#endif
269
270 swc.select_manager = select_manager_create(display);
271 if (!swc.select_manager) {
272 ERROR("Could not initialize select manager\n");
273 goto error17;
274 }
275
276 swc.xdg_output_manager = xdg_output_manager_create(display);
277 if (!swc.xdg_output_manager) {
278 ERROR("Could not initialize XDG output manager\n");
279 goto error17;
280 }
281
282 setup_compositor();
283
284 return true;
285
286error17:
287 wl_global_destroy(swc.select_manager);
288#ifdef ENABLE_XWAYLAND
289error16:
290#endif
291 wl_global_destroy(swc.snap_manager);
292error15:
293 wl_global_destroy(swc.panel_manager);
294error14:
295 wl_global_destroy(swc.layer_shell);
296error13:
297 wl_global_destroy(swc.kde_decoration_manager);
298error12:
299 wl_global_destroy(swc.xdg_decoration_manager);
300error11:
301 wl_global_destroy(swc.xdg_shell);
302error10:
303 wl_global_destroy(swc.shell);
304error9:
305 seat_destroy(swc.seat);
306error8:
307 wl_global_destroy(swc.data_device_manager);
308error7:
309 compositor_finalize();
310error6:
311 screens_finalize();
312error5:
313 wl_global_destroy(swc.subcompositor);
314error4:
315 bindings_finalize();
316error3:
317 shm_destroy(swc.shm);
318error2:
319#ifdef ENABLE_DRM
320 drm_finalize();
321#else
322 fb_finalize();
323#endif
324error1:
325 launch_finalize();
326error0:
327 return false;
328}
329
330EXPORT void
331swc_finalize(void)
332{
333#ifdef ENABLE_XWAYLAND
334 xserver_finalize();
335#endif
336 wl_global_destroy(swc.xdg_output_manager);
337 wl_global_destroy(swc.snap_manager);
338 wl_global_destroy(swc.select_manager);
339 wl_global_destroy(swc.panel_manager);
340 wl_global_destroy(swc.layer_shell);
341 wl_global_destroy(swc.xdg_decoration_manager);
342 wl_global_destroy(swc.xdg_shell);
343 wl_global_destroy(swc.shell);
344 seat_destroy(swc.seat);
345 wl_global_destroy(swc.data_device_manager);
346 compositor_finalize();
347 screens_finalize();
348 bindings_finalize();
349 shm_destroy(swc.shm);
350#ifdef ENABLE_DRM
351 drm_finalize();
352#else
353 fb_finalize();
354#endif
355 launch_finalize();
356}