After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 408327 - Improving tooltip positioning
Improving tooltip positioning
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
: 449083 453172 (view as bug list)
Depends on:
Blocks: 65490
 
 
Reported: 2007-02-15 18:20 UTC by Matthias Clasen
Modified: 2007-07-22 22:32 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
quick implementation of gtk_tooltip_set_position_hint() approach (7.40 KB, patch)
2007-07-09 14:47 UTC, Kristian Rietveld
none Details | Review
patch as committed (13.10 KB, patch)
2007-07-13 14:26 UTC, Kristian Rietveld
committed Details | Review

Description Matthias Clasen 2007-02-15 18:20:03 UTC
when moving the mouse fast from the labels to the treeview, one can end up
with the tooltip for the tree rows being displayed over the labels. That looks
odd. And it is aggravated by the tooltip position not updating when moving from row to row.
Comment 1 Kristian Rietveld 2007-02-16 19:23:01 UTC
This basically boils down to a single question: when should we update the position of a tooltip?  We can always update the tooltip position, which means that the tooltip will follow the mouse.  Nicer might be to only update the position of the tooltip when its contents change -- and for this case we would need a good way to determine when exactly those contents change.

I have been thinking about this issue during the implementation process, but didn't manage to come up with a nice answer back then.
Comment 2 Kristian Rietveld 2007-06-24 12:06:53 UTC
*** Bug 449083 has been marked as a duplicate of this bug. ***
Comment 3 Kristian Rietveld 2007-06-24 12:20:08 UTC
Adding a related bug as duplicate of this bug.

I've been aware that the tooltip positioning on tree views, etc is sub par since before I committed the stuff to trunk.  Fixing this is by no means an easy problem.

One way to get rid of all issues is to let the tooltip follow the mouse pointer.  IMHO this would be very ugly/evil/etc.

I've been quickly looking at how other toolkits solve this problem.  For example in mozilla list views, the tooltip for a row is hidden as soon as the pointer leaves the row.  When the pointer comes to rest at a new row, the tooltip delay timeout seems to be restarted.  It feels like mozilla treats rows as "separate widgets" all having their own tooltip.

Cocoa has specialized methods for handling tooltips on cells, etc.  For their TableView this method has been added to just the table view (basically it is a kind of signal which asks you to provide a string to display as tooltip for a given cell/column/row).


For GTK+, I think having the code reposition the tooltip when the tooltip's contents change is close to impossible, since it is very hard to catch all possible changes to a tooltip.

I think we need a way for widgets like GtkTreeViews, canvases, etc to be able to provide some kind of hint about when to reposition the tooltip.  For a GtkTreeView this hint would, for example, provide where the different rows/cells are, so the tooltip code will be able to figure out when the pointer moves to a different "item" so the tooltip can be updated and repositioned accordingly.
Comment 4 Kristian Rietveld 2007-06-25 18:51:03 UTC
Tim asked me to outline the problems I see with detecting tooltip changes, so here I go.

AFAICS basically you want to know if a visible tooltip changes between subsequent calls to query-tooltip.  If a tooltip goes from hidden to visible, you always want to reposition it.  When the contents of a tooltip change, there is a good change that the "context of the tooltip" changed (ie. it is pointing at another "distinguishable item" in the same widget) so you want to place the tooltip at another position.  (In tree and icon views this can be seen as moving the mouse pointer to another row/cell or icon/item).

Detecting changes in tooltip contents is hard:
  - For custom windows it is impossible to do for GTK+ at all.
  - Detecting changes in content of the custom widget embedded in a GtkTooltip is hard/impossible.
  - The GtkTooltip is reset at every requery.  If we want to detect whether the same string, pixbuf, etc is set between subsequent calls to query-tooltip, we will have to cache those values and compare.

Even then this wouldn't be fully fool-proof, if you have two different items in the same widget with the same tooltip contents (for both of which you want to reposition the tooltip: think two cells with the same tooltip, or two windows of the same problem with the same window title in the window list) you are still busted.
Comment 5 Kristian Rietveld 2007-06-26 08:29:15 UTC
This idea just came to mind, so I just had to write it down somewhere.  It occurred to me that it would be well possible to have the user set this "positioning hint" in the query-tooltip callback.  It could either be something like:

  gtk_tooltip_set_position_preference (tooltip, x, y)
  [this would specify an (x, y) where the tooltip could be positioned]

