Ticket #25127: pidgin_1.diff

File pidgin_1.diff, 77.2 KB (added by nefar@…, 14 years ago)

OK, removed the docklet mods. Made the quartz option the default. please give it a spin :)

  • Portfile

    diff -r 9b7fde062ca7 Portfile
    a b  
    11# -*- coding: utf-8; mode: tcl; tab-width: 4; truncate-lines: t; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:et:sw=4:ts=4:sts=4
    2 # $Id: Portfile 68537 2010-06-05 18:23:18Z jeremyhu@macports.org $
     2# $Id: Portfile 66057 2010-04-05 13:33:04Z rmsfisher@macports.org $
    33
    44PortSystem          1.0
    55
    66name                pidgin
    7 conflicts           finch
    8 version             2.7.0
     7version             2.7.1
    98categories          net
    109platforms           darwin
    1110maintainers         otherware.org:nefar
     
    2019
    2120homepage            http://www.pidgin.im/
    2221master_sites        sourceforge
    23 checksums           md5     63a36f91d29f5ac5a402ffd2d7dbbb72 \
    24                     sha1    7170aaae5e6f4039870eb5e0c5837d55285b758f \
    25                     rmd160  45e4b5a9acb9c4080ce6b33cedbf9b962883ca25
     22checksums           md5     0dd2adb9e8214ac960f956823c84e7e2 \
     23                    sha1    b746720cc3e65b3d6da6eab0729f26673f997849 \
     24                    rmd160  5e5deec529b1c8d75cd3f925b3f5e4f5310e42e5
    2625use_bzip2           yes
    2726
    2827depends_build       port:libtool
     
    3938                    port:p5-xml-parser \
    4039                    port:intltool
    4140
    42 patchfiles          gst.diff
     41# who wouldn't want quartz?
     42default_variants +quartz
    4343
    4444# nss is not universal
    4545universal_variant   no
     
    6565
    6666# --disable-dependency-tracking was added because a +universal perl will result in
    6767# PERL_CFLAGS containing multiple -arch arguments... this is the easiest workaround
    68 
    6968configure.ldflags-append    -bind_at_load
    7069configure.cppflags-append   -no-cpp-precomp
    7170
     71variant finch_only requires finch description {Build without pidgin} {
     72    configure.args-append   --disable-gtkui \
     73                            --without-x
     74}
     75
     76variant finch description {Build with finch} {
     77    configure.args-delete   --disable-consoleui
     78    patchfiles-append          patch-finch_libgnt_Makefile.in.diff patch-finch_libgnt_gntwm.c
     79}
     80
    7281post-destroot {
    7382    fs-traverse file ${destroot}${prefix}/lib/perl5 {
    7483        if {[file tail ${file}] == "perllocal.pod"} {
     
    8695}
    8796
    8897variant quartz requires no_x11 {
    89     patchfiles-append       gtkdocklet-quartz.diff
    90 
    91     configure.args-append   --disable-gestures \
    92                             --enable-gtkstatusicon
     98    configure.args-append   --disable-gestures
    9399
    94100    depends_build           port:autoconf \
    95101                            port:automake \
  • deleted file files/gst.diff

    diff -r 9b7fde062ca7 files/gst.diff
    + -  
    1 Index: libpurple/media/backend-fs2.h
    2 ===================================================================
    3 --- libpurple/media/backend-fs2.h
    4 +++ libpurple/media/backend-fs2.h
    5 @@ -55,6 +55,7 @@
    6   */
    7  GType purple_media_backend_fs2_get_type(void);
    8 
    9 +#ifdef USE_GSTREAMER
    10  /*
    11   * Temporary function in order to be able to test while
    12   * integrating with PurpleMedia
    13 @@ -71,6 +72,7 @@
    14   void purple_media_backend_fs2_set_output_volume(PurpleMediaBackendFs2 *self,
    15   const gchar *sess_id, const gchar *who, double level);
    16  /* end tmp */
    17 +#endif /* USE_GSTREAMER */
    18 
    19  G_END_DECLS
  • deleted file files/gtkdocklet-quartz.diff

    diff -r 9b7fde062ca7 files/gtkdocklet-quartz.diff
    + -  
    1 Index: configure.ac
    2 ===================================================================
    3 --- configure.ac.orig   2008-11-06 00:16:37.000000000 +0100
    4 +++ configure.ac        2008-11-06 00:17:02.000000000 +0100
    5 @@ -371,6 +371,10 @@
    6         [AC_HELP_STRING([--disable-gestures],
    7                 [compile without the gestures plugin])],
    8         enable_gestures="$enableval", enable_gestures="yes")
    9 +AC_ARG_ENABLE(gtkstatusicon,
    10 +       [AC_HELP_STRING([--enable-gtkstatusicon],
    11 +               [Use GtkStatusIcon instead of X11 docklet])],
    12 +       enable_gtkstatusicon="$enableval", enable_gtkstatusicon="no")
    13  
    14  AC_PATH_XTRA
    15  # We can't assume that $x_libraries will be set, because autoconf does not
    16 @@ -594,6 +598,16 @@
    17                         fi])
    18         fi
    19          
    20 +       dnl #######################################################################
    21 +       dnl # Check for GtkStatusIcon support
    22 +       dnl #######################################################################
    23 +       if test "x$enable_gtkstatusicon" = "xyes"; then
    24 +               AC_MSG_CHECKING(GtkStatusIcon)   
    25 +               PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.9.0],
    26 +                       [enable_gtkstatusicon="yes"],
    27 +                       [enable_gtkstatusicon="no"]
    28 +               )
    29 +       fi
    30  
    31  else # GTK
    32         enable_cap=no
    33 @@ -608,6 +622,7 @@
    34  AM_CONDITIONAL(BUILD_GEVOLUTION, test "x$enable_gevolution" = "xyes")
    35  AM_CONDITIONAL(ENABLE_CAP, test "x$enable_cap" = "xyes")
    36  AM_CONDITIONAL(ENABLE_GESTURES, test "x$enable_gestures" = "xyes")
    37 +AM_CONDITIONAL(GTK_STATUS_ICON, test "x$enable_gtkstatusicon" = "xyes")
    38  
    39  
    40  dnl #######################################################################
    41 @@ -2438,6 +2453,7 @@
    42  echo Build console UI.............. : $enable_consoleui
    43  echo Build for X11................. : $with_x
    44  echo
    45 +echo Build with GtkStatusIcon...... : $enable_gtkstatusicon
    46  echo Enable Gestures............... : $enable_gestures
    47  echo Protocols to build dynamically : $DYNAMIC_PRPLS
    48  echo Protocols to link statically.. : $STATIC_PRPLS
    49 Index: pidgin/Makefile.am
    50 ===================================================================
    51 --- pidgin/Makefile.am.orig     2008-10-18 19:49:45.000000000 +0200
    52 +++ pidgin/Makefile.am  2008-11-06 00:17:02.000000000 +0100
    53 @@ -74,7 +74,6 @@
    54  bin_PROGRAMS = pidgin
    55  
    56  pidgin_SOURCES = \
    57 -       eggtrayicon.c \
    58         pidgincombobox.c \
    59         pidginstock.c \
    60         gtkaccount.c \
    61 @@ -91,7 +90,6 @@
    62         gtkdialogs.c \
    63         gtkdnd-hints.c \
    64         gtkdocklet.c \
    65 -       gtkdocklet-x11.c \
    66         gtkeventloop.c \
    67         gtkexpander.c \
    68         gtkft.c \
    69 @@ -124,6 +122,15 @@
    70         minidialog.c \
    71         pidgintooltip.c
    72  
    73 +if GTK_STATUS_ICON
    74 +pidgin_SOURCES += \
    75 +       gtkdocklet-gtk.c
    76 +else
    77 +pidgin_SOURCES += \
    78 +       gtkdocklet-x11.c \
    79 +       eggtrayicon.c
    80 +endif
    81 +
    82  pidgin_headers = \
    83         eggtrayicon.h \
    84         gtkaccount.h \
    85 Index: pidgin/gtkdocklet-gtk.c
    86 ===================================================================
    87 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
    88 +++ pidgin/gtkdocklet-gtk.c     2008-11-06 00:17:02.000000000 +0100
    89 @@ -0,0 +1,195 @@
    90 +/*
    91 + * System tray icon (aka docklet) plugin for Purple
    92 + *
    93 + * Copyright (C) 2007 Anders Hasselqvist
    94 + *
    95 + * This program is free software; you can redistribute it and/or
    96 + * modify it under the terms of the GNU General Public License as
    97 + * published by the Free Software Foundation; either version 2 of the
    98 + * License, or (at your option) any later version.
    99 + *
    100 + * This program is distributed in the hope that it will be useful, but
    101 + * WITHOUT ANY WARRANTY; without even the implied warranty of
    102 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    103 + * General Public License for more details.
    104 + *
    105 + * You should have received a copy of the GNU General Public License
    106 + * along with this program; if not, write to the Free Software
    107 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    108 + * 02111-1307, USA.
    109 + */
    110 +
    111 +#include "internal.h"
    112 +#include "pidgin.h"
    113 +#include "debug.h"
    114 +#include "prefs.h"
    115 +#include "pidginstock.h"
    116 +#include "gtkdocklet.h"
    117 +
    118 +#include <gtk/gtkstatusicon.h>
    119 +
    120 +
    121 +/* globals */
    122 +GtkStatusIcon *docklet = NULL;
    123 +
    124 +static void
    125 +docklet_gtk_status_clicked_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data)
    126 +{
    127 +       purple_debug(PURPLE_DEBUG_INFO, "docklet", "button clicked %d\n", button);
    128 +
    129 +#if defined(__APPLE__) && !defined(HAVE_X11)
    130 +       /* You can only click left mouse button on MacOSX native GTK. Let that be the menu */
    131 +       pidgin_docklet_clicked(3);
    132 +#else
    133 +       pidgin_docklet_clicked(button);
    134 +#endif
    135 +}
    136 +
    137 +static void
    138 +docklet_gtk_status_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending)
    139 +{
    140 +       const gchar *icon_name = NULL;
    141 +
    142 +       switch (status) {
    143 +               case PURPLE_STATUS_OFFLINE:
    144 +                       icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
    145 +                       break;
    146 +               case PURPLE_STATUS_AWAY:
    147 +                       icon_name = PIDGIN_STOCK_TRAY_AWAY;
    148 +                       break;
    149 +               case PURPLE_STATUS_UNAVAILABLE:
    150 +                       icon_name = PIDGIN_STOCK_TRAY_BUSY;
    151 +                       break;
    152 +               case PURPLE_STATUS_EXTENDED_AWAY:
    153 +                       icon_name = PIDGIN_STOCK_TRAY_XA;
    154 +                       break;
    155 +               case PURPLE_STATUS_INVISIBLE:
    156 +                       icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
    157 +                       break;
    158 +               default:
    159 +                       icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
    160 +                       break;
    161 +       }
    162 +
    163 +       if (pending)
    164 +               icon_name = PIDGIN_STOCK_TRAY_PENDING;
    165 +       if (connecting)
    166 +               icon_name = PIDGIN_STOCK_TRAY_CONNECT;
    167 +
    168 +       if(icon_name) {
    169 +               GtkWidget *win;
    170 +               GdkPixbuf *pixbuf;
    171 +
    172 +               /* We do these steps because gtk_status_icon_set_from_stock()
    173 +                  only accepts icons of exactly size GTK_ICON_SIZE_SMALL_TOOLBAR.
    174 +                  Doing it this way we force GtkStatusIcon to scale the pixbuf
    175 +                  itself */
    176 +               
    177 +               /* Er, yeah, a hack, but it works :).
    178 +                  We need to have a widget for getting a style */
    179 +               win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    180 +               gtk_widget_realize(win);
    181 +
    182 +               pixbuf = gtk_widget_render_icon(win, icon_name,
    183 +                                                                               GTK_ICON_SIZE_MENU, NULL);
    184 +
    185 +               if (pixbuf == NULL)
    186 +               {
    187 +                       gtk_widget_destroy(win);
    188 +                       return;
    189 +               }
    190 +
    191 +               gtk_status_icon_set_from_pixbuf(docklet, pixbuf);
    192 +               g_object_unref(pixbuf);
    193 +               gtk_widget_destroy(win);
    194 +       }
    195 +}
    196 +
    197 +static gboolean
    198 +docklet_gtk_status_resize_icon(GtkStatusIcon *status_icon, gint size, gpointer user_data)
    199 +{
    200 +       /* Let GTK rescale for now */
    201 +       return FALSE;
    202 +}
    203 +
    204 +static void
    205 +docklet_gtk_status_set_tooltip(gchar *tooltip)
    206 +{
    207 +       if (tooltip) {
    208 +               gtk_status_icon_set_tooltip(docklet, tooltip);
    209 +       } else {
    210 +               gtk_status_icon_set_tooltip(docklet, NULL);
    211 +       }
    212 +}
    213 +
    214 +static void
    215 +docklet_gtk_status_position_menu(GtkMenu *menu, int *x, int *y, gboolean *push_in,
    216 +                                                                       gpointer user_data)
    217 +{
    218 +       gtk_status_icon_position_menu(menu, x, y, push_in, docklet);
    219 +}
    220 +
    221 +static void
    222 +docklet_gtk_status_destroy()
    223 +{
    224 +       g_return_if_fail(docklet != NULL);
    225 +
    226 +       pidgin_docklet_remove();
    227 +       
    228 +       g_object_unref(G_OBJECT(docklet));
    229 +       docklet = NULL;
    230 +
    231 +       purple_debug(PURPLE_DEBUG_INFO, "docklet", "destroyed\n");
    232 +}
    233 +
    234 +static void
    235 +docklet_gtk_status_create(gboolean recreate)
    236 +{
    237 +       if (docklet) {
    238 +               /* if this is being called when a tray icon exists, it's because
    239 +                  something messed up. try destroying it before we proceed,
    240 +                  although docklet_refcount may be all hosed. hopefully won't happen. */
    241 +               purple_debug(PURPLE_DEBUG_WARNING, "docklet", "trying to create icon but it already exists?\n");
    242 +               docklet_gtk_status_destroy();
    243 +       }
    244 +
    245 +       docklet = gtk_status_icon_new();
    246 +       g_return_if_fail(docklet != NULL);
    247 +
    248 +       g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL);
    249 +       g_signal_connect(G_OBJECT(docklet), "size-changed", G_CALLBACK(docklet_gtk_status_resize_icon), NULL);
    250 +
    251 +       pidgin_docklet_embedded();
    252 +       gtk_status_icon_set_visible(docklet, TRUE);
    253 +       purple_debug(PURPLE_DEBUG_INFO, "docklet", "created\n");
    254 +}
    255 +
    256 +static void
    257 +docklet_gtk_status_create_ui_op()
    258 +{
    259 +       docklet_gtk_status_create(FALSE);
    260 +}
    261 +
    262 +
    263 +static void
    264 +docklet_gtk_status_set_blink(gboolean blinking)
    265 +{
    266 +       gtk_status_icon_set_blinking(docklet, blinking);
    267 +}
    268 +
    269 +static struct docklet_ui_ops ui_ops =
    270 +{
    271 +       docklet_gtk_status_create_ui_op,
    272 +       docklet_gtk_status_destroy,
    273 +       docklet_gtk_status_update_icon,
    274 +       NULL,
    275 +       docklet_gtk_status_set_tooltip,
    276 +       docklet_gtk_status_position_menu,
    277 +       docklet_gtk_status_set_blink
    278 +};
    279 +
    280 +void
    281 +docklet_ui_init()
    282 +{
    283 +       pidgin_docklet_set_ui_ops(&ui_ops);
    284 +}
    285 Index: pidgin/gtkdocklet-x11.c
    286 ===================================================================
    287 --- pidgin/gtkdocklet-x11.c.orig        2008-08-13 03:23:17.000000000 +0200
    288 +++ pidgin/gtkdocklet-x11.c     2008-11-06 00:17:02.000000000 +0100
    289 @@ -314,10 +314,11 @@
    290         docklet_x11_blank_icon,
    291         docklet_x11_set_tooltip,
    292  #if GTK_CHECK_VERSION(2,2,0)
    293 -       docklet_x11_position_menu
    294 +       docklet_x11_position_menu,
    295  #else
    296 -       NULL
    297 +       NULL,
    298  #endif
    299 +       NULL /* blink */
    300  };
    301  
    302  void
    303 Index: pidgin/gtkdocklet.c
    304 ===================================================================
    305 --- pidgin/gtkdocklet.c.orig    2008-08-06 23:57:07.000000000 +0200
    306 +++ pidgin/gtkdocklet.c 2008-11-06 00:17:02.000000000 +0100
    307 @@ -62,7 +62,7 @@
    308   * docklet status and utility functions
    309   **************************************************************************/
    310  static gboolean
    311 -docklet_blink_icon(gpointer data)
    312 +docklet_blink_icon_cb()
    313  {
    314         static gboolean blinked = FALSE;
    315         gboolean ret = FALSE; /* by default, don't keep blinking */
    316 @@ -85,6 +85,15 @@
    317         return ret;
    318  }
    319  
    320 +static void
    321 +docklet_blink_icon(gboolean blink)
    322 +{
    323 +       if (ui_ops->blink)
    324 +               ui_ops->blink(blink);
    325 +       else if (blink)
    326 +               docklet_blinking_timer = g_timeout_add(500, docklet_blink_icon_cb, NULL);
    327 +}
    328 +
    329  static GList *
    330  get_pending_list(guint max)
    331  {
    332 @@ -211,7 +220,9 @@
    333                 /* and schedule the blinker function if messages are pending */
    334                 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")
    335                         && pending && !connecting && docklet_blinking_timer == 0) {
    336 -                       docklet_blinking_timer = g_timeout_add(500, docklet_blink_icon, NULL);
    337 +                       docklet_blink_icon(TRUE);
    338 +               } else {
    339 +                       docklet_blink_icon(FALSE);
    340                 }
    341         }
    342  
    343 Index: pidgin/gtkdocklet.h
    344 ===================================================================
    345 --- pidgin/gtkdocklet.h.orig    2007-10-28 02:52:05.000000000 +0100
    346 +++ pidgin/gtkdocklet.h 2008-11-06 00:17:02.000000000 +0100
    347 @@ -35,6 +35,7 @@
    348         void (*blank_icon)(void);
    349         void (*set_tooltip)(gchar *);
    350         GtkMenuPositionFunc position_menu;
    351 +       void (*blink)(gboolean);
    352  };
    353  
    354  
    355 Index: pidgin/win32/gtkdocklet-win32.c
    356 ===================================================================
    357 --- pidgin/win32/gtkdocklet-win32.c.orig        2008-03-31 02:32:21.000000000 +0200
    358 +++ pidgin/win32/gtkdocklet-win32.c     2008-11-06 00:17:02.000000000 +0100
    359 @@ -661,7 +661,8 @@
    360         winpidgin_tray_update_icon,
    361         winpidgin_tray_blank_icon,
    362         winpidgin_tray_set_tooltip,
    363 -       NULL
    364 +       NULL,                                           /* position menu */
    365 +       NULL                                            /* blink */
    366  };
    367  
    368  /* Used by docklet's plugin load func */
  • deleted file files/ige-integration.diff

    diff -r 9b7fde062ca7 files/ige-integration.diff
    + -  
    1 --- pidgin/gtkblist.c   2007-12-07 15:37:11.000000000 +0100
    2 +++ ../pidgin-2.3.1/pidgin/gtkblist.c   2008-02-11 15:59:25.000000000 +0100
    3 @@ -27,6 +27,9 @@
    4  #include "internal.h"
    5  #include "pidgin.h"
    6  
    7 +#include "ige-mac-menu.h"
    8 +#include "ige-mac-dock.h"
    9 +#include "ige-mac-bundle.h"
    10  #include "account.h"
    11  #include "connection.h"
    12  #include "core.h"
    13 @@ -5311,6 +5314,7 @@
    14         pidgin_blist_restore_position();
    15         gtk_widget_show_all(GTK_WIDGET(gtkblist->vbox));
    16         gtk_widget_realize(GTK_WIDGET(gtkblist->window));
    17 +       ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(menu));
    18         purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible"));
    19  
    20         /* start the refresh timer */
    21 --- pidgin/ige-mac-bundle.c     1970-01-01 01:00:00.000000000 +0100
    22 +++ ../pidgin-2.3.1/pidgin/ige-mac-bundle.c     2008-02-11 14:38:28.000000000 +0100
    23 @@ -0,0 +1,377 @@
    24 +/* GTK+ Integration for app bundles.
    25 + *
    26 + * Copyright (C) 2007-2008 Imendio AB
    27 + *
    28 + * This library is free software; you can redistribute it and/or
    29 + * modify it under the terms of the GNU Lesser General Public
    30 + * License as published by the Free Software Foundation; version 2.1
    31 + * of the License.
    32 + *
    33 + * This library is distributed in the hope that it will be useful,
    34 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    35 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    36 + * Lesser General Public License for more details.
    37 + *
    38 + * You should have received a copy of the GNU Lesser General Public
    39 + * License along with this library; if not, write to the
    40 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    41 + * Boston, MA 02111-1307, USA.
    42 + */
    43 +
    44 +/* TODO: Add command line parsing and remove any
    45 + * -psn_... arguments?
    46 + */
    47 +
    48 +#include <gtk/gtk.h>
    49 +#include <Carbon/Carbon.h>
    50 +
    51 +#include "ige-mac-bundle.h"
    52 +
    53 +typedef struct IgeMacBundlePriv IgeMacBundlePriv;
    54 +
    55 +struct IgeMacBundlePriv {
    56 +  CFBundleRef  cf_bundle;
    57 +  gchar       *path;
    58 +  gchar       *id;
    59 +  gchar       *datadir;
    60 +  gchar       *localedir;
    61 +  UInt32       type;
    62 +  UInt32       creator;
    63 +};
    64 +
    65 +static void   mac_bundle_finalize              (GObject      *object);
    66 +static gchar *cf_string_to_utf8                (CFStringRef   str);
    67 +static void   mac_bundle_set_environment_value (IgeMacBundle *bundle,
    68 +                                                const gchar  *key,
    69 +                                                const gchar  *value);
    70 +
    71 +static IgeMacBundle *global_bundle;
    72 +
    73 +G_DEFINE_TYPE (IgeMacBundle, ige_mac_bundle, G_TYPE_OBJECT)
    74 +
    75 +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), IGE_TYPE_MAC_BUNDLE, IgeMacBundlePriv))
    76 +
    77 +static void
    78 +ige_mac_bundle_class_init (IgeMacBundleClass *class)
    79 +{
    80 +  GObjectClass *object_class = G_OBJECT_CLASS (class);
    81 +
    82 +  object_class->finalize = mac_bundle_finalize;
    83 +
    84 +  g_type_class_add_private (object_class, sizeof (IgeMacBundlePriv));
    85 +}
    86 +
    87 +static void
    88 +ige_mac_bundle_init (IgeMacBundle *bundle)
    89 +{
    90 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    91 +  CFURLRef          cf_url;
    92 +  CFStringRef       cf_string;
    93 +  CFDictionaryRef   cf_dict;
    94 +
    95 +  priv->cf_bundle = CFBundleGetMainBundle ();
    96 +  if (!priv->cf_bundle)
    97 +    return;
    98 +
    99 +  CFRetain (priv->cf_bundle);
    100 +
    101 +  /* Bundle or binary location. */
    102 +  cf_url = CFBundleCopyBundleURL (priv->cf_bundle);
    103 +  cf_string = CFURLCopyFileSystemPath (cf_url, kCFURLPOSIXPathStyle);
    104 +  priv->path = cf_string_to_utf8 (cf_string);
    105 +  CFRelease (cf_string);
    106 +  CFRelease (cf_url);
    107 +
    108 +  /* Package info. */
    109 +  CFBundleGetPackageInfo (priv->cf_bundle, &priv->type, &priv->creator);
    110 +
    111 +  /* Identifier. */
    112 +  cf_string = CFBundleGetIdentifier (priv->cf_bundle);
    113 +  if (cf_string)
    114 +    priv->id = cf_string_to_utf8 (cf_string);
    115 +
    116 +  /* Get non-localized keys. */
    117 +  cf_dict = CFBundleGetInfoDictionary (priv->cf_bundle);
    118 +  if (cf_dict)
    119 +    {
    120 +      CFDictionaryRef   env_dict;
    121 +      CFIndex           n_keys, i;
    122 +      const void      **keys;
    123 +      const void      **values;
    124 +
    125 +      env_dict = (CFDictionaryRef) CFDictionaryGetValue (cf_dict, CFSTR ("LSEnvironment"));
    126 +      if (env_dict)
    127 +        {
    128 +          n_keys = CFDictionaryGetCount (env_dict);
    129 +
    130 +          keys = (const void **) g_new (void *, n_keys);
    131 +          values = (const void **) g_new (void *, n_keys);
    132 +
    133 +          CFDictionaryGetKeysAndValues (env_dict, keys, values);
    134 +
    135 +          for (i = 0; i < n_keys; i++)
    136 +            {
    137 +              gchar *key;
    138 +              gchar *value;
    139 +
    140 +              key = cf_string_to_utf8 ((CFStringRef) keys[i]);
    141 +              value = cf_string_to_utf8 ((CFStringRef) values[i]);
    142 +
    143 +              mac_bundle_set_environment_value (bundle, key, value);
    144 +
    145 +              g_free (key);
    146 +              g_free (value);
    147 +            }
    148 +
    149 +          g_free (keys);
    150 +          g_free (values);
    151 +        }     
    152 +    }
    153 +}
    154 +
    155 +static void
    156 +mac_bundle_finalize (GObject *object)
    157 +{
    158 +  IgeMacBundlePriv *priv;
    159 +
    160 +  priv = GET_PRIV (object);
    161 +
    162 +  g_free (priv->path);
    163 +  g_free (priv->id);
    164 +  g_free (priv->datadir);
    165 +  g_free (priv->localedir);
    166 +
    167 +  CFRelease (priv->cf_bundle);
    168 +
    169 +  G_OBJECT_CLASS (ige_mac_bundle_parent_class)->finalize (object);
    170 +}
    171 +
    172 +IgeMacBundle *
    173 +ige_mac_bundle_new (void)
    174 +{
    175 +  return g_object_new (IGE_TYPE_MAC_BUNDLE, NULL);
    176 +}
    177 +
    178 +IgeMacBundle *
    179 +ige_mac_bundle_get_default (void)
    180 +{
    181 +  if (!global_bundle)
    182 +    global_bundle = ige_mac_bundle_new ();
    183 +
    184 +  return global_bundle;
    185 +}
    186 +
    187 +static gchar *
    188 +cf_string_to_utf8 (CFStringRef str)
    189 +{
    190 +  CFIndex  len;
    191 +  gchar   *ret;
    192 +
    193 +  len = CFStringGetMaximumSizeForEncoding (CFStringGetLength (str),
    194 +                                           kCFStringEncodingUTF8) + 1;
    195 +
    196 +  ret = g_malloc (len);
    197 +  ret[len] = '\0';
    198 +
    199 +  if (CFStringGetCString (str, ret, len, kCFStringEncodingUTF8))
    200 +    return ret;
    201 +
    202 +  g_free (ret);
    203 +  return NULL;
    204 +}
    205 +
    206 +static void
    207 +mac_bundle_set_environment_value (IgeMacBundle *bundle,
    208 +                                  const gchar  *key,
    209 +                                  const gchar  *value)
    210 +{
    211 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    212 +  GRegex           *regex;
    213 +  gchar            *new_value;
    214 +
    215 +  regex = g_regex_new ("@executable_path", 0, 0, NULL);
    216 +
    217 +  new_value = g_regex_replace_literal (regex,
    218 +                                       value,
    219 +                                       -1,
    220 +                                       0,
    221 +                                       priv->path,
    222 +                                       0, NULL);
    223 +
    224 +  g_print ("%s => %s\n", value, new_value);
    225 +
    226 +  if (new_value)
    227 +    value = new_value;
    228 +
    229 +
    230 +  g_setenv (key, value, TRUE);
    231 +
    232 +  g_free (new_value);
    233 +  g_regex_unref (regex);
    234 +}
    235 +
    236 +const gchar *
    237 +ige_mac_bundle_get_id (IgeMacBundle *bundle)
    238 +{
    239 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    240 +
    241 +  return priv->id;
    242 +}
    243 +
    244 +const gchar *
    245 +ige_mac_bundle_get_path (IgeMacBundle *bundle)
    246 +{
    247 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    248 +
    249 +  return priv->path;
    250 +}
    251 +
    252 +gboolean
    253 +ige_mac_bundle_get_is_app_bundle (IgeMacBundle *bundle)
    254 +{
    255 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    256 +
    257 +  return (priv->type == 'APPL' && priv->id);
    258 +}
    259 +
    260 +const gchar *
    261 +ige_mac_bundle_get_datadir (IgeMacBundle *bundle)
    262 +{
    263 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    264 +
    265 +  if (!ige_mac_bundle_get_is_app_bundle (bundle))
    266 +    return NULL;
    267 +
    268 +  if (!priv->datadir)
    269 +    {
    270 +      priv->datadir = g_build_filename (priv->path,
    271 +                                        "Contents",
    272 +                                        "Resources",
    273 +                                        "share",
    274 +                                        NULL);
    275 +    }
    276 +
    277 +  return priv->datadir;
    278 +}
    279 +
    280 +const gchar *
    281 +ige_mac_bundle_get_localedir (IgeMacBundle *bundle)
    282 +{
    283 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    284 +
    285 +  if (!ige_mac_bundle_get_is_app_bundle (bundle))
    286 +    return NULL;
    287 +
    288 +  if (!priv->localedir)
    289 +    {
    290 +      priv->localedir = g_build_filename (priv->path,
    291 +                                          "Contents",
    292 +                                          "Resources",
    293 +                                          "share",
    294 +                                          "locale",
    295 +                                          NULL);
    296 +    }
    297 +
    298 +  return priv->localedir;
    299 +}
    300 +
    301 +void
    302 +ige_mac_bundle_setup_environment (IgeMacBundle *bundle)
    303 +{
    304 +  IgeMacBundlePriv *priv = GET_PRIV (bundle);
    305 +  gchar            *resources;
    306 +  gchar            *share, *lib, *etc;
    307 +  gchar            *etc_xdg, *etc_immodules, *etc_gtkrc;
    308 +  gchar            *etc_pixbuf, *etc_pangorc;
    309 +  const gchar      *rc_files;
    310 +
    311 +  if (!ige_mac_bundle_get_is_app_bundle (bundle))
    312 +    return;
    313 +
    314 +  resources = g_build_filename (priv->path,
    315 +                                "Contents",
    316 +                                "Resources",
    317 +                                NULL);
    318 +
    319 +  share = g_build_filename (resources, "share", NULL);
    320 +  lib = g_build_filename (resources, "lib", NULL);
    321 +  etc = g_build_filename (resources, "etc", NULL);
    322 +  etc_xdg = g_build_filename (etc, "xdg", NULL);
    323 +  etc_immodules = g_build_filename (etc, "gtk-2.0", "gtk.immodules", NULL);
    324 +  etc_gtkrc = g_build_filename (etc, "gtk-2.0", "gtkrc", NULL);
    325 +  etc_pixbuf = g_build_filename (etc, "gtk-2.0", "gdk-pixbuf.loaders", NULL);
    326 +  etc_pangorc = g_build_filename (etc, "pango", "pangorc", NULL);
    327 +
    328 +  g_setenv ("XDG_CONFIG_DIRS", etc_xdg, TRUE);
    329 +  g_setenv ("XDG_DATA_DIRS", share, TRUE);
    330 +  g_setenv ("GTK_DATA_PREFIX", share, TRUE);
    331 +  g_setenv ("GTK_EXE_PREFIX", resources, TRUE);
    332 +  g_setenv ("GTK_PATH_PREFIX", resources, TRUE);
    333 +
    334 +  /* Append the normal gtkrc path to allow customizing the theme from
    335 +   * Info.plist.
    336 +   */
    337 +  rc_files = g_getenv ("GTK2_RC_FILES");
    338 +  if (rc_files)
    339 +    {
    340 +      gchar *tmp;
    341 +
    342 +      tmp = g_strdup_printf ("%s:%s", rc_files, etc_gtkrc);
    343 +      g_setenv ("GTK2_RC_FILES", tmp, TRUE);
    344 +      g_free (tmp);
    345 +    }
    346 +  else
    347 +    g_setenv ("GTK2_RC_FILES", etc_gtkrc, TRUE);
    348 +
    349 +  g_setenv ("GTK_IM_MODULE_FILE", etc_immodules, TRUE);
    350 +  g_setenv ("GDK_PIXBUF_MODULE_FILE", etc_pixbuf, TRUE);
    351 +  g_setenv ("PANGO_RC_FILE", etc_pangorc, TRUE);
    352 +  g_setenv ("CHARSETALIASDIR", lib, TRUE);
    353 +
    354 +  // could add FONTCONFIG_FILE
    355 +
    356 +  /*export LANG="\`grep \"\\\`defaults read .GlobalPreferences AppleCollationOrder \
    357 + 2>&1\\\`_\" /usr/share/locale/locale.alias | tail -n1 | sed 's/\./ /' | \
    358 + awk '{print \$2}'\`.UTF-8"*/
    359 +
    360 +  g_free (share);
    361 +  g_free (lib);
    362 +  g_free (etc);
    363 +  g_free (etc_xdg);
    364 +  g_free (etc_immodules);
    365 +  g_free (etc_gtkrc);
    366 +  g_free (etc_pixbuf);
    367 +  g_free (etc_pangorc);
    368 +}
    369 +
    370 +gchar *
    371 +ige_mac_bundle_get_resource_path (IgeMacBundle *bundle,
    372 +                                  const gchar  *name,
    373 +                                  const gchar  *type,
    374 +                                  const gchar  *subdir)
    375 +{
    376 +  IgeMacBundlePriv *priv;
    377 +  CFURLRef          cf_url;
    378 +  CFStringRef       cf_string;
    379 +  gchar            *path;
    380 +
    381 +  if (!bundle)
    382 +    bundle = ige_mac_bundle_get_default ();
    383 +
    384 +  priv = GET_PRIV (bundle);
    385 +
    386 +  if (!priv->cf_bundle)
    387 +    return NULL;
    388 +
    389 +  // FIXME: Look at using CFURLGetFileSystemRepresentation (urlcf_, true, (UInt8*)outPathName, 256)
    390 +
    391 +  // FIXME: crate real cfstring here...
    392 +  cf_url = CFBundleCopyResourceURL (priv->cf_bundle,
    393 +                                    CFSTR("name"), CFSTR("type"), CFSTR("subdir"));
    394 +  cf_string = CFURLCopyFileSystemPath (cf_url, kCFURLPOSIXPathStyle);
    395 +  path = cf_string_to_utf8 (cf_string);
    396 +  CFRelease (cf_string);
    397 +  CFRelease (cf_url);
    398 +
    399 +  return path;
    400 +}
    401 --- pidgin/ige-mac-bundle.h     1970-01-01 01:00:00.000000000 +0100
    402 +++ ../pidgin-2.3.1/pidgin/ige-mac-bundle.h     2008-02-11 14:38:30.000000000 +0100
    403 @@ -0,0 +1,62 @@
    404 +/* GTK+ Integration for app bundles.
    405 + *
    406 + * Copyright (C) 2007-2008 Imendio AB
    407 + *
    408 + * This library is free software; you can redistribute it and/or
    409 + * modify it under the terms of the GNU Lesser General Public
    410 + * License as published by the Free Software Foundation; version 2.1
    411 + * of the License.
    412 + *
    413 + * This library is distributed in the hope that it will be useful,
    414 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    415 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    416 + * Lesser General Public License for more details.
    417 + *
    418 + * You should have received a copy of the GNU Lesser General Public
    419 + * License along with this library; if not, write to the
    420 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    421 + * Boston, MA 02111-1307, USA.
    422 + */
    423 +
    424 +#ifndef __IGE_MAC_BUNDLE_H__
    425 +#define __IGE_MAC_BUNDLE_H__
    426 +
    427 +#include <glib-object.h>
    428 +
    429 +G_BEGIN_DECLS
    430 +
    431 +#define IGE_TYPE_MAC_BUNDLE            (ige_mac_bundle_get_type ())
    432 +#define IGE_MAC_BUNDLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IGE_TYPE_MAC_BUNDLE, IgeMacBundle))
    433 +#define IGE_MAC_BUNDLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IGE_TYPE_MAC_BUNDLE, IgeMacBundleClass))
    434 +#define IGE_IS_MAC_BUNDLE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IGE_TYPE_MAC_BUNDLE))
    435 +#define IGE_IS_MAC_BUNDLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IGE_TYPE_MAC_BUNDLE))
    436 +#define IGE_MAC_BUNDLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IGE_TYPE_MAC_BUNDLE, IgeMacBundleClass))
    437 +
    438 +typedef struct _IgeMacBundle      IgeMacBundle;
    439 +typedef struct _IgeMacBundleClass IgeMacBundleClass;
    440 +
    441 +struct _IgeMacBundle {
    442 +  GObject parent_instance;
    443 +};
    444 +
    445 +struct _IgeMacBundleClass {
    446 +  GObjectClass parent_class;
    447 +};
    448 +
    449 +GType         ige_mac_bundle_get_type          (void);
    450 +IgeMacBundle *ige_mac_bundle_new               (void);
    451 +IgeMacBundle *ige_mac_bundle_get_default       (void);
    452 +void          ige_mac_bundle_setup_environment (IgeMacBundle *bundle);
    453 +const gchar * ige_mac_bundle_get_id            (IgeMacBundle *bundle);
    454 +const gchar * ige_mac_bundle_get_path          (IgeMacBundle *bundle);
    455 +gboolean      ige_mac_bundle_get_is_app_bundle (IgeMacBundle *bundle);
    456 +const gchar * ige_mac_bundle_get_localedir     (IgeMacBundle *bundle);
    457 +const gchar * ige_mac_bundle_get_datadir       (IgeMacBundle *bundle);
    458 +gchar *       ige_mac_bundle_get_resource_path (IgeMacBundle *bundle,
    459 +                                                const gchar  *name,
    460 +                                                const gchar  *type,
    461 +                                                const gchar  *subdir);
    462 +
    463 +G_END_DECLS
    464 +
    465 +#endif /* __IGE_MAC_BUNDLE_H__ */
    466 --- pidgin/ige-mac-dock.c       1970-01-01 01:00:00.000000000 +0100
    467 +++ ../pidgin-2.3.1/pidgin/ige-mac-dock.c       2008-02-11 14:38:28.000000000 +0100
    468 @@ -0,0 +1,449 @@
    469 +/* GTK+ Integration for the Mac OS X Dock.
    470 + *
    471 + * Copyright (C) 2007-2008 Imendio AB
    472 + *
    473 + * This library is free software; you can redistribute it and/or
    474 + * modify it under the terms of the GNU Lesser General Public
    475 + * License as published by the Free Software Foundation; version 2.1
    476 + * of the License.
    477 + *
    478 + * This library is distributed in the hope that it will be useful,
    479 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    480 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    481 + * Lesser General Public License for more details.
    482 + *
    483 + * You should have received a copy of the GNU Lesser General Public
    484 + * License along with this library; if not, write to the
    485 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    486 + * Boston, MA 02111-1307, USA.
    487 + */
    488 +
    489 +/* FIXME: Add example like this to docs for the open documents stuff:
    490 +
    491 +    <key>CFBundleDocumentTypes</key>
    492 +    <array>
    493 +      <dict>
    494 +        <key>CFBundleTypeExtensions</key>
    495 +        <array>
    496 +          <string>txt</string>
    497 +        </array>
    498 +      </dict>
    499 +    </array>
    500 +
    501 +*/
    502 +
    503 +#include <config.h>
    504 +#include <Carbon/Carbon.h>
    505 +#include <sys/param.h>
    506 +#include <gtk/gtk.h>
    507 +
    508 +#include "ige-mac-dock.h"
    509 +#include "ige-mac-bundle.h"
    510 +#include "ige-mac-image-utils.h"
    511 +
    512 +enum {
    513 +  CLICKED,
    514 +  QUIT_ACTIVATE,
    515 +  OPEN_DOCUMENTS,
    516 +  LAST_SIGNAL
    517 +};
    518 +
    519 +static guint signals[LAST_SIGNAL] = { 0 };
    520 +
    521 +typedef struct IgeMacDockPriv IgeMacDockPriv;
    522 +
    523 +struct IgeMacDockPriv {
    524 +  glong id;
    525 +};
    526 +
    527 +static void  mac_dock_finalize                  (GObject          *object);
    528 +static OSErr mac_dock_handle_quit               (const AppleEvent *inAppleEvent,
    529 +                                                 AppleEvent       *outAppleEvent,
    530 +                                                 long              inHandlerRefcon);
    531 +static OSErr mac_dock_handle_open_documents     (const AppleEvent *inAppleEvent,
    532 +                                                 AppleEvent       *outAppleEvent,
    533 +                                                 long              inHandlerRefcon);
    534 +static OSErr mac_dock_handle_open_application   (const AppleEvent *inAppleEvent,
    535 +                                                 AppleEvent       *outAppleEvent,
    536 +                                                 long              inHandlerRefcon);
    537 +static OSErr mac_dock_handle_reopen_application (const AppleEvent *inAppleEvent,
    538 +                                                 AppleEvent       *outAppleEvent,
    539 +                                                 long              inHandlerRefcon);
    540 +
    541 +G_DEFINE_TYPE (IgeMacDock, ige_mac_dock, G_TYPE_OBJECT)
    542 +
    543 +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), IGE_TYPE_MAC_DOCK, IgeMacDockPriv))
    544 +
    545 +static GList      *handlers;
    546 +static IgeMacDock *global_dock;
    547 +
    548 +static void
    549 +ige_mac_dock_class_init (IgeMacDockClass *class)
    550 +{
    551 +  GObjectClass *object_class = G_OBJECT_CLASS (class);
    552 +
    553 +  object_class->finalize = mac_dock_finalize;
    554 +
    555 +  signals[CLICKED] =
    556 +    g_signal_new ("clicked",
    557 +                  IGE_TYPE_MAC_DOCK,
    558 +                  G_SIGNAL_RUN_LAST,
    559 +                  0,
    560 +                  NULL, NULL,
    561 +                  g_cclosure_marshal_VOID__VOID,
    562 +                  G_TYPE_NONE, 0);
    563 +
    564 +  /* FIXME: Need marshaller. */
    565 +  signals[OPEN_DOCUMENTS] =
    566 +    g_signal_new ("open-documents",
    567 +                  IGE_TYPE_MAC_DOCK,
    568 +                  G_SIGNAL_RUN_LAST,
    569 +                  0,
    570 +                  NULL, NULL,
    571 +                  g_cclosure_marshal_VOID__VOID,
    572 +                  G_TYPE_NONE, 0);
    573 +
    574 +  signals[QUIT_ACTIVATE] =
    575 +    g_signal_new ("quit-activate",
    576 +                  IGE_TYPE_MAC_DOCK,
    577 +                  G_SIGNAL_RUN_LAST,
    578 +                  0,
    579 +                  NULL, NULL,
    580 +                  g_cclosure_marshal_VOID__VOID,
    581 +                  G_TYPE_NONE, 0);
    582 +
    583 +  g_type_class_add_private (object_class, sizeof (IgeMacDockPriv));
    584 +
    585 +  /* FIXME: Just testing with triggering Carbon to take control over
    586 +   * the dock menu events instead of Cocoa (which happens when the
    587 +   * sharedApplication is created) to get custom dock menu working
    588 +   * with carbon menu code. However, doing this makes the dock icon
    589 +   * not get a "running triangle".
    590 +   */
    591 +#if 0
    592 +  EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
    593 +  EventRef event;
    594 
    595 +  ReceiveNextEvent (GetEventTypeCount (kFakeEventList),
    596 +                    kFakeEventList,
    597 +                    kEventDurationNoWait, false,
    598 +                    &event);
    599 +#endif
    600 +}
    601 +
    602 +static void
    603 +ige_mac_dock_init (IgeMacDock *dock)
    604 +{
    605 +  IgeMacDockPriv *priv = GET_PRIV (dock);
    606 +  static glong    id;
    607 +
    608 +  priv->id = ++id;
    609 +
    610 +  handlers = g_list_prepend (handlers, dock);
    611 +
    612 +  AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
    613 +                         mac_dock_handle_quit,
    614 +                         priv->id, true);
    615 +  AEInstallEventHandler (kCoreEventClass, kAEOpenApplication,
    616 +                         mac_dock_handle_open_application,
    617 +                         priv->id, true);
    618 +  AEInstallEventHandler (kCoreEventClass, kAEReopenApplication,
    619 +                         mac_dock_handle_reopen_application,
    620 +                         priv->id, true);
    621 +  AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments,
    622 +                         mac_dock_handle_open_documents,
    623 +                         priv->id, true);
    624 +}
    625 +
    626 +static void
    627 +mac_dock_finalize (GObject *object)
    628 +{
    629 +  IgeMacDockPriv *priv;
    630 +
    631 +  priv = GET_PRIV (object);
    632 +
    633 +  AERemoveEventHandler (kCoreEventClass, kAEQuitApplication,
    634 +                        mac_dock_handle_quit, false);
    635 +  AERemoveEventHandler (kCoreEventClass, kAEReopenApplication,
    636 +                        mac_dock_handle_reopen_application, false);
    637 +  AERemoveEventHandler (kCoreEventClass, kAEOpenApplication,
    638 +                        mac_dock_handle_open_application, false);
    639 +  AERemoveEventHandler (kCoreEventClass, kAEOpenDocuments,
    640 +                        mac_dock_handle_open_documents, false);
    641 +
    642 +  handlers = g_list_remove (handlers, object);
    643 +
    644 +  G_OBJECT_CLASS (ige_mac_dock_parent_class)->finalize (object);
    645 +}
    646 +
    647 +IgeMacDock *
    648 +ige_mac_dock_new (void)
    649 +{
    650 +  return g_object_new (IGE_TYPE_MAC_DOCK, NULL);
    651 +}
    652 +
    653 +IgeMacDock *
    654 +ige_mac_dock_get_default (void)
    655 +{
    656 +  if (!global_dock)
    657 +    global_dock = g_object_new (IGE_TYPE_MAC_DOCK, NULL);
    658 +
    659 +  return global_dock;
    660 +}
    661 +
    662 +static IgeMacDock *
    663 +mac_dock_get_from_id (gulong id)
    664 +{
    665 +  GList      *l;
    666 +  IgeMacDock *dock = NULL;
    667 +
    668 +  for (l = handlers; l; l = l->next)
    669 +    {
    670 +      dock = l->data;
    671 +      if (GET_PRIV (dock)->id == id)
    672 +        break;
    673 +
    674 +      dock = NULL;
    675 +  }
    676 +
    677 +  return dock;
    678 +}
    679 +
    680 +static OSErr
    681 +mac_dock_handle_quit (const AppleEvent *inAppleEvent,
    682 +                      AppleEvent       *outAppleEvent,
    683 +                      long              inHandlerRefcon)
    684 +{
    685 +  IgeMacDock *dock;
    686 +
    687 +  dock = mac_dock_get_from_id (inHandlerRefcon);
    688 +
    689 +  if (dock)
    690 +    g_signal_emit (dock, signals[QUIT_ACTIVATE], 0);
    691 +
    692 +  return noErr;
    693 +}
    694 +
    695 +static OSErr
    696 +mac_dock_handle_open_application (const AppleEvent *inAppleEvent,
    697 +                                  AppleEvent       *outAppleEvent,
    698 +                                  long              inHandlerRefCon)
    699 +{
    700 +  g_print ("FIXME: mac_dock_handle_open_application\n");
    701 +
    702 +  return noErr;
    703 +}
    704 +
    705 +static OSErr
    706 +mac_dock_handle_reopen_application (const AppleEvent *inAppleEvent,
    707 +                                    AppleEvent       *outAppleEvent,
    708 +                                    long              inHandlerRefcon)
    709 +{
    710 +  IgeMacDock *dock;
    711 +
    712 +  dock = mac_dock_get_from_id (inHandlerRefcon);
    713 +
    714 +  if (dock)
    715 +    g_signal_emit (dock, signals[CLICKED], 0);
    716 
    717 +  return noErr;
    718 +}
    719 +
    720 +static OSErr
    721 +mac_dock_handle_open_documents (const AppleEvent *inAppleEvent,
    722 +                                AppleEvent       *outAppleEvent,
    723 +                                long              inHandlerRefCon)
    724 +{
    725 +  IgeMacDock *dock;
    726 +  OSStatus    status;
    727 +  AEDescList  documents;
    728 +  gchar       path[MAXPATHLEN];
    729 +
    730 +  g_print ("FIXME: mac_dock_handle_open_documents\n");
    731 +
    732 +  dock = mac_dock_get_from_id (inHandlerRefCon);
    733 +
    734 +  status = AEGetParamDesc (inAppleEvent,
    735 +                           keyDirectObject, typeAEList,
    736 +                           &documents);
    737 +  if (status == noErr)
    738 +    {
    739 +      long count = 0;
    740 +      int  i;
    741 +
    742 +      AECountItems (&documents, &count);
    743 +
    744 +      for (i = 0; i < count; i++)
    745 +        {
    746 +          FSRef ref;
    747 +
    748 +          status = AEGetNthPtr (&documents, i + 1, typeFSRef,
    749 +                                0, 0, &ref, sizeof (ref),
    750 +                                0);
    751 +          if (status != noErr)
    752 +            continue;
    753 +
    754 +          FSRefMakePath (&ref, path, MAXPATHLEN);
    755 +
    756 +          /* FIXME: Add to a list, then emit the open-documents
    757 +           * signal.
    758 +           */
    759 +          g_print ("  %s\n", path);
    760 +        }
    761 +    }
    762 +       
    763 +    return status;
    764 +}
    765 +
    766 +void
    767 +ige_mac_dock_set_icon_from_pixbuf (IgeMacDock *dock,
    768 +                                   GdkPixbuf  *pixbuf)
    769 +{
    770 +  if (!pixbuf)
    771 +    RestoreApplicationDockTileImage ();
    772 +  else
    773 +    {
    774 +      CGImageRef image;
    775 +
    776 +      image = ige_mac_image_from_pixbuf (pixbuf);
    777 +      SetApplicationDockTileImage (image);
    778 +      CGImageRelease (image);
    779 +    }
    780 +}
    781 +
    782 +void
    783 +ige_mac_dock_set_icon_from_resource (IgeMacDock   *dock,
    784 +                                     IgeMacBundle *bundle,
    785 +                                     const gchar  *name,
    786 +                                     const gchar  *type,
    787 +                                     const gchar  *subdir)
    788 +{
    789 +  gchar *path;
    790 +
    791 +  g_return_if_fail (IGE_IS_MAC_DOCK (dock));
    792 +  g_return_if_fail (name != NULL);
    793 +
    794 +  path = ige_mac_bundle_get_resource_path (bundle, name, type, subdir);
    795 +  if (path)
    796 +    {
    797 +      GdkPixbuf *pixbuf;
    798 +
    799 +      pixbuf = gdk_pixbuf_new_from_file (path, NULL);
    800 +      if (pixbuf)
    801 +        {
    802 +          ige_mac_dock_set_icon_from_pixbuf (dock, pixbuf);
    803 +          g_object_unref (pixbuf);
    804 +        }
    805 +
    806 +      g_free (path);
    807 +    }
    808 +}
    809 +
    810 +void
    811 +ige_mac_dock_set_overlay_from_pixbuf (IgeMacDock  *dock,
    812 +                                      GdkPixbuf   *pixbuf)
    813 +{
    814 +  CGImageRef image;
    815 +
    816 +  g_return_if_fail (IGE_IS_MAC_DOCK (dock));
    817 +  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
    818 +
    819 +  image = ige_mac_image_from_pixbuf (pixbuf);
    820 +  OverlayApplicationDockTileImage (image);
    821 +  CGImageRelease (image);
    822 +}
    823 +
    824 +void
    825 +ige_mac_dock_set_overlay_from_resource (IgeMacDock   *dock,
    826 +                                        IgeMacBundle *bundle,
    827 +                                        const gchar  *name,
    828 +                                        const gchar  *type,
    829 +                                        const gchar  *subdir)
    830 +{
    831 +  gchar *path;
    832 +
    833 +  g_return_if_fail (IGE_IS_MAC_DOCK (dock));
    834 +  g_return_if_fail (name != NULL);
    835 +
    836 +  path = ige_mac_bundle_get_resource_path (bundle, name, type, subdir);
    837 +  if (path)
    838 +    {
    839 +      GdkPixbuf *pixbuf;
    840 +
    841 +      pixbuf = gdk_pixbuf_new_from_file (path, NULL);
    842 +      if (pixbuf)
    843 +        {
    844 +          ige_mac_dock_set_overlay_from_pixbuf (dock, pixbuf);
    845 +          g_object_unref (pixbuf);
    846 +        }
    847 +
    848 +      g_free (path);
    849 +    }
    850 +}
    851 +
    852 +struct _IgeMacAttentionRequest {
    853 +  NMRec    nm_request;
    854 +  guint    timeout_id;
    855 +  gboolean is_cancelled;
    856 +};
    857 +
    858 +static gboolean
    859 +mac_dock_attention_cb (IgeMacAttentionRequest *request)
    860 +{
    861 +  request->timeout_id = 0;
    862 +  request->is_cancelled = TRUE;
    863 +
    864 +  NMRemove (&request->nm_request);
    865 +
    866 +  return FALSE;
    867 +}
    868 +
    869 +
    870 +/* FIXME: Add listener for "application activated" and cancel any
    871 + * requests.
    872 + */
    873 +IgeMacAttentionRequest *
    874 +ige_mac_dock_attention_request (IgeMacDock          *dock,
    875 +                                IgeMacAttentionType  type)
    876 +{
    877 +  IgeMacAttentionRequest *request;
    878 +
    879 +  request = g_new0 (IgeMacAttentionRequest, 1);
    880 +
    881 +  request->nm_request.nmMark = 1;
    882 +  request->nm_request.qType = nmType;
    883 
    884 +  if (NMInstall (&request->nm_request) != noErr)
    885 +    {
    886 +      g_free (request);
    887 +      return NULL;
    888 +    }
    889 +
    890 +  if (type == IGE_MAC_ATTENTION_INFO)
    891 +    request->timeout_id = gdk_threads_add_timeout (
    892 +            1000,
    893 +            (GSourceFunc) mac_dock_attention_cb,
    894 +            request);
    895 +
    896 +  return request;
    897 +}
    898 +
    899 +void
    900 +ige_mac_dock_attention_cancel (IgeMacDock             *dock,
    901 +                               IgeMacAttentionRequest *request)
    902 +{
    903 +  if (request->timeout_id)
    904 +    g_source_remove (request->timeout_id);
    905 +
    906 +  if (!request->is_cancelled)
    907 +    NMRemove (&request->nm_request);
    908 +
    909 +  g_free (request);
    910 +}
    911 +
    912 +GType
    913 +ige_mac_attention_type_get_type (void)
    914 +{
    915 +  /* FIXME */
    916 +  return 0;
    917 +}
    918 --- pidgin/ige-mac-dock.h       1970-01-01 01:00:00.000000000 +0100
    919 +++ ../pidgin-2.3.1/pidgin/ige-mac-dock.h       2008-02-11 14:38:30.000000000 +0100
    920 @@ -0,0 +1,83 @@
    921 +/* GTK+ Integration for the Mac OS X Dock.
    922 + *
    923 + * Copyright (C) 2007-2008 Imendio AB
    924 + *
    925 + * This library is free software; you can redistribute it and/or
    926 + * modify it under the terms of the GNU Lesser General Public
    927 + * License as published by the Free Software Foundation; version 2.1
    928 + * of the License.
    929 + *
    930 + * This library is distributed in the hope that it will be useful,
    931 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    932 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    933 + * Lesser General Public License for more details.
    934 + *
    935 + * You should have received a copy of the GNU Lesser General Public
    936 + * License along with this library; if not, write to the
    937 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    938 + * Boston, MA 02111-1307, USA.
    939 + */
    940 +
    941 +#ifndef __IGE_MAC_DOCK_H__
    942 +#define __IGE_MAC_DOCK_H__
    943 +
    944 +#include <gtk/gtk.h>
    945 +#include <ige-mac-bundle.h>
    946 +
    947 +G_BEGIN_DECLS
    948 +
    949 +#define IGE_TYPE_MAC_DOCK            (ige_mac_dock_get_type ())
    950 +#define IGE_MAC_DOCK(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), IGE_TYPE_MAC_DOCK, IgeMacDock))
    951 +#define IGE_MAC_DOCK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), IGE_TYPE_MAC_DOCK, IgeMacDockClass))
    952 +#define IGE_IS_MAC_DOCK(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IGE_TYPE_MAC_DOCK))
    953 +#define IGE_IS_MAC_DOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IGE_TYPE_MAC_DOCK))
    954 +#define IGE_MAC_DOCK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), IGE_TYPE_MAC_DOCK, IgeMacDockClass))
    955 +
    956 +typedef struct _IgeMacDock      IgeMacDock;
    957 +typedef struct _IgeMacDockClass IgeMacDockClass;
    958 +
    959 +typedef struct _IgeMacAttentionRequest IgeMacAttentionRequest;
    960 +
    961 +struct _IgeMacDock
    962 +{
    963 +  GObject parent_instance;
    964 +};
    965 +
    966 +struct _IgeMacDockClass
    967 +{
    968 +  GObjectClass parent_class;
    969 +};
    970 +
    971 +typedef enum {
    972 +        IGE_MAC_ATTENTION_CRITICAL,
    973 +        IGE_MAC_ATTENTION_INFO
    974 +} IgeMacAttentionType;
    975 +
    976 +GType                   ige_mac_dock_get_type                  (void);
    977 +IgeMacDock *            ige_mac_dock_new                       (void);
    978 +IgeMacDock *            ige_mac_dock_get_default               (void);
    979 +void                    ige_mac_dock_set_icon_from_pixbuf      (IgeMacDock             *dock,
    980 +                                                                GdkPixbuf              *pixbuf);
    981 +void                    ige_mac_dock_set_icon_from_resource    (IgeMacDock             *dock,
    982 +                                                                IgeMacBundle           *bundle,
    983 +                                                                const gchar            *name,
    984 +                                                                const gchar            *type,
    985 +                                                                const gchar            *subdir);
    986 +void                    ige_mac_dock_set_overlay_from_pixbuf   (IgeMacDock             *dock,
    987 +                                                                GdkPixbuf              *pixbuf);
    988 +void                    ige_mac_dock_set_overlay_from_resource (IgeMacDock             *dock,
    989 +                                                                IgeMacBundle           *bundle,
    990 +                                                                const gchar            *name,
    991 +                                                                const gchar            *type,
    992 +                                                                const gchar            *subdir);
    993 +IgeMacAttentionRequest *ige_mac_dock_attention_request         (IgeMacDock             *dock,
    994 +                                                                IgeMacAttentionType     type);
    995 +void                    ige_mac_dock_attention_cancel          (IgeMacDock             *dock,
    996 +                                                                IgeMacAttentionRequest *request);
    997 +
    998 +#define IGE_TYPE_MAC_ATTENTION_TYPE (ige_mac_attention_type_get_type())
    999 +GType                   ige_mac_attention_type_get_type        (void);
    1000 +
    1001 +G_END_DECLS
    1002 +
    1003 +#endif /* __IGE_MAC_DOCK_H__ */
    1004 --- pidgin/ige-mac-image-utils.c        1970-01-01 01:00:00.000000000 +0100
    1005 +++ ../pidgin-2.3.1/pidgin/ige-mac-image-utils.c        2008-02-11 14:38:28.000000000 +0100
    1006 @@ -0,0 +1,60 @@
    1007 +/*
    1008 + * Copyright (C) 2007 Imendio AB
    1009 + *
    1010 + * This library is free software; you can redistribute it and/or
    1011 + * modify it under the terms of the GNU Lesser General Public
    1012 + * License as published by the Free Software Foundation; version 2.1
    1013 + * of the License.
    1014 + *
    1015 + * This library is distributed in the hope that it will be useful,
    1016 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1017 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    1018 + * Lesser General Public License for more details.
    1019 + *
    1020 + * You should have received a copy of the GNU Lesser General Public
    1021 + * License along with this library; if not, write to the
    1022 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    1023 + * Boston, MA 02111-1307, USA.
    1024 + */
    1025 +
    1026 +#include <config.h>
    1027 +#include <gtk/gtk.h>
    1028 +#include <Carbon/Carbon.h>
    1029 +
    1030 +#include "ige-mac-image-utils.h"
    1031 +
    1032 +CGImageRef
    1033 +ige_mac_image_from_pixbuf (GdkPixbuf *pixbuf)
    1034 +{
    1035 +  CGColorSpaceRef   colorspace;
    1036 +  CGDataProviderRef data_provider;
    1037 +  CGImageRef        image;
    1038 +  void             *data;
    1039 +  gint              rowstride;
    1040 +  gint              pixbuf_width, pixbuf_height;
    1041 +  gboolean          has_alpha;
    1042 +
    1043 +  pixbuf_width = gdk_pixbuf_get_width (pixbuf);
    1044 +  pixbuf_height = gdk_pixbuf_get_height (pixbuf);
    1045 +  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
    1046 +  has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
    1047 +
    1048 +  data = gdk_pixbuf_get_pixels (pixbuf);
    1049 +
    1050 +  colorspace = CGColorSpaceCreateDeviceRGB ();
    1051 +  data_provider = CGDataProviderCreateWithData (NULL, data,
    1052 +                                                pixbuf_height * rowstride,
    1053 +                                                NULL);
    1054 +
    1055 +  image = CGImageCreate (pixbuf_width, pixbuf_height, 8,
    1056 +                         has_alpha ? 32 : 24, rowstride,
    1057 +                         colorspace,
    1058 +                         has_alpha ? kCGImageAlphaLast : 0,
    1059 +                         data_provider, NULL, FALSE,
    1060 +                         kCGRenderingIntentDefault);
    1061 +
    1062 +  CGDataProviderRelease (data_provider);
    1063 +  CGColorSpaceRelease (colorspace);
    1064 +
    1065 +  return image;
    1066 +}
    1067 --- pidgin/ige-mac-image-utils.h        1970-01-01 01:00:00.000000000 +0100
    1068 +++ ../pidgin-2.3.1/pidgin/ige-mac-image-utils.h        2008-02-11 14:38:30.000000000 +0100
    1069 @@ -0,0 +1,32 @@
    1070 +/*
    1071 + * Copyright (C) 2007 Imendio AB
    1072 + *
    1073 + * This library is free software; you can redistribute it and/or
    1074 + * modify it under the terms of the GNU Lesser General Public
    1075 + * License as published by the Free Software Foundation; version 2.1
    1076 + * of the License.
    1077 + *
    1078 + * This library is distributed in the hope that it will be useful,
    1079 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1080 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    1081 + * Lesser General Public License for more details.
    1082 + *
    1083 + * You should have received a copy of the GNU Lesser General Public
    1084 + * License along with this library; if not, write to the
    1085 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    1086 + * Boston, MA 02111-1307, USA.
    1087 + */
    1088 +
    1089 +#ifndef __IGE_MAC_IMAGE_UTILS_H__
    1090 +#define __IGE_MAC_IMAGE_UTILS_H__
    1091 +
    1092 +#include <gdk-pixbuf/gdk-pixbuf.h>
    1093 +#include <Carbon/Carbon.h>
    1094 +
    1095 +G_BEGIN_DECLS
    1096 +
    1097 +CGImageRef ige_mac_image_from_pixbuf (GdkPixbuf *pixbuf);
    1098 +
    1099 +G_END_DECLS
    1100 +
    1101 +#endif /* __IGE_MAC_IMAGE_UTILS_H__ */
    1102 --- pidgin/ige-mac-menu.c       1970-01-01 01:00:00.000000000 +0100
    1103 +++ ../pidgin-2.3.1/pidgin/ige-mac-menu.c       2008-02-11 14:38:28.000000000 +0100
    1104 @@ -0,0 +1,936 @@
    1105 +/* GTK+ Integration for the Mac OS X Menubar.
    1106 + *
    1107 + * Copyright (C) 2007 Pioneer Research Center USA, Inc.
    1108 + * Copyright (C) 2007 Imendio AB
    1109 + *
    1110 + * For further information, see:
    1111 + * http://developer.imendio.com/projects/gtk-macosx/menubar
    1112 + *
    1113 + * This library is free software; you can redistribute it and/or
    1114 + * modify it under the terms of the GNU Lesser General Public
    1115 + * License as published by the Free Software Foundation; version 2.1
    1116 + * of the License.
    1117 + *
    1118 + * This library is distributed in the hope that it will be useful,
    1119 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1120 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    1121 + * Lesser General Public License for more details.
    1122 + *
    1123 + * You should have received a copy of the GNU Lesser General Public
    1124 + * License along with this library; if not, write to the
    1125 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    1126 + * Boston, MA 02111-1307, USA.
    1127 + */
    1128 +
    1129 +#include <gtk/gtk.h>
    1130 +#include <gdk/gdkkeysyms.h>
    1131 +#include <Carbon/Carbon.h>
    1132 +
    1133 +#include "ige-mac-menu.h"
    1134 +
    1135 +/* TODO
    1136 + *
    1137 + * - Adding a standard Window menu (Minimize etc)?
    1138 + * - Sync reordering items? Does that work now?
    1139 + * - Create on demand? (can this be done with gtk+? ie fill in menu
    1140 +     items when the menu is opened)
    1141 + * - Figure out what to do per app/window...
    1142 + *
    1143 + */
    1144 +
    1145 +#define IGE_QUARTZ_MENU_CREATOR 'IGEC'
    1146 +#define IGE_QUARTZ_ITEM_WIDGET  'IWID'
    1147 +
    1148 +
    1149 +static void   sync_menu_shell (GtkMenuShell *menu_shell,
    1150 +                              MenuRef       carbon_menu,
    1151 +                              gboolean      toplevel,
    1152 +                              gboolean      debug);
    1153 +
    1154 +
    1155 +/*
    1156 + * utility functions
    1157 + */
    1158 +
    1159 +static GtkWidget *
    1160 +find_menu_label (GtkWidget *widget)
    1161 +{
    1162 +  GtkWidget *label = NULL;
    1163 +
    1164 +  if (GTK_IS_LABEL (widget))
    1165 +    return widget;
    1166 +
    1167 +  if (GTK_IS_CONTAINER (widget))
    1168 +    {
    1169 +      GList *children;
    1170 +      GList *l;
    1171 +
    1172 +      children = gtk_container_get_children (GTK_CONTAINER (widget));
    1173 +
    1174 +      for (l = children; l; l = l->next)
    1175 +       {
    1176 +         label = find_menu_label (l->data);
    1177 +         if (label)
    1178 +           break;
    1179 +       }
    1180 +
    1181 +      g_list_free (children);
    1182 +    }
    1183 +
    1184 +  return label;
    1185 +}
    1186 +
    1187 +static const gchar *
    1188 +get_menu_label_text (GtkWidget  *menu_item,
    1189 +                    GtkWidget **label)
    1190 +{
    1191 +  GtkWidget *my_label;
    1192 +
    1193 +  my_label = find_menu_label (menu_item);
    1194 +  if (label)
    1195 +    *label = my_label;
    1196 +
    1197 +  if (my_label)
    1198 +    return gtk_label_get_text (GTK_LABEL (my_label));
    1199 +
    1200 +  return NULL;
    1201 +}
    1202 +
    1203 +static gboolean
    1204 +accel_find_func (GtkAccelKey *key,
    1205 +                GClosure    *closure,
    1206 +                gpointer     data)
    1207 +{
    1208 +  return (GClosure *) data == closure;
    1209 +}
    1210 +
    1211 +
    1212 +/*
    1213 + * CarbonMenu functions
    1214 + */
    1215 +
    1216 +typedef struct
    1217 +{
    1218 +  MenuRef menu;
    1219 +  guint   toplevel : 1;
    1220 +} CarbonMenu;
    1221 +
    1222 +static GQuark carbon_menu_quark = 0;
    1223 +
    1224 +static CarbonMenu *
    1225 +carbon_menu_new (void)
    1226 +{
    1227 +  return g_slice_new0 (CarbonMenu);
    1228 +}
    1229 +
    1230 +static void
    1231 +carbon_menu_free (CarbonMenu *menu)
    1232 +{
    1233 +  g_slice_free (CarbonMenu, menu);
    1234 +}
    1235 +
    1236 +static CarbonMenu *
    1237 +carbon_menu_get (GtkWidget *widget)
    1238 +{
    1239 +  return g_object_get_qdata (G_OBJECT (widget), carbon_menu_quark);
    1240 +}
    1241 +
    1242 +static void
    1243 +carbon_menu_connect (GtkWidget *menu,
    1244 +                    MenuRef    menuRef,
    1245 +                     gboolean   toplevel)
    1246 +{
    1247 +  CarbonMenu *carbon_menu = carbon_menu_get (menu);
    1248 +
    1249 +  if (!carbon_menu)
    1250 +    {
    1251 +      carbon_menu = carbon_menu_new ();
    1252 +
    1253 +      g_object_set_qdata_full (G_OBJECT (menu), carbon_menu_quark,
    1254 +                              carbon_menu,
    1255 +                              (GDestroyNotify) carbon_menu_free);
    1256 +    }
    1257 +
    1258 +  carbon_menu->menu = menuRef;
    1259 +  carbon_menu->toplevel = toplevel;
    1260 +}
    1261 +
    1262 +
    1263 +/*
    1264 + * CarbonMenuItem functions
    1265 + */
    1266 +
    1267 +typedef struct
    1268 +{
    1269 +  MenuRef        menu;
    1270 +  MenuItemIndex  index;
    1271 +  MenuRef        submenu;
    1272 +  GClosure      *accel_closure;
    1273 +} CarbonMenuItem;
    1274 +
    1275 +static GQuark carbon_menu_item_quark = 0;
    1276 +
    1277 +static CarbonMenuItem *
    1278 +carbon_menu_item_new (void)
    1279 +{
    1280 +  return g_slice_new0 (CarbonMenuItem);
    1281 +}
    1282 +
    1283 +static void
    1284 +carbon_menu_item_free (CarbonMenuItem *menu_item)
    1285 +{
    1286 +  if (menu_item->accel_closure)
    1287 +    g_closure_unref (menu_item->accel_closure);
    1288 +
    1289 +  g_slice_free (CarbonMenuItem, menu_item);
    1290 +}
    1291 +
    1292 +static CarbonMenuItem *
    1293 +carbon_menu_item_get (GtkWidget *widget)
    1294 +{
    1295 +  return g_object_get_qdata (G_OBJECT (widget), carbon_menu_item_quark);
    1296 +}
    1297 +
    1298 +static void
    1299 +carbon_menu_item_update_state (CarbonMenuItem *carbon_item,
    1300 +                              GtkWidget      *widget)
    1301 +{
    1302 +  gboolean sensitive;
    1303 +  gboolean visible;
    1304 +  UInt32   set_attrs = 0;
    1305 +  UInt32   clear_attrs = 0;
    1306 +
    1307 +  g_object_get (widget,
    1308 +                "sensitive", &sensitive,
    1309 +                "visible",   &visible,
    1310 +                NULL);
    1311 +
    1312 +  if (!sensitive)
    1313 +    set_attrs |= kMenuItemAttrDisabled;
    1314 +  else
    1315 +    clear_attrs |= kMenuItemAttrDisabled;
    1316 +
    1317 +  if (!visible)
    1318 +    set_attrs |= kMenuItemAttrHidden;
    1319 +  else
    1320 +    clear_attrs |= kMenuItemAttrHidden;
    1321 +
    1322 +  ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
    1323 +                            set_attrs, clear_attrs);
    1324 +}
    1325 +
    1326 +static void
    1327 +carbon_menu_item_update_active (CarbonMenuItem *carbon_item,
    1328 +                               GtkWidget      *widget)
    1329 +{
    1330 +  gboolean active;
    1331 +
    1332 +  g_object_get (widget,
    1333 +                "active", &active,
    1334 +                NULL);
    1335 +
    1336 +  CheckMenuItem (carbon_item->menu, carbon_item->index,
    1337 +                active);
    1338 +}
    1339 +
    1340 +static void
    1341 +carbon_menu_item_update_submenu (CarbonMenuItem *carbon_item,
    1342 +                                GtkWidget      *widget)
    1343 +{
    1344 +  GtkWidget *submenu;
    1345 +
    1346 +  submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
    1347 +
    1348 +  if (submenu)
    1349 +    {
    1350 +      const gchar *label_text;
    1351 +      CFStringRef  cfstr = NULL;
    1352 +
    1353 +      label_text = get_menu_label_text (widget, NULL);
    1354 +      if (label_text)
    1355 +        cfstr = CFStringCreateWithCString (NULL, label_text,
    1356 +                                          kCFStringEncodingUTF8);
    1357 +
    1358 +      CreateNewMenu (0, 0, &carbon_item->submenu);
    1359 +      SetMenuTitleWithCFString (carbon_item->submenu, cfstr);
    1360 +      SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
    1361 +                                  carbon_item->submenu);
    1362 +
    1363 +      sync_menu_shell (GTK_MENU_SHELL (submenu), carbon_item->submenu, FALSE, FALSE);
    1364 +
    1365 +      if (cfstr)
    1366 +       CFRelease (cfstr);
    1367 +    }
    1368 +  else
    1369 +    {
    1370 +      SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
    1371 +                                  NULL);
    1372 +      carbon_item->submenu = NULL;
    1373 +    }
    1374 +}
    1375 +
    1376 +static void
    1377 +carbon_menu_item_update_label (CarbonMenuItem *carbon_item,
    1378 +                              GtkWidget      *widget)
    1379 +{
    1380 +  const gchar *label_text;
    1381 +  CFStringRef  cfstr = NULL;
    1382 +
    1383 +  label_text = get_menu_label_text (widget, NULL);
    1384 +  if (label_text)
    1385 +    cfstr = CFStringCreateWithCString (NULL, label_text,
    1386 +                                      kCFStringEncodingUTF8);
    1387 +
    1388 +  SetMenuItemTextWithCFString (carbon_item->menu, carbon_item->index,
    1389 +                              cfstr);
    1390 +
    1391 +  if (cfstr)
    1392 +    CFRelease (cfstr);
    1393 +}
    1394 +
    1395 +static void
    1396 +carbon_menu_item_update_accelerator (CarbonMenuItem *carbon_item,
    1397 +                                    GtkWidget      *widget)
    1398 +{
    1399 +  GtkWidget *label;
    1400 +
    1401 +  get_menu_label_text (widget, &label);
    1402 +
    1403 +  if (GTK_IS_ACCEL_LABEL (label) &&
    1404 +      GTK_ACCEL_LABEL (label)->accel_closure)
    1405 +    {
    1406 +      GtkAccelKey *key;
    1407 +
    1408 +      key = gtk_accel_group_find (GTK_ACCEL_LABEL (label)->accel_group,
    1409 +                                 accel_find_func,
    1410 +                                 GTK_ACCEL_LABEL (label)->accel_closure);
    1411 +
    1412 +      if (key            &&
    1413 +         key->accel_key &&
    1414 +         key->accel_flags & GTK_ACCEL_VISIBLE)
    1415 +       {
    1416 +         GdkDisplay      *display = gtk_widget_get_display (widget);
    1417 +         GdkKeymap       *keymap  = gdk_keymap_get_for_display (display);
    1418 +         GdkKeymapKey    *keys;
    1419 +         gint             n_keys;
    1420 +
    1421 +         if (gdk_keymap_get_entries_for_keyval (keymap, key->accel_key,
    1422 +                                                &keys, &n_keys))
    1423 +           {
    1424 +             UInt8 modifiers = 0;
    1425 +
    1426 +             SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
    1427 +                                    true, keys[0].keycode);
    1428 +
    1429 +             g_free (keys);
    1430 +
    1431 +             if (key->accel_mods)
    1432 +               {
    1433 +                 if (key->accel_mods & GDK_SHIFT_MASK)
    1434 +                   modifiers |= kMenuShiftModifier;
    1435 +
    1436 +                 if (key->accel_mods & GDK_MOD1_MASK)
    1437 +                   modifiers |= kMenuOptionModifier;
    1438 +               }
    1439 +
    1440 +             if (!(key->accel_mods & GDK_CONTROL_MASK))
    1441 +               {
    1442 +                 modifiers |= kMenuNoCommandModifier;
    1443 +               }
    1444 +
    1445 +             SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
    1446 +                                   modifiers);
    1447 +
    1448 +             return;
    1449 +           }
    1450 +       }
    1451 +    }
    1452 +
    1453 +  /*  otherwise, clear the menu shortcut  */
    1454 +  SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
    1455 +                       kMenuNoModifiers | kMenuNoCommandModifier);
    1456 +  ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
    1457 +                           0, kMenuItemAttrUseVirtualKey);
    1458 +  SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
    1459 +                        false, 0);
    1460 +}
    1461 +
    1462 +static void
    1463 +carbon_menu_item_accel_changed (GtkAccelGroup   *accel_group,
    1464 +                               guint            keyval,
    1465 +                               GdkModifierType  modifier,
    1466 +                               GClosure        *accel_closure,
    1467 +                               GtkWidget       *widget)
    1468 +{
    1469 +  CarbonMenuItem *carbon_item = carbon_menu_item_get (widget);
    1470 +  GtkWidget      *label;
    1471 +
    1472 +  get_menu_label_text (widget, &label);
    1473 +
    1474 +  if (GTK_IS_ACCEL_LABEL (label) &&
    1475 +      GTK_ACCEL_LABEL (label)->accel_closure == accel_closure)
    1476 +    carbon_menu_item_update_accelerator (carbon_item, widget);
    1477 +}
    1478 +
    1479 +static void
    1480 +carbon_menu_item_update_accel_closure (CarbonMenuItem *carbon_item,
    1481 +                                      GtkWidget      *widget)
    1482 +{
    1483 +  GtkAccelGroup *group;
    1484 +  GtkWidget     *label;
    1485 +
    1486 +  get_menu_label_text (widget, &label);
    1487 +
    1488 +  if (carbon_item->accel_closure)
    1489 +    {
    1490 +      group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
    1491 +
    1492 +      g_signal_handlers_disconnect_by_func (group,
    1493 +                                           carbon_menu_item_accel_changed,
    1494 +                                           widget);
    1495 +
    1496 +      g_closure_unref (carbon_item->accel_closure);
    1497 +      carbon_item->accel_closure = NULL;
    1498 +    }
    1499 +
    1500 +  if (GTK_IS_ACCEL_LABEL (label))
    1501 +    carbon_item->accel_closure = GTK_ACCEL_LABEL (label)->accel_closure;
    1502 +
    1503 +  if (carbon_item->accel_closure)
    1504 +    {
    1505 +      g_closure_ref (carbon_item->accel_closure);
    1506 +
    1507 +      group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
    1508 +
    1509 +      g_signal_connect_object (group, "accel-changed",
    1510 +                              G_CALLBACK (carbon_menu_item_accel_changed),
    1511 +                              widget, 0);
    1512 +    }
    1513 +
    1514 +  carbon_menu_item_update_accelerator (carbon_item, widget);
    1515 +}
    1516 +
    1517 +static void
    1518 +carbon_menu_item_notify (GObject        *object,
    1519 +                        GParamSpec     *pspec,
    1520 +                        CarbonMenuItem *carbon_item)
    1521 +{
    1522 +  if (!strcmp (pspec->name, "sensitive") ||
    1523 +      !strcmp (pspec->name, "visible"))
    1524 +    {
    1525 +      carbon_menu_item_update_state (carbon_item, GTK_WIDGET (object));
    1526 +    }
    1527 +  else if (!strcmp (pspec->name, "active"))
    1528 +    {
    1529 +      carbon_menu_item_update_active (carbon_item, GTK_WIDGET (object));
    1530 +    }
    1531 +  else if (!strcmp (pspec->name, "submenu"))
    1532 +    {
    1533 +      carbon_menu_item_update_submenu (carbon_item, GTK_WIDGET (object));
    1534 +    }
    1535 +}
    1536 +
    1537 +static void
    1538 +carbon_menu_item_notify_label (GObject    *object,
    1539 +                              GParamSpec *pspec,
    1540 +                              gpointer    data)
    1541 +{
    1542 +  CarbonMenuItem *carbon_item = carbon_menu_item_get (GTK_WIDGET (object));
    1543 +
    1544 +  if (!strcmp (pspec->name, "label"))
    1545 +    {
    1546 +      carbon_menu_item_update_label (carbon_item,
    1547 +                                    GTK_WIDGET (object));
    1548 +    }
    1549 +  else if (!strcmp (pspec->name, "accel-closure"))
    1550 +    {
    1551 +      carbon_menu_item_update_accel_closure (carbon_item,
    1552 +                                            GTK_WIDGET (object));
    1553 +    }
    1554 +}
    1555 +
    1556 +static CarbonMenuItem *
    1557 +carbon_menu_item_connect (GtkWidget     *menu_item,
    1558 +                         GtkWidget     *label,
    1559 +                         MenuRef        menu,
    1560 +                         MenuItemIndex  index)
    1561 +{
    1562 +  CarbonMenuItem *carbon_item = carbon_menu_item_get (menu_item);
    1563 +
    1564 +  if (!carbon_item)
    1565 +    {
    1566 +      carbon_item = carbon_menu_item_new ();
    1567 +
    1568 +      g_object_set_qdata_full (G_OBJECT (menu_item), carbon_menu_item_quark,
    1569 +                              carbon_item,
    1570 +                              (GDestroyNotify) carbon_menu_item_free);
    1571 +
    1572 +      g_signal_connect (menu_item, "notify",
    1573 +                        G_CALLBACK (carbon_menu_item_notify),
    1574 +                        carbon_item);
    1575 +
    1576 +      if (label)
    1577 +       g_signal_connect_swapped (label, "notify::label",
    1578 +                                 G_CALLBACK (carbon_menu_item_notify_label),
    1579 +                                 menu_item);
    1580 +    }
    1581 +
    1582 +  carbon_item->menu  = menu;
    1583 +  carbon_item->index = index;
    1584 +
    1585 +  return carbon_item;
    1586 +}
    1587 +
    1588 +
    1589 +/*
    1590 + * carbon event handler
    1591 + */
    1592 +
    1593 +static OSStatus
    1594 +menu_event_handler_func (EventHandlerCallRef  event_handler_call_ref,
    1595 +                        EventRef             event_ref,
    1596 +                        void                *data)
    1597 +{
    1598 +  UInt32  event_class = GetEventClass (event_ref);
    1599 +  UInt32  event_kind = GetEventKind (event_ref);
    1600 +  MenuRef menu_ref;
    1601 +
    1602 +  switch (event_class)
    1603 +    {
    1604 +    case kEventClassCommand:
    1605 +      /* This is called when activating (is that the right GTK+ term?)
    1606 +       * a menu item.
    1607 +       */
    1608 +      if (event_kind == kEventCommandProcess)
    1609 +       {
    1610 +         HICommand command;
    1611 +         OSStatus  err;
    1612 +
    1613 +         /*g_printerr ("Menu: kEventClassCommand/kEventCommandProcess\n");*/
    1614 +
    1615 +         err = GetEventParameter (event_ref, kEventParamDirectObject,
    1616 +                                  typeHICommand, 0,
    1617 +                                  sizeof (command), 0, &command);
    1618 +
    1619 +         if (err == noErr)
    1620 +           {
    1621 +             GtkWidget *widget = NULL;
    1622 +
    1623 +             /* Get any GtkWidget associated with the item. */
    1624 +             err = GetMenuItemProperty (command.menu.menuRef,
    1625 +                                        command.menu.menuItemIndex,
    1626 +                                        IGE_QUARTZ_MENU_CREATOR,
    1627 +                                        IGE_QUARTZ_ITEM_WIDGET,
    1628 +                                        sizeof (widget), 0, &widget);
    1629 +             if (err == noErr && GTK_IS_WIDGET (widget))
    1630 +               {
    1631 +                 gtk_menu_item_activate (GTK_MENU_ITEM (widget));
    1632 +                 return noErr;
    1633 +               }
    1634 +           }
    1635 +       }
    1636 +      break;
    1637 +
    1638 +    case kEventClassMenu:
    1639 +      GetEventParameter (event_ref,
    1640 +                        kEventParamDirectObject,
    1641 +                        typeMenuRef,
    1642 +                        NULL,
    1643 +                        sizeof (menu_ref),
    1644 +                        NULL,
    1645 +                        &menu_ref);
    1646 +
    1647 +      switch (event_kind)
    1648 +       {
    1649 +       case kEventMenuTargetItem:
    1650 +         /* This is called when an item is selected (what is the
    1651 +          * GTK+ term? prelight?)
    1652 +          */
    1653 +         /*g_printerr ("kEventClassMenu/kEventMenuTargetItem\n");*/
    1654 +         break;
    1655 +
    1656 +       case kEventMenuOpening:
    1657 +         /* Is it possible to dynamically build the menu here? We
    1658 +          * can at least set visibility/sensitivity.
    1659 +          */
    1660 +         /*g_printerr ("kEventClassMenu/kEventMenuOpening\n");*/
    1661 +         break;
    1662 +
    1663 +       case kEventMenuClosed:
    1664 +         /*g_printerr ("kEventClassMenu/kEventMenuClosed\n");*/
    1665 +         break;
    1666 +
    1667 +       default:
    1668 +         break;
    1669 +       }
    1670 +
    1671 +      break;
    1672 +
    1673 +    default:
    1674 +      break;
    1675 +    }
    1676 +
    1677 +  return CallNextEventHandler (event_handler_call_ref, event_ref);
    1678 +}
    1679 +
    1680 +static void
    1681 +setup_menu_event_handler (void)
    1682 +{
    1683 +  static gboolean is_setup;
    1684 +  EventHandlerUPP menu_event_handler_upp;
    1685 +  EventHandlerRef menu_event_handler_ref;
    1686 +  const EventTypeSpec menu_events[] = {
    1687 +    { kEventClassCommand, kEventCommandProcess },
    1688 +    { kEventClassMenu, kEventMenuTargetItem },
    1689 +    { kEventClassMenu, kEventMenuOpening },
    1690 +    { kEventClassMenu, kEventMenuClosed }
    1691 +  };
    1692 +
    1693 +  if (is_setup)
    1694 +    return;
    1695 +
    1696 +  /* FIXME: We might have to install one per window? */
    1697 +
    1698 +  menu_event_handler_upp = NewEventHandlerUPP (menu_event_handler_func);
    1699 +  InstallEventHandler (GetApplicationEventTarget (), menu_event_handler_upp,
    1700 +                      GetEventTypeCount (menu_events), menu_events, 0,
    1701 +                      &menu_event_handler_ref);
    1702 +
    1703 +#if 0
    1704 +  /* FIXME: Remove the handler with: */
    1705 +  RemoveEventHandler(menu_event_handler_ref);
    1706 +  DisposeEventHandlerUPP(menu_event_handler_upp);
    1707 +#endif
    1708 +  is_setup = TRUE;
    1709 +}
    1710 +
    1711 +static void
    1712 +sync_menu_shell (GtkMenuShell *menu_shell,
    1713 +                 MenuRef       carbon_menu,
    1714 +                gboolean      toplevel,
    1715 +                gboolean      debug)
    1716 +{
    1717 +  GList         *children;
    1718 +  GList         *l;
    1719 +  MenuItemIndex  carbon_index = 1;
    1720 +
    1721 +  if (debug)
    1722 +    g_printerr ("%s: syncing shell %p\n", G_STRFUNC, menu_shell);
    1723 +
    1724 +  carbon_menu_connect (GTK_WIDGET (menu_shell), carbon_menu, toplevel);
    1725 +
    1726 +  children = gtk_container_get_children (GTK_CONTAINER (menu_shell));
    1727 +
    1728 +  for (l = children; l; l = l->next)
    1729 +    {
    1730 +      GtkWidget      *menu_item = l->data;
    1731 +      CarbonMenuItem *carbon_item;
    1732 +
    1733 +      if (GTK_IS_TEAROFF_MENU_ITEM (menu_item))
    1734 +       continue;
    1735 +
    1736 +      if (toplevel && g_object_get_data (G_OBJECT (menu_item),
    1737 +                                        "gtk-empty-menu-item"))
    1738 +       continue;
    1739 +
    1740 +      carbon_item = carbon_menu_item_get (menu_item);
    1741 +
    1742 +      if (debug)
    1743 +       g_printerr ("%s: carbon_item %d for menu_item %d (%s, %s)\n",
    1744 +                   G_STRFUNC, carbon_item ? carbon_item->index : -1,
    1745 +                   carbon_index, get_menu_label_text (menu_item, NULL),
    1746 +                   g_type_name (G_TYPE_FROM_INSTANCE (menu_item)));
    1747 +
    1748 +      if (carbon_item && carbon_item->index != carbon_index)
    1749 +       {
    1750 +         if (debug)
    1751 +           g_printerr ("%s:   -> not matching, deleting\n", G_STRFUNC);
    1752 +
    1753 +         DeleteMenuItem (carbon_item->menu, carbon_index);
    1754 +         carbon_item = NULL;
    1755 +       }
    1756 +
    1757 +      if (!carbon_item)
    1758 +       {
    1759 +         GtkWidget          *label      = NULL;
    1760 +         const gchar        *label_text;
    1761 +         CFStringRef         cfstr      = NULL;
    1762 +         MenuItemAttributes  attributes = 0;
    1763 +
    1764 +         if (debug)
    1765 +           g_printerr ("%s:   -> creating new\n", G_STRFUNC);
    1766 +
    1767 +         label_text = get_menu_label_text (menu_item, &label);
    1768 +         if (label_text)
    1769 +           cfstr = CFStringCreateWithCString (NULL, label_text,
    1770 +                                              kCFStringEncodingUTF8);
    1771 +
    1772 +         if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item))
    1773 +           attributes |= kMenuItemAttrSeparator;
    1774 +
    1775 +         if (!GTK_WIDGET_IS_SENSITIVE (menu_item))
    1776 +           attributes |= kMenuItemAttrDisabled;
    1777 +
    1778 +         if (!GTK_WIDGET_VISIBLE (menu_item))
    1779 +           attributes |= kMenuItemAttrHidden;
    1780 +
    1781 +         InsertMenuItemTextWithCFString (carbon_menu, cfstr,
    1782 +                                         carbon_index - 1,
    1783 +                                         attributes, 0);
    1784 +         SetMenuItemProperty (carbon_menu, carbon_index,
    1785 +                              IGE_QUARTZ_MENU_CREATOR,
    1786 +                              IGE_QUARTZ_ITEM_WIDGET,
    1787 +                              sizeof (menu_item), &menu_item);
    1788 +
    1789 +         if (cfstr)
    1790 +           CFRelease (cfstr);
    1791 +
    1792 +         carbon_item = carbon_menu_item_connect (menu_item, label,
    1793 +                                                 carbon_menu,
    1794 +                                                 carbon_index);
    1795 +
    1796 +         if (GTK_IS_CHECK_MENU_ITEM (menu_item))
    1797 +           carbon_menu_item_update_active (carbon_item, menu_item);
    1798 +
    1799 +         carbon_menu_item_update_accel_closure (carbon_item, menu_item);
    1800 +
    1801 +         if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item)))
    1802 +           carbon_menu_item_update_submenu (carbon_item, menu_item);
    1803 +       }
    1804 +
    1805 +      carbon_index++;
    1806 +    }
    1807 +
    1808 +  g_list_free (children);
    1809 +}
    1810 +
    1811 +static gulong emission_hook_id = 0;
    1812 +static gint   emission_hook_count = 0;
    1813 +
    1814 +static gboolean
    1815 +parent_set_emission_hook (GSignalInvocationHint *ihint,
    1816 +                         guint                  n_param_values,
    1817 +                         const GValue          *param_values,
    1818 +                         gpointer               data)
    1819 +{
    1820 +  GtkWidget *instance = g_value_get_object (param_values);
    1821 +
    1822 +  if (GTK_IS_MENU_ITEM (instance))
    1823 +    {
    1824 +      GtkWidget *previous_parent = g_value_get_object (param_values + 1);
    1825 +      GtkWidget *menu_shell      = NULL;
    1826 +
    1827 +      if (GTK_IS_MENU_SHELL (previous_parent))
    1828 +       {
    1829 +         menu_shell = previous_parent;
    1830 +        }
    1831 +      else if (GTK_IS_MENU_SHELL (instance->parent))
    1832 +       {
    1833 +         menu_shell = instance->parent;
    1834 +       }
    1835 +
    1836 +      if (menu_shell)
    1837 +        {
    1838 +         CarbonMenu *carbon_menu = carbon_menu_get (menu_shell);
    1839 +
    1840 +         if (carbon_menu)
    1841 +           {
    1842 +#if 0
    1843 +             g_printerr ("%s: item %s %p (%s, %s)\n", G_STRFUNC,
    1844 +                         previous_parent ? "removed from" : "added to",
    1845 +                         menu_shell,
    1846 +                         get_menu_label_text (instance, NULL),
    1847 +                         g_type_name (G_TYPE_FROM_INSTANCE (instance)));
    1848 +#endif
    1849 +
    1850 +             sync_menu_shell (GTK_MENU_SHELL (menu_shell),
    1851 +                              carbon_menu->menu,
    1852 +                              carbon_menu->toplevel,
    1853 +                              FALSE);
    1854 +           }
    1855 +        }
    1856 +    }
    1857 +
    1858 +  return TRUE;
    1859 +}
    1860 +
    1861 +static void
    1862 +parent_set_emission_hook_remove (GtkWidget *widget,
    1863 +                                gpointer   data)
    1864 +{
    1865 +  emission_hook_count--;
    1866 +
    1867 +  if (emission_hook_count > 0)
    1868 +    return;
    1869 +
    1870 +  g_signal_remove_emission_hook (g_signal_lookup ("parent-set",
    1871 +                                                 GTK_TYPE_WIDGET),
    1872 +                                emission_hook_id);
    1873 +  emission_hook_id = 0;
    1874 +}
    1875 +
    1876 +
    1877 +/*
    1878 + * public functions
    1879 + */
    1880 +
    1881 +void
    1882 +ige_mac_menu_set_menu_bar (GtkMenuShell *menu_shell)
    1883 +{
    1884 +  MenuRef carbon_menubar;
    1885 +
    1886 +  g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
    1887 +
    1888 +  if (carbon_menu_quark == 0)
    1889 +    carbon_menu_quark = g_quark_from_static_string ("CarbonMenu");
    1890 +
    1891 +  if (carbon_menu_item_quark == 0)
    1892 +    carbon_menu_item_quark = g_quark_from_static_string ("CarbonMenuItem");
    1893 +
    1894 +  CarbonMenu *current_menu;
    1895 +  current_menu = carbon_menu_get (GTK_WIDGET (menu_shell));
    1896 +  if (current_menu)
    1897 +    {
    1898 +      SetRootMenu (current_menu->menu);
    1899 +      return;
    1900 +    }
    1901 +
    1902 +  CreateNewMenu (0 /*id*/, 0 /*options*/, &carbon_menubar);
    1903 +  SetRootMenu (carbon_menubar);
    1904 +
    1905 +  setup_menu_event_handler ();
    1906 +
    1907 +  if (emission_hook_id == 0)
    1908 +    {
    1909 +      emission_hook_id =
    1910 +        g_signal_add_emission_hook (g_signal_lookup ("parent-set",
    1911 +                                                     GTK_TYPE_WIDGET),
    1912 +                                    0,
    1913 +                                    parent_set_emission_hook,
    1914 +                                    NULL, NULL);
    1915 +    }
    1916 +
    1917 +  emission_hook_count++;
    1918 +
    1919 +  g_signal_connect (menu_shell, "destroy",
    1920 +                   G_CALLBACK (parent_set_emission_hook_remove),
    1921 +                   NULL);
    1922 +
    1923 +  sync_menu_shell (menu_shell, carbon_menubar, TRUE, FALSE);
    1924 +}
    1925 +
    1926 +void
    1927 +ige_mac_menu_set_quit_menu_item (GtkMenuItem *menu_item)
    1928 +{
    1929 +  MenuRef       appmenu;
    1930 +  MenuItemIndex index;
    1931 +
    1932 +  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
    1933 +
    1934 +  setup_menu_event_handler ();
    1935 +
    1936 +  if (GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
    1937 +                                   &appmenu, &index) == noErr)
    1938 +    {
    1939 +      SetMenuItemCommandID (appmenu, index, 0);
    1940 +      SetMenuItemProperty (appmenu, index,
    1941 +                           IGE_QUARTZ_MENU_CREATOR,
    1942 +                           IGE_QUARTZ_ITEM_WIDGET,
    1943 +                           sizeof (menu_item), &menu_item);
    1944 +
    1945 +      gtk_widget_hide (GTK_WIDGET (menu_item));
    1946 +    }
    1947 +}
    1948 +
    1949 +
    1950 +struct _IgeMacMenuGroup
    1951 +{
    1952 +  GList *items;
    1953 +};
    1954 +
    1955 +static GList *app_menu_groups = NULL;
    1956 +
    1957 +IgeMacMenuGroup *
    1958 +ige_mac_menu_add_app_menu_group (void)
    1959 +{
    1960 +  IgeMacMenuGroup *group = g_slice_new0 (IgeMacMenuGroup);
    1961 +
    1962 +  app_menu_groups = g_list_append (app_menu_groups, group);
    1963 +
    1964 +  return group;
    1965 +}
    1966 +
    1967 +void
    1968 +ige_mac_menu_add_app_menu_item (IgeMacMenuGroup *group,
    1969 +                               GtkMenuItem     *menu_item,
    1970 +                               const gchar     *label)
    1971 +{
    1972 +  MenuRef  appmenu;
    1973 +  GList   *list;
    1974 +  gint     index = 0;
    1975 +
    1976 +  g_return_if_fail (group != NULL);
    1977 +  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
    1978 +
    1979 +  setup_menu_event_handler ();
    1980 +
    1981 +  if (GetIndMenuItemWithCommandID (NULL, kHICommandHide, 1,
    1982 +                                   &appmenu, NULL) != noErr)
    1983 +    {
    1984 +      g_warning ("%s: retrieving app menu failed",
    1985 +                G_STRFUNC);
    1986 +      return;
    1987 +    }
    1988 +
    1989 +  for (list = app_menu_groups; list; list = g_list_next (list))
    1990 +    {
    1991 +      IgeMacMenuGroup *list_group = list->data;
    1992 +
    1993 +      index += g_list_length (list_group->items);
    1994 +
    1995 +      /*  adjust index for the separator between groups, but not
    1996 +       *  before the first group
    1997 +       */
    1998 +      if (list_group->items && list->prev)
    1999 +       index++;
    2000 +
    2001 +      if (group == list_group)
    2002 +       {
    2003 +         CFStringRef cfstr;
    2004 +
    2005 +         /*  add a separator before adding the first item, but not
    2006 +          *  for the first group
    2007 +          */
    2008 +         if (!group->items && list->prev)
    2009 +           {
    2010 +             InsertMenuItemTextWithCFString (appmenu, NULL, index,
    2011 +                                             kMenuItemAttrSeparator, 0);
    2012 +             index++;
    2013 +           }
    2014 +
    2015 +         if (!label)
    2016 +           label = get_menu_label_text (GTK_WIDGET (menu_item), NULL);
    2017 +
    2018 +         cfstr = CFStringCreateWithCString (NULL, label,
    2019 +                                            kCFStringEncodingUTF8);
    2020 +
    2021 +         InsertMenuItemTextWithCFString (appmenu, cfstr, index, 0, 0);
    2022 +         SetMenuItemProperty (appmenu, index + 1,
    2023 +                              IGE_QUARTZ_MENU_CREATOR,
    2024 +                              IGE_QUARTZ_ITEM_WIDGET,
    2025 +                              sizeof (menu_item), &menu_item);
    2026 +
    2027 +         CFRelease (cfstr);
    2028 +
    2029 +         gtk_widget_hide (GTK_WIDGET (menu_item));
    2030 +
    2031 +         group->items = g_list_append (group->items, menu_item);
    2032 +
    2033 +         return;
    2034 +       }
    2035 +    }
    2036 +
    2037 +  if (!list)
    2038 +    g_warning ("%s: app menu group %p does not exist",
    2039 +              G_STRFUNC, group);
    2040 +}
    2041 --- pidgin/ige-mac-menu.h       1970-01-01 01:00:00.000000000 +0100
    2042 +++ ../pidgin-2.3.1/pidgin/ige-mac-menu.h       2008-02-11 14:38:30.000000000 +0100
    2043 @@ -0,0 +1,44 @@
    2044 +/* GTK+ Integration for the Mac OS X Menubar.
    2045 + *
    2046 + * Copyright (C) 2007 Pioneer Research Center USA, Inc.
    2047 + * Copyright (C) 2007 Imendio AB
    2048 + *
    2049 + * For further information, see:
    2050 + * http://developer.imendio.com/projects/gtk-macosx/menubar
    2051 + *
    2052 + * This library is free software; you can redistribute it and/or
    2053 + * modify it under the terms of the GNU Lesser General Public
    2054 + * License as published by the Free Software Foundation; version 2.1
    2055 + * of the License.
    2056 + *
    2057 + * This library is distributed in the hope that it will be useful,
    2058 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2059 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
    2060 + * Lesser General Public License for more details.
    2061 + *
    2062 + * You should have received a copy of the GNU Lesser General Public
    2063 + * License along with this library; if not, write to the
    2064 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    2065 + * Boston, MA 02111-1307, USA.
    2066 + */
    2067 +
    2068 +#ifndef __IGE_MAC_MENU_H__
    2069 +#define __IGE_MAC_MENU_H__
    2070 +
    2071 +#include <gtk/gtk.h>
    2072 +
    2073 +G_BEGIN_DECLS
    2074 +
    2075 +typedef struct _IgeMacMenuGroup IgeMacMenuGroup;
    2076 +
    2077 +void              ige_mac_menu_set_menu_bar       (GtkMenuShell    *menu_shell);
    2078 +void              ige_mac_menu_set_quit_menu_item (GtkMenuItem     *menu_item);
    2079 +
    2080 +IgeMacMenuGroup * ige_mac_menu_add_app_menu_group (void);
    2081 +void              ige_mac_menu_add_app_menu_item  (IgeMacMenuGroup *group,
    2082 +                                                  GtkMenuItem     *menu_item,
    2083 +                                                  const gchar     *label);
    2084 +
    2085 +G_END_DECLS
    2086 +
    2087 +#endif /* __IGE_MAC_MENU_H__ */
    2088 --- pidgin/Makefile.am  2008-02-11 16:07:09.000000000 +0100
    2089 +++ ../pidgin-2.3.1/pidgin/Makefile.am  2008-02-11 16:08:11.000000000 +0100
    2090 @@ -117,7 +117,11 @@
    2091         gtkthemes.c \
    2092         gtkutils.c \
    2093         gtkwhiteboard.c \
    2094 -       minidialog.c
    2095 +       minidialog.c \
    2096 +       ige-mac-bundle.c \
    2097 +       ige-mac-dock.c \
    2098 +       ige-mac-image-utils.c \
    2099 +       ige-mac-menu.c
    2100  
    2101  pidgin_headers = \
    2102         eggtrayicon.h \
    2103 @@ -170,7 +174,11 @@
    2104         gtkutils.h \
    2105         gtkwhiteboard.h \
    2106         minidialog.h \
    2107 -       pidgin.h
    2108 +       pidgin.h \
    2109 +       ige-mac-bundle.h \
    2110 +       ige-mac-dock.h \
    2111 +       ige-mac-image-utils.h \
    2112 +       ige-mac-menu.h
    2113  
    2114  pidginincludedir=$(includedir)/pidgin
    2115  pidgininclude_HEADERS = \
    2116 --- configure.ac        2007-12-07 15:36:58.000000000 +0100
    2117 +++ ../pidgin-2.3.1/configure.ac        2008-02-11 16:46:34.000000000 +0100
    2118 @@ -123,6 +123,11 @@
    2119                 ], [])
    2120         ], [])
    2121  
    2122 +        AC_CHECK_HEADER(Carbon/Carbon.h, [
    2123 +                        AC_DEFINE(HAVE_CARBON, 1, [Define if we have CARBON])
    2124 +                        LIBS="$LIBS -framework Carbon"
    2125 +        ], [])
    2126 +
    2127         AC_MSG_CHECKING([for fink])
    2128         if test -d /sw; then
    2129                 AC_MSG_RESULT([found, adding /sw to search paths])
  • new file files/patch-finch_libgnt_Makefile.in.diff

    diff -r 9b7fde062ca7 files/patch-finch_libgnt_Makefile.in.diff
    - +  
     1Index: finch/libgnt/Makefile.in
     2===================================================================
     3--- finch/libgnt/Makefile.in.orig       2009-09-05 23:12:38.000000000 +0200
     4+++ finch/libgnt/Makefile.in    2009-09-14 00:50:09.000000000 +0200
     5@@ -167,7 +167,7 @@
     6 GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
     7 GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
     8 GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
     9-GLIB_CFLAGS = @GLIB_CFLAGS@
     10+GLIB_CFLAGS = @GLIB_CFLAGS@ -D_XOPEN_SOURCE_EXTENDED
     11 GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
     12 GLIB_LIBS = @GLIB_LIBS@
     13 GMOFILES = @GMOFILES@
  • new file files/patch-finch_libgnt_gntwm.c

    diff -r 9b7fde062ca7 files/patch-finch_libgnt_gntwm.c
    - +  
     1--- finch/libgnt/gntwm.c.old    2009-12-20 09:43:59.000000000 -0800
     2+++ finch/libgnt/gntwm.c        2009-12-20 09:44:24.000000000 -0800
     3@@ -22,6 +22,8 @@
     4 
     5 #include "config.h"
     6 
     7+#define NO_WIDECHAR
     8+
     9 #ifdef USE_PYTHON
     10 #include <Python.h>
     11 #else