mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 10:50:10 +00:00
widget: Implement gtk_widget_pick()
... and use it.
This commit is contained in:
parent
65a7557fc1
commit
cf2d549e92
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
int dest_x, dest_y;
|
||||
GtkWidget *picked;
|
||||
|
||||
if (!gtk_widget_is_sensitive (popover->widget) ||
|
||||
!gtk_widget_is_drawable (popover->widget))
|
||||
continue;
|
||||
gtk_widget_translate_coordinates (widget, popover->widget,
|
||||
x, y,
|
||||
&dest_x, &dest_y);
|
||||
|
||||
gtk_widget_get_outer_allocation (popover->widget, &rect);
|
||||
|
||||
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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user