Changes in uspace/lib/gui/window.c [de19d4a:2bb6d04] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/gui/window.c
rde19d4a r2bb6d04 48 48 #include <adt/list.h> 49 49 50 #include <async.h> 50 51 #include <loc.h> 51 52 … … 55 56 #include <draw/drawctx.h> 56 57 #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;71 69 72 70 static pixel_t color_highlight = PIXEL(255, 255, 255, 255); … … 84 82 static pixel_t color_caption_focus = PIXEL(255, 255, 255, 255); 85 83 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_event101 };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 }110 84 111 85 static void paint_internal(widget_t *widget) … … 284 258 static void root_handle_position_event(widget_t *widget, pos_event_t event) 285 259 { 286 gfx_coord2_t pos;287 288 260 if (widget->window->is_decorated) { 289 261 sysarg_t width = widget->width; … … 291 263 292 264 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; 293 267 294 268 bool left = (event.hpos < border_thickness); … … 296 270 bool top = (event.vpos < border_thickness); 297 271 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 305 272 bool header = (event.hpos >= border_thickness) && 306 273 (event.hpos < width - border_thickness) && … … 310 277 (event.hpos >= width - border_thickness - close_thickness); 311 278 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); 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); 348 321 } else if (close && btn_left) { 349 win dow_close(widget->window);322 win_close_request(widget->window->osess); 350 323 } else if (header && btn_left) { 351 (void) display_window_move_req(widget->window->dwindow, 352 &pos); 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); 353 328 } else { 354 329 list_foreach(widget->children, link, widget_t, child) { … … 395 370 sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags) 396 371 { 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) 372 if (width < 2 * border_thickness + header_min_width) { 373 win_damage(win->osess, 0, 0, 0, 0); 408 374 return; 409 410 if (height < 2 * border_thickness + header_height) 375 } 376 377 if (height < 2 * border_thickness + header_height) { 378 win_damage(win->osess, 0, 0, 0, 0); 411 379 return; 412 380 } 381 382 /* Allocate resources for new surface. */ 383 surface_t *new_surface = surface_create(width, height, NULL, 384 SURFACE_FLAG_SHARED); 385 if (!new_surface) 386 return; 387 388 /* Switch new and old surface. */ 413 389 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, 503 SURFACE_FLAG_SHARED); 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. */ 390 surface_t *old_surface = win->surface; 511 391 win->surface = new_surface; 512 win->bitmap = new_bitmap;513 392 fibril_mutex_unlock(&win->guard); 514 393 … … 523 402 fibril_mutex_unlock(&win->guard); 524 403 525 (void) gfx_bitmap_render(win->bitmap, NULL, NULL); 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 } 526 435 } 527 436 … … 534 443 { 535 444 sysarg_t x, y, width, height; 536 gfx_rect_t rect;537 445 fibril_mutex_lock(&win->guard); 538 446 surface_get_damaged_region(win->surface, &x, &y, &width, &height); … … 541 449 542 450 if (width > 0 && height > 0) { 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); 451 /* Notify compositor. */ 452 win_damage(win->osess, x, y, width, height); 550 453 } 551 454 } … … 569 472 win->focus = NULL; 570 473 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); 474 win_close(win->osess); 475 async_hangup(win->isess); 476 async_hangup(win->osess); 581 477 582 478 while (!list_empty(&win->events.list)) { … … 610 506 break; 611 507 case ET_POSITION_EVENT: 508 if (!win->is_focused) { 509 win->is_focused = true; 510 handle_refresh(win); 511 } 612 512 deliver_position_event(win, event->data.pos); 613 513 break; … … 659 559 } 660 560 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 661 593 window_t *window_open(const char *winreg, const void *data, 662 594 window_flags_t flags, const char *caption) 663 595 { 664 display_wnd_params_t wparams; 665 666 window_t *win = (window_t *) calloc(1, sizeof(window_t)); 596 window_t *win = (window_t *) malloc(sizeof(window_t)); 667 597 if (!win) 668 598 return NULL; … … 670 600 win->is_main = flags & WINDOW_MAIN; 671 601 win->is_decorated = flags & WINDOW_DECORATED; 672 win->is_resizable = flags & WINDOW_RESIZEABLE;673 602 win->is_focused = true; 674 603 prodcons_initialize(&win->events); … … 685 614 win->grab = NULL; 686 615 win->focus = NULL; 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) { 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) { 693 621 free(win); 694 622 return NULL; 695 623 } 696 624 697 errno_t rc = display_open(winreg, &win->display);698 if (rc != EOK) {699 surface_destroy(win->surface);625 async_sess_t *reg_sess = 626 loc_service_connect(reg_dsid, INTERFACE_COMPOSITOR, 0); 627 if (reg_sess == NULL) { 700 628 free(win); 701 629 return NULL; 702 630 } 703 631 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); 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); 715 636 if (rc != EOK) { 716 display_close(win->display);717 surface_destroy(win->surface);718 637 free(win); 719 638 return NULL; 720 639 } 721 640 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); 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); 727 650 free(win); 728 651 return NULL; … … 801 724 { 802 725 fid_t ev_fid = fibril_create(event_loop, win); 803 if (!ev_fid) { 726 fid_t fi_fid = fibril_create(fetch_input, win); 727 if (!ev_fid || !fi_fid) { 804 728 return; 805 729 } 806 730 fibril_add_ready(ev_fid); 731 fibril_add_ready(fi_fid); 807 732 } 808 733 … … 820 745 void window_close(window_t *win) 821 746 { 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); 747 /* Request compositor to init closing cascade. */ 748 win_close_request(win->osess); 918 749 } 919 750
Note:
See TracChangeset
for help on using the changeset viewer.