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 }