[gimp/gimp-2-8] app: Port to gtk-mac-integration



commit 2d548c71df2e62bd345e02f50e5a3c1b08a1cf1e
Author: Daniel Sabo <DanielSabo gmail com>
Date:   Sat Nov 9 21:00:55 2013 +0100

    app: Port to gtk-mac-integration
    
    Replace deprecated Carbon APIs with Cocoa.
    
    Includes code by:
    Simone Karin Lehmann
    Michael Natterer
    Daniel Sabo
    
    (cherry picked from commit e56344294c90e1ba97de5c134b50c4c522f0808f)

 app/Makefile.am        |    4 +-
 app/gui/Makefile.am    |   24 +-
 app/gui/gui-unique.c   |  175 +++++----
 app/gui/gui.c          |   82 +++--
 app/gui/ige-mac-menu.c |  988 ------------------------------------------------
 app/gui/ige-mac-menu.h |   43 ---
 configure.ac           |    9 +
 7 files changed, 176 insertions(+), 1149 deletions(-)
---
diff --git a/app/Makefile.am b/app/Makefile.am
index a4ef552..a2a1bde 100644
--- a/app/Makefile.am
+++ b/app/Makefile.am
@@ -90,7 +90,7 @@ gimp_2_8_SOURCES = $(libapp_sources) main.c
 
 
 if PLATFORM_OSX
-framework_carbon = -framework Carbon
+framework_cocoa = -framework Cocoa
 endif
 
 if OS_WIN32
@@ -186,7 +186,7 @@ gimpconsoleldadd = \
 gimp_2_8_LDFLAGS = \
        $(AM_LDFLAGS)           \
        $(win32_ldflags)        \
-       $(framework_carbon)
+       $(framework_cocoa)
 
 gimp_2_8_LDADD = \
        gui/libappgui.a         \
diff --git a/app/gui/Makefile.am b/app/gui/Makefile.am
index 10f9c32..d2b07d5 100644
--- a/app/gui/Makefile.am
+++ b/app/gui/Makefile.am
@@ -1,17 +1,23 @@
 ## Process this file with automake to produce Makefile.in
 
+if PLATFORM_OSX
+xobjective_c = "-xobjective-c"
+endif
+
 AM_CPPFLAGS = \
        -DG_LOG_DOMAIN=\"Gimp-GUI\"     \
        -DGIMP_COMMAND=\"@GIMP_COMMAND \"
 
 INCLUDES = \
-       -I$(top_builddir)       \
-       -I$(top_srcdir)         \
-       -I$(top_builddir)/app   \
-       -I$(top_srcdir)/app     \
-       $(GEGL_CFLAGS)          \
-       $(GTK_CFLAGS)           \
-       $(DBUS_GLIB_CFLAGS)     \
+       -I$(top_builddir)               \
+       -I$(top_srcdir)                 \
+       -I$(top_builddir)/app           \
+       -I$(top_srcdir)/app             \
+       $(xobjective_c)                 \
+       $(GEGL_CFLAGS)                  \
+       $(GTK_CFLAGS)                   \
+       $(DBUS_GLIB_CFLAGS)             \
+       $(GTK_MAC_INTEGRATION_CFLAGS)   \
        -I$(includedir)
 
 noinst_LIBRARIES = libappgui.a
@@ -37,9 +43,7 @@ libappgui_a_sources = \
        splash.c                \
        splash.h                \
        themes.c                \
-       themes.h                \
-       ige-mac-menu.c          \
-       ige-mac-menu.h
+       themes.h
 
 libappgui_a_built_sources = gimpdbusservice-glue.h 
 
diff --git a/app/gui/gui-unique.c b/app/gui/gui-unique.c
index 122d0f6..5218d78 100644
--- a/app/gui/gui-unique.c
+++ b/app/gui/gui-unique.c
@@ -24,8 +24,8 @@
 #endif
 
 #ifdef GDK_WINDOWING_QUARTZ
