[gtk/wip/chergert/quartz4u] start bringing over event translations



commit e6057fcd62c13e8de30f3f144715e94ad8c5f352
Author: Christian Hergert <chergert redhat com>
Date:   Fri May 1 21:18:22 2020 -0700

    start bringing over event translations

 gdk/macos/GdkMacosCairoView.c         |  61 ++++
 gdk/macos/GdkMacosCairoView.h         |   4 +
 gdk/macos/gdkmacoscairocontext.c      |   7 +
 gdk/macos/gdkmacoscursor-private.h    |  32 ++
 gdk/macos/gdkmacoscursor.c            | 134 ++++++++
 gdk/macos/gdkmacosdevice.c            |  25 ++
 gdk/macos/gdkmacosdisplay-private.h   |  37 ++-
 gdk/macos/gdkmacosdisplay-translate.c | 586 ++++++++++++++++++++++++++++++++++
 gdk/macos/gdkmacosdisplay.c           |  88 ++---
 gdk/macos/gdkmacoskeymap-private.h    |   5 +-
 gdk/macos/gdkmacoskeymap.c            |  76 ++++-
 gdk/macos/gdkmacossurface-private.h   |   4 +
 gdk/macos/gdkmacossurface.c           |  57 +++-
 gdk/macos/meson.build                 |   2 +
 14 files changed, 1035 insertions(+), 83 deletions(-)
---
diff --git a/gdk/macos/GdkMacosCairoView.c b/gdk/macos/GdkMacosCairoView.c
index 0d9f7a4bed..512f59b646 100644
--- a/gdk/macos/GdkMacosCairoView.c
+++ b/gdk/macos/GdkMacosCairoView.c
@@ -21,6 +21,9 @@
 
 #include "config.h"
 
+#include <CoreGraphics/CoreGraphics.h>
+#include <cairo-quartz.h>
+
 #import "GdkMacosCairoView.h"
 
 #include "gdkinternals.h"
@@ -43,4 +46,62 @@
   return YES;
 }
 
+-(void)setCairoSurfaceWithRegion:(cairo_surface_t *)cairoSurface
+                     cairoRegion:(cairo_region_t *)cairoRegion
+{
+  guint n_rects;
+
+  g_clear_pointer (&self->surface, cairo_surface_destroy);
+  g_clear_pointer (&self->region, cairo_region_destroy);
+
+  self->surface = cairoSurface;
+  self->region = cairoRegion;
+
+  n_rects = cairo_region_num_rectangles (cairoRegion);
+  for (guint i = 0; i < n_rects; i++)
+    {
+      cairo_rectangle_int_t rect;
+
+      cairo_region_get_rectangle (cairoRegion, i, &rect);
+      [self setNeedsDisplayInRect:NSMakeRect (rect.x, rect.y, rect.width, rect.height)];
+    }
+}
+
+-(void)drawRect:(NSRect)rect
+{
+  cairo_surface_t *dest;
+  cairo_t *cr;
+  guint n_rects;
+
+  if (self->surface == NULL || self->region == NULL)
+    return;
+
+  dest = cairo_quartz_surface_create_for_cg_context (NSGraphicsContext.currentContext.CGContext,
+                                                     self.bounds.size.width,
+                                                     self.bounds.size.height);
+  cr = cairo_create (dest);
+
+  n_rects = cairo_region_num_rectangles (self->region);
+  for (guint i = 0; i < n_rects; i++)
+    {
+      cairo_rectangle_int_t r;
+
+      cairo_region_get_rectangle (self->region, i, &r);
+      cairo_rectangle (cr, r.x, r.y, r.width, r.height);
+    }
+
+  cairo_set_source_surface (cr, self->surface, 0, 0);
+  cairo_rectangle (cr, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+  cairo_paint (cr);
+
+  cairo_rectangle (cr, 0, 0, self.bounds.size.width, self.bounds.size.height);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_fill (cr);
+
+  cairo_destroy (cr);
+
+  cairo_surface_flush (dest);
+  cairo_surface_destroy (dest);
+}
+
 @end
diff --git a/gdk/macos/GdkMacosCairoView.h b/gdk/macos/GdkMacosCairoView.h
index a7b39bccfe..c65de74eb0 100644
--- a/gdk/macos/GdkMacosCairoView.h
+++ b/gdk/macos/GdkMacosCairoView.h
@@ -26,6 +26,10 @@
 @interface GdkMacosCairoView : GdkMacosBaseView
 {
   cairo_surface_t *surface;
+  cairo_region_t  *region;
 }
 
+-(void)setCairoSurfaceWithRegion:(cairo_surface_t *)cairoSurface
+                     cairoRegion:(cairo_region_t *)region;
+
 @end
diff --git a/gdk/macos/gdkmacoscairocontext.c b/gdk/macos/gdkmacoscairocontext.c
index db5dfda164..a3ef32fc84 100644
--- a/gdk/macos/gdkmacoscairocontext.c
+++ b/gdk/macos/gdkmacoscairocontext.c
@@ -108,6 +108,7 @@ _gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
                                     cairo_region_t *painted)
 {
   GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
+  GdkSurface *surface;
   cairo_t *cr;
 
   g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
@@ -125,6 +126,12 @@ _gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
 
   cairo_surface_flush (self->window_surface);
 
+  surface = gdk_draw_context_get_surface (draw_context);
+  if (GDK_IS_MACOS_SURFACE (surface))
+    _gdk_macos_surface_damage_cairo (GDK_MACOS_SURFACE (surface),
+                                     g_steal_pointer (&self->window_surface),
+                                     painted);
+
   g_clear_pointer (&self->paint_surface, cairo_surface_destroy);
   g_clear_pointer (&self->window_surface, cairo_surface_destroy);
 }
