Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/pre_gtkrc
===================================================================
--- packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/pre_gtkrc	(revision 16790)
+++ packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/pre_gtkrc	(working copy)
@@ -1,502 +0,0 @@
-#
-# GTK theme to be used on Mac OS X, to mimic the appearance of Tiger
-# 
-# Heavily based on Clearlooks-Quicksilver
-# Scrollbars from OSX-theme by Lauri Taimila (lauri@...1859...)
-# 
-# (c) 2007 JiHO <jo.irisson@...400...>. 
-# GNU General Public License http://www.gnu.org/copyleft/gpl.html
-#
-
-style "clearlooks-default"
-{
-	GtkButton		::default_border	 = { 0, 0, 0, 0 }
-	GtkRange			::trough_border	 = 0
-	GtkPaned			::handle_size		 = 6
-	GtkRange			::slider_width		 = 15
-	GtkRange			::stepper_size		 = 15
-	GtkScrollbar	::min_slider_length = 30
-	GtkCheckButton	::indicator_size	 = 12
-	GtkMenuBar		::internal-padding	 = 0
-	GtkTreeView		::expander_size	 = 14
-	GtkExpander		::expander_size	 = 16
-
-	xthickness = 1
-	ythickness = 1
-
-	fg[NORMAL]			= "#000000" # black
-	fg[PRELIGHT]		= "#000000" # black
-	fg[SELECTED]		= "#ffffff" # white 
-	fg[ACTIVE]			= "#000000" # black
-	fg[INSENSITIVE]	= {0.6, 0.6, 0.6} # dark gray
-
-	bg[NORMAL]			= {0.95, 0.95, 0.95} # very light gray
-	bg[PRELIGHT]		= "#ffffff" # white
-	bg[SELECTED]		= OSX_MENU_COLOR_PLACEHOLDER	# menu color
-	bg[INSENSITIVE]	= {0.9, 0.9, 0.9} # light gray
-	bg[ACTIVE]			= {0.85, 0.85, 0.85} # gray
-
-	base[NORMAL]		= "#ffffff" # white 
-	base[PRELIGHT]		= OSX_MENU_COLOR_PLACEHOLDER # menu color
-	base[ACTIVE]		= {0.6, 0.6, 0.6} # dark gray
-	base[SELECTED]		= OSX_HILI_COLOR_PLACEHOLDER # highlight color
-	base[INSENSITIVE] = {0.9, 0.9, 0.9} # light gray
-
-	text[NORMAL]		= "#000000" # black
-	text[PRELIGHT]		= "#000000" # black
-	text[ACTIVE]		= "#ffffff" # white
-	text[SELECTED]		= "#ffffff" # white
-	text[INSENSITIVE]	= {0.6, 0.6, 0.6} # dark gray
-
-	engine "clearlooks" 
-	{
-	menubarstyle		= 1		# 0 = flat, 1 = sunken, 2 = flat gradient
-	menuitemstyle		= 0		# 0 = flat, 1 = 3d-ish (gradient), 2 = 3d-ish (button)
-	listviewitemstyle	= 0		# 0 = flat, 1 = 3d-ish (gradient)
-	progressbarstyle	= 0		# 0 = candy bar, 1 = flat
-	}
-}
-
-style "clearlooks-wide" = "clearlooks-default"
-{
-	xthickness = 2
-	ythickness = 2
-}
-
-style "clearlooks-button" = "clearlooks-default"
-{
-	xthickness = 3
-	ythickness = 3
-
-	bg[NORMAL] = "#f0f1f2" # a hint of blue...
-}
-
-style "clearlooks-notebook" = "clearlooks-wide"
-{
-	bg[NORMAL] = {0.93, 0.93, 0.93}
-	bg[INSENSITIVE] = {0.93, 0.93, 0.93}
-}
-
-style "clearlooks-tasklist" = "clearlooks-default"
-{
-	xthickness = 5
-	ythickness = 3
-}
-
-style "clearlooks-menu" = "clearlooks-default"
-{
-	xthickness = 2
-	ythickness = 1
-	bg[NORMAL] = "#ffffff"
-}
-
-style "clearlooks-menu-item" = "clearlooks-default"
-{
-	xthickness = 2
-	ythickness = 3
-	fg[PRELIGHT] = "#ffffff"
-	text[PRELIGHT] = "#ffffff"
-}
-
-style "clearlooks-menu-itembar" = "clearlooks-default"
-{
-	xthickness = 3
-	ythickness = 3
-}
-
-style "clearlooks-tree" = "clearlooks-default"
-{
-	xthickness = 2
-	ythickness = 2
-}
-
-style "clearlooks-frame-title" = "clearlooks-default"
-{
-	fg[NORMAL] = "#404040"
-}
-
-style "clearlooks-tooltips" = "clearlooks-default"
-{
-	xthickness = 4
-	ythickness = 4
-	bg[NORMAL] = { 1.0,1.0,0.75 }
-}
-
-style "clearlooks-progressbar" = "clearlooks-default"
-{
-	xthickness = 1
-	ythickness = 1
-
-	fg[PRELIGHT]	= "#ffffff"
-}
-
-style "clearlooks-combo" = "clearlooks-default"
-{
-	xthickness = 2
-	ythickness = 3
-}
-
-# Added pixmaps for scollbars
-style "scrollbar" = "default"
-{
-	# The values I set here have to do with the relative size of three graphic elements
-	# I have used: the slider, the arrow box, and the trough. They all have the same width
-	# of 15 pixels, but gtk wants to put in some spacing between them. It seems like it
-	# places the sliders inside the trough with a default 1 pixel border on either side of the slider,
-	# so that the trough has its width stretched by an additional two pixels(?). Setting the
-	# trough border makes the arrow box sit on top of the trough squarely, by making sure that
-	# the trough stays the same width as the arrowbox(?). I could be totally wrong here.
-	GtkRange::trough_border = 0
-	GtkRange::slider_width = 15
-
-	# This sets the size of the steppers (arrow buttons on the end of the scrollbar). 
-	# The image I am using is 15x15 pixels, and if I dont set this a one pixel line 
-	# gets cut off of the top of the "up" stepper.
-	GtkRange::stepper_size = 15
-
-	# Set a minimum length for the slider. Since I set the border on the slider 
-	# image to 15 pixels on either end of the slider I want the min length to be 
-	# at least 30 pixels to avoid an ugly slider when gtk wants to make it smaller 
-	# than 30 pixels.
-	GtkScrollbar::min_slider_length = 30
-
-	engine "pixmap" 
-	{
-		# Horizontal slider background
-		image 
-		{
-			function		= BOX
-			recolorable		= TRUE
-			detail			= "trough"
-			file			= "Scrollbars/trough-scrollbar-horiz.png"
-			border			= { 30, 30, 0, 0 }
-			stretch			= TRUE
-			orientation		= HORIZONTAL
-		}
-		
-		# Vertical slider background
-		image 
-		{
-			function		= BOX
-			recolorable		= TRUE
-			detail			= "trough"
-			file			= "Scrollbars/trough-scrollbar-vert.png"
-			border			= { 0, 0, 30, 30 }
-			stretch			= TRUE
-			orientation		= VERTICAL
-		}
-
-		# Normal horizontal slider
-		image 
-		{
-			function		= SLIDER
-			recolorable		= TRUE
-			state			= NORMAL
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-horiz.png"
-			border			= { 15, 15, 6, 6 }
-			stretch			= TRUE
-			orientation		= HORIZONTAL
-		}
-		
-		# Horizontal slider (active)
-		image 
-		{
-			function		= SLIDER
-			recolorable		= TRUE
-			state			= ACTIVE
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-horiz-prelight.png"
-			border			= { 15, 15, 6, 6 }
-			stretch			= TRUE
-			orientation		= HORIZONTAL
-		}
-
-		# Horizontal slider (mouse over)
-		image 
-		{
-			function		= SLIDER 
-			recolorable		= TRUE
-			state			= PRELIGHT
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-horiz-prelight.png"
-			border			= { 15, 15, 6, 6 }
-			stretch			= TRUE
-			orientation		= HORIZONTAL
-		}
-		
-		# Horizontal slider (Insesitive)
-		image 
-		{
-			function		= SLIDER 
-			recolorable		= TRUE
-			state			= INSENSITIVE
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-horiz.png"
-			border			= { 15, 15, 6, 6 }
-			stretch			= TRUE
-			orientation		= HORIZONTAL
-		}
-
-		# Normal vertical slider
-		image 
-		{
-			function		= SLIDER
-			recolorable		= TRUE
-			state			= NORMAL
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-vert.png"
-			border			= { 6, 6, 15, 15 }
-			stretch			= TRUE
-			orientation		= VERTICAL
-		}
-		
-		# Vertical slider (Active)
-		image 
-		{
-			function		= SLIDER
-			recolorable		= TRUE
-			state			= ACTIVE
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-vert.png"
-			border			= { 6, 6, 15, 15 }
-			stretch			= TRUE
-			orientation		= VERTICAL
-		}
-
-		# Vertical slider (mouse over)
-		image 
-		{
-			function		= SLIDER 
-			recolorable		= TRUE
-			state			= PRELIGHT
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-vert-prelight.png"
-			border			= { 6, 6, 15, 15 }
-			stretch			= TRUE
-			orientation		= VERTICAL
-		}
-		
-		# Vertical slider (Insesitive)
-		image 
-		{
-			function		= SLIDER 
-			recolorable		= TRUE
-			state			= INSENSITIVE
-			file			= "Scrollbars_AQUASTYLE_PLACEHOLDER/slider-vert-prelight.png"
-			border			= { 6, 6, 15, 15 }
-			stretch			= TRUE
-			orientation		= VERTICAL
-		}
-
-################################################################################
-# SCROLLBAR STEPPERS
-################################################################################
-
-	# Up
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= NORMAL
-		file				= "Scrollbars/stepper-up.png"
-		#border			= { 12, 2, 2, 9 }
-		stretch			= TRUE
-		arrow_direction = UP
-	}
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= PRELIGHT
-		file				= "Scrollbars/stepper-up.png"
-		#border			= { 12, 2, 2, 9 }
-		stretch			= TRUE
-		arrow_direction = UP
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= ACTIVE
-		file				= "Scrollbars/stepper-up.png"
-		#border			= { 12, 2, 2, 9 }
-		stretch			= TRUE
-		arrow_direction = UP
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= INSENSITIVE
-		file				= "Scrollbars/stepper-up.png"
-		#border			= { 12, 2, 2, 9 }
-		stretch			= TRUE
-		arrow_direction = UP
-	}
-
- ######### DOWN ############
-
-
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= NORMAL
-		file				= "Scrollbars/stepper-down.png"
-		#border			= { 12, 2, 10, 2 }
-		stretch			= TRUE
-		arrow_direction = DOWN
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= PRELIGHT
-		file				= "Scrollbars/stepper-down.png"
-		#border			= { 12, 2, 10, 2 }
-		stretch			= TRUE
-		arrow_direction = DOWN
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= ACTIVE
-		file				= "Scrollbars/stepper-down.png"
-		#border			= { 12, 2, 10, 2 }
-		stretch			= TRUE
-		arrow_direction = DOWN
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= INSENSITIVE
-		file				= "Scrollbars/stepper-down.png"
-		#border			= { 12, 2, 10, 2 }
-		stretch			= TRUE
-		arrow_direction = DOWN
-	}
-
-############ RIGHT ################
-
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= NORMAL
-		file				= "Scrollbars/stepper-right.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = RIGHT
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= PRELIGHT
-		file				= "Scrollbars/stepper-right.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = RIGHT
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= ACTIVE
-		file				= "Scrollbars/stepper-right.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = RIGHT
-	}
- image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= INSENSITIVE
-		file				= "Scrollbars/stepper-right.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = RIGHT
-	}
-
-############### LEFT ###################
-
-
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= NORMAL
-		file				= "Scrollbars/stepper-left.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = LEFT
-	}
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= PRELIGHT
-		file				= "Scrollbars/stepper-left.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = LEFT
-	}
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= ACTIVE
-		file				= "Scrollbars/stepper-left.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = LEFT
-	}
-	image 
-	{
-		function			= STEPPER
-		recolorable		= TRUE
-		state				= INSENSITIVE
-		file				= "Scrollbars/stepper-left.png"
-		#border			= { 2, 9, 2, 13 }
-		stretch			= TRUE
-		arrow_direction = LEFT
-	}
-	}
-}
-
-# widget styles
-class "GtkWidget" style "clearlooks-default"
-class "GtkButton" style "clearlooks-button"
-class "GtkCombo"	style "clearlooks-button"
-class "GtkRange"	style "clearlooks-wide"
-class "GtkFrame"	style "clearlooks-wide"
-class "GtkMenu"		style "clearlooks-menu"
-class "GtkEntry"	style "clearlooks-button"
-class "GtkMenuItem"		 style "clearlooks-menu-item"
-class "GtkStatusbar"	 style "clearlooks-wide"
-class "GtkNotebook"		 style "clearlooks-notebook"
-class "GtkProgressBar" style "clearlooks-progressbar"
-class "GtkScrollbar"	 style "scrollbar"
-
-widget_class "*MenuItem.*" style "clearlooks-menu-item"
-
-# combobox stuff
-widget_class "*.GtkComboBox.GtkButton" style "clearlooks-combo"
-widget_class "*.GtkCombo.GtkButton"		 style "clearlooks-combo"
-
-# tooltips stuff
-widget_class "*.tooltips.*.GtkToggleButton" style "clearlooks-tasklist"
-widget "gtk-tooltips" style "clearlooks-tooltips"
-
-# treeview stuff
-widget_class "*.GtkTreeView.GtkButton" style "clearlooks-tree"
-widget_class "*.GtkCTree.GtkButton" style "clearlooks-tree"
-widget_class "*.GtkList.GtkButton" style "clearlooks-tree"
-widget_class "*.GtkCList.GtkButton" style "clearlooks-tree"
-widget_class "*.GtkFrame.GtkLabel" style "clearlooks-frame-title"
-
-# notebook stuff
-widget_class "*.GtkNotebook.*.GtkEventBox" style "clearlooks-notebook"
-widget_class "*.GtkNotebook.*.GtkViewport" style "clearlooks-notebook"
-
-gtk-font-name="Lucida Grande 12"
-gtk-icon-theme-name = "gnome"
-gtk-icon-sizes = "gtk-menu=16,16:gtk-dialog=48,48:gtk-dnd=32,32:gtk-button=20,20:gtk-large-toolbar=24,24:gtk-small-toolbar=16,16:inkscape-decoration=12,12"
-
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/sync_osx_look.sh
===================================================================
--- packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/sync_osx_look.sh	(revision 16790)
+++ packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/sync_osx_look.sh	(working copy)
@@ -1,32 +0,0 @@
-#!/bin/sh
-#
-#	Reads defaults from Apple preferences and modifies GTK accordingly
-#
-#	(c) 2007 JiHO <jo.irisson@...400...>
-#	GNU General Public License http://www.gnu.org/copyleft/gpl.html
-#
-
-# Appearance setting
-aquaStyle=`defaults read "Apple Global Domain" AppleAquaColorVariant`
-# 1 for aqua, 6 for graphite
-
-# Highlight Color setting
-hiliColor=`defaults read "Apple Global Domain" AppleHighlightColor`
-# a RGB value, with components between 0 and 1
-
-# Menu items color
-if [[ aquaStyle -eq 1 ]]; then
-	menuColor="#4a76cd"
-else
-	menuColor="#7c8da4"
-fi
-# Format highlight color as a GTK rgb value
-hiliColorFormated=`echo $hiliColor | awk -F " " '{print "\\\{"$1","$2","$3"\\\}"}'`
-
-# echo $menuColor
-# echo $hiliColorFormated
-
-# Modify the gtkrc
-#	- with the correct colors
-#	- to point to the correct scrollbars folder
-sed 's/OSX_HILI_COLOR_PLACEHOLDER/'$hiliColorFormated'/g' pre_gtkrc | sed 's/OSX_MENU_COLOR_PLACEHOLDER/\"'$menuColor'\"/g' | sed 's/AQUASTYLE_PLACEHOLDER/'$aquaStyle'/g' > gtkrc
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars/stepper-right.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars/trough-scrollbar-horiz.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars/stepper-up.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars/stepper-down.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars/trough-scrollbar-vert.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars/stepper-left.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/slider-vert-prelight.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/copy-slider.sh
===================================================================
--- packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/copy-slider.sh	(revision 16790)
+++ packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/copy-slider.sh	(working copy)
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-cp -f slider-vert.png slider-vert-prelight.png
-cp -f slider-vert.png slider-horiz-prelight.png
-cp -f slider-vert.png slider-horiz.png
-convert -rotate 90 slider-horiz.png slider-horiz.png
-convert -rotate 90 slider-horiz-prelight.png slider-horiz-prelight.png
\ No newline at end of file
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/slider-vert.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/slider-horiz-prelight.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_1/slider-horiz.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/slider-vert-prelight.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/copy-slider.sh
===================================================================
--- packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/copy-slider.sh	(revision 16790)
+++ packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/copy-slider.sh	(working copy)
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-cp -f slider-vert.png slider-vert-prelight.png
-cp -f slider-vert.png slider-horiz-prelight.png
-cp -f slider-vert.png slider-horiz.png
-convert -rotate 90 slider-horiz.png slider-horiz.png
-convert -rotate 90 slider-horiz-prelight.png slider-horiz-prelight.png
\ No newline at end of file
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/slider-vert.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/slider-horiz-prelight.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: packaging/macosx/Resources/themes/Clearlooks-Quicksilver-OSX/gtk-2.0/Scrollbars_6/slider-horiz.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: src/ige-mac-menu.c
===================================================================
--- src/ige-mac-menu.c	(revision 0)
+++ src/ige-mac-menu.c	(revision 0)
@@ -0,0 +1,915 @@
+/* GTK+ Integration for the Mac OS X Menubar.
+ *
+ * Copyright (C) 2007 Pioneer Research Center USA, Inc.
+ *
+ * For further information, see:
+ * http://developer.imendio.com/projects/gtk-macosx/menubar
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+
+#ifdef GDK_WINDOWING_QUARTZ
+
+#include <gdk/gdkkeysyms.h>
+
+#include <Carbon/Carbon.h>
+
+#include "ige-mac-menu.h"
+
+
+/* TODO
+ *
+ * - Sync adding/removing/reordering items
+ * - Create on demand? (can this be done with gtk+? ie fill in menu
+     items when the menu is opened)
+ * - Figure out what to do per app/window...
+ *
+ */
+
+#define IGE_QUARTZ_MENU_CREATOR 'IGEC'
+#define IGE_QUARTZ_ITEM_WIDGET  'IWID'
+
+
+static void   sync_menu_shell (GtkMenuShell *menu_shell,
+			       MenuRef       carbon_menu,
+			       gboolean      toplevel,
+			       gboolean      debug);
+
+
+/*
+ * utility functions
+ */
+
+static GtkWidget *
+find_menu_label (GtkWidget *widget)
+{
+  GtkWidget *label = NULL;
+
+  if (GTK_IS_LABEL (widget))
+    return widget;
+
+  if (GTK_IS_CONTAINER (widget))
+    {
+      GList *children;
+      GList *l;
+
+      children = gtk_container_get_children (GTK_CONTAINER (widget));
+
+      for (l = children; l; l = l->next)
+	{
+	  label = find_menu_label (l->data);
+	  if (label)
+	    break;
+	}
+
+      g_list_free (children);
+    }
+
+  return label;
+}
+
+static const gchar *
+get_menu_label_text (GtkWidget  *menu_item,
+		     GtkWidget **label)
+{
+  GtkWidget *my_label;
+
+  my_label = find_menu_label (menu_item);
+  if (label)
+    *label = my_label;
+
+  if (my_label)
+    return gtk_label_get_text (GTK_LABEL (my_label));
+
+  return NULL;
+}
+
+static gboolean
+accel_find_func (GtkAccelKey *key,
+		 GClosure    *closure,
+		 gpointer     data)
+{
+  return (GClosure *) data == closure;
+}
+
+
+/*
+ * CarbonMenu functions
+ */
+
+typedef struct
+{
+  MenuRef menu;
+} CarbonMenu;
+
+static GQuark carbon_menu_quark = 0;
+
+static CarbonMenu *
+carbon_menu_new (void)
+{
+  return g_slice_new0 (CarbonMenu);
+}
+
+static void
+carbon_menu_free (CarbonMenu *menu)
+{
+  g_slice_free (CarbonMenu, menu);
+}
+
+static CarbonMenu *
+carbon_menu_get (GtkWidget *widget)
+{
+  return g_object_get_qdata (G_OBJECT (widget), carbon_menu_quark);
+}
+
+static void
+carbon_menu_connect (GtkWidget *menu,
+		     MenuRef    menuRef)
+{
+  CarbonMenu *carbon_menu = carbon_menu_get (menu);
+
+  if (!carbon_menu)
+    {
+      carbon_menu = carbon_menu_new ();
+
+      g_object_set_qdata_full (G_OBJECT (menu), carbon_menu_quark,
+			       carbon_menu,
+			       (GDestroyNotify) carbon_menu_free);
+    }
+
+  carbon_menu->menu = menuRef;
+}
+
+
+/*
+ * CarbonMenuItem functions
+ */
+
+typedef struct
+{
+  MenuRef        menu;
+  MenuItemIndex  index;
+  MenuRef        submenu;
+  GClosure      *accel_closure;
+} CarbonMenuItem;
+
+static GQuark carbon_menu_item_quark = 0;
+
+static CarbonMenuItem *
+carbon_menu_item_new (void)
+{
+  return g_slice_new0 (CarbonMenuItem);
+}
+
+static void
+carbon_menu_item_free (CarbonMenuItem *menu_item)
+{
+  if (menu_item->accel_closure)
+    g_closure_unref (menu_item->accel_closure);
+
+  g_slice_free (CarbonMenuItem, menu_item);
+}
+
+static CarbonMenuItem *
+carbon_menu_item_get (GtkWidget *widget)
+{
+  return g_object_get_qdata (G_OBJECT (widget), carbon_menu_item_quark);
+}
+
+static void
+carbon_menu_item_update_state (CarbonMenuItem *carbon_item,
+			       GtkWidget      *widget)
+{
+  gboolean sensitive;
+  gboolean visible;
+  UInt32   set_attrs = 0;
+  UInt32   clear_attrs = 0;
+
+  g_object_get (widget,
+                "sensitive", &sensitive,
+                "visible",   &visible,
+                NULL);
+
+  if (!sensitive)
+    set_attrs |= kMenuItemAttrDisabled;
+  else
+    clear_attrs |= kMenuItemAttrDisabled;
+
+  if (!visible)
+    set_attrs |= kMenuItemAttrHidden;
+  else
+    clear_attrs |= kMenuItemAttrHidden;
+
+  ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
+                            set_attrs, clear_attrs);
+}
+
+static void
+carbon_menu_item_update_active (CarbonMenuItem *carbon_item,
+				GtkWidget      *widget)
+{
+  gboolean active;
+
+  g_object_get (widget,
+                "active", &active,
+                NULL);
+
+  CheckMenuItem (carbon_item->menu, carbon_item->index,
+		 active);
+}
+
+static void
+carbon_menu_item_update_submenu (CarbonMenuItem *carbon_item,
+				 GtkWidget      *widget)
+{
+  GtkWidget *submenu;
+
+  submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+
+  if (submenu)
+    {
+      const gchar *label_text;
+      CFStringRef  cfstr = NULL;
+
+      label_text = get_menu_label_text (widget, NULL);
+      if (label_text)
+        cfstr = CFStringCreateWithCString (NULL, label_text,
+					   kCFStringEncodingUTF8);
+
+      CreateNewMenu (0, 0, &carbon_item->submenu);
+      SetMenuTitleWithCFString (carbon_item->submenu, cfstr);
+      SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
+				   carbon_item->submenu);
+
+      sync_menu_shell (GTK_MENU_SHELL (submenu), carbon_item->submenu, FALSE, FALSE);
+
+      if (cfstr)
+	CFRelease (cfstr);
+    }
+  else
+    {
+      SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
+				   NULL);
+      carbon_item->submenu = NULL;
+    }
+}
+
+static void
+carbon_menu_item_update_label (CarbonMenuItem *carbon_item,
+			       GtkWidget      *widget)
+{
+  const gchar *label_text;
+  CFStringRef  cfstr = NULL;
+
+  label_text = get_menu_label_text (widget, NULL);
+  if (label_text)
+    cfstr = CFStringCreateWithCString (NULL, label_text,
+				       kCFStringEncodingUTF8);
+
+  SetMenuItemTextWithCFString (carbon_item->menu, carbon_item->index,
+			       cfstr);
+
+  if (cfstr)
+    CFRelease (cfstr);
+}
+
+static void
+carbon_menu_item_update_accelerator (CarbonMenuItem *carbon_item,
+				     GtkWidget      *widget)
+{
+  GtkWidget *label;
+
+  get_menu_label_text (widget, &label);
+
+  if (GTK_IS_ACCEL_LABEL (label) &&
+      GTK_ACCEL_LABEL (label)->accel_closure)
+    {
+      GtkAccelKey *key;
+
+      key = gtk_accel_group_find (GTK_ACCEL_LABEL (label)->accel_group,
+				  accel_find_func,
+				  GTK_ACCEL_LABEL (label)->accel_closure);
+
+      if (key            &&
+	  key->accel_key &&
+	  key->accel_flags & GTK_ACCEL_VISIBLE)
+	{
+	  GdkDisplay      *display = gtk_widget_get_display (widget);
+	  GdkKeymap       *keymap  = gdk_keymap_get_for_display (display);
+	  GdkKeymapKey    *keys;
+	  gint             n_keys;
+
+	  if (gdk_keymap_get_entries_for_keyval (keymap, key->accel_key,
+						 &keys, &n_keys))
+	    {
+	      UInt8 modifiers = 0;
+
+	      SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
+				     true, keys[0].keycode);
+
+	      g_free (keys);
+
+	      if (key->accel_mods)
+		{
+		  if (key->accel_mods & GDK_SHIFT_MASK)
+		    modifiers |= kMenuShiftModifier;
+
+		  if (key->accel_mods & GDK_MOD1_MASK)
+		    modifiers |= kMenuOptionModifier;
+		}
+
+	      if (!(key->accel_mods & GDK_CONTROL_MASK))
+		{
+		  modifiers |= kMenuNoCommandModifier;
+		}
+
+	      SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
+				    modifiers);
+
+	      return;
+	    }
+	}
+    }
+
+  /*  otherwise, clear the menu shortcut  */
+  SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
+			kMenuNoModifiers | kMenuNoCommandModifier);
+  ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
+			    0, kMenuItemAttrUseVirtualKey);
+  SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
+			 false, 0);
+}
+
+static void
+carbon_menu_item_accel_changed (GtkAccelGroup   *accel_group,
+				guint            keyval,
+				GdkModifierType  modifier,
+				GClosure        *accel_closure,
+				GtkWidget       *widget)
+{
+  CarbonMenuItem *carbon_item = carbon_menu_item_get (widget);
+  GtkWidget      *label;
+
+  get_menu_label_text (widget, &label);
+
+  if (GTK_IS_ACCEL_LABEL (label) &&
+      GTK_ACCEL_LABEL (label)->accel_closure == accel_closure)
+    carbon_menu_item_update_accelerator (carbon_item, widget);
+}
+
+static void
+carbon_menu_item_update_accel_closure (CarbonMenuItem *carbon_item,
+				       GtkWidget      *widget)
+{
+  GtkAccelGroup *group;
+  GtkWidget     *label;
+
+  get_menu_label_text (widget, &label);
+
+  if (carbon_item->accel_closure)
+    {
+      group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
+
+      g_signal_handlers_disconnect_by_func (group,
+					    carbon_menu_item_accel_changed,
+					    widget);
+
+      g_closure_unref (carbon_item->accel_closure);
+      carbon_item->accel_closure = NULL;
+    }
+
+  if (GTK_IS_ACCEL_LABEL (label))
+    carbon_item->accel_closure = GTK_ACCEL_LABEL (label)->accel_closure;
+
+  if (carbon_item->accel_closure)
+    {
+      g_closure_ref (carbon_item->accel_closure);
+
+      group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
+
+      g_signal_connect_object (group, "accel-changed",
+			       G_CALLBACK (carbon_menu_item_accel_changed),
+			       widget, 0);
+    }
+
+  carbon_menu_item_update_accelerator (carbon_item, widget);
+}
+
+static void
+carbon_menu_item_notify (GObject        *object,
+			 GParamSpec     *pspec,
+			 CarbonMenuItem *carbon_item)
+{
+  if (!strcmp (pspec->name, "sensitive") ||
+      !strcmp (pspec->name, "visible"))
+    {
+      carbon_menu_item_update_state (carbon_item, GTK_WIDGET (object));
+    }
+  else if (!strcmp (pspec->name, "active"))
+    {
+      carbon_menu_item_update_active (carbon_item, GTK_WIDGET (object));
+    }
+  else if (!strcmp (pspec->name, "submenu"))
+    {
+      carbon_menu_item_update_submenu (carbon_item, GTK_WIDGET (object));
+    }
+}
+
+static void
+carbon_menu_item_notify_label (GObject    *object,
+			       GParamSpec *pspec,
+			       gpointer    data)
+{
+  CarbonMenuItem *carbon_item = carbon_menu_item_get (GTK_WIDGET (object));
+
+  if (!strcmp (pspec->name, "label"))
+    {
+      carbon_menu_item_update_label (carbon_item,
+				     GTK_WIDGET (object));
+    }
+  else if (!strcmp (pspec->name, "accel-closure"))
+    {
+      carbon_menu_item_update_accel_closure (carbon_item,
+					     GTK_WIDGET (object));
+    }
+}
+
+static CarbonMenuItem *
+carbon_menu_item_connect (GtkWidget     *menu_item,
+			  GtkWidget     *label,
+			  MenuRef        menu,
+			  MenuItemIndex  index)
+{
+  CarbonMenuItem *carbon_item = carbon_menu_item_get (menu_item);
+
+  if (!carbon_item)
+    {
+      carbon_item = carbon_menu_item_new ();
+
+      g_object_set_qdata_full (G_OBJECT (menu_item), carbon_menu_item_quark,
+			       carbon_item,
+			       (GDestroyNotify) carbon_menu_item_free);
+
+      g_signal_connect (menu_item, "notify",
+                        G_CALLBACK (carbon_menu_item_notify),
+                        carbon_item);
+
+      if (label)
+	g_signal_connect_swapped (label, "notify::label",
+				  G_CALLBACK (carbon_menu_item_notify_label),
+				  menu_item);
+    }
+
+  carbon_item->menu  = menu;
+  carbon_item->index = index;
+
+  return carbon_item;
+}
+
+
+/*
+ * carbon event handler
+ */
+
+static OSStatus
+menu_event_handler_func (EventHandlerCallRef  event_handler_call_ref,
+			 EventRef             event_ref,
+			 void                *data)
+{
+  UInt32  event_class = GetEventClass (event_ref);
+  UInt32  event_kind = GetEventKind (event_ref);
+  MenuRef menu_ref;
+
+  switch (event_class)
+    {
+    case kEventClassCommand:
+      /* This is called when activating (is that the right GTK+ term?)
+       * a menu item.
+       */
+      if (event_kind == kEventCommandProcess)
+	{
+	  HICommand command;
+	  OSStatus  err;
+
+	  /*g_printerr ("Menu: kEventClassCommand/kEventCommandProcess\n");*/
+
+	  err = GetEventParameter (event_ref, kEventParamDirectObject,
+				   typeHICommand, 0,
+				   sizeof (command), 0, &command);
+
+	  if (err == noErr)
+	    {
+	      GtkWidget *widget = NULL;
+
+	      /* Get any GtkWidget associated with the item. */
+	      err = GetMenuItemProperty (command.menu.menuRef,
+					 command.menu.menuItemIndex,
+					 IGE_QUARTZ_MENU_CREATOR,
+					 IGE_QUARTZ_ITEM_WIDGET,
+					 sizeof (widget), 0, &widget);
+	      if (err == noErr && GTK_IS_WIDGET (widget))
+		{
+		  gtk_menu_item_activate (GTK_MENU_ITEM (widget));
+		  return noErr;
+		}
+	    }
+	}
+      break;
+
+    case kEventClassMenu:
+      GetEventParameter (event_ref,
+			 kEventParamDirectObject,
+			 typeMenuRef,
+			 NULL,
+			 sizeof (menu_ref),
+			 NULL,
+			 &menu_ref);
+
+      switch (event_kind)
+	{
+	case kEventMenuTargetItem:
+	  /* This is called when an item is selected (what is the
+	   * GTK+ term? prelight?)
+	   */
+	  /*g_printerr ("kEventClassMenu/kEventMenuTargetItem\n");*/
+	  break;
+
+	case kEventMenuOpening:
+	  /* Is it possible to dynamically build the menu here? We
+	   * can at least set visibility/sensitivity.
+	   */
+	  /*g_printerr ("kEventClassMenu/kEventMenuOpening\n");*/
+	  break;
+
+	case kEventMenuClosed:
+	  /*g_printerr ("kEventClassMenu/kEventMenuClosed\n");*/
+	  break;
+
+	default:
+	  break;
+	}
+
+      break;
+
+    default:
+      break;
+    }
+
+  return CallNextEventHandler (event_handler_call_ref, event_ref);
+}
+
+static void
+setup_menu_event_handler (void)
+{
+  EventHandlerUPP menu_event_handler_upp;
+  EventHandlerRef menu_event_handler_ref;
+  const EventTypeSpec menu_events[] = {
+    { kEventClassCommand, kEventCommandProcess },
+    { kEventClassMenu, kEventMenuTargetItem },
+    { kEventClassMenu, kEventMenuOpening },
+    { kEventClassMenu, kEventMenuClosed }
+  };
+
+  /* FIXME: We might have to install one per window? */
+
+  menu_event_handler_upp = NewEventHandlerUPP (menu_event_handler_func);
+  InstallEventHandler (GetApplicationEventTarget (), menu_event_handler_upp,
+		       GetEventTypeCount (menu_events), menu_events, 0,
+		       &menu_event_handler_ref);
+
+#if 0
+  /* FIXME: Remove the handler with: */
+  RemoveEventHandler(menu_event_handler_ref);
+  DisposeEventHandlerUPP(menu_event_handler_upp);
+#endif
+}
+
+static void
+sync_menu_shell (GtkMenuShell *menu_shell,
+                 MenuRef       carbon_menu,
+		 gboolean      toplevel,
+		 gboolean      debug)
+{
+  GList         *children;
+  GList         *l;
+  MenuItemIndex  carbon_index = 1;
+
+  if (debug)
+    g_printerr ("%s: syncing shell %p\n", G_STRFUNC, menu_shell);
+
+  carbon_menu_connect (GTK_WIDGET (menu_shell), carbon_menu);
+
+  children = gtk_container_get_children (GTK_CONTAINER (menu_shell));
+
+  for (l = children; l; l = l->next)
+    {
+      GtkWidget      *menu_item = l->data;
+      CarbonMenuItem *carbon_item;
+
+      if (GTK_IS_TEAROFF_MENU_ITEM (menu_item))
+	continue;
+
+      if (toplevel && g_object_get_data (G_OBJECT (menu_item),
+					 "gtk-empty-menu-item"))
+	continue;
+
+      carbon_item = carbon_menu_item_get (menu_item);
+
+      if (debug)
+	g_printerr ("%s: carbon_item %d for menu_item %d (%s, %s)\n",
+		    G_STRFUNC, carbon_item ? carbon_item->index : -1,
+		    carbon_index, get_menu_label_text (menu_item, NULL),
+		    g_type_name (G_TYPE_FROM_INSTANCE (menu_item)));
+
+      if (carbon_item && carbon_item->index != carbon_index)
+	{
+	  if (debug)
+	    g_printerr ("%s:   -> not matching, deleting\n", G_STRFUNC);
+
+	  DeleteMenuItem (carbon_item->menu, carbon_index);
+	  carbon_item = NULL;
+	}
+
+      if (!carbon_item)
+	{
+	  GtkWidget          *label      = NULL;
+	  const gchar        *label_text;
+	  CFStringRef         cfstr      = NULL;
+	  MenuItemAttributes  attributes = 0;
+
+	  if (debug)
+	    g_printerr ("%s:   -> creating new\n", G_STRFUNC);
+
+	  label_text = get_menu_label_text (menu_item, &label);
+	  if (label_text)
+	    cfstr = CFStringCreateWithCString (NULL, label_text,
+					       kCFStringEncodingUTF8);
+
+	  if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item))
+	    attributes |= kMenuItemAttrSeparator;
+
+	  if (!GTK_WIDGET_IS_SENSITIVE (menu_item))
+	    attributes |= kMenuItemAttrDisabled;
+
+	  if (!GTK_WIDGET_VISIBLE (menu_item))
+	    attributes |= kMenuItemAttrHidden;
+
+	  InsertMenuItemTextWithCFString (carbon_menu, cfstr,
+					  carbon_index - 1,
+					  attributes, 0);
+	  SetMenuItemProperty (carbon_menu, carbon_index,
+			       IGE_QUARTZ_MENU_CREATOR,
+			       IGE_QUARTZ_ITEM_WIDGET,
+			       sizeof (menu_item), &menu_item);
+
+	  if (cfstr)
+	    CFRelease (cfstr);
+
+	  carbon_item = carbon_menu_item_connect (menu_item, label,
+						  carbon_menu,
+						  carbon_index);
+
+	  if (GTK_IS_CHECK_MENU_ITEM (menu_item))
+	    carbon_menu_item_update_active (carbon_item, menu_item);
+
+	  carbon_menu_item_update_accel_closure (carbon_item, menu_item);
+
+	  if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item)))
+	    carbon_menu_item_update_submenu (carbon_item, menu_item);
+	}
+
+      carbon_index++;
+    }
+
+  g_list_free (children);
+}
+
+
+static gulong emission_hook_id = 0;
+
+static gboolean
+parent_set_emission_hook (GSignalInvocationHint *ihint,
+			  guint                  n_param_values,
+			  const GValue          *param_values,
+			  gpointer               data)
+{
+  GtkWidget *instance = g_value_get_object (param_values);
+
+  if (GTK_IS_MENU_ITEM (instance))
+    {
+      GtkWidget *previous_parent = g_value_get_object (param_values + 1);
+      GtkWidget *menu_shell      = NULL;
+
+      if (GTK_IS_MENU_SHELL (previous_parent))
+	{
+	  menu_shell = previous_parent;
+        }
+      else if (GTK_IS_MENU_SHELL (instance->parent))
+	{
+	  menu_shell = instance->parent;
+	}
+
+      if (menu_shell)
+        {
+	  CarbonMenu *carbon_menu = carbon_menu_get (menu_shell);
+
+	  if (carbon_menu)
+	    {
+#if 0
+	      g_printerr ("%s: item %s %p (%s, %s)\n", G_STRFUNC,
+			  previous_parent ? "removed from" : "added to",
+			  menu_shell,
+			  get_menu_label_text (instance, NULL),
+			  g_type_name (G_TYPE_FROM_INSTANCE (instance)));
+#endif
+
+	      sync_menu_shell (GTK_MENU_SHELL (menu_shell),
+			       carbon_menu->menu,
+			       carbon_menu->menu == (MenuRef) data,
+			       FALSE);
+	    }
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+parent_set_emission_hook_remove (GtkWidget *widget,
+				 gpointer   data)
+{
+  g_signal_remove_emission_hook (g_signal_lookup ("parent-set",
+						  GTK_TYPE_WIDGET),
+				 emission_hook_id);
+}
+
+
+/*
+ * public functions
+ */
+
+void
+ige_mac_menu_set_menu_bar (GtkMenuShell *menu_shell)
+{
+  MenuRef carbon_menubar;
+  guint   hook_id;
+
+  g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
+
+  if (carbon_menu_quark == 0)
+    carbon_menu_quark = g_quark_from_static_string ("CarbonMenu");
+
+  if (carbon_menu_item_quark == 0)
+    carbon_menu_item_quark = g_quark_from_static_string ("CarbonMenuItem");
+
+  CreateNewMenu (0 /*id*/, 0 /*options*/, &carbon_menubar);
+  SetRootMenu (carbon_menubar);
+
+  setup_menu_event_handler ();
+
+  emission_hook_id =
+    g_signal_add_emission_hook (g_signal_lookup ("parent-set",
+						 GTK_TYPE_WIDGET),
+				0,
+				parent_set_emission_hook,
+				carbon_menubar, NULL);
+
+  g_signal_connect (menu_shell, "destroy",
+		    G_CALLBACK (parent_set_emission_hook_remove),
+		    NULL);
+
+  sync_menu_shell (menu_shell, carbon_menubar, TRUE, FALSE);
+}
+
+void
+ige_mac_menu_set_quit_menu_item (GtkMenuItem *menu_item)
+{
+  MenuRef       appmenu;
+  MenuItemIndex index;
+
+  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+  if (GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
+                                   &appmenu, &index) == noErr)
+    {
+      SetMenuItemCommandID (appmenu, index, 0);
+      SetMenuItemProperty (appmenu, index,
+                           IGE_QUARTZ_MENU_CREATOR,
+                           IGE_QUARTZ_ITEM_WIDGET,
+                           sizeof (menu_item), &menu_item);
+
+      gtk_widget_hide (GTK_WIDGET (menu_item));
+    }
+}
+
+
+struct _IgeMacMenuGroup
+{
+  GList *items;
+};
+
+static GList *app_menu_groups = NULL;
+
+IgeMacMenuGroup *
+ige_mac_menu_add_app_menu_group (void)
+{
+  IgeMacMenuGroup *group = g_slice_new0 (IgeMacMenuGroup);
+
+  app_menu_groups = g_list_append (app_menu_groups, group);
+
+  return group;
+}
+
+void
+ige_mac_menu_add_app_menu_item (IgeMacMenuGroup *group,
+				GtkMenuItem     *menu_item,
+				const gchar     *label)
+{
+  MenuRef  appmenu;
+  GList   *list;
+  gint     index = 0;
+
+  g_return_if_fail (group != NULL);
+  g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+  if (GetIndMenuItemWithCommandID (NULL, kHICommandHide, 1,
+                                   &appmenu, NULL) != noErr)
+    {
+      g_warning ("%s: retrieving app menu failed",
+		 G_STRFUNC);
+      return;
+    }
+
+  for (list = app_menu_groups; list; list = g_list_next (list))
+    {
+      IgeMacMenuGroup *list_group = list->data;
+
+      index += g_list_length (list_group->items);
+
+      /*  adjust index for the separator between groups, but not
+       *  before the first group
+       */
+      if (list_group->items && list->prev)
+	index++;
+
+      if (group == list_group)
+	{
+	  CFStringRef cfstr;
+
+	  /*  add a separator before adding the first item, but not
+	   *  for the first group
+	   */
+	  if (!group->items && list->prev)
+	    {
+	      InsertMenuItemTextWithCFString (appmenu, NULL, index,
+					      kMenuItemAttrSeparator, 0);
+	      index++;
+	    }
+
+	  if (!label)
+	    label = get_menu_label_text (GTK_WIDGET (menu_item), NULL);
+
+	  cfstr = CFStringCreateWithCString (NULL, label,
+					     kCFStringEncodingUTF8);
+
+	  InsertMenuItemTextWithCFString (appmenu, cfstr, index, 0, 0);
+	  SetMenuItemProperty (appmenu, index + 1,
+			       IGE_QUARTZ_MENU_CREATOR,
+			       IGE_QUARTZ_ITEM_WIDGET,
+			       sizeof (menu_item), &menu_item);
+
+	  CFRelease (cfstr);
+
+	  gtk_widget_hide (GTK_WIDGET (menu_item));
+
+	  group->items = g_list_append (group->items, menu_item);
+
+	  return;
+	}
+    }
+
+  if (!list)
+    g_warning ("%s: app menu group %p does not exist",
+	       G_STRFUNC, group);
+}
+
+#endif /* GDK_WINDOWING_QUARTZ */

Property changes on: src/ige-mac-menu.c
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Id Rev Date Author
Name: svn:eol-style
   + native

Index: src/ige-mac-menu.h
===================================================================
--- src/ige-mac-menu.h	(revision 0)
+++ src/ige-mac-menu.h	(revision 0)
@@ -0,0 +1,43 @@
+/* GTK+ Integration for the Mac OS X Menubar.
+ *
+ * Copyright (C) 2007 Pioneer Research Center USA, Inc.
+ *
+ * For further information, see:
+ * http://developer.imendio.com/projects/gtk-macosx/menubar
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __IGE_MAC_MENU_H__
+#define __IGE_MAC_MENU_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _IgeMacMenuGroup IgeMacMenuGroup;
+
+void              ige_mac_menu_set_menu_bar       (GtkMenuShell    *menu_shell);
+void              ige_mac_menu_set_quit_menu_item (GtkMenuItem     *menu_item);
+
+IgeMacMenuGroup * ige_mac_menu_add_app_menu_group (void);
+void              ige_mac_menu_add_app_menu_item  (IgeMacMenuGroup *group,
+						   GtkMenuItem     *menu_item,
+						   const gchar     *label);
+
+G_END_DECLS
+
+#endif /* __IGE_MAC_MENU_H__ */

Property changes on: src/ige-mac-menu.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Id Rev Date Author
Name: svn:eol-style
   + native

Index: src/interface.cpp
===================================================================
--- src/interface.cpp	(revision 16998)
+++ src/interface.cpp	(working copy)
@@ -68,6 +68,11 @@
 #include "event-context.h"
 #include "gradient-drag.h"
 
+// Include Mac OS X menu synchronization on native OSX build
+#ifdef GDK_WINDOWING_QUARTZ
+#include "ige-mac-menu.h"
+#endif
+
 using Inkscape::IO::StringOutputStream;
 using Inkscape::IO::Base64OutputStream;
 
@@ -945,9 +950,17 @@
 {
     GtkWidget *mbar = gtk_menu_bar_new();
 
+#ifdef GDK_WINDOWING_QUARTZ
+	ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(mbar));
+#endif
+
     sp_ui_build_dyn_menus(inkscape_get_menus(INKSCAPE), mbar, view);
 
+#ifdef GDK_WINDOWING_QUARTZ
+	return NULL;
+#else
     return mbar;
+#endif
 }
 
 static void leave_group(GtkMenuItem *, SPDesktop *desktop) {
Index: src/widgets/toolbox.cpp
===================================================================
--- src/widgets/toolbox.cpp	(revision 16998)
+++ src/widgets/toolbox.cpp	(working copy)
@@ -630,14 +630,9 @@
 {
     GtkWidget *tb = gtk_vbox_new(FALSE, 0);
 
-    GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
-    GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
     gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
-    gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
-    gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
 
     g_object_set_data(G_OBJECT(tb), "desktop", NULL);
-    g_object_set_data(G_OBJECT(tb), "top_spacer", tb_s);
 
     gtk_widget_set_sensitive(tb, FALSE);
 
@@ -667,11 +662,7 @@
 {
     GtkWidget *tb = gtk_vbox_new(FALSE, 0);
 
-    GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
-    GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
     gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
-    gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
-    gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
 
     g_object_set_data(G_OBJECT(tb), "desktop", NULL);
     gtk_widget_set_sensitive(tb, FALSE);
@@ -1439,10 +1430,6 @@
     }
     gtk_widget_show(toolbox);
 
-    // need to show the spacer, or the padding will be off
-    GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
-    gtk_widget_show(spacer);
-
     gtk_widget_show_all(shown_toolbox);
 }
 
Index: src/Makefile_insert
===================================================================
--- src/Makefile_insert	(revision 16998)
+++ src/Makefile_insert	(working copy)
@@ -84,6 +84,7 @@
 	help.cpp help.h	\
 	helper-fns.h \
 	icon-size.h \
+	ige-mac-menu.h ige-mac-menu.c \
 	inkscape-stock.cpp inkscape-stock.h\
 	inkscape.cpp inkscape.h inkscape-private.h	\
 	interface.cpp interface.h	\
@@ -374,6 +375,7 @@
 	$(FREETYPE_LIBS)	\
 	$(kdeldadd)		\
 	$(win32ldflags)		\
+	$(CARBON_LDFLAGS)	\
 	$(PERL_LIBS)		\
 	$(PYTHON_LIBS)	\
 	$(INKBOARD_LIBS) \
Index: configure.ac
===================================================================
--- configure.ac	(revision 16790)
+++ configure.ac	(working copy)
@@ -586,6 +586,21 @@
 fi
 PKG_CHECK_MODULES(INKSCAPE, gdkmm-2.4  glibmm-2.4  gtkmm-2.4 >= 2.10.0  gtk+-2.0  libxml-2.0 >= 2.6.11  libxslt >= 1.0.15  cairo  sigc++-2.0 >= $min_sigc_version  $ink_spell_pkg  gthread-2.0 >= 2.0 libpng >= 1.2)
 
+# Check for Apple Mac OS X Carbon framework
+carbon_ok=no
+AC_MSG_CHECKING([for Mac OS X Carbon support])
+AC_TRY_CPP([
+#include <Carbon/Carbon.h>
+#include <CoreServices/CoreServices.h>
+], carbon_ok=yes)
+AC_MSG_RESULT($carbon_ok)
+if test "x$carbon_ok" = "xyes"; then
+  AC_DEFINE(HAVE_CARBON, 1, [define to 1 if Carbon is available])
+  CARBON_LDFLAGS="-framework Carbon"
+  AC_SUBST(CARBON_LDFLAGS)
+fi
+AM_CONDITIONAL(HAVE_CARBON, test "x$carbon_ok" = "xyes")
+
 # Check for some boost header files
 AC_CHECK_HEADERS([boost/concept_check.hpp], [], AC_MSG_ERROR([You need the boost package (e.g. libboost-dev)]))
 
