[gtk/wip/chergert/quartz4u] build: stub out macOS backend



commit 3c907f0d7019795bf0a18981d1069f886ffff09d
Author: Christian Hergert <chergert redhat com>
Date:   Thu Apr 23 16:36:46 2020 -0700

    build: stub out macOS backend

 gdk/gdkconfig.h.meson               |   1 +
 gdk/gdkdisplaymanager.c             |   7 +
 gdk/macos/gdkmacos.h                |  27 ++
 gdk/macos/gdkmacosdisplay-private.h |  31 ++
 gdk/macos/gdkmacosdisplay.c         | 349 ++++++++++++++++
 gdk/macos/gdkmacosdisplay.h         |  47 +++
 gdk/macos/gdkmacoskeymap-private.h  |  32 ++
 gdk/macos/gdkmacoskeymap.c          | 791 ++++++++++++++++++++++++++++++++++++
 gdk/macos/gdkmacoskeymap.h          |  43 ++
 gdk/macos/gdkmacosmonitor-private.h |  47 +++
 gdk/macos/gdkmacosmonitor.c         |  58 +++
 gdk/macos/gdkmacosmonitor.h         |  43 ++
 gdk/macos/gdkmacossurface-private.h |  37 ++
 gdk/macos/gdkmacossurface.c         |  74 ++++
 gdk/macos/gdkmacossurface.h         |  43 ++
 gdk/macos/gdkmacosutils-private.h   |  29 ++
 gdk/macos/meson.build               |  45 ++
 gdk/meson.build                     |   3 +-
 meson.build                         |   8 +-
 meson_options.txt                   |   2 +
 20 files changed, 1714 insertions(+), 3 deletions(-)
---
diff --git a/gdk/gdkconfig.h.meson b/gdk/gdkconfig.h.meson
index 80666b25f0..867b430e43 100644
--- a/gdk/gdkconfig.h.meson
+++ b/gdk/gdkconfig.h.meson
@@ -12,6 +12,7 @@ G_BEGIN_DECLS
 
 #mesondefine GDK_WINDOWING_X11
 #mesondefine GDK_WINDOWING_BROADWAY
+#mesondefine GDK_WINDOWING_MACOS
 #mesondefine GDK_WINDOWING_WAYLAND
 #mesondefine GDK_WINDOWING_WIN32
 
diff --git a/gdk/gdkdisplaymanager.c b/gdk/gdkdisplaymanager.c
index 8a359b77c6..2452f110e1 100644
--- a/gdk/gdkdisplaymanager.c
+++ b/gdk/gdkdisplaymanager.c
@@ -50,6 +50,10 @@
 #include "broadway/gdkprivate-broadway.h"
 #endif
 
+#ifdef GDK_WINDOWING_MACOS
+#include "macos/gdkmacosdisplay-private.h"
+#endif
+
 #ifdef GDK_WINDOWING_WIN32
 #include "win32/gdkwin32.h"
 #include "win32/gdkprivate-win32.h"
