New Ticket     Tickets     Wiki     Browse Source     Timeline     Roadmap     Ticket Reports     Search

Ticket #25127: pidgin_1.diff

File pidgin_1.diff, 77.2 KB (added by nefar@…, 3 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