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_cursor_set_position(int32_t x, int32_t y)
157{
158 if (!swc.seat || !swc.seat->pointer) {
159 return false;
160 }
161
162 pointer_handle_absolute_motion(swc.seat->pointer, get_time(),
163 wl_fixed_from_int(x), wl_fixed_from_int(y));
164 pointer_handle_frame(swc.seat->pointer);
165
166 return true;
167}
168
169EXPORT bool
170swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop,
171 const struct swc_manager *manager)
172{
173 swc.display = display;
174 swc.event_loop =
175 event_loop ? event_loop : wl_display_get_event_loop(display);
176 swc.manager = manager;
177 const char *default_seat = "seat0";
178 wl_signal_init(&swc.event_signal);
179
180 if (!launch_initialize()) {
181 ERROR("Could not connect to swc-launch\n");
182 goto error0;
183 }
184
185 if (!
186#ifdef ENABLE_DRM
187 drm_initialize()
188#else
189 fb_initialize()
190#endif
191 ) {
192 ERROR("Could not initialize video backend\n");
193 goto error1;
194 }
195
196 swc.shm = shm_create(display);
197 if (!swc.shm) {
198 ERROR("Could not initialize SHM\n");
199 goto error2;
200 }
201
202 if (!bindings_initialize()) {
203 ERROR("Could not initialize bindings\n");
204 goto error3;
205 }
206
207 swc.subcompositor = subcompositor_create(display);
208 if (!swc.subcompositor) {
209 ERROR("Could not initialize subcompositor\n");
210 goto error4;
211 }
212
213 if (!screens_initialize()) {
214 ERROR("Could not initialize screens\n");
215 goto error5;
216 }
217
218 if (!compositor_initialize()) {
219 ERROR("Could not initialize compositor\n");
220 goto error6;
221 }
222
223 swc.data_device_manager = data_device_manager_create(display);
224 if (!swc.data_device_manager) {
225 ERROR("Could not initialize data device manager\n");
226 goto error7;
227 }
228
229 swc.seat = seat_create(display, default_seat);
230 if (!swc.seat) {
231 ERROR("Could not initialize seat\n");
232 goto error8;
233 }
234
235 swc.shell = shell_create(display);
236 if (!swc.shell) {
237 ERROR("Could not initialize shell\n");
238 goto error9;
239 }
240
241 swc.xdg_shell = xdg_shell_create(display);
242 if (!swc.xdg_shell) {
243 ERROR("Could not initialize XDG shell\n");
244 goto error10;
245 }
246
247 swc.xdg_decoration_manager = xdg_decoration_manager_create(display);
248 if (!swc.xdg_decoration_manager) {
249 ERROR("Could not initialize XDG decoration manager\n");
250 goto error11;
251 }
252
253 swc.kde_decoration_manager = kde_decoration_manager_create(display);
254 if (!swc.kde_decoration_manager) {
255 ERROR("Could not initialize KDE decoration manager\n");
256 goto error12;
257 }
258
259 swc.layer_shell = layer_shell_create(display);
260 if (!swc.layer_shell) {
261 ERROR("Could not initialize layer shell\n");
262 goto error13;
263 }
264
265 swc.panel_manager = panel_manager_create(display);
266 if (!swc.panel_manager) {
267 ERROR("Could not initialize panel manager\n");
268 goto error14;
269 }
270
271 swc.snap_manager = snap_manager_create(display);
272 if (!swc.snap_manager) {
273 ERROR("Could not initialize snap manager\n");
274 goto error15;
275 }
276
277#ifdef ENABLE_XWAYLAND
278 if (!xserver_initialize()) {
279 ERROR("Could not initialize xwayland\n");
280 goto error16;
281 }
282#endif
283
284 swc.select_manager = select_manager_create(display);
285 if (!swc.select_manager) {
286 ERROR("Could not initialize select manager\n");
287 goto error17;
288 }
289
290 swc.xdg_output_manager = xdg_output_manager_create(display);
291 if (!swc.xdg_output_manager) {
292 ERROR("Could not initialize XDG output manager\n");
293 goto error17;
294 }
295
296 setup_compositor();
297
298 return true;
299
300error17:
301 wl_global_destroy(swc.select_manager);
302#ifdef ENABLE_XWAYLAND
303error16:
304#endif
305 wl_global_destroy(swc.snap_manager);
306error15:
307 wl_global_destroy(swc.panel_manager);
308error14:
309 wl_global_destroy(swc.layer_shell);
310error13:
311 wl_global_destroy(swc.kde_decoration_manager);
312error12:
313 wl_global_destroy(swc.xdg_decoration_manager);
314error11:
315 wl_global_destroy(swc.xdg_shell);
316error10:
317 wl_global_destroy(swc.shell);
318error9:
319 seat_destroy(swc.seat);
320error8:
321 wl_global_destroy(swc.data_device_manager);
322error7:
323 compositor_finalize();
324error6:
325 screens_finalize();
326error5:
327 wl_global_destroy(swc.subcompositor);
328error4:
329 bindings_finalize();
330error3:
331 shm_destroy(swc.shm);
332error2:
333#ifdef ENABLE_DRM
334 drm_finalize();
335#else
336 fb_finalize();
337#endif
338error1:
339 launch_finalize();
340error0:
341 return false;
342}
343
344EXPORT void
345swc_finalize(void)
346{
347#ifdef ENABLE_XWAYLAND
348 xserver_finalize();
349#endif
350 wl_global_destroy(swc.xdg_output_manager);
351 wl_global_destroy(swc.snap_manager);
352 wl_global_destroy(swc.select_manager);
353 wl_global_destroy(swc.panel_manager);
354 wl_global_destroy(swc.layer_shell);
355 wl_global_destroy(swc.xdg_decoration_manager);
356 wl_global_destroy(swc.xdg_shell);
357 wl_global_destroy(swc.shell);
358 seat_destroy(swc.seat);
359 wl_global_destroy(swc.data_device_manager);
360 compositor_finalize();
361 screens_finalize();
362 bindings_finalize();
363 shm_destroy(swc.shm);
364#ifdef ENABLE_DRM
365 drm_finalize();
366#else
367 fb_finalize();
368#endif
369 launch_finalize();
370}