diff --git a/gdk/macos/gdkmacoscursor-private.h b/gdk/macos/gdkmacoscursor-private.h
new file mode 100644
index 0000000000..b3e5bac70d
--- /dev/null
+++ b/gdk/macos/gdkmacoscursor-private.h
@@ -0,0 +1,32 @@
+/* gdkmacoscursor-private.h
+ *
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_MACOS_CURSOR_PRIVATE_H__
+#define __GDK_MACOS_CURSOR_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+NSCursor *_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_CURSOR_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacoscursor.c b/gdk/macos/gdkmacoscursor.c
new file mode 100644
index 0000000000..399339f8c0
--- /dev/null
+++ b/gdk/macos/gdkmacoscursor.c
@@ -0,0 +1,134 @@
+/* gdkcursor-macos.c
+ *
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gdkmacoscursor-private.h"
+
+/* OS X only exports a number of cursor types in its public NSCursor interface.
+ * By overriding the private _coreCursorType method, we can tell OS X to load
+ * one of its internal cursors instead (since cursor images are loaded on demand
+ * instead of in advance). WebKit does this too.
+ */
+
+@interface gdkCoreCursor : NSCursor {
+@private
+        int type;
+        BOOL override;
+}
+@end
+
+@implementation gdkCoreCursor
+
+- (int)_coreCursorType
+{
+        if (self->override)
+                return self->type;
+        return [super _coreCursorType];
+}
+
+#define CUSTOM_CURSOR_CTOR(name, id) \
+        + (gdkCoreCursor *)name \
+        { \
+                gdkCoreCursor *obj; \
+                obj = [self new]; \
+                if (obj) { \
+                        obj->override = YES; \
+                        obj->type = id; \
+                } \
+                return obj; \
+        }
+CUSTOM_CURSOR_CTOR(gdkHelpCursor, 40)
+CUSTOM_CURSOR_CTOR(gdkProgressCursor, 4)
+/* TODO OS X doesn't seem to have a way to get this. There is an undocumented
+ * method +[NSCursor _waitCursor], but it doesn't actually return this cursor,
+ * but rather some odd low-quality non-animating version of this cursor. Use
+ * the progress cursor instead for now.
+ */
+CUSTOM_CURSOR_CTOR(gdkWaitCursor, 4)
+CUSTOM_CURSOR_CTOR(gdkAliasCursor, 2)
+CUSTOM_CURSOR_CTOR(gdkMoveCursor, 39)
+/* TODO OS X doesn't seem to provide one; copy the move cursor for now
+ *  since it looks similar to what we want. */
+CUSTOM_CURSOR_CTOR(gdkAllScrollCursor, 39)
+CUSTOM_CURSOR_CTOR(gdkNEResizeCursor, 29)
+CUSTOM_CURSOR_CTOR(gdkNWResizeCursor, 33)
+CUSTOM_CURSOR_CTOR(gdkSEResizeCursor, 35)
+CUSTOM_CURSOR_CTOR(gdkSWResizeCursor, 37)
+CUSTOM_CURSOR_CTOR(gdkEWResizeCursor, 28)
+CUSTOM_CURSOR_CTOR(gdkNSResizeCursor, 32)
+CUSTOM_CURSOR_CTOR(gdkNESWResizeCursor, 30)
+CUSTOM_CURSOR_CTOR(gdkNWSEResizeCursor, 34)
+CUSTOM_CURSOR_CTOR(gdkZoomInCursor, 42)
+CUSTOM_CURSOR_CTOR(gdkZoomOutCursor, 43)
+
+@end
+
+struct CursorsByName {
+  const gchar *name;
+  NSString *selector;
+};
+
+static const struct CursorsByName cursors_by_name[] = {
+  /* Link & Status */
+  { "context-menu", @"contextualMenuCursor" },
+  { "help", @"gdkHelpCursor" },
+  { "pointer", @"pointingHandCursor" },
+  { "progress", @"gdkProgressCursor" },
+  { "wait", @"gdkWaitCursor" },
+  /* Selection */
+  { "cell", @"crosshairCursor" },
+  { "crosshair", @"crosshairCursor" },
+  { "text", @"IBeamCursor" },
+  { "vertical-text", @"IBeamCursorForVerticalLayout" },
+  /* Drag & Drop */
+  { "alias", @"gdkAliasCursor" },
+  { "copy", @"dragCopyCursor" },
+  { "move", @"gdkMoveCursor" },
+  { "no-drop", @"operationNotAllowedCursor" },
+  { "not-allowed", @"operationNotAllowedCursor" },
+  { "grab", @"openHandCursor" },
+  { "grabbing", @"closedHandCursor" },
+  /* Resize & Scrolling */
+  { "all-scroll", @"gdkAllScrollCursor" },
+  { "col-resize", @"resizeLeftRightCursor" },
+  { "row-resize", @"resizeUpDownCursor" },
+  { "n-resize", @"resizeUpCursor" },
+  { "e-resize", @"resizeRightCursor" },
+  { "s-resize", @"resizeDownCursor" },
+  { "w-resize", @"resizeLeftCursor" },
+  { "ne-resize", @"gdkNEResizeCursor" },
+  { "nw-resize", @"gdkNWResizeCursor" },
+  { "se-resize", @"gdkSEResizeCursor" },
+  { "sw-resize", @"gdkSWResizeCursor" },
+  { "ew-resize", @"gdkEWResizeCursor" },
+  { "ns-resize", @"gdkNSResizeCursor" },
+  { "nesw-resize", @"gdkNESWResizeCursor" },
+  { "nwse-resize", @"gdkNWSEResizeCursor" },
+  /* Zoom */
+  { "zoom-in", @"gdkZoomInCursor" },
+  { "zoom-out", @"gdkZoomOutCursor" },
+  { NULL, NULL },
+};
+
+NSCursor *
+_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
+{
+  return NULL;
+}
diff --git a/gdk/macos/gdkmacosdevice.c b/gdk/macos/gdkmacosdevice.c
index 7a0b2490dc..0f8e47c552 100644
--- a/gdk/macos/gdkmacosdevice.c
+++ b/gdk/macos/gdkmacosdevice.c
@@ -23,7 +23,9 @@
 
 #include "gdkdeviceprivate.h"
 
