[gimp] app: Port to gtk-mac-integration



commit e56344294c90e1ba97de5c134b50c4c522f0808f
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

 app/Makefile.am        |   27 +-
 app/gui/Makefile.am    |   10 +-
 app/gui/gui-unique.c   |  163 +++++---
 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, 177 insertions(+), 1145 deletions(-)
---
diff --git a/app/Makefile.am b/app/Makefile.am
index 80eaac0..2f9e9b5 100644
--- a/app/Makefile.am
+++ b/app/Makefile.am
@@ -88,7 +88,7 @@ gimp_ GIMP_APP_VERSION@_SOURCES = $(libapp_sources) main.c
 
 
 if PLATFORM_OSX
-framework_carbon = -framework Carbon
+framework_cocoa = -framework Cocoa
 endif
 
 if OS_WIN32
@@ -184,21 +184,22 @@ gimpconsoleldadd = \
 gimp_ GIMP_APP_VERSION@_LDFLAGS = \
        $(AM_LDFLAGS)           \
        $(win32_ldflags)        \
-       $(framework_carbon)     \
+       $(framework_cocoa)      \
        -Wl,-u,$(SYMPREFIX)gimp_lebl_dialog
 
 gimp_ GIMP_APP_VERSION@_LDADD = \
-       gui/libappgui.a         \
-       menus/libappmenus.a     \
-       actions/libappactions.a \
-       dialogs/libappdialogs.a \
-       tools/libapptools.a     \
-       display/libappdisplay.a \
-       widgets/libappwidgets.a \
-       $(libgimpwidgets)       \
-       $(GTK_LIBS)             \
-       $(DBUS_GLIB_LIBS)       \
-       $(gimpconsoleldadd)     \
+       gui/libappgui.a                 \
+       menus/libappmenus.a             \
+       actions/libappactions.a         \
+       dialogs/libappdialogs.a         \
+       tools/libapptools.a             \
+       display/libappdisplay.a         \
+       widgets/libappwidgets.a         \
+       $(libgimpwidgets)               \
+       $(GTK_LIBS)                     \
+       $(GTK_MAC_INTEGRATION_LIBS)     \
+       $(DBUS_GLIB_LIBS)               \
+       $(gimpconsoleldadd)             \
        $(GIMPRC)
 
 
diff --git a/app/gui/Makefile.am b/app/gui/Makefile.am
index 6717b3a..8487b5d 100644
--- a/app/gui/Makefile.am
+++ b/app/gui/Makefile.am
@@ -1,5 +1,9 @@
 ## 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 \"       \
@@ -7,9 +11,11 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)                         \
        -I$(top_builddir)/app                   \
        -I$(top_srcdir)/app                     \
+       $(xobjective_c)                         \
        $(GIO_UNIX_CFLAGS)                      \
        $(GEGL_CFLAGS)                          \
        $(GTK_CFLAGS)                           \
+       $(GTK_MAC_INTEGRATION_CFLAGS)           \
        $(DBUS_GLIB_CFLAGS)                     \
        -I$(includedir)
 
@@ -36,9 +42,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-generated.c     \
diff --git a/app/gui/gui-unique.c b/app/gui/gui-unique.c
index 8298761..5585d58 100644
--- a/app/gui/gui-unique.c
+++ b/app/gui/gui-unique.c
@@ -25,8 +25,8 @@
 #endif
 
 #ifdef GDK_WINDOWING_QUARTZ
-#include <Carbon/Carbon.h>
-#include <sys/param.h>
+#import <AppKit/AppKit.h>
+#include <gtkosxapplication.h>
 #endif
 
 #include "gui/gui-types.h"
@@ -52,11 +52,16 @@ static HWND  proxy_window = NULL;
 
 #elif defined (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;
 
 #else
 
@@ -75,7 +80,7 @@ gui_unique_init (Gimp *gimp)
 #ifdef G_OS_WIN32
   gui_unique_win32_init (gimp);
 #elif defined (GDK_WINDOWING_QUARTZ)
-  gui_unique_mac_init (gimp);
+  gui_unique_quartz_init (gimp);
 #else
   gui_dbus_service_init (gimp);
 #endif
@@ -87,7 +92,7 @@ gui_unique_exit (void)
 #ifdef G_OS_WIN32
   gui_unique_win32_exit ();
 #elif defined (GDK_WINDOWING_QUARTZ)
-  gui_unique_mac_exit ();
+  gui_unique_quartz_exit ();
 #else
   gui_dbus_service_exit ();
 #endif
@@ -228,7 +233,7 @@ gui_unique_win32_exit (void)
 #elif defined (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.
@@ -236,94 +241,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);
+
+  g_object_watch_closure (G_OBJECT (unique_gimp), closure);
 
-          status = AEGetNthPtr (&documents, i + 1, typeFSRef,
-                                0, 0, &ref, sizeof (ref),
-                                0);
-          if (status != noErr)
-            continue;
+  source = g_idle_source_new ();
 
-          FSRefMakePath (&ref, (UInt8 *) path, MAXPATHLEN);
+  g_source_set_priority (source, G_PRIORITY_LOW);
+  g_source_set_closure (source, closure);
+  g_source_attach (source, NULL);
+  g_source_unref (source);
 
-          callback_path = g_strdup (path);
+  return TRUE;
+}
 
-          closure = g_cclosure_new (G_CALLBACK (gui_unique_mac_idle_open),
-                                    (gpointer) callback_path,
-                                    (GClosureNotify) g_free);
+ implementation GimpAppleEventHandler
+- (void) handleEvent: (NSAppleEventDescriptor *) inEvent
+        andReplyWith: (NSAppleEventDescriptor *) replyEvent
+{
+  const gchar       *path;
+  NSURL             *url;
+  NSAutoreleasePool *urlpool;
+  NSInteger          count;
+  NSInteger          i;
 
-          g_object_watch_closure (G_OBJECT (unique_gimp), closure);
+  urlpool = [[NSAutoreleasePool alloc] init];
 
-          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);
-        }
+  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;
 }
 
 #else
diff --git a/app/gui/gui.c b/app/gui/gui.c
index b6825f5..6314d46 100644
--- a/app/gui/gui.c
+++ b/app/gui/gui.c
@@ -78,7 +78,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"
@@ -429,17 +429,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
 
@@ -470,47 +479,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 0808bf3..7d6fd74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,6 +64,7 @@ m4_define([lcms_required_version], [2.2])
 m4_define([libpng_required_version], [1.2.37])
 m4_define([liblzma_required_version], [5.0.0])
 m4_define([openexr_required_version], [1.6.1])
+m4_define([gtk_mac_integration_required_version], [1.0.1])
 
 
 AC_INIT([GIMP], [gimp_version],
@@ -1782,6 +1783,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]