Changeset 7e38970d in mainline for uspace/app/terminal/terminal.c
- Timestamp:
- 2020-12-07T00:08:37Z (4 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 25f26600
- Parents:
- 7a873f0 (diff), 8596474 (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 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/terminal/terminal.c
r7a873f0 r7e38970d 1 1 /* 2 * Copyright (c) 2020 Jiri Svoboda 2 3 * Copyright (c) 2012 Petr Koupy 3 4 * All rights reserved. … … 27 28 */ 28 29 29 /** @addtogroup gui30 /** @addtogroup terminal 30 31 * @{ 31 32 */ 32 33 /** 33 * @file 34 * @file Terminal application 34 35 */ 35 36 37 #include <adt/list.h> 38 #include <adt/prodcons.h> 36 39 #include <errno.h> 37 #include < stdlib.h>40 #include <fbfont/font-8x16.h> 38 41 #include <io/chargrid.h> 39 #include < draw/surface.h>40 #include < draw/gfx.h>42 #include <gfx/bitmap.h> 43 #include <gfx/context.h> 41 44 #include <io/con_srv.h> 42 45 #include <io/concaps.h> 43 46 #include <io/console.h> 44 #include < loc.h>47 #include <io/pixelmap.h> 45 48 #include <task.h> 46 #include <adt/list.h>47 #include <adt/prodcons.h>48 49 #include <stdarg.h> 50 #include <stdlib.h> 49 51 #include <str.h> 50 #include "window.h" 52 #include <ui/resource.h> 53 #include <ui/ui.h> 54 #include <ui/wdecor.h> 55 #include <ui/window.h> 56 51 57 #include "terminal.h" 52 58 53 #define NAME " vterm"54 #define NAMESPACE " vterm"59 #define NAME "terminal" 60 #define NAMESPACE "terminal" 55 61 56 62 #define LOCFS_MOUNT_POINT "/loc" … … 96 102 .set_cursor_visibility = term_set_cursor_visibility, 97 103 .get_event = term_get_event 104 }; 105 106 static void terminal_close_event(ui_window_t *, void *); 107 static void terminal_focus_event(ui_window_t *, void *); 108 static void terminal_kbd_event(ui_window_t *, void *, kbd_event_t *); 109 static void terminal_pos_event(ui_window_t *, void *, pos_event_t *); 110 static void terminal_unfocus_event(ui_window_t *, void *); 111 112 static ui_window_cb_t terminal_window_cb = { 113 .close = terminal_close_event, 114 .focus = terminal_focus_event, 115 .kbd = terminal_kbd_event, 116 .pos = terminal_pos_event, 117 .unfocus = terminal_unfocus_event 98 118 }; 99 119 … … 165 185 } 166 186 167 static void term_update_char(terminal_t *term, surface_t *surface, 187 static void term_update_region(terminal_t *term, sysarg_t x, sysarg_t y, 188 sysarg_t w, sysarg_t h) 189 { 190 gfx_rect_t rect; 191 gfx_rect_t nupdate; 192 193 rect.p0.x = x; 194 rect.p0.y = y; 195 rect.p1.x = x + w; 196 rect.p1.y = y + h; 197 198 gfx_rect_envelope(&term->update, &rect, &nupdate); 199 term->update = nupdate; 200 } 201 202 static void term_update_char(terminal_t *term, pixelmap_t *pixelmap, 168 203 sysarg_t sx, sysarg_t sy, sysarg_t col, sysarg_t row) 169 204 { … … 190 225 191 226 for (unsigned int y = 0; y < FONT_SCANLINES; y++) { 192 pixel_t *dst = pixelmap_pixel_at( 193 surface_pixmap_access(surface), bx, by + y); 194 pixel_t *dst_max = pixelmap_pixel_at( 195 surface_pixmap_access(surface), bx + FONT_WIDTH - 1, by + y); 227 pixel_t *dst = pixelmap_pixel_at(pixelmap, bx, by + y); 228 pixel_t *dst_max = pixelmap_pixel_at(pixelmap, bx + FONT_WIDTH - 1, by + y); 196 229 if (!dst || !dst_max) 197 230 continue; … … 201 234 } 202 235 } 203 surface_add_damaged_region(surface, bx, by, FONT_WIDTH, FONT_SCANLINES);204 } 205 206 static bool term_update_scroll(terminal_t *term, surface_t *surface,236 term_update_region(term, bx, by, FONT_WIDTH, FONT_SCANLINES); 237 } 238 239 static bool term_update_scroll(terminal_t *term, pixelmap_t *pixelmap, 207 240 sysarg_t sx, sysarg_t sy) 208 241 { 209 242 sysarg_t top_row = chargrid_get_top_row(term->frontbuf); 210 243 211 if (term->top_row == top_row) 244 if (term->top_row == top_row) { 212 245 return false; 246 } 213 247 214 248 term->top_row = top_row; … … 234 268 front_field->flags &= ~CHAR_FLAG_DIRTY; 235 269 236 if (update) 237 term_update_char(term, surface, sx, sy, col, row); 270 if (update) { 271 term_update_char(term, pixelmap, sx, sy, col, row); 272 } 238 273 } 239 274 } … … 242 277 } 243 278 244 static bool term_update_cursor(terminal_t *term, surface_t *surface,279 static bool term_update_cursor(terminal_t *term, pixelmap_t *pixelmap, 245 280 sysarg_t sx, sysarg_t sy) 246 281 { 247 bool damage = false;282 bool update = false; 248 283 249 284 sysarg_t front_col; … … 257 292 bool front_visibility = 258 293 chargrid_get_cursor_visibility(term->frontbuf) && 259 term-> widget.window->is_focused;294 term->is_focused; 260 295 bool back_visibility = 261 296 chargrid_get_cursor_visibility(term->backbuf); … … 264 299 chargrid_set_cursor_visibility(term->backbuf, 265 300 front_visibility); 266 term_update_char(term, surface, sx, sy, back_col, back_row);267 damage = true;301 term_update_char(term, pixelmap, sx, sy, back_col, back_row); 302 update = true; 268 303 } 269 304 270 305 if ((front_col != back_col) || (front_row != back_row)) { 271 306 chargrid_set_cursor(term->backbuf, front_col, front_row); 272 term_update_char(term, surface, sx, sy, back_col, back_row);273 term_update_char(term, surface, sx, sy, front_col, front_row);274 damage = true;275 } 276 277 return damage;307 term_update_char(term, pixelmap, sx, sy, back_col, back_row); 308 term_update_char(term, pixelmap, sx, sy, front_col, front_row); 309 update = true; 310 } 311 312 return update; 278 313 } 279 314 280 315 static void term_update(terminal_t *term) 281 316 { 282 fibril_mutex_lock(&term->mtx); 283 284 surface_t *surface = window_claim(term->widget.window); 285 if (!surface) { 286 window_yield(term->widget.window); 287 fibril_mutex_unlock(&term->mtx); 317 pixelmap_t pixelmap; 318 gfx_bitmap_alloc_t alloc; 319 gfx_coord2_t pos; 320 errno_t rc; 321 322 rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 323 if (rc != EOK) { 288 324 return; 289 325 } 290 326 291 bool damage = false; 292 sysarg_t sx = term->widget.hpos; 293 sysarg_t sy = term->widget.vpos; 294 295 if (term_update_scroll(term, surface, sx, sy)) { 296 damage = true; 327 fibril_mutex_lock(&term->mtx); 328 pixelmap.width = term->w; 329 pixelmap.height = term->h; 330 pixelmap.data = alloc.pixels; 331 332 bool update = false; 333 sysarg_t sx = 0/*term->widget.hpos*/; 334 sysarg_t sy = 0/*term->widget.vpos*/; 335 336 if (term_update_scroll(term, &pixelmap, sx, sy)) { 337 update = true; 297 338 } else { 298 339 for (sysarg_t y = 0; y < term->rows; y++) { … … 321 362 322 363 if (update) { 323 term_update_char(term, surface, sx, sy, x, y);324 damage = true;364 term_update_char(term, &pixelmap, sx, sy, x, y); 365 update = true; 325 366 } 326 367 } … … 328 369 } 329 370 330 if (term_update_cursor(term, surface, sx, sy)) 331 damage = true; 332 333 window_yield(term->widget.window); 334 335 if (damage) 336 window_damage(term->widget.window); 337 338 fibril_mutex_unlock(&term->mtx); 339 } 340 341 static void term_damage(terminal_t *term) 342 { 343 fibril_mutex_lock(&term->mtx); 344 345 surface_t *surface = window_claim(term->widget.window); 346 if (!surface) { 347 window_yield(term->widget.window); 348 fibril_mutex_unlock(&term->mtx); 371 if (term_update_cursor(term, &pixelmap, sx, sy)) 372 update = true; 373 374 if (update) { 375 pos.x = 4; 376 pos.y = 26; 377 (void) gfx_bitmap_render(term->bmp, &term->update, &pos); 378 379 term->update.p0.x = 0; 380 term->update.p0.y = 0; 381 term->update.p1.x = 0; 382 term->update.p1.y = 0; 383 } 384 385 fibril_mutex_unlock(&term->mtx); 386 } 387 388 static void term_repaint(terminal_t *term) 389 { 390 pixelmap_t pixelmap; 391 gfx_bitmap_alloc_t alloc; 392 errno_t rc; 393 394 rc = gfx_bitmap_get_alloc(term->bmp, &alloc); 395 if (rc != EOK) { 396 printf("Error getting bitmap allocation info.\n"); 349 397 return; 350 398 } 351 399 352 sysarg_t sx = term->widget.hpos; 353 sysarg_t sy = term->widget.vpos; 354 355 if (!term_update_scroll(term, surface, sx, sy)) { 400 fibril_mutex_lock(&term->mtx); 401 402 pixelmap.width = term->w; 403 pixelmap.height = term->h; 404 pixelmap.data = alloc.pixels; 405 406 sysarg_t sx = 0; 407 sysarg_t sy = 0; 408 409 if (!term_update_scroll(term, &pixelmap, sx, sy)) { 356 410 for (sysarg_t y = 0; y < term->rows; y++) { 357 411 for (sysarg_t x = 0; x < term->cols; x++) { … … 365 419 front_field->flags &= ~CHAR_FLAG_DIRTY; 366 420 367 term_update_char(term, surface, sx, sy, x, y);421 term_update_char(term, &pixelmap, sx, sy, x, y); 368 422 } 369 423 } 370 424 } 371 425 372 term_update_cursor(term, surface, sx, sy); 373 374 window_yield(term->widget.window); 375 window_damage(term->widget.window); 426 term_update_cursor(term, &pixelmap, sx, sy); 376 427 377 428 fibril_mutex_unlock(&term->mtx); … … 437 488 } 438 489 439 static void term_write_char(terminal_t *term, char32_t ch)490 static void term_write_char(terminal_t *term, wchar_t ch) 440 491 { 441 492 sysarg_t updated = 0; … … 588 639 } 589 640 590 void deinit_terminal(terminal_t *term)641 static void deinit_terminal(terminal_t *term) 591 642 { 592 643 list_remove(&term->link); 593 widget_deinit(&term->widget);594 644 595 645 if (term->frontbuf) … … 600 650 } 601 651 602 static void terminal_destroy(widget_t *widget) 603 { 604 terminal_t *term = (terminal_t *) widget; 605 652 void terminal_destroy(terminal_t *term) 653 { 606 654 deinit_terminal(term); 607 655 free(term); 608 }609 610 static void terminal_reconfigure(widget_t *widget)611 {612 /* No-op */613 }614 615 static void terminal_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,616 sysarg_t width, sysarg_t height)617 {618 terminal_t *term = (terminal_t *) widget;619 620 widget_modify(widget, hpos, vpos, width, height);621 widget->width_ideal = width;622 widget->height_ideal = height;623 624 term_damage(term);625 }626 627 static void terminal_repaint(widget_t *widget)628 {629 terminal_t *term = (terminal_t *) widget;630 631 term_damage(term);632 656 } 633 657 … … 646 670 } 647 671 648 /* Got key press/release event */ 649 static void terminal_handle_keyboard_event(widget_t *widget, 650 kbd_event_t kbd_event) 651 { 652 terminal_t *term = (terminal_t *) widget; 672 /** Handle window close event. */ 673 static void terminal_close_event(ui_window_t *window, void *arg) 674 { 675 terminal_t *term = (terminal_t *) arg; 676 677 (void) term; 678 679 // XXX This is not really a clean way of terminating 680 exit(0); 681 } 682 683 /** Handle window focus event. */ 684 static void terminal_focus_event(ui_window_t *window, void *arg) 685 { 686 terminal_t *term = (terminal_t *) arg; 687 688 term->is_focused = true; 689 term_update(term); 690 } 691 692 /** Handle window keyboard event */ 693 static void terminal_kbd_event(ui_window_t *window, void *arg, 694 kbd_event_t *kbd_event) 695 { 696 terminal_t *term = (terminal_t *) arg; 653 697 cons_event_t event; 654 698 655 699 event.type = CEV_KEY; 656 event.ev.key = kbd_event;700 event.ev.key = *kbd_event; 657 701 658 702 terminal_queue_cons_event(term, &event); 659 703 } 660 704 661 static void terminal_handle_position_event(widget_t *widget, pos_event_t pos_event) 662 { 663 cons_event_t event; 664 terminal_t *term = (terminal_t *) widget; 665 sysarg_t sx = term->widget.hpos; 666 sysarg_t sy = term->widget.vpos; 667 668 if (pos_event.type == POS_PRESS) { 669 event.type = CEV_POS; 670 event.ev.pos.type = pos_event.type; 671 event.ev.pos.pos_id = pos_event.pos_id; 672 event.ev.pos.btn_num = pos_event.btn_num; 673 674 event.ev.pos.hpos = (pos_event.hpos - sx) / FONT_WIDTH; 675 event.ev.pos.vpos = (pos_event.vpos - sy) / FONT_SCANLINES; 676 terminal_queue_cons_event(term, &event); 677 } 705 /** Handle window position event */ 706 static void terminal_pos_event(ui_window_t *window, void *arg, pos_event_t *event) 707 { 708 cons_event_t cevent; 709 terminal_t *term = (terminal_t *) arg; 710 711 sysarg_t sx = -term->off.x; 712 sysarg_t sy = -term->off.y; 713 714 if (event->type == POS_PRESS) { 715 cevent.type = CEV_POS; 716 cevent.ev.pos.type = event->type; 717 cevent.ev.pos.pos_id = event->pos_id; 718 cevent.ev.pos.btn_num = event->btn_num; 719 720 cevent.ev.pos.hpos = (event->hpos - sx) / FONT_WIDTH; 721 cevent.ev.pos.vpos = (event->vpos - sy) / FONT_SCANLINES; 722 terminal_queue_cons_event(term, &cevent); 723 } 724 } 725 726 /** Handle window unfocus event. */ 727 static void terminal_unfocus_event(ui_window_t *window, void *arg) 728 { 729 terminal_t *term = (terminal_t *) arg; 730 731 term->is_focused = false; 732 term_update(term); 678 733 } 679 734 … … 700 755 } 701 756 702 bool init_terminal(terminal_t *term, widget_t *parent, const void *data, 703 sysarg_t width, sysarg_t height) 704 { 705 widget_init(&term->widget, parent, data); 757 errno_t terminal_create(const char *display_spec, sysarg_t width, 758 sysarg_t height, terminal_flags_t flags, terminal_t **rterm) 759 { 760 terminal_t *term; 761 gfx_bitmap_params_t params; 762 ui_wnd_params_t wparams; 763 gfx_rect_t rect; 764 gfx_coord2_t off; 765 gfx_rect_t wrect; 766 errno_t rc; 767 768 term = calloc(1, sizeof(terminal_t)); 769 if (term == NULL) { 770 printf("Out of memory.\n"); 771 return ENOMEM; 772 } 706 773 707 774 link_initialize(&term->link); … … 712 779 term->char_remains_len = 0; 713 780 714 term->widget.width = width; 715 term->widget.height = height; 716 term->widget.width_ideal = width; 717 term->widget.height_ideal = height; 718 719 term->widget.destroy = terminal_destroy; 720 term->widget.reconfigure = terminal_reconfigure; 721 term->widget.rearrange = terminal_rearrange; 722 term->widget.repaint = terminal_repaint; 723 term->widget.handle_keyboard_event = terminal_handle_keyboard_event; 724 term->widget.handle_position_event = terminal_handle_position_event; 781 term->w = width; 782 term->h = height; 725 783 726 784 term->cols = width / FONT_WIDTH; … … 733 791 CHARGRID_FLAG_NONE); 734 792 if (!term->frontbuf) { 735 widget_deinit(&term->widget); 736 return false; 793 printf("Error creating front buffer.\n"); 794 rc = ENOMEM; 795 goto error; 737 796 } 738 797 … … 740 799 CHARGRID_FLAG_NONE); 741 800 if (!term->backbuf) { 742 widget_deinit(&term->widget); 743 return false; 801 printf("Error creating back buffer.\n"); 802 rc = ENOMEM; 803 goto error; 804 } 805 806 rect.p0.x = 0; 807 rect.p0.y = 0; 808 rect.p1.x = width; 809 rect.p1.y = height; 810 811 ui_wnd_params_init(&wparams); 812 wparams.caption = "Terminal"; 813 if ((flags & tf_topleft) != 0) 814 wparams.placement = ui_wnd_place_top_left; 815 816 /* 817 * Compute window rectangle such that application area corresponds 818 * to rect 819 */ 820 ui_wdecor_rect_from_app(wparams.style, &rect, &wrect); 821 off = wrect.p0; 822 gfx_rect_rtranslate(&off, &wrect, &wparams.rect); 823 824 term->off = off; 825 826 rc = ui_create(display_spec, &term->ui); 827 if (rc != EOK) { 828 printf("Error creating UI on %s.\n", display_spec); 829 goto error; 830 } 831 832 rc = ui_window_create(term->ui, &wparams, &term->window); 833 if (rc != EOK) { 834 printf("Error creating window.\n"); 835 goto error; 836 } 837 838 term->gc = ui_window_get_gc(term->window); 839 term->ui_res = ui_window_get_res(term->window); 840 841 ui_window_set_cb(term->window, &terminal_window_cb, (void *) term); 842 843 gfx_bitmap_params_init(¶ms); 844 params.rect.p0.x = 0; 845 params.rect.p0.y = 0; 846 params.rect.p1.x = width; 847 params.rect.p1.y = height; 848 849 rc = gfx_bitmap_create(term->gc, ¶ms, NULL, &term->bmp); 850 if (rc != EOK) { 851 printf("Error allocating screen bitmap.\n"); 852 goto error; 744 853 } 745 854 … … 753 862 term->srvs.sarg = term; 754 863 755 errno_trc = loc_server_register(NAME);864 rc = loc_server_register(NAME); 756 865 if (rc != EOK) { 757 widget_deinit(&term->widget); 758 return false; 866 printf("Error registering server.\n"); 867 rc = EIO; 868 goto error; 759 869 } 760 870 … … 765 875 rc = loc_service_register(vc, &term->dsid); 766 876 if (rc != EOK) { 767 widget_deinit(&term->widget); 768 return false; 877 printf("Error registering service.\n"); 878 rc = EIO; 879 goto error; 769 880 } 770 881 … … 772 883 getterm(vc, "/app/bdsh"); 773 884 774 return true; 775 } 776 777 terminal_t *create_terminal(widget_t *parent, const void *data, sysarg_t width, 778 sysarg_t height) 779 { 780 terminal_t *term = (terminal_t *) malloc(sizeof(terminal_t)); 781 if (!term) 782 return NULL; 783 784 bool ret = init_terminal(term, parent, data, width, height); 785 if (!ret) { 786 free(term); 787 return NULL; 788 } 789 790 return term; 885 term->is_focused = true; 886 887 term->update.p0.x = 0; 888 term->update.p0.y = 0; 889 term->update.p1.x = 0; 890 term->update.p1.y = 0; 891 892 term_repaint(term); 893 894 *rterm = term; 895 return EOK; 896 error: 897 if (term->window != NULL) 898 ui_window_destroy(term->window); 899 if (term->ui != NULL) 900 ui_destroy(term->ui); 901 if (term->frontbuf != NULL) 902 chargrid_destroy(term->frontbuf); 903 if (term->backbuf != NULL) 904 chargrid_destroy(term->backbuf); 905 free(term); 906 return rc; 791 907 } 792 908
Note:
See TracChangeset
for help on using the changeset viewer.