Changes in uspace/lib/ui/src/ui.c [252d03c:983052c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ui/src/ui.c
r252d03c r983052c 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2023 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 39 39 #include <errno.h> 40 40 #include <fibril.h> 41 #include <fibril_synch.h> 42 #include <gfx/color.h> 43 #include <gfx/cursor.h> 44 #include <gfx/render.h> 41 45 #include <io/console.h> 42 46 #include <stdbool.h> … … 44 48 #include <str.h> 45 49 #include <task.h> 50 #include <types/common.h> 51 #include <ui/clickmatic.h> 46 52 #include <ui/ui.h> 47 53 #include <ui/wdecor.h> 48 54 #include <ui/window.h> 55 #include "../private/wdecor.h" 49 56 #include "../private/window.h" 50 57 #include "../private/ui.h" … … 53 60 * 54 61 * Output specification has the form <proto>@<service> where proto is 55 * eiher 'disp' for display service or 'cons' for console. Service56 * is a location ID service name (e.g. hid/display).62 * eiher 'disp' for display service, 'cons' for console, 'null' 63 * for dummy output. Service is a location ID service name (e.g. hid/display). 57 64 * 58 65 * @param ospec Output specification 59 66 * @param ws Place to store window system type (protocol) 60 67 * @param osvc Place to store pointer to output service name 61 */ 62 static void ui_ospec_parse(const char *ospec, ui_winsys_t *ws, 63 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) 64 74 { 65 75 const char *cp; 66 67 if (ospec == UI_DISPLAY_DEFAULT) {68 *ws = ui_ws_display;69 *osvc = DISPLAY_DEFAULT;70 return; 71 }76 const char *qm; 77 const char *endptr; 78 uint64_t idev_id; 79 errno_t rc; 80 81 *ridev_id = 0; 72 82 73 83 cp = ospec; … … 75 85 ++cp; 76 86 87 /* Window system / protocol */ 77 88 if (*cp == '@') { 78 89 if (str_lcmp(ospec, "disp@", str_length("disp@")) == 0) { … … 80 91 } else if (str_lcmp(ospec, "cons@", str_length("cons@")) == 0) { 81 92 *ws = ui_ws_console; 93 } else if (str_lcmp(ospec, "null@", str_length("null@")) == 0) { 94 *ws = ui_ws_null; 95 } else if (str_lcmp(ospec, "@", str_length("@")) == 0) { 96 *ws = ui_ws_any; 82 97 } else { 83 98 *ws = ui_ws_unknown; 84 99 } 85 100 86 if (cp[1] != '\0') 87 *osvc = cp + 1; 88 else 89 *osvc = NULL; 101 ++cp; 90 102 } else { 91 103 *ws = ui_ws_display; 92 *osvc = ospec; 93 } 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; 94 145 } 95 146 … … 97 148 * 98 149 * @param ospec Output specification or @c UI_DISPLAY_DEFAULT to use 99 * the default output 150 * the default display service, UI_CONSOLE_DEFAULT to use 151 * the default console service, UI_DISPLAY_NULL to use 152 * dummy output. 100 153 * @param rui Place to store pointer to new UI 101 154 * @return EOK on success or an error code … … 108 161 console_gc_t *cgc; 109 162 ui_winsys_t ws; 110 const char *osvc; 163 char *osvc; 164 sysarg_t cols; 165 sysarg_t rows; 166 sysarg_t idev_id; 111 167 ui_t *ui; 112 168 113 ui_ospec_parse(ospec, &ws, &osvc); 114 115 if (ws == ui_ws_display) { 116 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); 117 176 if (rc != EOK) 118 return rc;177 goto disp_fail; 119 178 120 179 rc = ui_create_disp(display, &ui); 121 180 if (rc != EOK) { 122 181 display_close(display); 123 return rc; 124 } 125 } 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) { 126 194 console = console_init(stdin, stdout); 127 195 if (console == NULL) 128 return EIO; 196 goto cons_fail; 197 198 rc = console_get_size(console, &cols, &rows); 199 if (rc != EOK) { 200 console_done(console); 201 goto cons_fail; 202 } 203 204 console_cursor_visibility(console, false); 129 205 130 206 /* ws == ui_ws_console */ … … 132 208 if (rc != EOK) { 133 209 console_done(console); 134 return rc;210 goto cons_fail; 135 211 } 136 212 … … 139 215 ui_destroy(ui); 140 216 console_done(console); 217 goto cons_fail; 218 } 219 220 free(osvc); 221 222 ui->cgc = cgc; 223 ui->rect.p0.x = 0; 224 ui->rect.p0.y = 0; 225 ui->rect.p1.x = cols; 226 ui->rect.p1.y = rows; 227 228 (void) ui_paint(ui); 229 ui->myoutput = true; 230 *rui = ui; 231 return EOK; 232 } 233 234 cons_fail: 235 if (ws == ui_ws_null) { 236 free(osvc); 237 rc = ui_create_disp(NULL, &ui); 238 if (rc != EOK) 141 239 return rc; 142 } 143 144 ui->cgc = cgc; 145 } else { 146 return EINVAL; 147 } 148 149 ui->myoutput = true; 150 *rui = ui; 151 return EOK; 240 241 ui->myoutput = true; 242 *rui = ui; 243 return EOK; 244 } 245 246 free(osvc); 247 return EINVAL; 152 248 } 153 249 … … 160 256 { 161 257 ui_t *ui; 258 errno_t rc; 162 259 163 260 ui = calloc(1, sizeof(ui_t)); … … 165 262 return ENOMEM; 166 263 264 rc = ui_clickmatic_create(ui, &ui->clickmatic); 265 if (rc != EOK) { 266 free(ui); 267 return rc; 268 } 269 167 270 ui->console = console; 168 271 list_initialize(&ui->windows); 272 fibril_mutex_initialize(&ui->lock); 169 273 *rui = ui; 170 274 return EOK; … … 180 284 { 181 285 ui_t *ui; 286 errno_t rc; 182 287 183 288 ui = calloc(1, sizeof(ui_t)); … … 185 290 return ENOMEM; 186 291 292 rc = ui_clickmatic_create(ui, &ui->clickmatic); 293 if (rc != EOK) { 294 free(ui); 295 return rc; 296 } 297 187 298 ui->display = disp; 188 299 list_initialize(&ui->windows); 300 fibril_mutex_initialize(&ui->lock); 189 301 *rui = ui; 190 302 return EOK; … … 203 315 if (ui->cgc != NULL) 204 316 console_gc_delete(ui->cgc); 205 if (ui->console != NULL) 317 if (ui->console != NULL) { 318 console_cursor_visibility(ui->console, true); 206 319 console_done(ui->console); 320 } 207 321 if (ui->display != NULL) 208 322 display_close(ui->display); … … 216 330 ui_window_t *awnd; 217 331 ui_evclaim_t claim; 332 pos_event_t pos; 218 333 219 334 awnd = ui_window_get_active(ui); … … 223 338 switch (event->type) { 224 339 case CEV_KEY: 340 ui_lock(ui); 225 341 ui_window_send_kbd(awnd, &event->ev.key); 342 ui_unlock(ui); 226 343 break; 227 344 case CEV_POS: 228 claim = ui_wdecor_pos_event(awnd->wdecor, &event->ev.pos); 345 pos = event->ev.pos; 346 /* Translate event to window-relative coordinates */ 347 pos.hpos -= awnd->dpos.x; 348 pos.vpos -= awnd->dpos.y; 349 350 claim = ui_wdecor_pos_event(awnd->wdecor, &pos); 229 351 /* Note: If event is claimed, awnd might not be valid anymore */ 230 if (claim == ui_unclaimed) 231 ui_window_send_pos(awnd, &event->ev.pos); 352 if (claim == ui_unclaimed) { 353 ui_lock(ui); 354 ui_window_send_pos(awnd, &pos); 355 ui_unlock(ui); 356 } 357 232 358 break; 233 359 } … … 280 406 { 281 407 errno_t rc; 408 gfx_context_t *gc; 282 409 ui_window_t *awnd; 410 gfx_color_t *color = NULL; 411 412 /* In case of null output */ 413 if (ui->cgc == NULL) 414 return EOK; 415 416 gc = console_gc_get_ctx(ui->cgc); 417 418 rc = gfx_color_new_ega(0x11, &color); 419 if (rc != EOK) 420 return rc; 421 422 rc = gfx_set_color(gc, color); 423 if (rc != EOK) { 424 gfx_color_delete(color); 425 return rc; 426 } 427 428 rc = gfx_fill_rect(gc, &ui->rect); 429 if (rc != EOK) { 430 gfx_color_delete(color); 431 return rc; 432 } 433 434 gfx_color_delete(color); 283 435 284 436 /* XXX Should repaint all windows */ … … 292 444 293 445 return ui_window_paint(awnd); 446 } 447 448 /** Free up console for other users. 449 * 450 * Release console resources for another application (that the current 451 * task is starting). After the other application finishes, resume 452 * operation with ui_resume(). No calls to UI must happen inbetween 453 * and no events must be processed (i.e. the calling function must not 454 * return control to UI. 455 * 456 * @param ui UI 457 * @return EOK on success or an error code 458 */ 459 errno_t ui_suspend(ui_t *ui) 460 { 461 errno_t rc; 462 463 assert(!ui->suspended); 464 465 if (ui->cgc == NULL) { 466 ui->suspended = true; 467 return EOK; 468 } 469 470 (void) console_set_caption(ui->console, ""); 471 rc = console_gc_suspend(ui->cgc); 472 if (rc != EOK) 473 return rc; 474 475 ui->suspended = true; 476 return EOK; 477 } 478 479 /** Resume suspended UI. 480 * 481 * Reclaim console resources (after child application has finished running) 482 * and restore UI operation previously suspended by calling ui_suspend(). 483 * 484 * @param ui UI 485 * @return EOK on success or an error code 486 */ 487 errno_t ui_resume(ui_t *ui) 488 { 489 errno_t rc; 490 ui_window_t *awnd; 491 sysarg_t col; 492 sysarg_t row; 493 cons_event_t ev; 494 495 assert(ui->suspended); 496 497 if (ui->cgc == NULL) { 498 ui->suspended = false; 499 return EOK; 500 } 501 502 rc = console_get_pos(ui->console, &col, &row); 503 if (rc != EOK) 504 return rc; 505 506 /* 507 * Here's a little heuristic to help determine if we need 508 * to pause before returning to the UI. If we are in the 509 * top-left corner, chances are the screen is empty and 510 * there is no need to pause. 511 */ 512 if (col != 0 || row != 0) { 513 printf("Press any key or button to continue...\n"); 514 515 while (true) { 516 rc = console_get_event(ui->console, &ev); 517 if (rc != EOK) 518 return EIO; 519 520 if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS) 521 break; 522 523 if (ev.type == CEV_POS && ev.ev.pos.type == POS_PRESS) 524 break; 525 } 526 } 527 528 rc = console_gc_resume(ui->cgc); 529 if (rc != EOK) 530 return rc; 531 532 ui->suspended = false; 533 534 awnd = ui_window_get_active(ui); 535 if (awnd != NULL) 536 (void) console_set_caption(ui->console, awnd->wdecor->caption); 537 538 rc = gfx_cursor_set_visible(console_gc_get_ctx(ui->cgc), false); 539 if (rc != EOK) 540 return rc; 541 542 return EOK; 543 } 544 545 /** Determine if UI is suspended. 546 * 547 * @param ui UI 548 * @return @c true iff UI is suspended 549 */ 550 bool ui_is_suspended(ui_t *ui) 551 { 552 return ui->suspended; 553 } 554 555 /** Lock UI. 556 * 557 * Block UI from calling window callbacks. @c ui_lock() and @c ui_unlock() 558 * must be used when accessing UI resources from a fibril (as opposed to 559 * from a window callback). 560 * 561 * @param ui UI 562 */ 563 void ui_lock(ui_t *ui) 564 { 565 fibril_mutex_lock(&ui->lock); 566 } 567 568 /** Unlock UI. 569 * 570 * Allow UI to call window callbacks. @c ui_lock() and @c ui_unlock() 571 * must be used when accessing window resources from a fibril (as opposed to 572 * from a window callback). 573 * 574 * @param ui UI 575 */ 576 void ui_unlock(ui_t *ui) 577 { 578 fibril_mutex_unlock(&ui->lock); 294 579 } 295 580 … … 331 616 } 332 617 618 /** Get UI screen rectangle. 619 * 620 * @param ui User interface 621 * @param rect Place to store bounding rectangle 622 */ 623 errno_t ui_get_rect(ui_t *ui, gfx_rect_t *rect) 624 { 625 display_info_t info; 626 sysarg_t cols, rows; 627 errno_t rc; 628 629 if (ui->display != NULL) { 630 rc = display_get_info(ui->display, &info); 631 if (rc != EOK) 632 return rc; 633 634 *rect = info.rect; 635 } else if (ui->console != NULL) { 636 rc = console_get_size(ui->console, &cols, &rows); 637 if (rc != EOK) 638 return rc; 639 640 rect->p0.x = 0; 641 rect->p0.y = 0; 642 rect->p1.x = cols; 643 rect->p1.y = rows; 644 } else { 645 return ENOTSUP; 646 } 647 648 return EOK; 649 } 650 651 /** Get clickmatic from UI. 652 * 653 * @pararm ui UI 654 * @return Clickmatic 655 */ 656 ui_clickmatic_t *ui_get_clickmatic(ui_t *ui) 657 { 658 return ui->clickmatic; 659 } 660 333 661 /** @} 334 662 */
Note:
See TracChangeset
for help on using the changeset viewer.