+#include "gdkmacoscursor-private.h"
 #include "gdkmacosdevice.h"
+#include "gdkmacossurface.h"
 
 struct _GdkMacosDevice
 {
@@ -37,6 +39,26 @@ struct _GdkMacosDeviceClass
 
 G_DEFINE_TYPE (GdkMacosDevice, gdk_macos_device, GDK_TYPE_DEVICE)
 
+static void
+gdk_macos_device_set_surface_cursor (GdkDevice  *device,
+                                     GdkSurface *surface,
+                                     GdkCursor  *cursor)
+{
+  NSCursor *nscursor;
+
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (!cursor || GDK_IS_CURSOR (cursor));
+
+  nscursor = _gdk_macos_cursor_get_ns_cursor (cursor);
+
+  if (nscursor != NULL)
+    {
+      [nscursor set];
+      [nscursor release];
+    }
+}
+
 static void
 gdk_macos_device_finalize (GObject *object)
 {
@@ -47,8 +69,11 @@ static void
 gdk_macos_device_class_init (GdkMacosDeviceClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
 
   object_class->finalize = gdk_macos_device_finalize;
+
+  device_class->set_surface_cursor = gdk_macos_device_set_surface_cursor;
 }
 
 static void
diff --git a/gdk/macos/gdkmacosdisplay-private.h b/gdk/macos/gdkmacosdisplay-private.h
index 7d9fd6a55b..5f32411a82 100644
--- a/gdk/macos/gdkmacosdisplay-private.h
+++ b/gdk/macos/gdkmacosdisplay-private.h
@@ -26,22 +26,27 @@
 
 G_BEGIN_DECLS
 
-GdkDisplay *_gdk_macos_display_open                         (const gchar     *display_name);
-int         _gdk_macos_display_get_fd                       (GdkMacosDisplay *self);
-void        _gdk_macos_display_queue_events                 (GdkMacosDisplay *self);
-void        _gdk_macos_display_to_display_coords            (GdkMacosDisplay *self,
-                                                             int              x,
-                                                             int              y,
-                                                             int             *out_x,
-                                                             int             *out_y);
-void        _gdk_macos_display_from_display_coords          (GdkMacosDisplay *self,
-                                                             int              x,
-                                                             int              y,
-                                                             int             *out_x,
-                                                             int             *out_y);
-NSScreen   *_gdk_macos_display_get_screen_at_display_coords (GdkMacosDisplay *self,
-                                                             int              x,
-                                                             int              y);
+GdkDisplay      *_gdk_macos_display_open                         (const gchar     *display_name);
+int              _gdk_macos_display_get_fd                       (GdkMacosDisplay *self);
+void             _gdk_macos_display_queue_events                 (GdkMacosDisplay *self);
+void             _gdk_macos_display_to_display_coords            (GdkMacosDisplay *self,
+                                                                  int              x,
+                                                                  int              y,
+                                                                  int             *out_x,
+                                                                  int             *out_y);
+void             _gdk_macos_display_from_display_coords          (GdkMacosDisplay *self,
+                                                                  int              x,
+                                                                  int              y,
+                                                                  int             *out_x,
+                                                                  int             *out_y);
+NSScreen        *_gdk_macos_display_get_screen_at_display_coords (GdkMacosDisplay *self,
+                                                                  int              x,
+                                                                  int              y);
+GdkEvent        *_gdk_macos_display_translate                    (GdkMacosDisplay *self,
+                                                                  NSEvent         *event);
+void             _gdk_macos_display_break_all_grabs              (GdkMacosDisplay *self,
+                                                                  guint32          time);
+GdkModifierType  _gdk_macos_display_get_current_mouse_modifiers  (GdkMacosDisplay *self);
 
 G_END_DECLS
 
diff --git a/gdk/macos/gdkmacosdisplay-translate.c b/gdk/macos/gdkmacosdisplay-translate.c
new file mode 100644
index 0000000000..fd4a554d72
--- /dev/null
+++ b/gdk/macos/gdkmacosdisplay-translate.c
@@ -0,0 +1,586 @@
+/*
+ * Copyright © 2005 Imendio AB
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#import "GdkMacosWindow.h"
+#import "GdkMacosBaseView.h"
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacoskeymap-private.h"
+#include "gdkmacossurface-private.h"
+
+#define GRIP_WIDTH 15
+#define GRIP_HEIGHT 15
+#define GDK_LION_RESIZE 5
+
+static gboolean
+test_resize (NSEvent         *event,
+             GdkMacosSurface *surface,
+             gint             x,
+             gint             y)
+{
+  NSWindow *window;
+
+  g_assert (event != NULL);
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  window = _gdk_macos_surface_get_native (surface);
+
+  /* Resizing from the resize indicator only begins if an NSLeftMouseButton
+   * event is received in the resizing area.
+   */
+  if ([event type] == NSLeftMouseDown &&
+      [window 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 = [[window contentView] 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.
+   *
+   * We perform this check for a button press of all buttons, because we
+   * do receive, for instance, a right mouse down event for a GDK surface
+   * for x-coordinate range [-3, 0], but we do not want to forward this
+   * into GDK. Forwarding such events into GDK will confuse the pointer
+   * window finding code, because there are no GdkSurfaces present in
+   * the range [-3, 0].
+   */
+  if (([event type] == NSLeftMouseDown ||
+       [event type] == NSRightMouseDown ||
+       [event type] == NSOtherMouseDown))
+    {
+      if (x < GDK_LION_RESIZE ||
+          x > GDK_SURFACE (surface)->width - GDK_LION_RESIZE ||
+          y > GDK_SURFACE (surface)->height - GDK_LION_RESIZE)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static guint32
+get_time_from_ns_event (NSEvent *event)
+{
+  double time = [event timestamp];
+  /* cast via double->uint64 conversion to make sure that it is
+   * wrapped on 32-bit machines when it overflows
+   */
+  return (guint32) (guint64) (time * 1000.0);
+}
+
+static int
+get_mouse_button_from_ns_event (NSEvent *event)
+{
+  NSInteger button = [event buttonNumber];
+
+  switch (button)
+    {
+    case 0:
+      return 1;
+    case 1:
+      return 3;
+    case 2:
+      return 2;
+    default:
+      return button + 1;
+    }
+}
+
+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)
+{
+  GdkModifierType state = 0;
+  int button;
+
+  /* This maps buttons 1 to 5 to GDK_BUTTON[1-5]_MASK */
+  button = get_mouse_button_from_ns_event (event);
+  if (button >= 1 && button <= 5)
+    state = (1 << (button + 7));
+
+  return state;
+}
+
+static GdkModifierType
+get_keyboard_modifiers_from_ns_flags (NSUInteger nsflags)
+{
+  GdkModifierType modifiers = 0;
+
+  if (nsflags & NSAlphaShiftKeyMask)
+    modifiers |= GDK_LOCK_MASK;
+  if (nsflags & NSShiftKeyMask)
+    modifiers |= GDK_SHIFT_MASK;
+  if (nsflags & NSControlKeyMask)
+    modifiers |= GDK_CONTROL_MASK;
+  if (nsflags & NSAlternateKeyMask)
+    modifiers |= GDK_ALT_MASK;
+  if (nsflags & NSCommandKeyMask)
+    modifiers |= GDK_SUPER_MASK;
+
+  return modifiers;
+}
+
+static GdkModifierType
+get_keyboard_modifiers_from_ns_event (NSEvent *nsevent)
+{
+  return get_keyboard_modifiers_from_ns_flags ([nsevent modifierFlags]);
+}
+
+GdkModifierType
+_gdk_macos_display_get_current_mouse_modifiers (GdkMacosDisplay *self)
+{
+  return get_mouse_button_modifiers_from_ns_buttons ([NSEvent pressedMouseButtons]);
+}
+
+
+static GdkEvent *
+fill_button_event (GdkMacosDisplay *display,
+                   GdkMacosSurface *surface,
+                   NSEvent         *nsevent,
+                   gint             x,
+                   gint             y)
+{
+  GdkSeat *seat;
+  GdkEventType type;
+  GdkModifierType state;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+  state = get_keyboard_modifiers_from_ns_event (nsevent) |
+         _gdk_macos_display_get_current_mouse_modifiers (display);
+
+  switch ([nsevent type])
+    {
+    case NSLeftMouseDown:
+    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 ();
+    }
+
+  return gdk_button_event_new (type,
+                               GDK_SURFACE (surface),
+                               gdk_seat_get_pointer (seat),
+                               NULL,
+                               NULL,
+                               get_time_from_ns_event (nsevent),
+                               state,
+                               get_mouse_button_from_ns_event (nsevent),
+                               x,
+                               y,
+                               NULL);
+}
+
+static GdkEvent *
+synthesize_crossing_event (GdkMacosDisplay *display,
+                           GdkMacosSurface *surface,
+                           NSEvent         *nsevent,
+                           gint             x,
+                           gint             y)
+{
+  GdkEventType event_type;
+  GdkModifierType state;
+  GdkSeat *seat;
+
+  switch ([nsevent type])
+    {
+    case NSMouseEntered:
+      event_type = GDK_ENTER_NOTIFY;
+      break;
+
+    case NSMouseExited:
+      event_type = GDK_LEAVE_NOTIFY;
+      break;
+
+    default:
+      return NULL;
+    }
+
+  state = get_keyboard_modifiers_from_ns_event (nsevent) |
+         _gdk_macos_display_get_current_mouse_modifiers (display);
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+
+  return gdk_crossing_event_new (event_type,
+                                 surface,
+                                 gdk_seat_get_pointer (seat),
+                                 NULL,
+                                 get_time_from_ns_event (nsevent),
+                                 state,
+                                 x,
+                                 y,
+                                 GDK_CROSSING_NORMAL,
+                                 GDK_NOTIFY_NONLINEAR);
+}
+
+static GdkEvent *
+fill_key_event (GdkMacosDisplay *display,
+                GdkMacosSurface *surface,
+                NSEvent         *nsevent,
+                GdkEventType     type)
+{
+#if 1
+  return NULL;
+#else
+  GdkTranslatedKey translated;
+  GdkTranslatedKey no_lock;
+  GdkModifierType modifiers;
+  gboolean is_modifier;
+  GdkSeat *seat;
+  guint keycode;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (nsevent != NULL);
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+
+  return gdk_key_event_new (type,
+                            GDK_SURFACE (surface),
+                            gdk_seat_get_keyboard (seat),
+                            NULL,
+                            get_time_from_ns_event (nsevent),
+                            [nsevent keyCode],
+                            modifiers,
+                            is_modifier,
+                            &translated,
+                            &no_lock);
+#endif
+}
+
+GdkEvent *
+_gdk_macos_display_translate (GdkMacosDisplay *self,
+                              NSEvent         *nsevent)
+{
+  GdkEvent *ret = NULL;
+  NSEventType event_type;
+  NSWindow *nswindow;
+  GdkMacosSurface *surface;
+  NSPoint point;
+  int x, y;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+  g_return_val_if_fail (nsevent != NULL, NULL);
+
+  /* There is no support for real desktop wide grabs, so we break
+   * grabs when the application loses focus (gets deactivated).
+   */
+  event_type = [nsevent type];
+  if (event_type == NSAppKitDefined)
+    {
+      if ([nsevent subtype] == NSApplicationDeactivatedEventType)
+        _gdk_macos_display_break_all_grabs (self, get_time_from_ns_event (nsevent));
+
+      /* This could potentially be used to break grabs when clicking
+       * on the title. The subtype 20 is undocumented so it's probably
+       * not a good idea: else if (subtype == 20) break_all_grabs ();
+       */
+
+      /* Leave all AppKit events to AppKit. */
+      return NULL;
+    }
+
+  nswindow = [nsevent window];
+
+  /* Ignore events for windows not created by GDK. */
+  if (nswindow && ![[nswindow contentView] isKindOfClass:[GdkMacosBaseView class]])
+    return NULL;
+
+  /* Ignore events for ones with no windows */
+  if (!nswindow)
+    return NULL;
+
+  /* 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 ([(GdkMacosWindow *)nswindow isInMove])
+    {
+      _gdk_macos_display_break_all_grabs (self, get_time_from_ns_event (nsevent));
+      return NULL;
+    }
+
+  /* Also when in a manual resize or move , we ignore events so that
+   * these are pushed to GdkMacosNSWindow's sendEvent handler.
+   */
+  if ([(GdkMacosWindow *)nswindow isInManualResizeOrMove])
+    return NULL;
+
+  /* Get the location of the event within the toplevel */
+  point = [nsevent locationInWindow];
+  _gdk_macos_display_from_display_coords (self, point.x, point.y, &x, &y);
+
+  /* Find the right GDK surface to send the event to, taking grabs and
+   * event masks into consideration.
+   */
+  if (!(surface = [(GdkMacosWindow *)nswindow getGdkSurface]))
+    return NULL;
+
+  /* Quartz handles resizing on its own, so we want to stay out of the way. */
+  if (test_resize (nsevent, surface, x, y))
+    return NULL;
+
+  /* If the app is not active leave the event to AppKit so the window gets
+   * focused correctly and don't do click-through (so we behave like most
+   * native apps). If the app is active, we focus the window and then handle
+   * the event, also to match native apps.
+   */
+  if ((event_type == NSRightMouseDown ||
+       event_type == NSOtherMouseDown ||
+       event_type == NSLeftMouseDown))
+    {
+      if (![NSApp isActive])
+        {
+          [NSApp activateIgnoringOtherApps:YES];
+          return FALSE;
+        }
+      else if (![nswindow isKeyWindow])
+        {
+          [nswindow makeKeyWindow];
+        }
+    }
+
+  switch (event_type)
+    {
+    case NSLeftMouseDown:
+    case NSRightMouseDown:
+    case NSOtherMouseDown:
+    case NSLeftMouseUp:
+    case NSRightMouseUp:
+    case NSOtherMouseUp:
+      ret = fill_button_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSMouseExited:
+      [[NSCursor arrowCursor] set];
+      /* fall through */
+    case NSMouseEntered:
+      ret = synthesize_crossing_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSKeyDown:
+    case NSKeyUp:
+    case NSFlagsChanged: {
+      GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
+
+      if (type)
+        ret = fill_key_event (self, surface, nsevent, type);
+
+      break;
+    }
+
+    default:
+      break;
+    }
+
+#if 0
+  switch (event_type)
+    {
+    case NSLeftMouseDown:
+    case NSRightMouseDown:
+    case NSOtherMouseDown:
+    case NSLeftMouseUp:
+    case NSRightMouseUp:
+    case NSOtherMouseUp:
+      fill_button_event (window, event, nsevent, x, y, x_root, y_root);
+      break;
+
+    case NSLeftMouseDragged:
+    case NSRightMouseDragged:
+    case NSOtherMouseDragged:
+    case NSMouseMoved:
+      fill_motion_event (window, event, nsevent, x, y, x_root, y_root);
+      break;
+
+    case NSScrollWheel:
+      {
+        GdkScrollDirection direction;
+        float dx;
+        float dy;
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+        if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
+            [nsevent hasPreciseScrollingDeltas])
+          {
+            dx = [nsevent scrollingDeltaX];
+            dy = [nsevent scrollingDeltaY];
+            direction = GDK_SCROLL_SMOOTH;
+
+            fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
+                               -dx, -dy, direction);
+
+            /* Fall through for scroll buttons emulation */
+          }
+#endif
+        dx = [nsevent deltaX];
+        dy = [nsevent deltaY];
+
+        if (dy != 0.0)
+          {
+            if (dy < 0.0)
+              direction = GDK_SCROLL_DOWN;
+            else
+              direction = GDK_SCROLL_UP;
+
+            dy = fabs (dy);
+            dx = 0.0;
+          }
+        else if (dx != 0.0)
+          {
+            if (dx < 0.0)
+              direction = GDK_SCROLL_RIGHT;
+            else
+              direction = GDK_SCROLL_LEFT;
+
+            dx = fabs (dx);
+            dy = 0.0;
+          }
+
+        if (dx != 0.0 || dy != 0.0)
+          {
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+            if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
+                [nsevent hasPreciseScrollingDeltas])
+              {
+                GdkEvent *emulated_event;
+
+                emulated_event = gdk_event_new (GDK_SCROLL);
+                gdk_event_set_pointer_emulated (emulated_event, TRUE);
+                fill_scroll_event (window, emulated_event, nsevent,
+                                   x, y, x_root, y_root,
+                                   dx, dy, direction);
+                append_event (emulated_event, TRUE);
+              }
+            else
+#endif
+              fill_scroll_event (window, event, nsevent,
+                                 x, y, x_root, y_root,
+                                 dx, dy, direction);
+          }
+      }
+      break;
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER
+    case NSEventTypeMagnify:
+    case NSEventTypeRotate:
+      /* Event handling requires [NSEvent phase] which was introduced in 10.7 */
+      /* However - Tests on 10.7 showed that phase property does not work     */
+      if (gdk_quartz_osx_version () >= GDK_OSX_MOUNTAIN_LION)
+        fill_pinch_event (window, event, nsevent, x, y, x_root, y_root);
+      else
+        return_val = FALSE;
+      break;
+#endif
+    case NSMouseExited:
+      if (SURFACE_IS_TOPLEVEL (window))
+          [[NSCursor arrowCursor] set];
+      /* fall through */
+    case NSMouseEntered:
+      return_val = synthesize_crossing_event (window, event, nsevent, x, y, x_root, y_root);
+      break;
+
+    case NSKeyDown:
+    case NSKeyUp:
+    case NSFlagsChanged:
+      {
+        GdkEventType type;
+
+        type = _gdk_quartz_keys_event_type (nsevent);
+        if (type == GDK_NOTHING)
+          return_val = FALSE;
+        else
+          fill_key_event (window, event, nsevent, type);
+      }
+      break;
+
+    default:
+      /* Ignore everything elsee. */
+      return_val = FALSE;
+      break;
+    }
+
+ done:
+  if (return_val)
+    {
+      if (event->any.surface)
+        g_object_ref (event->any.surface);
+      if (((event->any.type == GDK_ENTER_NOTIFY) ||
+           (event->any.type == GDK_LEAVE_NOTIFY)) &&
+          (event->crossing.child_window != NULL))
+        g_object_ref (event->crossing.child_window);
+    }
+  else
+    {
+      /* Mark this event as having no resources to be freed */
+      event->any.surface = NULL;
+      event->any.type = GDK_NOTHING;
+    }
+#endif
+
+  return ret;
+}
+
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index 19bf94fbb7..a6282cb679 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -288,27 +288,26 @@ gdk_macos_display_notify_startup_complete (GdkDisplay  *display,
 static void
 gdk_macos_display_queue_events (GdkDisplay *display)
 {
-  g_warning ("Queue events");
-}
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+  NSEvent *nsevent;
+  GdkEvent *event;
+  GList *node;
 
-static void
-gdk_macos_display_event_data_copy (GdkDisplay *display,
-                                   GdkEvent   *event,
-                                   GdkEvent   *new_event)
-{
-  g_assert (GDK_IS_MACOS_DISPLAY (display));
-  g_assert (event != NULL);
-  g_assert (new_event != NULL);
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
 
-}
+  if (!(nsevent = _gdk_macos_event_source_get_pending ()))
+    return;
 
-static void
-gdk_macos_display_event_data_free (GdkDisplay *display,
-                                   GdkEvent   *event)
-{
-  g_assert (GDK_IS_MACOS_DISPLAY (display));
-  g_assert (event != NULL);
+  if (!(event = _gdk_macos_display_translate (self, nsevent)))
+    {
+      [NSApp sendEvent:nsevent];
+      _gdk_macos_event_source_release_event (nsevent);
+      return;
+    }
 
+  node = _gdk_event_queue_append (GDK_DISPLAY (self), event);
+  _gdk_windowing_got_event (GDK_DISPLAY (self), node, event, 0);
+  _gdk_macos_event_source_release_event (nsevent);
 }
 
 static GdkSurface *
@@ -367,8 +366,6 @@ gdk_macos_display_class_init (GdkMacosDisplayClass *klass)
 
   display_class->beep = gdk_macos_display_beep;
   display_class->create_surface = gdk_macos_display_create_surface;
-  display_class->event_data_copy = gdk_macos_display_event_data_copy;
-  display_class->event_data_free = gdk_macos_display_event_data_free;
   display_class->flush = gdk_macos_display_flush;
   display_class->get_keymap = gdk_macos_display_get_keymap;
   display_class->get_monitor = gdk_macos_display_get_monitor;
@@ -486,38 +483,41 @@ _gdk_macos_display_get_screen_at_display_coords (GdkMacosDisplay *self,
   return screen;
 }
 
-static GdkEvent *
-gdk_macos_display_translate (GdkMacosDisplay *self,
-                             NSEvent         *event)
-{
-  g_assert (GDK_IS_MACOS_DISPLAY (self));
-  g_assert (event != NULL);
-
-  /* TODO: Event translation */
-
-  return NULL;
-}
-
 void
-_gdk_macos_display_queue_events (GdkMacosDisplay *self)
+_gdk_macos_display_break_all_grabs (GdkMacosDisplay *self,
+                                    guint32          time)
 {
-  NSEvent *nsevent;
-  GdkEvent *event;
-  GList *node;
+  GList *devices = NULL;
+  GdkSeat *seat;
 
   g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
 
-  if (!(nsevent = _gdk_macos_event_source_get_pending ()))
-    return;
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+
+  devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
+  devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
 
-  if (!(event = gdk_macos_display_translate (self, nsevent)))
+  for (const GList *l = devices; l; l = l->next)
     {
-      [NSApp sendEvent:nsevent];
-      _gdk_macos_event_source_release_event (nsevent);
-      return;
+      GdkDevice *device = l->data;
+      GdkDeviceGrabInfo *grab;
+
+      grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), device);
+
+      if (grab != NULL)
+        {
+          grab->serial_end = 0;
+          grab->implicit_ungrab = TRUE;
+        }
+
+      _gdk_display_device_grab_update (GDK_DISPLAY (self), device, NULL, 0);
     }
 
-  node = _gdk_event_queue_append (GDK_DISPLAY (self), event);
-  _gdk_windowing_got_event (GDK_DISPLAY (self), node, event, 0);
-  _gdk_macos_event_source_release_event (nsevent);
+  g_list_free (devices);
+}
+
+void
+_gdk_macos_display_queue_events (GdkMacosDisplay *self)
+{
+  gdk_macos_display_queue_events (GDK_DISPLAY (self));
 }
diff --git a/gdk/macos/gdkmacoskeymap-private.h b/gdk/macos/gdkmacoskeymap-private.h
index 9cce0e6ba2..28eaa091ac 100644
--- a/gdk/macos/gdkmacoskeymap-private.h
+++ b/gdk/macos/gdkmacoskeymap-private.h
@@ -20,12 +20,15 @@
 #ifndef __GDK_MACOS_KEYMAP_PRIVATE_H__
 #define __GDK_MACOS_KEYMAP_PRIVATE_H__
 
+#include <AppKit/AppKit.h>
+
 #include "gdkmacosdisplay.h"
 #include "gdkmacoskeymap.h"
 
 G_BEGIN_DECLS
 
-GdkMacosKeymap *_gdk_macos_keymap_new (GdkMacosDisplay *display);
+GdkMacosKeymap *_gdk_macos_keymap_new            (GdkMacosDisplay *display);
+GdkEventType    _gdk_macos_keymap_get_event_type (NSEvent         *event);
 
 G_END_DECLS
 
diff --git a/gdk/macos/gdkmacoskeymap.c b/gdk/macos/gdkmacoskeymap.c
index 1adccfc3c3..0c2cd1d5bd 100644
--- a/gdk/macos/gdkmacoskeymap.c
+++ b/gdk/macos/gdkmacoskeymap.c
@@ -86,7 +86,7 @@ macroman2ucs (unsigned char c)
   /* Precalculated table mapping MacRoman-128 to Unicode. Generated
      by creating single element CFStringRefs then extracting the
      first character. */
-  
+
   static const unsigned short table[128] = {
     0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
     0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
@@ -590,7 +590,7 @@ gdk_macos_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
       GdkKeymapKey key;
 
       if (keyval_array[i] != keyval)
-       continue;
+        continue;
 
       (*n_keys)++;
 
@@ -602,7 +602,7 @@ gdk_macos_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
     }
 
   *keys = (GdkKeymapKey *)(gpointer)g_array_free (keys_array, FALSE);
-  
+
   return *n_keys > 0;
 }
 