@@ -262,6 +266,9 @@ static GdkBackend gdk_backends[] = {
 #ifdef GDK_WINDOWING_QUARTZ
   { "quartz",   _gdk_quartz_display_open },
 #endif
+#ifdef GDK_WINDOWING_MACOS
+  { "macos",   _gdk_macos_display_open },
+#endif
 #ifdef GDK_WINDOWING_WIN32
   { "win32",    _gdk_win32_display_open },
 #endif
diff --git a/gdk/macos/gdkmacos.h b/gdk/macos/gdkmacos.h
new file mode 100644
index 0000000000..f7eea95502
--- /dev/null
+++ b/gdk/macos/gdkmacos.h
@@ -0,0 +1,27 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_H__
+#define __GDK_MACOS_H__
+
+#include <gdk/gdk.h>
+
+#include "gdkmacosdisplay.h"
+
+#endif /* __GDK_MACOS_H__ */
diff --git a/gdk/macos/gdkmacosdisplay-private.h b/gdk/macos/gdkmacosdisplay-private.h
new file mode 100644
index 0000000000..6a025213d8
--- /dev/null
+++ b/gdk/macos/gdkmacosdisplay-private.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_DISPLAY_PRIVATE_H__
+#define __GDK_MACOS_DISPLAY_PRIVATE_H__
+
+#include "gdkmacosdisplay.h"
+
+G_BEGIN_DECLS
+
+GdkDisplay *_gdk_macos_display_open (const gchar *display_name);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DISPLAY_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
new file mode 100644
index 0000000000..f9bcb0ea00
--- /dev/null
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -0,0 +1,349 @@
+/*
+ * 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"
+
+#include <AppKit/AppKit.h>
+#include <gdk/gdk.h>
+
+#include "gdkdisplayprivate.h"
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacoskeymap-private.h"
+#include "gdkmacosmonitor-private.h"
+#include "gdkmacossurface-private.h"
+#include "gdkmacosutils-private.h"
+
+/**
+ * SECTION:macos_interaction
+ * @Short_description: macOS backend-specific functions
+ * @Title: macOS Interaction
+ * @Include: gdk/macos/gdkmacos.h
+ *
+ * The functions in this section are specific to the GDK macOS backend.
+ * To use them, you need to include the `<gdk/macos/gdkmacos.h>` header and
+ * use the macOS-specific pkg-config `gtk4-macos` file to build your
+ * application.
+ *
+ * To make your code compile with other GDK backends, guard backend-specific
+ * calls by an ifdef as follows. Since GDK may be built with multiple
+ * backends, you should also check for the backend that is in use (e.g. by
+ * using the GDK_IS_MACOS_DISPLAY() macro).
+ * |[<!-- language="C" -->
+ * #ifdef GDK_WINDOWING_MACOS
+ *   if (GDK_IS_MACOS_DISPLAY (display))
+ *     {
+ *       // make macOS-specific calls here
+ *     }
+ *   else
+ * #endif
+ * #ifdef GDK_WINDOWING_X11
+ *   if (GDK_IS_X11_DISPLAY (display))
+ *     {
+ *       // make X11-specific calls here
+ *     }
+ *   else
+ * #endif
+ *   g_error ("Unsupported GDK backend");
+ * ]|
+ */
+
+struct _GdkMacosDisplay
+{
+  GdkDisplay      parent_instance;
+  gchar          *name;
+  GPtrArray      *monitors;
+  GdkMacosKeymap *keymap;
+};
+
+struct _GdkMacosDisplayClass
+{
+  GdkDisplayClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMacosDisplay, gdk_macos_display, GDK_TYPE_DISPLAY)
+
+static gboolean
+gdk_macos_display_get_setting (GdkDisplay  *display,
+                               const gchar *setting,
+                               GValue      *value)
+{
+  return FALSE;
+}
+
+static int
+gdk_macos_display_get_n_monitors (GdkDisplay *display)
+{
+  return GDK_MACOS_DISPLAY (display)->monitors->len;
+}
+
+static GdkMonitor *
+gdk_macos_display_get_monitor (GdkDisplay *display,
+                               int         index)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+  g_assert (index >= 0);
+
+  if (index < self->monitors->len)
+    return g_ptr_array_index (self->monitors, index);
+
+  return NULL;
+}
+
+static GdkMonitor *
+gdk_macos_display_get_primary_monitor (GdkDisplay *display)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  return g_ptr_array_index (self->monitors, 0);
+}
+
+static void
+gdk_macos_display_add_monitor (GdkMacosDisplay *self,
+                               GdkMacosMonitor *monitor)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+  g_assert (GDK_IS_MACOS_MONITOR (monitor));
+
+  g_ptr_array_add (self->monitors, g_object_ref (monitor));
+  gdk_display_monitor_added (GDK_DISPLAY (self), GDK_MONITOR (monitor));
+}
+
+static void
+gdk_macos_display_remove_monitor (GdkMacosDisplay *self,
+                                  GdkMacosMonitor *monitor)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+  g_assert (GDK_IS_MACOS_MONITOR (monitor));
+
+  g_object_ref (monitor);
+
+  if (g_ptr_array_remove (self->monitors, monitor))
+    gdk_display_monitor_removed (GDK_DISPLAY (self), GDK_MONITOR (monitor));
+
+  g_object_unref (monitor);
+}
+
+static void
+gdk_macos_display_load_monitors (GdkMacosDisplay *self)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  NSArray *screens;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  screens = [NSScreen screens];
+
+  for (id obj in screens)
+    {
+      CGDirectDisplayID screen_id;
+      GdkMacosMonitor *monitor;
+
+      screen_id = [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
+      monitor = _gdk_macos_monitor_new (self, screen_id);
+
+      gdk_macos_display_add_monitor (self, monitor);
+
+      g_object_unref (monitor);
+    }
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static const gchar *
+gdk_macos_display_get_name (GdkDisplay *display)
+{
+  return GDK_MACOS_DISPLAY (display)->name;
+}
+
+static void
+gdk_macos_display_beep (GdkDisplay *display)
+{
+  NSBeep ();
+}
+
+static void
+gdk_macos_display_flush (GdkDisplay *display)
+{
+  /* Not Supported */
+}
+
+static void
+gdk_macos_display_sync (GdkDisplay *display)
+{
+  /* Not Supported */
+}
+
+static gboolean
+gdk_macos_display_supports_shapes (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+static gboolean
+gdk_macos_display_supports_input_shapes (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+static gulong
+gdk_macos_display_get_next_serial (GdkDisplay *display)
+{
+  return 0;
+}
+
+static gboolean
+gdk_macos_display_has_pending (GdkDisplay *display)
+{
+  g_warning ("Has pending");
+  return FALSE;
+}
+
+static void
+gdk_macos_display_notify_startup_complete (GdkDisplay  *display,
+                                           const gchar *startup_notification_id)
+{
+  /* Not Supported */
+}
+
+static void
+gdk_macos_display_queue_events (GdkDisplay *display)
+{
+  g_warning ("Queue events");
+}
+
+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);
+
+}
+
+static void
+gdk_macos_display_event_data_free (GdkDisplay *display,
+                                   GdkEvent   *event)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (event != NULL);
+
+}
+
+static GdkSurface *
+gdk_macos_display_create_surface (GdkDisplay     *display,
+                                  GdkSurfaceType  surface_type,
+                                  GdkSurface     *parent,
+                                  int             x,
+                                  int             y,
+                                  int             width,
+                                  int             height)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (!parent || GDK_IS_MACOS_SURFACE (parent));
+
+  return NULL;
+}
+
+static GdkKeymap *
+gdk_macos_display_get_keymap (GdkDisplay *display)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  return GDK_KEYMAP (self->keymap);
+}
+
+static void
+gdk_macos_display_finalize (GObject *object)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)object;
+
+  g_clear_pointer (&self->monitors, g_ptr_array_unref);
+  g_clear_pointer (&self->name, g_free);
+
+  G_OBJECT_CLASS (gdk_macos_display_parent_class)->finalize (object);
+}
+
+static void
+gdk_macos_display_class_init (GdkMacosDisplayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (klass);
+
+  object_class->finalize = gdk_macos_display_finalize;
+
+  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;
+  display_class->get_next_serial = gdk_macos_display_get_next_serial;
+  display_class->get_n_monitors = gdk_macos_display_get_n_monitors;
+  display_class->get_name = gdk_macos_display_get_name;
+  display_class->get_primary_monitor = gdk_macos_display_get_primary_monitor;
+  display_class->get_setting = gdk_macos_display_get_setting;
+  display_class->has_pending = gdk_macos_display_has_pending;
+  display_class->notify_startup_complete = gdk_macos_display_notify_startup_complete;
+  display_class->queue_events = gdk_macos_display_queue_events;
+  display_class->supports_input_shapes = gdk_macos_display_supports_input_shapes;
+  display_class->supports_shapes = gdk_macos_display_supports_shapes;
+  display_class->sync = gdk_macos_display_sync;
+}
+
+static void
+gdk_macos_display_init (GdkMacosDisplay *self)
+{
+  self->monitors = g_ptr_array_new_with_free_func (g_object_unref);
+}
+
+GdkDisplay *
+_gdk_macos_display_open (const gchar *display_name)
+{
+  GdkMacosDisplay *self;
+  ProcessSerialNumber psn = { 0, kCurrentProcess };
+
+  GDK_NOTE (MISC, g_message ("opening display %s", display_name ? display_name : ""));
+
+  /* Make the current process a foreground application, i.e. an app
+   * with a user interface, in case we're not running from a .app bundle
+   */
+  TransformProcessType (&psn, kProcessTransformToForegroundApplication);
+
+  [NSApplication sharedApplication];
+
+  self = g_object_new (GDK_TYPE_MACOS_DISPLAY, NULL);
+  self->name = g_strdup (display_name);
+  self->keymap = _gdk_macos_keymap_new (self);
+
+  gdk_macos_display_load_monitors (self);
+
+  gdk_display_emit_opened (GDK_DISPLAY (self));
+
+  return GDK_DISPLAY (self);
+}
diff --git a/gdk/macos/gdkmacosdisplay.h b/gdk/macos/gdkmacosdisplay.h
new file mode 100644
index 0000000000..7c5730d0c7
--- /dev/null
+++ b/gdk/macos/gdkmacosdisplay.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_DISPLAY_H__
+#define __GDK_MACOS_DISPLAY_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#ifdef GTK_COMPILATION
+typedef struct _GdkMacosDisplay GdkMacosDisplay;
+#else
+typedef GdkDisplay GdkMacosDisplay;
+#endif
+typedef struct _GdkMacosDisplayClass GdkMacosDisplayClass;
+
+#define GDK_TYPE_MACOS_DISPLAY       (gdk_macos_display_get_type())
+#define GDK_MACOS_DISPLAY(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DISPLAY, 
GdkMacosDisplay))
+#define GDK_IS_MACOS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DISPLAY))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_display_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DISPLAY_H__ */
diff --git a/gdk/macos/gdkmacoskeymap-private.h b/gdk/macos/gdkmacoskeymap-private.h
new file mode 100644
index 0000000000..9cce0e6ba2
--- /dev/null
+++ b/gdk/macos/gdkmacoskeymap-private.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_KEYMAP_PRIVATE_H__
+#define __GDK_MACOS_KEYMAP_PRIVATE_H__
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacoskeymap.h"
+
+G_BEGIN_DECLS
+
+GdkMacosKeymap *_gdk_macos_keymap_new (GdkMacosDisplay *display);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_KEYMAP_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacoskeymap.c b/gdk/macos/gdkmacoskeymap.c
new file mode 100644
index 0000000000..1adccfc3c3
--- /dev/null
+++ b/gdk/macos/gdkmacoskeymap.c
@@ -0,0 +1,791 @@
+/*
+ * Copyright © 2000-2020 Red Hat, Inc.
+ * Copyright © 2005 Imendio AB
+ *
+ * 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
+ */
+/* Some parts of this code come from quartzKeyboard.c,
+ * from the Apple X11 Server.
+ *
+ * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ *
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation files
+ *  (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify, merge,
+ *  publish, distribute, sublicense, and/or sell copies of the Software,
+ *  and to permit persons to whom the Software is furnished to do so,
+ *  subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be
+ *  included in all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *  NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ *  HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *  DEALINGS IN THE SOFTWARE.
+ *
+ *  Except as contained in this notice, the name(s) of the above
+ *  copyright holders shall not be used in advertising or otherwise to
+ *  promote the sale, use or other dealings in this Software without
+ *  prior written authorization.
+ */
+
+#include "config.h"
+
+#include <AppKit/AppKit.h>
+#include <Carbon/Carbon.h>
+#include <gdk/gdk.h>
+
+#include "gdkkeysprivate.h"
+#include "gdkkeysyms.h"
+#include "gdkmacoskeymap-private.h"
+
+struct _GdkMacosKeymap
+{
+  GdkKeymap parent_instance;
+};
+
+struct _GdkMacosKeymapClass
+{
+  GdkKeymapClass parent_instance;
+};
+
+G_DEFINE_TYPE (GdkMacosKeymap, gdk_macos_keymap, GDK_TYPE_KEYMAP)
+
+/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
+ * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
+ */
+static guint *keyval_array = NULL;
+
+#define NUM_KEYCODES 128
+#define KEYVALS_PER_KEYCODE 4
+#define GET_KEYVAL(keycode, group, level) \
+  (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
+
+static inline UniChar
+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,
+    0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
+    0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
+    0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
+    0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
+    0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
+    0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
+    0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
+    0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
+    0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
+    0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+    0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
+    0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
+    0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
+    0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7
+  };
+
+  if (c < 128)
+    return c;
+  else
+    return table[c - 128];
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+const static struct {
+  guint keycode;
+  guint keyval;
+  unsigned int modmask; /* So we can tell when a mod key is pressed/released */
+} modifier_keys[] = {
+  {  54, GDK_KEY_Meta_R,    NSCommandKeyMask },
+  {  55, GDK_KEY_Meta_L,    NSCommandKeyMask },
+  {  56, GDK_KEY_Shift_L,   NSShiftKeyMask },
+  {  57, GDK_KEY_Caps_Lock, NSAlphaShiftKeyMask },
+  {  58, GDK_KEY_Alt_L,     NSAlternateKeyMask },
+  {  59, GDK_KEY_Control_L, NSControlKeyMask },
+  {  60, GDK_KEY_Shift_R,   NSShiftKeyMask },
+  {  61, GDK_KEY_Alt_R,     NSAlternateKeyMask },
+  {  62, GDK_KEY_Control_R, NSControlKeyMask }
+};
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+const static struct {
+  guint keycode;
+  guint keyval;
+} function_keys[] = {
+  { 122, GDK_KEY_F1 },
+  { 120, GDK_KEY_F2 },
+  {  99, GDK_KEY_F3 },
+  { 118, GDK_KEY_F4 },
+  {  96, GDK_KEY_F5 },
+  {  97, GDK_KEY_F6 },
+  {  98, GDK_KEY_F7 },
+  { 100, GDK_KEY_F8 },
+  { 101, GDK_KEY_F9 },
+  { 109, GDK_KEY_F10 },
+  { 103, GDK_KEY_F11 },
+  { 111, GDK_KEY_F12 },
+  { 105, GDK_KEY_F13 },
+  { 107, GDK_KEY_F14 },
+  { 113, GDK_KEY_F15 },
+  { 106, GDK_KEY_F16 }
+};
+
+const static struct {
+  guint keycode;
+  guint normal_keyval, keypad_keyval;
+} known_numeric_keys[] = {
+  { 65, GDK_KEY_period, GDK_KEY_KP_Decimal },
+  { 67, GDK_KEY_asterisk, GDK_KEY_KP_Multiply },
+  { 69, GDK_KEY_plus, GDK_KEY_KP_Add },
+  { 75, GDK_KEY_slash, GDK_KEY_KP_Divide },
+  { 76, GDK_KEY_Return, GDK_KEY_KP_Enter },
+  { 78, GDK_KEY_minus, GDK_KEY_KP_Subtract },
+  { 81, GDK_KEY_equal, GDK_KEY_KP_Equal },
+  { 82, GDK_KEY_0, GDK_KEY_KP_0 },
+  { 83, GDK_KEY_1, GDK_KEY_KP_1 },
+  { 84, GDK_KEY_2, GDK_KEY_KP_2 },
+  { 85, GDK_KEY_3, GDK_KEY_KP_3 },
+  { 86, GDK_KEY_4, GDK_KEY_KP_4 },
+  { 87, GDK_KEY_5, GDK_KEY_KP_5 },
+  { 88, GDK_KEY_6, GDK_KEY_KP_6 },
+  { 89, GDK_KEY_7, GDK_KEY_KP_7 },
+  { 91, GDK_KEY_8, GDK_KEY_KP_8 },
+  { 92, GDK_KEY_9, GDK_KEY_KP_9 }
+};
+
+/* These values aren't covered by gdk_unicode_to_keyval */
+const static struct {
+  gunichar ucs_value;
+  guint keyval;
+} special_ucs_table [] = {
+  { 0x0001, GDK_KEY_Home },
+  { 0x0003, GDK_KEY_Return },
+  { 0x0004, GDK_KEY_End },
+  { 0x0008, GDK_KEY_BackSpace },
+  { 0x0009, GDK_KEY_Tab },
+  { 0x000b, GDK_KEY_Page_Up },
+  { 0x000c, GDK_KEY_Page_Down },
+  { 0x000d, GDK_KEY_Return },
+  { 0x001b, GDK_KEY_Escape },
+  { 0x001c, GDK_KEY_Left },
+  { 0x001d, GDK_KEY_Right },
+  { 0x001e, GDK_KEY_Up },
+  { 0x001f, GDK_KEY_Down },
+  { 0x007f, GDK_KEY_Delete },
+  { 0xf027, GDK_KEY_dead_acute },
+  { 0xf060, GDK_KEY_dead_grave },
+  { 0xf300, GDK_KEY_dead_grave },
+  { 0xf0b4, GDK_KEY_dead_acute },
+  { 0xf301, GDK_KEY_dead_acute },
+  { 0xf385, GDK_KEY_dead_acute },
+  { 0xf05e, GDK_KEY_dead_circumflex },
+  { 0xf2c6, GDK_KEY_dead_circumflex },
+  { 0xf302, GDK_KEY_dead_circumflex },
+  { 0xf07e, GDK_KEY_dead_tilde },
+  { 0xf2dc, GDK_KEY_dead_tilde },
+  { 0xf303, GDK_KEY_dead_tilde },
+  { 0xf342, GDK_KEY_dead_perispomeni },
+  { 0xf0af, GDK_KEY_dead_macron },
+  { 0xf304, GDK_KEY_dead_macron },
+  { 0xf2d8, GDK_KEY_dead_breve },
+  { 0xf306, GDK_KEY_dead_breve },
+  { 0xf2d9, GDK_KEY_dead_abovedot },
+  { 0xf307, GDK_KEY_dead_abovedot },
+  { 0xf0a8, GDK_KEY_dead_diaeresis },
+  { 0xf308, GDK_KEY_dead_diaeresis },
+  { 0xf2da, GDK_KEY_dead_abovering },
+  { 0xf30A, GDK_KEY_dead_abovering },
+  { 0xf022, GDK_KEY_dead_doubleacute },
+  { 0xf2dd, GDK_KEY_dead_doubleacute },
+  { 0xf30B, GDK_KEY_dead_doubleacute },
+  { 0xf2c7, GDK_KEY_dead_caron },
+  { 0xf30C, GDK_KEY_dead_caron },
+  { 0xf0be, GDK_KEY_dead_cedilla },
+  { 0xf327, GDK_KEY_dead_cedilla },
+  { 0xf2db, GDK_KEY_dead_ogonek },
+  { 0xf328, GDK_KEY_dead_ogonek },
+  { 0xfe5d, GDK_KEY_dead_iota },
+  { 0xf323, GDK_KEY_dead_belowdot },
+  { 0xf309, GDK_KEY_dead_hook },
+  { 0xf31B, GDK_KEY_dead_horn },
+  { 0xf02d, GDK_KEY_dead_stroke },
+  { 0xf335, GDK_KEY_dead_stroke },
+  { 0xf336, GDK_KEY_dead_stroke },
+  { 0xf313, GDK_KEY_dead_abovecomma },
+  /*  { 0xf313, GDK_KEY_dead_psili }, */
+  { 0xf314, GDK_KEY_dead_abovereversedcomma },
+  /*  { 0xf314, GDK_KEY_dead_dasia }, */
+  { 0xf30F, GDK_KEY_dead_doublegrave },
+  { 0xf325, GDK_KEY_dead_belowring },
+  { 0xf2cd, GDK_KEY_dead_belowmacron },
+  { 0xf331, GDK_KEY_dead_belowmacron },
+  { 0xf32D, GDK_KEY_dead_belowcircumflex },
+  { 0xf330, GDK_KEY_dead_belowtilde },
+  { 0xf32E, GDK_KEY_dead_belowbreve },
+  { 0xf324, GDK_KEY_dead_belowdiaeresis },
+  { 0xf311, GDK_KEY_dead_invertedbreve },
+  { 0xf02c, GDK_KEY_dead_belowcomma },
+  { 0xf326, GDK_KEY_dead_belowcomma }
+};
+
+static void
+gdk_macos_keymap_update (GdkMacosKeymap *self)
+{
+  const void *chr_data = NULL;
+  guint *p;
+  int i;
+
+  /* Note: we could check only if building against the 10.5 SDK instead, but
+   * that would make non-xml layouts not work in 32-bit which would be a quite
+   * bad regression. This way, old unsupported layouts will just not work in
+   * 64-bit.
+   */
+#ifdef __LP64__
+  TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
+  CFDataRef layout_data_ref;
+
+#else
+  KeyboardLayoutRef new_layout;
+  KeyboardLayoutKind layout_kind;
+
+  KLGetCurrentKeyboardLayout (&new_layout);
+#endif
+
+  g_free (keyval_array);
+  keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
+
+#ifdef __LP64__
+  layout_data_ref = (CFDataRef) TISGetInputSourceProperty
+    (new_layout, kTISPropertyUnicodeKeyLayoutData);
+
+  if (layout_data_ref)
+    chr_data = CFDataGetBytePtr (layout_data_ref);
+
+  if (chr_data == NULL)
+    {
+      g_error ("cannot get keyboard layout data");
+      return;
+    }
+#else
+
+  /* Get the layout kind */
+  KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
+
+  /* 8-bit-only keyabord layout */
+  if (layout_kind == kKLKCHRKind)
+    {
+      /* Get chr data */
+      KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
+
+      for (i = 0; i < NUM_KEYCODES; i++)
+        {
+          int j;
+          UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
+
+          p = keyval_array + i * KEYVALS_PER_KEYCODE;
+
+          for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
+            {
+              UInt32 c, state = 0;
+              UInt16 key_code;
+              UniChar uc;
+
+              key_code = modifiers[j] | i;
+              c = KeyTranslate (chr_data, key_code, &state);
+
+              if (state != 0)
+                {
+                  UInt32 state2 = 0;
+                  c = KeyTranslate (chr_data, key_code | 128, &state2);
+                }
+
+              if (c != 0 && c != 0x10)
+                {
+                  int k;
+                  gboolean found = FALSE;
+
+                  /* FIXME: some keyboard layouts (e.g. Russian) use a
+                   * different 8-bit character set. We should check
+                   * for this. Not a serious problem, because most
+                   * (all?) of these layouts also have a uchr version.
+                   */
+                  uc = macroman2ucs (c);
+
+                  for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
+                    {
+                      if (special_ucs_table[k].ucs_value == uc)
+                        {
+                          p[j] = special_ucs_table[k].keyval;
+                          found = TRUE;
+                          break;
+                        }
+                    }
+
+                  /* Special-case shift-tab since GTK+ expects
+                   * GDK_KEY_ISO_Left_Tab for that.
+                   */
+                  if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
+                    p[j] = GDK_KEY_ISO_Left_Tab;
+
+                  if (!found)
+                    p[j] = gdk_unicode_to_keyval (uc);
+                }
+            }
+
+          if (p[3] == p[2])
+            p[3] = 0;
+          if (p[2] == p[1])
+            p[2] = 0;
+          if (p[1] == p[0])
+            p[1] = 0;
+          if (p[0] == p[2] &&
+              p[1] == p[3])
+            p[2] = p[3] = 0;
+        }
+    }
+  /* unicode keyboard layout */
+  else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
+    {
+      /* Get chr data */
+      KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
+#endif
+
+      for (i = 0; i < NUM_KEYCODES; i++)
+        {
+          int j;
+          UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
+          UniChar chars[4];
+          UniCharCount nChars;
+
+          p = keyval_array + i * KEYVALS_PER_KEYCODE;
+
+          for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
+            {
+              UInt32 state = 0;
+              OSStatus err;
+              UInt16 key_code;
+              UniChar uc;
+
+              key_code = modifiers[j] | i;
+              err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
+                                    (modifiers[j] >> 8) & 0xFF,
+                                    LMGetKbdType(),
+                                    0,
+                                    &state, 4, &nChars, chars);
+
+              /* FIXME: Theoretically, we can get multiple UTF-16
+               * values; we should convert them to proper unicode and
+               * figure out whether there are really keyboard layouts
+               * that give us more than one character for one
+               * keypress.
+               */
+              if (err == noErr && nChars == 1)
+                {
+                  int k;
+                  gboolean found = FALSE;
+
+                  /* A few <Shift><Option>keys return two characters,
+                   * the first of which is U+00a0, which isn't
+                   * interesting; so we return the second. More
+                   * sophisticated handling is the job of a
+                   * GtkIMContext.
+                   *
+                   * If state isn't zero, it means that it's a dead
+                   * key of some sort. Some of those are enumerated in
+                   * the special_ucs_table with the high nibble set to
+                   * f to push it into the private use range. Here we
+                   * do the same.
+                   */
+                  if (state != 0)
+                    chars[nChars - 1] |= 0xf000;
+                  uc = chars[nChars - 1];
+
+                  for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
+                    {
+                      if (special_ucs_table[k].ucs_value == uc)
+                        {
+                          p[j] = special_ucs_table[k].keyval;
+                          found = TRUE;
+                          break;
+                        }
+                    }
+
+                  /* Special-case shift-tab since GTK+ expects
+                   * GDK_KEY_ISO_Left_Tab for that.
+                   */
+                  if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
+                    p[j] = GDK_KEY_ISO_Left_Tab;
+
+                  if (!found)
+                    p[j] = gdk_unicode_to_keyval (uc);
+                }
+            }
+
+          if (p[3] == p[2])
+            p[3] = 0;
+          if (p[2] == p[1])
+            p[2] = 0;
+          if (p[1] == p[0])
+            p[1] = 0;
+          if (p[0] == p[2] &&
+              p[1] == p[3])
+            p[2] = p[3] = 0;
+        }
+#ifndef __LP64__
+    }
+  else
+    {
+      g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
+               " - not supported right now");
+    }
+#endif
+
+  for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
+    {
+      p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
+
+      if (p[0] == 0 && p[1] == 0 &&
+          p[2] == 0 && p[3] == 0)
+        p[0] = modifier_keys[i].keyval;
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
+    {
+      p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
+
+      p[0] = function_keys[i].keyval;
+      p[1] = p[2] = p[3] = 0;
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
+    {
+      p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
+
+      if (p[0] == known_numeric_keys[i].normal_keyval)
+        p[0] = known_numeric_keys[i].keypad_keyval;
+    }
+
+  g_signal_emit_by_name (self, "keys-changed");
+}
+
+static PangoDirection
+gdk_macos_keymap_get_direction (GdkKeymap *keymap)
+{
+  return PANGO_DIRECTION_NEUTRAL;
+}
+
+static gboolean
+gdk_macos_keymap_have_bidi_layouts (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static gboolean
+gdk_macos_keymap_get_caps_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static gboolean
+gdk_macos_keymap_get_num_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static gboolean
+gdk_macos_keymap_get_scroll_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static guint
+gdk_macos_keymap_lookup_key (GdkKeymap          *keymap,
+                             const GdkKeymapKey *key)
+{
+  GdkMacosKeymap *self = (GdkMacosKeymap *)keymap;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (self));
+  g_assert (key != NULL);
+
+  return GET_KEYVAL (key->keycode, key->group, key->level);
+}
+
+static guint
+translate_keysym (guint            hardware_keycode,
+                  gint             group,
+                  GdkModifierType  state,
+                  gint            *effective_group,
+                  gint            *effective_level)
+{
+  gint level;
+  guint tmp_keyval;
+
+  level = (state & GDK_SHIFT_MASK) ? 1 : 0;
+
+  if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
+      (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
+    group = 0;
+
+  if (!GET_KEYVAL (hardware_keycode, group, level) &&
+      GET_KEYVAL (hardware_keycode, group, 0))
+    level = 0;
+
+  tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
+
+  if (state & GDK_LOCK_MASK)
+    {
+      guint upper = gdk_keyval_to_upper (tmp_keyval);
+      if (upper != tmp_keyval)
+        tmp_keyval = upper;
+    }
+
+  if (effective_group)
+    *effective_group = group;
+  if (effective_level)
+    *effective_level = level;
+
+  return tmp_keyval;
+}
+
+static gboolean
+gdk_macos_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
+                                         guint          keyval,
+                                         GdkKeymapKey **keys,
+                                         gint          *n_keys)
+{
+  GArray *keys_array;
+  guint i;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (keymap));
+  g_assert (keys != NULL);
+  g_assert (n_keys != NULL);
+
+  *n_keys = 0;
+  keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
+
+  for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
+    {
+      GdkKeymapKey key;
+
+      if (keyval_array[i] != keyval)
+       continue;
+
+      (*n_keys)++;
+
+      key.keycode = i / KEYVALS_PER_KEYCODE;
+      key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
+      key.level = i % 2;
+
+      g_array_append_val (keys_array, key);
+    }
+
+  *keys = (GdkKeymapKey *)(gpointer)g_array_free (keys_array, FALSE);
+  
+  return *n_keys > 0;
+}
+
+static gboolean
+gdk_macos_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
+                                          guint          hardware_keycode,
+                                          GdkKeymapKey **keys,
+                                          guint        **keyvals,
+                                          gint          *n_entries)
+{
+  GArray *keys_array;
+  GArray *keyvals_array;
+  guint *p;
+  guint i;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (keymap));
+  g_assert (keys != NULL);
+  g_assert (keyvals != NULL);
+  g_assert (n_entries != NULL);
+
+  *keys = NULL;
+  *keyvals = NULL;
+  *n_entries = 0;
+
+  if (hardware_keycode > NUM_KEYCODES)
+    return FALSE;
+
+  if (keys)
+    keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
+  else
+    keys_array = NULL;
+
+  if (keyvals)
+    keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
+  else
+    keyvals_array = NULL;
+
+  p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
+  
+  for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
+    {
+      if (!p[i])
+       continue;
+
+      (*n_entries)++;
+      
+      if (keyvals_array)
+       g_array_append_val (keyvals_array, p[i]);
+
+      if (keys_array)
+       {
+         GdkKeymapKey key;
+
+         key.keycode = hardware_keycode;
+         key.group = i >= 2;
+         key.level = i % 2;
+
+         g_array_append_val (keys_array, key);
+       }
+    }
+  
+  if (keys)
+    *keys = (GdkKeymapKey *)(gpointer)g_array_free (keys_array, FALSE);
+
+  if (keyvals)
+    *keyvals = (guint *)(gpointer)g_array_free (keyvals_array, FALSE);
+
+  return *n_entries > 0;
+}
+
+static gboolean
+gdk_macos_keymap_translate_keyboard_state (GdkKeymap       *keymap,
+                                           guint            hardware_keycode,
+                                           GdkModifierType  state,
+                                           gint             group,
+                                           guint           *keyval,
+                                           gint            *effective_group,
+                                           gint            *level,
+                                           GdkModifierType *consumed_modifiers)
+{
+  guint tmp_keyval;
+  GdkModifierType bit;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (keymap));
+
+  if (keyval)
+    *keyval = 0;
+  if (effective_group)
+    *effective_group = 0;
+  if (level)
+    *level = 0;
+  if (consumed_modifiers)
+    *consumed_modifiers = 0;
+
+  if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
+    return FALSE;
+
+  tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
+
+  /* Check if modifiers modify the keyval */
+  if (consumed_modifiers)
+    {
+      guint tmp_modifiers = (state & GDK_MODIFIER_MASK);
+
+      for (bit = 1; bit <= tmp_modifiers; bit <<= 1)
+        {
+          if ((bit & tmp_modifiers) &&
+              translate_keysym (hardware_keycode, group, state & ~bit,
+                                NULL, NULL) == tmp_keyval)
+            tmp_modifiers &= ~bit;
+        }
+
+      *consumed_modifiers = tmp_modifiers;
+    }
+
+  if (keyval)
+    *keyval = tmp_keyval; 
+
+  return TRUE;
+}
+
+static void
+input_sources_changed_notification (CFNotificationCenterRef  center,
+                                    void                    *observer,
+                                    CFStringRef              name,
+                                    const void              *object,
+                                    CFDictionaryRef          userInfo)
+{
+  GdkMacosKeymap *self = observer;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (self));
+  
+  gdk_macos_keymap_update (self);
+}
+
+static void
+gdk_macos_keymap_finalize (GObject *object)
+{
+  CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
+                                      object,
+                                      CFSTR ("AppleSelectedInputSourcesChangedNotification"),
+                                      NULL);
+
+  G_OBJECT_CLASS (gdk_macos_keymap_parent_class)->finalize (object);
+}
+
+static void
+gdk_macos_keymap_class_init (GdkMacosKeymapClass *klass)
+{
+  GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_macos_keymap_finalize;
+
+  keymap_class->get_caps_lock_state = gdk_macos_keymap_get_caps_lock_state;
+  keymap_class->get_direction = gdk_macos_keymap_get_direction;
+  keymap_class->get_entries_for_keycode = gdk_macos_keymap_get_entries_for_keycode;
+  keymap_class->get_entries_for_keyval = gdk_macos_keymap_get_entries_for_keyval;
+  keymap_class->get_num_lock_state = gdk_macos_keymap_get_num_lock_state;
+  keymap_class->get_scroll_lock_state = gdk_macos_keymap_get_scroll_lock_state;
+  keymap_class->have_bidi_layouts = gdk_macos_keymap_have_bidi_layouts;
+  keymap_class->lookup_key = gdk_macos_keymap_lookup_key;
+  keymap_class->translate_keyboard_state = gdk_macos_keymap_translate_keyboard_state;
+}
+
+static void
+gdk_macos_keymap_init (GdkMacosKeymap *self)
+{
+  CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
+                                   self,
+                                   input_sources_changed_notification,
+                                   CFSTR ("AppleSelectedInputSourcesChangedNotification"),
+                                   NULL,
+                                   CFNotificationSuspensionBehaviorDeliverImmediately);
+  gdk_macos_keymap_update (self);
+}
+
+GdkMacosKeymap *
+_gdk_macos_keymap_new (GdkMacosDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  return g_object_new (GDK_TYPE_MACOS_KEYMAP,
+                       "display", display,
+                       NULL);
+}
diff --git a/gdk/macos/gdkmacoskeymap.h b/gdk/macos/gdkmacoskeymap.h
new file mode 100644
index 0000000000..6a8a7e288f
--- /dev/null
+++ b/gdk/macos/gdkmacoskeymap.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_KEYMAP_H__
+#define __GDK_MACOS_KEYMAP_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosKeymap      GdkMacosKeymap;
+typedef struct _GdkMacosKeymapClass GdkMacosKeymapClass;
+
+#define GDK_TYPE_MACOS_KEYMAP       (gdk_macos_keymap_get_type())
+#define GDK_MACOS_KEYMAP(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_KEYMAP, 
GdkMacosKeymap))
+#define GDK_IS_MACOS_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_KEYMAP))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_keymap_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_KEYMAP_H__ */
diff --git a/gdk/macos/gdkmacosmonitor-private.h b/gdk/macos/gdkmacosmonitor-private.h
new file mode 100644
index 0000000000..ef5721e27d
--- /dev/null
+++ b/gdk/macos/gdkmacosmonitor-private.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_MONITOR_PRIVATE_H__
+#define __GDK_MACOS_MONITOR_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacosmonitor.h"
+
+#include "gdkmonitorprivate.h"
+
+G_BEGIN_DECLS
+
+struct _GdkMacosMonitor
+{
+  GdkMonitor parent_instance;
+};
+
+struct _GdkMacosMonitorClass
+{
+  GdkMonitorClass parent_class;
+};
+
+GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay   *display,
+                                         CGDirectDisplayID  monitor_id);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_MONITOR_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosmonitor.c b/gdk/macos/gdkmacosmonitor.c
new file mode 100644
index 0000000000..37dc40274e
--- /dev/null
+++ b/gdk/macos/gdkmacosmonitor.c
@@ -0,0 +1,58 @@
+/*
+ * 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"
+
+#include <gdk/gdk.h>
+
+#include "gdkmacosmonitor-private.h"
+
+G_DEFINE_TYPE (GdkMacosMonitor, gdk_macos_monitor, GDK_TYPE_MONITOR)
+
+static void
+gdk_macos_monitor_finalize (GObject *object)
+{
+  GdkMacosMonitor *self = (GdkMacosMonitor *)object;
+
+  G_OBJECT_CLASS (gdk_macos_monitor_parent_class)->finalize (object);
+}
+
+static void
+gdk_macos_monitor_class_init (GdkMacosMonitorClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_macos_monitor_finalize;
+}
+
+static void
+gdk_macos_monitor_init (GdkMacosMonitor *self)
+{
+}
+
+GdkMacosMonitor *
+_gdk_macos_monitor_new (GdkMacosDisplay   *display,
+                        CGDirectDisplayID  screen_id)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  return g_object_new (GDK_TYPE_MACOS_MONITOR,
+                       "display", display,
+                       NULL);
+}
diff --git a/gdk/macos/gdkmacosmonitor.h b/gdk/macos/gdkmacosmonitor.h
new file mode 100644
index 0000000000..64b91f887e
--- /dev/null
+++ b/gdk/macos/gdkmacosmonitor.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_MONITOR_H__
+#define __GDK_MACOS_MONITOR_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosMonitor      GdkMacosMonitor;
+typedef struct _GdkMacosMonitorClass GdkMacosMonitorClass;
+
+#define GDK_TYPE_MACOS_MONITOR       (gdk_macos_monitor_get_type())
+#define GDK_MACOS_MONITOR(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_MONITOR, 
GdkMacosMonitor))
+#define GDK_IS_MACOS_MONITOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_MONITOR))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_monitor_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_MONITOR_H__ */
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
new file mode 100644
index 0000000000..2081a8f52f
--- /dev/null
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -0,0 +1,37 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_SURFACE_PRIVATE_H__
+#define __GDK_MACOS_SURFACE_PRIVATE_H__
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacossurface.h"
+
+G_BEGIN_DECLS
+
+GdkMacosSurface *_gdk_macos_surface_new (GdkMacosDisplay *display,
+                                         GdkSurfaceType   surface_type,
+                                         int              x,
+                                         int              y,
+                                         int              width,
+                                         int              height);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_SURFACE_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
new file mode 100644
index 0000000000..a61f8008c0
--- /dev/null
+++ b/gdk/macos/gdkmacossurface.c
@@ -0,0 +1,74 @@
+/*
+ * 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"
+
+#include <AppKit/AppKit.h>
+#include <gdk/gdk.h>
+
+#include "gdksurfaceprivate.h"
+#include "gdkmacossurface-private.h"
+
+struct _GdkMacosSurface
+{
+  GdkSurface parent_instance;
+};
+
+struct _GdkMacosSurfaceClass
+{
+  GdkSurfaceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMacosSurface, gdk_macos_surface, GDK_TYPE_SURFACE)
+
+static void
+gdk_macos_surface_finalize (GObject *object)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)object;
+
+  G_OBJECT_CLASS (gdk_macos_surface_parent_class)->finalize (object);
+}
+
+static void
+gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_macos_surface_finalize;
+}
+
+static void
+gdk_macos_surface_init (GdkMacosSurface *self)
+{
+}
+
+GdkMacosSurface *
+_gdk_macos_surface_new (GdkMacosDisplay   *display,
+                        GdkSurfaceType     surface_type,
+                        int                x,
+                        int                y,
+                        int                width,
+                        int                height)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  return g_object_new (GDK_TYPE_MACOS_SURFACE,
+                       "display", display,
+                       NULL);
+}
diff --git a/gdk/macos/gdkmacossurface.h b/gdk/macos/gdkmacossurface.h
new file mode 100644
index 0000000000..81b59689ad
--- /dev/null
+++ b/gdk/macos/gdkmacossurface.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_SURFACE_H__
+#define __GDK_MACOS_SURFACE_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosSurface      GdkMacosSurface;
+typedef struct _GdkMacosSurfaceClass GdkMacosSurfaceClass;
+
+#define GDK_TYPE_MACOS_SURFACE       (gdk_macos_surface_get_type())
+#define GDK_MACOS_SURFACE(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_SURFACE, 
GdkMacosSurface))
+#define GDK_IS_MACOS_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_SURFACE))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_surface_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_SURFACE_H__ */
diff --git a/gdk/macos/gdkmacosutils-private.h b/gdk/macos/gdkmacosutils-private.h
new file mode 100644
index 0000000000..49185551a4
--- /dev/null
+++ b/gdk/macos/gdkmacosutils-private.h
@@ -0,0 +1,29 @@
+/*
+ * 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
+ */
+
+#ifndef __GDK_MACOS_UTILS_PRIVATE_H__
+#define __GDK_MACOS_UTILS_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+#include <gdk/gdk.h>
+
+#define GDK_BEGIN_MACOS_ALLOC_POOL NSAutoreleasePool *_pool = [[NSAutoreleasePool alloc] init]
+#define GDK_END_MACOS_ALLOC_POOL   [_pool release]
+
+#endif /* __GDK_MACOS_UTILS_PRIVATE_H__ */
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
new file mode 100644
index 0000000000..55a702eed0
--- /dev/null
+++ b/gdk/macos/meson.build
@@ -0,0 +1,45 @@
+gdk_macos_sources = files([
+  'gdkmacosdisplay.c',
+  'gdkmacoskeymap.c',
+  'gdkmacosmonitor.c',
+  'gdkmacossurface.c',
+
+  # 'gdkapplaunchcontext-macos.c',
+  # 'gdkcairocontext-macos.c',
+  # 'gdkclipboard-macos.c',
+  # 'gdkcursor-macos.c',
+  # 'gdkdevice-macos.c',
+  # 'gdkdrag-macos.c',
+  # 'gdkdrop-macos.c',
+  # 'gdkeventsource.c',
+  # 'gdkglcontext-macos.c',
+  # 'gdkkeys-macos.c',
+  # 'gdkprimary-macos.c',
+  # 'gdksurface-macos.c',
+])
+
+gdk_macos_public_headers = files([
+  'gdkmacosdisplay.h',
+  'gdkmacosmonitor.h',
+  'gdkmacoskeymap.h',
+
+  # 'gdkmacosdevice.h',
+  # 'gdkmacosglcontext.h',
+])
+
+install_headers(gdk_macos_public_headers, 'gdkmacos.h', subdir: 'gtk-4.0/gdk/macos/')
+
+gdk_macos_deps = [
+]
+
+libgdk_macos = static_library('gdk-macos',
+                                gdk_macos_sources, gdkconfig, gdkenum_h,
+                                include_directories: [ confinc, gdkinc, ],
+                                c_args: [
+                                  '-DGTK_COMPILATION',
+                                  '-DG_LOG_DOMAIN="Gdk"',
+                                  '-xobjective-c',
+                                ] + common_cflags,
+                                link_args: common_ldflags,
+                                link_with: [],
+                                dependencies: [ gdk_deps, gdk_macos_deps])
diff --git a/gdk/meson.build b/gdk/meson.build
index ac14c3b6fe..5835c0fbbf 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -143,6 +143,7 @@ gdkconfig_cdata.set('GDK_WINDOWING_X11', x11_enabled)
 gdkconfig_cdata.set('GDK_WINDOWING_WAYLAND', wayland_enabled)
 gdkconfig_cdata.set('GDK_WINDOWING_WIN32', win32_enabled)
 gdkconfig_cdata.set('GDK_WINDOWING_BROADWAY', broadway_enabled)
