]> Pileus Git - ~andy/gtk/blobdiff - gdk/quartz/gdkevents-quartz.c
Change FSF Address
[~andy/gtk] / gdk / quartz / gdkevents-quartz.c
index f4f4e8abfe46b8626a3223f76706a7112dab5001..ec3440d47a7d729e61ed3e240960246b5fb36059 100644 (file)
@@ -15,9 +15,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
 #import <Cocoa/Cocoa.h>
 #include <Carbon/Carbon.h>
 
+#include <gdk/gdkdisplayprivate.h>
+
 #include "gdkscreen.h"
 #include "gdkkeysyms.h"
-#include "gdkdisplay-quartz.h"
+#include "gdkquartz.h"
+#include "gdkquartzdisplay.h"
 #include "gdkprivate-quartz.h"
-#include "gdkdevicemanager-core.h"
+#include "gdkquartzdevicemanager-core.h"
 
 #define GRIP_WIDTH 15
 #define GRIP_HEIGHT 15
+#define GDK_LION_RESIZE 5
 
 #define WINDOW_IS_TOPLEVEL(window)                  \
   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
 /* This is the window corresponding to the key window */
 static GdkWindow   *current_keyboard_window;
 
-/* This is the event mask and button state from the last event */
-static GdkEventMask current_event_mask;
-static int          current_button_state;
 
 static void append_event                        (GdkEvent  *event,
                                                  gboolean   windowing);
 
-NSEvent *
-gdk_quartz_event_get_nsevent (GdkEvent *event)
-{
-  /* FIXME: If the event here is unallocated, we crash. */
-  return ((GdkEventPrivate *) event)->windowing_data;
-}
+static GdkWindow *find_toplevel_under_pointer   (GdkDisplay *display,
+                                                 NSPoint     screen_point,
+                                                 gint       *x,
+                                                 gint       *y);
+
 
 void
 _gdk_quartz_events_init (void)
@@ -198,6 +196,25 @@ get_mouse_button_from_ns_event (NSEvent *event)
     }
 }
 
+static GdkModifierType
+get_mouse_button_modifiers_from_ns_buttons (NSUInteger nsbuttons)
+{
+  GdkModifierType modifiers = 0;
+
+  if (nsbuttons & (1 << 0))
+    modifiers |= GDK_BUTTON1_MASK;
+  if (nsbuttons & (1 << 1))
+    modifiers |= GDK_BUTTON3_MASK;
+  if (nsbuttons & (1 << 2))
+    modifiers |= GDK_BUTTON2_MASK;
+  if (nsbuttons & (1 << 3))
+    modifiers |= GDK_BUTTON4_MASK;
+  if (nsbuttons & (1 << 4))
+    modifiers |= GDK_BUTTON5_MASK;
+
+  return modifiers;
+}
+
 static GdkModifierType
 get_mouse_button_modifiers_from_ns_event (NSEvent *event)
 {
@@ -213,25 +230,30 @@ get_mouse_button_modifiers_from_ns_event (NSEvent *event)
 }
 
 static GdkModifierType
-get_keyboard_modifiers_from_ns_event (NSEvent *nsevent)
+get_keyboard_modifiers_from_ns_flags (NSUInteger nsflags)
 {
   GdkModifierType modifiers = 0;
-  int nsflags;
 
-  nsflags = [nsevent modifierFlags];
-  
   if (nsflags & NSAlphaShiftKeyMask)
     modifiers |= GDK_LOCK_MASK;
   if (nsflags & NSShiftKeyMask)
     modifiers |= GDK_SHIFT_MASK;
   if (nsflags & NSControlKeyMask)
     modifiers |= GDK_CONTROL_MASK;
-  if (nsflags & NSCommandKeyMask)
+  if (nsflags & NSAlternateKeyMask)
     modifiers |= GDK_MOD1_MASK;
+  if (nsflags & NSCommandKeyMask)
+    modifiers |= GDK_MOD2_MASK;
 
   return modifiers;
 }
 
+static GdkModifierType
+get_keyboard_modifiers_from_ns_event (NSEvent *nsevent)
+{
+  return get_keyboard_modifiers_from_ns_flags ([nsevent modifierFlags]);
+}
+
 /* Return an event mask from an NSEvent */
 static GdkEventMask
 get_event_mask_from_ns_event (NSEvent *nsevent)
