[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: xterm-mouse-mode gives incorrect posn-object-x-y with display space

From: JD Smith
Subject: Re: xterm-mouse-mode gives incorrect posn-object-x-y with display space
Date: Fri, 25 Nov 2022 10:15:37 -0500

> On Nov 25, 2022, at 2:21 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>> From: JD Smith <jdtsmith@gmail.com>
>> Date: Thu, 24 Nov 2022 16:42:29 -0500
>> Cc: emacs-devel@gnu.org
>> Thanks.  The documentation on posn-object-* provides no guidance that a 
>> “string object” would not include a
>> stretched string with specified space.  So it was not at all surprising to 
>> me that it worked "as expected" in the
>> GUI.  In further support of this impression (leaving aside specified space), 
>> posn-object-x-y works perfectly
>> well on normal width characters in the buffer, providing pixel level 
>> information on where *within the
>> character* you clicked.  In fact I cannot think what "pixel-based x and y 
>> coordinates relative to the upper left
>> corner” would mean other than this for a "string object".  Surely that is 
>> not an accident of the
>> implementation!
> Yes, but on TTY frames the DX/DY _within_ the character glyph are always
> zero, because each character is considered to be exactly one "pixel".  And
> if I tell you that stretches of whitespace produced by 'space' display specs
> are implemented on TTY as sequences of SPC characters (of course, what
> else?), then I think you will understand why the DX/DY values, defined in
> the ELisp manual as "the coordinates relative to the top left corner of the
> character glyph clicked on", on a TTY are always zero: wherever the click
> is, it is always on a glyph of some SPC character from those that represent
> the stretch of whitespace.

Thanks for these details.  This I had indeed understood; with char units, you 
can’t and won't get any pixel offsets within a single char glyph.  Since for 
the TTY, Emacs implements a specified space under the hood as a “series of 
spaces”, the natural thing for consistency with the GUI would be for 
posn-object-x-y to report click position offsets (in integer character units, 
naturally) within that stretched space.  It sounds like this may be challenging 
to implement internally, but it would be the most consistent.  It must be 
possible, since Emacs 1) knows it drew a specified space as a series of space 
chars in the TTY, and 2) knows (or could know) where the click occurred within 
that group of space chars it drew.

To summarize, the fact that in the TTY a stretched space is implemented as a 
collection of space chars, and on GUI, some other type of pixel-precise 
graphical element is IMO just an implementation detail.  What if TTY’s of the 
future allow drawing small graphical elements at pixel precision? How is the 
user of posn-object-* to know which of the two different and incompatible 
result flavors they will get?

>> Is there a reliable way to determine where (in pixels [1]) the mouse was 
>> clicked relative to a string displayed
>> with specified space, which works equally in the GUI and TTYs?   Keep in 
>> mind that the string may not be at
>> a fixed column, but at an arbitrary pixel offset from the window (due to 
>> prior specified space, variable width
>> fonts, etc.).  
> Please tell more about your use case.  I don't think I understand what you
> mean by "string displayed with specified space”;

This is how I implement mlscroll, a mode line scroll bar we’ve discussed here 
before.  The basic design is 3 specified spaces in a row , usually 
right-aligned in the mode line. Together these 3 (varying width) spaces 
indicate the number of lines: i) above ii) showing, and iii) after the window.  
Just like a “real” scrollbar, the user can interact with it by 
clicking/dragging/etc.  When clicking on the bar, the precise relative click 
position determines what lines are scrolled into view (again, just like a real 
scrollbar).  Surprisingly it looks pretty good on TTY without any special 
casing, though obviously with char- instead of pixel-granularity.  But this 
happy consistency breaks down with xterm-mouse-mode, since clicks on the 
modeline scrollbar are not reportable as positions w.r.t. the clicked element, 
i.e. since posn-object-x-y always reports 0 on TTY.  

> If I have to guess what you want, then my suggestion would be to use
> something like this:
>  (let* ((event-posn (posn-point (event-start ev)))
>         (click-x-y (posn-x-y (event-start ev)))
>         (obj-x-y (posn-x-y (posn-at-point event-posn))))
>    (cons (- (car click-x-y) (car obj-x-y))
>          (- (cdr click-x-y) (cdr obj-x-y))))
> IOW, don't trust DX/DY, but calculate the offsets "by hand".

Thanks for your good suggestion; this would indeed work as desired in the 
buffer, since posn-at-point does seem to “know” it’s in a specified space in 
both GUI and TTY (which makes me think posn-object-x-y should also be able to 
know this).

Unfortunately posn-point returns nil for posn-area = mode-line, so this does 
not solve the problem.  Is there any other way you know to determine the 
starting char position of the _group of spaces_ that TTY Emacs translates a 
specified space into, in the mode line?  Calculating the char-start of the 
scrollbar myself will be challenging given dynamic modeline elements and the 
possibility for the user to place the scrollbar anywhere they want (i.e. not 
just right-aligned).

reply via email to

[Prev in Thread] Current Thread [Next in Thread]