-#include <Carbon/Carbon.h>
-#include <sys/param.h>
+#import <AppKit/AppKit.h>
+#include <gtkosxapplication.h>
 #endif
 
 #if HAVE_DBUS_GLIB
@@ -63,11 +63,16 @@ static HWND             proxy_window     = NULL;
 #endif
 
 #ifdef GDK_WINDOWING_QUARTZ
-static void  gui_unique_mac_init (Gimp *gimp);
-static void  gui_unique_mac_exit (void);
+static void gui_unique_quartz_init (Gimp *gimp);
+static void gui_unique_quartz_exit (void);
 
-static Gimp            *unique_gimp      = NULL;
-AEEventHandlerUPP       open_document_callback_proc;
+ interface GimpAppleEventHandler : NSObject {}
+- (void) handleEvent:(NSAppleEventDescriptor *) inEvent
+        andReplyWith:(NSAppleEventDescriptor *) replyEvent;
+ end
+
+static Gimp                   *unique_gimp   = NULL;
+static GimpAppleEventHandler  *event_handler = NULL;
 #endif
 
 
@@ -76,13 +81,11 @@ gui_unique_init (Gimp *gimp)
 {
 #ifdef G_OS_WIN32
   gui_unique_win32_init (gimp);
-#elif HAVE_DBUS_GLIB
+#elif defined (GDK_WINDOWING_QUARTZ)
+  gui_unique_quartz_init (gimp);
+#elif defined (HAVE_DBUS_GLIB)
   gui_dbus_service_init (gimp);
 #endif
-
-#ifdef GDK_WINDOWING_QUARTZ
-  gui_unique_mac_init (gimp);
-#endif
 }
 
 void
@@ -90,13 +93,11 @@ gui_unique_exit (void)
 {
 #ifdef G_OS_WIN32
   gui_unique_win32_exit ();
-#elif HAVE_DBUS_GLIB
+#elif defined (GDK_WINDOWING_QUARTZ)
+  gui_unique_quartz_exit ();
+#elif defined (HAVE_DBUS_GLIB)
   gui_dbus_service_exit ();
 #endif
-
-#ifdef GDK_WINDOWING_QUARTZ
-  gui_unique_mac_exit ();
-#endif
 }
 
 
@@ -280,7 +281,7 @@ gui_unique_win32_exit (void)
 #ifdef GDK_WINDOWING_QUARTZ
 
 static gboolean
