]> Pileus Git - ~andy/gtk/blobdiff - gdk/quartz/gdkevents-quartz.c
Change FSF Address
[~andy/gtk] / gdk / quartz / gdkevents-quartz.c
index 1a0b67846b4a258532af51291181d58323c68036..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 "gdkquartz.h"
+#include "gdkquartzdisplay.h"
 #include "gdkprivate-quartz.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 &&   \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
 
 /* 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_events_init (void)
+_gdk_quartz_events_init (void)
 {
   _gdk_quartz_event_loop_init ();
 
@@ -62,103 +67,36 @@ _gdk_events_init (void)
 }
 
 gboolean
-gdk_events_pending (void)
-{
-  return (_gdk_event_queue_find_first (_gdk_display) ||
-         (_gdk_quartz_event_loop_check_pending ()));
-}
-
-GdkEvent*
-gdk_event_get_graphics_expose (GdkWindow *window)
-{
-  /* FIXME: Implement */
-  return NULL;
-}
-
-GdkGrabStatus
-gdk_keyboard_grab (GdkWindow  *window,
-                  gint        owner_events,
-                  guint32     time)
-{
-  GdkDisplay *display;
-  GdkWindow  *toplevel;
-
-  g_return_val_if_fail (window != NULL, 0);
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-
-  display = gdk_drawable_get_display (window);
-  toplevel = gdk_window_get_toplevel (window);
-
-  _gdk_display_set_has_keyboard_grab (display,
-                                      window,
-                                      toplevel,
-                                      owner_events,
-                                      0,
-                                      time);
-
-  return GDK_GRAB_SUCCESS;
-}
-
-void
-gdk_display_keyboard_ungrab (GdkDisplay *display,
-                            guint32     time)
-{
-  _gdk_display_unset_has_keyboard_grab (display, FALSE);
-}
-
-void
-gdk_display_pointer_ungrab (GdkDisplay *display,
-                           guint32     time)
+_gdk_quartz_display_has_pending (GdkDisplay *display)
 {
-  GdkPointerGrabInfo *grab;
-
-  grab = _gdk_display_get_last_pointer_grab (display);
-  if (grab)
-    grab->serial_end = 0;
-
-  _gdk_display_pointer_grab_update (display, 0);
-}
-
-GdkGrabStatus
-_gdk_windowing_pointer_grab (GdkWindow    *window,
-                             GdkWindow    *native,
-                             gboolean     owner_events,
-                             GdkEventMask  event_mask,
-                             GdkWindow    *confine_to,
-                             GdkCursor    *cursor,
-                             guint32       time)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-
-  _gdk_display_add_pointer_grab (_gdk_display,
-                                 window,
-                                 native,
-                                 owner_events,
-                                 event_mask,
-                                 0,
-                                 time,
-                                 FALSE);
-
-  return GDK_GRAB_SUCCESS;
+  return (_gdk_event_queue_find_first (display) ||
+         (_gdk_quartz_event_loop_check_pending ()));
 }
 
 static void
 break_all_grabs (guint32 time)
 {
-  GdkPointerGrabInfo *grab;
-
-  if (_gdk_display->keyboard_grab.window)
-    _gdk_display_unset_has_keyboard_grab (_gdk_display, FALSE);
+  GList *list, *l;
+  GdkDeviceManager *device_manager;
 
-  grab = _gdk_display_get_last_pointer_grab (_gdk_display);
-  if (grab)
+  device_manager = gdk_display_get_device_manager (_gdk_display);
+  list = gdk_device_manager_list_devices (device_manager,
+                                          GDK_DEVICE_TYPE_MASTER);
+  for (l = list; l; l = l->next)
     {
-      grab->serial_end = 0;
-      grab->implicit_ungrab = TRUE;
+      GdkDeviceGrabInfo *grab;
+
+      grab = _gdk_display_get_last_device_grab (_gdk_display, l->data);
+      if (grab)
+        {
+          grab->serial_end = 0;
+          grab->implicit_ungrab = TRUE;
+        }
+
+      _gdk_display_device_grab_update (_gdk_display, l->data, NULL, 0);
     }
 
-  _gdk_display_pointer_grab_update (_gdk_display, 0);
+  g_list_free (list);
 }
 
 static void
