main shrub/neuswc / libswc / swc.c
  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}