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#include "drm.h"
29#include "event.h"
30#include "internal.h"
31#include "kde_decoration.h"
32#include "keyboard.h"
33#include "launch.h"
34#include "layer_shell.h"
35#include "panel_manager.h"
36#include "pointer.h"
37#include "screen.h"
38#include "seat.h"
39#include "select.h"
40#include "shell.h"
41#include "shm.h"
42#include "snap.h"
43#include "subcompositor.h"
44#include "util.h"
45#include "window.h"
46#include "xdg_decoration.h"
47#include "xdg_output.h"
48#include "xdg_shell.h"
49#ifdef ENABLE_XWAYLAND
50#include "xserver.h"
51#endif
52
53extern struct swc_launch swc_launch;
54extern const struct swc_bindings swc_bindings;
55extern struct swc_compositor swc_compositor;
56extern struct swc_drm swc_drm;
57#ifdef ENABLE_XWAYLAND
58extern struct swc_xserver swc_xserver;
59#endif
60
61extern struct pointer_handler screens_pointer_handler;
62
63struct swc swc = {
64 .bindings = &swc_bindings,
65 .compositor = &swc_compositor,
66 .drm = &swc_drm,
67#ifdef ENABLE_XWAYLAND
68 .xserver = &swc_xserver,
69#endif
70};
71
72static void
73setup_compositor(void)
74{
75 pixman_region32_t pointer_region;
76 struct screen *screen;
77 struct swc_rectangle *geom;
78
79 wl_list_insert(&swc.seat->keyboard->handlers,
80 &swc.bindings->keyboard_handler->link);
81 wl_list_insert(&swc.seat->pointer->handlers,
82 &swc.bindings->pointer_handler->link);
83 wl_list_insert(&swc.seat->pointer->handlers,
84 &swc.compositor->pointer_handler->link);
85 wl_list_insert(&swc.seat->pointer->handlers, &screens_pointer_handler.link);
86 wl_signal_add(&swc.seat->pointer->focus.event_signal,
87 &window_enter_listener);
88
89 /* Calculate pointer region */
90 pixman_region32_init(&pointer_region);
91
92 wl_list_for_each(screen, &swc.screens, link)
93 {
94 geom = &screen->base.geometry;
95 pixman_region32_union_rect(&pointer_region, &pointer_region, geom->x,
96 geom->y, geom->width, geom->height);
97 }
98
99 pointer_set_region(swc.seat->pointer, &pointer_region);
100 pixman_region32_fini(&pointer_region);
101}
102
103void
104swc_activate(void)
105{
106 swc.active = true;
107 send_event(&swc.event_signal, SWC_EVENT_ACTIVATED, NULL);
108 if (swc.manager->activate) {
109 swc.manager->activate();
110 }
111}
112
113void
114swc_deactivate(void)
115{
116 swc.active = false;
117 send_event(&swc.event_signal, SWC_EVENT_DEACTIVATED, NULL);
118 if (swc.manager->deactivate) {
119 swc.manager->deactivate();
120 }
121}
122
123EXPORT bool
124swc_cursor_position(int32_t *x, int32_t *y)
125{
126 if (x) {
127 *x = 0;
128 }
129 if (y) {
130 *y = 0;
131 }
132
133 if (!swc.seat || !swc.seat->pointer) {
134 return false;
135 }
136
137 if (x) {
138 *x = swc.seat->pointer->x;
139 }
140 if (y) {
141 *y = swc.seat->pointer->y;
142 }
143
144 return true;
145}
146
147EXPORT bool
148swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop,
149 const struct swc_manager *manager)
150{
151 swc.display = display;
152 swc.event_loop =
153 event_loop ? event_loop : wl_display_get_event_loop(display);
154 swc.manager = manager;
155 const char *default_seat = "seat0";
156 wl_signal_init(&swc.event_signal);
157
158 if (!launch_initialize()) {
159 ERROR("Could not connect to swc-launch\n");
160 goto error0;
161 }
162
163 if (!drm_initialize()) {
164 ERROR("Could not initialize DRM\n");
165 goto error1;
166 }
167
168 swc.shm = shm_create(display);
169 if (!swc.shm) {
170 ERROR("Could not initialize SHM\n");
171 goto error2;
172 }
173
174 if (!bindings_initialize()) {
175 ERROR("Could not initialize bindings\n");
176 goto error3;
177 }
178
179 swc.subcompositor = subcompositor_create(display);
180 if (!swc.subcompositor) {
181 ERROR("Could not initialize subcompositor\n");
182 goto error4;
183 }
184
185 if (!screens_initialize()) {
186 ERROR("Could not initialize screens\n");
187 goto error5;
188 }
189
190 if (!compositor_initialize()) {
191 ERROR("Could not initialize compositor\n");
192 goto error6;
193 }
194
195 swc.data_device_manager = data_device_manager_create(display);
196 if (!swc.data_device_manager) {
197 ERROR("Could not initialize data device manager\n");
198 goto error7;
199 }
200
201 swc.seat = seat_create(display, default_seat);
202 if (!swc.seat) {
203 ERROR("Could not initialize seat\n");
204 goto error8;
205 }
206
207 swc.shell = shell_create(display);
208 if (!swc.shell) {
209 ERROR("Could not initialize shell\n");
210 goto error9;
211 }
212
213 swc.xdg_shell = xdg_shell_create(display);
214 if (!swc.xdg_shell) {
215 ERROR("Could not initialize XDG shell\n");
216 goto error10;
217 }
218
219 swc.xdg_decoration_manager = xdg_decoration_manager_create(display);
220 if (!swc.xdg_decoration_manager) {
221 ERROR("Could not initialize XDG decoration manager\n");
222 goto error11;
223 }
224
225 swc.kde_decoration_manager = kde_decoration_manager_create(display);
226 if (!swc.kde_decoration_manager) {
227 ERROR("Could not initialize KDE decoration manager\n");
228 goto error12;
229 }
230
231 swc.layer_shell = layer_shell_create(display);
232 if (!swc.layer_shell) {
233 ERROR("Could not initialize layer shell\n");
234 goto error13;
235 }
236
237 swc.panel_manager = panel_manager_create(display);
238 if (!swc.panel_manager) {
239 ERROR("Could not initialize panel manager\n");
240 goto error14;
241 }
242
243 swc.snap_manager = snap_manager_create(display);
244 if (!swc.snap_manager) {
245 ERROR("Could not initialize snap manager\n");
246 goto error15;
247 }
248
249#ifdef ENABLE_XWAYLAND
250 if (!xserver_initialize()) {
251 ERROR("Could not initialize xwayland\n");
252 goto error16;
253 }
254#endif
255
256 swc.select_manager = select_manager_create(display);
257 if (!swc.select_manager) {
258 ERROR("Could not initialize select manager\n");
259 goto error17;
260 }
261
262 swc.xdg_output_manager = xdg_output_manager_create(display);
263 if (!swc.xdg_output_manager) {
264 ERROR("Could not initialize XDG output manager\n");
265 goto error17;
266 }
267
268 setup_compositor();
269
270 return true;
271
272error17:
273 wl_global_destroy(swc.select_manager);
274#ifdef ENABLE_XWAYLAND
275error16:
276#endif
277 wl_global_destroy(swc.snap_manager);
278error15:
279 wl_global_destroy(swc.panel_manager);
280error14:
281 wl_global_destroy(swc.layer_shell);
282error13:
283 wl_global_destroy(swc.kde_decoration_manager);
284error12:
285 wl_global_destroy(swc.xdg_decoration_manager);
286error11:
287 wl_global_destroy(swc.xdg_shell);
288error10:
289 wl_global_destroy(swc.shell);
290error9:
291 seat_destroy(swc.seat);
292error8:
293 wl_global_destroy(swc.data_device_manager);
294error7:
295 compositor_finalize();
296error6:
297 screens_finalize();
298error5:
299 wl_global_destroy(swc.subcompositor);
300error4:
301 bindings_finalize();
302error3:
303 shm_destroy(swc.shm);
304error2:
305 drm_finalize();
306error1:
307 launch_finalize();
308error0:
309 return false;
310}
311
312EXPORT void
313swc_finalize(void)
314{
315#ifdef ENABLE_XWAYLAND
316 xserver_finalize();
317#endif
318 wl_global_destroy(swc.xdg_output_manager);
319 wl_global_destroy(swc.snap_manager);
320 wl_global_destroy(swc.select_manager);
321 wl_global_destroy(swc.panel_manager);
322 wl_global_destroy(swc.layer_shell);
323 wl_global_destroy(swc.xdg_decoration_manager);
324 wl_global_destroy(swc.xdg_shell);
325 wl_global_destroy(swc.shell);
326 seat_destroy(swc.seat);
327 wl_global_destroy(swc.data_device_manager);
328 compositor_finalize();
329 screens_finalize();
330 bindings_finalize();
331 shm_destroy(swc.shm);
332 drm_finalize();
333 launch_finalize();
334}