+gdkconfig_cdata.set('GDK_WINDOWING_MACOS', macos_enabled)
 gdkconfig_cdata.set('GDK_RENDERING_VULKAN', have_vulkan)
 
 gdkconfig = configure_file(
@@ -218,7 +219,7 @@ endif
 
 gdk_backends = []
 gdk_backends_gen_headers = []  # non-public generated headers
-foreach backend : ['broadway', 'quartz', 'wayland', 'win32', 'x11']
+foreach backend : ['broadway', 'quartz', 'wayland', 'win32', 'x11', 'macos']
   if get_variable('@0@_enabled'.format(backend))
     subdir(backend)
     gdk_deps += get_variable('gdk_@0@_deps'.format(backend))
diff --git a/meson.build b/meson.build
index 12388f743a..c5c431a17a 100644
--- a/meson.build
+++ b/meson.build
@@ -93,6 +93,7 @@ gtk_api_version = '4.0'
 x11_enabled      = get_option('x11-backend')
 wayland_enabled  = get_option('wayland-backend')
 broadway_enabled = get_option('broadway-backend')
+macos_enabled    = get_option('macos-backend')
 quartz_enabled   = get_option('quartz-backend')
 win32_enabled    = get_option('win32-backend')
 
@@ -242,6 +243,8 @@ if cc.get_id() == 'msvc'
 elif cc.get_id() == 'gcc' or cc.get_id() == 'clang'
   test_cflags = [
     '-fno-strict-aliasing',
+    '-Wno-c++11-extensions',
+    '-Wno-missing-include-dirs',
     '-Wno-typedef-redefinition',
     '-Wcast-align',
     '-Wduplicated-branches',
@@ -368,7 +371,8 @@ pangocairo_dep = dependency('pangocairo', version: cairo_req,
 pixbuf_dep     = dependency('gdk-pixbuf-2.0', version: gdk_pixbuf_req,
                             fallback : ['gdk-pixbuf', 'gdkpixbuf_dep'])
 epoxy_dep      = dependency('epoxy', version: epoxy_req,
-                            fallback: ['libepoxy', 'libepoxy_dep'])
+                            fallback: ['libepoxy', 'libepoxy_dep'],
+                            static: false)
 atk_dep        = dependency('atk', version: atk_req)
 harfbuzz_dep   = dependency('harfbuzz', version: '>= 0.9', required: false)
 xkbdep         = dependency('xkbcommon', version: xkbcommon_req, required: wayland_enabled)
@@ -775,7 +779,7 @@ pkg_install_dir = join_paths(get_option('libdir'), 'pkgconfig')
 pkgs = [ 'gtk4.pc' ]
 
 pkg_targets = ''
-foreach backend: [ 'broadway', 'quartz', 'wayland', 'win32', 'x11', ]
+foreach backend: [ 'broadway', 'quartz', 'macos', 'wayland', 'win32', 'x11', ]
   if get_variable('@0@_enabled'.format(backend))
     pkgs += ['gtk4-@0@.pc'.format(backend)]
     pkg_targets += ' ' + backend
diff --git a/meson_options.txt b/meson_options.txt
index 73f26da7da..61c8930ab3 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -9,6 +9,8 @@ option('win32-backend', type: 'boolean', value: true,
   description : 'Enable the Windows gdk backend (only when building on Windows)')
 option('quartz-backend', type: 'boolean', value: true,
   description : 'Enable the macOS gdk backend (only when building on macOS)')
+option('macos-backend', type: 'boolean', value: true,
+  description : 'Enable the macOS gdk backend (only when building on macOS)')
 
 # Media backends
 option('media', type: 'string', value: 'gstreamer',


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