@@ -307,18 +329,73 @@ get_event_mask_from_ns_event (NSEvent *nsevent)
   return 0;
 }
 
+static void
+get_window_point_from_screen_point (GdkWindow *window,
+                                    NSPoint    screen_point,
+                                    gint      *x,
+                                    gint      *y)
+{
+  NSPoint point;
+  NSWindow *nswindow;
+
+  nswindow = ((GdkWindowImplQuartz *)window->impl)->toplevel;
+
+  point = [nswindow convertScreenToBase:screen_point];
+
+  *x = point.x;
+  *y = window->height - point.y;
+}
+
+static GdkWindow *
+get_toplevel_from_ns_event (NSEvent *nsevent,
+                            NSPoint *screen_point,
+                            gint    *x,
+                            gint    *y)
+{
+  GdkWindow *toplevel;
+
+  if ([nsevent window])
+    {
+      GdkQuartzView *view;
+      NSPoint point;
+
+      view = (GdkQuartzView *)[[nsevent window] contentView];
+
+      toplevel = [view gdkWindow];
+
+      point = [nsevent locationInWindow];
+      *screen_point = [[nsevent window] convertBaseToScreen:point];
+
+      *x = point.x;
+      *y = toplevel->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;
+}
+
 static GdkEvent *
 create_focus_event (GdkWindow *window,
                    gboolean   in)
 {
   GdkEvent *event;
-  GdkDeviceManagerCore *device_manager;
+  GdkQuartzDeviceManagerCore *device_manager;
 
   event = gdk_event_new (GDK_FOCUS_CHANGE);
   event->focus_change.window = window;
   event->focus_change.in = in;
 
-  device_manager = GDK_DEVICE_MANAGER_CORE (_gdk_display->device_manager);
+  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_display->device_manager);
   gdk_event_set_device (event, device_manager->core_keyboard);
 
   return event;
@@ -328,31 +405,18 @@ create_focus_event (GdkWindow *window,
 static void
 generate_motion_event (GdkWindow *window)
 {
-  NSPoint point;
   NSPoint screen_point;
-  NSWindow *nswindow;
-  GdkQuartzView *view;
   GdkEvent *event;
   gint x, y, x_root, y_root;
-  GdkDisplay *display;
 
   event = gdk_event_new (GDK_MOTION_NOTIFY);
   event->any.window = NULL;
   event->any.send_event = TRUE;
 
-  nswindow = ((GdkWindowImplQuartz *)window->impl)->toplevel;
-  view = (GdkQuartzView *)[nswindow contentView];
-
-  display = gdk_window_get_display (window);
-
   screen_point = [NSEvent mouseLocation];
 
   _gdk_quartz_window_nspoint_to_gdk_xy (screen_point, &x_root, &y_root);
-
-  point = [nswindow convertScreenToBase:screen_point];
-
-  x = point.x;
-  y = window->height - point.y;
+  get_window_point_from_screen_point (window, screen_point, &x, &y);
 
   event->any.type = GDK_MOTION_NOTIFY;
   event->motion.window = window;
@@ -362,7 +426,8 @@ generate_motion_event (GdkWindow *window)
   event->motion.x_root = x_root;
   event->motion.y_root = y_root;
   /* FIXME event->axes */
-  event->motion.state = 0;
+  event->motion.state = _gdk_quartz_events_get_current_keyboard_modifiers () |
+                        _gdk_quartz_events_get_current_mouse_modifiers ();
   event->motion.is_hint = FALSE;
   event->motion.device = _gdk_display->core_pointer;
 
@@ -379,7 +444,7 @@ _gdk_quartz_events_update_focus_window (GdkWindow *window,
   if (got_focus && window == current_keyboard_window)
     return;
 
-  /* FIXME: Don't do this when grabbed? Or make GdkQuartzWindow
+  /* FIXME: Don't do this when grabbed? Or make GdkQuartzNSWindow
    * disallow it in the first place instead?
    */
   
@@ -417,9 +482,7 @@ _gdk_quartz_events_update_focus_window (GdkWindow *window,
 void
 _gdk_quartz_events_send_enter_notify_event (GdkWindow *window)
 {
-  NSPoint point;
   NSPoint screen_point;
-  NSWindow *nswindow;
   GdkEvent *event;
   gint x, y, x_root, y_root;
 
@@ -427,16 +490,10 @@ _gdk_quartz_events_send_enter_notify_event (GdkWindow *window)
   event->any.window = NULL;
   event->any.send_event = FALSE;
 
-  nswindow = ((GdkWindowImplQuartz *)window->impl)->toplevel;
-
   screen_point = [NSEvent mouseLocation];
 
   _gdk_quartz_window_nspoint_to_gdk_xy (screen_point, &x_root, &y_root);
-
-  point = [nswindow convertScreenToBase:screen_point];
-
-  x = point.x;
-  y = window->height - point.y;
+  get_window_point_from_screen_point (window, screen_point, &x, &y);
 
   event->crossing.window = window;
   event->crossing.subwindow = NULL;
@@ -447,7 +504,8 @@ _gdk_quartz_events_send_enter_notify_event (GdkWindow *window)
   event->crossing.y_root = y_root;
   event->crossing.mode = GDK_CROSSING_NORMAL;
   event->crossing.detail = GDK_NOTIFY_ANCESTOR;
-  event->crossing.state = 0;
+  event->crossing.state = _gdk_quartz_events_get_current_keyboard_modifiers () |
+                          _gdk_quartz_events_get_current_mouse_modifiers ();
 
   gdk_event_set_device (event, _gdk_display->core_pointer);
 
@@ -485,17 +543,7 @@ find_toplevel_under_pointer (GdkDisplay *display,
   info = _gdk_display_get_pointer_info (display, display->core_pointer);
   toplevel = info->toplevel_under_pointer;
   if (toplevel && WINDOW_IS_TOPLEVEL (toplevel))
-    {
-      NSWindow *nswindow;
-      NSPoint point;
-
-      nswindow = ((GdkWindowImplQuartz *)toplevel->impl)->toplevel;
-
-      point = [nswindow convertScreenToBase:screen_point];
-
-      *x = point.x;
-      *y = toplevel->height - point.y;
-    }
+    get_window_point_from_screen_point (toplevel, screen_point, x, y);
 
   return toplevel;
 }
@@ -543,22 +591,17 @@ find_toplevel_for_mouse_event (NSEvent    *nsevent,
                                gint       *x,
                                gint       *y)
 {
-  NSPoint point;
   NSPoint screen_point;
   NSEventType event_type;
   GdkWindow *toplevel;
-  GdkQuartzView *view;
   GdkDisplay *display;
   GdkDeviceGrabInfo *grab;
 
-  view = (GdkQuartzView *)[[nsevent window] contentView];
-  toplevel = [view gdkWindow];
+  toplevel = get_toplevel_from_ns_event (nsevent, &screen_point, x, y);
 
   display = gdk_window_get_display (toplevel);
 
   event_type = [nsevent type];
-  point = [nsevent locationInWindow];
-  screen_point = [[nsevent window] convertBaseToScreen:point];
 
   /* From the docs for XGrabPointer:
    *
@@ -606,16 +649,10 @@ find_toplevel_for_mouse_event (NSEvent    *nsevent,
         {
           /* Finally check the grab window. */
           GdkWindow *grab_toplevel;
-          NSWindow *grab_nswindow;
 
           grab_toplevel = gdk_window_get_effective_toplevel (grab->window);
-
-          grab_nswindow = ((GdkWindowImplQuartz *)grab_toplevel->impl)->toplevel;
-          point = [grab_nswindow convertScreenToBase:screen_point];
-
-          /* Note: x_root and y_root are already right. */
-          *x = point.x;
-          *y = grab_toplevel->height - point.y;
+          get_window_point_from_screen_point (grab_toplevel, screen_point,
+                                              x, y);
 
           return grab_toplevel;
         }
@@ -652,30 +689,6 @@ find_toplevel_for_mouse_event (NSEvent    *nsevent,
 
           toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
 
-          if ([toplevel_impl->toplevel showsResizeIndicator])
-            {
-              NSRect frame;
-
-              /* If the resize indicator is visible and the event
-               * is in the lower right 15x15 corner, we leave these
-               * events to Cocoa as to be handled as resize events.
-               * Applications may have widgets in this area.  These
-               * will most likely be larger than 15x15 and for
-               * scroll bars there are also other means to move
-               * the scroll bar.  Since the resize indicator is
-               * the only way of resizing windows on Mac OS, it
-               * is too important to not make functional.
-               */
-              frame = [toplevel_impl->view bounds];
-              if (x_tmp > frame.size.width - GRIP_WIDTH
-                  && x_tmp < frame.size.width
-                  && y_tmp > frame.size.height - GRIP_HEIGHT
-                  && y_tmp < frame.size.height)
-                {
-                  return NULL;
-                }
-            }
-
           *x = x_tmp;
           *y = y_tmp;
         }
@@ -697,20 +710,13 @@ find_window_for_ns_event (NSEvent *nsevent,
                           gint    *y_root)
 {
   GdkQuartzView *view;
-  NSPoint point;
+  GdkWindow *toplevel;
   NSPoint screen_point;
   NSEventType event_type;
-  GdkWindow *toplevel;
 
   view = (GdkQuartzView *)[[nsevent window] contentView];
-  toplevel = [view gdkWindow];
-
-  point = [nsevent locationInWindow];
-  screen_point = [[nsevent window] convertBaseToScreen:point];
-
-  *x = point.x;
-  *y = toplevel->height - point.y;
 
+  toplevel = get_toplevel_from_ns_event (nsevent, &screen_point, x, y);
   _gdk_quartz_window_nspoint_to_gdk_xy (screen_point, x_root, y_root);
 
   event_type = [nsevent type];
@@ -775,7 +781,8 @@ fill_crossing_event (GdkWindow       *toplevel,
   event->crossing.y_root = y_root;
   event->crossing.mode = mode;
   event->crossing.detail = detail;
-  event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent);
+  event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent) |
+                         _gdk_quartz_events_get_current_mouse_modifiers ();
 
   gdk_event_set_device (event, _gdk_display->core_pointer);
 
@@ -793,9 +800,9 @@ fill_button_event (GdkWindow *window,
 {
   GdkEventType type;
   gint state;
-  gint button;
 
-  state = get_keyboard_modifiers_from_ns_event (nsevent);
+  state = get_keyboard_modifiers_from_ns_event (nsevent) |
+         _gdk_quartz_events_get_current_mouse_modifiers ();
 
   switch ([nsevent type])
     {
@@ -803,18 +810,19 @@ fill_button_event (GdkWindow *window,
     case NSRightMouseDown:
     case NSOtherMouseDown:
       type = GDK_BUTTON_PRESS;
+      state &= ~get_mouse_button_modifiers_from_ns_event (nsevent);
       break;
+
     case NSLeftMouseUp:
     case NSRightMouseUp:
     case NSOtherMouseUp:
       type = GDK_BUTTON_RELEASE;
       state |= get_mouse_button_modifiers_from_ns_event (nsevent);
       break;
+
     default:
       g_assert_not_reached ();
     }
-  
-  button = get_mouse_button_from_ns_event (nsevent);
 
   event->any.type = type;
   event->button.window = window;
@@ -825,7 +833,7 @@ fill_button_event (GdkWindow *window,
   event->button.y_root = y_root;
   /* FIXME event->axes */
   event->button.state = state;
-  event->button.button = button;
+  event->button.button = get_mouse_button_from_ns_event (nsevent);
   event->button.device = _gdk_display->core_pointer;
 }
 
@@ -838,22 +846,6 @@ fill_motion_event (GdkWindow *window,
                    gint       x_root,
                    gint       y_root)
 {
-  GdkModifierType state;
-
-  state = get_keyboard_modifiers_from_ns_event (nsevent);
-
-  switch ([nsevent type])
-    {
-    case NSLeftMouseDragged:
-    case NSRightMouseDragged:
-    case NSOtherMouseDragged:
-      state |= get_mouse_button_modifiers_from_ns_event (nsevent);
-      break;
-
-    case NSMouseMoved:
-      break;
-    }
-
   event->any.type = GDK_MOTION_NOTIFY;
   event->motion.window = window;
   event->motion.time = get_time_from_ns_event (nsevent);
@@ -862,7 +854,8 @@ fill_motion_event (GdkWindow *window,
   event->motion.x_root = x_root;
   event->motion.y_root = y_root;
   /* FIXME event->axes */
-  event->motion.state = state;
+  event->motion.state = get_keyboard_modifiers_from_ns_event (nsevent) |
+                        _gdk_quartz_events_get_current_mouse_modifiers ();
   event->motion.is_hint = FALSE;
   event->motion.device = _gdk_display->core_pointer;
 }
@@ -900,7 +893,7 @@ fill_key_event (GdkWindow    *window,
                 GdkEventType  type)
 {
   GdkEventPrivate *priv;
-  GdkDeviceManagerCore *device_manager;
+  GdkQuartzDeviceManagerCore *device_manager;
   gchar buf[7];
   gunichar c = 0;
 
@@ -915,10 +908,10 @@ fill_key_event (GdkWindow    *window,
   event->key.group = ([nsevent modifierFlags] & NSAlternateKeyMask) ? 1 : 0;
   event->key.keyval = GDK_KEY_VoidSymbol;
 
-  device_manager = GDK_DEVICE_MANAGER_CORE (_gdk_display->device_manager);
+  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_display->device_manager);
   gdk_event_set_device (event, device_manager->core_keyboard);
   
-  gdk_keymap_translate_keyboard_state (NULL,
+  gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (_gdk_display),
                                       event->key.hardware_keycode,
                                       event->key.state, 
                                       event->key.group,
@@ -939,7 +932,7 @@ fill_key_event (GdkWindow    *window,
         {
         case GDK_KEY_Meta_R:
         case GDK_KEY_Meta_L:
-          mask = GDK_MOD1_MASK;
+          mask = GDK_MOD2_MASK;
           break;
         case GDK_KEY_Shift_R:
         case GDK_KEY_Shift_L:
@@ -950,7 +943,7 @@ fill_key_event (GdkWindow    *window,
           break;
         case GDK_KEY_Alt_R:
         case GDK_KEY_Alt_L:
-          mask = GDK_MOD5_MASK;
+          mask = GDK_MOD1_MASK;
           break;
         case GDK_KEY_Control_R:
         case GDK_KEY_Control_L:
@@ -966,7 +959,14 @@ fill_key_event (GdkWindow    *window,
         event->key.state |= mask;
     }
 
-  event->key.state |= current_button_state;
+  event->key.state |= _gdk_quartz_events_get_current_mouse_modifiers ();
+
+  /* The X11 backend adds the first virtual modifier MOD2..MOD5 are
+   * mapped to. Since we only have one virtual modifier in the quartz
+   * backend, calling the standard function will do.
+   */
+  gdk_keymap_add_virtual_modifiers (gdk_keymap_get_for_display (_gdk_display),
+                                    &event->key.state);
 
   event->key.string = NULL;
 
@@ -1063,10 +1063,97 @@ synthesize_crossing_event (GdkWindow *window,
   return FALSE;
 }
 
-GdkEventMask 
-_gdk_quartz_events_get_current_event_mask (void)
+GdkModifierType
+_gdk_quartz_events_get_current_keyboard_modifiers (void)
+{
+  if (gdk_quartz_osx_version () >= GDK_OSX_SNOW_LEOPARD)
+    {
+      return get_keyboard_modifiers_from_ns_flags ([NSClassFromString(@"NSEvent") modifierFlags]);
+    }
+  else
+    {
+      guint carbon_modifiers = GetCurrentKeyModifiers ();
+      GdkModifierType modifiers = 0;
+
+      if (carbon_modifiers & alphaLock)
+        modifiers |= GDK_LOCK_MASK;
+      if (carbon_modifiers & shiftKey)
+        modifiers |= GDK_SHIFT_MASK;
+      if (carbon_modifiers & controlKey)
+        modifiers |= GDK_CONTROL_MASK;
+      if (carbon_modifiers & optionKey)
+        modifiers |= GDK_MOD1_MASK;
+      if (carbon_modifiers & cmdKey)
+        modifiers |= GDK_MOD2_MASK;
+
+      return modifiers;
+    }
+}
+
+GdkModifierType
+_gdk_quartz_events_get_current_mouse_modifiers (void)
 {
-  return current_event_mask;
+  if (gdk_quartz_osx_version () >= GDK_OSX_SNOW_LEOPARD)
+    {
+      return get_mouse_button_modifiers_from_ns_buttons ([NSClassFromString(@"NSEvent") pressedMouseButtons]);
+    }
+  else
+    {
+      return get_mouse_button_modifiers_from_ns_buttons (GetCurrentButtonState ());
+    }
+}
+
+/* Detect window resizing */
+
+static gboolean
+test_resize (NSEvent *event, GdkWindow *toplevel, gint x, gint y)
+{
+  GdkWindowImplQuartz *toplevel_impl;
+  gboolean lion;
+
+  /* Resizing only begins if an NSLeftMouseButton event is received in
+   * the resizing area. Handle anything else.
+   */
+  if ([event type] != NSLeftMouseDown)
+    return FALSE;
+
+  toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
+  if ([toplevel_impl->toplevel showsResizeIndicator])
+    {
+      NSRect frame;
+
+      /* If the resize indicator is visible and the event
+       * is in the lower right 15x15 corner, we leave these
+       * events to Cocoa as to be handled as resize events.
+       * Applications may have widgets in this area.  These
+       * will most likely be larger than 15x15 and for
+       * scroll bars there are also other means to move
+       * the scroll bar.  Since the resize indicator is
+       * the only way of resizing windows on Mac OS, it
+       * is too important to not make functional.
+       */
+      frame = [toplevel_impl->view bounds];
+      if (x > frame.size.width - GRIP_WIDTH &&
+          x < frame.size.width &&
+          y > frame.size.height - GRIP_HEIGHT &&
+          y < frame.size.height)
+        return TRUE;
+     }
+
+  /* If we're on Lion and within 5 pixels of an edge,
+   * then assume that the user wants to resize, and
+   * return NULL to let Quartz get on with it. We check
+   * the selector isRestorable to see if we're on 10.7.
+   * This extra check is in case the user starts
+   * dragging before GDK recognizes the grab.
+   */
+  lion = gdk_quartz_osx_version () >= GDK_OSX_LION;
+  if (lion && (x < GDK_LION_RESIZE ||
+               x > toplevel->width - GDK_LION_RESIZE ||
+               y > toplevel->height - GDK_LION_RESIZE))
+    return TRUE;
+
+  return FALSE;
 }
 
 static gboolean
@@ -1098,25 +1185,6 @@ gdk_event_translate (GdkEvent *event,
       return FALSE;
     }
 
-  /* Keep track of button state, since we don't get that information
-   * for key events. 
-   */
-  switch (event_type)
-    {
-    case NSLeftMouseDown:
-    case NSRightMouseDown:
-    case NSOtherMouseDown:
-      current_button_state |= get_mouse_button_modifiers_from_ns_event (nsevent);
-      break;
-    case NSLeftMouseUp:
-    case NSRightMouseUp:
-    case NSOtherMouseUp:
-      current_button_state &= ~get_mouse_button_modifiers_from_ns_event (nsevent);
-      break;
-    default:
-      break;
-    }
-
   if (_gdk_default_filters)
     {
       /* Apply global filters */
@@ -1132,15 +1200,38 @@ 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.
    */
-  if ([(GdkQuartzWindow *)nswindow isInMove])
+  if ([(GdkQuartzNSWindow *)nswindow isInMove])
     {
       break_all_grabs (get_time_from_ns_event (nsevent));
       return FALSE;
@@ -1153,6 +1244,10 @@ gdk_event_translate (GdkEvent *event,
   if (!window)
     return FALSE;
 
+  /* Quartz handles resizing on its own, so we want to stay out of the way. */
+  if (test_resize (nsevent, window, x, y))
+    return FALSE;
+
   /* Apply any window filters. */
   if (GDK_IS_WINDOW (window))
     {
@@ -1201,8 +1296,6 @@ gdk_event_translate (GdkEvent *event,
         }
     }
 
-  current_event_mask = get_event_mask_from_ns_event (nsevent);
-
   return_val = TRUE;
 
   switch (event_type)
@@ -1336,42 +1429,6 @@ _gdk_quartz_display_queue_events (GdkDisplay *display)
     }
 }
 
-void
-gdk_flush (void)
-{
-  /* Not supported. */
-}
-
-void
-_gdk_quartz_display_add_client_message_filter (GdkDisplay   *display,
-                                               GdkAtom       message_type,
-                                               GdkFilterFunc func,
-                                               gpointer      data)
-{
-  /* Not supported. */
-}
-
-void
-_gdk_quartz_display_sync (GdkDisplay *display)
-{
-  /* Not supported. */
-}
-
-void
-_gdk_quartz_display_flush (GdkDisplay *display)
-{
-  /* Not supported. */
-}
-
-gboolean
-_gdk_quartz_display_send_client_message (GdkDisplay      *display,
-                                         GdkEvent        *event,
-                                         GdkNativeWindow  winid)
-{
-  /* Not supported. */
-  return FALSE;
-}
-
 void
 _gdk_quartz_screen_broadcast_client_message (GdkScreen *screen,
                                              GdkEvent  *event)