diff options
| author | Eli Zaretskii | 2014-06-04 12:16:46 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2014-06-04 12:16:46 +0300 |
| commit | d13adf6ddc858a988f88233fe6d73a8ca4a87cf7 (patch) | |
| tree | f7ded9b13a8785e0c643bb3cd6a7cd893bfede25 /src | |
| parent | 4a52a98a9a5a49719da0a44d5ab1ddfde9a2aedc (diff) | |
| download | emacs-d13adf6ddc858a988f88233fe6d73a8ca4a87cf7.tar.gz emacs-d13adf6ddc858a988f88233fe6d73a8ca4a87cf7.zip | |
Attempt to solve bug #17497 by minimizing cursor motion during TTY menu updates.
src/term.c (tty_menu_display): Don't position cursor here. Instead,
pass the cursor coordinates to update_frame_with_menu.
(tty_menu_activate): Send the hide cursor command only once in an
iteration through the outer 'while' loop.
src/dispnew.c (update_frame_1): Accept an additional argument
SET_CURSOR_P, and position the cursor at the end of the frame
update only if that argument is non-zero. All callers changed to
provide the additional argument as non-zero, except for
update_frame_with_menu.
(update_frame_with_menu): Accept 2 additional arguments ROW and
COL; if they are non-negative, instruct update_frame_1 not to
position the cursor, and instead position it according to ROW and
COL.
src/dispextern.h (update_frame_with_menu): Update prototype.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 20 | ||||
| -rw-r--r-- | src/dispextern.h | 2 | ||||
| -rw-r--r-- | src/dispnew.c | 30 | ||||
| -rw-r--r-- | src/term.c | 16 |
4 files changed, 50 insertions, 18 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 5759d155580..16e3328a735 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,23 @@ | |||
| 1 | 2014-06-04 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | Minimize cursor motion during TTY menu updates. | ||
| 4 | * term.c (tty_menu_display): Don't position cursor here. Instead, | ||
| 5 | pass the cursor coordinates to update_frame_with_menu. | ||
| 6 | (tty_menu_activate): Send the hide cursor command only once in an | ||
| 7 | iteration through the outer 'while' loop. | ||
| 8 | |||
| 9 | * dispnew.c (update_frame_1): Accept an additional argument | ||
| 10 | SET_CURSOR_P, and position the cursor at the end of the frame | ||
| 11 | update only if that argument is non-zero. All callers changed to | ||
| 12 | provide the additional argument as non-zero, except for | ||
| 13 | update_frame_with_menu. | ||
| 14 | (update_frame_with_menu): Accept 2 additional arguments ROW and | ||
| 15 | COL; if they are non-negative, instruct update_frame_1 not to | ||
| 16 | position the cursor, and instead position it according to ROW and | ||
| 17 | COL. | ||
| 18 | |||
| 19 | * dispextern.h (update_frame_with_menu): Update prototype. | ||
| 20 | |||
| 1 | 2014-06-02 Stefan Monnier <monnier@iro.umontreal.ca> | 21 | 2014-06-02 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 22 | ||
| 3 | * callproc.c (call_process): Don't check read-only if we don't insert | 23 | * callproc.c (call_process): Don't check read-only if we don't insert |
diff --git a/src/dispextern.h b/src/dispextern.h index 9ecd4ecdf7e..8ccc3d35d8c 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -3454,7 +3454,7 @@ extern Lisp_Object marginal_area_string (struct window *, enum window_part, | |||
| 3454 | int *, int *, int *, int *); | 3454 | int *, int *, int *, int *); |
| 3455 | extern void redraw_frame (struct frame *); | 3455 | extern void redraw_frame (struct frame *); |
| 3456 | extern bool update_frame (struct frame *, bool, bool); | 3456 | extern bool update_frame (struct frame *, bool, bool); |
| 3457 | extern void update_frame_with_menu (struct frame *); | 3457 | extern void update_frame_with_menu (struct frame *, int, int); |
| 3458 | extern void bitch_at_user (void); | 3458 | extern void bitch_at_user (void); |
| 3459 | extern void adjust_frame_glyphs (struct frame *); | 3459 | extern void adjust_frame_glyphs (struct frame *); |
| 3460 | void free_glyphs (struct frame *); | 3460 | void free_glyphs (struct frame *); |
diff --git a/src/dispnew.c b/src/dispnew.c index 1a9eefc5cfc..163780952a6 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -92,7 +92,7 @@ static void check_matrix_pointers (struct glyph_matrix *, | |||
| 92 | static void mirror_line_dance (struct window *, int, int, int *, char *); | 92 | static void mirror_line_dance (struct window *, int, int, int *, char *); |
| 93 | static bool update_window_tree (struct window *, bool); | 93 | static bool update_window_tree (struct window *, bool); |
| 94 | static bool update_window (struct window *, bool); | 94 | static bool update_window (struct window *, bool); |
| 95 | static bool update_frame_1 (struct frame *, bool, bool); | 95 | static bool update_frame_1 (struct frame *, bool, bool, bool); |
| 96 | static bool scrolling (struct frame *); | 96 | static bool scrolling (struct frame *); |
| 97 | static void set_window_cursor_after_update (struct window *); | 97 | static void set_window_cursor_after_update (struct window *); |
| 98 | static void adjust_frame_glyphs_for_window_redisplay (struct frame *); | 98 | static void adjust_frame_glyphs_for_window_redisplay (struct frame *); |
| @@ -3070,7 +3070,7 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p) | |||
| 3070 | 3070 | ||
| 3071 | /* Update the display */ | 3071 | /* Update the display */ |
| 3072 | update_begin (f); | 3072 | update_begin (f); |
| 3073 | paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p); | 3073 | paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p, 1); |
| 3074 | update_end (f); | 3074 | update_end (f); |
| 3075 | 3075 | ||
| 3076 | if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) | 3076 | if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) |
| @@ -3100,12 +3100,17 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p) | |||
| 3100 | glyphs. This is like the second part of update_frame, but it | 3100 | glyphs. This is like the second part of update_frame, but it |
| 3101 | doesn't call build_frame_matrix, because we already have the | 3101 | doesn't call build_frame_matrix, because we already have the |
| 3102 | desired matrix prepared, and don't want it to be overwritten by the | 3102 | desired matrix prepared, and don't want it to be overwritten by the |
| 3103 | text of the normal display. */ | 3103 | text of the normal display. |
| 3104 | |||
| 3105 | ROW and COL, if non-negative, are the row and column of the TTY | ||
| 3106 | frame where to position the cursor after the frame update is | ||
| 3107 | complete. Negative values mean ask update_frame_1 to position the | ||
| 3108 | cursor "normally", i.e. at point in the selected window. */ | ||
| 3104 | void | 3109 | void |
| 3105 | update_frame_with_menu (struct frame *f) | 3110 | update_frame_with_menu (struct frame *f, int row, int col) |
| 3106 | { | 3111 | { |
| 3107 | struct window *root_window = XWINDOW (f->root_window); | 3112 | struct window *root_window = XWINDOW (f->root_window); |
| 3108 | bool paused_p; | 3113 | bool paused_p, cursor_at_point_p; |
| 3109 | 3114 | ||
| 3110 | eassert (FRAME_TERMCAP_P (f)); | 3115 | eassert (FRAME_TERMCAP_P (f)); |
| 3111 | 3116 | ||
| @@ -3115,9 +3120,14 @@ update_frame_with_menu (struct frame *f) | |||
| 3115 | 3120 | ||
| 3116 | /* Update the display. */ | 3121 | /* Update the display. */ |
| 3117 | update_begin (f); | 3122 | update_begin (f); |
| 3123 | cursor_at_point_p = !(row >= 0 && col >= 0); | ||
| 3118 | /* Force update_frame_1 not to stop due to pending input, and not | 3124 | /* Force update_frame_1 not to stop due to pending input, and not |
| 3119 | try scrolling. */ | 3125 | try scrolling. */ |
| 3120 | paused_p = update_frame_1 (f, 1, 1); | 3126 | paused_p = update_frame_1 (f, 1, 1, cursor_at_point_p); |
| 3127 | /* ROW and COL tell us where in the menu to position the cursor, so | ||
| 3128 | that screen readers know the active region on the screen. */ | ||
| 3129 | if (!cursor_at_point_p) | ||
| 3130 | cursor_to (f, row, col); | ||
| 3121 | update_end (f); | 3131 | update_end (f); |
| 3122 | 3132 | ||
| 3123 | if (FRAME_TTY (f)->termscript) | 3133 | if (FRAME_TTY (f)->termscript) |
| @@ -4413,12 +4423,14 @@ scrolling_window (struct window *w, bool header_line_p) | |||
| 4413 | /* Update the desired frame matrix of frame F. | 4423 | /* Update the desired frame matrix of frame F. |
| 4414 | 4424 | ||
| 4415 | FORCE_P means that the update should not be stopped by pending input. | 4425 | FORCE_P means that the update should not be stopped by pending input. |
| 4416 | INHIBIT_HAIRY_ID_P means that scrolling should not be tried. | 4426 | INHIBIT_ID_P means that scrolling by insert/delete should not be tried. |
| 4427 | SET_CURSOR_P false means do not set cursor at point in selected window. | ||
| 4417 | 4428 | ||
| 4418 | Value is true if update was stopped due to pending input. */ | 4429 | Value is true if update was stopped due to pending input. */ |
| 4419 | 4430 | ||
| 4420 | static bool | 4431 | static bool |
| 4421 | update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p) | 4432 | update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, |
| 4433 | bool set_cursor_p) | ||
| 4422 | { | 4434 | { |
| 4423 | /* Frame matrices to work on. */ | 4435 | /* Frame matrices to work on. */ |
| 4424 | struct glyph_matrix *current_matrix = f->current_matrix; | 4436 | struct glyph_matrix *current_matrix = f->current_matrix; |
| @@ -4490,7 +4502,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p) | |||
| 4490 | pause_p = 0 < i && i < FRAME_LINES (f) - 1; | 4502 | pause_p = 0 < i && i < FRAME_LINES (f) - 1; |
| 4491 | 4503 | ||
| 4492 | /* Now just clean up termcap drivers and set cursor, etc. */ | 4504 | /* Now just clean up termcap drivers and set cursor, etc. */ |
| 4493 | if (!pause_p) | 4505 | if (!pause_p && set_cursor_p) |
| 4494 | { | 4506 | { |
| 4495 | if ((cursor_in_echo_area | 4507 | if ((cursor_in_echo_area |
| 4496 | /* If we are showing a message instead of the mini-buffer, | 4508 | /* If we are showing a message instead of the mini-buffer, |
diff --git a/src/term.c b/src/term.c index 12cd2ce8508..8661cba1160 100644 --- a/src/term.c +++ b/src/term.c | |||
| @@ -2907,8 +2907,7 @@ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces, | |||
| 2907 | display_tty_menu_item (menu->text[j], max_width, face, x, y + i, | 2907 | display_tty_menu_item (menu->text[j], max_width, face, x, y + i, |
| 2908 | menu->submenu[j] != NULL); | 2908 | menu->submenu[j] != NULL); |
| 2909 | } | 2909 | } |
| 2910 | update_frame_with_menu (sf); | 2910 | update_frame_with_menu (sf, row, col); |
| 2911 | cursor_to (sf, row, col); | ||
| 2912 | } | 2911 | } |
| 2913 | 2912 | ||
| 2914 | /* --------------------------- X Menu emulation ---------------------- */ | 2913 | /* --------------------------- X Menu emulation ---------------------- */ |
| @@ -3079,7 +3078,7 @@ static void | |||
| 3079 | screen_update (struct frame *f, struct glyph_matrix *mtx) | 3078 | screen_update (struct frame *f, struct glyph_matrix *mtx) |
| 3080 | { | 3079 | { |
| 3081 | restore_desired_matrix (f, mtx); | 3080 | restore_desired_matrix (f, mtx); |
| 3082 | update_frame_with_menu (f); | 3081 | update_frame_with_menu (f, -1, -1); |
| 3083 | } | 3082 | } |
| 3084 | 3083 | ||
| 3085 | typedef enum { | 3084 | typedef enum { |
| @@ -3228,7 +3227,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, | |||
| 3228 | 3227 | ||
| 3229 | /* Force update of the current frame, so that the desired and the | 3228 | /* Force update of the current frame, so that the desired and the |
| 3230 | current matrices are identical. */ | 3229 | current matrices are identical. */ |
| 3231 | update_frame_with_menu (sf); | 3230 | update_frame_with_menu (sf, -1, -1); |
| 3232 | state[0].menu = menu; | 3231 | state[0].menu = menu; |
| 3233 | state[0].screen_behind = save_and_enable_current_matrix (sf); | 3232 | state[0].screen_behind = save_and_enable_current_matrix (sf); |
| 3234 | 3233 | ||
| @@ -3373,8 +3372,6 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, | |||
| 3373 | state[statecount - 1].y, | 3372 | state[statecount - 1].y, |
| 3374 | state[statecount - 1].pane, | 3373 | state[statecount - 1].pane, |
| 3375 | faces, x, y, first_item, 1); | 3374 | faces, x, y, first_item, 1); |
| 3376 | tty_hide_cursor (tty); | ||
| 3377 | fflush (tty->output); | ||
| 3378 | /* The call to display help-echo below will move the cursor, | 3375 | /* The call to display help-echo below will move the cursor, |
| 3379 | so remember its current position as computed by | 3376 | so remember its current position as computed by |
| 3380 | tty_menu_display. */ | 3377 | tty_menu_display. */ |
| @@ -3393,10 +3390,13 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx, | |||
| 3393 | item, so that screen readers and other accessibility aids | 3390 | item, so that screen readers and other accessibility aids |
| 3394 | know where the active region is. */ | 3391 | know where the active region is. */ |
| 3395 | cursor_to (sf, row, col); | 3392 | cursor_to (sf, row, col); |
| 3396 | tty_hide_cursor (tty); | ||
| 3397 | fflush (tty->output); | ||
| 3398 | prev_menu_help_message = menu_help_message; | 3393 | prev_menu_help_message = menu_help_message; |
| 3399 | } | 3394 | } |
| 3395 | /* Both tty_menu_display and help_callback invoke update_end, | ||
| 3396 | which calls tty_show_cursor. Re-hide it, so it doesn't show | ||
| 3397 | through the menus. */ | ||
| 3398 | tty_hide_cursor (tty); | ||
| 3399 | fflush (tty->output); | ||
| 3400 | } | 3400 | } |
| 3401 | 3401 | ||
| 3402 | sf->mouse_moved = 0; | 3402 | sf->mouse_moved = 0; |