swc

(Pinephone) swc with touch and other mobile stuff
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

compositor.c (24091B)


      1 /* swc: libswc/compositor.c
      2  *
      3  * Copyright (c) 2013-2020 Michael Forney
      4  *
      5  * Based in part upon compositor.c from weston, which is:
      6  *
      7  *     Copyright © 2010-2011 Intel Corporation
      8  *     Copyright © 2008-2011 Kristian Høgsberg
      9  *     Copyright © 2012 Collabora, Ltd.
     10  *
     11  * Permission is hereby granted, free of charge, to any person obtaining a copy
     12  * of this software and associated documentation files (the "Software"), to deal
     13  * in the Software without restriction, including without limitation the rights
     14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     15  * copies of the Software, and to permit persons to whom the Software is
     16  * furnished to do so, subject to the following conditions:
     17  *
     18  * The above copyright notice and this permission notice shall be included in
     19  * all copies or substantial portions of the Software.
     20  *
     21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     27  * SOFTWARE.
     28  */
     29 
     30 #include "swc.h"
     31 #include "compositor.h"
     32 #include "data_device_manager.h"
     33 #include "drm.h"
     34 #include "event.h"
     35 #include "internal.h"
     36 #include "input_method.h"
     37 #include "launch.h"
     38 #include "output.h"
     39 #include "pointer.h"
     40 #include "region.h"
     41 #include "screen.h"
     42 #include "seat.h"
     43 #include "shm.h"
     44 #include "surface.h"
     45 #include "touch.h"
     46 #include "text_input.h"
     47 #include "util.h"
     48 #include "view.h"
     49 
     50 #include <errno.h>
     51 #include <stdlib.h>
     52 #include <stdio.h>
     53 #include <assert.h>
     54 #include <wld/wld.h>
     55 #include <wld/drm.h>
     56 #include <xkbcommon/xkbcommon-keysyms.h>
     57 
     58 struct target {
     59 	struct wld_surface *surface;
     60 	struct wld_buffer *next_buffer, *current_buffer;
     61 	struct view *view;
     62 	struct view_handler view_handler;
     63 	uint32_t mask;
     64 
     65 	struct wl_listener screen_destroy_listener;
     66 };
     67 
     68 static bool handle_pointer_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t x, wl_fixed_t y);
     69 static bool handle_touch_down(struct touch_handler *handler, uint32_t time, int32_t slot, wl_fixed_t x, wl_fixed_t y);
     70 static void perform_update(void *data);
     71 
     72 static struct pointer_handler pointer_handler = {
     73 	.motion = handle_pointer_motion,
     74 };
     75 
     76 /* TODO */
     77 static struct touch_handler touch_handler = {
     78 	.down = handle_touch_down,
     79 };
     80 
     81 static struct {
     82 	struct wl_list views;
     83 	pixman_region32_t damage, opaque;
     84 	struct wl_listener swc_listener;
     85 
     86 	/* A mask of screens that have been repainted but are waiting on a page flip. */
     87 	uint32_t pending_flips;
     88 
     89 	/* A mask of screens that are scheduled to be repainted on the next idle. */
     90 	uint32_t scheduled_updates;
     91 
     92 	bool updating;
     93 	struct wl_global *global;
     94 } compositor;
     95 
     96 struct swc_compositor swc_compositor = {
     97 	.pointer_handler = &pointer_handler,
     98 	.touch_handler = &touch_handler,
     99 };
    100 
    101 static void
    102 handle_screen_destroy(struct wl_listener *listener, void *data)
    103 {
    104 	struct target *target = wl_container_of(listener, target, screen_destroy_listener);
    105 
    106 	wld_destroy_surface(target->surface);
    107 	free(target);
    108 }
    109 
    110 static struct target *
    111 target_get(struct screen *screen)
    112 {
    113 	struct wl_listener *listener = wl_signal_get(&screen->destroy_signal, &handle_screen_destroy);
    114 	struct target *target;
    115 
    116 	return listener ? wl_container_of(listener, target, screen_destroy_listener) : NULL;
    117 }
    118 
    119 static void
    120 handle_screen_frame(struct view_handler *handler, uint32_t time)
    121 {
    122 	struct target *target = wl_container_of(handler, target, view_handler);
    123 	struct compositor_view *view;
    124 
    125 	compositor.pending_flips &= ~target->mask;
    126 
    127 	wl_list_for_each (view, &compositor.views, link) {
    128 		if (view->visible && view->base.screens & target->mask)
    129 			view_frame(&view->base, time);
    130 	}
    131 
    132 	if (target->current_buffer)
    133 		wld_surface_release(target->surface, target->current_buffer);
    134 
    135 	target->current_buffer = target->next_buffer;
    136 
    137 	/* If we had scheduled updates that couldn't run because we were waiting on a
    138 	 * page flip, run them now. If the compositor is currently updating, then the
    139 	 * frame finished immediately, and we can be sure that there are no pending
    140 	 * updates. */
    141 	if (compositor.scheduled_updates && !compositor.updating)
    142 		perform_update(NULL);
    143 }
    144 
    145 static const struct view_handler_impl screen_view_handler = {
    146 	.frame = handle_screen_frame,
    147 };
    148 
    149 static int
    150 target_swap_buffers(struct target *target)
    151 {
    152 	target->next_buffer = wld_surface_take(target->surface);
    153 	return view_attach(target->view, target->next_buffer);
    154 }
    155 
    156 static struct target *
    157 target_new(struct screen *screen)
    158 {
    159 	struct target *target;
    160 	struct swc_rectangle *geom = &screen->base.geometry;
    161 
    162 	if (!(target = malloc(sizeof(*target))))
    163 		goto error0;
    164 
    165 	target->surface = wld_create_surface(swc.drm->context, geom->width, geom->height, WLD_FORMAT_XRGB8888, WLD_DRM_FLAG_SCANOUT);
    166 
    167 	if (!target->surface)
    168 		goto error1;
    169 
    170 	target->view = &screen->planes.primary.view;
    171 	target->view_handler.impl = &screen_view_handler;
    172 	wl_list_insert(&target->view->handlers, &target->view_handler.link);
    173 	target->current_buffer = NULL;
    174 	target->mask = screen_mask(screen);
    175 
    176 	target->screen_destroy_listener.notify = &handle_screen_destroy;
    177 	wl_signal_add(&screen->destroy_signal, &target->screen_destroy_listener);
    178 
    179 	return target;
    180 
    181 error1:
    182 	free(target);
    183 error0:
    184 	return NULL;
    185 }
    186 
    187 /* Rendering {{{ */
    188 
    189 static void
    190 repaint_view(struct target *target, struct compositor_view *view, pixman_region32_t *damage)
    191 {
    192 	pixman_region32_t view_region, view_damage, border_damage;
    193 	const struct swc_rectangle *geom = &view->base.geometry, *target_geom = &target->view->geometry;
    194 
    195 	if (!view->base.buffer)
    196 		return;
    197 
    198 	pixman_region32_init_rect(&view_region, geom->x, geom->y, geom->width, geom->height);
    199 	pixman_region32_init_with_extents(&view_damage, &view->extents);
    200 	pixman_region32_init(&border_damage);
    201 
    202 	pixman_region32_intersect(&view_damage, &view_damage, damage);
    203 	pixman_region32_subtract(&view_damage, &view_damage, &view->clip);
    204 	pixman_region32_subtract(&border_damage, &view_damage, &view_region);
    205 	pixman_region32_intersect(&view_damage, &view_damage, &view_region);
    206 
    207 	pixman_region32_fini(&view_region);
    208 
    209 	if (pixman_region32_not_empty(&view_damage)) {
    210 		pixman_region32_translate(&view_damage, -geom->x, -geom->y);
    211 		wld_copy_region(swc.drm->renderer, view->buffer, geom->x - target_geom->x, geom->y - target_geom->y, &view_damage);
    212 	}
    213 
    214 	pixman_region32_fini(&view_damage);
    215 
    216 	/* Draw border */
    217 	if (pixman_region32_not_empty(&border_damage)) {
    218 		pixman_region32_translate(&border_damage, -target_geom->x, -target_geom->y);
    219 		wld_fill_region(swc.drm->renderer, view->border.color, &border_damage);
    220 	}
    221 
    222 	pixman_region32_fini(&border_damage);
    223 }
    224 
    225 static void
    226 renderer_repaint(struct target *target, pixman_region32_t *damage, pixman_region32_t *base_damage, struct wl_list *views)
    227 {
    228 	struct compositor_view *view;
    229 
    230 	DEBUG("Rendering to target { x: %d, y: %d, w: %u, h: %u }\n",
    231 	      target->view->geometry.x, target->view->geometry.y,
    232 	      target->view->geometry.width, target->view->geometry.height);
    233 
    234 	wld_set_target_surface(swc.drm->renderer, target->surface);
    235 
    236 	/* Paint base damage black. */
    237 	if (pixman_region32_not_empty(base_damage)) {
    238 		pixman_region32_translate(base_damage, -target->view->geometry.x, -target->view->geometry.y);
    239 		wld_fill_region(swc.drm->renderer, 0xff000000, base_damage);
    240 	}
    241 
    242 	wl_list_for_each_reverse (view, views, link) {
    243 		if (view->visible && view->base.screens & target->mask)
    244 			repaint_view(target, view, damage);
    245 	}
    246 
    247 	wld_flush(swc.drm->renderer);
    248 }
    249 
    250 static int
    251 renderer_attach(struct compositor_view *view, struct wld_buffer *client_buffer)
    252 {
    253 	struct wld_buffer *buffer;
    254 	bool was_proxy = view->buffer != view->base.buffer;
    255 	bool needs_proxy = client_buffer && !(wld_capabilities(swc.drm->renderer, client_buffer) & WLD_CAPABILITY_READ);
    256 	bool resized = view->buffer && client_buffer && (view->buffer->width != client_buffer->width || view->buffer->height != client_buffer->height);
    257 
    258 	if (client_buffer) {
    259 		/* Create a proxy buffer if necessary (for example a hardware buffer backing
    260 		 * a SHM buffer). */
    261 		if (needs_proxy) {
    262 			if (!was_proxy || resized) {
    263 				DEBUG("Creating a proxy buffer\n");
    264 				buffer = wld_create_buffer(swc.drm->context, client_buffer->width, client_buffer->height, client_buffer->format, WLD_FLAG_MAP);
    265 
    266 				if (!buffer)
    267 					return -ENOMEM;
    268 			} else {
    269 				/* Otherwise we can keep the original proxy buffer. */
    270 				buffer = view->buffer;
    271 			}
    272 		} else {
    273 			buffer = client_buffer;
    274 		}
    275 	} else {
    276 		buffer = NULL;
    277 	}
    278 
    279 	/* If we no longer need a proxy buffer, or the original buffer is of a
    280 	 * different size, destroy the old proxy image. */
    281 	if (view->buffer && ((!needs_proxy && was_proxy) || (needs_proxy && resized)))
    282 		wld_buffer_unreference(view->buffer);
    283 
    284 	view->buffer = buffer;
    285 
    286 	return 0;
    287 }
    288 
    289 static void
    290 renderer_flush_view(struct compositor_view *view)
    291 {
    292 	if (view->buffer == view->base.buffer)
    293 		return;
    294 
    295 	wld_set_target_buffer(swc.shm->renderer, view->buffer);
    296 	wld_copy_region(swc.shm->renderer, view->base.buffer, 0, 0, &view->surface->state.damage);
    297 	wld_flush(swc.shm->renderer);
    298 }
    299 
    300 /* }}} */
    301 
    302 /* Surface Views {{{ */
    303 
    304 /**
    305  * Adds the region below a view to the compositor's damaged region,
    306  * taking into account its clip region.
    307  */
    308 static void
    309 damage_below_view(struct compositor_view *view)
    310 {
    311 	pixman_region32_t damage_below;
    312 
    313 	pixman_region32_init_with_extents(&damage_below, &view->extents);
    314 	pixman_region32_subtract(&damage_below, &damage_below, &view->clip);
    315 	pixman_region32_union(&compositor.damage, &compositor.damage, &damage_below);
    316 	pixman_region32_fini(&damage_below);
    317 }
    318 
    319 /**
    320  * Completely damages the surface and its border.
    321  */
    322 static void
    323 damage_view(struct compositor_view *view)
    324 {
    325 	damage_below_view(view);
    326 	view->border.damaged = true;
    327 }
    328 
    329 static void
    330 update_extents(struct compositor_view *view)
    331 {
    332 	view->extents.x1 = view->base.geometry.x - view->border.width;
    333 	view->extents.y1 = view->base.geometry.y - view->border.width;
    334 	view->extents.x2 = view->base.geometry.x + view->base.geometry.width + view->border.width;
    335 	view->extents.y2 = view->base.geometry.y + view->base.geometry.height + view->border.width;
    336 
    337 	/* Damage border. */
    338 	view->border.damaged = true;
    339 }
    340 
    341 static void
    342 schedule_updates(uint32_t screens)
    343 {
    344 	if (compositor.scheduled_updates == 0)
    345 		wl_event_loop_add_idle(swc.event_loop, &perform_update, NULL);
    346 
    347 	if (screens == -1) {
    348 		struct screen *screen;
    349 
    350 		screens = 0;
    351 		wl_list_for_each (screen, &swc.screens, link)
    352 			screens |= screen_mask(screen);
    353 	}
    354 
    355 	compositor.scheduled_updates |= screens;
    356 }
    357 
    358 static bool
    359 update(struct view *base)
    360 {
    361 	struct compositor_view *view = (void *)base;
    362 
    363 	if (!swc.active || !view->visible)
    364 		return false;
    365 
    366 	schedule_updates(view->base.screens);
    367 
    368 	return true;
    369 }
    370 
    371 static int
    372 attach(struct view *base, struct wld_buffer *buffer)
    373 {
    374 	struct compositor_view *view = (void *)base;
    375 	pixman_box32_t old_extents;
    376 	pixman_region32_t old, new, both;
    377 	int ret;
    378 
    379 	if ((ret = renderer_attach(view, buffer)) < 0)
    380 		return ret;
    381 
    382 	/* Schedule updates on the screens the view was previously
    383 	 * visible on. */
    384 	update(&view->base);
    385 
    386 	if (view_set_size_from_buffer(&view->base, buffer)) {
    387 		/* The view was resized. */
    388 		old_extents = view->extents;
    389 		update_extents(view);
    390 
    391 		if (view->visible) {
    392 			/* Damage the region that was newly uncovered
    393 			 * or covered, minus the clip region. */
    394 			pixman_region32_init_with_extents(&old, &old_extents);
    395 			pixman_region32_init_with_extents(&new, &view->extents);
    396 			pixman_region32_init(&both);
    397 			pixman_region32_intersect(&both, &old, &new);
    398 			pixman_region32_union(&new, &old, &new);
    399 			pixman_region32_subtract(&new, &new, &both);
    400 			pixman_region32_subtract(&new, &new, &view->clip);
    401 			pixman_region32_union(&compositor.damage, &compositor.damage, &new);
    402 			pixman_region32_fini(&old);
    403 			pixman_region32_fini(&new);
    404 			pixman_region32_fini(&both);
    405 
    406 			view_update_screens(&view->base);
    407 			update(&view->base);
    408 		}
    409 	}
    410 
    411 	return 0;
    412 }
    413 
    414 static bool
    415 move(struct view *base, int32_t x, int32_t y)
    416 {
    417 	struct compositor_view *view = (void *)base;
    418 
    419 	if (view->visible) {
    420 		damage_below_view(view);
    421 		update(&view->base);
    422 	}
    423 
    424 	if (view_set_position(&view->base, x, y)) {
    425 		update_extents(view);
    426 
    427 		if (view->visible) {
    428 			/* Assume worst-case no clipping until we draw the next frame (in case the
    429 			 * surface gets moved again before that). */
    430 			pixman_region32_init(&view->clip);
    431 
    432 			view_update_screens(&view->base);
    433 			damage_below_view(view);
    434 			update(&view->base);
    435 		}
    436 	}
    437 
    438 	return true;
    439 }
    440 
    441 static const struct view_impl view_impl = {
    442 	.update = update,
    443 	.attach = attach,
    444 	.move = move,
    445 };
    446 
    447 struct compositor_view *
    448 compositor_create_view(struct surface *surface)
    449 {
    450 	struct compositor_view *view;
    451 
    452 	view = malloc(sizeof(*view));
    453 
    454 	if (!view)
    455 		return NULL;
    456 
    457 	view_initialize(&view->base, &view_impl);
    458 	view->surface = surface;
    459 	view->buffer = NULL;
    460 	view->window = NULL;
    461 	view->parent = NULL;
    462 	view->visible = false;
    463 	view->extents.x1 = 0;
    464 	view->extents.y1 = 0;
    465 	view->extents.x2 = 0;
    466 	view->extents.y2 = 0;
    467 	view->border.width = 0;
    468 	view->border.color = 0x000000;
    469 	view->border.damaged = false;
    470 	pixman_region32_init(&view->clip);
    471 	wl_signal_init(&view->destroy_signal);
    472 	surface_set_view(surface, &view->base);
    473 	wl_list_insert(&compositor.views, &view->link);
    474 
    475 	return view;
    476 }
    477 
    478 void
    479 compositor_view_destroy(struct compositor_view *view)
    480 {
    481 	wl_signal_emit(&view->destroy_signal, NULL);
    482 	compositor_view_hide(view);
    483 	surface_set_view(view->surface, NULL);
    484 	view_finalize(&view->base);
    485 	pixman_region32_fini(&view->clip);
    486 	wl_list_remove(&view->link);
    487 	free(view);
    488 }
    489 
    490 struct compositor_view *
    491 compositor_view(struct view *view)
    492 {
    493 	return view->impl == &view_impl ? (struct compositor_view *)view : NULL;
    494 }
    495 
    496 void
    497 compositor_view_set_parent(struct compositor_view *view, struct compositor_view *parent)
    498 {
    499 	view->parent = view;
    500 
    501 	if (parent->visible)
    502 		compositor_view_show(view);
    503 	else
    504 		compositor_view_hide(view);
    505 }
    506 
    507 void
    508 compositor_view_show(struct compositor_view *view)
    509 {
    510 	struct compositor_view *other;
    511 
    512 	if (view->visible)
    513 		return;
    514 
    515 	view->visible = true;
    516 	view_update_screens(&view->base);
    517 
    518 	/* Assume worst-case no clipping until we draw the next frame (in case the
    519 	 * surface gets moved before that. */
    520 	pixman_region32_clear(&view->clip);
    521 	damage_view(view);
    522 	update(&view->base);
    523 
    524 	wl_list_for_each (other, &compositor.views, link) {
    525 		if (other->parent == view)
    526 			compositor_view_show(other);
    527 	}
    528 }
    529 
    530 void
    531 compositor_view_hide(struct compositor_view *view)
    532 {
    533 	struct compositor_view *other;
    534 
    535 	if (!view->visible)
    536 		return;
    537 
    538 	/* Update all the screens the view was on. */
    539 	update(&view->base);
    540 	damage_below_view(view);
    541 
    542 	view_set_screens(&view->base, 0);
    543 	view->visible = false;
    544 
    545 	wl_list_for_each (other, &compositor.views, link) {
    546 		if (other->parent == view)
    547 			compositor_view_hide(other);
    548 	}
    549 }
    550 
    551 void
    552 compositor_view_set_border_width(struct compositor_view *view, uint32_t width)
    553 {
    554 	if (view->border.width == width)
    555 		return;
    556 
    557 	view->border.width = width;
    558 	view->border.damaged = true;
    559 
    560 	/* XXX: Damage above surface for transparent surfaces? */
    561 
    562 	update_extents(view);
    563 	update(&view->base);
    564 }
    565 
    566 void
    567 compositor_view_set_border_color(struct compositor_view *view, uint32_t color)
    568 {
    569 	if (view->border.color == color)
    570 		return;
    571 
    572 	view->border.color = color;
    573 	view->border.damaged = true;
    574 
    575 	/* XXX: Damage above surface for transparent surfaces? */
    576 
    577 	update(&view->base);
    578 }
    579 
    580 /* }}} */
    581 
    582 static void
    583 calculate_damage(void)
    584 {
    585 	struct compositor_view *view;
    586 	struct swc_rectangle *geom;
    587 	pixman_region32_t surface_opaque, *surface_damage;
    588 
    589 	pixman_region32_clear(&compositor.opaque);
    590 	pixman_region32_init(&surface_opaque);
    591 
    592 	/* Go through views top-down to calculate clipping regions. */
    593 	wl_list_for_each (view, &compositor.views, link) {
    594 		if (!view->visible)
    595 			continue;
    596 
    597 		geom = &view->base.geometry;
    598 
    599 		/* Clip the surface by the opaque region covering it. */
    600 		pixman_region32_copy(&view->clip, &compositor.opaque);
    601 
    602 		/* Translate the opaque region to global coordinates. */
    603 		pixman_region32_copy(&surface_opaque, &view->surface->state.opaque);
    604 		pixman_region32_translate(&surface_opaque, geom->x, geom->y);
    605 
    606 		/* Add the surface's opaque region to the accumulated opaque region. */
    607 		pixman_region32_union(&compositor.opaque, &compositor.opaque, &surface_opaque);
    608 
    609 		surface_damage = &view->surface->state.damage;
    610 
    611 		if (pixman_region32_not_empty(surface_damage)) {
    612 			renderer_flush_view(view);
    613 
    614 			/* Translate surface damage to global coordinates. */
    615 			pixman_region32_translate(surface_damage, geom->x, geom->y);
    616 
    617 			/* Add the surface damage to the compositor damage. */
    618 			pixman_region32_union(&compositor.damage, &compositor.damage, surface_damage);
    619 			pixman_region32_clear(surface_damage);
    620 		}
    621 
    622 		if (view->border.damaged) {
    623 			pixman_region32_t border_region, view_region;
    624 
    625 			pixman_region32_init_with_extents(&border_region, &view->extents);
    626 			pixman_region32_init_rect(&view_region, geom->x, geom->y, geom->width, geom->height);
    627 
    628 			pixman_region32_subtract(&border_region, &border_region, &view_region);
    629 
    630 			pixman_region32_union(&compositor.damage, &compositor.damage, &border_region);
    631 
    632 			pixman_region32_fini(&border_region);
    633 			pixman_region32_fini(&view_region);
    634 
    635 			view->border.damaged = false;
    636 		}
    637 	}
    638 
    639 	pixman_region32_fini(&surface_opaque);
    640 }
    641 
    642 static void
    643 update_screen(struct screen *screen)
    644 {
    645 	struct target *target;
    646 	const struct swc_rectangle *geom = &screen->base.geometry;
    647 	pixman_region32_t damage, *total_damage;
    648 
    649 	if (!(compositor.scheduled_updates & screen_mask(screen)))
    650 		return;
    651 
    652 	if (!(target = target_get(screen)))
    653 		return;
    654 
    655 	pixman_region32_init(&damage);
    656 	pixman_region32_intersect_rect(&damage, &compositor.damage, geom->x, geom->y, geom->width, geom->height);
    657 	pixman_region32_translate(&damage, -geom->x, -geom->y);
    658 	total_damage = wld_surface_damage(target->surface, &damage);
    659 
    660 	/* Don't repaint the screen if it is waiting for a page flip. */
    661 	if (compositor.pending_flips & screen_mask(screen)) {
    662 		pixman_region32_fini(&damage);
    663 		return;
    664 	}
    665 
    666 	pixman_region32_t base_damage;
    667 	pixman_region32_copy(&damage, total_damage);
    668 	pixman_region32_translate(&damage, geom->x, geom->y);
    669 	pixman_region32_init(&base_damage);
    670 	pixman_region32_subtract(&base_damage, &damage, &compositor.opaque);
    671 	renderer_repaint(target, &damage, &base_damage, &compositor.views);
    672 	pixman_region32_fini(&damage);
    673 	pixman_region32_fini(&base_damage);
    674 
    675 	switch (target_swap_buffers(target)) {
    676 	case -EACCES:
    677 		/* If we get an EACCES, it is because this session is being deactivated, but
    678 		 * we haven't yet received the deactivate signal from swc-launch. */
    679 		swc_deactivate();
    680 		break;
    681 	case 0:
    682 		compositor.pending_flips |= screen_mask(screen);
    683 		break;
    684 	}
    685 }
    686 
    687 static void
    688 perform_update(void *data)
    689 {
    690 	struct screen *screen;
    691 	uint32_t updates = compositor.scheduled_updates & ~compositor.pending_flips;
    692 
    693 	if (!swc.active || !updates)
    694 		return;
    695 
    696 	DEBUG("Performing update\n");
    697 
    698 	compositor.updating = true;
    699 	calculate_damage();
    700 
    701 	wl_list_for_each (screen, &swc.screens, link)
    702 		update_screen(screen);
    703 
    704 	/* XXX: Should assert that all damage was covered by some output */
    705 	pixman_region32_clear(&compositor.damage);
    706 	compositor.scheduled_updates &= ~updates;
    707 	compositor.updating = false;
    708 }
    709 
    710 bool
    711 handle_pointer_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_fixed_t fy)
    712 {
    713 	struct compositor_view *view;
    714 	bool found = false;
    715 	int32_t x = wl_fixed_to_int(fx), y = wl_fixed_to_int(fy);
    716 	struct swc_rectangle *geom;
    717 
    718 	/* If buttons are pressed, don't change pointer focus. */
    719 	if (swc.seat->pointer->buttons.size > 0)
    720 		return false;
    721 
    722 	wl_list_for_each (view, &compositor.views, link) {
    723 		if (!view->visible)
    724 			continue;
    725 		geom = &view->base.geometry;
    726 		if (rectangle_contains_point(geom, x, y)) {
    727 			if (pixman_region32_contains_point(&view->surface->state.input, x - geom->x, y - geom->y, NULL)) {
    728 				found = true;
    729 				break;
    730 			}
    731 		}
    732 	}
    733 
    734 	pointer_set_focus(swc.seat->pointer, found ? view : NULL);
    735 
    736 	return false;
    737 }
    738 
    739 bool
    740 handle_touch_down(struct touch_handler *handler, uint32_t time, int32_t slot, wl_fixed_t fx, wl_fixed_t fy)
    741 {
    742 	struct compositor_view *view;
    743 	bool found = false;
    744 	int32_t x = wl_fixed_to_int(fx), y = wl_fixed_to_int(fy);
    745 	struct swc_rectangle *geom;
    746 	struct text_input_manager *timanager = wl_global_get_user_data(swc.text_input_manager);
    747 	struct wl_client *client = NULL;
    748 
    749 	wl_list_for_each (view, &compositor.views, link) {
    750 		if (!view->visible)
    751 			continue;
    752 		geom = &view->base.geometry;
    753 		if (rectangle_contains_point(geom, x, y)) {
    754 			if (pixman_region32_contains_point(&view->surface->state.input, x - geom->x, y - geom->y, NULL)) {
    755 				found = true;
    756 				client = wl_resource_get_client(view->surface->resource);
    757 				break;
    758 			}
    759 		}
    760 	}
    761 
    762 	if (found) {
    763 		touch_point_add(swc.seat->touch, view, slot, fx, fy);
    764 		touch_set_focus(swc.seat->touch, view);
    765 	}
    766 	if (swc.seat->input_method && swc.seat->input_method->client != client) {
    767 		text_input_set_focus(timanager, view);
    768 	}
    769 
    770 	return false;
    771 }
    772 
    773 static void
    774 handle_terminate(void *data, uint32_t time, uint32_t value, uint32_t state)
    775 {
    776 	if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
    777 		wl_display_terminate(swc.display);
    778 }
    779 
    780 static void
    781 handle_switch_vt(void *data, uint32_t time, uint32_t value, uint32_t state)
    782 {
    783 	uint8_t vt = value - XKB_KEY_XF86Switch_VT_1 + 1;
    784 
    785 	if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
    786 		launch_activate_vt(vt);
    787 }
    788 
    789 static void
    790 handle_swc_event(struct wl_listener *listener, void *data)
    791 {
    792 	struct event *event = data;
    793 
    794 	switch (event->type) {
    795 	case SWC_EVENT_ACTIVATED:
    796 		schedule_updates(-1);
    797 		break;
    798 	case SWC_EVENT_DEACTIVATED:
    799 		compositor.scheduled_updates = 0;
    800 		break;
    801 	}
    802 }
    803 
    804 static void
    805 create_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id)
    806 {
    807 	struct surface *surface;
    808 
    809 	/* Initialize surface. */
    810 	surface = surface_new(client, wl_resource_get_version(resource), id);
    811 
    812 	if (!surface) {
    813 		wl_resource_post_no_memory(resource);
    814 		return;
    815 	}
    816 
    817 	wl_signal_emit(&swc_compositor.signal.new_surface, surface);
    818 }
    819 
    820 static void
    821 create_region(struct wl_client *client, struct wl_resource *resource, uint32_t id)
    822 {
    823 	if (!region_new(client, wl_resource_get_version(resource), id))
    824 		wl_resource_post_no_memory(resource);
    825 }
    826 
    827 static const struct wl_compositor_interface compositor_impl = {
    828 	.create_surface = create_surface,
    829 	.create_region = create_region,
    830 };
    831 
    832 static void
    833 bind_compositor(struct wl_client *client, void *data, uint32_t version, uint32_t id)
    834 {
    835 	struct wl_resource *resource;
    836 
    837 	resource = wl_resource_create(client, &wl_compositor_interface, version, id);
    838 	if (!resource) {
    839 		wl_client_post_no_memory(client);
    840 		return;
    841 	}
    842 	wl_resource_set_implementation(resource, &compositor_impl, NULL, NULL);
    843 }
    844 
    845 bool
    846 compositor_initialize(void)
    847 {
    848 	struct screen *screen;
    849 	uint32_t keysym;
    850 
    851 	compositor.global = wl_global_create(swc.display, &wl_compositor_interface, 4, NULL, &bind_compositor);
    852 
    853 	if (!compositor.global)
    854 		return false;
    855 
    856 	compositor.scheduled_updates = 0;
    857 	compositor.pending_flips = 0;
    858 	compositor.updating = false;
    859 	pixman_region32_init(&compositor.damage);
    860 	pixman_region32_init(&compositor.opaque);
    861 	wl_list_init(&compositor.views);
    862 	wl_signal_init(&swc_compositor.signal.new_surface);
    863 	compositor.swc_listener.notify = &handle_swc_event;
    864 	wl_signal_add(&swc.event_signal, &compositor.swc_listener);
    865 
    866 	wl_list_for_each (screen, &swc.screens, link)
    867 		target_new(screen);
    868 	if (swc.active)
    869 		schedule_updates(-1);
    870 
    871 	swc_add_binding(SWC_BINDING_KEY, SWC_MOD_CTRL | SWC_MOD_ALT, XKB_KEY_BackSpace, &handle_terminate, NULL);
    872 
    873 	for (keysym = XKB_KEY_XF86Switch_VT_1; keysym <= XKB_KEY_XF86Switch_VT_12; ++keysym)
    874 		swc_add_binding(SWC_BINDING_KEY, SWC_MOD_ANY, keysym, &handle_switch_vt, NULL);
    875 
    876 	return true;
    877 }
    878 
    879 void
    880 compositor_finalize(void)
    881 {
    882 	pixman_region32_fini(&compositor.damage);
    883 	pixman_region32_fini(&compositor.opaque);
    884 	wl_global_destroy(compositor.global);
    885 }