Mercurial > vim
comparison src/terminal.c @ 11786:98154b91e43a v8.0.0775
patch 8.0.0775: in a terminal the cursor is updated too often
commit https://github.com/vim/vim/commit/fc716d725613c3b5934e7eac6573adde8e4f8183
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Jul 25 23:08:47 2017 +0200
patch 8.0.0775: in a terminal the cursor is updated too often
Problem: In a terminal the cursor is updated too often.
Solution: Only flush when needed. (Yasuhiro Matsumoto). Remeber whether the
cursor is visible. (closes #1873)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 25 Jul 2017 23:15:03 +0200 |
parents | e8005055f845 |
children | 4dfebc1b2674 |
comparison
equal
deleted
inserted
replaced
11785:e22f9669e392 | 11786:98154b91e43a |
---|---|
104 /* Range of screen rows to update. Zero based. */ | 104 /* Range of screen rows to update. Zero based. */ |
105 int tl_dirty_row_start; /* -1 if nothing dirty */ | 105 int tl_dirty_row_start; /* -1 if nothing dirty */ |
106 int tl_dirty_row_end; /* row below last one to update */ | 106 int tl_dirty_row_end; /* row below last one to update */ |
107 | 107 |
108 pos_T tl_cursor; | 108 pos_T tl_cursor; |
109 int tl_cursor_visible; | |
109 }; | 110 }; |
110 | 111 |
111 /* | 112 /* |
112 * List of all active terminals. | 113 * List of all active terminals. |
113 */ | 114 */ |
174 | 175 |
175 term = (term_T *)alloc_clear(sizeof(term_T)); | 176 term = (term_T *)alloc_clear(sizeof(term_T)); |
176 if (term == NULL) | 177 if (term == NULL) |
177 return; | 178 return; |
178 term->tl_dirty_row_end = MAX_ROW; | 179 term->tl_dirty_row_end = MAX_ROW; |
180 term->tl_cursor_visible = TRUE; | |
179 | 181 |
180 /* Open a new window or tab. */ | 182 /* Open a new window or tab. */ |
181 vim_memset(&split_ea, 0, sizeof(split_ea)); | 183 vim_memset(&split_ea, 0, sizeof(split_ea)); |
182 split_ea.cmdidx = CMD_new; | 184 split_ea.cmdidx = CMD_new; |
183 split_ea.cmd = (char_u *)"new"; | 185 split_ea.cmd = (char_u *)"new"; |
314 /* this invokes the damage callbacks */ | 316 /* this invokes the damage callbacks */ |
315 vterm_screen_flush_damage(vterm_obtain_screen(vterm)); | 317 vterm_screen_flush_damage(vterm_obtain_screen(vterm)); |
316 } | 318 } |
317 | 319 |
318 static void | 320 static void |
319 update_cursor() | 321 update_cursor(term_T *term, int redraw) |
320 { | 322 { |
321 /* TODO: this should not always be needed */ | 323 /* TODO: this should not always be needed */ |
322 setcursor(); | 324 setcursor(); |
323 out_flush(); | 325 if (redraw && term->tl_buffer == curbuf && term->tl_cursor_visible) |
326 { | |
327 out_flush(); | |
324 #ifdef FEAT_GUI | 328 #ifdef FEAT_GUI |
325 if (gui.in_use) | 329 if (gui.in_use) |
326 gui_update_cursor(FALSE, FALSE); | 330 gui_update_cursor(FALSE, FALSE); |
327 #endif | 331 #endif |
332 } | |
328 } | 333 } |
329 | 334 |
330 /* | 335 /* |
331 * Invoked when "msg" output from a job was received. Write it to the terminal | 336 * Invoked when "msg" output from a job was received. Write it to the terminal |
332 * of "buffer". | 337 * of "buffer". |
340 ch_logn(channel, "writing %d bytes to terminal", (int)len); | 345 ch_logn(channel, "writing %d bytes to terminal", (int)len); |
341 term_write_job_output(term, msg, len); | 346 term_write_job_output(term, msg, len); |
342 | 347 |
343 /* TODO: only update once in a while. */ | 348 /* TODO: only update once in a while. */ |
344 update_screen(0); | 349 update_screen(0); |
345 update_cursor(); | 350 update_cursor(term, TRUE); |
346 } | 351 } |
347 | 352 |
348 /* | 353 /* |
349 * Convert typed key "c" into bytes to send to the job. | 354 * Convert typed key "c" into bytes to send to the job. |
350 * Return the number of bytes in "buf". | 355 * Return the number of bytes in "buf". |
471 | 476 |
472 for (;;) | 477 for (;;) |
473 { | 478 { |
474 /* TODO: skip screen update when handling a sequence of keys. */ | 479 /* TODO: skip screen update when handling a sequence of keys. */ |
475 update_screen(0); | 480 update_screen(0); |
476 update_cursor(); | 481 update_cursor(curbuf->b_term, FALSE); |
477 ++no_mapping; | 482 ++no_mapping; |
478 ++allow_keys; | 483 ++allow_keys; |
479 got_int = FALSE; | 484 got_int = FALSE; |
480 c = vgetc(); | 485 c = vgetc(); |
481 --no_mapping; | 486 --no_mapping; |
557 term->tl_status_text = NULL; | 562 term->tl_status_text = NULL; |
558 redraw_buf_and_status_later(term->tl_buffer, VALID); | 563 redraw_buf_and_status_later(term->tl_buffer, VALID); |
559 did_one = TRUE; | 564 did_one = TRUE; |
560 } | 565 } |
561 if (did_one) | 566 if (did_one) |
562 { | |
563 redraw_statuslines(); | 567 redraw_statuslines(); |
564 update_cursor(); | 568 if (curbuf->b_term != NULL) |
565 } | 569 { |
566 if (curbuf->b_term != NULL && curbuf->b_term->tl_job == job) | 570 if (curbuf->b_term->tl_job == job) |
567 maketitle(); | 571 maketitle(); |
572 update_cursor(curbuf->b_term, TRUE); | |
573 } | |
568 } | 574 } |
569 | 575 |
570 /* | 576 /* |
571 * Return TRUE if the job for "buf" is still running. | 577 * Return TRUE if the job for "buf" is still running. |
572 */ | 578 */ |
579 static void | 585 static void |
580 position_cursor(win_T *wp, VTermPos *pos) | 586 position_cursor(win_T *wp, VTermPos *pos) |
581 { | 587 { |
582 wp->w_wrow = MIN(pos->row, MAX(0, wp->w_height - 1)); | 588 wp->w_wrow = MIN(pos->row, MAX(0, wp->w_height - 1)); |
583 wp->w_wcol = MIN(pos->col, MAX(0, wp->w_width - 1)); | 589 wp->w_wcol = MIN(pos->col, MAX(0, wp->w_width - 1)); |
590 } | |
591 | |
592 static void | |
593 may_toggle_cursor(term_T *term) | |
594 { | |
595 if (curbuf == term->tl_buffer) | |
596 { | |
597 if (term->tl_cursor_visible) | |
598 cursor_on(); | |
599 else | |
600 cursor_off(); | |
601 } | |
584 } | 602 } |
585 | 603 |
586 static int | 604 static int |
587 handle_damage(VTermRect rect, void *user) | 605 handle_damage(VTermRect rect, void *user) |
588 { | 606 { |
606 | 624 |
607 static int | 625 static int |
608 handle_movecursor( | 626 handle_movecursor( |
609 VTermPos pos, | 627 VTermPos pos, |
610 VTermPos oldpos UNUSED, | 628 VTermPos oldpos UNUSED, |
611 int visible UNUSED, | 629 int visible, |
612 void *user) | 630 void *user) |
613 { | 631 { |
614 term_T *term = (term_T *)user; | 632 term_T *term = (term_T *)user; |
615 win_T *wp; | 633 win_T *wp; |
616 int is_current = FALSE; | 634 int is_current = FALSE; |
623 if (wp == curwin) | 641 if (wp == curwin) |
624 is_current = TRUE; | 642 is_current = TRUE; |
625 } | 643 } |
626 } | 644 } |
627 | 645 |
646 term->tl_cursor_visible = visible; | |
628 if (is_current) | 647 if (is_current) |
629 update_cursor(); | 648 { |
649 may_toggle_cursor(term); | |
650 update_cursor(term, TRUE); | |
651 } | |
630 | 652 |
631 return 1; | 653 return 1; |
632 } | 654 } |
633 | 655 |
634 static int | 656 static int |
646 term->tl_title = vim_strsave((char_u *)value->string); | 668 term->tl_title = vim_strsave((char_u *)value->string); |
647 vim_free(term->tl_status_text); | 669 vim_free(term->tl_status_text); |
648 term->tl_status_text = NULL; | 670 term->tl_status_text = NULL; |
649 if (term == curbuf->b_term) | 671 if (term == curbuf->b_term) |
650 maketitle(); | 672 maketitle(); |
651 return 1; | 673 break; |
674 | |
675 case VTERM_PROP_CURSORVISIBLE: | |
676 term->tl_cursor_visible = value->boolean; | |
677 may_toggle_cursor(term); | |
678 out_flush(); | |
679 break; | |
680 | |
652 default: | 681 default: |
653 break; | 682 break; |
654 } | 683 } |
655 return 0; | 684 /* Always return 1, otherwise vterm doesn't store the value internally. */ |
685 return 1; | |
656 } | 686 } |
657 | 687 |
658 /* | 688 /* |
659 * The job running in the terminal resized the terminal. | 689 * The job running in the terminal resized the terminal. |
660 */ | 690 */ |