<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre, #msg p { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[34646] trunk/dports/net/pidgin/files/ige-integration.diff</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.macosforge.org/projects/macports/changeset/34646">34646</a></dd>
<dt>Author</dt> <dd>reiffert@macports.org</dd>
<dt>Date</dt> <dd>2008-03-01 04:15:53 -0800 (Sat, 01 Mar 2008)</dd>
</dl>

<h3>Log Message</h3>
<pre>ige gtk integration patch for later use.</pre>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkdportsnetpidginfilesigeintegrationdiff">trunk/dports/net/pidgin/files/ige-integration.diff</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkdportsnetpidginfilesigeintegrationdiff"></a>
<div class="addfile"><h4>Added: trunk/dports/net/pidgin/files/ige-integration.diff (0 => 34646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/dports/net/pidgin/files/ige-integration.diff                                (rev 0)
+++ trunk/dports/net/pidgin/files/ige-integration.diff        2008-03-01 12:15:53 UTC (rev 34646)
</span><span class="lines">@@ -0,0 +1,2129 @@
</span><ins>+--- pidgin/gtkblist.c        2007-12-07 15:37:11.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/gtkblist.c        2008-02-11 15:59:25.000000000 +0100
+@@ -27,6 +27,9 @@
+ #include &quot;internal.h&quot;
+ #include &quot;pidgin.h&quot;

++#include &quot;ige-mac-menu.h&quot;
++#include &quot;ige-mac-dock.h&quot;
++#include &quot;ige-mac-bundle.h&quot;
+ #include &quot;account.h&quot;
+ #include &quot;connection.h&quot;
+ #include &quot;core.h&quot;
+@@ -5311,6 +5314,7 @@
+         pidgin_blist_restore_position();
+         gtk_widget_show_all(GTK_WIDGET(gtkblist-&gt;vbox));
+         gtk_widget_realize(GTK_WIDGET(gtkblist-&gt;window));
++              ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(menu)); 
+         purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT &quot;/blist/list_visible&quot;));

