Changes in uspace/lib/ui/src/ui.c [3d10a2f:26edcd6] in mainline
- File:
-
- 1 edited
-
uspace/lib/ui/src/ui.c (modified) (21 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ui/src/ui.c
r3d10a2f r26edcd6 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2026 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 39 39 #include <errno.h> 40 40 #include <fibril.h> 41 #include <fibril_synch.h> 41 42 #include <gfx/color.h> 43 #include <gfx/cursor.h> 42 44 #include <gfx/render.h> 43 45 #include <io/console.h> … … 46 48 #include <str.h> 47 49 #include <task.h> 50 #include <types/common.h> 51 #include <ui/clickmatic.h> 48 52 #include <ui/ui.h> 49 53 #include <ui/wdecor.h> 50 54 #include <ui/window.h> 55 #include "../private/wdecor.h" 51 56 #include "../private/window.h" 52 57 #include "../private/ui.h" … … 61 66 * @param ws Place to store window system type (protocol) 62 67 * @param osvc Place to store pointer to output service name 63 */ 64 static void ui_ospec_parse(const char *ospec, ui_winsys_t *ws, 65 const char **osvc) 68 * @param ridev_id Place to store input device ID 69 * @return EOK on success, EINVAL if syntax is invalid, ENOMEM if out of 70 * memory 71 */ 72 static errno_t ui_ospec_parse(const char *ospec, ui_winsys_t *ws, 73 char **osvc, sysarg_t *ridev_id) 66 74 { 67 75 const char *cp; 68 69 if (ospec == UI_DISPLAY_DEFAULT) {70 *ws = ui_ws_display;71 *osvc = DISPLAY_DEFAULT;72 return; 73 }76 const char *qm; 77 const char *endptr; 78 uint64_t idev_id; 79 errno_t rc; 80 81 *ridev_id = 0; 74 82 75 83 cp = ospec; … … 77 85 ++cp; 78 86 87 /* Window system / protocol */ 79 88 if (*cp == '@') { 80 89 if (str_lcmp(ospec, "disp@", str_length("disp@")) == 0) { … … 84 93 } else if (str_lcmp(ospec, "null@", str_length("null@")) == 0) { 85 94 *ws = ui_ws_null; 95 } else if (str_lcmp(ospec, "@", str_length("@")) == 0) { 96 *ws = ui_ws_any; 86 97 } else { 87 98 *ws = ui_ws_unknown; 88 99 } 89 100 90 if (cp[1] != '\0') 91 *osvc = cp + 1; 92 else 93 *osvc = NULL; 101 ++cp; 94 102 } else { 95 103 *ws = ui_ws_display; 96 *osvc = ospec; 97 } 104 } 105 106 /* Output service is the part before question mark */ 107 qm = str_chr(cp, '?'); 108 if (qm != NULL) { 109 *osvc = str_ndup(cp, qm - cp); 110 } else { 111 /* No question mark */ 112 *osvc = str_dup(cp); 113 } 114 115 if (*osvc == NULL) 116 return ENOMEM; 117 118 if (qm != NULL) { 119 /* The part after the question mark */ 120 cp = qm + 1; 121 122 /* Input device ID parameter */ 123 if (str_lcmp(cp, "idev=", str_length("idev=")) == 0) { 124 cp += str_length("idev="); 125 126 rc = str_uint64_t(cp, &endptr, 10, false, &idev_id); 127 if (rc != EOK) 128 goto error; 129 130 *ridev_id = idev_id; 131 cp = endptr; 132 } 133 } 134 135 if (*cp != '\0') { 136 rc = EINVAL; 137 goto error; 138 } 139 140 return EOK; 141 error: 142 free(*osvc); 143 *osvc = NULL; 144 return rc; 98 145 } 99 146 … … 114 161 console_gc_t *cgc; 115 162 ui_winsys_t ws; 116 c onst char *osvc;163 char *osvc; 117 164 sysarg_t cols; 118 165 sysarg_t rows; 166 sysarg_t idev_id; 119 167 ui_t *ui; 120 168 121 ui_ospec_parse(ospec, &ws, &osvc); 122 123 if (ws == ui_ws_display) { 124 rc = display_open(osvc, &display); 169 rc = ui_ospec_parse(ospec, &ws, &osvc, &idev_id); 170 if (rc != EOK) 171 return rc; 172 173 if (ws == ui_ws_display || ws == ui_ws_any) { 174 rc = display_open((str_cmp(osvc, "") != 0) ? osvc : 175 DISPLAY_DEFAULT, &display); 125 176 if (rc != EOK) 126 return rc;177 goto disp_fail; 127 178 128 179 rc = ui_create_disp(display, &ui); 129 180 if (rc != EOK) { 130 181 display_close(display); 131 return rc; 132 } 133 } else if (ws == ui_ws_console) { 182 goto disp_fail; 183 } 184 185 free(osvc); 186 ui->myoutput = true; 187 ui->idev_id = idev_id; 188 *rui = ui; 189 return EOK; 190 } 191 192 disp_fail: 193 if (ws == ui_ws_console || ws == ui_ws_any) { 134 194 console = console_init(stdin, stdout); 135 195 if (console == NULL) 136 return EIO;196 goto cons_fail; 137 197 138 198 rc = console_get_size(console, &cols, &rows); 139 199 if (rc != EOK) { 140 200 console_done(console); 141 return rc;201 goto cons_fail; 142 202 } 143 203 … … 148 208 if (rc != EOK) { 149 209 console_done(console); 150 return rc;210 goto cons_fail; 151 211 } 152 212 … … 155 215 ui_destroy(ui); 156 216 console_done(console); 157 return rc; 158 } 217 goto cons_fail; 218 } 219 220 free(osvc); 159 221 160 222 ui->cgc = cgc; … … 165 227 166 228 (void) ui_paint(ui); 167 } else if (ws == ui_ws_null) { 229 ui->myoutput = true; 230 *rui = ui; 231 return EOK; 232 } 233 234 cons_fail: 235 if (ws == ui_ws_null) { 236 free(osvc); 168 237 rc = ui_create_disp(NULL, &ui); 169 238 if (rc != EOK) 170 239 return rc; 171 } else { 172 return EINVAL; 173 } 174 175 ui->myoutput = true; 176 *rui = ui; 177 return EOK; 240 241 ui->myoutput = true; 242 *rui = ui; 243 return EOK; 244 } 245 246 free(osvc); 247 return EINVAL; 178 248 } 179 249 … … 186 256 { 187 257 ui_t *ui; 258 errno_t rc; 188 259 189 260 ui = calloc(1, sizeof(ui_t)); … … 191 262 return ENOMEM; 192 263 264 rc = ui_clickmatic_create(ui, &ui->clickmatic); 265 if (rc != EOK) { 266 free(ui); 267 return rc; 268 } 269 193 270 ui->console = console; 194 271 list_initialize(&ui->windows); 272 fibril_mutex_initialize(&ui->lock); 195 273 *rui = ui; 196 274 return EOK; … … 206 284 { 207 285 ui_t *ui; 286 errno_t rc; 208 287 209 288 ui = calloc(1, sizeof(ui_t)); … … 211 290 return ENOMEM; 212 291 292 rc = ui_clickmatic_create(ui, &ui->clickmatic); 293 if (rc != EOK) { 294 free(ui); 295 return rc; 296 } 297 213 298 ui->display = disp; 214 299 list_initialize(&ui->windows); 300 fibril_mutex_initialize(&ui->lock); 215 301 *rui = ui; 216 302 return EOK; … … 240 326 } 241 327 328 /** Resize UI after screen size change. 329 * 330 * @param ui UI 331 * @param rect New screen rectangle. 332 */ 333 static void ui_resize(ui_t *ui, gfx_rect_t *rect) 334 { 335 ui_window_t *wnd; 336 337 ui->rect = *rect; 338 339 /* Reposition/resize windows */ 340 wnd = ui_window_first(ui); 341 while (wnd != NULL) { 342 ui_window_update_placement(wnd); 343 wnd = ui_window_next(wnd); 344 } 345 346 /* 347 * XXX Resizing cleared console GC so we need to repaint the 348 * background. 349 */ 350 (void)ui_paint(ui); 351 } 352 242 353 static void ui_cons_event_process(ui_t *ui, cons_event_t *event) 243 354 { … … 245 356 ui_evclaim_t claim; 246 357 pos_event_t pos; 358 sysarg_t cols, rows; 359 gfx_rect_t rect; 360 errno_t rc; 247 361 248 362 awnd = ui_window_get_active(ui); … … 252 366 switch (event->type) { 253 367 case CEV_KEY: 368 ui_lock(ui); 254 369 ui_window_send_kbd(awnd, &event->ev.key); 370 ui_unlock(ui); 255 371 break; 256 372 case CEV_POS: … … 262 378 claim = ui_wdecor_pos_event(awnd->wdecor, &pos); 263 379 /* Note: If event is claimed, awnd might not be valid anymore */ 264 if (claim == ui_unclaimed) 380 if (claim == ui_unclaimed) { 381 ui_lock(ui); 265 382 ui_window_send_pos(awnd, &pos); 266 383 ui_unlock(ui); 384 } 385 386 break; 387 case CEV_RESIZE: 388 rc = console_gc_resize(ui->cgc); 389 if (rc != EOK) { 390 /* XXX No good way to recover. */ 391 console_done(ui->console); 392 exit(1); 393 } 394 395 rc = console_get_size(ui->console, &cols, &rows); 396 if (rc != EOK) { 397 /* XXX No good way to recover. */ 398 console_done(ui->console); 399 exit(1); 400 } 401 402 ui_lock(ui); 403 404 rect.p0.x = 0; 405 rect.p0.y = 0; 406 rect.p1.x = cols; 407 rect.p1.y = rows; 408 409 ui_resize(ui, &rect); 410 ui_unlock(ui); 267 411 break; 268 412 } … … 316 460 errno_t rc; 317 461 gfx_context_t *gc; 318 ui_window_t * awnd;462 ui_window_t *wnd; 319 463 gfx_color_t *color = NULL; 320 464 … … 343 487 gfx_color_delete(color); 344 488 345 /* XXX Should repaint all windows */ 489 /* Repaint all windows */ 490 wnd = ui_window_first(ui); 491 while (wnd != NULL) { 492 rc = ui_wdecor_paint(wnd->wdecor); 493 if (rc != EOK) 494 return rc; 495 496 rc = ui_window_paint(wnd); 497 if (rc != EOK) 498 return rc; 499 500 wnd = ui_window_next(wnd); 501 } 502 503 return EOK; 504 } 505 506 /** Free up console for other users. 507 * 508 * Release console resources for another application (that the current 509 * task is starting). After the other application finishes, resume 510 * operation with ui_resume(). No calls to UI must happen inbetween 511 * and no events must be processed (i.e. the calling function must not 512 * return control to UI. 513 * 514 * @param ui UI 515 * @return EOK on success or an error code 516 */ 517 errno_t ui_suspend(ui_t *ui) 518 { 519 errno_t rc; 520 521 assert(!ui->suspended); 522 523 if (ui->cgc == NULL) { 524 ui->suspended = true; 525 return EOK; 526 } 527 528 (void) console_set_caption(ui->console, ""); 529 rc = console_gc_suspend(ui->cgc); 530 if (rc != EOK) 531 return rc; 532 533 ui->suspended = true; 534 return EOK; 535 } 536 537 /** Resume suspended UI. 538 * 539 * Reclaim console resources (after child application has finished running) 540 * and restore UI operation previously suspended by calling ui_suspend(). 541 * 542 * @param ui UI 543 * @return EOK on success or an error code 544 */ 545 errno_t ui_resume(ui_t *ui) 546 { 547 errno_t rc; 548 ui_window_t *awnd; 549 sysarg_t col; 550 sysarg_t row; 551 cons_event_t ev; 552 553 assert(ui->suspended); 554 555 if (ui->cgc == NULL) { 556 ui->suspended = false; 557 return EOK; 558 } 559 560 rc = console_get_pos(ui->console, &col, &row); 561 if (rc != EOK) 562 return rc; 563 564 /* 565 * Here's a little heuristic to help determine if we need 566 * to pause before returning to the UI. If we are in the 567 * top-left corner, chances are the screen is empty and 568 * there is no need to pause. 569 */ 570 if (col != 0 || row != 0) { 571 printf("Press any key or button to continue...\n"); 572 573 while (true) { 574 rc = console_get_event(ui->console, &ev); 575 if (rc != EOK) 576 return EIO; 577 578 if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS) 579 break; 580 581 if (ev.type == CEV_POS && ev.ev.pos.type == POS_PRESS) 582 break; 583 } 584 } 585 586 rc = console_gc_resume(ui->cgc); 587 if (rc != EOK) 588 return rc; 589 590 ui->suspended = false; 591 346 592 awnd = ui_window_get_active(ui); 347 if (awnd == NULL)348 return EOK;349 350 rc = ui_wdecor_paint(awnd->wdecor);593 if (awnd != NULL) 594 (void) console_set_caption(ui->console, awnd->wdecor->caption); 595 596 rc = gfx_cursor_set_visible(console_gc_get_ctx(ui->cgc), false); 351 597 if (rc != EOK) 352 598 return rc; 353 599 354 return ui_window_paint(awnd); 600 return EOK; 601 } 602 603 /** Determine if UI is suspended. 604 * 605 * @param ui UI 606 * @return @c true iff UI is suspended 607 */ 608 bool ui_is_suspended(ui_t *ui) 609 { 610 return ui->suspended; 611 } 612 613 /** Lock UI. 614 * 615 * Block UI from calling window callbacks. @c ui_lock() and @c ui_unlock() 616 * must be used when accessing UI resources from a fibril (as opposed to 617 * from a window callback). 618 * 619 * @param ui UI 620 */ 621 void ui_lock(ui_t *ui) 622 { 623 if (ui->display != NULL) 624 display_lock(ui->display); 625 fibril_mutex_lock(&ui->lock); 626 } 627 628 /** Unlock UI. 629 * 630 * Allow UI to call window callbacks. @c ui_lock() and @c ui_unlock() 631 * must be used when accessing window resources from a fibril (as opposed to 632 * from a window callback). 633 * 634 * @param ui UI 635 */ 636 void ui_unlock(ui_t *ui) 637 { 638 fibril_mutex_unlock(&ui->lock); 639 if (ui->display != NULL) 640 display_unlock(ui->display); 355 641 } 356 642 … … 392 678 } 393 679 680 /** Get UI screen rectangle. 681 * 682 * @param ui User interface 683 * @param rect Place to store bounding rectangle 684 */ 685 errno_t ui_get_rect(ui_t *ui, gfx_rect_t *rect) 686 { 687 display_info_t info; 688 sysarg_t cols, rows; 689 errno_t rc; 690 691 if (ui->display != NULL) { 692 rc = display_get_info(ui->display, &info); 693 if (rc != EOK) 694 return rc; 695 696 *rect = info.rect; 697 } else if (ui->console != NULL) { 698 rc = console_get_size(ui->console, &cols, &rows); 699 if (rc != EOK) 700 return rc; 701 702 rect->p0.x = 0; 703 rect->p0.y = 0; 704 rect->p1.x = cols; 705 rect->p1.y = rows; 706 } else { 707 return ENOTSUP; 708 } 709 710 return EOK; 711 } 712 713 /** Get clickmatic from UI. 714 * 715 * @pararm ui UI 716 * @return Clickmatic 717 */ 718 ui_clickmatic_t *ui_get_clickmatic(ui_t *ui) 719 { 720 return ui->clickmatic; 721 } 722 394 723 /** @} 395 724 */
Note:
See TracChangeset
for help on using the changeset viewer.