@@ -641,29 +641,29 @@ gdk_macos_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
     keyvals_array = NULL;
 
   p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
-  
+
   for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
     {
       if (!p[i])
-       continue;
+        continue;
 
       (*n_entries)++;
-      
+
       if (keyvals_array)
-       g_array_append_val (keyvals_array, p[i]);
+        g_array_append_val (keyvals_array, p[i]);
 
       if (keys_array)
-       {
-         GdkKeymapKey key;
+        {
+          GdkKeymapKey key;
 
-         key.keycode = hardware_keycode;
-         key.group = i >= 2;
-         key.level = i % 2;
+          key.keycode = hardware_keycode;
+          key.group = i >= 2;
+          key.level = i % 2;
 
-         g_array_append_val (keys_array, key);
-       }
+          g_array_append_val (keys_array, key);
+        }
     }
-  
+
   if (keys)
     *keys = (GdkKeymapKey *)(gpointer)g_array_free (keys_array, FALSE);
 
@@ -719,7 +719,7 @@ gdk_macos_keymap_translate_keyboard_state (GdkKeymap       *keymap,
     }
 
   if (keyval)
-    *keyval = tmp_keyval; 
+    *keyval = tmp_keyval;
 
   return TRUE;
 }
@@ -734,7 +734,7 @@ input_sources_changed_notification (CFNotificationCenterRef  center,
   GdkMacosKeymap *self = observer;
 
   g_assert (GDK_IS_MACOS_KEYMAP (self));
-  
+
   gdk_macos_keymap_update (self);
 }
 
