Tk Source Code

View Ticket
Login
Ticket UUID: 0ca1768080319a4e1447486a46b962c1de03ed40
Title: Text widget: @x,y index inconsistent with insert mark placement
Type: Bug Version: 8.6.11
Submitter: anonymous Created on: 2021-04-15 23:25:34
Subsystem: 75. wish Assigned To: fvogel
Priority: 3 Low Severity: Minor
Status: Closed Last Modified: 2021-04-20 17:12:53
Resolution: Fixed Closed By: fvogel
    Closed on: 2021-04-20 17:12:53
Description:

When clicking on a letter in a text widget, the insert mark is placed
either to the left or to the right side of that letter, depending on
the exact position of the mouse pointer relative to the center of the letter.
However, when the same x,y coordinates of that click are fed
to the index command, the result is a different index, apparently pointing
always at the start of the letter.

How to replicate the problem:

package require Tk
pack [text .t -font {-family serif -size 144} -width 2 -height 2]
.t insert end W
bind .t <ButtonPress-1> {puts [%W index @%x,%y]}
bind .t <ButtonRelease-1> {puts [%W index insert]}
Click a little to the right of the center of the letter 'W',
and observe the index printed for the @x,y pair: it will be 1.0.
Now, release the mouse button and observe the index printed for
the insert mark: it will be 1.1, and the insertion symbol will indeed be flashing
after the letter. The two results are inconsistent.

To get a consistent index for both @x,y and insert, I use the
following workaround:
proc Idx@ {W x y} {
	lassign [$W bbox @$x,$y] xc yc w
	$W index @[expr {$x >= $xc + $w / 2 ? $xc + $w : $xc}],$y
}
bind .t <ButtonPress-1> {puts [%W index @%x,%y]\t[Idx@ %W %x %y]}

dzach

User Comments: fvogel added on 2021-04-20 17:12:53:

The behavior described in the previous message is the object of [b461c70399]. Follow-up is there.


anonymous added on 2021-04-19 13:12:08:

Here is a behavior which seems to be unique to Tk's text widget:

Clicking on the left of the center of the empty space remaining from a wrapped line
places the insert mark at the end of the last character of that line.
Clicking on the right places the insert mark at the beginning of the next line.

I checked LibreOffice Writer, Kubuntu's kate and kwrite, Mate's Pluma, and Xfce's
Mousepad, and they all place the insert mark at the end of the last character
of the wrapped line, and not at the start of the next line.


To replicate this behavior:

package require Tk
pack [text .t -width 10 -height 3 -font {-size 72} -wrap word]
.t insert end "123456 1234567"
Click on the first line, at the far right of that line's empty space. The insert mark
goes to the start of the next line. Apparently, this is based on the same center-line
principle which is applied to single characters.

dzach


fvogel added on 2021-04-18 12:09:47:
Thanks for the feedback. Documentation fix now merged into core-8-6-branch, trunk and revised_text.

anonymous added on 2021-04-17 11:41:53:
There is no other description of the placement of the insert mark that I can find, 
nor would any be required, other than the one in BINDINGS.1, I think.

I was doing some coding that involved the text widget, which resulted in 
some of these bug reports. This one puzzled me for a while while trying to 
achieve some tag functionality, and my views may reflect my struggles with that. 
The little workaround I posted here solved the issue for me. I understand that 
the two operations, i.e. getting the index for @x,y and moving the insert mark, 
both caused by the same single mouse click, may well be independent.

In fact, I just checked LibreOffice Writer; the way placement of the insert mark is
done there is the same as in the text widget, i.e. left/right of the centerline. 
So, even as a matter of consensus, the current approach seems to be the one 
prevailing.

I believe this issue may be closed now. I very much appreciate your prompt responses.

dzach

fvogel added on 2021-04-17 09:27:41:
> having the insert mark placement done this way, instead of the way
> described in the manual

This is precisely where I still do not follow you. Where in the manual (except in the BINDINGS section, which I have now corrected) is the insert mark placement described differently from what we can observe being implemented?

anonymous added on 2021-04-16 23:35:32:
fvogel, thank you for bearing with me. I don't see this as being a serious problem, it's just that I find no good reason for having the insert mark placement done this way, instead of the way described in the manual.

Truth is, I hadn't noticed the BINDINGS.1 statement before starting this; had I had, this ticket would have been just asking for a proper implementation of what the manual specifies, which seems to me consistent behavior.