@@ -189,19 +127,40 @@ append_event (GdkEvent *event,
 static gint
 gdk_event_apply_filters (NSEvent *nsevent,
                         GdkEvent *event,
-                        GList *filters)
+                        GList **filters)
 {
   GList *tmp_list;
   GdkFilterReturn result;
   
-  tmp_list = filters;
+  tmp_list = *filters;
 
   while (tmp_list)
     {
       GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
-      
-      tmp_list = tmp_list->next;
+      GList *node;
+
+      if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0)
+        {
+          tmp_list = tmp_list->next;
+          continue;
+        }
+
+      filter->ref_count++;
       result = filter->function (nsevent, event, filter->data);
+
+      /* get the next node after running the function since the
+         function may add or remove a next node */
+      node = tmp_list;
+      tmp_list = tmp_list->next;
+
+      filter->ref_count--;
+      if (filter->ref_count == 0)
+        {
+          *filters = g_list_remove_link (*filters, node);
+          g_list_free_1 (node);
+          g_free (filter);
+        }
+
       if (result !=  GDK_FILTER_CONTINUE)
        return result;
     }
@@ -237,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)
 {
@@ -252,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)
@@ -346,16 +329,75 @@ 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;
+  GdkQuartzDeviceManagerCore *device_manager;
 
   event = gdk_event_new (GDK_FOCUS_CHANGE);
   event->focus_change.window = window;
   event->focus_change.in = in;
 
+  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_display->device_manager);
+  gdk_event_set_device (event, device_manager->core_keyboard);
+
   return event;
 }
 