-gui_unique_mac_idle_open (gchar *data)
+gui_unique_quartz_idle_open (gchar *path)
 {
   /*  We want to be called again later in case that GIMP is not fully
    *  started yet.
@@ -288,94 +289,126 @@ gui_unique_mac_idle_open (gchar *data)
   if (! gimp_is_restored (unique_gimp))
     return TRUE;
 
-  if (data)
+  if (path)
     {
-      file_open_from_command_line (unique_gimp, data, FALSE);
+      file_open_from_command_line (unique_gimp, path, FALSE);
     }
 
   return FALSE;
 }
 
-/* Handle the kAEOpenDocuments Apple events. This will register
- * an idle source callback for each filename in the event.
- */
-static pascal OSErr
-gui_unique_mac_open_documents (const AppleEvent *inAppleEvent,
-                               AppleEvent       *outAppleEvent,
-                               long              handlerRefcon)
+static gboolean
+gui_unique_quartz_nsopen_file_callback (GtkosxApplication *osx_app,
+                                        gchar             *path,
+                                        gpointer           user_data)
 {
-  OSStatus    status;
-  AEDescList  documents;
-  gchar       path[MAXPATHLEN];
-
-  status = AEGetParamDesc (inAppleEvent,
-                           keyDirectObject, typeAEList,
-                           &documents);
-  if (status == noErr)
-    {
-      long count = 0;
-      int  i;
+  gchar    *callback_path;
+  GSource  *source;
+  GClosure *closure;
 
-      AECountItems (&documents, &count);
+  callback_path = g_strdup (path);
 
-      for (i = 0; i < count; i++)
-        {
-          FSRef    ref;
-          gchar    *callback_path;
-          GSource  *source;
-          GClosure *closure;
+  closure = g_cclosure_new (G_CALLBACK (gui_unique_quartz_idle_open),
+                            (gpointer) callback_path,
+                            (GClosureNotify) g_free);
 
-          status = AEGetNthPtr (&documents, i + 1, typeFSRef,
-                                0, 0, &ref, sizeof (ref),
-                                0);
-          if (status != noErr)
-            continue;
+  g_object_watch_closure (G_OBJECT (unique_gimp), closure);
 
-          FSRefMakePath (&ref, (UInt8 *) path, MAXPATHLEN);
+  source = g_idle_source_new ();
 
-          callback_path = g_strdup (path);
+  g_source_set_priority (source, G_PRIORITY_LOW);
+  g_source_set_closure (source, closure);
+  g_source_attach (source, NULL);
+  g_source_unref (source);
 
-          closure = g_cclosure_new (G_CALLBACK (gui_unique_mac_idle_open),
-                                    (gpointer) callback_path,
-                                    (GClosureNotify) g_free);
+  return TRUE;
+}
 
-          g_object_watch_closure (G_OBJECT (unique_gimp), closure);
+ implementation GimpAppleEventHandler
+- (void) handleEvent: (NSAppleEventDescriptor *) inEvent
+        andReplyWith: (NSAppleEventDescriptor *) replyEvent
+{
+  const gchar       *path;
+  NSURL             *url;
+  NSAutoreleasePool *urlpool;
+  NSInteger          count;
+  NSInteger          i;
 
-          source = g_idle_source_new ();
-          g_source_set_priority (source, G_PRIORITY_LOW);
-          g_source_set_closure (source, closure);
-          g_source_attach (source, NULL);
-          g_source_unref (source);
-        }
+  urlpool = [[NSAutoreleasePool alloc] init];
+
+  count = [inEvent numberOfItems];
+
+  for (i = 1; i <= count; i++)
+    {
+      gchar    *callback_path;
+      GSource  *source;
+      GClosure *closure;
+
+      url = [NSURL URLWithString: [[inEvent descriptorAtIndex: i] stringValue]];
+      path = [[url path] UTF8String];
+
+      callback_path = g_strdup (path);
+      closure = g_cclosure_new (G_CALLBACK (gui_unique_quartz_idle_open),
+                                (gpointer) callback_path,
+                                (GClosureNotify) g_free);
+
+      g_object_watch_closure (G_OBJECT (unique_gimp), closure);
+
+      source = g_idle_source_new ();
+      g_source_set_priority (source, G_PRIORITY_LOW);
+      g_source_set_closure (source, closure);
+      g_source_attach (source, NULL);
+      g_source_unref (source);
     }
 
-    return status;
+  [urlpool drain];
 }
+ end
 
 static void
-gui_unique_mac_init (Gimp *gimp)
+gui_unique_quartz_init (Gimp *gimp)
 {
+  GtkosxApplication *osx_app;
+
   g_return_if_fail (GIMP_IS_GIMP (gimp));
   g_return_if_fail (unique_gimp == NULL);
 
+  osx_app = gtkosx_application_get ();
+
   unique_gimp = gimp;
 
-  open_document_callback_proc = NewAEEventHandlerUPP(gui_unique_mac_open_documents);
+  g_signal_connect (osx_app, "NSApplicationOpenFile",
+                    G_CALLBACK (gui_unique_quartz_nsopen_file_callback),
+                    gimp);
+
+  /* Using the event handler is a hack, it is neccesary becuase
+   * gtkosx_application will drop the file open events if any
+   * event processing is done before gtkosx_application_ready is
+   * called, which we unfortuantly can't avoid doing right now.
+   */
+  event_handler = [[GimpAppleEventHandler alloc] init];
 
-  AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments,
-                         open_document_callback_proc,
-                         0L, TRUE);
+  [[NSAppleEventManager sharedAppleEventManager]
+      setEventHandler: event_handler
+          andSelector: @selector (handleEvent: andReplyWith:)
+        forEventClass: kCoreEventClass
+           andEventID: kAEOpenDocuments];
 }
 
 static void
-gui_unique_mac_exit (void)
+gui_unique_quartz_exit (void)
 {
+  g_return_if_fail (GIMP_IS_GIMP (unique_gimp));
+
   unique_gimp = NULL;
 
-  AERemoveEventHandler (kCoreEventClass, kAEOpenDocuments,
-                        open_document_callback_proc, TRUE);
+  [[NSAppleEventManager sharedAppleEventManager]
+      removeEventHandlerForEventClass: kCoreEventClass
+                           andEventID: kAEOpenDocuments];
+
+  [event_handler release];
 
-  DisposeAEEventHandlerUPP(open_document_callback_proc);
+  event_handler = NULL;
 }
 
 #endif /* GDK_WINDOWING_QUARTZ */
diff --git a/app/gui/gui.c b/app/gui/gui.c
index f3ad117..faaa91b 100644
--- a/app/gui/gui.c
+++ b/app/gui/gui.c
@@ -77,7 +77,7 @@
 #include "splash.h"
 #include "themes.h"
 #ifdef GDK_WINDOWING_QUARTZ
-#include "ige-mac-menu.h"
+#include <gtkosxapplication.h>
 #endif /* GDK_WINDOWING_QUARTZ */
 
 #include "gimp-intl.h"
@@ -427,17 +427,26 @@ gui_restore_callback (Gimp               *gimp,
 
 #ifdef GDK_WINDOWING_QUARTZ
 static void
-gui_add_to_app_menu (GimpUIManager   *ui_manager,
-                     IgeMacMenuGroup *group,
-                     const gchar     *action_path,
-                     const gchar     *label)
+gui_add_to_app_menu (GimpUIManager     *ui_manager,
+                     GtkosxApplication *osx_app,
+                     const gchar       *action_path,
+                     gint               index)
 {
   GtkWidget *item;
 
   item = gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui_manager), action_path);
 
   if (GTK_IS_MENU_ITEM (item))
-    ige_mac_menu_add_app_menu_item (group, GTK_MENU_ITEM (item), label);
+    gtkosx_application_insert_app_menu_item (osx_app, GTK_WIDGET (item), index);
+}
+
+static gboolean
+gui_quartz_quit_callback (GtkosxApplication *osx_app,
+                          GimpUIManager     *ui_manager)
+{
+  gimp_ui_manager_activate_action (ui_manager, "file", "file-quit");
+
+  return TRUE;
 }
 #endif
 
