From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Po Lu Newsgroups: gmane.emacs.devel Subject: Re: Allowing point to be outside the window? Date: Sat, 04 Dec 2021 19:18:38 +0800 Message-ID: <87czmcvcs1.fsf@yahoo.com> References: <87ilwd7zaq.fsf.ref@yahoo.com> <87ilwd7zaq.fsf@yahoo.com> <83bl24yaed.fsf@gnu.org> <87sfvg7l51.fsf@yahoo.com> <83zgpowu23.fsf@gnu.org> <87zgpo5tws.fsf@yahoo.com> <83pmqkwi6r.fsf@gnu.org> <87v90c5su6.fsf@yahoo.com> <83o864wg2a.fsf@gnu.org> <87ilwb68ck.fsf@yahoo.com> <83zgpnunfo.fsf@gnu.org> <87fsrf3xmd.fsf@yahoo.com> <83y257ulfp.fsf@gnu.org> <8735ne4e0e.fsf@yahoo.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="26244"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.60 (gnu/linux) Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Dec 04 12:19:55 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mtT58-0006gY-Cj for ged-emacs-devel@m.gmane-mx.org; Sat, 04 Dec 2021 12:19:54 +0100 Original-Received: from localhost ([::1]:38380 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mtT56-0007iF-9k for ged-emacs-devel@m.gmane-mx.org; Sat, 04 Dec 2021 06:19:52 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:58334) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mtT49-000718-Dv for emacs-devel@gnu.org; Sat, 04 Dec 2021 06:18:53 -0500 Original-Received: from sonic315-20.consmr.mail.ne1.yahoo.com ([66.163.190.146]:44998) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mtT45-00085W-Vy for emacs-devel@gnu.org; Sat, 04 Dec 2021 06:18:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1638616728; bh=ZEWvffjcQ2W3EJrTCJtE5wEEOi1NHZaxpG9jkTNh6/8=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From:Subject:Reply-To; b=Tra/7qqLN6/Dya7q9kSehGDK4qwkE9CRT6UMkNMp2IJ3CIOuGHG9sOmD/DQUQ88FOlZrz3AC+rZaFPTHtDDIyuXcVvTZ+QcsYk23vg1O/sBrIFPZZos0WFAvDXZCBYKh5SopYWKksKzjJ4Vats0W3U+FxmX5XqwaqNlvUshBRZfsubzvfYBo45qP6K0jC+H7WvCDSbM1rdgttQ/ljXHMBecDPhMaSkNtstKAck/cC3uBeifALjnElVmQGvb2VhZWvHKxbL+sbPGOsyYnEhiIcGUkIByeiH55ngEK8jRaboCMXKkCH5hGa8EFK/eo7PLX+Kss9Pt+f07Ap05U3kdR3g== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1638616728; bh=PkBge+wW2V+QQyb3LhJMEheQZfiOLQ7dwSJSz5y6Fre=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=nbJfJLdEQ447VcyHlKjCbQkTRVGGVgY3T1gRlT9qevA5n0mXZTZOjjtCDpzaOsGeZLIvUjE3mwLrxtuPr+DsujfcJwBceNDpOuvqpSPHGNsN9Zymv2Dy5VXs1OD/7FhzxcQDu0IGnmv3HNK3P2uT3AeNkBKx8e2a1E+gKCCtwDLHG8qEv2RlKqQCqGP3ONn+r7O7bKnXKkqguTZB9jJ3RwJLsbCl4UwdnHtCqkxQ+KYQIfxht/Rsl1HkRkl4/H6rgWSPY0bO4vtIaf6sbjIa3C6wNs05KI/Ip9q26IVx+IVbq4CrHAd53sA/oTE8N0xntupFNZp+2zXfElsr/gz2sA== X-YMail-OSG: Qxg_O5cVM1lIc0GSmpBAkZF6Mgaw1xTR0g5v3wQjSYgsUkMkf1j3ZIFvtqRWcDE Gl7YdEQb.Ddd7Wj3Fl9YLlqgcsggM0khv5QBonyr25.joNuCytT0lhkl1Xv7r8vIRR1nG8cfA2xE VUSlt9O4J69wpC35IQ6UwGwjnertQbLefCIAUjKr.rOTOt3CeIvJC__wgSAf8u6ndRzrddJYuWbw Ga56BciiqA09hJ4ptF1XUoLGP5Tzjy0BnP6dMVqnJRh9kD_oJzg4zDGxzmYtuMfKsMJkCiAHjphY baSY5e7XuvjSpMWLcfXe19g37zDVaL5Mrc85m3YVWTubDgY3HUOBFQgQ6vH_GtOa4VwqsvGJuOHE kmjxNmgAJIBlMagVTd3r51NfHwPE9k_MxT5vOAng5EAbw2BTSdSblzyTUdikmE1GFFet2VvGGFB0 rqvn78aSLHgHk6NipgSpZB1lqZ8k803tqOORLFcY6drGPo3c77DHGdo3CmKE4N7hJFpzBjo.gKLE wqeug6kaS3liDdpByBcMy32J3_lvAJZ8c44c_3WQWNPDGsnKA3ytaJBReO8Ffsdpdb0JYURDkjsM AtrlaDUJR9xHra1u6SKOx9rvi8IQBJX41TDFnAaD5QBd1urvlY7PIzPnOFJXnhFNa74kLVAuJyEe plVzK.JPtXG8E5fGOiC1vYgE3ZORN80hU5osmsUeBuvQ4Sa33UQHS_fB4QkLEcFaXYJ9VrJ6eeLg 1yAJIh3GQPmYTFFTU4C2KFaCK91lH5FcWmqlptkIGW4HKhsBRVj8Xwowb0Sk2J933YHXuPDX6K8F ecYuxRUsCEhl.KTMpjaDfEgCANRkIbc4sh.HehfSYv X-Sonic-MF: Original-Received: from sonic.gate.mail.ne1.yahoo.com by sonic315.consmr.mail.ne1.yahoo.com with HTTP; Sat, 4 Dec 2021 11:18:48 +0000 Original-Received: by kubenode510.mail-prod1.omega.sg3.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID 624500ba9d66db8fca25ff7c24910afd; Sat, 04 Dec 2021 11:18:42 +0000 (UTC) In-Reply-To: <8735ne4e0e.fsf@yahoo.com> (Po Lu's message of "Tue, 30 Nov 2021 09:40:33 +0800") X-Mailer: WebService/1.1.19306 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.yahoo Received-SPF: pass client-ip=66.163.190.146; envelope-from=luangruo@yahoo.com; helo=sonic315-20.consmr.mail.ne1.yahoo.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:280907 Archived-At: --=-=-= Content-Type: text/plain Po Lu writes: > Eli Zaretskii writes: > >> It might also be called by redisplay, > > That is what I'm worried about, thanks. > >> ... it makes very little sense to me to introduce such a feature only >> for the sake of pixel-wise scrolling. We should allow such a mode >> with all the Emacs commands, not just in pixel-wise scrolling. And >> anyway, Emacs might call scrolling commands as part of other commands, >> not just because the user types C-v. > > Makes sense, I will work on it. I haven't figured out most of the user level command things, but here's a patch that allows point to be outside a window. Some redisplay optimizations are disabled, but I hope to solve that soon. WDYT? Thanks. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Make-it-possible-for-point-to-appear-outside-a-windo.patch >From f2295fbfceff3ef0db91c9c5b9e5155fefe12697 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 4 Dec 2021 18:33:53 +0800 Subject: [PATCH] Make it possible for point to appear outside a window * src/window.h (struct window): New field `cursor_visible_p'. * src/xdisp.c (redisplay_internal, redisplay_window): Allow point to appear outside the window. (set_cursor_from_row): Set cursor_visible_p appropriately. (try_window_id) (try_cursor_movement): Disable optimization when point is allowed to be invisible. (display_and_set_cursor): Erase cursor if invisible. (try_window): Allow some things. (syms_of_xdisp) : New variable. --- src/window.h | 4 ++ src/xdisp.c | 194 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 150 insertions(+), 48 deletions(-) diff --git a/src/window.h b/src/window.h index 2400c422c1..e9528ff02f 100644 --- a/src/window.h +++ b/src/window.h @@ -445,6 +445,10 @@ #define WINDOW_H_INCLUDED window. */ bool_bf suspend_auto_hscroll : 1; + /* True if the cursor is supposed to be visible in this + window. */ + bool_bf cursor_visible_p : 1; + /* Amount by which lines of this window are scrolled in y-direction (smooth scrolling). */ int vscroll; diff --git a/src/xdisp.c b/src/xdisp.c index 7ca3977200..7a0949d514 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -16118,6 +16118,8 @@ #define AINC(a,i) \ tlbufpos = this_line_start_pos; tlendpos = this_line_end_pos; if (!consider_all_windows_p + /* TODO: enable this optimization. */ + && keep_point_visible && CHARPOS (tlbufpos) > 0 && !w->update_mode_line && !current_buffer->clip_changed @@ -16989,6 +16991,8 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, comes from a text property, not from an overlay. */ bool string_from_text_prop = false; + w->cursor_visible_p = false; + /* Don't even try doing anything if called for a mode-line or header-line or tab-line row, since the rest of the code isn't prepared to deal with such calamities. */ @@ -17575,6 +17579,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, CHARPOS (this_line_start_pos) = 0; } + w->cursor_visible_p = true; return true; } @@ -18183,6 +18188,10 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, return rc; #endif + /* TODO: enable this optimization. */ + if (!keep_point_visible) + return CURSOR_MOVEMENT_CANNOT_BE_USED; + /* Previously, there was a check for Lisp integer in the if-statement below. Now, this field is converted to ptrdiff_t, thus zero means invalid position in a buffer. */ @@ -18770,6 +18779,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) clear_glyph_matrix (w->desired_matrix); } + debug_method_add (w, "real redisplay starts"); + /* Otherwise set up data on this window; select its buffer and point value. */ /* Really select the buffer, for the sake of buffer-local @@ -18964,34 +18975,39 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) if (w->cursor.vpos < 0) { - /* If point does not appear, try to move point so it does - appear. The desired matrix has been built above, so we - can use it here. First see if point is in invisible - text, and if so, move it to the first visible buffer - position past that. */ - struct glyph_row *r = NULL; - Lisp_Object invprop = - get_char_property_and_overlay (make_fixnum (PT), Qinvisible, - Qnil, NULL); - - if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0) + if (!keep_point_visible) + w->cursor_visible_p = false; + else { - ptrdiff_t alt_pt; - Lisp_Object invprop_end = - Fnext_single_char_property_change (make_fixnum (PT), Qinvisible, - Qnil, Qnil); + /* If point does not appear, try to move point so it does + appear. The desired matrix has been built above, so we + can use it here. First see if point is in invisible + text, and if so, move it to the first visible buffer + position past that. */ + struct glyph_row *r = NULL; + Lisp_Object invprop = + get_char_property_and_overlay (make_fixnum (PT), Qinvisible, + Qnil, NULL); + + if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0) + { + ptrdiff_t alt_pt; + Lisp_Object invprop_end = + Fnext_single_char_property_change (make_fixnum (PT), Qinvisible, + Qnil, Qnil); - if (FIXNATP (invprop_end)) - alt_pt = XFIXNAT (invprop_end); - else - alt_pt = ZV; - r = row_containing_pos (w, alt_pt, w->desired_matrix->rows, - NULL, 0); + if (FIXNATP (invprop_end)) + alt_pt = XFIXNAT (invprop_end); + else + alt_pt = ZV; + r = row_containing_pos (w, alt_pt, w->desired_matrix->rows, + NULL, 0); + } + if (r) + new_vpos = MATRIX_ROW_BOTTOM_Y (r); + else /* Give up and just move to the middle of the window. */ + new_vpos = window_box_height (w) / 2; } - if (r) - new_vpos = MATRIX_ROW_BOTTOM_Y (r); - else /* Give up and just move to the middle of the window. */ - new_vpos = window_box_height (w) / 2; } if (!cursor_row_fully_visible_p (w, false, false, false)) @@ -19223,10 +19239,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) IF_DEBUG (debug_method_add (w, "1")); clear_glyph_matrix (w->desired_matrix); if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0) - /* -1 means we need to scroll. - 0 means we need new matrices, but fonts_changed - is set in that case, so we will detect it below. */ - goto try_to_scroll; + { + /* -1 means we need to scroll. + 0 means we need new matrices, but fonts_changed + is set in that case, so we will detect it below. */ + goto try_to_scroll; + } } if (f->fonts_changed) @@ -19253,9 +19271,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) clear_glyph_matrix (w->desired_matrix); } + if (!keep_point_visible) + goto maybe_try_window; + try_to_scroll: - /* Redisplay the mode line. Select the buffer properly for that. */ + /* Redisplay the mode line. Select the buffer properly for that. */ if (!update_mode_line) { update_mode_line = true; @@ -19317,6 +19338,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) /* Determine the window start relative to point. */ init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); it.current_y = it.last_visible_y; + if (centering_position < 0) { ptrdiff_t margin_pos = CHARPOS (startp); @@ -19584,6 +19606,53 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) centering_position = 0; goto recenter; } + goto done; + + maybe_try_window: + + /* Set the window start position here explicitly if it is outside + the accessible portion of the buffer. */ + + if (CHARPOS (startp) < BEGV + || CHARPOS (startp) > ZV) + { + if (CHARPOS (startp) < BEGV) + set_marker_both (w->start, Qnil, BEGV, BEGV_BYTE); + else + set_marker_both (w->start, Qnil, ZV, ZV_BYTE); + + SET_TEXT_POS_FROM_MARKER (startp, w->start); + + /* Run scroll hooks. */ + startp = run_window_scroll_functions (window, startp); + } + + /* We invoke try_window and try_window_reusing_current_matrix below, + and they manipulate the bidi cache. Save and restore the cache + state of our iterator, so we could continue using it after that. */ + itdata = bidi_shelve_cache (); + + /* Redisplay the window. */ + use_desired_matrix = false; + if (!current_matrix_up_to_date_p + || windows_or_buffers_changed + || f->cursor_type_changed + /* Don't use try_window_reusing_current_matrix in this case + because it can have changed the buffer. */ + || !NILP (Vwindow_scroll_functions) + || !just_this_one_p + || MINI_WINDOW_P (w) + || !(used_current_matrix_p + = try_window_reusing_current_matrix (w))) + use_desired_matrix = (try_window (window, startp, 0) == 1); + + bidi_unshelve_cache (itdata, false); + + /* If new fonts have been loaded (due to fontsets), give up. We + have to start a new redisplay since we need to re-adjust glyph + matrices. */ + if (f->fonts_changed) + goto need_larger_matrices; done: @@ -19591,6 +19660,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) w->start_at_line_beg = (CHARPOS (startp) == BEGV || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'); + if (!keep_point_visible + && (!w->cursor_visible_p + || w->cursor.vpos == -1) + && w->phys_cursor_on_p) + erase_phys_cursor (w); + /* Display the mode line, header line, and tab-line, if we must. */ if ((update_mode_line /* If window not full width, must redo its mode line @@ -19801,6 +19876,8 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) struct frame *f = XFRAME (w->frame); int cursor_vpos = w->cursor.vpos; + debug_method_add (w, "try_window"); + /* Make POS the new window start. */ set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos)); @@ -19960,6 +20037,10 @@ try_window_reusing_current_matrix (struct window *w) return false; #endif + /* TODO: enable this optimization. */ + if (!keep_point_visible) + return false; + /* The variable new_start now holds the new window start. The old start `start' can be determined from the current matrix. */ SET_TEXT_POS_FROM_MARKER (new_start, w->start); @@ -20875,6 +20956,8 @@ #define GIVE_UP(X) return 0 row = row_containing_pos (w, PT, r0, NULL, 0); if (row) set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0); + else + w->cursor_visible_p = false; return 1; } } @@ -20915,6 +20998,8 @@ #define GIVE_UP(X) return 0 row = row_containing_pos (w, PT, r0, NULL, 0); if (row) set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0); + else + w->cursor_visible_p = false; return 2; } } @@ -21152,6 +21237,8 @@ #define GIVE_UP(X) return 0 last_unchanged_at_beg_row + 1, 0); if (row) set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); + else + w->cursor_visible_p = false; } /* Start from first_unchanged_at_end_row looking for PT. */ @@ -21162,6 +21249,8 @@ #define GIVE_UP(X) return 0 if (row) set_cursor_from_row (w, row, w->current_matrix, delta, delta_bytes, dy, dvpos); + else + w->cursor_visible_p = false; } /* Give up if cursor was not found. */ @@ -21173,24 +21262,25 @@ #define GIVE_UP(X) return 0 } /* Don't let the cursor end in the scroll margins. */ - { - int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS); - int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height; - - if ((w->cursor.y < this_scroll_margin - && CHARPOS (start) > BEGV) - /* Old redisplay didn't take scroll margin into account at the bottom, - but then global-hl-line-mode doesn't scroll. KFS 2004-06-14 */ - || (w->cursor.y - + (cursor_row_fully_visible_p (w, false, true, true) - ? 1 - : cursor_height + this_scroll_margin)) > it.last_visible_y) - { - w->cursor.vpos = -1; - clear_glyph_matrix (w->desired_matrix); - return -1; - } - } + if (w->cursor_visible_p) + { + int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS); + int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height; + + if ((w->cursor.y < this_scroll_margin + && CHARPOS (start) > BEGV) + /* Old redisplay didn't take scroll margin into account at the bottom, + but then global-hl-line-mode doesn't scroll. KFS 2004-06-14 */ + || (w->cursor.y + + (cursor_row_fully_visible_p (w, false, true, true) + ? 1 + : cursor_height + this_scroll_margin)) > it.last_visible_y) + { + w->cursor.vpos = -1; + clear_glyph_matrix (w->desired_matrix); + return -1; + } + } /* Scroll the display. Do it before changing the current matrix so that xterm.c doesn't get confused about where the cursor glyph is @@ -32387,6 +32477,10 @@ display_and_set_cursor (struct window *w, bool on, && new_cursor_width != w->phys_cursor_width))) erase_phys_cursor (w); + if (!w->cursor_visible_p + || w->cursor.vpos == -1) + return; + /* Don't check phys_cursor_on_p here because that flag is only set to false in some cases where we know that the cursor has been completely erased, to avoid the extra work of erasing the cursor @@ -35491,6 +35585,10 @@ syms_of_xdisp (void) x_stretch_cursor_p = 0; #endif + DEFVAR_BOOL ("keep-point-visible", keep_point_visible, + doc: /* Non-nil means to keep the point visible. */); + keep_point_visible = 1; + DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace, doc: /* Non-nil means highlight trailing whitespace. The face used for trailing whitespace is `trailing-whitespace'. */); -- 2.33.1 --=-=-=--