@@ -363,33 +405,18 @@ create_focus_event (GdkWindow *window,
 static void
 generate_motion_event (GdkWindow *window)
 {
-  NSPoint point;
   NSPoint screen_point;
-  NSWindow *nswindow;
-  GdkQuartzView *view;
-  GdkWindowObject *private;
   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;
 
-  private = (GdkWindowObject *)window;
-  nswindow = ((GdkWindowImplQuartz *)private->impl)->toplevel;
-  view = (GdkQuartzView *)[nswindow contentView];
-
-  display = gdk_drawable_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 = private->height - point.y;
+  get_window_point_from_screen_point (window, screen_point, &x, &y);
 
   event->any.type = GDK_MOTION_NOTIFY;
   event->motion.window = window;
@@ -399,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;
 
@@ -416,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?
    */
   
@@ -454,10 +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;
-  GdkWindowObject *private;
   GdkEvent *event;
   gint x, y, x_root, y_root;
 
@@ -465,17 +490,10 @@ _gdk_quartz_events_send_enter_notify_event (GdkWindow *window)
   event->any.window = NULL;
   event->any.send_event = FALSE;
 
-  private = (GdkWindowObject *)window;
-  nswindow = ((GdkWindowImplQuartz *)private->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 = private->height - point.y;
+  get_window_point_from_screen_point (window, screen_point, &x, &y);
 
   event->crossing.window = window;
   event->crossing.subwindow = NULL;
@@ -486,7 +504,10 @@ _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);
 
   append_event (event, TRUE);
 }
@@ -494,13 +515,12 @@ _gdk_quartz_events_send_enter_notify_event (GdkWindow *window)
 void
 _gdk_quartz_events_send_map_event (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
+  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
 
   if (!impl->toplevel)
     return;
 
-  if (private->event_mask & GDK_STRUCTURE_MASK)
+  if (window->event_mask & GDK_STRUCTURE_MASK)
     {
       GdkEvent event;
 
@@ -518,24 +538,165 @@ find_toplevel_under_pointer (GdkDisplay *display,
                              gint       *y)
 {
   GdkWindow *toplevel;
+  GdkPointerWindowInfo *info;
+
+  info = _gdk_display_get_pointer_info (display, display->core_pointer);
+  toplevel = info->toplevel_under_pointer;
+  if (toplevel && WINDOW_IS_TOPLEVEL (toplevel))
+    get_window_point_from_screen_point (toplevel, screen_point, x, y);
 
-  toplevel = display->pointer_info.toplevel_under_pointer;
-  if (toplevel)
+  return toplevel;
+}
+
+static GdkWindow *
+find_toplevel_for_keyboard_event (NSEvent *nsevent)
+{
+  GList *list, *l;
+  GdkWindow *window;
+  GdkDisplay *display;
+  GdkQuartzView *view;
+  GdkDeviceManager *device_manager;
+
+  view = (GdkQuartzView *)[[nsevent window] contentView];
+  window = [view gdkWindow];
+
+  display = gdk_window_get_display (window);
+
+  device_manager = gdk_display_get_device_manager (display);
+  list = gdk_device_manager_list_devices (device_manager,
+                                          GDK_DEVICE_TYPE_MASTER);
+  for (l = list; l; l = l->next)
     {
-      GdkWindowObject *private;
-      NSWindow *nswindow;
-      NSPoint point;
+      GdkDeviceGrabInfo *grab;
+      GdkDevice *device = l->data;
 
-      private = (GdkWindowObject *)toplevel;
-      nswindow = ((GdkWindowImplQuartz *)private->impl)->toplevel;
+      if (gdk_device_get_source(device) != GDK_SOURCE_KEYBOARD)
+        continue;
 
-      point = [nswindow convertScreenToBase:screen_point];
+      grab = _gdk_display_get_last_device_grab (display, device);
+      if (grab && grab->window && !grab->owner_events)
+        {
+          window = gdk_window_get_effective_toplevel (grab->window);
+          break;
+        }
+    }
 
-      *x = point.x;
-      *y = private->height - point.y;
+  g_list_free (list);
+
+  return window;
+}
+
+static GdkWindow *
+find_toplevel_for_mouse_event (NSEvent    *nsevent,
+                               gint       *x,
+                               gint       *y)
+{
+  NSPoint screen_point;
+  NSEventType event_type;
+  GdkWindow *toplevel;
+  GdkDisplay *display;
+  GdkDeviceGrabInfo *grab;
+
+  toplevel = get_toplevel_from_ns_event (nsevent, &screen_point, x, y);
+
+  display = gdk_window_get_display (toplevel);
+
+  event_type = [nsevent type];
+
+  /* From the docs for XGrabPointer:
+   *
+   * If owner_events is True and if a generated pointer event
+   * would normally be reported to this client, it is reported
+   * as usual. Otherwise, the event is reported with respect to
+   * the grab_window and is reported only if selected by
+   * event_mask. For either value of owner_events, unreported
+   * events are discarded.
+   */
+  grab = _gdk_display_get_last_device_grab (display,
+                                            display->core_pointer);
+  if (WINDOW_IS_TOPLEVEL (toplevel) && grab)
+    {
+      /* Implicit grabs do not go through XGrabPointer and thus the
+       * event mask should not be checked.
+       */
+      if (!grab->implicit
+          && (grab->event_mask & get_event_mask_from_ns_event (nsevent)) == 0)
+        return NULL;
+
+      if (grab->owner_events)
+        {
+          /* For owner events, we need to use the toplevel under the
+           * pointer, not the window from the NSEvent, since that is
+           * reported with respect to the key window, which could be
+           * wrong.
+           */
+          GdkWindow *toplevel_under_pointer;
+          gint x_tmp, y_tmp;
+
+          toplevel_under_pointer = find_toplevel_under_pointer (display,
+                                                                screen_point,
+                                                                &x_tmp, &y_tmp);
+          if (toplevel_under_pointer)
+            {
+              toplevel = toplevel_under_pointer;
+              *x = x_tmp;
+              *y = y_tmp;
+            }
+
+          return toplevel;
+        }
+      else
+        {
+          /* Finally check the grab window. */
+          GdkWindow *grab_toplevel;
+
+          grab_toplevel = gdk_window_get_effective_toplevel (grab->window);
+          get_window_point_from_screen_point (grab_toplevel, screen_point,
+                                              x, y);
+
+          return grab_toplevel;
+        }
+
+      return NULL;
     }
+  else 
+    {
+      /* The non-grabbed case. */
+      GdkWindow *toplevel_under_pointer;
+      gint x_tmp, y_tmp;
+
+      /* Ignore all events but mouse moved that might be on the title
+       * bar (above the content view). The reason is that otherwise
+       * gdk gets confused about getting e.g. button presses with no
+       * window (the title bar is not known to it).
+       */
+      if (event_type != NSMouseMoved)
+        if (*y < 0)
+          return NULL;
 
-  return toplevel;
+      /* As for owner events, we need to use the toplevel under the
+       * pointer, not the window from the NSEvent.
+       */
+      toplevel_under_pointer = find_toplevel_under_pointer (display,
+                                                            screen_point,
+                                                            &x_tmp, &y_tmp);
+      if (toplevel_under_pointer
+          && WINDOW_IS_TOPLEVEL (toplevel_under_pointer))
+        {
+          GdkWindowImplQuartz *toplevel_impl;
+
+          toplevel = toplevel_under_pointer;
+
+          toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
+
+          *x = x_tmp;
+          *y = y_tmp;
+        }
+
+      return toplevel;
+    }
+
+  return NULL;
 }
 
 /* This function finds the correct window to send an event to, taking
@@ -550,22 +711,12 @@ find_window_for_ns_event (NSEvent *nsevent,
 {
   GdkQuartzView *view;
   GdkWindow *toplevel;
-  GdkWindowObject *private;
-  NSPoint point;
   NSPoint screen_point;
   NSEventType event_type;
 
   view = (GdkQuartzView *)[[nsevent window] contentView];
 
-  toplevel = [view gdkWindow];
-  private = GDK_WINDOW_OBJECT (toplevel);
-
-  point = [nsevent locationInWindow];
-  screen_point = [[nsevent window] convertBaseToScreen:point];
-
-  *x = point.x;
-  *y = private->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];
@@ -583,138 +734,7 @@ find_window_for_ns_event (NSEvent *nsevent,
     case NSLeftMouseDragged:
     case NSRightMouseDragged:
     case NSOtherMouseDragged:
-      {
-       GdkDisplay *display;
-        GdkPointerGrabInfo *grab;
-
-        display = gdk_drawable_get_display (toplevel);
-
-       /* From the docs for XGrabPointer:
-        *
-        * If owner_events is True and if a generated pointer event
-        * would normally be reported to this client, it is reported
-        * as usual. Otherwise, the event is reported with respect to
-        * the grab_window and is reported only if selected by
-        * event_mask. For either value of owner_events, unreported
-        * events are discarded.
-        */
-        grab = _gdk_display_get_last_pointer_grab (display);
-       if (grab)
-         {
-            /* Implicit grabs do not go through XGrabPointer and thus the
-             * event mask should not be checked.
-             */
-           if (!grab->implicit
-                && (grab->event_mask & get_event_mask_from_ns_event (nsevent)) == 0)
-              return NULL;
-
-            if (grab->owner_events)
-              {
-                /* For owner events, we need to use the toplevel under the
-                 * pointer, not the window from the NSEvent, since that is
-                 * reported with respect to the key window, which could be
-                 * wrong.
-                 */
-                GdkWindow *toplevel_under_pointer;
-                gint x_tmp, y_tmp;
-
-                toplevel_under_pointer = find_toplevel_under_pointer (display,
-                                                                      screen_point,
-                                                                      &x_tmp, &y_tmp);
-                if (toplevel_under_pointer)
-                  {
-                    toplevel = toplevel_under_pointer;
-                    *x = x_tmp;
-                    *y = y_tmp;
-                  }
-
-                return toplevel;
-              }
-            else
-              {
-                /* Finally check the grab window. */
-               GdkWindow *grab_toplevel;
-                GdkWindowObject *grab_private;
-                NSWindow *grab_nswindow;
-
-               grab_toplevel = gdk_window_get_toplevel (grab->window);
-                grab_private = (GdkWindowObject *)grab_toplevel;
-
-                grab_nswindow = ((GdkWindowImplQuartz *)grab_private->impl)->toplevel;
-                point = [grab_nswindow convertScreenToBase:screen_point];
-
-                /* Note: x_root and y_root are already right. */
-                *x = point.x;
-                *y = grab_private->height - point.y;
-
-               return grab_toplevel;
-             }
-
-           return NULL;
-         }
-       else 
-         {
-           /* The non-grabbed case. */
-            GdkWindow *toplevel_under_pointer;
-            gint x_tmp, y_tmp;
-
-            /* Ignore all events but mouse moved that might be on the title
-             * bar (above the content view). The reason is that otherwise
-             * gdk gets confused about getting e.g. button presses with no
-             * window (the title bar is not known to it).
-             */
-            if (event_type != NSMouseMoved)
-              if (*y < 0)
-                return NULL;
-
-            /* As for owner events, we need to use the toplevel under the
-             * pointer, not the window from the NSEvent.
-             */
-            toplevel_under_pointer = find_toplevel_under_pointer (display,
-                                                                  screen_point,
-                                                                  &x_tmp, &y_tmp);
-            if (toplevel_under_pointer)
-              {
-                GdkWindowObject *toplevel_private;
-                GdkWindowImplQuartz *toplevel_impl;
-
-                toplevel = toplevel_under_pointer;
-
-                toplevel_private = (GdkWindowObject *)toplevel;
-                toplevel_impl = (GdkWindowImplQuartz *)toplevel_private->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;
-              }
-
-            return toplevel;
-         }
-      }
-      break;
+      return find_toplevel_for_mouse_event (nsevent, x, y);
       
     case NSMouseEntered:
     case NSMouseExited:
@@ -729,10 +749,7 @@ find_window_for_ns_event (NSEvent *nsevent,
     case NSKeyDown:
     case NSKeyUp:
     case NSFlagsChanged:
-      if (_gdk_display->keyboard_grab.window && !_gdk_display->keyboard_grab.owner_events)
-        return gdk_window_get_toplevel (_gdk_display->keyboard_grab.window);
-
-      return toplevel;
+      return find_toplevel_for_keyboard_event (nsevent);
 
     default:
       /* Ignore everything else. */
@@ -764,7 +781,10 @@ 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);
 
   /* FIXME: Focus and button state? */
 }
@@ -780,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])
     {
@@ -790,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;
@@ -812,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;
 }
 
