[gtk+] widget: Implement gtk_widget_pick()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] widget: Implement gtk_widget_pick()
- Date: Sun, 5 Nov 2017 04:18:15 +0000 (UTC)
commit cf2d549e922b51e7c4c790c04531be0cfb6ddd63
Author: Benjamin Otte <otte redhat com>
Date: Sun Nov 5 00:49:18 2017 +0100
widget: Implement gtk_widget_pick()
... and use it.
docs/reference/gtk/gtk4-sections.txt | 1 +
gtk/gtkmain.c | 31 ++++----------------
gtk/gtkpointerfocus.c | 5 ++-
gtk/gtkwidget.c | 53 +++++++++++++++++++++++++++------
gtk/gtkwidget.h | 8 +++--
gtk/gtkwindow.c | 36 ++++++----------------
gtk/inspector/inspect-button.c | 14 +-------
7 files changed, 70 insertions(+), 78 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 0c5003c..27c8de3 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4592,6 +4592,7 @@ gtk_widget_get_width
gtk_widget_get_height
gtk_widget_get_clip
gtk_widget_contains
+gtk_widget_pick
gtk_widget_get_can_default
gtk_widget_set_can_default
gtk_widget_get_can_focus
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 198bd91..5837f7c 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1509,7 +1509,9 @@ handle_pointing_event (GdkEvent *event)
case GDK_TOUCH_BEGIN:
case GDK_TOUCH_UPDATE:
case GDK_MOTION_NOTIFY:
- target = _gtk_toplevel_pick (toplevel, x, y, NULL, NULL);
+ target = gtk_widget_pick (GTK_WIDGET (toplevel), x, y);
+ if (target == NULL)
+ target = GTK_WIDGET (toplevel);
old_target = update_pointer_focus_state (toplevel, event, target);
if (event->type == GDK_MOTION_NOTIFY || event->type == GDK_ENTER_NOTIFY)
@@ -1544,7 +1546,9 @@ handle_pointing_event (GdkEvent *event)
if (event->type == GDK_BUTTON_RELEASE)
{
old_target = target;
- target = _gtk_toplevel_pick (toplevel, x, y, NULL, NULL);
+ target = gtk_widget_pick (GTK_WIDGET (toplevel), x, y);
+ if (target == NULL)
+ target = GTK_WIDGET (toplevel);
gtk_synthesize_crossing_events (toplevel, old_target, target, event,
GDK_CROSSING_UNGRAB);
gtk_window_maybe_update_cursor (toplevel, NULL, device);
@@ -2617,26 +2621,3 @@ gtk_propagate_event (GtkWidget *widget,
gtk_propagate_event_internal (widget, event, topmost);
}
-
-GtkWidget *
-_gtk_toplevel_pick (GtkWindow *toplevel,
- gdouble x,
- gdouble y,
- gdouble *x_out,
- gdouble *y_out)
-{
- GtkWidget *target = NULL, *widget = GTK_WIDGET (toplevel);
-
- while (widget)
- {
- target = widget;
- widget = GTK_WIDGET_GET_CLASS (target)->pick (widget, x, y, &x, &y);
- }
-
- if (x_out)
- *x_out = x;
- if (y_out)
- *y_out = y;
-
- return target;
-}
diff --git a/gtk/gtkpointerfocus.c b/gtk/gtkpointerfocus.c
index cb484b8..5229e39 100644
--- a/gtk/gtkpointerfocus.c
+++ b/gtk/gtkpointerfocus.c
@@ -133,7 +133,8 @@ gtk_pointer_focus_repick_target (GtkPointerFocus *focus)
{
GtkWidget *target;
- target = _gtk_toplevel_pick (focus->toplevel, focus->x, focus->y,
- NULL, NULL);
+ target = gtk_widget_pick (GTK_WIDGET (focus->toplevel), focus->x, focus->y);
+ if (target == NULL)
+ target = GTK_WIDGET (focus->toplevel);
gtk_pointer_focus_set_target (focus, target);
}
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 70152b9..69dfe6d 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -951,29 +951,28 @@ gtk_widget_real_contains (GtkWidget *widget,
static GtkWidget *
gtk_widget_real_pick (GtkWidget *widget,
gdouble x,
- gdouble y,
- gdouble *x_out,
- gdouble *y_out)
+ gdouble y)
{
GtkWidget *child;
+ if (!gtk_widget_contains (widget, x, y))
+ return NULL;
+
for (child = _gtk_widget_get_last_child (widget);
child;
child = _gtk_widget_get_prev_sibling (child))
{
+ GtkWidget *picked;
int dx, dy;
gtk_widget_get_origin_relative_to_parent (child, &dx, &dy);
- if (gtk_widget_contains (child, x - dx, y - dy))
- {
- *x_out = x - dx;
- *y_out = y - dy;
- return child;
- }
+ picked = gtk_widget_pick (child, x - dx, y - dy);
+ if (picked)
+ return picked;
}
- return NULL;
+ return widget;
}
static void
@@ -13156,6 +13155,40 @@ gtk_widget_contains (GtkWidget *widget,
return GTK_WIDGET_GET_CLASS (widget)->contains (widget, x, y);
}
+/**
+ * gtk_widget_pick:
+ * @widget: the widget to query
+ * @x: X coordinate to test, relative to @widget's origin
+ * @y: Y coordinate to test, relative to @widget's origin
+ *
+ * Finds the descendant of widget (including widget itself) closest
+ * to the screen at the point (@x, @y). The point must be given in
+ * widget coordinates, so (0, 0) is assumed to be the top left of
+ * @widget's content area.
+ *
+ * Usually widgets will return %NULL if the given coordinate is not
+ * contained in @widget checked via gtk_widget_contains(). Otherwise
+ * they will recursively try to find a child that does not return %NULL.
+ * Widgets are however free to customize their picking algorithm.
+ *
+ * This function is used on the toplevel to determine the widget below
+ * the mouse cursor for purposes of hover hilighting and delivering events.
+ *
+ * Returns: (nullable) (transfer none): The widget descendant at the given
+ * coordinate or %NULL if none.
+ *
+ * Since: 3.94
+ **/
+GtkWidget *
+gtk_widget_pick (GtkWidget *widget,
+ gdouble x,
+ gdouble y)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ return GTK_WIDGET_GET_CLASS (widget)->pick (widget, x, y);
+}
+
void
gtk_widget_get_outer_allocation (GtkWidget *widget,
GdkRectangle *allocation)
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 0f4a785..3568d87 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -472,9 +472,7 @@ struct _GtkWidgetClass
gdouble y);
GtkWidget * (* pick) (GtkWidget *widget,
gdouble x,
- gdouble y,
- gdouble *x_out,
- gdouble *y_out);
+ gdouble y);
/*< private >*/
@@ -894,6 +892,10 @@ GDK_AVAILABLE_IN_3_94
gboolean gtk_widget_contains (GtkWidget *widget,
gdouble x,
gdouble y);
+GDK_AVAILABLE_IN_3_94
+GtkWidget * gtk_widget_pick (GtkWidget *widget,
+ gdouble x,
+ gdouble y);
/* Hide widget and return TRUE.
*/
GDK_AVAILABLE_IN_ALL
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index ed60d5c..6a80635 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -742,9 +742,7 @@ static void popover_get_rect (GtkWindowPopover *popover,
static GtkWidget *
gtk_window_pick (GtkWidget *widget,
gdouble x,
- gdouble y,
- gdouble *x_out,
- gdouble *y_out)
+ gdouble y)
{
GtkWindow *window = GTK_WINDOW (widget);
GList *popovers;
@@ -752,33 +750,19 @@ gtk_window_pick (GtkWidget *widget,
for (popovers = window->priv->popovers.tail; popovers; popovers = popovers->prev)
{
GtkWindowPopover *popover = popovers->data;
- cairo_rectangle_int_t rect;
-
- if (!gtk_widget_is_sensitive (popover->widget) ||
- !gtk_widget_is_drawable (popover->widget))
- continue;
+ int dest_x, dest_y;
+ GtkWidget *picked;
- gtk_widget_get_outer_allocation (popover->widget, &rect);
+ gtk_widget_translate_coordinates (widget, popover->widget,
+ x, y,
+ &dest_x, &dest_y);
- if (gdk_rectangle_contains_point (&rect, x, y))
- {
- if (x_out && y_out)
- {
- int dest_x, dest_y;
- gtk_widget_translate_coordinates (widget, popover->widget,
- x, y,
- &dest_x, &dest_y);
-
- *x_out = dest_x;
- *y_out = dest_y;
- }
-
- return popover->widget;
- }
+ picked = gtk_widget_pick (popover->widget, dest_x, dest_y);
+ if (picked)
+ return picked;
}
- return GTK_WIDGET_CLASS (gtk_window_parent_class)->pick (widget, x, y,
- x_out, y_out);
+ return GTK_WIDGET_CLASS (gtk_window_parent_class)->pick (widget, x, y);
}
static void
diff --git a/gtk/inspector/inspect-button.c b/gtk/inspector/inspect-button.c
index 8c5ecdc..517e716 100644
--- a/gtk/inspector/inspect-button.c
+++ b/gtk/inspector/inspect-button.c
@@ -73,20 +73,10 @@ find_widget_at_pointer (GdkDevice *device)
gdk_window_get_device_position_double (gtk_widget_get_window (widget),
device, &x, &y, NULL);
- while (widget)
- {
- GtkWidget *w;
-
- w = GTK_WIDGET_GET_CLASS (widget)->pick (widget, x, y, &x, &y);
-
- if (!w)
- return widget;
-
- widget = w;
- }
+ widget = gtk_widget_pick (widget, x, y);
}
- return NULL;
+ return widget;
}
static gboolean draw_flash (GtkWidget *widget,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]