bug#43405: Tool bar item doesn't align to the right edge

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Juri Linkov-2
This bug report is from emacs-devel thread:

>> Anyway, there is a bug in tool-bar code that doesn't allow to use
>> align-to, whereas align-to works perfectly when used on the tab-bar.
>>
>> Here is the test case to reproduce the bug on the tool-bar:
>>
>> emacs -Q and eval:
>>
>>   (define-key-after (default-value 'tool-bar-map) [global-menu-bar]
>>     `(menu-item (propertize " " 'display '(space :align-to (- right 5)))
>>                 (lambda ()
>>                   (interactive)
>>                   (popup-menu (mouse-menu-bar-map)))
>>                 :image ,(tool-bar--image-expression "newsticker/narrow")
>>                 :help "Pop up the global menu bar"))
>>   (force-mode-line-update)
>>
>> It doesn't align the icon to the right edge of the tool-bar
>> whereas the same code aligns it on the tab-bar.
>
> Here, the above displays nothing at all on the tool bar.

The icon is displayed only after more changes in window-configuration like
switching buffers, i.e. force-mode-line-update (copied from tool-bar-local-item)
has no effect.

Another bug?  Or should this code use both (redraw-display) and
(force-mode-line-update) like in bug#43397?



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Eli Zaretskii
> From: Juri Linkov <[hidden email]>
> Date: Mon, 14 Sep 2020 22:18:33 +0300
>
> >> emacs -Q and eval:
> >>
> >>   (define-key-after (default-value 'tool-bar-map) [global-menu-bar]
> >>     `(menu-item (propertize " " 'display '(space :align-to (- right 5)))
> >>                 (lambda ()
> >>                   (interactive)
> >>                   (popup-menu (mouse-menu-bar-map)))
> >>                 :image ,(tool-bar--image-expression "newsticker/narrow")
> >>                 :help "Pop up the global menu bar"))
> >>   (force-mode-line-update)
> >>
> >> It doesn't align the icon to the right edge of the tool-bar
> >> whereas the same code aligns it on the tab-bar.
> >
> > Here, the above displays nothing at all on the tool bar.
>
> The icon is displayed only after more changes in window-configuration like
> switching buffers, i.e. force-mode-line-update (copied from tool-bar-local-item)
> has no effect.
>
> Another bug?  Or should this code use both (redraw-display) and
> (force-mode-line-update) like in bug#43397?

I didn't yet look into that bug report, so I cannot say.

Btw, are you trying this in a GTK build or with some other toolkit?



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Caio Henrique
In reply to this post by Juri Linkov-2
Juri Linkov <[hidden email]> writes:

> The icon is displayed only after more changes in window-configuration like
> switching buffers, i.e. force-mode-line-update (copied from tool-bar-local-item)
> has no effect.
>
> Another bug?  Or should this code use both (redraw-display) and
> (force-mode-line-update) like in bug#43397?

I tried all related functions that I could think of
(force-mode-line-update, redraw-display, force-mode-line-update) just to
try to understand what is happening. I.e. I don't know what the code
should use and I don't know if this is a bug.



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Eli Zaretskii
In reply to this post by Eli Zaretskii
> From: Juri Linkov <[hidden email]>
> Cc: [hidden email]
> Date: Tue, 15 Sep 2020 21:14:45 +0300
>
> > Btw, are you trying this in a GTK build or with some other toolkit?
>
> I tried both GTK and no-toolkit, and it can't align the icon to the right
> on the tool-bar.
>
> Whereas the same code nicely alights the icon on the tab-bar:
>
> (progn
>   (tab-bar-mode)
>   (advice-add
>    'tab-bar-make-keymap-1 :around
>    (lambda (orig-fun)
>      (append (funcall orig-fun)
>     `((menu-bar
> menu-item
> ,(concat
>  (propertize " " 'display '(space :align-to (- right 5)))
>  (propertize " " 'display
>      '(image :type xpm
>      :file "newsticker/narrow.xpm")))
> (lambda ()
>  (interactive)
>  (popup-menu (mouse-menu-bar-map)))))))
>    '((name . tab-bar-menu-bar))))

I think you forget how the tool bar is displayed.  In the versions of
Emacs that produce our native tool bar, the tool bar is displayed by
displaying a Lisp string made of spaces, where each space has a
display property which specifies the icon to display.  Your code puts
the :align-to properties on menu item's name, but that name is not
used at all for the display of tool bar, so it has no effect.  What
you need is to put the :align-to property on the respective space of
the Lisp string used to display the tool bar.  I don't think this can
be done in Lisp, we need support on the C level.

In the versions of Emacs that use the so-called "external tool bar",
like the GTK build, I don't see how :align-to can have any effect at
all; we need instead to use GTK facilities to arrange the buttons
(assuming that such facilities exist and are available to Emacs).



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Eli Zaretskii
> From: Robert Pluim <[hidden email]>
> Cc: Juri Linkov <[hidden email]>,  [hidden email]
> Date: Thu, 17 Sep 2020 11:03:46 +0200
>
> >>>>> On Tue, 15 Sep 2020 21:39:22 +0300, Eli Zaretskii <[hidden email]> said:
>
>     Eli> In the versions of Emacs that use the so-called "external tool bar",
>     Eli> like the GTK build, I don't see how :align-to can have any effect at
>     Eli> all; we need instead to use GTK facilities to arrange the buttons
>     Eli> (assuming that such facilities exist and are available to Emacs).
>
> The GTK code just adds items to the toolbar in order. Itʼs possible in
> GTK to specify negative positions for toolbar items, but that just
> means 'append', not 'align to right border' as far as I can see.

Thanks.

If we cannot control the placement of icons on GTK, then I guess it
makes little sense to add features to do this in our native tool bar,
since most users will be unable to take advantage of it.



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Robert Pluim
>>>>> On Thu, 17 Sep 2020 16:45:16 +0300, Eli Zaretskii <[hidden email]> said:

    >> The GTK code just adds items to the toolbar in order. Itʼs possible in
    >> GTK to specify negative positions for toolbar items, but that just
    >> means 'append', not 'align to right border' as far as I can see.

    Eli> Thanks.

    Eli> If we cannot control the placement of icons on GTK, then I guess it
    Eli> makes little sense to add features to do this in our native tool bar,
    Eli> since most users will be unable to take advantage of it.

Actually we *can* control the placement of the icons on the GTK
toolbar, as it turns out. Buried in the fine print is this sentence:

    If the GtkToolbar child property "expand" is TRUE and the property
    "draw" is set to FALSE, the effect is to force all following items to
    the end of the toolbar.

So if you do the following, all toolbar items added after this
separator end up on the right:

      ti = gtk_separator_tool_item_new ();
      gtk_tool_item_set_expand (ti, true);
      gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (ti), true);
      gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j);

It does produce an ugly empty patch in the middle of the toolbar
thatʼs a different colour though.

The other way to do this would be to add toolbar items at specific
positions in the toolbar, but I couldn't find an api that answered the
question "how many items of size x can I add before I reach the right
border of the window" (and then weʼd have to recalculate the positions
if the frame changes size).

Robert



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Eli Zaretskii
> From: Robert Pluim <[hidden email]>
> Cc: [hidden email],  [hidden email]
> Date: Thu, 17 Sep 2020 16:43:37 +0200
>
>     If the GtkToolbar child property "expand" is TRUE and the property
>     "draw" is set to FALSE, the effect is to force all following items to
>     the end of the toolbar.
>
> So if you do the following, all toolbar items added after this
> separator end up on the right:
>
>       ti = gtk_separator_tool_item_new ();
>       gtk_tool_item_set_expand (ti, true);
>       gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (ti), true);
>       gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j);
>
> It does produce an ugly empty patch in the middle of the toolbar
> thatʼs a different colour though.

So you are saying that, while possible, doing this is not really
workable, since it produces ugly display?



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Robert Pluim
>>>>> On Thu, 17 Sep 2020 17:54:15 +0300, Eli Zaretskii <[hidden email]> said:

    >> From: Robert Pluim <[hidden email]>
    >> Cc: [hidden email],  [hidden email]
    >> Date: Thu, 17 Sep 2020 16:43:37 +0200
    >>
    >> If the GtkToolbar child property "expand" is TRUE and the property
    >> "draw" is set to FALSE, the effect is to force all following items to
    >> the end of the toolbar.
    >>
    >> So if you do the following, all toolbar items added after this
    >> separator end up on the right:
    >>
    >> ti = gtk_separator_tool_item_new ();
    >> gtk_tool_item_set_expand (ti, true);
    >> gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (ti), true);
    >> gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j);
    >>
    >> It does produce an ugly empty patch in the middle of the toolbar
    >> thatʼs a different colour though.

    Eli> So you are saying that, while possible, doing this is not really
    Eli> workable, since it produces ugly display?

You know this is 2020, so truth == lies, and lies == truth, right?
So, once I actually follow the documentation and pass 'false' in the right
place, the toolbar looks correct :-)

Now the question is: do we want to expose this to lisp, and if so,
how? I mean, I have no idea if the macOS or MS-Windows tool bar have
a similar feature.

Robert



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Robert Pluim
>>>>> On Thu, 17 Sep 2020 18:33:17 +0300, Eli Zaretskii <[hidden email]> said:
    >> Now the question is: do we want to expose this to lisp

    Eli> I think so, yes.

    >> and if so, how?

    Eli> Some attribute of the binding, similar to :image and :vert-only, I
    Eli> guess?

    >> I mean, I have no idea if the macOS or MS-Windows tool bar have a
    >> similar feature.

    Eli> I don't know about macOS, but MS-Windows uses the native tool bar
    Eli> produced by our own code, i.e. it displays a Lisp string in a special
    Eli> window.

OK, so I took a look, and Iʼm not sure itʼs possible with the native
tool bar. We have '(space :align-to right)', but that just inserts
space up to a specified location, everything subsequent is
appended. In order to calculate the correct location, Iʼd need to know
the width of everything that came after the space, which only
redisplay can tell us, unless thereʼs a function Iʼve missed?
'string-width' doesnʼt take 'display properties into account.

macOS has something called a flexibleSpace toolbar item that might
serve, but Iʼm utterly ignorant of how the macOS code works.

Robert



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Eli Zaretskii
> From: Robert Pluim <[hidden email]>
> Cc: [hidden email],  [hidden email]
> Date: Fri, 18 Sep 2020 10:38:18 +0200
>
>     Eli> Some attribute of the binding, similar to :image and :vert-only, I
>     Eli> guess?
>
>     >> I mean, I have no idea if the macOS or MS-Windows tool bar have a
>     >> similar feature.
>
>     Eli> I don't know about macOS, but MS-Windows uses the native tool bar
>     Eli> produced by our own code, i.e. it displays a Lisp string in a special
>     Eli> window.
>
> OK, so I took a look, and Iʼm not sure itʼs possible with the native
> tool bar. We have '(space :align-to right)', but that just inserts
> space up to a specified location, everything subsequent is
> appended. In order to calculate the correct location, Iʼd need to know
> the width of everything that came after the space, which only
> redisplay can tell us, unless thereʼs a function Iʼve missed?

The support for doing this with the native tool bar must be in C, and
should indeed be part of the display engine.  So everything redisplay
knows should be at your fingertips.



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Robert Pluim
In reply to this post by Juri Linkov-2
>>>>> On Fri, 18 Sep 2020 11:58:21 +0300, Eli Zaretskii <[hidden email]> said:

    >> OK, so I took a look, and Iʼm not sure itʼs possible with the native
    >> tool bar. We have '(space :align-to right)', but that just inserts
    >> space up to a specified location, everything subsequent is
    >> appended. In order to calculate the correct location, Iʼd need to know
    >> the width of everything that came after the space, which only
    >> redisplay can tell us, unless thereʼs a function Iʼve missed?

    Eli> The support for doing this with the native tool bar must be in C, and
    Eli> should indeed be part of the display engine.  So everything redisplay
    Eli> knows should be at your fingertips.

Your fingertips maybe, not mine :-)

So let's assume we do this by exending the display spec to allow

'(:right-justify t)

which would mean to move everything on this line as far to the right
in the window as possible.

At some point weʼd end up in 'gui_produce_glyphs' with a 'struct
iter' pointing at the char with that property set. Then:

remember it->current_x
loop over the iters until we hit eol or max_x, calling PRODUCE_GLPYHS
The final it->current_x minus the remembered one is the width of the remaining
glyphs on the line.
Now set it->current_x to the window right edge minus the width.

Does that sound like it would work? Is there a more direct way of
calculating that width? (I got lost in all the various move_to
functions).

Robert



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Eli Zaretskii
> From: Robert Pluim <[hidden email]>
> Cc: [hidden email],  [hidden email]
> Date: Mon, 21 Sep 2020 20:30:53 +0200
>
> So let's assume we do this by exending the display spec to allow
>
> '(:right-justify t)
>
> which would mean to move everything on this line as far to the right
> in the window as possible.
>
> At some point weʼd end up in 'gui_produce_glyphs' with a 'struct
> iter' pointing at the char with that property set. Then:
>
> remember it->current_x
> loop over the iters until we hit eol or max_x, calling PRODUCE_GLPYHS
> The final it->current_x minus the remembered one is the width of the remaining
> glyphs on the line.
> Now set it->current_x to the window right edge minus the width.
>
> Does that sound like it would work? Is there a more direct way of
> calculating that width? (I got lost in all the various move_to
> functions).

I'd first try to repeat what we do for :align-to support: insert a
stretch glyph of a suitable width, computed using it->last_visible_x
and the width of the image for the button that has to be
right-justified.  See produce_stretch_glyph (except that most of it is
not relevant, since :align-to supports a lot of functionalities).



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Robert Pluim
>>>>> On Mon, 21 Sep 2020 22:04:36 +0300, Eli Zaretskii <[hidden email]> said:
    >> Does that sound like it would work? Is there a more direct way of
    >> calculating that width? (I got lost in all the various move_to
    >> functions).

    Eli> I'd first try to repeat what we do for :align-to support: insert a
    Eli> stretch glyph of a suitable width, computed using it->last_visible_x
    Eli> and the width of the image for the button that has to be
    Eli> right-justified.  See produce_stretch_glyph (except that most of it is
    Eli> not relevant, since :align-to supports a lot of functionalities).

OK, that would work, but then you could only right justify a single
item, which would be different from what you can do with the GTK tool
bar (and I see no reason to restrict this to tool bar buttons, I see
at least org-mode wants to right-justify headline tags)

Robert



Reply | Threaded
Open this post in threaded view
|

bug#43405: Tool bar item doesn't align to the right edge

Robert Pluim
>>>>> On Tue, 22 Sep 2020 17:39:23 +0300, Eli Zaretskii <[hidden email]> said:

    >> From: Robert Pluim <[hidden email]>
    >> Cc: [hidden email],  [hidden email]
    >> Date: Mon, 21 Sep 2020 22:07:51 +0200
    >>
    Eli> I'd first try to repeat what we do for :align-to support: insert a
    Eli> stretch glyph of a suitable width, computed using it->last_visible_x
    Eli> and the width of the image for the button that has to be
    Eli> right-justified.  See produce_stretch_glyph (except that most of it is
    Eli> not relevant, since :align-to supports a lot of functionalities).
    >>
    >> OK, that would work, but then you could only right justify a single
    >> item, which would be different from what you can do with the GTK tool
    >> bar

    Eli> No, it will work with more than one as well, you just need to loop
    Eli> twice over all the buttons and keep track of all those which should be
    Eli> right-justified.

OK, weʼre saying the same thing with different words: everything to
the right of this stretch glyph needs its width calculated (and its
x-coordinate adjusted)

    >> (and I see no reason to restrict this to tool bar buttons, I see
    >> at least org-mode wants to right-justify headline tags)

    Eli> What are "headline tags" in Org, and how are they related?

Org headlines look like this:

* This is a headline                       :tag1:tag2:tag3

The tags are right justified by default, but this is done by inserting
spaces, which fails with non-monospace fonts. Thereʼs a patch to
org-mode to do this by instead inserting a space with an :align-to
property, but that code has to calculate the value to specify in lisp,
which I strongly suspect will turn out to be slow, hence doing it in
redisplay would be better (and perhaps more likely to be accurate).

    Eli> Your original description said:

    >> So let's assume we do this by exending the display spec to allow
    >>
    >> '(:right-justify t)
    >>
    >> which would mean to move everything on this line as far to the right
    >> in the window as possible.

    Eli> "Everything on this line" on which line?

Sorry, everything on this line after whatever element has that display
spec. Everything before stays where it is (and only the first
:right-justify property found in the line is acted upon).

    Eli> Do you mean you want to display an entire screen line justified to the
    Eli> right?  Then we already do something like that with R2L lines
    Eli> (although there we also reorder display elements, something you don't
    Eli> need here).

No, I just want to be able to produce:

This is text                          This is right justified

And have the "This is right justified" stay right justified as the
window size and line content changes (unless the user deletes that
stretch glyph in the middle).

If the line became longer than could be displayed in the available
window width, then I think the stretch glyph in the middle would just
be treated as a single space (and hence line continuation/truncation
would work as normal).

Robert