Changeset ddb844e in mainline for uspace/lib/gui/window.c
- Timestamp:
- 2020-07-03T23:00:34Z (5 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e79a025
- Parents:
- edb57bc6 (diff), 1a1c75e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/gui/window.c
redb57bc6 rddb844e 48 48 #include <adt/list.h> 49 49 50 #include <async.h>51 50 #include <loc.h> 52 51 … … 56 55 #include <draw/drawctx.h> 57 56 #include <draw/surface.h> 57 #include <display.h> 58 58 59 59 #include "common.h" … … 67 67 static sysarg_t header_min_width = 40; 68 68 static sysarg_t close_thickness = 20; 69 static sysarg_t corner_size = 24; 70 static sysarg_t window_initial_size = 1; 69 71 70 72 static pixel_t color_highlight = PIXEL(255, 255, 255, 255); … … 82 84 static pixel_t color_caption_focus = PIXEL(255, 255, 255, 255); 83 85 static pixel_t color_caption_unfocus = PIXEL(255, 207, 207, 207); 86 87 static void window_close_event(void *); 88 static void window_focus_event(void *); 89 static void window_kbd_event(void *, kbd_event_t *); 90 static void window_pos_event(void *, pos_event_t *); 91 static void window_resize_event(void *, gfx_rect_t *); 92 static void window_unfocus_event(void *); 93 94 static display_wnd_cb_t window_cb = { 95 .close_event = window_close_event, 96 .focus_event = window_focus_event, 97 .kbd_event = window_kbd_event, 98 .pos_event = window_pos_event, 99 .resize_event = window_resize_event, 100 .unfocus_event = window_unfocus_event 101 }; 102 103 static void set_cursor(window_t *window, display_stock_cursor_t cursor) 104 { 105 if (cursor != window->cursor) { 106 (void) display_window_set_cursor(window->dwindow, cursor); 107 window->cursor = cursor; 108 } 109 } 84 110 85 111 static void paint_internal(widget_t *widget) … … 258 284 static void root_handle_position_event(widget_t *widget, pos_event_t event) 259 285 { 286 gfx_coord2_t pos; 287 260 288 if (widget->window->is_decorated) { 261 289 sysarg_t width = widget->width; … … 263 291 264 292 bool btn_left = (event.btn_num == 1) && (event.type == POS_PRESS); 265 bool btn_right = (event.btn_num == 2) && (event.type == POS_PRESS);266 bool allowed_button = btn_left || btn_right;267 293 268 294 bool left = (event.hpos < border_thickness); … … 270 296 bool top = (event.vpos < border_thickness); 271 297 bool bottom = (event.vpos >= height - border_thickness); 298 bool edge = left || right || top || bottom; 299 300 bool cleft = (event.hpos < corner_size); 301 bool cright = (event.hpos >= width - corner_size); 302 bool ctop = (event.vpos < corner_size); 303 bool cbottom = (event.vpos >= height - corner_size); 304 272 305 bool header = (event.hpos >= border_thickness) && 273 306 (event.hpos < width - border_thickness) && … … 277 310 (event.hpos >= width - border_thickness - close_thickness); 278 311 279 if (top && left && allowed_button) { 280 window_grab_flags_t flags = GF_EMPTY; 281 flags |= GF_MOVE_X; 282 flags |= GF_MOVE_Y; 283 flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X; 284 flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y; 285 win_grab(widget->window->osess, event.pos_id, flags); 286 } else if (bottom && left && allowed_button) { 287 window_grab_flags_t flags = GF_EMPTY; 288 flags |= GF_MOVE_X; 289 flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X; 290 flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y; 291 win_grab(widget->window->osess, event.pos_id, flags); 292 } else if (bottom && right && allowed_button) { 293 window_grab_flags_t flags = GF_EMPTY; 294 flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X; 295 flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y; 296 win_grab(widget->window->osess, event.pos_id, flags); 297 } else if (top && right && allowed_button) { 298 window_grab_flags_t flags = GF_EMPTY; 299 flags |= GF_MOVE_Y; 300 flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X; 301 flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y; 302 win_grab(widget->window->osess, event.pos_id, flags); 303 } else if (top && allowed_button) { 304 window_grab_flags_t flags = GF_EMPTY; 305 flags |= GF_MOVE_Y; 306 flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y; 307 win_grab(widget->window->osess, event.pos_id, flags); 308 } else if (left && allowed_button) { 309 window_grab_flags_t flags = GF_EMPTY; 310 flags |= GF_MOVE_X; 311 flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X; 312 win_grab(widget->window->osess, event.pos_id, flags); 313 } else if (bottom && allowed_button) { 314 window_grab_flags_t flags = GF_EMPTY; 315 flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y; 316 win_grab(widget->window->osess, event.pos_id, flags); 317 } else if (right && allowed_button) { 318 window_grab_flags_t flags = GF_EMPTY; 319 flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X; 320 win_grab(widget->window->osess, event.pos_id, flags); 312 bool isresize = widget->window->is_resizable; 313 display_wnd_rsztype_t rsztype = 0; 314 315 if (edge && ctop && cleft) { 316 rsztype = display_wr_top_left; 317 } else if (edge && cbottom && cleft) { 318 rsztype = display_wr_bottom_left; 319 } else if (edge && cbottom && cright) { 320 rsztype = display_wr_bottom_right; 321 } else if (edge && ctop && cright) { 322 rsztype = display_wr_top_right; 323 } else if (top) { 324 rsztype = display_wr_top; 325 } else if (left) { 326 rsztype = display_wr_left; 327 } else if (bottom) { 328 rsztype = display_wr_bottom; 329 } else if (right) { 330 rsztype = display_wr_right; 331 } else { 332 isresize = false; 333 } 334 335 if (isresize) { 336 (void) set_cursor(widget->window, 337 display_cursor_from_wrsz(rsztype)); 338 } else { 339 (void) set_cursor(widget->window, dcurs_arrow); 340 } 341 342 pos.x = event.hpos; 343 pos.y = event.vpos; 344 345 if (isresize && btn_left) { 346 (void) display_window_resize_req( 347 widget->window->dwindow, rsztype, &pos); 321 348 } else if (close && btn_left) { 322 win _close_request(widget->window->osess);349 window_close(widget->window); 323 350 } else if (header && btn_left) { 324 window_grab_flags_t flags = GF_EMPTY; 325 flags |= GF_MOVE_X; 326 flags |= GF_MOVE_Y; 327 win_grab(widget->window->osess, event.pos_id, flags); 351 (void) display_window_move_req(widget->window->dwindow, 352 &pos); 328 353 } else { 329 354 list_foreach(widget->children, link, widget_t, child) { … … 370 395 sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags) 371 396 { 372 if (width < 2 * border_thickness + header_min_width) { 373 win_damage(win->osess, 0, 0, 0, 0); 374 return; 375 } 376 377 if (height < 2 * border_thickness + header_height) { 378 win_damage(win->osess, 0, 0, 0, 0); 379 return; 380 } 381 382 /* Allocate resources for new surface. */ 383 surface_t *new_surface = surface_create(width, height, NULL, 397 gfx_bitmap_params_t params; 398 gfx_bitmap_alloc_t alloc; 399 gfx_bitmap_t *new_bitmap = NULL; 400 gfx_coord2_t offs; 401 gfx_coord2_t dpos; 402 display_info_t dinfo; 403 gfx_rect_t drect; 404 gfx_rect_t nrect; 405 errno_t rc; 406 407 if (width < 2 * border_thickness + header_min_width) 408 return; 409 410 if (height < 2 * border_thickness + header_height) 411 return; 412 413 fibril_mutex_lock(&win->guard); 414 415 /* Deallocate old bitmap. */ 416 if (win->bitmap != NULL) { 417 gfx_bitmap_destroy(win->bitmap); 418 win->bitmap = NULL; 419 } 420 421 /* Deallocate old surface. */ 422 if (win->surface != NULL) { 423 surface_destroy(win->surface); 424 win->surface = NULL; 425 } 426 427 /* Place window, if appropriate */ 428 if (placement_flags != WINDOW_PLACEMENT_ANY) { 429 dpos.x = 0; 430 dpos.y = 0; 431 432 rc = display_get_info(win->display, &dinfo); 433 if (rc != EOK) { 434 fibril_mutex_unlock(&win->guard); 435 return; 436 } 437 438 drect = dinfo.rect; 439 440 if (placement_flags & WINDOW_PLACEMENT_LEFT) 441 dpos.x = drect.p0.x; 442 else if (placement_flags & WINDOW_PLACEMENT_CENTER_X) 443 dpos.x = (drect.p0.x + drect.p1.x - width) / 2; 444 else 445 dpos.x = drect.p1.x - width; 446 447 if (placement_flags & WINDOW_PLACEMENT_TOP) 448 dpos.y = drect.p0.y; 449 else if (placement_flags & WINDOW_PLACEMENT_CENTER_Y) 450 dpos.y = (drect.p0.y + drect.p1.y - height) / 2; 451 else 452 dpos.y = drect.p1.y - height; 453 454 (void) display_window_move(win->dwindow, &dpos); 455 } 456 457 /* Resize the display window. */ 458 offs.x = offset_x; 459 offs.y = offset_y; 460 nrect.p0.x = 0; 461 nrect.p0.y = 0; 462 nrect.p1.x = width; 463 nrect.p1.y = height; 464 465 rc = display_window_resize(win->dwindow, &offs, &nrect); 466 if (rc != EOK) { 467 fibril_mutex_unlock(&win->guard); 468 return; 469 } 470 471 gfx_bitmap_params_init(¶ms); 472 #ifndef CONFIG_WIN_DOUBLE_BUF 473 params.flags = bmpf_direct_output; 474 #else 475 params.flags = 0; 476 #endif 477 params.rect.p0.x = 0; 478 params.rect.p0.y = 0; 479 params.rect.p1.x = width; 480 params.rect.p1.y = height; 481 482 rc = gfx_bitmap_create(win->gc, ¶ms, NULL, &new_bitmap); 483 if (rc != EOK) { 484 if (rc == ENOTSUP) { 485 /* Direct output is not supported */ 486 params.flags &= ~bmpf_direct_output; 487 rc = gfx_bitmap_create(win->gc, ¶ms, NULL, &new_bitmap); 488 if (rc != EOK) { 489 fibril_mutex_unlock(&win->guard); 490 return; 491 } 492 } 493 } 494 495 rc = gfx_bitmap_get_alloc(new_bitmap, &alloc); 496 if (rc != EOK) { 497 fibril_mutex_unlock(&win->guard); 498 return; 499 } 500 501 /* Allocate new surface. */ 502 surface_t *new_surface = surface_create(width, height, alloc.pixels, 384 503 SURFACE_FLAG_SHARED); 385 if (!new_surface) 386 return; 387 388 /* Switch new and old surface. */ 389 fibril_mutex_lock(&win->guard); 390 surface_t *old_surface = win->surface; 504 if (!new_surface) { 505 gfx_bitmap_destroy(new_bitmap); 506 fibril_mutex_unlock(&win->guard); 507 return; 508 } 509 510 /* Switch in new surface and bitmap. */ 391 511 win->surface = new_surface; 512 win->bitmap = new_bitmap; 392 513 fibril_mutex_unlock(&win->guard); 393 514 … … 402 523 fibril_mutex_unlock(&win->guard); 403 524 404 /* Inform compositor about new surface. */ 405 errno_t rc = win_resize(win->osess, offset_x, offset_y, width, height, 406 placement_flags, surface_direct_access(new_surface)); 407 408 if (rc != EOK) { 409 /* Rollback to old surface. Reverse all changes. */ 410 411 sysarg_t old_width = 0; 412 sysarg_t old_height = 0; 413 if (old_surface) 414 surface_get_resolution(old_surface, &old_width, &old_height); 415 416 fibril_mutex_lock(&win->guard); 417 new_surface = win->surface; 418 win->surface = old_surface; 419 fibril_mutex_unlock(&win->guard); 420 421 win->root.rearrange(&win->root, 0, 0, old_width, old_height); 422 423 if (win->surface) { 424 fibril_mutex_lock(&win->guard); 425 surface_reset_damaged_region(win->surface); 426 fibril_mutex_unlock(&win->guard); 427 } 428 429 surface_destroy(new_surface); 430 } else { 431 /* Deallocate old surface. */ 432 if (old_surface) 433 surface_destroy(old_surface); 434 } 525 (void) gfx_bitmap_render(win->bitmap, NULL, NULL); 435 526 } 436 527 … … 443 534 { 444 535 sysarg_t x, y, width, height; 536 gfx_rect_t rect; 445 537 fibril_mutex_lock(&win->guard); 446 538 surface_get_damaged_region(win->surface, &x, &y, &width, &height); … … 449 541 450 542 if (width > 0 && height > 0) { 451 /* Notify compositor. */ 452 win_damage(win->osess, x, y, width, height); 543 rect.p0.x = x; 544 rect.p0.y = y; 545 rect.p1.x = x + width; 546 rect.p1.y = y + height; 547 548 if (win->bitmap != NULL) 549 (void) gfx_bitmap_render(win->bitmap, &rect, NULL); 453 550 } 454 551 } … … 472 569 win->focus = NULL; 473 570 474 win_close(win->osess); 475 async_hangup(win->isess); 476 async_hangup(win->osess); 571 gfx_bitmap_destroy(win->bitmap); 572 573 /* 574 * XXX Here we should properly destroy the IPC GC. We only have 575 * the generic GC so either it would need to be cast back or 576 * GC needs a virtual destructor. 577 */ 578 579 display_window_destroy(win->dwindow); 580 display_close(win->display); 477 581 478 582 while (!list_empty(&win->events.list)) { … … 506 610 break; 507 611 case ET_POSITION_EVENT: 508 if (!win->is_focused) {509 win->is_focused = true;510 handle_refresh(win);511 }512 612 deliver_position_event(win, event->data.pos); 513 613 break; … … 559 659 } 560 660 561 /* Input fetcher from compositor. Runs in own dedicated fibril. */562 static errno_t fetch_input(void *arg)563 {564 errno_t rc;565 bool terminate = false;566 window_t *win = (window_t *) arg;567 568 while (true) {569 window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));570 571 if (event) {572 rc = win_get_event(win->isess, event);573 if (rc == EOK) {574 terminate = (event->type == ET_WINDOW_CLOSE);575 link_initialize(&event->link);576 prodcons_produce(&win->events, &event->link);577 } else {578 free(event);579 terminate = true;580 }581 } else {582 terminate = true;583 }584 585 if (terminate) {586 break;587 }588 }589 590 return 0;591 }592 593 661 window_t *window_open(const char *winreg, const void *data, 594 662 window_flags_t flags, const char *caption) 595 663 { 596 window_t *win = (window_t *) malloc(sizeof(window_t)); 664 display_wnd_params_t wparams; 665 666 window_t *win = (window_t *) calloc(1, sizeof(window_t)); 597 667 if (!win) 598 668 return NULL; … … 600 670 win->is_main = flags & WINDOW_MAIN; 601 671 win->is_decorated = flags & WINDOW_DECORATED; 672 win->is_resizable = flags & WINDOW_RESIZEABLE; 602 673 win->is_focused = true; 603 674 prodcons_initialize(&win->events); … … 614 685 win->grab = NULL; 615 686 win->focus = NULL; 616 win->surface = NULL; 617 618 service_id_t reg_dsid; 619 errno_t rc = loc_service_get_id(winreg, ®_dsid, 0); 620 if (rc != EOK) { 687 win->cursor = dcurs_arrow; 688 689 /* Allocate resources for new surface. */ 690 win->surface = surface_create(window_initial_size, 691 window_initial_size, NULL, SURFACE_FLAG_SHARED); 692 if (win->surface == NULL) { 621 693 free(win); 622 694 return NULL; 623 695 } 624 696 625 async_sess_t *reg_sess =626 loc_service_connect(reg_dsid, INTERFACE_COMPOSITOR, 0);627 if (reg_sess == NULL) {697 errno_t rc = display_open(winreg, &win->display); 698 if (rc != EOK) { 699 surface_destroy(win->surface); 628 700 free(win); 629 701 return NULL; 630 702 } 631 703 632 service_id_t in_dsid; 633 service_id_t out_dsid; 634 rc = win_register(reg_sess, flags, &in_dsid, &out_dsid); 635 async_hangup(reg_sess); 704 /* Window dimensions are not know at this time */ 705 display_wnd_params_init(&wparams); 706 wparams.rect.p0.x = 0; 707 wparams.rect.p0.y = 0; 708 wparams.rect.p1.x = window_initial_size; 709 wparams.rect.p1.y = window_initial_size; 710 wparams.min_size.x = 2 * border_thickness + header_min_width; 711 wparams.min_size.y = 2 * border_thickness + header_height; 712 713 rc = display_window_create(win->display, &wparams, &window_cb, 714 (void *) win, &win->dwindow); 636 715 if (rc != EOK) { 716 display_close(win->display); 717 surface_destroy(win->surface); 637 718 free(win); 638 719 return NULL; 639 720 } 640 721 641 win->osess = loc_service_connect(out_dsid, INTERFACE_COMPOSITOR, 0); 642 if (win->osess == NULL) { 643 free(win); 644 return NULL; 645 } 646 647 win->isess = loc_service_connect(in_dsid, INTERFACE_COMPOSITOR, 0); 648 if (win->isess == NULL) { 649 async_hangup(win->osess); 722 rc = display_window_get_gc(win->dwindow, &win->gc); 723 if (rc != EOK) { 724 display_window_destroy(win->dwindow); 725 display_close(win->display); 726 surface_destroy(win->surface); 650 727 free(win); 651 728 return NULL; … … 724 801 { 725 802 fid_t ev_fid = fibril_create(event_loop, win); 726 fid_t fi_fid = fibril_create(fetch_input, win); 727 if (!ev_fid || !fi_fid) { 803 if (!ev_fid) { 728 804 return; 729 805 } 730 806 fibril_add_ready(ev_fid); 731 fibril_add_ready(fi_fid);732 807 } 733 808 … … 745 820 void window_close(window_t *win) 746 821 { 747 /* Request compositor to init closing cascade. */ 748 win_close_request(win->osess); 822 window_event_t *event; 823 824 event = (window_event_t *) calloc(1, sizeof(window_event_t)); 825 if (event == NULL) 826 return; 827 828 link_initialize(&event->link); 829 event->type = ET_WINDOW_CLOSE; 830 prodcons_produce(&win->events, &event->link); 831 } 832 833 static void window_close_event(void *arg) 834 { 835 window_t *win = (window_t *) arg; 836 837 window_close(win); 838 } 839 840 static void window_focus_event(void *arg) 841 { 842 window_t *win = (window_t *) arg; 843 window_event_t *event; 844 845 event = (window_event_t *) calloc(1, sizeof(window_event_t)); 846 if (event == NULL) 847 return; 848 849 link_initialize(&event->link); 850 event->type = ET_WINDOW_FOCUS; 851 prodcons_produce(&win->events, &event->link); 852 } 853 854 static void window_kbd_event(void *arg, kbd_event_t *kevent) 855 { 856 window_t *win = (window_t *) arg; 857 window_event_t *event; 858 859 event = (window_event_t *) calloc(1, sizeof(window_event_t)); 860 if (event == NULL) 861 return; 862 863 link_initialize(&event->link); 864 event->type = ET_KEYBOARD_EVENT; 865 event->data.kbd = *kevent; 866 prodcons_produce(&win->events, &event->link); 867 } 868 869 static void window_pos_event(void *arg, pos_event_t *pevent) 870 { 871 window_t *win = (window_t *) arg; 872 window_event_t *event; 873 874 event = (window_event_t *) calloc(1, sizeof(window_event_t)); 875 if (event == NULL) 876 return; 877 878 link_initialize(&event->link); 879 event->type = ET_POSITION_EVENT; 880 event->data.pos = *pevent; 881 prodcons_produce(&win->events, &event->link); 882 } 883 884 static void window_resize_event(void *arg, gfx_rect_t *nrect) 885 { 886 window_t *win = (window_t *) arg; 887 window_event_t *event; 888 889 if (!win->is_resizable) 890 return; 891 892 event = (window_event_t *) calloc(1, sizeof(window_event_t)); 893 if (event == NULL) 894 return; 895 896 link_initialize(&event->link); 897 event->type = ET_WINDOW_RESIZE; 898 event->data.resize.offset_x = nrect->p0.x; 899 event->data.resize.offset_y = nrect->p0.y; 900 event->data.resize.width = nrect->p1.x - nrect->p0.x; 901 event->data.resize.height = nrect->p1.y - nrect->p0.y; 902 event->data.resize.placement_flags = WINDOW_PLACEMENT_ANY; 903 prodcons_produce(&win->events, &event->link); 904 } 905 906 static void window_unfocus_event(void *arg) 907 { 908 window_t *win = (window_t *) arg; 909 window_event_t *event; 910 911 event = (window_event_t *) calloc(1, sizeof(window_event_t)); 912 if (event == NULL) 913 return; 914 915 link_initialize(&event->link); 916 event->type = ET_WINDOW_UNFOCUS; 917 prodcons_produce(&win->events, &event->link); 749 918 } 750 919
Note:
See TracChangeset
for help on using the changeset viewer.