@@ -825,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);
@@ -849,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;
 }
@@ -864,11 +870,8 @@ fill_scroll_event (GdkWindow          *window,
                    gint                y_root,
                    GdkScrollDirection  direction)
 {
-  GdkWindowObject *private;
   NSPoint point;
 
-  private = GDK_WINDOW_OBJECT (window);
-
   point = [nsevent locationInWindow];
 
   event->any.type = GDK_SCROLL;
@@ -890,6 +893,7 @@ fill_key_event (GdkWindow    *window,
                 GdkEventType  type)
 {
   GdkEventPrivate *priv;
+  GdkQuartzDeviceManagerCore *device_manager;
   gchar buf[7];
   gunichar c = 0;
 
@@ -902,9 +906,12 @@ fill_key_event (GdkWindow    *window,
   event->key.state = get_keyboard_modifiers_from_ns_event (nsevent);
   event->key.hardware_keycode = [nsevent keyCode];
   event->key.group = ([nsevent modifierFlags] & NSAlternateKeyMask) ? 1 : 0;
-  event->key.keyval = GDK_VoidSymbol;
+  event->key.keyval = GDK_KEY_VoidSymbol;
+
+  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,
@@ -923,23 +930,23 @@ fill_key_event (GdkWindow    *window,
 
       switch (event->key.keyval)
         {
-        case GDK_Meta_R:
-        case GDK_Meta_L:
-          mask = GDK_MOD1_MASK;
+        case GDK_KEY_Meta_R:
+        case GDK_KEY_Meta_L:
+          mask = GDK_MOD2_MASK;
           break;
-        case GDK_Shift_R:
-        case GDK_Shift_L:
+        case GDK_KEY_Shift_R:
+        case GDK_KEY_Shift_L:
           mask = GDK_SHIFT_MASK;
           break;
-        case GDK_Caps_Lock:
+        case GDK_KEY_Caps_Lock:
           mask = GDK_LOCK_MASK;
           break;
-        case GDK_Alt_R:
-        case GDK_Alt_L:
-          mask = GDK_MOD5_MASK;
+        case GDK_KEY_Alt_R:
+        case GDK_KEY_Alt_L:
+          mask = GDK_MOD1_MASK;
           break;
-        case GDK_Control_R:
-        case GDK_Control_L:
+        case GDK_KEY_Control_R:
+        case GDK_KEY_Control_L:
           mask = GDK_CONTROL_MASK;
           break;
         default:
@@ -952,12 +959,19 @@ 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;
 
   /* Fill in ->string since apps depend on it, taken from the x11 backend. */
-  if (event->key.keyval != GDK_VoidSymbol)
+  if (event->key.keyval != GDK_KEY_VoidSymbol)
     c = gdk_keyval_to_unicode (event->key.keyval);
 
   if (c)
@@ -974,13 +988,13 @@ fill_key_event (GdkWindow    *window,
       if (event->key.string)
        event->key.length = bytes_written;
     }
-  else if (event->key.keyval == GDK_Escape)
+  else if (event->key.keyval == GDK_KEY_Escape)
     {
       event->key.length = 1;
       event->key.string = g_strdup ("\033");
     }
-  else if (event->key.keyval == GDK_Return ||
-         event->key.keyval == GDK_KP_Enter)
+  else if (event->key.keyval == GDK_KEY_Return ||
+         event->key.keyval == GDK_KEY_KP_Enter)
     {
       event->key.length = 1;
       event->key.string = g_strdup ("\r");
@@ -1009,17 +1023,13 @@ synthesize_crossing_event (GdkWindow *window,
                            gint       x_root,
                            gint       y_root)
 {
-  GdkWindowObject *private;
-
-  private = GDK_WINDOW_OBJECT (window);
-
   switch ([nsevent type])
     {
     case NSMouseEntered:
       /* Enter events are considered always to be from the root window as we
        * can't know for sure from what window we enter.
        */
-      if (!(private->event_mask & GDK_ENTER_NOTIFY_MASK))
+      if (!(window->event_mask & GDK_ENTER_NOTIFY_MASK))
         return FALSE;
 
       fill_crossing_event (window, event, nsevent,
@@ -1035,7 +1045,7 @@ synthesize_crossing_event (GdkWindow *window,
        * since there is no way to reliably get information about what new
        * window is entered when exiting one.
        */
-      if (!(private->event_mask & GDK_LEAVE_NOTIFY_MASK))
+      if (!(window->event_mask & GDK_LEAVE_NOTIFY_MASK))
         return FALSE;
 
       fill_crossing_event (window, event, nsevent,
@@ -1053,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
@@ -1088,31 +1185,12 @@ 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 */
       GdkFilterReturn result;
 
-      result = gdk_event_apply_filters (nsevent, event, _gdk_default_filters);
+      result = gdk_event_apply_filters (nsevent, event, &_gdk_default_filters);
       if (result != GDK_FILTER_CONTINUE)
         {
           return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
@@ -1122,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;
@@ -1143,17 +1244,20 @@ 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))
     {
-      GdkWindowObject *filter_private = (GdkWindowObject *) window;
       GdkFilterReturn result;
 
-      if (filter_private->filters)
+      if (window->filters)
        {
          g_object_ref (window);
 
-         result = gdk_event_apply_filters (nsevent, event, filter_private->filters);
+         result = gdk_event_apply_filters (nsevent, event, &window->filters);
 
          g_object_unref (window);
 
@@ -1174,8 +1278,7 @@ gdk_event_translate (GdkEvent *event,
        event_type == NSOtherMouseDown ||
        event_type == NSLeftMouseDown))
     {
-      GdkWindowObject *private = (GdkWindowObject *)window;
-      GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
+      GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
 
       if (![NSApp isActive])
         {
@@ -1184,16 +1287,15 @@ gdk_event_translate (GdkEvent *event,
         }
       else if (![impl->toplevel isKeyWindow])
         {
-          GdkPointerGrabInfo *grab;
+          GdkDeviceGrabInfo *grab;
 
-          grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+          grab = _gdk_display_get_last_device_grab (_gdk_display,
+                                                    _gdk_display->core_pointer);
           if (!grab)
             [impl->toplevel makeKeyWindow];
         }
     }
 
-  current_event_mask = get_event_mask_from_ns_event (nsevent);
-
   return_val = TRUE;
 
   switch (event_type)
@@ -1288,7 +1390,7 @@ gdk_event_translate (GdkEvent *event,
 }
 
 void
-_gdk_events_queue (GdkDisplay *display)
+_gdk_quartz_display_queue_events (GdkDisplay *display)
 {  
   NSEvent *nsevent;
 
@@ -1328,60 +1430,16 @@ _gdk_events_queue (GdkDisplay *display)
 }
 
 void
-gdk_flush (void)
-{
-  /* Not supported. */
-}
-
-void
-gdk_display_add_client_message_filter (GdkDisplay   *display,
-                                      GdkAtom       message_type,
-                                      GdkFilterFunc func,
-                                      gpointer      data)
-{
-  /* Not supported. */
-}
-
-void
-gdk_add_client_message_filter (GdkAtom       message_type,
-                              GdkFilterFunc func,
-                              gpointer      data)
-{
-  /* Not supported. */
-}
-
-void
-gdk_display_sync (GdkDisplay *display)
-{
-  /* Not supported. */
-}
-
-void
-gdk_display_flush (GdkDisplay *display)
-{
-  /* Not supported. */
-}
-
-gboolean
-gdk_event_send_client_message_for_display (GdkDisplay      *display,
-                                          GdkEvent        *event,
-                                          GdkNativeWindow  winid)
-{
-  /* Not supported. */
-  return FALSE;
-}
-
-void
-gdk_screen_broadcast_client_message (GdkScreen *screen,
-                                    GdkEvent  *event)
+_gdk_quartz_screen_broadcast_client_message (GdkScreen *screen,
+                                             GdkEvent  *event)
 {
   /* Not supported. */
 }
 
 gboolean
-gdk_screen_get_setting (GdkScreen   *screen,
-                       const gchar *name,
-                       GValue      *value)
+_gdk_quartz_screen_get_setting (GdkScreen   *screen,
+                                const gchar *name,
+                                GValue      *value)
 {
   if (strcmp (name, "gtk-double-click-time") == 0)
     {
@@ -1438,8 +1496,9 @@ gdk_screen_get_setting (GdkScreen   *screen,
 }
 
 void
-_gdk_windowing_event_data_copy (const GdkEvent *src,
-                                GdkEvent       *dst)
+_gdk_quartz_display_event_data_copy (GdkDisplay     *display,
+                                     const GdkEvent *src,
+                                     GdkEvent       *dst)
 {
   GdkEventPrivate *priv_src = (GdkEventPrivate *) src;
   GdkEventPrivate *priv_dst = (GdkEventPrivate *) dst;
@@ -1452,7 +1511,8 @@ _gdk_windowing_event_data_copy (const GdkEvent *src,
 }
 
 void
-_gdk_windowing_event_data_free (GdkEvent *event)
+_gdk_quartz_display_event_data_free (GdkDisplay *display,
+                                     GdkEvent   *event)
 {
   GdkEventPrivate *priv = (GdkEventPrivate *) event;