@@ -789,3 +789,45 @@ _gdk_macos_keymap_new (GdkMacosDisplay *display)
                        "display", display,
                        NULL);
 }
+
+/* What sort of key event is this? Returns one of
+ * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
+ */
+GdkEventType
+_gdk_macos_keymap_get_event_type (NSEvent *event)
+{
+  unsigned short keycode;
+  unsigned int flags;
+
+  switch ([event type])
+    {
+    case NSKeyDown:
+      return GDK_KEY_PRESS;
+    case NSKeyUp:
+      return GDK_KEY_RELEASE;
+    case NSFlagsChanged:
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  /* For flags-changed events, we have to find the special key that caused the
+   * event, and see if it's in the modifier mask. */
+  keycode = [event keyCode];
+  flags = [event modifierFlags];
+
+  for (guint i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
+    {
+      if (modifier_keys[i].keycode == keycode)
+        {
+          if (flags & modifier_keys[i].modmask)
+            return GDK_KEY_PRESS;
+          else
+            return GDK_KEY_RELEASE;
+        }
+    }
+
+  /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
+   * events for no good reason. Ignore them! */
+  return 0;
+}
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
index e4319bf516..5829888151 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -21,6 +21,7 @@
 #define __GDK_MACOS_SURFACE_PRIVATE_H__
 
 #include <AppKit/AppKit.h>
+#include <cairo.h>
 
 #include "gdkinternals.h"
 #include "gdksurfaceprivate.h"
@@ -73,6 +74,9 @@ void               _gdk_macos_surface_resize                  (GdkMacosSurface
                                                                int                 scale);
 void               _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface    *self);
 void               _gdk_macos_surface_update_position         (GdkMacosSurface    *self);
+void               _gdk_macos_surface_damage_cairo            (GdkMacosSurface    *self,
+                                                               cairo_surface_t    *surface,
+                                                               cairo_region_t     *painted);
 
 G_END_DECLS
 
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index 425416c256..f6d307174b 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -23,12 +23,14 @@
 #include <float.h>
 #include <gdk/gdk.h>
 
+#import "GdkMacosCairoView.h"
 #import "GdkMacosWindow.h"
 
 #include "gdkframeclockidleprivate.h"
 #include "gdkinternals.h"
 #include "gdksurfaceprivate.h"
 
+#include "gdkmacosdevice.h"
 #include "gdkmacosdisplay-private.h"
 #include "gdkmacosdragsurface-private.h"
 #include "gdkmacospopupsurface-private.h"
@@ -184,7 +186,6 @@ gdk_macos_surface_begin_frame (GdkMacosSurface *self)
 {
   g_assert (GDK_IS_MACOS_SURFACE (self));
 
-  g_print ("%s: begin_frame\n", G_OBJECT_TYPE_NAME (self));
 }
 
 static void
@@ -192,7 +193,6 @@ gdk_macos_surface_end_frame (GdkMacosSurface *self)
 {
   g_assert (GDK_IS_MACOS_SURFACE (self));
 
-  g_print ("%s: end_frame\n", G_OBJECT_TYPE_NAME (self));
 }
 
 static void
@@ -270,6 +270,39 @@ gdk_macos_surface_get_root_coords (GdkSurface *surface,
     *root_y = tmp_y;
 }
 
+static gboolean
+gdk_macos_surface_get_device_state (GdkSurface      *surface,
+                                    GdkDevice       *device,
+                                    gdouble         *x,
+                                    gdouble         *y,
+                                    GdkModifierType *mask)
+{
+  GdkDisplay *display;
+  NSWindow *nswindow;
+  NSPoint point;
+  int x_tmp;
+  int y_tmp;
+
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (x != NULL);
+  g_assert (y != NULL);
+  g_assert (mask != NULL);
+
+  display = gdk_surface_get_display (surface);
+  nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
+  point = [nswindow mouseLocationOutsideOfEventStream];
+
+  _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display),
+                                          point.x, point.y,
+                                          &x_tmp, &y_tmp);
+
+  *x = x_tmp;
+  *y = x_tmp;
+
+  return TRUE;
+}
+
 static void
 gdk_macos_surface_destroy (GdkSurface *surface,
                            gboolean    foreign_destroy)
