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_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}