Whatever the result, thank you for considering my view.

dzach

fvogel added on 2021-04-16 21:38:40:

I'm sorry, despite your valuable efforts to explain your point (thank you!), I still don't really see what you're after. I think we both see/understand the difference in behavior between "index @x,y" and "index insert". But, really, these two things are different beasts and I don't follow you when you seem to want them to return the same value.

"index @x,y" (always) returns the character index that covers pixel at x,y, in other words it returns the character whose bounding box contains the pixel at x,y. I think the reason for @x,y to behave like it behaves is that this allows to designate a character by hovering the mouse over it for instance, which is a feature.

"index insert" (always) returns the index of the character located immediately after the insert mark, whatever the location of this mark is. It's simply another feature: Tk provides a way to introspect where the insert cursor is.

I don't see any reason why the two commands should return the same thing (except in the special case where the insert mark is just before the character covering the x,y coordinates in question). The two commands are simply providing two different features.

I agree you have spotted a line in the manual where the behavior is not accurately described. I propose to fix this as in [1be076e675].


anonymous added on 2021-04-16 19:59:22:
I see your point, but this idiosyncrasy makes it more costly to utilize the index 
base @x,y without actually offering a reason for that, and is in contrast with the 
manual which describes a consistent behavior for both the 'index @x,y' and 
'index insert' commands.

Is there an actual reason for that?

fvogel added on 2021-04-16 17:34:17:
> the manual states in section BINDINGS

Good point, the manual should be corrected.

anonymous added on 2021-04-16 15:35:35:
Also, the manual states in section BINDINGS:

1. Clicking mouse button 1 positions the insertion cursor just before the 
character underneath the mouse cursor, sets the input focus to this widget, and 
clears any selection in the widget.

dzach

fvogel added on 2021-04-16 15:24:43:

Thank you for your efforts in explaining how you see things. However I have to say I don't see an inconsistency.

You have properly described the logic I think, and with consistency with the manual. What is happening when clicking on a character is that the insert mark moves to a new position located at the left or right of the clicked character, depending on the side this character was clicked on.

> It seems to me that the second interpretation, which decides on the
> placement of the insert mark based on the position of the click
> relative to the centerline of the character, though more sound
> from a geometrical point of view, is in contrast with the definition
> for a mark index, which states that the mark index indicates the character
> just after the mark, i.e. the mark precedes the character.
> Contrary to this definition, the insert mark, instead, follows the
> character, if the click occurred in the right half of the character.

I don't see a contrast here. You click, which has the effect that the insert mark moves to the closest position between two characters. This closest position is either at the left or at the right of the clicked character. At any time, index insert really returns the index of the character just after the mark named "insert". It is the case before the click (before the mark move) and also after the click (after the move). Also at any time index @x,y really returns the index of the character that covers this pixel at (x,y). I would say the observed behaviour and the manual do agree.


anonymous added on 2021-04-16 13:44:41:

A few clarifications:
I chose the ticket type 'bug' in absence of a better choice. The problem,
as it is described above, is that the results of index @x,y and
index insert are unexpectedly different. What is expected and why?
According to the manual:

@x,y
    Indicates the character that covers the pixel whose x and y
    coordinates within the text's window are x and y.
mark
    Indicates the character just after the mark whose name is mark. 
So, there appears to be a different interpretation of the word 'covers'
of the definition by the internals of the commands index @x,y and
index insert.

index @x,y interpretation of the click:
    any click in the space occupied by character results to an index
    pointing before the character.
internal logic for placing the insert mark:
    depending on whether the click was to the right or to the left
    of the centerline of the character, the insert mark will be
    placed and pointing to the left or to the right of the character,
    i.e. before or after the character, respectively.
It seems to me that the second interpretation, which decides on the
placement of the insert mark based on the position of the click
relative to the centerline of the character, though more sound
from a geometrical point of view, is in contrast with the definition
for a mark index, which states that the mark index indicates the character
just after the mark, i.e. the mark precedes the character.
Contrary to this definition, the insert mark, instead, follows the
character, if the click occurred in the right half of the character.

This inconsistency becomes a problem when trying to anticipate the position
of the insert mark using a <ButtonPress> event, in order to decide for
some action before the insert mark is actually placed.

Hopefully the above explain the claim that the results are inconsistent from a
user's point of view.

dzach


fvogel added on 2021-04-16 11:48:33:
Also in revised_text.