From: Gerd Möllmann Date: Wed, 23 Oct 2024 10:59:09 +0000 (+0200) Subject: Handle obscured cursor differently X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=7d85b0ab4a6d81ef78cd1df9b879b589030d5fe4;p=emacs.git Handle obscured cursor differently This also fixes an error made when porting this to savannah. * src/dispnew.c (abs_cursor_pos, (is_cursor_obscured) (terminal_cursor_magic): Port correctly and fix. (cherry picked from commit 9b8d1e0addeca9b508324537e7743d0af508a630) --- diff --git a/src/dispnew.c b/src/dispnew.c index 1235ab431c0..0d7e7770bb0 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -3804,25 +3804,68 @@ update_tty_frame (struct frame *f, bool force_p) return false; } -static void +/* Return the cursor position of the selected window of frame F, in + absolute coordinates in *X and *Y. Note that if F is a child frame, + its cursor may be clipped, i.e. outside of the bounds of the terminal + window. Value is false if the selected window of F doesn't have + valid cursor position info. */ + +static bool abs_cursor_pos (struct frame *f, int *x, int *y) { - frame_pos_abs (f, x, y); struct window *w = XWINDOW (f->selected_window); - *x += w->cursor.x; - *y += w->cursor.y; + if (w->cursor.vpos >= 0 + /* The cursor vpos may be temporarily out of bounds + in the following situation: There is one window, + with the cursor in the lower half of it. The window + is split, and a message causes a redisplay before + a new cursor position has been computed. */ + && w->cursor.vpos < WINDOW_TOTAL_LINES (w)) + { + int wx = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos); + int wy = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos); + + wx += max (0, w->left_margin_cols); + + int fx, fy; + frame_pos_abs (f, &fx, &fy); + *x = fx + wx; + *y = fy + wy; + return true; + } + + *x = *y = 0; + return false; +} + +static bool +is_in_matrix (struct frame *f, int x, int y) +{ + struct frame *root = root_frame (f); + if (x < 0 || x >= root->current_matrix->matrix_w || y < 0 + || y >= root->current_matrix->matrix_h) + return false; + return true; } -/* Is the terminal cursor of frame F obscured by a child frame? */ +/* Is the terminal cursor of the selected frame obscured by a child + frame? */ static bool is_cursor_obscured (void) { + /* Give up if we can't tell where the cursor currently is. */ int x, y; - abs_cursor_pos (SELECTED_FRAME (), &x, &y); + if (!abs_cursor_pos (SELECTED_FRAME (), &x, &y)) + return false; + + /* (x, y) may be outside of the root frame in case the selected frame is a + child frame which is clipped. */ struct frame *root = root_frame (SELECTED_FRAME ()); + if (!is_in_matrix (root, x, y)) + return true; + struct glyph_row *cursor_row = MATRIX_ROW (root->current_matrix, y); - eassert (x < root->current_matrix->matrix_w); struct glyph *cursor_glyph = cursor_row->glyphs[0] + x; return cursor_glyph->frame != SELECTED_FRAME (); } @@ -3851,14 +3894,18 @@ terminal_cursor_magic (struct frame *root, struct frame *topmost_child) Lisp_Object frame; XSETFRAME (frame, topmost_child); + int x, y; Lisp_Object cursor = Fframe_parameter (frame, Qtty_non_selected_cursor); - if (!NILP (cursor)) + if (!NILP (cursor) && abs_cursor_pos (topmost_child, &x, &y)) { - int x, y; - abs_cursor_pos (topmost_child, &x, &y); - cursor_to (root, y, x); - tty_show_cursor (FRAME_TTY (topmost_child)); - } + if (is_in_matrix (root, x, y)) + { + cursor_to (root, y, x); + tty_show_cursor (FRAME_TTY (topmost_child)); + } + else + tty_hide_cursor (FRAME_TTY (root)); + } } }