From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Po Lu via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#50660: 28.0.50; Text artifacting when the cursor moves over text under mouse face that originally displayed a box Date: Sat, 02 Oct 2021 20:52:58 +0800 Message-ID: <878rzbd1w5.fsf@yahoo.com> References: <87czp6ysw7.fsf.ref@yahoo.com> <838rzs4i09.fsf@gnu.org> <87fsu06oxi.fsf@yahoo.com> <83ee9j3ju3.fsf@gnu.org> <834kaf3ets.fsf@gnu.org> <8335pz3dli.fsf@gnu.org> <87r1dj4q4m.fsf@yahoo.com> <83zgs71su7.fsf@gnu.org> <87k0jb4k5l.fsf@yahoo.com> <83sfxz1pw0.fsf@gnu.org> <87o88m14g0.fsf@yahoo.com> <83sfxyxeer.fsf@gnu.org> <87h7ee1252.fsf@yahoo.com> <83pmt2xcox.fsf@gnu.org> <87lf3myhlb.fsf@yahoo.com> <87a6jzvnpq.fsf@yahoo.com> <83o88fom1k.fsf@gnu.org> <871r5bvex8.fsf@yahoo.com> <83v92mkzft.fsf@gnu.org> <87k0j0rwo3.fsf@yahoo.com> <838rzbddfa.fsf@gnu.org> Reply-To: Po Lu 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="31126"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) Cc: larsi@gnus.org, 50660@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Oct 02 15:09:49 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1mWelw-0007sI-Jk for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 02 Oct 2021 15:09:48 +0200 Original-Received: from localhost ([::1]:36600 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mWelu-00018c-1v for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 02 Oct 2021 09:09:47 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:33138) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mWeWg-0001LH-2t for bug-gnu-emacs@gnu.org; Sat, 02 Oct 2021 08:54:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:46639) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mWeWf-0000l7-PD for bug-gnu-emacs@gnu.org; Sat, 02 Oct 2021 08:54:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1mWeWf-0001RG-Mi for bug-gnu-emacs@gnu.org; Sat, 02 Oct 2021 08:54:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Po Lu Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 02 Oct 2021 12:54:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 50660 X-GNU-PR-Package: emacs Original-Received: via spool by 50660-submit@debbugs.gnu.org id=B50660.16331791945469 (code B ref 50660); Sat, 02 Oct 2021 12:54:01 +0000 Original-Received: (at 50660) by debbugs.gnu.org; 2 Oct 2021 12:53:14 +0000 Original-Received: from localhost ([127.0.0.1]:58185 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mWeVu-0001Q8-6R for submit@debbugs.gnu.org; Sat, 02 Oct 2021 08:53:14 -0400 Original-Received: from sonic302-21.consmr.mail.ne1.yahoo.com ([66.163.186.147]:44463) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mWeVs-0001Pv-La for 50660@debbugs.gnu.org; Sat, 02 Oct 2021 08:53:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1633179186; bh=UUneFM/0tX1rThJv4a22qJYttOyH9mwk8jpzK4UW41Q=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From:Subject:Reply-To; b=oVbcZHtij9ZJLBvqQojK9NKfZn6kX/+bL6UXYUnHCpfJi4rEsCvYwuYXlTAZ6Ii3NUFHPMS8mewMIr8Kp5yWgptMJMzTegPvRaeMkliZn/ZLt9XK82MfwgMG+faZOcbhdcJyrbHRh9QH3ih6pmxfg2RfWQtFBLFQkaIbnFZoUNLYcz2mAk0D/SfN7iYDVh1r95cfjjUkHP9LOj7tngToNA1IWeJMiwshs2nNvkHQqz8y58dEyAjmfmT2m7g3Iwz+Pl/QhYt8YoP29XOfnSoAsJ/ttSAcNSR/BOqCfAGnBpJbW7u1Yn9OiveRRHoG8PqA5rsQ2cCDEmah86885of7UA== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1633179186; bh=YikpR1nE9ouZJODsO1KZS286CYB3d8r73ciWxerat0g=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=P5SahmDT3YX6TEV0Wzgdkh157+dnUN3nU/3y5yjLYxekUkoNIkIydJdvF1Bz6rzI41houjANJ7OJKEjh17siBwAbn8nbEsBtZH9QvyQ4kAAL8GvWkzLwoMBMLk7cCrdvUR0OAHqPd2grce/dHnC8yyphE28xQelBTdU890yCqZc/7Zp/8rmx6X2uvXbdeQ8uuE0XIHVa/Hhum/Fp8fukpmLZ2AzdEox9I+YpzHM0b4eHQavyRyN+O2I1xIQbvQ0Zb8iML/rOqGp7mALQubojjjgH2cwxlIHU2LKYgy+XOpxn24AlaAVu8byXAT38JluhI6KSAZVeUdIzhndqWXI8zw== X-YMail-OSG: ATQMEtMVM1nu6YqrKfMfP.onri87t.w_Mbqiv4Db.BAFKIixdLcAmJmn3V0Ilww 3tSp1u5ejKGqifGI5vFd4PR_lU6vCJaXKrhjrAshXTSMI7rz4A1gayJ470Y7X4pq7PJ0NBQZG8Zf eJ78PTfK73QpREP99TjkYa0C1nEFo1smoVGYXYV_DadcVuaOGOaXsm2JeRqOMoidhix3PurVRmI8 nkVc_ztvWX2u_Rj0gsvmXPw9_QpWtBj64P4o7vkA5lFQaRGRHA7yYZhLA3yt2VFDL9OQmXu7UDhY YsegLttXlL2e3E2i93HHbsOxiltxqYtIIm7BeMCiRfezSGK79kMVIOHrj9ddwoxcWnOJYB_zJZK7 mvIcOa9WRR97ax4604c797IbFf7UjCqQE.ka5Whgh8xHnIdYkLPr6HMBWHVK6M9vr2HAV1sfpVID IGvLm98nuBIYmDIjVpNtNFYRBOAMhg_zmi8jof1d.s6q2t88EL7muki5_ruVWnavuHHhmCNK5MdZ nHxQLdE5DUXSBdjlEeW_Q.2pOuAeekEAkSDiNCkubo8.XmTslAfqwLkTZ3bZ4fQ_BGN6SmHnpInS yQsD4dW4rImdQoAlGrFglWjzs1sJzYdzB3QQSrX0IjmKjTx2lKSqfKy2McC7h8wiZ.3JprcwERqX qj0Fy6MkKs9RQkhV36s8vaK.d_WzJr6.26TLNN5y7Cdgc4NwJY.LG3UoZIjC5_OIgzWJqZaWtv3T l6NUscuJG9LM3EqDzPD1uitdZ_zqLdKlaZLcD7DsYNikV_8S2Tpq0SRT82jh2ukXKNmUW1tgNWdS BeTu.253cuEM0n6SDjUF9l998e2qvcbZOw9U.SBAr2 X-Sonic-MF: Original-Received: from sonic.gate.mail.ne1.yahoo.com by sonic302.consmr.mail.ne1.yahoo.com with HTTP; Sat, 2 Oct 2021 12:53:06 +0000 Original-Received: by kubenode518.mail-prod1.omega.sg3.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID c1da78d18a9b8de9fb1294d5befa1c23; Sat, 02 Oct 2021 12:53:02 +0000 (UTC) In-Reply-To: <838rzbddfa.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 02 Oct 2021 11:43:53 +0300") X-Mailer: WebService/1.1.19076 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.yahoo X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:216141 Archived-At: --=-=-= Content-Type: text/plain Eli Zaretskii writes: Thanks for the comments, I'm attaching a rectified patch. I think the rest of what you've brought up has been resolved by the new patch, but I would like to clarify something here: > There's no reason to use -= and += here. The callers never initialize > the argument to anything but zero, nor should they. This function > _calculates_ the offset, it doesn't _correct_ it. So a simple > assignment should do better, because using the above begs the > question: what could the initial value be? The callers should add or > subtract the corrections as they see fit. I changed the function to use an internal accumulator variable initialized to 0. The -= and += is still necessary, as we are inside a loop which can potentially go through many glyphs that are relevant. Thanks. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=fix-cursor-position.patch diff --git a/src/dispnew.c b/src/dispnew.c index 0c31319917..62f7074dcd 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -3848,6 +3848,9 @@ gui_update_window_end (struct window *w, bool cursor_on_p, w->output_cursor.hpos, w->output_cursor.vpos, w->output_cursor.x, w->output_cursor.y); + if (cursor_in_mouse_face_p (w) && cursor_on_p) + mouse_face_overwritten_p = 1; + if (draw_window_fringes (w, true)) { if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) diff --git a/src/xdisp.c b/src/xdisp.c index 2e72f6b591..f2b4e43592 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1179,7 +1179,9 @@ #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false) static Lisp_Object get_it_property (struct it *, Lisp_Object); static Lisp_Object calc_line_height_property (struct it *, Lisp_Object, struct font *, int, bool); - +static void get_cursor_offset_for_mouse_face (struct window *w, + struct glyph_row *row, + int *offset); #endif /* HAVE_WINDOW_SYSTEM */ static void produce_special_glyphs (struct it *, enum display_element_type); @@ -29509,6 +29511,8 @@ produce_image_glyph (struct it *it) if (face->box != FACE_NO_BOX) { + /* If you change the logic here, please change it in + get_cursor_offset_for_mouse_face as well. */ if (face->box_horizontal_line_width > 0) { if (slice.y == 0) @@ -31741,6 +31745,10 @@ erase_phys_cursor (struct window *w) Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); int hpos = w->phys_cursor.hpos; int vpos = w->phys_cursor.vpos; +#ifdef HAVE_WINDOW_SYSTEM + int mouse_delta; + int phys_x = w->phys_cursor.x; +#endif bool mouse_face_here_p = false; struct glyph_matrix *active_glyphs = w->current_matrix; struct glyph_row *cursor_row; @@ -31810,6 +31818,16 @@ erase_phys_cursor (struct window *w) && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0) mouse_face_here_p = true; +#ifdef HAVE_WINDOW_SYSTEM + /* The problem solved by the code below is outlined + in the comment above get_cursor_offset_for_mouse_face. */ + if (mouse_face_here_p) + { + get_cursor_offset_for_mouse_face (w, cursor_row, &mouse_delta); + w->phys_cursor.x += mouse_delta; + } +#endif + /* Maybe clear the display under the cursor. */ if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) { @@ -31845,6 +31863,9 @@ erase_phys_cursor (struct window *w) draw_phys_cursor_glyph (w, cursor_row, hl); mark_cursor_off: +#ifdef HAVE_WINDOW_SYSTEM + w->phys_cursor.x = phys_x; +#endif w->phys_cursor_on_p = false; w->phys_cursor_type = NO_CURSOR; } @@ -32081,6 +32102,9 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) && hlinfo->mouse_face_end_row < w->current_matrix->nrows) { bool phys_cursor_on_p = w->phys_cursor_on_p; +#ifdef HAVE_WINDOW_SYSTEM + int mouse_off = 0; +#endif struct glyph_row *row, *first, *last; first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row); @@ -32154,6 +32178,16 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) row->mouse_face_p = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; } +#ifdef HAVE_WINDOW_SYSTEM + if ((MATRIX_ROW_VPOS (row, w->current_matrix) + == w->phys_cursor.vpos) + /* Otherwise this crashes when highlighting a pseudo + window, such as the toolbar which can't have a cursor + anyway. */ + && !w->pseudo_window_p + && draw == DRAW_MOUSE_FACE) + get_cursor_offset_for_mouse_face (w, row, &mouse_off); +#endif } /* When we've written over the cursor, arrange for it to @@ -32163,6 +32197,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) { #ifdef HAVE_WINDOW_SYSTEM int hpos = w->phys_cursor.hpos; + int old_phys_cursor_x = w->phys_cursor.x; /* When the window is hscrolled, cursor hpos can legitimately be out of bounds, but we draw the cursor at the corresponding @@ -32174,7 +32209,9 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) block_input (); display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos, - w->phys_cursor.x, w->phys_cursor.y); + w->phys_cursor.x + mouse_off, + w->phys_cursor.y); + w->phys_cursor.x = old_phys_cursor_x; unblock_input (); #endif /* HAVE_WINDOW_SYSTEM */ } @@ -35926,4 +35963,110 @@ cancel_hourglass (void) } } +#ifdef HAVE_WINDOW_SYSTEM +/* Get the offset to apply before drawing phys_cursor, and return it + in OFFSET. ROW should be a row that is under mouse face and contains + the phys cursor. + + This is required because the produce_XXX_glyph series of functions + add the width of the various vertical box lines to the total width + of the glyph, but isn't updated when the row is put under mouse + face, which can have different box dimensions. */ +static void +get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row, + int *offset) +{ + int sum = 0; + /* Return because the mode line can't possibly have a cursor. */ + if (row->mode_line_p) + return; + + block_input (); + + struct frame *f = WINDOW_XFRAME (w); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + struct glyph *start, *end; + struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id); + int hpos = w->phys_cursor.hpos; + end = &row->glyphs[TEXT_AREA][hpos]; + + if (!row->reversed_p) + { + if (MATRIX_ROW_VPOS (row, w->current_matrix) == + hlinfo->mouse_face_beg_row) + start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col]; + else + start = row->glyphs[TEXT_AREA]; + } + else + { + if (MATRIX_ROW_VPOS (row, w->current_matrix) == + hlinfo->mouse_face_end_row) + start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col]; + else + start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1]; + } + + /* Calculate an offset to correct phys_cursor x if we are + drawing the cursor in the mouse face. */ + + for (; row->reversed_p ? start >= end : start <= end; + row->reversed_p ? --start : ++start) + { + struct glyph *g = start; + struct face *mouse = mouse_face; + struct face *regular_face = FACE_FROM_ID (f, g->face_id); + + bool do_left_box_p = g->left_box_line_p; + bool do_right_box_p = g->right_box_line_p; + + /* This is required because we test some parameters + of the image slice before applying the box in + produce_image_glyph. */ + + if (g->type == IMAGE_GLYPH) + { + if (!row->reversed_p) + { + struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w), + g->u.img_id); + do_left_box_p = g->left_box_line_p && + g->slice.img.x == 0; + do_right_box_p = g->right_box_line_p && + g->slice.img.x + g->slice.img.width == img->width; + } + else + { + struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w), + g->u.img_id); + do_left_box_p = g->left_box_line_p && + g->slice.img.x + g->slice.img.width == img->width; + do_right_box_p = g->right_box_line_p && + g->slice.img.x == 0; + } + } + + /* If the glyph has a left box line, subtract it the + offset. */ + if (do_left_box_p) + sum -= max (0, regular_face->box_vertical_line_width); + /* Likewise with the right box line, as there may be a + box there as well. */ + if (do_right_box_p) + sum -= max (0, regular_face->box_vertical_line_width); + /* Now we add the line widths from the new face. */ + if (g->left_box_line_p) + sum += max (0, mouse->box_vertical_line_width); + if (g->right_box_line_p) + sum += max (0, mouse->box_vertical_line_width); + } + + if (row->reversed_p) + sum = -sum; + + *offset = sum; + + unblock_input (); +} +#endif #endif /* HAVE_WINDOW_SYSTEM */ --=-=-=--