eventcontrollermotion: translate event to widget coordinates
When creating the motion controller, we know the widget that is of interest based on gtk_event_controller_motion_new(). However, not all incoming events are guaranteed to be of the GdkWindow associated to that widget. They may also be for a descendant. Therefore, it is useful to translate those coordinates into the target widget coordinate space as that is likely what they care about.
This commit is contained in:
		@ -58,18 +58,49 @@ static guint signals[N_SIGNALS] = { 0 };
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (GtkEventControllerMotion, gtk_event_controller_motion, GTK_TYPE_EVENT_CONTROLLER)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
get_coords (GtkWidget      *widget,
 | 
			
		||||
            const GdkEvent *event,
 | 
			
		||||
            double         *x,
 | 
			
		||||
            double         *y)
 | 
			
		||||
{
 | 
			
		||||
  GdkWindow *window, *ancestor;
 | 
			
		||||
  GtkAllocation alloc;
 | 
			
		||||
 | 
			
		||||
  gtk_widget_get_allocation (widget, &alloc);
 | 
			
		||||
  gdk_event_get_coords (event, x, y);
 | 
			
		||||
 | 
			
		||||
  ancestor = gtk_widget_get_window (widget);
 | 
			
		||||
  window = gdk_event_get_window (event);
 | 
			
		||||
 | 
			
		||||
  while (window && ancestor && (window != ancestor))
 | 
			
		||||
    {
 | 
			
		||||
      gdk_window_coords_to_parent (window, *x, *y, x, y);
 | 
			
		||||
      window = gdk_window_get_parent (window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!gtk_widget_get_has_window (widget))
 | 
			
		||||
    {
 | 
			
		||||
      *x -= alloc.x;
 | 
			
		||||
      *y -= alloc.y;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
gtk_event_controller_motion_handle_event (GtkEventController *controller,
 | 
			
		||||
                                          const GdkEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
  GtkEventControllerClass *parent_class;
 | 
			
		||||
  GtkWidget *widget;
 | 
			
		||||
  GdkEventType type;
 | 
			
		||||
 | 
			
		||||
  widget = gtk_event_controller_get_widget (controller);
 | 
			
		||||
 | 
			
		||||
  type = gdk_event_get_event_type (event);
 | 
			
		||||
  if (type == GDK_ENTER_NOTIFY)
 | 
			
		||||
    {
 | 
			
		||||
      double x, y;
 | 
			
		||||
      gdk_event_get_coords (event, &x, &y);
 | 
			
		||||
      get_coords (widget, event, &x, &y);
 | 
			
		||||
      g_signal_emit (controller, signals[ENTER], 0, x, y);
 | 
			
		||||
    }
 | 
			
		||||
  else if (type == GDK_LEAVE_NOTIFY)
 | 
			
		||||
@ -79,7 +110,7 @@ gtk_event_controller_motion_handle_event (GtkEventController *controller,
 | 
			
		||||
  else if (type == GDK_MOTION_NOTIFY)
 | 
			
		||||
    {
 | 
			
		||||
      double x, y;
 | 
			
		||||
      gdk_event_get_coords (event, &x, &y);
 | 
			
		||||
      get_coords (widget, event, &x, &y);
 | 
			
		||||
      g_signal_emit (controller, signals[MOTION], 0, x, y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user