+         /* start the refresh timer */
+--- pidgin/ige-mac-bundle.c        1970-01-01 01:00:00.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/ige-mac-bundle.c        2008-02-11 14:38:28.000000000 +0100
+@@ -0,0 +1,377 @@
++/* GTK+ Integration for app bundles.
++ *
++ * Copyright (C) 2007-2008 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; version 2.1
++ * of the License.
++ *
++ * 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, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/* TODO: Add command line parsing and remove any
++ * -psn_... arguments?
++ */
++
++#include &lt;gtk/gtk.h&gt;
++#include &lt;Carbon/Carbon.h&gt;
++
++#include &quot;ige-mac-bundle.h&quot;
++
++typedef struct IgeMacBundlePriv IgeMacBundlePriv;
++
++struct IgeMacBundlePriv {
++  CFBundleRef  cf_bundle; 
++  gchar       *path;
++  gchar       *id;
++  gchar       *datadir;
++  gchar       *localedir;
++  UInt32       type;
++  UInt32       creator;
++};
++
++static void   mac_bundle_finalize              (GObject      *object);
++static gchar *cf_string_to_utf8                (CFStringRef   str);
++static void   mac_bundle_set_environment_value (IgeMacBundle *bundle,
++                                                const gchar  *key,
++                                                const gchar  *value);
++
++static IgeMacBundle *global_bundle;
++
++G_DEFINE_TYPE (IgeMacBundle, ige_mac_bundle, G_TYPE_OBJECT)
++
++#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), IGE_TYPE_MAC_BUNDLE, IgeMacBundlePriv))
++
++static void
++ige_mac_bundle_class_init (IgeMacBundleClass *class)
++{
++  GObjectClass *object_class = G_OBJECT_CLASS (class);
++
++  object_class-&gt;finalize = mac_bundle_finalize;
++
++  g_type_class_add_private (object_class, sizeof (IgeMacBundlePriv));
++}
++
++static void
++ige_mac_bundle_init (IgeMacBundle *bundle)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++  CFURLRef          cf_url;
++  CFStringRef       cf_string;
++  CFDictionaryRef   cf_dict;
++
++  priv-&gt;cf_bundle = CFBundleGetMainBundle ();
++  if (!priv-&gt;cf_bundle)
++    return;
++
++  CFRetain (priv-&gt;cf_bundle);
++
++  /* Bundle or binary location. */
++  cf_url = CFBundleCopyBundleURL (priv-&gt;cf_bundle);
++  cf_string = CFURLCopyFileSystemPath (cf_url, kCFURLPOSIXPathStyle);
++  priv-&gt;path = cf_string_to_utf8 (cf_string);
++  CFRelease (cf_string);
++  CFRelease (cf_url);
++
++  /* Package info. */
++  CFBundleGetPackageInfo (priv-&gt;cf_bundle, &amp;priv-&gt;type, &amp;priv-&gt;creator);
++
++  /* Identifier. */
++  cf_string = CFBundleGetIdentifier (priv-&gt;cf_bundle);
++  if (cf_string)
++    priv-&gt;id = cf_string_to_utf8 (cf_string);
++
++  /* Get non-localized keys. */
++  cf_dict = CFBundleGetInfoDictionary (priv-&gt;cf_bundle);
++  if (cf_dict)
++    {
++      CFDictionaryRef   env_dict;
++      CFIndex           n_keys, i;
++      const void      **keys;
++      const void      **values;
++
++      env_dict = (CFDictionaryRef) CFDictionaryGetValue (cf_dict, CFSTR (&quot;LSEnvironment&quot;));
++      if (env_dict)
++        {
++          n_keys = CFDictionaryGetCount (env_dict);
++
++          keys = (const void **) g_new (void *, n_keys);
++          values = (const void **) g_new (void *, n_keys);
++
++          CFDictionaryGetKeysAndValues (env_dict, keys, values);
++
++          for (i = 0; i &lt; n_keys; i++)
++            {
++              gchar *key;
++              gchar *value;
++
++              key = cf_string_to_utf8 ((CFStringRef) keys[i]);
++              value = cf_string_to_utf8 ((CFStringRef) values[i]);
++
++              mac_bundle_set_environment_value (bundle, key, value);
++
++              g_free (key);
++              g_free (value);
++            }
++
++          g_free (keys);
++          g_free (values);
++        }      
++    }
++}
++
++static void
++mac_bundle_finalize (GObject *object)
++{
++  IgeMacBundlePriv *priv;
++
++  priv = GET_PRIV (object);
++
++  g_free (priv-&gt;path);
++  g_free (priv-&gt;id);
++  g_free (priv-&gt;datadir);
++  g_free (priv-&gt;localedir);
++
++  CFRelease (priv-&gt;cf_bundle);
++
++  G_OBJECT_CLASS (ige_mac_bundle_parent_class)-&gt;finalize (object);
++}
++
++IgeMacBundle *
++ige_mac_bundle_new (void)
++{
++  return g_object_new (IGE_TYPE_MAC_BUNDLE, NULL);
++}
++
++IgeMacBundle *
++ige_mac_bundle_get_default (void)
++{
++  if (!global_bundle)
++    global_bundle = ige_mac_bundle_new ();
++
++  return global_bundle;
++}
++
++static gchar *
++cf_string_to_utf8 (CFStringRef str)
++{
++  CFIndex  len;
++  gchar   *ret;
++
++  len = CFStringGetMaximumSizeForEncoding (CFStringGetLength (str), 
++                                           kCFStringEncodingUTF8) + 1;
++
++  ret = g_malloc (len);
++  ret[len] = '\0';
++
++  if (CFStringGetCString (str, ret, len, kCFStringEncodingUTF8))
++    return ret;
++
++  g_free (ret);
++  return NULL;
++}
++
++static void
++mac_bundle_set_environment_value (IgeMacBundle *bundle,
++                                  const gchar  *key, 
++                                  const gchar  *value)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++  GRegex           *regex;
++  gchar            *new_value;
++
++  regex = g_regex_new (&quot;@executable_path&quot;, 0, 0, NULL);
++
++  new_value = g_regex_replace_literal (regex,
++                                       value,
++                                       -1,
++                                       0,
++                                       priv-&gt;path,
++                                       0, NULL);
++
++  g_print (&quot;%s =&gt; %s\n&quot;, value, new_value);
++
++  if (new_value)
++    value = new_value;
++
++
++  g_setenv (key, value, TRUE);
++
++  g_free (new_value);
++  g_regex_unref (regex);
++}
++
++const gchar *
++ige_mac_bundle_get_id (IgeMacBundle *bundle)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++
++  return priv-&gt;id;
++}
++
++const gchar *
++ige_mac_bundle_get_path (IgeMacBundle *bundle)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++
++  return priv-&gt;path;
++}
++
++gboolean
++ige_mac_bundle_get_is_app_bundle (IgeMacBundle *bundle)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++
++  return (priv-&gt;type == 'APPL' &amp;&amp; priv-&gt;id);
++}
++
++const gchar *
++ige_mac_bundle_get_datadir (IgeMacBundle *bundle)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++
++  if (!ige_mac_bundle_get_is_app_bundle (bundle))
++    return NULL;
++
++  if (!priv-&gt;datadir)
++    {
++      priv-&gt;datadir = g_build_filename (priv-&gt;path,
++                                        &quot;Contents&quot;,
++                                        &quot;Resources&quot;,
++                                        &quot;share&quot;,
++                                        NULL);
++    }
++
++  return priv-&gt;datadir;
++}
++
++const gchar *
++ige_mac_bundle_get_localedir (IgeMacBundle *bundle)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++
++  if (!ige_mac_bundle_get_is_app_bundle (bundle))
++    return NULL;
++
++  if (!priv-&gt;localedir)
++    {
++      priv-&gt;localedir = g_build_filename (priv-&gt;path,
++                                          &quot;Contents&quot;,
++                                          &quot;Resources&quot;,
++                                          &quot;share&quot;,
++                                          &quot;locale&quot;,
++                                          NULL);
++    }
++
++  return priv-&gt;localedir;
++}
++
++void
++ige_mac_bundle_setup_environment (IgeMacBundle *bundle)
++{
++  IgeMacBundlePriv *priv = GET_PRIV (bundle);
++  gchar            *resources;
++  gchar            *share, *lib, *etc;
++  gchar            *etc_xdg, *etc_immodules, *etc_gtkrc;
++  gchar            *etc_pixbuf, *etc_pangorc;
++  const gchar      *rc_files;
++
++  if (!ige_mac_bundle_get_is_app_bundle (bundle))
++    return;
++
++  resources = g_build_filename (priv-&gt;path,
++                                &quot;Contents&quot;,
++                                &quot;Resources&quot;,
++                                NULL);
++
++  share = g_build_filename (resources, &quot;share&quot;, NULL);
++  lib = g_build_filename (resources, &quot;lib&quot;, NULL);
++  etc = g_build_filename (resources, &quot;etc&quot;, NULL);
++  etc_xdg = g_build_filename (etc, &quot;xdg&quot;, NULL);
++  etc_immodules = g_build_filename (etc, &quot;gtk-2.0&quot;, &quot;gtk.immodules&quot;, NULL);
++  etc_gtkrc = g_build_filename (etc, &quot;gtk-2.0&quot;, &quot;gtkrc&quot;, NULL);
++  etc_pixbuf = g_build_filename (etc, &quot;gtk-2.0&quot;, &quot;gdk-pixbuf.loaders&quot;, NULL);
++  etc_pangorc = g_build_filename (etc, &quot;pango&quot;, &quot;pangorc&quot;, NULL);
++
++  g_setenv (&quot;XDG_CONFIG_DIRS&quot;, etc_xdg, TRUE);
++  g_setenv (&quot;XDG_DATA_DIRS&quot;, share, TRUE);
++  g_setenv (&quot;GTK_DATA_PREFIX&quot;, share, TRUE);
++  g_setenv (&quot;GTK_EXE_PREFIX&quot;, resources, TRUE);
++  g_setenv (&quot;GTK_PATH_PREFIX&quot;, resources, TRUE);
++
++  /* Append the normal gtkrc path to allow customizing the theme from
++   * Info.plist.
++   */
++  rc_files = g_getenv (&quot;GTK2_RC_FILES&quot;);
++  if (rc_files)
++    {
++      gchar *tmp;
++
++      tmp = g_strdup_printf (&quot;%s:%s&quot;, rc_files, etc_gtkrc);
++      g_setenv (&quot;GTK2_RC_FILES&quot;, tmp, TRUE);
++      g_free (tmp);
++    }
++  else
++    g_setenv (&quot;GTK2_RC_FILES&quot;, etc_gtkrc, TRUE);
++
++  g_setenv (&quot;GTK_IM_MODULE_FILE&quot;, etc_immodules, TRUE);
++  g_setenv (&quot;GDK_PIXBUF_MODULE_FILE&quot;, etc_pixbuf, TRUE);
++  g_setenv (&quot;PANGO_RC_FILE&quot;, etc_pangorc, TRUE);
++  g_setenv (&quot;CHARSETALIASDIR&quot;, lib, TRUE);
++
++  // could add FONTCONFIG_FILE
++
++  /*export LANG=&quot;\`grep \&quot;\\\`defaults read .GlobalPreferences AppleCollationOrder \
++ 2&gt;&amp;1\\\`_\&quot; /usr/share/locale/locale.alias | tail -n1 | sed 's/\./ /' | \
++ awk '{print \$2}'\`.UTF-8&quot;*/
++
++  g_free (share);
++  g_free (lib);
++  g_free (etc);
++  g_free (etc_xdg);
++  g_free (etc_immodules);
++  g_free (etc_gtkrc);
++  g_free (etc_pixbuf);
++  g_free (etc_pangorc);
++}
++
++gchar *
++ige_mac_bundle_get_resource_path (IgeMacBundle *bundle,
++                                  const gchar  *name,
++                                  const gchar  *type,
++                                  const gchar  *subdir)
++{
++  IgeMacBundlePriv *priv;
++  CFURLRef          cf_url;
++  CFStringRef       cf_string;
++  gchar            *path;
++
++  if (!bundle)
++    bundle = ige_mac_bundle_get_default ();
++
++  priv = GET_PRIV (bundle);
++
++  if (!priv-&gt;cf_bundle)
++    return NULL;
++
++  // FIXME: Look at using CFURLGetFileSystemRepresentation (urlcf_, true, (UInt8*)outPathName, 256)
++
++  // FIXME: crate real cfstring here...
++  cf_url = CFBundleCopyResourceURL (priv-&gt;cf_bundle, 
++                                    CFSTR(&quot;name&quot;), CFSTR(&quot;type&quot;), CFSTR(&quot;subdir&quot;));
++  cf_string = CFURLCopyFileSystemPath (cf_url, kCFURLPOSIXPathStyle);
++  path = cf_string_to_utf8 (cf_string);
++  CFRelease (cf_string);
++  CFRelease (cf_url);
++
++  return path;
++}
+--- pidgin/ige-mac-bundle.h        1970-01-01 01:00:00.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/ige-mac-bundle.h        2008-02-11 14:38:30.000000000 +0100
+@@ -0,0 +1,62 @@
++/* GTK+ Integration for app bundles.
++ *
++ * Copyright (C) 2007-2008 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; version 2.1
++ * of the License.
++ *
++ * 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, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __IGE_MAC_BUNDLE_H__
++#define __IGE_MAC_BUNDLE_H__
++
++#include &lt;glib-object.h&gt;
++
++G_BEGIN_DECLS
++
++#define IGE_TYPE_MAC_BUNDLE            (ige_mac_bundle_get_type ())
++#define IGE_MAC_BUNDLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IGE_TYPE_MAC_BUNDLE, IgeMacBundle))
++#define IGE_MAC_BUNDLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IGE_TYPE_MAC_BUNDLE, IgeMacBundleClass))
++#define IGE_IS_MAC_BUNDLE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IGE_TYPE_MAC_BUNDLE))
++#define IGE_IS_MAC_BUNDLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IGE_TYPE_MAC_BUNDLE))
++#define IGE_MAC_BUNDLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IGE_TYPE_MAC_BUNDLE, IgeMacBundleClass))
++
++typedef struct _IgeMacBundle      IgeMacBundle;
++typedef struct _IgeMacBundleClass IgeMacBundleClass;
++
++struct _IgeMacBundle {
++  GObject parent_instance;
++};
++
++struct _IgeMacBundleClass {
++  GObjectClass parent_class;
++};
++
++GType         ige_mac_bundle_get_type          (void);
++IgeMacBundle *ige_mac_bundle_new               (void);
++IgeMacBundle *ige_mac_bundle_get_default       (void);
++void          ige_mac_bundle_setup_environment (IgeMacBundle *bundle);
++const gchar * ige_mac_bundle_get_id            (IgeMacBundle *bundle);
++const gchar * ige_mac_bundle_get_path          (IgeMacBundle *bundle);
++gboolean      ige_mac_bundle_get_is_app_bundle (IgeMacBundle *bundle);
++const gchar * ige_mac_bundle_get_localedir     (IgeMacBundle *bundle);
++const gchar * ige_mac_bundle_get_datadir       (IgeMacBundle *bundle);
++gchar *       ige_mac_bundle_get_resource_path (IgeMacBundle *bundle,
++                                                const gchar  *name,
++                                                const gchar  *type,
++                                                const gchar  *subdir);
++
++G_END_DECLS
++
++#endif /* __IGE_MAC_BUNDLE_H__ */
+--- pidgin/ige-mac-dock.c        1970-01-01 01:00:00.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/ige-mac-dock.c        2008-02-11 14:38:28.000000000 +0100
+@@ -0,0 +1,449 @@
++/* GTK+ Integration for the Mac OS X Dock.
++ *
++ * Copyright (C) 2007-2008 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; version 2.1
++ * of the License.
++ *
++ * 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, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++/* FIXME: Add example like this to docs for the open documents stuff:
++
++    &lt;key&gt;CFBundleDocumentTypes&lt;/key&gt;
++    &lt;array&gt;
++      &lt;dict&gt;
++        &lt;key&gt;CFBundleTypeExtensions&lt;/key&gt;
++        &lt;array&gt;
++          &lt;string&gt;txt&lt;/string&gt;
++        &lt;/array&gt;
++      &lt;/dict&gt;
++    &lt;/array&gt;
++
++*/
++
++#include &lt;config.h&gt;
++#include &lt;Carbon/Carbon.h&gt;
++#include &lt;sys/param.h&gt;
++#include &lt;gtk/gtk.h&gt;
++
++#include &quot;ige-mac-dock.h&quot;
++#include &quot;ige-mac-bundle.h&quot;
++#include &quot;ige-mac-image-utils.h&quot;
++
++enum {
++  CLICKED,
++  QUIT_ACTIVATE,
++  OPEN_DOCUMENTS,
++  LAST_SIGNAL
++};
++
++static guint signals[LAST_SIGNAL] = { 0 };
++
++typedef struct IgeMacDockPriv IgeMacDockPriv;
++
++struct IgeMacDockPriv {
++  glong id;
++};
++
++static void  mac_dock_finalize                  (GObject          *object);
++static OSErr mac_dock_handle_quit               (const AppleEvent *inAppleEvent,
++                                                 AppleEvent       *outAppleEvent,
++                                                 long              inHandlerRefcon);
++static OSErr mac_dock_handle_open_documents     (const AppleEvent *inAppleEvent,
++                                                 AppleEvent       *outAppleEvent,
++                                                 long              inHandlerRefcon);
++static OSErr mac_dock_handle_open_application   (const AppleEvent *inAppleEvent,
++                                                 AppleEvent       *outAppleEvent,
++                                                 long              inHandlerRefcon);
++static OSErr mac_dock_handle_reopen_application (const AppleEvent *inAppleEvent,
++                                                 AppleEvent       *outAppleEvent,
++                                                 long              inHandlerRefcon);
++
++G_DEFINE_TYPE (IgeMacDock, ige_mac_dock, G_TYPE_OBJECT)
++
++#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), IGE_TYPE_MAC_DOCK, IgeMacDockPriv))
++
++static GList      *handlers;
++static IgeMacDock *global_dock;
++
++static void
++ige_mac_dock_class_init (IgeMacDockClass *class)
++{
++  GObjectClass *object_class = G_OBJECT_CLASS (class);
++
++  object_class-&gt;finalize = mac_dock_finalize;
++
++  signals[CLICKED] =
++    g_signal_new (&quot;clicked&quot;,
++                  IGE_TYPE_MAC_DOCK,
++                  G_SIGNAL_RUN_LAST,
++                  0,
++                  NULL, NULL,
++                  g_cclosure_marshal_VOID__VOID,
++                  G_TYPE_NONE, 0);
++
++  /* FIXME: Need marshaller. */
++  signals[OPEN_DOCUMENTS] =
++    g_signal_new (&quot;open-documents&quot;,
++                  IGE_TYPE_MAC_DOCK,
++                  G_SIGNAL_RUN_LAST,
++                  0,
++                  NULL, NULL,
++                  g_cclosure_marshal_VOID__VOID,
++                  G_TYPE_NONE, 0);
++
++  signals[QUIT_ACTIVATE] =
++    g_signal_new (&quot;quit-activate&quot;,
++                  IGE_TYPE_MAC_DOCK,
++                  G_SIGNAL_RUN_LAST,
++                  0,
++                  NULL, NULL,
++                  g_cclosure_marshal_VOID__VOID,
++                  G_TYPE_NONE, 0);
++
++  g_type_class_add_private (object_class, sizeof (IgeMacDockPriv));
++
++  /* FIXME: Just testing with triggering Carbon to take control over
++   * the dock menu events instead of Cocoa (which happens when the
++   * sharedApplication is created) to get custom dock menu working
++   * with carbon menu code. However, doing this makes the dock icon
++   * not get a &quot;running triangle&quot;.
++   */
++#if 0
++  EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
++  EventRef event;
++  
++  ReceiveNextEvent (GetEventTypeCount (kFakeEventList),
++                    kFakeEventList,
++                    kEventDurationNoWait, false, 
++                    &amp;event);
++#endif
++}
++
++static void
++ige_mac_dock_init (IgeMacDock *dock)
++{
++  IgeMacDockPriv *priv = GET_PRIV (dock);
++  static glong    id;
++
++  priv-&gt;id = ++id;
++
++  handlers = g_list_prepend (handlers, dock);
++
++  AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, 
++                         mac_dock_handle_quit,
++                         priv-&gt;id, true);
++  AEInstallEventHandler (kCoreEventClass, kAEOpenApplication,
++                         mac_dock_handle_open_application,
++                         priv-&gt;id, true);
++  AEInstallEventHandler (kCoreEventClass, kAEReopenApplication, 
++                         mac_dock_handle_reopen_application,
++                         priv-&gt;id, true);
++  AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments,
++                         mac_dock_handle_open_documents,
++                         priv-&gt;id, true);
++}
++
++static void
++mac_dock_finalize (GObject *object)
++{
++  IgeMacDockPriv *priv;
++
++  priv = GET_PRIV (object);
++
++  AERemoveEventHandler (kCoreEventClass, kAEQuitApplication,
++                        mac_dock_handle_quit, false);
++  AERemoveEventHandler (kCoreEventClass, kAEReopenApplication,
++                        mac_dock_handle_reopen_application, false);
++  AERemoveEventHandler (kCoreEventClass, kAEOpenApplication,
++                        mac_dock_handle_open_application, false);
++  AERemoveEventHandler (kCoreEventClass, kAEOpenDocuments,
++                        mac_dock_handle_open_documents, false);
++
++  handlers = g_list_remove (handlers, object);
++
++  G_OBJECT_CLASS (ige_mac_dock_parent_class)-&gt;finalize (object);
++}
++
++IgeMacDock *
++ige_mac_dock_new (void)
++{
++  return g_object_new (IGE_TYPE_MAC_DOCK, NULL);
++}
++
++IgeMacDock *
++ige_mac_dock_get_default (void)
++{
++  if (!global_dock)
++    global_dock = g_object_new (IGE_TYPE_MAC_DOCK, NULL);
++
++  return global_dock;
++}
++
++static IgeMacDock *
++mac_dock_get_from_id (gulong id)
++{
++  GList      *l;
++  IgeMacDock *dock = NULL;
++
++  for (l = handlers; l; l = l-&gt;next)
++    {
++      dock = l-&gt;data;
++      if (GET_PRIV (dock)-&gt;id == id)
++        break;
++
++      dock = NULL;
++  }
++
++  return dock;
++}
++
++static OSErr
++mac_dock_handle_quit (const AppleEvent *inAppleEvent, 
++                      AppleEvent       *outAppleEvent, 
++                      long              inHandlerRefcon)
++{
++  IgeMacDock *dock;
++
++  dock = mac_dock_get_from_id (inHandlerRefcon);
++
++  if (dock)
++    g_signal_emit (dock, signals[QUIT_ACTIVATE], 0);
++
++  return noErr;
++}
++
++static OSErr
++mac_dock_handle_open_application (const AppleEvent *inAppleEvent,
++                                  AppleEvent       *outAppleEvent,
++                                  long              inHandlerRefCon)
++{
++  g_print (&quot;FIXME: mac_dock_handle_open_application\n&quot;);
++
++  return noErr;
++}
++
++static OSErr
++mac_dock_handle_reopen_application (const AppleEvent *inAppleEvent, 
++                                    AppleEvent       *outAppleEvent, 
++                                    long              inHandlerRefcon)
++{
++  IgeMacDock *dock;
++
++  dock = mac_dock_get_from_id (inHandlerRefcon);
++
++  if (dock)
++    g_signal_emit (dock, signals[CLICKED], 0);
++  
++  return noErr;
++}
++
++static OSErr
++mac_dock_handle_open_documents (const AppleEvent *inAppleEvent,
++                                AppleEvent       *outAppleEvent,
++                                long              inHandlerRefCon)
++{
++  IgeMacDock *dock;
++  OSStatus    status;
++  AEDescList  documents;
++  gchar       path[MAXPATHLEN];
++
++  g_print (&quot;FIXME: mac_dock_handle_open_documents\n&quot;);
++
++  dock = mac_dock_get_from_id (inHandlerRefCon);
++
++  status = AEGetParamDesc (inAppleEvent,
++                           keyDirectObject, typeAEList,
++                           &amp;documents);
++  if (status == noErr)
++    {
++      long count = 0;
++      int  i;
++
++      AECountItems (&amp;documents, &amp;count);
++
++      for (i = 0; i &lt; count; i++)
++        {
++          FSRef ref;
++
++          status = AEGetNthPtr (&amp;documents, i + 1, typeFSRef, 
++                                0, 0, &amp;ref, sizeof (ref),
++                                0);
++          if (status != noErr)
++            continue;
++
++          FSRefMakePath (&amp;ref, path, MAXPATHLEN);
++
++          /* FIXME: Add to a list, then emit the open-documents
++           * signal.
++           */
++          g_print (&quot;  %s\n&quot;, path);
++        }
++    }
++        
++    return status;
++}
++
++void
++ige_mac_dock_set_icon_from_pixbuf (IgeMacDock *dock,
++                                   GdkPixbuf  *pixbuf)
++{
++  if (!pixbuf)
++    RestoreApplicationDockTileImage ();
++  else
++    {
++      CGImageRef image;
++
++      image = ige_mac_image_from_pixbuf (pixbuf);
++      SetApplicationDockTileImage (image);
++      CGImageRelease (image);
++    }
++}
++
++void
++ige_mac_dock_set_icon_from_resource (IgeMacDock   *dock,
++                                     IgeMacBundle *bundle,
++                                     const gchar  *name,
++                                     const gchar  *type,
++                                     const gchar  *subdir)
++{
++  gchar *path;
++
++  g_return_if_fail (IGE_IS_MAC_DOCK (dock));
++  g_return_if_fail (name != NULL);
++
++  path = ige_mac_bundle_get_resource_path (bundle, name, type, subdir);
++  if (path)
++    {
++      GdkPixbuf *pixbuf;
++
++      pixbuf = gdk_pixbuf_new_from_file (path, NULL);
++      if (pixbuf)
++        {
++          ige_mac_dock_set_icon_from_pixbuf (dock, pixbuf);
++          g_object_unref (pixbuf);
++        }
++
++      g_free (path);
++    }
++}
++
++void
++ige_mac_dock_set_overlay_from_pixbuf (IgeMacDock  *dock,
++                                      GdkPixbuf   *pixbuf)
++{
++  CGImageRef image;
++
++  g_return_if_fail (IGE_IS_MAC_DOCK (dock));
++  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
++
++  image = ige_mac_image_from_pixbuf (pixbuf);
++  OverlayApplicationDockTileImage (image);
++  CGImageRelease (image);
++}
++
++void
++ige_mac_dock_set_overlay_from_resource (IgeMacDock   *dock,
++                                        IgeMacBundle *bundle,
++                                        const gchar  *name,
++                                        const gchar  *type,
++                                        const gchar  *subdir)
++{
++  gchar *path;
++
++  g_return_if_fail (IGE_IS_MAC_DOCK (dock));
++  g_return_if_fail (name != NULL);
++
++  path = ige_mac_bundle_get_resource_path (bundle, name, type, subdir);
++  if (path)
++    {
++      GdkPixbuf *pixbuf;
++
++      pixbuf = gdk_pixbuf_new_from_file (path, NULL);
++      if (pixbuf)
++        {
++          ige_mac_dock_set_overlay_from_pixbuf (dock, pixbuf);
++          g_object_unref (pixbuf);
++        }
++
++      g_free (path);
++    }
++}
++
++struct _IgeMacAttentionRequest {
++  NMRec    nm_request;
++  guint    timeout_id;
++  gboolean is_cancelled;
++};
++
++static gboolean
++mac_dock_attention_cb (IgeMacAttentionRequest *request)
++{
++  request-&gt;timeout_id = 0;
++  request-&gt;is_cancelled = TRUE;
++
++  NMRemove (&amp;request-&gt;nm_request);
++
++  return FALSE;
++}
++
++
++/* FIXME: Add listener for &quot;application activated&quot; and cancel any
++ * requests.
++ */
++IgeMacAttentionRequest *
++ige_mac_dock_attention_request (IgeMacDock          *dock,
++                                IgeMacAttentionType  type)
++{
++  IgeMacAttentionRequest *request;
++
++  request = g_new0 (IgeMacAttentionRequest, 1);
++
++  request-&gt;nm_request.nmMark = 1;
++  request-&gt;nm_request.qType = nmType;
++  
++  if (NMInstall (&amp;request-&gt;nm_request) != noErr)
++    {
++      g_free (request);
++      return NULL;
++    }
++
++  if (type == IGE_MAC_ATTENTION_INFO)
++    request-&gt;timeout_id = gdk_threads_add_timeout (
++            1000,
++            (GSourceFunc) mac_dock_attention_cb,
++            request);
++
++  return request;
++}
++
++void
++ige_mac_dock_attention_cancel (IgeMacDock             *dock,
++                               IgeMacAttentionRequest *request)
++{
++  if (request-&gt;timeout_id)
++    g_source_remove (request-&gt;timeout_id);
++
++  if (!request-&gt;is_cancelled)
++    NMRemove (&amp;request-&gt;nm_request);
++
++  g_free (request);
++}
++
++GType
++ige_mac_attention_type_get_type (void)
++{
++  /* FIXME */
++  return 0;
++}
+--- pidgin/ige-mac-dock.h        1970-01-01 01:00:00.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/ige-mac-dock.h        2008-02-11 14:38:30.000000000 +0100
+@@ -0,0 +1,83 @@
++/* GTK+ Integration for the Mac OS X Dock.
++ *
++ * Copyright (C) 2007-2008 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; version 2.1
++ * of the License.
++ *
++ * 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, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __IGE_MAC_DOCK_H__
++#define __IGE_MAC_DOCK_H__
++
++#include &lt;gtk/gtk.h&gt;
++#include &lt;ige-mac-bundle.h&gt;
++
++G_BEGIN_DECLS
++
++#define IGE_TYPE_MAC_DOCK            (ige_mac_dock_get_type ())
++#define IGE_MAC_DOCK(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IGE_TYPE_MAC_DOCK, IgeMacDock))
++#define IGE_MAC_DOCK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IGE_TYPE_MAC_DOCK, IgeMacDockClass))
++#define IGE_IS_MAC_DOCK(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IGE_TYPE_MAC_DOCK))
++#define IGE_IS_MAC_DOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IGE_TYPE_MAC_DOCK))
++#define IGE_MAC_DOCK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IGE_TYPE_MAC_DOCK, IgeMacDockClass))
++
++typedef struct _IgeMacDock      IgeMacDock;
++typedef struct _IgeMacDockClass IgeMacDockClass;
++
++typedef struct _IgeMacAttentionRequest IgeMacAttentionRequest;
++
++struct _IgeMacDock
++{
++  GObject parent_instance;
++};
++
++struct _IgeMacDockClass
++{
++  GObjectClass parent_class;
++};
++
++typedef enum {
++        IGE_MAC_ATTENTION_CRITICAL,
++        IGE_MAC_ATTENTION_INFO
++} IgeMacAttentionType;
++
++GType                   ige_mac_dock_get_type                  (void);
++IgeMacDock *            ige_mac_dock_new                       (void);
++IgeMacDock *            ige_mac_dock_get_default               (void);
++void                    ige_mac_dock_set_icon_from_pixbuf      (IgeMacDock             *dock,
++                                                                GdkPixbuf              *pixbuf);
++void                    ige_mac_dock_set_icon_from_resource    (IgeMacDock             *dock,
++                                                                IgeMacBundle           *bundle,
++                                                                const gchar            *name,
++                                                                const gchar            *type,
++                                                                const gchar            *subdir);
++void                    ige_mac_dock_set_overlay_from_pixbuf   (IgeMacDock             *dock,
++                                                                GdkPixbuf              *pixbuf);
++void                    ige_mac_dock_set_overlay_from_resource (IgeMacDock             *dock,
++                                                                IgeMacBundle           *bundle,
++                                                                const gchar            *name,
++                                                                const gchar            *type,
++                                                                const gchar            *subdir);
++IgeMacAttentionRequest *ige_mac_dock_attention_request         (IgeMacDock             *dock,
++                                                                IgeMacAttentionType     type);
++void                    ige_mac_dock_attention_cancel          (IgeMacDock             *dock,
++                                                                IgeMacAttentionRequest *request);
++
++#define IGE_TYPE_MAC_ATTENTION_TYPE (ige_mac_attention_type_get_type())
++GType                   ige_mac_attention_type_get_type        (void);
++
++G_END_DECLS
++
++#endif /* __IGE_MAC_DOCK_H__ */
+--- pidgin/ige-mac-image-utils.c        1970-01-01 01:00:00.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/ige-mac-image-utils.c        2008-02-11 14:38:28.000000000 +0100
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2007 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; version 2.1
++ * of the License.
++ *
++ * 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, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#include &lt;config.h&gt;
++#include &lt;gtk/gtk.h&gt;
++#include &lt;Carbon/Carbon.h&gt;
++
++#include &quot;ige-mac-image-utils.h&quot;
++
++CGImageRef
++ige_mac_image_from_pixbuf (GdkPixbuf *pixbuf)
++{
++  CGColorSpaceRef   colorspace;
++  CGDataProviderRef data_provider;
++  CGImageRef        image;
++  void             *data;
++  gint              rowstride;
++  gint              pixbuf_width, pixbuf_height;
++  gboolean          has_alpha;
++ 
++  pixbuf_width = gdk_pixbuf_get_width (pixbuf);
++  pixbuf_height = gdk_pixbuf_get_height (pixbuf);
++  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
++  has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
++
++  data = gdk_pixbuf_get_pixels (pixbuf);
++
++  colorspace = CGColorSpaceCreateDeviceRGB ();
++  data_provider = CGDataProviderCreateWithData (NULL, data, 
++                                                pixbuf_height * rowstride, 
++                                                NULL);
++
++  image = CGImageCreate (pixbuf_width, pixbuf_height, 8,
++                         has_alpha ? 32 : 24, rowstride, 
++                         colorspace, 
++                         has_alpha ? kCGImageAlphaLast : 0,
++                         data_provider, NULL, FALSE, 
++                         kCGRenderingIntentDefault);
++
++  CGDataProviderRelease (data_provider);
++  CGColorSpaceRelease (colorspace);
++
++  return image;
++}
+--- pidgin/ige-mac-image-utils.h        1970-01-01 01:00:00.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/ige-mac-image-utils.h        2008-02-11 14:38:30.000000000 +0100
+@@ -0,0 +1,32 @@
++/*
++ * Copyright (C) 2007 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; version 2.1
++ * of the License.
++ *
++ * 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, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#ifndef __IGE_MAC_IMAGE_UTILS_H__
++#define __IGE_MAC_IMAGE_UTILS_H__
++
++#include &lt;gdk-pixbuf/gdk-pixbuf.h&gt;
++#include &lt;Carbon/Carbon.h&gt;
++
++G_BEGIN_DECLS
++
++CGImageRef ige_mac_image_from_pixbuf (GdkPixbuf *pixbuf);
++
++G_END_DECLS
++
++#endif /* __IGE_MAC_IMAGE_UTILS_H__ */
+--- pidgin/ige-mac-menu.c        1970-01-01 01:00:00.000000000 +0100
++++ ../pidgin-2.3.1/pidgin/ige-mac-menu.c        2008-02-11 14:38:28.000000000 +0100
+@@ -0,0 +1,936 @@
++/* GTK+ Integration for the Mac OS X Menubar.
++ *
++ * Copyright (C) 2007 Pioneer Research Center USA, Inc.
++ * Copyright (C) 2007 Imendio AB
++ *
++ * For further information, see:
++ * http://developer.imendio.com/projects/gtk-macosx/menubar
++ *
++ * 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; version 2.1
++ * of the License.
++ *
++ * 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, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#include &lt;gtk/gtk.h&gt;
++#include &lt;gdk/gdkkeysyms.h&gt;
++#include &lt;Carbon/Carbon.h&gt;
++
++#include &quot;ige-mac-menu.h&quot;
++
++/* TODO
++ *
++ * - Adding a standard Window menu (Minimize etc)?
++ * - Sync reordering items? Does that work now?
++ * - Create on demand? (can this be done with gtk+? ie fill in menu
++     items when the menu is opened)
++ * - Figure out what to do per app/window...
++ *
++ */
++
++#define IGE_QUARTZ_MENU_CREATOR 'IGEC'
++#define IGE_QUARTZ_ITEM_WIDGET  'IWID'
++
++
++static void   sync_menu_shell (GtkMenuShell *menu_shell,
++                               MenuRef       carbon_menu,
++                               gboolean      toplevel,
++                               gboolean      debug);
++
++
++/*
++ * utility functions
++ */
++
++static GtkWidget *
++find_menu_label (GtkWidget *widget)
++{
++  GtkWidget *label = NULL;
++
++  if (GTK_IS_LABEL (widget))
++    return widget;
++
++  if (GTK_IS_CONTAINER (widget))
++    {
++      GList *children;
++      GList *l;
++
++      children = gtk_container_get_children (GTK_CONTAINER (widget));
++
++      for (l = children; l; l = l-&gt;next)
++        {
++          label = find_menu_label (l-&gt;data);
++          if (label)
++            break;
++        }
++
++      g_list_free (children);
++    }
++
++  return label;
++}
++
++static const gchar *
++get_menu_label_text (GtkWidget  *menu_item,
++                     GtkWidget **label)
++{
++  GtkWidget *my_label;
++
++  my_label = find_menu_label (menu_item);
++  if (label)
++    *label = my_label;
++
++  if (my_label)
++    return gtk_label_get_text (GTK_LABEL (my_label));
++
++  return NULL;
++}
++
++static gboolean
++accel_find_func (GtkAccelKey *key,
++                 GClosure    *closure,
++                 gpointer     data)
++{
++  return (GClosure *) data == closure;
++}
++
++
++/*
++ * CarbonMenu functions
++ */
++
++typedef struct
++{
++  MenuRef menu;
++  guint   toplevel : 1;
++} CarbonMenu;
++
++static GQuark carbon_menu_quark = 0;
++
++static CarbonMenu *
++carbon_menu_new (void)
++{
++  return g_slice_new0 (CarbonMenu);
++}
++
++static void
++carbon_menu_free (CarbonMenu *menu)
++{
++  g_slice_free (CarbonMenu, menu);
++}
++
++static CarbonMenu *
++carbon_menu_get (GtkWidget *widget)
++{
++  return g_object_get_qdata (G_OBJECT (widget), carbon_menu_quark);
++}
++
++static void
++carbon_menu_connect (GtkWidget *menu,
++                     MenuRef    menuRef,
++                     gboolean   toplevel)
++{
++  CarbonMenu *carbon_menu = carbon_menu_get (menu);
++
++  if (!carbon_menu)
++    {
++      carbon_menu = carbon_menu_new ();
++
++      g_object_set_qdata_full (G_OBJECT (menu), carbon_menu_quark,
++                               carbon_menu,
++                               (GDestroyNotify) carbon_menu_free);
++    }
++
++  carbon_menu-&gt;menu = menuRef;
++  carbon_menu-&gt;toplevel = toplevel;
++}
++
++
++/*
++ * CarbonMenuItem functions
++ */
++
++typedef struct
++{
++  MenuRef        menu;
++  MenuItemIndex  index;
++  MenuRef        submenu;
++  GClosure      *accel_closure;
++} CarbonMenuItem;
++
++static GQuark carbon_menu_item_quark = 0;
++
++static CarbonMenuItem *
++carbon_menu_item_new (void)
++{
++  return g_slice_new0 (CarbonMenuItem);
++}
++
++static void
++carbon_menu_item_free (CarbonMenuItem *menu_item)
++{
++  if (menu_item-&gt;accel_closure)
++    g_closure_unref (menu_item-&gt;accel_closure);
++
++  g_slice_free (CarbonMenuItem, menu_item);
++}
++
++static CarbonMenuItem *
++carbon_menu_item_get (GtkWidget *widget)
++{
++  return g_object_get_qdata (G_OBJECT (widget), carbon_menu_item_quark);
++}
++
++static void
++carbon_menu_item_update_state (CarbonMenuItem *carbon_item,
++                               GtkWidget      *widget)
++{
++  gboolean sensitive;
++  gboolean visible;
++  UInt32   set_attrs = 0;
++  UInt32   clear_attrs = 0;
++
++  g_object_get (widget,
++                &quot;sensitive&quot;, &amp;sensitive,
++                &quot;visible&quot;,   &amp;visible,
++                NULL);
++
++  if (!sensitive)
++    set_attrs |= kMenuItemAttrDisabled;
++  else
++    clear_attrs |= kMenuItemAttrDisabled;
++
++  if (!visible)
++    set_attrs |= kMenuItemAttrHidden;
++  else
++    clear_attrs |= kMenuItemAttrHidden;
++
++  ChangeMenuItemAttributes (carbon_item-&gt;menu, carbon_item-&gt;index,
++                            set_attrs, clear_attrs);
++}
++
++static void
++carbon_menu_item_update_active (CarbonMenuItem *carbon_item,
++                                GtkWidget      *widget)
++{
++  gboolean active;
++
++  g_object_get (widget,
++                &quot;active&quot;, &amp;active,
++                NULL);
++
++  CheckMenuItem (carbon_item-&gt;menu, carbon_item-&gt;index,
++                 active);
++}
++
++static void
++carbon_menu_item_update_submenu (CarbonMenuItem *carbon_item,
++                                 GtkWidget      *widget)
++{
++  GtkWidget *submenu;
++
++  submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
++
++  if (submenu)
++    {
++      const gchar *label_text;
++      CFStringRef  cfstr = NULL;
++
++      label_text = get_menu_label_text (widget, NULL);
++      if (label_text)
++        cfstr = CFStringCreateWithCString (NULL, label_text,
++                                           kCFStringEncodingUTF8);
++
++      CreateNewMenu (0, 0, &amp;carbon_item-&gt;submenu);
++      SetMenuTitleWithCFString (carbon_item-&gt;submenu, cfstr);
++      SetMenuItemHierarchicalMenu (carbon_item-&gt;menu, carbon_item-&gt;index,
++                                   carbon_item-&gt;submenu);
++
++      sync_menu_shell (GTK_MENU_SHELL (submenu), carbon_item-&gt;submenu, FALSE, FALSE);
++
++      if (cfstr)
++        CFRelease (cfstr);
++    }
++  else
++    {
++      SetMenuItemHierarchicalMenu (carbon_item-&gt;menu, carbon_item-&gt;index,
++                                   NULL);
++      carbon_item-&gt;submenu = NULL;
++    }
++}
++
++static void
++carbon_menu_item_update_label (CarbonMenuItem *carbon_item,
++                               GtkWidget      *widget)
++{
++  const gchar *label_text;
++  CFStringRef  cfstr = NULL;
++
++  label_text = get_menu_label_text (widget, NULL);
++  if (label_text)
++    cfstr = CFStringCreateWithCString (NULL, label_text,
++                                       kCFStringEncodingUTF8);
++
++  SetMenuItemTextWithCFString (carbon_item-&gt;menu, carbon_item-&gt;index,
++                               cfstr);
++
++  if (cfstr)
++    CFRelease (cfstr);
++}
++
++static void
++carbon_menu_item_update_accelerator (CarbonMenuItem *carbon_item,
++                                     GtkWidget      *widget)
++{
++  GtkWidget *label;
++
++  get_menu_label_text (widget, &amp;label);
++
++  if (GTK_IS_ACCEL_LABEL (label) &amp;&amp;
++      GTK_ACCEL_LABEL (label)-&gt;accel_closure)
++    {
++      GtkAccelKey *key;
++
++      key = gtk_accel_group_find (GTK_ACCEL_LABEL (label)-&gt;accel_group,
++                                  accel_find_func,
++                                  GTK_ACCEL_LABEL (label)-&gt;accel_closure);
++
++      if (key            &amp;&amp;
++          key-&gt;accel_key &amp;&amp;
++          key-&gt;accel_flags &amp; GTK_ACCEL_VISIBLE)
++        {
++          GdkDisplay      *display = gtk_widget_get_display (widget);
++          GdkKeymap       *keymap  = gdk_keymap_get_for_display (display);
++          GdkKeymapKey    *keys;
++          gint             n_keys;
++
++          if (gdk_keymap_get_entries_for_keyval (keymap, key-&gt;accel_key,
++                                                 &amp;keys, &amp;n_keys))
++            {
++              UInt8 modifiers = 0;
++
++              SetMenuItemCommandKey (carbon_item-&gt;menu, carbon_item-&gt;index,
++                                     true, keys[0].keycode);
++
++              g_free (keys);
++
++              if (key-&gt;accel_mods)
++                {
++                  if (key-&gt;accel_mods &amp; GDK_SHIFT_MASK)
++                    modifiers |= kMenuShiftModifier;
++
++                  if (key-&gt;accel_mods &amp; GDK_MOD1_MASK)
++                    modifiers |= kMenuOptionModifier;
++                }
++
++              if (!(key-&gt;accel_mods &amp; GDK_CONTROL_MASK))
++                {
++                  modifiers |= kMenuNoCommandModifier;
++                }
++
++              SetMenuItemModifiers (carbon_item-&gt;menu, carbon_item-&gt;index,
++                                    modifiers);
++
++              return;
++            }
++        }
++    }
++
++  /*  otherwise, clear the menu shortcut  */
++  SetMenuItemModifiers (carbon_item-&gt;menu, carbon_item-&gt;index,
++                        kMenuNoModifiers | kMenuNoCommandModifier);
++  ChangeMenuItemAttributes (carbon_item-&gt;menu, carbon_item-&gt;index,
++                            0, kMenuItemAttrUseVirtualKey);
++  SetMenuItemCommandKey (carbon_item-&gt;menu, carbon_item-&gt;index,
++                         false, 0);
++}
++
++static void
++carbon_menu_item_accel_changed (GtkAccelGroup   *accel_group,
++                                guint            keyval,
++                                GdkModifierType  modifier,
++                                GClosure        *accel_closure,
++                                GtkWidget       *widget)
++{
++  CarbonMenuItem *carbon_item = carbon_menu_item_get (widget);
++  GtkWidget      *label;
++
++  get_menu_label_text (widget, &amp;label);
++
++  if (GTK_IS_ACCEL_LABEL (label) &amp;&amp;
++      GTK_ACCEL_LABEL (label)-&gt;accel_closure == accel_closure)
++    carbon_menu_item_update_accelerator (carbon_item, widget);
++}
++
++static void
++carbon_menu_item_update_accel_closure (CarbonMenuItem *carbon_item,
++                                       GtkWidget      *widget)
++{
++  GtkAccelGroup *group;
++  GtkWidget     *label;
++
++  get_menu_label_text (widget, &amp;label);
++
++  if (carbon_item-&gt;accel_closure)
++    {
++      group = gtk_accel_group_from_accel_closure (carbon_item-&gt;accel_closure);
++
++      g_signal_handlers_disconnect_by_func (group,
++                                            carbon_menu_item_accel_changed,
++                                            widget);
++
++      g_closure_unref (carbon_item-&gt;accel_closure);
++      carbon_item-&gt;accel_closure = NULL;
++    }
++
++  if (GTK_IS_ACCEL_LABEL (label))
++    carbon_item-&gt;accel_closure = GTK_ACCEL_LABEL (label)-&gt;accel_closure;
++
++  if (carbon_item-&gt;accel_closure)
++    {
++      g_closure_ref (carbon_item-&gt;accel_closure);
++
++      group = gtk_accel_group_from_accel_closure (carbon_item-&gt;accel_closure);
++
++      g_signal_connect_object (group, &quot;accel-changed&quot;,
++                               G_CALLBACK (carbon_menu_item_accel_changed),
++                               widget, 0);
++    }
++
++  carbon_menu_item_update_accelerator (carbon_item, widget);
++}
++
++static void
++carbon_menu_item_notify (GObject        *object,
++                         GParamSpec     *pspec,
++                         CarbonMenuItem *carbon_item)
++{
++  if (!strcmp (pspec-&gt;name, &quot;sensitive&quot;) ||
++      !strcmp (pspec-&gt;name, &quot;visible&quot;))
++    {
++      carbon_menu_item_update_state (carbon_item, GTK_WIDGET (object));
++    }
++  else if (!strcmp (pspec-&gt;name, &quot;active&quot;))
++    {
++      carbon_menu_item_update_active (carbon_item, GTK_WIDGET (object));
++    }
++  else if (!strcmp (pspec-&gt;name, &quot;submenu&quot;))
++    {
++      carbon_menu_item_update_submenu (carbon_item, GTK_WIDGET (object));
++    }
++}
++
++static void
++carbon_menu_item_notify_label (GObject    *object,
++                               GParamSpec *pspec,
++                               gpointer    data)
++{
++  CarbonMenuItem *carbon_item = carbon_menu_item_get (GTK_WIDGET (object));
++
++  if (!strcmp (pspec-&gt;name, &quot;label&quot;))
++    {
++      carbon_menu_item_update_label (carbon_item,
++                                     GTK_WIDGET (object));
++    }
++  else if (!strcmp (pspec-&gt;name, &quot;accel-closure&quot;))
++    {
++      carbon_menu_item_update_accel_closure (carbon_item,
++                                             GTK_WIDGET (object));
++    }
++}
++
++static CarbonMenuItem *
++carbon_menu_item_connect (GtkWidget     *menu_item,
++                          GtkWidget     *label,
++                          MenuRef        menu,
++                          MenuItemIndex  index)
++{
++  CarbonMenuItem *carbon_item = carbon_menu_item_get (menu_item);
++
++  if (!carbon_item)
++    {
++      carbon_item = carbon_menu_item_new ();
++
++      g_object_set_qdata_full (G_OBJECT (menu_item), carbon_menu_item_quark,
++                               carbon_item,
++                               (GDestroyNotify) carbon_menu_item_free);
++
++      g_signal_connect (menu_item, &quot;notify&quot;,
++                        G_CALLBACK (carbon_menu_item_notify),
++                        carbon_item);
++
++      if (label)
++        g_signal_connect_swapped (label, &quot;notify::label&quot;,
++                                  G_CALLBACK (carbon_menu_item_notify_label),
++                                  menu_item);
++    }
++
++  carbon_item-&gt;menu  = menu;
++  carbon_item-&gt;index = index;
++
++  return carbon_item;
++}
++
++
++/*
++ * carbon event handler
++ */
++
++static OSStatus
++menu_event_handler_func (EventHandlerCallRef  event_handler_call_ref,
++                         EventRef             event_ref,
++                         void                *data)
++{
++  UInt32  event_class = GetEventClass (event_ref);
++  UInt32  event_kind = GetEventKind (event_ref);
++  MenuRef menu_ref;
++
++  switch (event_class)
++    {
++    case kEventClassCommand:
++      /* This is called when activating (is that the right GTK+ term?)
++       * a menu item.
++       */
++      if (event_kind == kEventCommandProcess)
++        {
++          HICommand command;
++          OSStatus  err;
++
++          /*g_printerr (&quot;Menu: kEventClassCommand/kEventCommandProcess\n&quot;);*/
++
++          err = GetEventParameter (event_ref, kEventParamDirectObject,
++                                   typeHICommand, 0,
++                                   sizeof (command), 0, &amp;command);
++
++          if (err == noErr)
++            {
++              GtkWidget *widget = NULL;
++
++              /* Get any GtkWidget associated with the item. */
++              err = GetMenuItemProperty (command.menu.menuRef,
++                                         command.menu.menuItemIndex,
++                                         IGE_QUARTZ_MENU_CREATOR,
++                                         IGE_QUARTZ_ITEM_WIDGET,
++                                         sizeof (widget), 0, &amp;widget);
++              if (err == noErr &amp;&amp; GTK_IS_WIDGET (widget))
++                {
++                  gtk_menu_item_activate (GTK_MENU_ITEM (widget));
++                  return noErr;
++                }
++            }
++        }
++      break;
++
++    case kEventClassMenu:
++      GetEventParameter (event_ref,
++                         kEventParamDirectObject,
++                         typeM