@@ -468,47 +477,50 @@ gui_restore_after_callback (Gimp               *gimp,
 
 #ifdef GDK_WINDOWING_QUARTZ
   {
-    IgeMacMenuGroup *group;
-    GtkWidget       *menu;
-    GtkWidget       *item;
+    GtkosxApplication *osx_app;
+    GtkWidget         *menu;
+    GtkWidget         *item;
 
-    menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER (image_ui_manager),
-                                     "/dummy-menubar/image-popup");
+    osx_app = gtkosx_application_get ();
 
+    menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER (image_ui_manager),
+                                      "/image-menubar");
     if (GTK_IS_MENU_ITEM (menu))
       menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu));
 
-    ige_mac_menu_set_menu_bar (GTK_MENU_SHELL (menu));
+    gtkosx_application_set_menu_bar (osx_app, GTK_MENU_SHELL (menu));
+    gtkosx_application_set_use_quartz_accelerators (osx_app, FALSE);
 
-    item = gtk_ui_manager_get_widget (GTK_UI_MANAGER (image_ui_manager),
-                                      "/dummy-menubar/image-popup/File/file-quit");
-    if (GTK_IS_MENU_ITEM (item))
-      ige_mac_menu_set_quit_menu_item (GTK_MENU_ITEM (item));
+    gui_add_to_app_menu (image_ui_manager, osx_app,
+                         "/image-menubar/Help/dialogs-about", 0);
+
+#define PREFERENCES "/image-menubar/Edit/Preferences/"
 
