On Fri, 2004-11-05 at 19:39 +0100, Christof Petig wrote: > Owenn Taylor schrieb: > > Here's an alternate approach I came up with talking to Jonathan (he's > > promised a more detailed writeup of GtkTreeView requirements) is a > > little more of a radical change. > > > > * We ditch (deprecate) GtkTooltips; GtkTooltips objects are 90% just > > annoying to create and memory manage. > > I'm 100% in favor of ditching GtkTooltips in favor of a widget property. > What about tip_private? It does not show up in your proposal at all. I don't see any reason to carry tip_private forward, there's a vague idea that it has something to do with what-is-this help, but it was never really anything useful. If someone passes in a non-NULL tip_private we can store it in object data for backwards-compat, but it should have no presence in the non-deprecated API. If we want to actually support what-is-this help, that needs to be thought out from scratch. I'm not sure if it belongs in the tooltips API ... looking at the API for Windows, etc, might be useful. (Note that there is another vestigal appearance of what-is-this help in the GtkWidgetHelpType parameter to the ::show-help action signal.) > > * We can reimplement GtkTooltips using GtkTooltipsGroup and > > gtk_widget_set_tooltip(). > > Agreed. (You are talking about backwards compatibility here, right?) Right. > > * For custom tooltips, we introduce the GtkTooltipsWindow widget, > > There is a singleton GtkTooltipsWindow object per toplevel, > > which can be retrieved with: > > > > gtk_widget_get_tooltips_window() > > > > This both handles the display of the yellow rectangle, and the > > logic for showing/hiding the tooltip based on keyboard and > > mouse actions. > > So, TooltipsWindow is manageing querying the widgets for the text and > the display of the tooltip? I don't know what you mean by that. GtkTooltipsWindow *is* the window that pops up if a tooltip is displayed. (I think, perhaps it would be better to generate that window on the fly.) But it also is the object that tracks the current state of the tooltips and decides when and where to pop up the tooltips widget. > > void gtk_tooltips_window_begin (GtkTooltipsWindow *window, > > GtkTooltipsContext context, > > GObject *owner); > > void gtk_tooltips_window_end (GtkTooltipsWindow *window, > > GtkTooltipsContext context, > > GObject *owner); > > Who calls these? And what would be done inside these calls? [Emitting a > signal?] For widget global tooltips, it's called by gtkwidget.c. But for widgets with multiple tooltips within them, it would be called by the widget implementation as it gives enter/leave focus-in/focus-out events. What is done inside these calls is updating internal state variables, setting up timeouts, etc. > > void gtk_tooltips_window_set_text (GtkTooltipsWindow *window, > > GtkTooltipsContext context, > > GObject *owner, > > const char *text); > > void gtk_tooltips_window_set_markup (GtkTooltipsWindow *window, > > GtkTooltipsContext context, > > GObject *owner, > > const char *markup); > > This looks like you still manage the tip storage outside of widgets. (In > Tooltips Window). The information is only stored for the duration that this "tooltipable object" is an area of interest for mouse or keyboard tooltips. > owner would always be a GtkWidget, wouldn't it?\ No. 'owner' is just an arbitrary GObject that is used to distinguish this "tooltipable object" from any other tooltip-able widget that might be active at the same time. If I was doing row tooltips on GtkTreeView, the object I'd probably use is the treeview's "bin window" (the GdkWindow that the rows are drawn in.). Since GdkWindow is also a GObject. It can't be the treeview itself, since that would cause confusion with tooltips on the treeview. > > void gtk_tooltips_window_set_area (GtkTooltipsWindow *window, > > GtkTooltipsContext context, > > GdkWindow *relative_to, > > int x, int y, int width, int height); > > So here you mark the active area. Managing different areas inside one > widget is missing? This is just saying "if you pop up the tooltip right now use the specified area to position the tooltip) > > void gtk_tooltips_window_set_group (GtkTooltipsWindow *window, > > GtkTooltipsContext context, > > GObject *owner, > > GtkTooltipsGroup group); > > I would code it as > void gtk_tooltips_group_add(GtkTooltipsGroup *group, GtkWidget *widget) That would be there for whole-widget tooltips, but the above is allow grouping of fly-weight sub-widget areas. They have no persistent existence, so we can't permanently add them to a group. > > - The GtkTooltipsWindow keeps two stacks of "active objects" for > > keyboard and mouse focus. With each object in the stack, we > > store text/markup rectangle, and possible GtkTooltipsGroup. > > Sounds like a heavyweight object. I'd like to store the information > inside the widgets. Not at all heavyweight - the information is only stored for widgets, or flyweight areas within widgets, that currently either: - Contain the pointer - Have keyboard focus > > - You call tw.begin (MOUSE) on when the mouse enters a tooltips > > area, tw.begin (KEYBOARD) on a tooltips object getting > > keyboard focus and tw.end (MOUSE/KEYBOARD) on > > mouse leave / focus out. > > > > - The 'GObject *owner*' arguments allow proper handling of nested > > tooltips areas. (think a treeview with tooltips with tooltips > > on individual rows.) It can be any GObject - the widget itself, > > a GdkWindow, whatever. > > > > A lot of the details of the above maybe should be a little different > > than I've sketched out, but I think it is a whole lot simpler than > > any callback-based mechanism with the same set of functionality. > > I originally envisioned asking the toplevel widget for the > text/markup/widget to display when the mouse _rests_ at a certain spot > of the window. Containers would query their children in turn. Possibly a > container can return it's own tip when its child does not provide a tip. > > So the tooltip text query signal/vfunc (I tend to use a vfunc) would > only get called when a tip is about to be displayed. Hopefully the above will help explain what I was thinking about. But Perhaps you do have a point that a pick interface might work better (I'd tend to use a signal) - My interface clearly wasn't very easy to understand :-) - There are a lot of problems with enter/leave events not being received on widgets where people want to put tooltips. These can be *hard* to fix. But there are also some issues with such an interface: - Currently we pop up tooltips based on enter/leave not on lack-of-motion-events. To duplicate this, you'd have to query the tooltip area for *every* enter/leave/motion event. - The toplevel doesn't get access to enter/leave/motion events on subwindows currently, so we'd have to hack this into the GTK+ event propagation system as a special case. (Which is possible.) - X doesn't *send* enter/leave/motion events for areas of the window where these events haven't been selected for. To make query-for-tooltips work reliably, we'd probably have to make gtk_widget_get_events() always include these events. That shouldn't cause compat problems (unless people have assertions in their code that they won't get events they haven't selected for.) Or even major performance problems. But it would be ironic considering that not sending unnecessary motion events is the reason that X and thus GTK+ has event masks at all. Hard problem ... I don't have a good definitive answer at the moment, but perhaps that will give you something to think about. > Displaying the tooltip for the cursor focus is a different issue (mouse > movement does not affect the display but focus changes do) because the > actual on screen position is meaningless (that means we do not need to > hierarchically query the widget tree for the tip to display). Issue that came up a few minutes ago talking to Matthias: GtkComboBox has a button in it that has the keyboard focus You set a tooltip on the GtkComboBox You hit Control-F1 The tooltip doesn't display So, there is hierarchy there, though it isn't a hierarchical pick. Regards, Owen
Attachment:
signature.asc
Description: This is a digitally signed message part