or

  gtk_tooltip_set_position_hint (tooltip, rect)
  [this would specify a rectangle around the item for which these tooltips
   contents are meant.  This could be a tree view row/cell, icon view item,
   window list item, etc, etc.]


Not sure if this is a good idea at all.  Right now I would say I prefer the second option and think it would actually work.
Comment 6 Kristian Rietveld 2007-07-02 18:26:21 UTC
*** Bug 453172 has been marked as a duplicate of this bug. ***
Comment 7 Kristian Rietveld 2007-07-09 14:47:04 UTC
Created attachment 91497 [details] [review]
quick implementation of gtk_tooltip_set_position_hint() approach

I played around with the gtk_tooltip_set_position_hint() approach today, resulting in this patch.  It works by hiding the tooltip once the pointer leaves the area of interest (the widget itself, or a user-supplied "context area"/position hint).  The behavior of the tooltips on GtkToolbars (try the "Application main window" demo in gtk-demo) is much better.  If you add the following lines to the query_tooltip_tree_view_cb() in testtooltips, you get nicely behaving tooltips on tree views:

  gtk_tree_view_get_background_area (tree_view, path, NULL, &rect);
  gtk_tree_view_convert_tree_to_widget_coords (tree_view,
                                               NULL, rect.y,
                                               NULL, &rect.y);
  rect.x = GTK_WIDGET (tree_view)->allocation.x;
  rect.width = GTK_WIDGET (tree_view)->allocation.width;
  gtk_tooltip_set_position_hint (tooltip, &rect);


This approach is very flexible, though it feels like it will result in a good amount of code duplication...  For per-row tooltips, each tree view needs those 7 lines of code above in the query-tooltip callback.
Comment 8 Matthias Clasen 2007-07-09 15:11:17 UTC
Playing the gtk-demo a bit, I have to say that I find it a little bit 
irritating that the horizontal positioning of the tooltip depends on where
I enter the toolitem from and how fast I move.

The treeview positioning in testtooltips is in fact nice. I guess we can
always add a convenience function like

gtk_tooltip_set_treeview_position_hint (GtkTooltip  *tip,
                                        GtkTreeView *treeview,
                                        GtkTreePath *path)