@@ -366,6 +399,7 @@ gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
   surface_class->begin_move_drag = gdk_macos_surface_begin_move_drag;
   surface_class->begin_resize_drag = gdk_macos_surface_begin_resize_drag;
   surface_class->destroy = gdk_macos_surface_destroy;
+  surface_class->get_device_state = gdk_macos_surface_get_device_state;
   surface_class->get_root_coords = gdk_macos_surface_get_root_coords;
   surface_class->get_scale_factor = gdk_macos_surface_get_scale_factor;
   surface_class->hide = gdk_macos_surface_hide;
@@ -425,9 +459,6 @@ _gdk_macos_surface_new (GdkMacosDisplay   *display,
       ret = NULL;
     }
 
-  if (ret != NULL)
-    gdk_surface_freeze_updates (GDK_SURFACE (ret));
-
   g_object_unref (frame_clock);
 
   return g_steal_pointer (&ret);
@@ -628,3 +659,19 @@ _gdk_macos_surface_update_position (GdkMacosSurface *self)
 
   GDK_END_MACOS_ALLOC_POOL;
 }
+
+void
+_gdk_macos_surface_damage_cairo (GdkMacosSurface *self,
+                                 cairo_surface_t *surface,
+                                 cairo_region_t  *painted)
+{
+  GdkMacosSurfacePrivate *priv = gdk_macos_surface_get_instance_private (self);
+  GdkMacosCairoView *view;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+  g_return_if_fail (surface != NULL);
+
+  view = (GdkMacosCairoView *)[priv->window contentView];
+  [view setCairoSurfaceWithRegion:surface
+                      cairoRegion:painted];
+}
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
index 2d06ca021a..805c1ff29e 100644
--- a/gdk/macos/meson.build
+++ b/gdk/macos/meson.build
@@ -1,8 +1,10 @@
 gdk_macos_sources = files([
   'GdkMacosWindow.c',
   'gdkmacoscairocontext.c',
+  'gdkmacoscursor.c',
   'gdkmacosdevice.c',
   'gdkmacosdisplay.c',
+  'gdkmacosdisplay-translate.c',
   'gdkmacosdragsurface.c',
   'gdkmacoseventsource.c',
   'gdkmacoskeymap.c',



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