-    /*  the about group  */
-    group = ige_mac_menu_add_app_menu_group ();
+    gui_add_to_app_menu (image_ui_manager, osx_app,
+                         PREFERENCES "dialogs-preferences", 2);
+    gui_add_to_app_menu (image_ui_manager, osx_app,
+                         PREFERENCES "dialogs-input-devices", 3);
+    gui_add_to_app_menu (image_ui_manager, osx_app,
+                         PREFERENCES "dialogs-keyboard-shortcuts", 4);
+    gui_add_to_app_menu (image_ui_manager, osx_app,
+                         PREFERENCES "dialogs-module-dialog", 5);
+    gui_add_to_app_menu (image_ui_manager, osx_app,
+                         PREFERENCES "plug-in-unit-editor", 6);
 
-    gui_add_to_app_menu (image_ui_manager, group,
-                         "/dummy-menubar/image-popup/Help/dialogs-about",
-                         _("About GIMP"));
+#undef PREFERENCES
 
-    /*  the preferences group  */
-    group = ige_mac_menu_add_app_menu_group ();
+    item = gtk_separator_menu_item_new ();
+    gtkosx_application_insert_app_menu_item (osx_app, item, 7);
 
-#define PREFERENCES "/dummy-menubar/image-popup/Edit/Preferences/"
+    item = gtk_ui_manager_get_widget (GTK_UI_MANAGER (image_ui_manager),
+                                      "/image-menubar/File/file-quit");
+    gtk_widget_hide (item);
 
-    gui_add_to_app_menu (image_ui_manager, group,
-                         PREFERENCES "dialogs-preferences", NULL);
-    gui_add_to_app_menu (image_ui_manager, group,
-                         PREFERENCES "dialogs-input-devices", NULL);
-    gui_add_to_app_menu (image_ui_manager, group,
-                         PREFERENCES "dialogs-keyboard-shortcuts", NULL);
-    gui_add_to_app_menu (image_ui_manager, group,
-                         PREFERENCES "dialogs-module-dialog", NULL);
-    gui_add_to_app_menu (image_ui_manager, group,
-                         PREFERENCES "plug-in-unit-editor", NULL);
+    g_signal_connect (osx_app, "NSApplicationBlockTermination",
+                      G_CALLBACK (gui_quartz_quit_callback),
+                      image_ui_manager);
 
-#undef PREFERENCES
+    gtkosx_application_ready (osx_app);
   }
 #endif /* GDK_WINDOWING_QUARTZ */
 
diff --git a/configure.ac b/configure.ac
index 712f30f..038b5e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,6 +64,7 @@ m4_define([exif_required_version], [0.6.15])
 m4_define([lcms1_required_version], [1.16])
 m4_define([lcms2_required_version], [2.2])
 m4_define([libpng_required_version], [1.2.37])
+m4_define([gtk_mac_integration_required_version], [1.0.1])
 
 
 AC_INIT([GIMP], [gimp_version],
@@ -1843,6 +1844,14 @@ if test "x$enable_python" != xno; then
 fi
 AM_CONDITIONAL(BUILD_PYTHON, test "x$enable_python" != xno)
 
+####################################
+# Check for GTK Mac Integration
+####################################
+
+if test "x$platform_osx" != xno; then
+  PKG_CHECK_MODULES(GTK_MAC_INTEGRATION, gtk-mac-integration >= gtk_mac_integration_required_version)
+fi
+
 
 #########################################
 # Check whether Script-Fu should be built


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