GNOME Bugzilla – Bug 111031
Unable to determine what character is at a point
Last modified: 2011-02-04 16:17:18 UTC
The attached test program shows problem determin ing what character is at a point. For example, I get the rectangle for the character at offset 1 and check what character is at each point. As can be seen from attached output the last few points which should be in the character at offset 1 are reported as being at offset 2.
Created attachment 15810 [details] Test program
Created attachment 15811 [details] Test output
See extensive discussion in bug 102592. What needs to be understand here is that gtk_text_view_get_iter_at_location() is working 100% correctly (finding the cursor position nearest to the location), it just isn't doing what is desired (find the character at the location). Note that the corresponding Pango API, by returning the character, along with the "trailing" flag allows for both. And also note the connection to the problem of needing to keep track of "trailing for the previous character" vs. "leading for the next character" for the cursor mark.
[Could be moved back to 2.4 API freeze if a proposal/patch appeared]
The reference to bug 102592 should be 102952.
I have looked at this to try and figure out what is going on and it seems that pango_layout_xy_to_index returns a trailing value of 1 for the second half of a character extents. Should gtk_text_layout_get_iter_at_pixel() ignore the trailing value?
If you want to determine what *character* was clicked on, you ignore the trailing value. On the other hand, gtk_text_layout_get_iter_at_pixel() is about finding the space between characters (an iter is conceptually between characters) - like for positioning the insertion cursor. So it *does* pay attention to trailing.
Thanks. I think I understand what is happening now. Proposal: gint gtk_text_view_get_offset_at_location (GtkTextView *view, gint x, gint y); Also gint gtk_text_layout_get_offset_at_pixel (GtkTextLayout *layout, gint x, gint y); If these functions are acceptable I can put together a patch.
It seems totally confusing to me that if you get an iter it's an intercharacter position and if you get an offset it's the character itself. gtk_text_iter_get_offset() does exist after all. If you have get_iter_at and get_offset_at people will think the difference is just how the position is represented. Maybe have a function with the "trailing" arg or have get_character_at_location() or something like that.
Note that we're going to need a variant with the trailing argument to fix bug 81412.
How about void gtk_text_view_get_offset_at_location (GtkTextView *view, gint x, gint y, gint *offset, gint *trailing);
I prefer if it returns an iterator, since the rest of the API uses iterators. As a name, how about gtk_text_view_get_iter_at_pixel() or get_iter_at_position() and then deprecate the get_iter_at_location() we have currently. is "trailing" supposed to be a boolean or can it have a value other than 0/1?
trailing is an integer judging by the comment in pango_layout_line_x_to_index.
Apologies for spam... marking as GNOMEVER2.3 so it appears on the official GNOME bug list :)
based on Owen's comments on 06/05, I am provisionally marking this 2.4 API Freeze. Unfortunately this bug seems to have gotten lost for awhile, but we (ATK team) need the functionality in order to reliably satisfy our own atk_text_get_offset_at_point API, if I understand Padraig correctly.
Apologies for spam-- ensuring Sun a11y team are cc'ed on all current a11y bugs. Filter on "SUN A11Y SPAM" to ignore.
So it seems what is needed here is a patch which adds void gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout, GtkTextIter *iter, gint *trailing, gint x, gint y); void gtk_text_view_get_iter_at_pixel (GtkTextView *view, GtkTextIter *iter, gint *trailing, gint x, gint y); and deprecates gtk_text_layout_get_iter_at_location(), gtk_text_view_get_iter_at_location()
Created attachment 34478 [details] [review] a patch Does this patch work for you ? Note that I named the functions at_position(), since gtk_text_layout_get_iter_at_pixel() was already taken
Hmm, I thought I had grokked the theory behind trailing, but what I get when I replace the call to get_iter_at_location() by my get_iter_at_position() leaves me confused.
Created attachment 34532 [details] test output with the patch
I get output very similar to yours. Results seem to be correct until we come to the Hebrew characters at the end of the 6th line. There the offset seems to be different for the last pixel of the character. Things seem to go seriously wrong with the Hebrew punctuation on the next line.
Here is your example extended to track the character under the pointer (click and drag). It seems to show that we're generally doing ok, but as you point out, the hebrew punctuation seems problematic.
Created attachment 34594 [details] updated test program
Created attachment 34619 [details] another update This version prints out trailing as well. Using that, you can find trailing values of up to 5 in the Hebrew punctuation, and values of up to 7 in the "Thai wrong spelling".
It looks to me that if the iter is on a right-to-left character the x value returned by gtk_text_view_get_iter_location() 1 one larger than it ought to be.
Created attachment 34626 [details] my test program
Created attachment 34627 [details] my test output Note that the four Hebrew characters bertween 430 and 462. I think they should be between 429 and 461, judging by the position of the left-to-rgight characters on either side of them.
2004-12-08 Matthias Clasen <mclasen@redhat.com> Fix #111031, reported by Padraig O'Briain: * gtk/gtktextlayout.h: * gtk/gtktextlayout.c (gtk_text_layout_get_iter_at_position): Add a variant of gtk_text_layout_get_iter_at_pixel() which returns the character at the position, not the closest cursor position. * gtk/gtktextview.h: * gtk/gtktextview.c (gtk_text_view_get_iter_at_position): Add a variant of gtk_text_view_get_iter_at_location() which returns the character at the position, not the closest cursor position.