later
Comment 9 Kristian Rietveld 2007-07-09 15:34:44 UTC
(In reply to comment #8)
> Playing the gtk-demo a bit, I have to say that I find it a little bit 
> irritating that the horizontal positioning of the tooltip depends on where
> I enter the toolitem from and how fast I move.

The position function which is used right now, places the tooltip below the mouse pointer at the right (I think this is what Soeren suggested in one of his mails).  This position is calculated as soon as the "delay timeout" expires.  When moving from button to button in the toolbar, this timeout can be very short because of the browse timeout (which is probably exactly what you want on a toolbar and other "grouped" widgets).

> The treeview positioning in testtooltips is in fact nice. I guess we can
> always add a convenience function like
> 
> gtk_tooltip_set_treeview_position_hint (GtkTooltip  *tip,
>                                         GtkTreeView *treeview,
>                                         GtkTreePath *path)
> 
> later

Yeah, was thinking of convenience functions too.  Does need some more thought, because some people will want to have per-cell tooltips, or group cells, etc.  But having one basic one which can cover the basic needs would be good.
Comment 10 Tim Janik 2007-07-13 12:31:58 UTC
(In reply to comment #5)
> This idea just came to mind, so I just had to write it down somewhere.

>   gtk_tooltip_set_position_hint (tooltip, rect)
>   [this would specify a rectangle around the item for which these tooltips
>    contents are meant.  This could be a tree view row/cell, icon view item,
>    window list item, etc, etc.]

i agree that we need tooltip API to specify sub-widget tip areas. i'd like to suggest to change the name accordingly though ("hint" is much too vague i think):

    void gtk_tooltip_set_tip_area (GtkTooltip*, GdkRectangle*);

(In reply to comment #8)
> The treeview positioning in testtooltips is in fact nice. I guess we can
> always add a convenience function like
> 
> gtk_tooltip_set_treeview_position_hint (GtkTooltip  *tip,
>                                         GtkTreeView *treeview,
>                                         GtkTreePath *path)

hum, i think that is badly misnamed. every big widget that has areas of interest smaller than the actual widget size will need such functionality, so this clearly doesn't belong into the gtk_tooltip namespace. given the above tip_area function and Kris' comments about cells, it makes sense to also add:

  void gtk_treeview_set_tooltip_row  (GtkTreeview*,GtkToolip*,GtkTreePath*);
  void gtk_treeview_set_tooltip_cell (GtkTreeview*,GtkToolip*,GtkTreePath*,int);
etc.
particularly for rows, i think we should have this API right away, it's clear that people will want to set tooltips on rows already.
Comment 11 Kristian Rietveld 2007-07-13 14:26:53 UTC
Created attachment 91736 [details] [review]
patch as committed

Patch as committed.  Leaving the bug open for review.
Comment 12 Matthias Clasen 2007-07-14 15:47:04 UTC
hmm, it is actually less convenient than one might expect, looking at the
callback in testtooltips.c:

  if (keyboard_tip)
    {
      /* Keyboard mode */
      gtk_tree_view_get_cursor (tree_view, &path, NULL);

      if (!path)
        return FALSE;
    }
  else
    {
      gint bin_x, bin_y;

      gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y,
                                                         &bin_x, &bin_y);

      /* Mouse mode */
      if (!gtk_tree_view_get_path_at_pos (tree_view, bin_x, bin_y,
                                          &path, NULL, NULL, NULL))
        return FALSE;
    }


will pretty much have to be repeated in every implementation.
Maybe a 

gboolean (* query_treeview_tooltip) (GtkTreeView       *treeview,
                                     GtkTreePath       *path,
                                     GtkTreeViewColumn *column,
                                     GtkCellRenderer   *renderer);

would allow to avoid that code repetition, but a "convenience signal"
is a bit harder to do.
Comment 13 Tim Janik 2007-07-14 16:52:04 UTC
(In reply to comment #12)
> hmm, it is actually less convenient than one might expect, looking at the
> callback in testtooltips.c:
> 
>   if (keyboard_tip)
>     {
>       /* Keyboard mode */
>       gtk_tree_view_get_cursor (tree_view, &path, NULL);
> 
>       if (!path)
>         return FALSE;
>     }
>   else
>     {
>       gint bin_x, bin_y;
> 
>       gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y,
>                                                          &bin_x, &bin_y);
> 
>       /* Mouse mode */
>       if (!gtk_tree_view_get_path_at_pos (tree_view, bin_x, bin_y,
>                                           &path, NULL, NULL, NULL))
>         return FALSE;
>     }
> 
> 
> will pretty much have to be repeated in every implementation.

nah, it looks more like there's a bit more API needed to make treeviews really convenient. the query_tooltip_text_view_cb() seems to suggest the same for GtkTextView btw. e.g. for tree view, the callback could read:

  if (!gtk_tree_view_get_tooltip_args (tree_view, x, y, keyboard_tip,
                                       &model, &path, &iter))
    return FALSE;
  tip_string = g_strdup_printf (...);
  gtk_tooltip_set_markup (tooltip, tip_string);
  gtk_tree_view_set_tooltip_row (tree_view, tooltip, path);
  gtk_tree_path_free (path);
  g_free (tip_string);
  return TRUE;

or maybe s/get_tooltip_args/get_tooltip_context/...

> Maybe a 
> gboolean (* query_treeview_tooltip) (GtkTreeView       *treeview,
>                                      GtkTreePath       *path,
>                                      GtkTreeViewColumn *column,
>                                      GtkCellRenderer   *renderer);
> would allow to avoid that code repetition, but a "convenience signal"
> is a bit harder to do.

i think this would be the entirely wrong approach, when you could simply have 1 or 2 treeview convenience functions instead that implement the tooltip logic handling for you.
Comment 14 Kristian Rietveld 2007-07-19 15:57:01 UTC
We also have gtk_tree_view_get_tooltip_context() now and the uber-cool gtk_tree_view_set_tooltip_column().

Resolving as FIXED.

Comment 15 Vincent Untz 2007-07-22 22:32:32 UTC
*** Bug 457984 has been marked as a duplicate of this bug. ***