GNOME Bugzilla – Bug 313273
Implement gtk_notebook_get_page_at_pos()
Last modified: 2018-02-10 03:37:18 UTC
When a custom popup menu for the tabs is needed, the first that comes to mind would be to put an eventbox above the label widget of every tab, and check for the "button-press-event" event. But that method doesn't catch clicks that are at the tab, but outside the label widget (the "tab-border" property of GtkNotebook). And also, it would be a waste to add a lot of event windows, when GtkNotebook already has one. So if there was a function like: gint page_num gtk_notebook_get_page_at_pos(GtkNotebook *notebook, gint x, gint y); - it would be possible to know what tab is clicked on, providing the event->x and event->y. It should return some negative value if the click is not at a tab.
To clarify a few things: Instead of connecting the event box above the label to "button-press-event", you would connect the GtkNotebook instead. And if there is a negative return value from gtk_notebook_get_page_at_pos(), it might be considered not to show the popup menu.
Should that not be gtk_notebook_get_tab_at_pos() then ?
Carlos, doesn't one of your outstanding patches add a (private) gtk_notebook_get_tab_at_pos() function ? Might be worth to export it.
Yeah, it's implemented in patch from bug #332991, once we figure out what to do with it, I'll make a patch to export it
Hmm, while implementing this I've found a small dilemma, using widget coordinates seem to be the most obvious (other *_at_pos() functions already do that), but if you connect to say ::button-press-event and use this function, the event coordinates will be relative to notebook->event_window, used for catching tabs events. One solution would be adding gtk_notebook_window_to_tabs_coords() and gtk_notebook_tabs_to_window_coords(), but exposing this implementation detail sucks completely. Another solution would be assuming that the coords will be related to notebook->event_window, given that this function would be mostly used in event handlers, but it would fail "misteriously" if it's used outside one of these with known coordinates.
I think documenting that the coordinates are relative to event_window, together with a small example showing how to use it in an event handler would be acceptable
If you take that approach, don't you need to provide a getter for event_window a) for language bindability b) because event_window isn't documented as a public field?
Well, I suppose if you just assume that whenever you get an event on the Notebook it is in event window coordinates, you are OK, but it seems messy. I wonder if we could have: gtk_widget_get_event_position(GtkWidget *widget, GdkEvent *event, int *x, int *y); that translated the event coordinates into widget coordinates - that *is* possible to do generically, though its somewhat tricky. (I'd make that suggestion more enthusiastically, if "widget coordinates" weren't so weirdly defined...)
Continuing to talk to myself: "assuming that whenever you get an event it is in event window coordinates" is simply wrong, because of the inheritance of button press events up the widget heirarchy when not handled.
Created attachment 74578 [details] [review] patch This patch implements gtk_widget_get_event_position() and gtk_notebook_get_tab_at_pos(), with this, all that an event handler should do to know the tab below the pointer is: gint x, y, position; gtk_widget_get_event_position (widget, event, &x, y); position = gtk_notebook_get_tab_at_pos (GTK_NOTEBOOK (widget), x, y);
g_return_val_if_fail (gdk_event_get_coords (event, &event_x, &event_y), FALSE); You can't rely on side-effects of return-val-if-fail. + * Return Value: #FALSE if the widget is not realized, the widget and + * the event window do not share a common toplevel, or the event doesn't + * deliver event window coordinates. I don't see any code to return FALSE if the even does not deliver event window coordinates. The documentation should probably mention for which types of common events this does work, like mouse events.
Created attachment 76610 [details] [review] updated patch, fixes those issues
Yes, looks better on that count. But I have to admit that I'm not really sure that it returns the correct values in all cases, since as Owen said, widget coordinates are wierd.
as far as I can tell, it would always return coordinates relative to the widget allocation, was done following the same semantics than gtk_widget_translate_coordinates(), even uses it if the event which receives the event and the passed widget aren't the same. Oh, perhaps allocation relative coordinates isn't always equivalent to widget coordinates? AFAICS gtk_widget_translate_coordinates() tries to make clear that it's using the former, should just a doc change making this clear be ok?
Patch 76610 applies cleanly. Reviewing it would take a little while. (Working on http://mail.gnome.org/archives/gtk-devel-list/2007-March/msg00148.html)
Could a maintainer review the patch, please?
To me the proposed approach seems a little awkward, particularly when looking back at the original use case. What about (a) signal(s) being emitted whenever a mouse button is pressed over a tab label? One argument could be the page index.
We're moving to gitlab! As part of this move, we are closing bugs that haven't seen activity in more than 5 years. If this issue is still imporant to you and still relevant with GTK+ 3.22 or master, please consider creating a gitlab issue for it.