[gtk+/gtk-2-24] quartz: Process motion events within windows bounds without window set



commit 6725dee3aabc3335450657c5d40d54d6d217eeee
Author: Kristian Rietveld <kris lanedo com>
Date:   Sun Nov 6 09:25:16 2011 +0100

    quartz: Process motion events within windows bounds without window set
    
    When an NSEvent does not have the window field set, we already assumed
    the event was not for us and discarded it.  But for NSMouseMoved events
    we now make an exception, because such events generated after
    using/clicking the main menu bar have the window field set to NULL while
    the application window still has focus.
    
    We used to experience a loss of motion events after using the menu bar,
    this could be seen in buttons that stopped prelighting and first
    clicks often being ignored unless you clicked somewhere else first.
    These issues are fixed by this patch.

 gdk/quartz/gdkevents-quartz.c |   68 +++++++++++++++++++++++++++++++++-------
 1 files changed, 56 insertions(+), 12 deletions(-)
---
diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c
index 75ad808..9d389f4 100644
--- a/gdk/quartz/gdkevents-quartz.c
+++ b/gdk/quartz/gdkevents-quartz.c
@@ -52,6 +52,12 @@ static int          current_button_state;
 static void append_event                        (GdkEvent  *event,
                                                  gboolean   windowing);
 
+static GdkWindow *find_toplevel_under_pointer   (GdkDisplay *display,
+                                                 NSPoint     screen_point,
+                                                 gint       *x,
+                                                 gint       *y);
+
+
 NSEvent *
 gdk_quartz_event_get_nsevent (GdkEvent *event)
 {
@@ -379,21 +385,36 @@ get_toplevel_from_ns_event (NSEvent *nsevent,
                             gint    *x,
                             gint    *y)
 {
-  GdkQuartzView *view;
   GdkWindow *toplevel;
-  GdkWindowObject *private;
-  NSPoint point;
 
-  view = (GdkQuartzView *)[[nsevent window] contentView];
+  if ([nsevent window])
+    {
+      GdkQuartzView *view;
+      GdkWindowObject *private;
+      NSPoint point;
 
-  toplevel = [view gdkWindow];
-  private = GDK_WINDOW_OBJECT (toplevel);
+      view = (GdkQuartzView *)[[nsevent window] contentView];
 
-  point = [nsevent locationInWindow];
-  *screen_point = [[nsevent window] convertBaseToScreen:point];
+      toplevel = [view gdkWindow];
+      private = GDK_WINDOW_OBJECT (toplevel);
 
-  *x = point.x;
-  *y = private->height - point.y;
+      point = [nsevent locationInWindow];
+      *screen_point = [[nsevent window] convertBaseToScreen:point];
+
+      *x = point.x;
+      *y = private->height - point.y;
+    }
+  else
+    {
+      /* Fallback used when no NSWindow set.  This happens e.g. when
+       * we allow motion events without a window set in gdk_event_translate()
+       * that occur immediately after the main menu bar was clicked/used.
+       */
+      *screen_point = [NSEvent mouseLocation];
+      toplevel = find_toplevel_under_pointer (_gdk_display,
+                                              *screen_point,
+                                              x, y);
+    }
 
   return toplevel;
 }
@@ -1153,10 +1174,33 @@ gdk_event_translate (GdkEvent *event,
 
   nswindow = [nsevent window];
 
-  /* Ignore events for no window or ones not created by GDK. */
-  if (!nswindow || ![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
+  /* Ignore events for windows not created by GDK. */
+  if (nswindow && ![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
     return FALSE;
 
+  /* Ignore events for ones with no windows */
+  if (!nswindow)
+    {
+      GdkWindow *toplevel = NULL;
+
+      if (event_type == NSMouseMoved)
+        {
+          /* Motion events received after clicking the menu bar do not have the
+           * window field set.  Instead of giving up on the event immediately,
+           * we first check whether this event is within our window bounds.
+           */
+          NSPoint screen_point = [NSEvent mouseLocation];
+          gint x_tmp, y_tmp;
+
+          toplevel = find_toplevel_under_pointer (_gdk_display,
+                                                  screen_point,
+                                                  &x_tmp, &y_tmp);
+        }
+
+      if (!toplevel)
+        return FALSE;
+    }
+
   /* Ignore events and break grabs while the window is being
    * dragged. This is a workaround for the window getting events for
    * the window title.



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