[gtk/wip/matthiasc/focus3: 25/40] Share crossing and focus change event code



commit cdcd2bb073e55a50eacad04497fbbb6eacac378a
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Mar 6 22:25:31 2019 -0500

    Share crossing and focus change event code
    
    Make a single function that can emit both
    enter/leave and focus change events.

 gtk/gtkmain.c | 106 +++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 39 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 9cc8c22e7d..70a7c43313 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1407,61 +1407,65 @@ static void
 synth_crossing (GtkWidget       *widget,
                 GtkWidget       *toplevel,
                 gboolean         enter,
-                GtkWidget       *other_widget,
+                GtkWidget       *target,
+                GtkWidget       *related_target,
                 GdkEvent        *source,
                 GdkNotifyType    notify_type,
                 GdkCrossingMode  crossing_mode)
 {
   GdkEvent *event;
-  gdouble x, y;
+  GtkStateFlags flags;
+
+  if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE)
+    {
+      event = gdk_event_new (GDK_FOCUS_CHANGE);
+      event->focus_change.in = enter;
+      event->focus_change.mode = crossing_mode;
+      event->focus_change.detail = notify_type;
+
+      flags = GTK_STATE_FLAG_FOCUSED;
+      if (!GTK_IS_WINDOW (toplevel) || gtk_window_get_focus_visible (GTK_WINDOW (toplevel)))
+        flags |= GTK_STATE_FLAG_FOCUS_VISIBLE;
+    }
+  else
+    {
+      gdouble x, y;
+      event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
+      if (related_target)
+        event->crossing.child_surface = g_object_ref (gtk_widget_get_surface (related_target));
+      gdk_event_get_coords (source, &x, &y);
+      event->crossing.x = x;
+      event->crossing.y = y;
+      event->crossing.mode = crossing_mode;
+      event->crossing.detail = notify_type;
+
+      flags = GTK_STATE_FLAG_PRELIGHT;
+    }
 
-  event = gdk_event_new (enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
-  gdk_event_set_target (event, G_OBJECT (widget));
+  gdk_event_set_target (event, G_OBJECT (target));
+  gdk_event_set_related_target (event, G_OBJECT (related_target));
   gdk_event_set_device (event, gdk_event_get_device (source));
   gdk_event_set_source_device (event, gdk_event_get_source_device (source));
 
   event->any.surface = g_object_ref (gtk_widget_get_surface (toplevel));
-  if (other_widget)
-    event->crossing.child_surface = g_object_ref (gtk_widget_get_surface (other_widget));
 
   if (enter)
-    gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
+    gtk_widget_set_state_flags (widget, flags, FALSE);
   else
-    gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT);
-
-  gdk_event_get_coords (source, &x, &y);
-  event->crossing.x = x;
-  event->crossing.y = y;
-  event->crossing.mode = crossing_mode;
-  event->crossing.detail = notify_type;
+    gtk_widget_unset_state_flags (widget, flags);
 
+  if (gdk_event_get_event_type (source) == GDK_FOCUS_CHANGE)
+    {
+      if (notify_type == GDK_NOTIFY_ANCESTOR ||
+          notify_type == GDK_NOTIFY_INFERIOR ||
+          notify_type == GDK_NOTIFY_NONLINEAR)
+        gtk_widget_set_has_focus (widget, enter);
+    }
+    
   gtk_widget_event (widget, event);
   g_object_unref (event);
 }
 
-static GtkWidget *
-update_pointer_focus_state (GtkWindow *toplevel,
-                            GdkEvent  *event,
-                            GtkWidget *new_target)
-{
-  GtkWidget *old_target = NULL;
-  GdkEventSequence *sequence;
-  GdkDevice *device;
-  gdouble x, y;
-
-  device = gdk_event_get_device (event);
-  sequence = gdk_event_get_event_sequence (event);
-  old_target = gtk_window_lookup_pointer_focus_widget (toplevel, device, sequence);
-  if (old_target == new_target)
-    return old_target;
-
-  gdk_event_get_coords (event, &x, &y);
-  gtk_window_update_pointer_focus (toplevel, device, sequence,
-                                   new_target, x, y);
-
-  return old_target;
-}
-
 static void
 gtk_synthesize_crossing_events (GtkWindow       *toplevel,
                                 GtkWidget       *old_target,
@@ -1498,7 +1502,7 @@ gtk_synthesize_crossing_events (GtkWindow       *toplevel,
             leave_type : get_virtual_notify_type (leave_type);
 
           synth_crossing (widget, GTK_WIDGET (toplevel), FALSE,
-                          new_target, event, notify_type, mode);
+                          old_target, new_target, event, notify_type, mode);
           widget = gtk_widget_get_parent (widget);
         }
     }
@@ -1523,11 +1527,35 @@ gtk_synthesize_crossing_events (GtkWindow       *toplevel,
             enter_type : get_virtual_notify_type (enter_type);
 
           synth_crossing (widget, GTK_WIDGET (toplevel), TRUE,
-                          old_target, event, notify_type, mode);
+                          new_target, old_target, event, notify_type, mode);
         }
     }
 }
 
+
+static GtkWidget *
+update_pointer_focus_state (GtkWindow *toplevel,
+                            GdkEvent  *event,
+                            GtkWidget *new_target)
+{
+  GtkWidget *old_target = NULL;
+  GdkEventSequence *sequence;
+  GdkDevice *device;
+  gdouble x, y;
+
+  device = gdk_event_get_device (event);
+  sequence = gdk_event_get_event_sequence (event);
+  old_target = gtk_window_lookup_pointer_focus_widget (toplevel, device, sequence);
+  if (old_target == new_target)
+    return old_target;
+
+  gdk_event_get_coords (event, &x, &y);
+  gtk_window_update_pointer_focus (toplevel, device, sequence,
+                                   new_target, x, y);
+
+  return old_target;
+}
+
 static gboolean
 is_pointing_event (GdkEvent *event)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]