diff options
author | Richard Purdie <rpurdie@linux.intel.com> | 2010-08-27 15:14:24 +0100 |
---|---|---|
committer | Richard Purdie <rpurdie@linux.intel.com> | 2010-08-27 15:29:45 +0100 |
commit | 29d6678fd546377459ef75cf54abeef5b969b5cf (patch) | |
tree | 8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-gnome/gtk+ | |
parent | da49de6885ee1bc424e70bc02f21f6ab920efb55 (diff) | |
download | openembedded-core-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz openembedded-core-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.bz2 openembedded-core-29d6678fd546377459ef75cf54abeef5b969b5cf.zip |
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things
and is generally overwhelming. This commit splits it into several
logical sections roughly based on function, recipes.txt gives more
information about the classifications used.
The opportunity is also used to switch from "packages" to "recipes"
as used in OpenEmbedded as the term "packages" can be confusing to
people and has many different meanings.
Not all recipes have been classified yet, this is just a first pass
at separating things out. Some packages are moved to meta-extras as
they're no longer actively used or maintained.
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-gnome/gtk+')
43 files changed, 14336 insertions, 0 deletions
diff --git a/meta/recipes-gnome/gtk+/gdk-pixbuf-csource-native_2.12.7.bb b/meta/recipes-gnome/gtk+/gdk-pixbuf-csource-native_2.12.7.bb new file mode 100644 index 0000000000..c88a79570a --- /dev/null +++ b/meta/recipes-gnome/gtk+/gdk-pixbuf-csource-native_2.12.7.bb @@ -0,0 +1,37 @@ +require gtk+_${PV}.bb +inherit native +DEPENDS = "jpeg-native libpng-native gettext-native glib-2.0-native libx11-native" +S = "${WORKDIR}/gtk+-${PV}" +FILESPATH = "${FILE_DIRNAME}/gdk-pixbuf-csource:${FILE_DIRNAME}/gtk+-${PV}:${FILE_DIRNAME}/files" +SRC_URI += "file://reduce-dependencies.patch;patch=1" +PR = "r11" + +#clear recommends for uclibc builds +RRECOMMENDS = " " +RRECOMMENDS_${PN}_linux = " " +RRECOMMENDS_${PN}_linux-gnueabi = " " + +EXTRA_OECONF = "\ + --with-gdktarget=x11 \ + --without-libtiff \ + --with-libjpeg \ + --with-libpng \ + --x-includes=${STAGING_INCDIR} \ + --x-libraries=${STAGING_LIBDIR} \ +" + +PACKAGES_DYNAMIC = "" + +do_compile() { + cd gdk-pixbuf && oe_runmake +} + +do_install() { + cd gdk-pixbuf + oe_runmake 'DESTDIR=${D}' install + install -d ${D}${sysconfdir}/gtk-2.0 + GDK_PIXBUF_MODULEDIR=${D}${libdir}/gtk-2.0/2.10.0/loaders ${D}${bindir}/gdk-pixbuf-query-loaders > ${D}${sysconfdir}/gtk-2.0/gdk-pixbuf.loaders + sed -i -e 's#${D}##g' ${D}${sysconfdir}/gtk-2.0/gdk-pixbuf.loaders + find ${D}${libdir} -name "libpixbufloader-*.la" -exec rm \{\} \; +} + diff --git a/meta/recipes-gnome/gtk+/gdk-pixbuf-csource/reduce-dependencies.patch b/meta/recipes-gnome/gtk+/gdk-pixbuf-csource/reduce-dependencies.patch new file mode 100644 index 0000000000..6b030e8f16 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gdk-pixbuf-csource/reduce-dependencies.patch @@ -0,0 +1,221 @@ +# +# strip unnecessary stuff out of configure, we just want +# to build gdk-pixbuf-csource. +# -- Michael 'Mickey' Lauer <mlauer@vanille-media.de> +# +--- +# configure.in | 116 ++--------------------------------------------------------- +# 1 file changed, 5 insertions(+), 111 deletions(-) +# +--- gtk+-2.12.7.orig/configure.in ++++ gtk+-2.12.7/configure.in +@@ -30,13 +30,10 @@ m4_define([gtk_api_version], [2.0]) + #GTK_BINARY_VERSION=$GTK_MAJOR_VERSION.$GTK_MINOR_VERSION.$LT_CURRENT + m4_define([gtk_binary_version], [2.10.0]) + + # required versions of other packages + m4_define([glib_required_version], [2.13.5]) +-m4_define([pango_required_version], [1.17.3]) +-m4_define([atk_required_version], [1.9.0]) +-m4_define([cairo_required_version], [1.2.0]) + + + AC_INIT([gtk+], [gtk_version], + [http://bugzilla.gnome.org/enter_bug.cgi?product=gtk%2B], + [gtk+]) +@@ -347,14 +344,11 @@ ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" + ## Later on we actually use the cflags/libs from separate pkg-config + ## calls. Oh, also the later pkg-config calls don't include + ## the version requirements since those make the module lists + ## annoying to construct + PKG_CHECK_MODULES(BASE_DEPENDENCIES, +- [glib-2.0 >= glib_required_version dnl +- atk >= atk_required_version dnl +- pango >= pango_required_version dnl +- cairo >= cairo_required_version]) ++ [glib-2.0 >= glib_required_version]) + + if test "$os_win32" != yes; then + # libtool option to control which symbols are exported + # right now, symbols starting with _ are not exported + LIBTOOL_EXPORT_OPTIONS='-export-symbols-regex "^[[^_]].*"' +@@ -1059,27 +1053,19 @@ GDK_PIXBUF_DEP_CFLAGS="`$PKG_CONFIG --cf + + GDK_PIXBUF_XLIB_PACKAGES= + GDK_PIXBUF_XLIB_EXTRA_CFLAGS= + GDK_PIXBUF_XLIB_EXTRA_LIBS= + +-X_PACKAGES=fontconfig ++X_PACKAGES= + GDK_EXTRA_LIBS="$GDK_WLIBS" + GDK_EXTRA_CFLAGS= + + # GTK+ uses some X calls, so needs to link against X directly + GTK_DEP_PACKAGES_FOR_X= + GTK_DEP_LIBS_FOR_X= + + if test "x$gdktarget" = "xx11"; then +- # +- # We use fontconfig very peripherally when decoding the default +- # settings. +- # +- if $PKG_CONFIG --exists fontconfig; then : ; else +- AC_MSG_ERROR([ +-*** fontconfig (http://www.fontconfig.org) is required by the X11 backend.]) +- fi + + # + # Check for basic X packages; we use pkg-config if available + # + if $PKG_CONFIG --exists x11 xext xrender; then +@@ -1122,20 +1108,10 @@ if test "x$gdktarget" = "xx11"; then + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + gtk_save_LIBS=$LIBS + LIBS="$x_libs_for_checks $LIBS" + +- # Sanity check for the X11 and Xext libraries. While everything we need from +- # Xext is optional, the chances a system has *none* of these things is so +- # small that we just unconditionally require it. +- AC_CHECK_FUNC(XOpenDisplay, :, +- AC_MSG_ERROR([*** libX11 not found. Check 'config.log' for more details.])) +- AC_CHECK_FUNC(XextFindDisplay, :, +- AC_MSG_ERROR([*** libXext not found. Check 'config.log' for more details.])) +- AC_CHECK_FUNC(XRenderQueryExtension, :, +- AC_MSG_ERROR([*** libXrender not found. Check 'config.log' for more details.])) +- + # Check for xReply + + AC_MSG_CHECKING([if <X11/extensions/XIproto.h> is needed for xReply]) + AC_TRY_COMPILE([#include <X11/Xlibint.h>], + [xReply *rep;], +@@ -1416,104 +1392,33 @@ if test "x$gdktarget" = "xdirectfb"; the + AM_CONDITIONAL(USE_DIRECTFB, true) + else + AM_CONDITIONAL(USE_DIRECTFB, false) + fi + +- +-# Check for Pango flags +- +-if test "x$gdktarget" = "xwin32"; then +- PANGO_PACKAGES="pangowin32 pangocairo" +-else +- PANGO_PACKAGES="pango pangocairo" +-fi +- +-AC_MSG_CHECKING(Pango flags) +-if $PKG_CONFIG --exists $PANGO_PACKAGES ; then +- PANGO_CFLAGS=`$PKG_CONFIG --cflags $PANGO_PACKAGES` +- PANGO_LIBS=`$PKG_CONFIG --libs $PANGO_PACKAGES` +- +- AC_MSG_RESULT($PANGO_CFLAGS $PANGO_LIBS) +-else +- AC_MSG_ERROR([ +-*** Pango not found. Pango built with Cairo support is required +-*** to build GTK+. See http://www.pango.org for Pango information. +-]) +-fi +- +-CFLAGS="$CFLAGS $PANGO_CFLAGS" +- +-if $PKG_CONFIG --uninstalled $PANGO_PACKAGES; then +- : +-else +- gtk_save_LIBS="$LIBS" +- LIBS="$PANGO_LIBS $LIBS" +- AC_TRY_LINK_FUNC(pango_context_new, :, AC_MSG_ERROR([ +-*** Can't link to Pango. Pango is required to build +-*** GTK+. For more information see http://www.pango.org])) +- LIBS="$gtk_save_LIBS" +-fi +- +-CFLAGS="$saved_cflags" +-LDFLAGS="$saved_ldflags" +- +-GDK_PACKAGES="$PANGO_PACKAGES" +-if test "x$gdktarget" = "xx11"; then +- GDK_PACKAGES="$GDK_PACKAGES $X_PACKAGES" +-fi + GDK_DEP_LIBS="$GDK_EXTRA_LIBS `$PKG_CONFIG --libs $GDK_PIXBUF_PACKAGES $GDK_PACKAGES` $GDK_PIXBUF_EXTRA_LIBS" + GDK_DEP_CFLAGS="`$PKG_CONFIG --cflags gthread-2.0 $GDK_PIXBUF_PACKAGES $GDK_PACKAGES` $GDK_PIXBUF_EXTRA_CFLAGS $GDK_EXTRA_CFLAGS" + + # + # If we aren't writing explicit dependencies, then don't put the extra libraries we need + # into the pkg-config files + # + if test $enable_explicit_deps != yes ; then +- GDK_PACKAGES="$PANGO_PACKAGES" ++ GDK_PACKAGES= + GDK_EXTRA_LIBS= + fi + + AC_SUBST(GDK_PACKAGES) + AC_SUBST(GDK_EXTRA_LIBS) + AC_SUBST(GDK_EXTRA_CFLAGS) + AC_SUBST(GDK_DEP_LIBS) + AC_SUBST(GDK_DEP_CFLAGS) + + +-######################################## +-# Check for Accessibility Toolkit flags +-######################################## +- +-ATK_PACKAGES=atk +-AC_MSG_CHECKING(ATK flags) +-if $PKG_CONFIG --exists $ATK_PACKAGES ; then +- ATK_CFLAGS=`$PKG_CONFIG --cflags $ATK_PACKAGES` +- ATK_LIBS=`$PKG_CONFIG --libs $ATK_PACKAGES` +- +- AC_MSG_RESULT($ATK_CFLAGS $ATK_LIBS) +-else +- AC_MSG_ERROR([ +-*** Accessibility Toolkit not found. Accessibility Toolkit is required +-*** to build GTK+. +-]) +-fi +- +-if $PKG_CONFIG --uninstalled $ATK_PACKAGES; then +- : +-else +- gtk_save_LIBS="$LIBS" +- LIBS="$ATK_LIBS $LIBS" +- AC_TRY_LINK_FUNC(atk_object_get_type, : , AC_MSG_ERROR([ +- *** Cannot link to Accessibility Toolkit. Accessibility Toolkit is required +- *** to build GTK+])) +- LIBS="$gtk_save_LIBS" +-fi +- +-GTK_PACKAGES="atk cairo" ++GTK_PACKAGES= + GTK_EXTRA_LIBS= + GTK_EXTRA_CFLAGS= +-GTK_DEP_LIBS="$GDK_EXTRA_LIBS $GTK_DEP_LIBS_FOR_X `$PKG_CONFIG --libs $GDK_PIXBUF_PACKAGES $PANGO_PACKAGES $GTK_PACKAGES_FOR_X $GTK_PACKAGES` $GTK_EXTRA_LIBS $GDK_PIXBUF_EXTRA_LIBS" ++GTK_DEP_LIBS="$GDK_EXTRA_LIBS $GTK_DEP_LIBS_FOR_X `$PKG_CONFIG --libs $GDK_PIXBUF_PACKAGES $GTK_PACKAGES_FOR_X $GTK_PACKAGES` $GTK_EXTRA_LIBS $GDK_PIXBUF_EXTRA_LIBS" + GTK_DEP_CFLAGS="`$PKG_CONFIG --cflags gthread-2.0 $GDK_PIXBUF_PACKAGES $GDK_PACKAGES $GTK_PACKAGES` $GDK_PIXBUF_EXTRA_CFLAGS $GDK_EXTRA_CFLAGS $GTK_EXTRA_CFLAGS" + + if test x"$os_win32" = xyes; then + GTK_EXTRA_CFLAGS="$msnative_struct" + fi +@@ -1567,21 +1472,10 @@ LIBS="$CUPS_LIBS" + AC_CHECK_FUNCS(httpGetAuthString) + LIBS="$gtk_save_libs" + + gtk_save_cppflags="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $GTK_DEP_CFLAGS" +- +-AC_CHECK_HEADER(cairo-pdf.h,,AC_MSG_ERROR([ +-*** Can't find cairo-pdf.h. You must build Cairo with the pdf +-*** backend enabled.])) +- +-if test "$os_win32" != "yes"; then +- AC_CHECK_HEADER(cairo-ps.h,,AC_MSG_ERROR([ +-*** Can't find cairo-ps.h. You must build Cairo with the +-*** postscript backend enabled.])) +-fi +- + CPPFLAGS="$gtk_save_cppflags" + + + AC_ARG_ENABLE(test-print-backend, + [AC_HELP_STRING([--enable-test-print-backend], diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/cellrenderer-cairo.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/cellrenderer-cairo.patch new file mode 100644 index 0000000000..4439e69fb6 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/cellrenderer-cairo.patch @@ -0,0 +1,32 @@ +Index: gtk/gtkcellrenderer.c +=================================================================== +RCS file: /cvs/gnome/gtk+/gtk/gtkcellrenderer.c,v +retrieving revision 1.55 +diff -u -r1.55 gtkcellrenderer.c +--- gtk/gtkcellrenderer.c 14 May 2006 04:25:28 -0000 1.55 ++++ gtk/gtkcellrenderer.c 30 Jun 2006 10:57:43 -0000 +@@ -551,6 +551,7 @@ + + if (cell->cell_background_set && !selected) + { ++#ifdef USE_CAIRO_INTERNALLY + cairo_t *cr = gdk_cairo_create (window); + + gdk_cairo_rectangle (cr, background_area); +@@ -558,6 +559,16 @@ + cairo_fill (cr); + + cairo_destroy (cr); ++#else ++ GdkGC *gc; ++ ++ gc = gdk_gc_new (window); ++ gdk_gc_set_rgb_fg_color (gc, &priv->cell_background); ++ gdk_draw_rectangle (window, gc, TRUE, ++ background_area->x, background_area->y, ++ background_area->width, background_area->height); ++ g_object_unref (gc); ++#endif + } + + GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell, diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/combo-arrow-size.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/combo-arrow-size.patch new file mode 100644 index 0000000000..d44c454ce3 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/combo-arrow-size.patch @@ -0,0 +1,67 @@ +Index: gtk/gtkcombobox.c +=================================================================== +RCS file: /cvs/gnome/gtk+/gtk/gtkcombobox.c,v +retrieving revision 1.185 +diff -u -p -r1.185 gtkcombobox.c +--- gtk/gtkcombobox.c 12 Oct 2006 13:48:07 -0000 1.185 ++++ gtk/gtkcombobox.c 1 Nov 2006 19:01:09 -0000 +@@ -756,6 +756,25 @@ gtk_combo_box_class_init (GtkComboBoxCla + FALSE, + GTK_PARAM_READABLE)); + ++ /** ++ * GtkComboBox:arrow-size: ++ * ++ * Sets the minimum size of the arrow in the combo box. Note ++ * that the arrow size is coupled to the font size, so in case ++ * a larger font is used, the arrow will be larger than set ++ * by arrow size. ++ * ++ * Since: 2.12 ++ */ ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_int ("arrow-size", ++ P_("Arrow Size"), ++ P_("The minimum size of the arrow in the combo box"), ++ 0, ++ G_MAXINT, ++ 15, ++ GTK_PARAM_READABLE)); ++ + g_type_class_add_private (object_class, sizeof (GtkComboBoxPrivate)); + } + +@@ -1897,7 +1916,12 @@ gtk_combo_box_size_request (GtkWidget + { + gint width, height; + gint focus_width, focus_pad; ++ gint font_size; ++ gint arrow_size; + GtkRequisition bin_req; ++ PangoContext *context; ++ PangoFontMetrics *metrics; ++ PangoFontDescription *font_desc; + + GtkComboBox *combo_box = GTK_COMBO_BOX (widget); + +@@ -1910,7 +1934,20 @@ gtk_combo_box_size_request (GtkWidget + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, ++ "arrow-size", &arrow_size, + NULL); ++ ++ font_desc = GTK_BIN (widget)->child->style->font_desc; ++ context = gtk_widget_get_pango_context (widget); ++ metrics = pango_context_get_metrics (context, font_desc, ++ pango_context_get_language (context)); ++ font_size = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + ++ pango_font_metrics_get_descent (metrics)); ++ pango_font_metrics_unref (metrics); ++ ++ arrow_size = MAX (arrow_size, font_size); ++ ++ gtk_widget_set_size_request (combo_box->priv->arrow, arrow_size, arrow_size); + + if (!combo_box->priv->tree_view) + { diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/disable-print.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/disable-print.patch new file mode 100644 index 0000000000..13cbd91d77 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/disable-print.patch @@ -0,0 +1,26 @@ +--- gtk+-2.12.0/configure.in~ 2006-07-05 18:11:44.000000000 +0200 ++++ gtk+-2.12.0/configure.in 2006-07-05 18:11:44.000000000 +0200 +@@ -1554,22 +1554 @@ +-AC_PATH_PROG(CUPS_CONFIG, cups-config, no) +-if test "x$CUPS_CONFIG" != "xno"; then +- CUPS_CFLAGS=`$CUPS_CONFIG --cflags | sed 's/-O[0-9]*//' | sed 's/-m[^\t]*//g'` +- CUPS_LIBS=`$CUPS_CONFIG --libs` +- +- CUPS_API_VERSION=`$CUPS_CONFIG --api-version` +- CUPS_API_MAJOR=`echo $ECHO_N $CUPS_API_VERSION | awk -F. '{print $1}'` +- CUPS_API_MINOR=`echo $ECHO_N $CUPS_API_VERSION | awk -F. '{print $2}'` +- +- if test $CUPS_API_MAJOR -gt 1 -o \ +- $CUPS_API_MAJOR -eq 1 -a $CUPS_API_MINOR -ge 2; then +- AC_DEFINE(HAVE_CUPS_API_1_2) +- fi +- +- AC_SUBST(CUPS_API_MAJOR) +- AC_SUBST(CUPS_API_MINOR) +- AC_SUBST(CUPS_CFLAGS) +- AC_SUBST(CUPS_LIBS) +- +- AC_CHECK_HEADER(cups/cups.h,,AC_MSG_ERROR([[*** Sorry, cups-config present but cups/cups.h missing.]])) +-fi +-AM_CONDITIONAL(HAVE_CUPS, test "x$CUPS_CONFIG" != "xno") ++AM_CONDITIONAL(HAVE_CUPS, false) diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/entry-cairo.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/entry-cairo.patch new file mode 100644 index 0000000000..3313e7f132 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/entry-cairo.patch @@ -0,0 +1,103 @@ +Index: gtk/gtkentry.c +=================================================================== +RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v +retrieving revision 1.317 +diff -u -r1.317 gtkentry.c +--- gtk/gtkentry.c 29 Jun 2006 09:18:05 -0000 1.317 ++++ gtk/gtkentry.c 2 Jul 2006 14:14:24 -0000 +@@ -3337,7 +3337,9 @@ + if (GTK_WIDGET_DRAWABLE (entry)) + { + PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); ++#ifdef USE_CAIRO_INTERNALLY + cairo_t *cr; ++#endif + gint x, y; + gint start_pos, end_pos; + +@@ -3345,23 +3347,35 @@ + + get_layout_position (entry, &x, &y); + ++#ifdef USE_CAIRO_INTERNALLY + cr = gdk_cairo_create (entry->text_area); + + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); + pango_cairo_show_layout (cr, layout); ++#else ++ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], ++ x, y, ++ layout); ++#endif + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) + { + gint *ranges; + gint n_ranges, i; + PangoRectangle logical_rect; +- GdkColor *selection_color, *text_color; + GtkBorder inner_border; ++#ifdef USE_CAIRO_INTERNALLY ++ GdkColor *selection_color, *text_color; ++#else ++ GdkGC *selection_gc, *text_gc; ++ GdkRegion *clip_region; ++#endif + + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); + ++#ifdef USE_CAIRO_INTERNALLY + if (GTK_WIDGET_HAS_FOCUS (entry)) + { + selection_color = &widget->style->base [GTK_STATE_SELECTED]; +@@ -3390,11 +3404,46 @@ + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, text_color); + pango_cairo_show_layout (cr, layout); +- ++#else ++ if (GTK_WIDGET_HAS_FOCUS (entry)) ++ { ++ selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; ++ text_gc = widget->style->text_gc [GTK_STATE_SELECTED]; ++ } ++ else ++ { ++ selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; ++ text_gc = widget->style->text_gc [GTK_STATE_ACTIVE]; ++ } ++ ++ clip_region = gdk_region_new (); ++ for (i = 0; i < n_ranges; ++i) ++ { ++ GdkRectangle rect; ++ ++ rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i]; ++ rect.y = y; ++ rect.width = ranges[2 * i + 1]; ++ rect.height = logical_rect.height; ++ ++ gdk_draw_rectangle (entry->text_area, selection_gc, TRUE, ++ rect.x, rect.y, rect.width, rect.height); ++ ++ gdk_region_union_with_rect (clip_region, &rect); ++ } ++ ++ gdk_gc_set_clip_region (text_gc, clip_region); ++ gdk_draw_layout (entry->text_area, text_gc, ++ x, y, ++ layout); ++ gdk_gc_set_clip_region (text_gc, NULL); ++ gdk_region_destroy (clip_region); ++#endif + g_free (ranges); + } +- ++#ifdef USE_CAIRO_INTERNALLY + cairo_destroy (cr); ++#endif + } + } + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-default.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-default.patch new file mode 100644 index 0000000000..146316c9c1 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-default.patch @@ -0,0 +1,9521 @@ +Index: gtk+-2.12.5/gtk/gtkfilechooserdefault.c +================ =================================================== +--- gtk+-2.12.5/gtk/gtkfilechooserdefault.c (revision 19337) ++++ gtk+-2.12.5/gtk/gtkfilechooserdefault.c (working copy) +@@ -27,12 +27,12 @@ + #include "gtkcelllayout.h" + #include "gtkcellrendererpixbuf.h" + #include "gtkcellrenderertext.h" ++#include "gtkcellrenderertext.h" + #include "gtkcheckmenuitem.h" + #include "gtkclipboard.h" + #include "gtkcombobox.h" + #include "gtkentry.h" + #include "gtkeventbox.h" +-#include "gtkexpander.h" + #include "gtkfilechooserprivate.h" + #include "gtkfilechooserdefault.h" + #include "gtkfilechooserembed.h" +@@ -53,17 +53,13 @@ + #include "gtkmarshalers.h" + #include "gtkmenuitem.h" + #include "gtkmessagedialog.h" +-#include "gtkpathbar.h" + #include "gtkprivate.h" + #include "gtkradiobutton.h" +-#include "gtkrecentfilter.h" +-#include "gtkrecentmanager.h" + #include "gtkscrolledwindow.h" + #include "gtkseparatormenuitem.h" + #include "gtksizegroup.h" + #include "gtkstock.h" + #include "gtktable.h" +-#include "gtktooltip.h" + #include "gtktreednd.h" + #include "gtktreeprivate.h" + #include "gtktreeselection.h" +@@ -81,8 +77,6 @@ + #include <errno.h> + #include <string.h> + #include <time.h> +-#include <sys/stat.h> +-#include <sys/types.h> + + + #ifdef HAVE_UNISTD_H +@@ -92,6 +86,8 @@ + #include <io.h> + #endif + ++#define DEFAULT_SPACING 5 ++ + /* Profiling stuff */ + #undef PROFILE_FILE_CHOOSER + #ifdef PROFILE_FILE_CHOOSER +@@ -150,6 +145,7 @@ + #define GTK_FILE_CHOOSER_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass)) + + #define MAX_LOADING_TIME 500 ++#define LONG_CLICK_LENGTH 500 + + struct _GtkFileChooserDefaultClass + { +@@ -163,38 +159,12 @@ + UP_FOLDER, + DOWN_FOLDER, + HOME_FOLDER, +- DESKTOP_FOLDER, +- QUICK_BOOKMARK, +- LOCATION_TOGGLE_POPUP, + SHOW_HIDDEN, +- SEARCH_SHORTCUT, +- RECENT_SHORTCUT, +- + LAST_SIGNAL + }; + + static guint signals[LAST_SIGNAL] = { 0 }; + +-/* Column numbers for the shortcuts tree. Keep these in sync with shortcuts_model_create() */ +-enum { +- SHORTCUTS_COL_PIXBUF, +- SHORTCUTS_COL_NAME, +- SHORTCUTS_COL_DATA, +- SHORTCUTS_COL_TYPE, +- SHORTCUTS_COL_REMOVABLE, +- SHORTCUTS_COL_PIXBUF_VISIBLE, +- SHORTCUTS_COL_HANDLE, +- SHORTCUTS_COL_NUM_COLUMNS +-}; +- +-typedef enum { +- SHORTCUT_TYPE_PATH, +- SHORTCUT_TYPE_VOLUME, +- SHORTCUT_TYPE_SEPARATOR, +- SHORTCUT_TYPE_SEARCH, +- SHORTCUT_TYPE_RECENT +-} ShortcutType; +- + /* Column numbers for the file list */ + enum { + FILE_LIST_COL_NAME, +@@ -203,100 +173,10 @@ + FILE_LIST_COL_NUM_COLUMNS + }; + +-/* Column numbers for the search model. +- * Keep this in sync with search_setup_model() +- */ +-enum { +- SEARCH_MODEL_COL_PATH, +- SEARCH_MODEL_COL_DISPLAY_NAME, +- SEARCH_MODEL_COL_COLLATION_KEY, +- SEARCH_MODEL_COL_STAT, +- SEARCH_MODEL_COL_HANDLE, +- SEARCH_MODEL_COL_PIXBUF, +- SEARCH_MODEL_COL_MIME_TYPE, +- SEARCH_MODEL_COL_IS_FOLDER, +- SEARCH_MODEL_COL_NUM_COLUMNS +-}; +- +-enum { +- RECENT_MODEL_COL_PATH, +- RECENT_MODEL_COL_DISPLAY_NAME, +- RECENT_MODEL_COL_INFO, +- RECENT_MODEL_COL_IS_FOLDER, +- RECENT_MODEL_COL_HANDLE, +- RECENT_MODEL_COL_NUM_COLUMNS +-}; +- +-/* Identifiers for target types */ +-enum { +- GTK_TREE_MODEL_ROW, +- TEXT_URI_LIST +-}; +- +-/* Target types for dragging from the shortcuts list */ +-static const GtkTargetEntry shortcuts_source_targets[] = { +- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW } +-}; +- +-static const int num_shortcuts_source_targets = G_N_ELEMENTS (shortcuts_source_targets); +- +-/* Target types for dropping into the shortcuts list */ +-static const GtkTargetEntry shortcuts_dest_targets[] = { +- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }, +- { "text/uri-list", 0, TEXT_URI_LIST } +-}; +- +-static const int num_shortcuts_dest_targets = G_N_ELEMENTS (shortcuts_dest_targets); +- +-/* Target types for DnD from the file list */ +-static const GtkTargetEntry file_list_source_targets[] = { +- { "text/uri-list", 0, TEXT_URI_LIST } +-}; +- +-static const int num_file_list_source_targets = G_N_ELEMENTS (file_list_source_targets); +- +-/* Target types for dropping into the file list */ +-static const GtkTargetEntry file_list_dest_targets[] = { +- { "text/uri-list", 0, TEXT_URI_LIST } +-}; +- +-static const int num_file_list_dest_targets = G_N_ELEMENTS (file_list_dest_targets); +- +-/* Target types for dragging from the recent files list */ +-static const GtkTargetEntry recent_list_source_targets[] = { +- { "text/uri-list", 0, TEXT_URI_LIST } +-}; +- +-static const int num_recent_list_source_targets = G_N_ELEMENTS (recent_list_source_targets); +- +-static gboolean +-search_is_possible (GtkFileChooserDefault *impl) +-{ +- if (impl->search_engine == NULL) +- impl->search_engine = _gtk_search_engine_new (); +- +- return impl->search_engine != NULL; +-} +- +-/* Interesting places in the shortcuts bar */ +-typedef enum { +- SHORTCUTS_SEARCH, +- SHORTCUTS_RECENT, +- SHORTCUTS_RECENT_SEPARATOR, +- SHORTCUTS_HOME, +- SHORTCUTS_DESKTOP, +- SHORTCUTS_VOLUMES, +- SHORTCUTS_SHORTCUTS, +- SHORTCUTS_BOOKMARKS_SEPARATOR, +- SHORTCUTS_BOOKMARKS, +- SHORTCUTS_CURRENT_FOLDER_SEPARATOR, +- SHORTCUTS_CURRENT_FOLDER +-} ShortcutsIndex; +- + /* Icon size for if we can't get it from the theme */ +-#define FALLBACK_ICON_SIZE 16 ++#define FALLBACK_ICON_SIZE 24 + +-#define PREVIEW_HBOX_SPACING 12 ++#define LIST_HBOX_SPACING DEFAULT_SPACING + #define NUM_LINES 45 + #define NUM_CHARS 60 + +@@ -369,52 +248,17 @@ + static gboolean gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed); + static void gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed); + +-static void location_popup_handler (GtkFileChooserDefault *impl, +- const gchar *path); +-static void location_popup_on_paste_handler (GtkFileChooserDefault *impl); +-static void location_toggle_popup_handler (GtkFileChooserDefault *impl); +-static void up_folder_handler (GtkFileChooserDefault *impl); +-static void down_folder_handler (GtkFileChooserDefault *impl); +-static void home_folder_handler (GtkFileChooserDefault *impl); +-static void desktop_folder_handler (GtkFileChooserDefault *impl); +-static void quick_bookmark_handler (GtkFileChooserDefault *impl, +- gint bookmark_index); +-static void show_hidden_handler (GtkFileChooserDefault *impl); +-static void search_shortcut_handler (GtkFileChooserDefault *impl); +-static void recent_shortcut_handler (GtkFileChooserDefault *impl); +-static void update_appearance (GtkFileChooserDefault *impl); ++static void up_folder_handler (GtkFileChooserDefault *impl); ++static void down_folder_handler (GtkFileChooserDefault *impl); ++static void home_folder_handler (GtkFileChooserDefault *impl); ++static void show_hidden_handler (GtkFileChooserDefault *impl); ++static void update_appearance (GtkFileChooserDefault *impl); + +-static void set_current_filter (GtkFileChooserDefault *impl, +- GtkFileFilter *filter); +-static void check_preview_change (GtkFileChooserDefault *impl); +- + static void filter_combo_changed (GtkComboBox *combo_box, + GtkFileChooserDefault *impl); +-static void shortcuts_row_activated_cb (GtkTreeView *tree_view, +- GtkTreePath *path, +- GtkTreeViewColumn *column, +- GtkFileChooserDefault *impl); + +-static gboolean shortcuts_key_press_event_cb (GtkWidget *widget, +- GdkEventKey *event, +- GtkFileChooserDefault *impl); +- +-static gboolean shortcuts_select_func (GtkTreeSelection *selection, +- GtkTreeModel *model, +- GtkTreePath *path, +- gboolean path_currently_selected, +- gpointer data); +-static gboolean shortcuts_get_selected (GtkFileChooserDefault *impl, +- GtkTreeIter *iter); +-static void shortcuts_activate_iter (GtkFileChooserDefault *impl, +- GtkTreeIter *iter); +-static int shortcuts_get_index (GtkFileChooserDefault *impl, +- ShortcutsIndex where); +-static int shortcut_find_position (GtkFileChooserDefault *impl, +- const GtkFilePath *path); +- +-static void bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl); +- ++static void set_current_filter (GtkFileChooserDefault *impl, ++ GtkFileFilter *filter); + static gboolean list_select_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, +@@ -433,19 +277,6 @@ + GtkTreeIter *iter, + gpointer user_data); + +-static void path_bar_clicked (GtkPathBar *path_bar, +- GtkFilePath *file_path, +- GtkFilePath *child_path, +- gboolean child_is_hidden, +- GtkFileChooserDefault *impl); +- +-static void add_bookmark_button_clicked_cb (GtkButton *button, +- GtkFileChooserDefault *impl); +-static void remove_bookmark_button_clicked_cb (GtkButton *button, +- GtkFileChooserDefault *impl); +-static void save_folder_combo_changed_cb (GtkComboBox *combo, +- GtkFileChooserDefault *impl); +- + static void list_icon_data_func (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, +@@ -477,115 +308,8 @@ + + static void location_button_toggled_cb (GtkToggleButton *toggle, + GtkFileChooserDefault *impl); +-static void location_switch_to_path_bar (GtkFileChooserDefault *impl); ++static void settings_load (GtkFileChooserDefault *impl); + +-static void search_stop_searching (GtkFileChooserDefault *impl, +- gboolean remove_query); +-static void search_clear_model (GtkFileChooserDefault *impl, +- gboolean remove_from_treeview); +-static gboolean search_should_respond (GtkFileChooserDefault *impl); +-static void search_switch_to_browse_mode (GtkFileChooserDefault *impl); +-static GSList *search_get_selected_paths (GtkFileChooserDefault *impl); +-static void search_entry_activate_cb (GtkEntry *entry, +- gpointer data); +-static void settings_load (GtkFileChooserDefault *impl); +-static void search_get_valid_child_iter (GtkFileChooserDefault *impl, +- GtkTreeIter *child_iter, +- GtkTreeIter *iter); +- +-static void recent_manager_update (GtkFileChooserDefault *impl); +-static void recent_stop_loading (GtkFileChooserDefault *impl); +-static void recent_clear_model (GtkFileChooserDefault *impl, +- gboolean remove_from_treeview); +-static gboolean recent_should_respond (GtkFileChooserDefault *impl); +-static void recent_switch_to_browse_mode (GtkFileChooserDefault *impl); +-static GSList * recent_get_selected_paths (GtkFileChooserDefault *impl); +-static void recent_get_valid_child_iter (GtkFileChooserDefault *impl, +- GtkTreeIter *child_iter, +- GtkTreeIter *iter); +- +- +- +- +-/* Drag and drop interface declarations */ +- +-typedef struct { +- GtkTreeModelFilter parent; +- +- GtkFileChooserDefault *impl; +-} ShortcutsPaneModelFilter; +- +-typedef struct { +- GtkTreeModelFilterClass parent_class; +-} ShortcutsPaneModelFilterClass; +- +-#define SHORTCUTS_PANE_MODEL_FILTER_TYPE (_shortcuts_pane_model_filter_get_type ()) +-#define SHORTCUTS_PANE_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHORTCUTS_PANE_MODEL_FILTER_TYPE, ShortcutsPaneModelFilter)) +- +-static void shortcuts_pane_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface); +- +-G_DEFINE_TYPE_WITH_CODE (ShortcutsPaneModelFilter, +- _shortcuts_pane_model_filter, +- GTK_TYPE_TREE_MODEL_FILTER, +- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE, +- shortcuts_pane_model_filter_drag_source_iface_init)) +- +-static GtkTreeModel *shortcuts_pane_model_filter_new (GtkFileChooserDefault *impl, +- GtkTreeModel *child_model, +- GtkTreePath *root); +- +- +-typedef struct { +- GtkTreeModelSort parent; +- +- GtkFileChooserDefault *impl; +-} RecentModelSort; +- +-typedef struct { +- GtkTreeModelSortClass parent_class; +-} RecentModelSortClass; +- +-#define RECENT_MODEL_SORT_TYPE (_recent_model_sort_get_type ()) +-#define RECENT_MODEL_SORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RECENT_MODEL_SORT_TYPE, RecentModelSort)) +- +-static void recent_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface); +- +-G_DEFINE_TYPE_WITH_CODE (RecentModelSort, +- _recent_model_sort, +- GTK_TYPE_TREE_MODEL_SORT, +- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE, +- recent_model_sort_drag_source_iface_init)); +- +-static GtkTreeModel *recent_model_sort_new (GtkFileChooserDefault *impl, +- GtkTreeModel *child_model); +- +- +-typedef struct { +- GtkTreeModelSort parent; +- +- GtkFileChooserDefault *impl; +-} SearchModelSort; +- +-typedef struct { +- GtkTreeModelSortClass parent_class; +-} SearchModelSortClass; +- +-#define SEARCH_MODEL_SORT_TYPE (_search_model_sort_get_type ()) +-#define SEARCH_MODEL_SORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEARCH_MODEL_SORT_TYPE, SearchModelSort)) +- +-static void search_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface); +- +-G_DEFINE_TYPE_WITH_CODE (SearchModelSort, +- _search_model_sort, +- GTK_TYPE_TREE_MODEL_SORT, +- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE, +- search_model_sort_drag_source_iface_init)); +- +-static GtkTreeModel *search_model_sort_new (GtkFileChooserDefault *impl, +- GtkTreeModel *child_model); +- +- +- + G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_TYPE_VBOX, + G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER, + gtk_file_chooser_default_iface_init) +@@ -595,13 +319,9 @@ + static void + _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class) + { +- static const guint quick_bookmark_keyvals[10] = { +- GDK_1, GDK_2, GDK_3, GDK_4, GDK_5, GDK_6, GDK_7, GDK_8, GDK_9, GDK_0 +- }; + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + GtkBindingSet *binding_set; +- int i; + + gobject_class->finalize = gtk_file_chooser_default_finalize; + gobject_class->constructor = gtk_file_chooser_default_constructor; +@@ -621,7 +341,7 @@ + _gtk_binding_signal_new (I_("location-popup"), + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, +- G_CALLBACK (location_popup_handler), ++ NULL, + NULL, NULL, + _gtk_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +@@ -629,18 +349,10 @@ + _gtk_binding_signal_new ("location-popup-on-paste", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, +- G_CALLBACK (location_popup_on_paste_handler), ++ NULL, + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); +- signals[LOCATION_TOGGLE_POPUP] = +- _gtk_binding_signal_new (I_("location-toggle-popup"), +- G_OBJECT_CLASS_TYPE (class), +- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, +- G_CALLBACK (location_toggle_popup_handler), +- NULL, NULL, +- _gtk_marshal_VOID__VOID, +- G_TYPE_NONE, 0); + signals[UP_FOLDER] = + _gtk_binding_signal_new (I_("up-folder"), + G_OBJECT_CLASS_TYPE (class), +@@ -665,22 +377,6 @@ + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); +- signals[DESKTOP_FOLDER] = +- _gtk_binding_signal_new (I_("desktop-folder"), +- G_OBJECT_CLASS_TYPE (class), +- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, +- G_CALLBACK (desktop_folder_handler), +- NULL, NULL, +- _gtk_marshal_VOID__VOID, +- G_TYPE_NONE, 0); +- signals[QUICK_BOOKMARK] = +- _gtk_binding_signal_new (I_("quick-bookmark"), +- G_OBJECT_CLASS_TYPE (class), +- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, +- G_CALLBACK (quick_bookmark_handler), +- NULL, NULL, +- _gtk_marshal_VOID__INT, +- G_TYPE_NONE, 1, G_TYPE_INT); + signals[SHOW_HIDDEN] = + _gtk_binding_signal_new ("show-hidden", + G_OBJECT_CLASS_TYPE (class), +@@ -689,22 +385,6 @@ + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); +- signals[SEARCH_SHORTCUT] = +- _gtk_binding_signal_new ("search-shortcut", +- G_OBJECT_CLASS_TYPE (class), +- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, +- G_CALLBACK (search_shortcut_handler), +- NULL, NULL, +- _gtk_marshal_VOID__VOID, +- G_TYPE_NONE, 0); +- signals[RECENT_SHORTCUT] = +- _gtk_binding_signal_new ("recent-shortcut", +- G_OBJECT_CLASS_TYPE (class), +- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, +- G_CALLBACK (recent_shortcut_handler), +- NULL, NULL, +- _gtk_marshal_VOID__VOID, +- G_TYPE_NONE, 0); + + binding_set = gtk_binding_set_by_class (class); + +@@ -764,29 +444,11 @@ + "home-folder", + 0); + gtk_binding_entry_add_signal (binding_set, +- GDK_d, GDK_MOD1_MASK, +- "desktop-folder", +- 0); +- gtk_binding_entry_add_signal (binding_set, + GDK_h, GDK_CONTROL_MASK, + "show-hidden", + 0); +- gtk_binding_entry_add_signal (binding_set, +- GDK_s, GDK_MOD1_MASK, +- "search-shortcut", +- 0); +- gtk_binding_entry_add_signal (binding_set, +- GDK_r, GDK_MOD1_MASK, +- "recent-shortcut", +- 0); + +- for (i = 0; i < 10; i++) +- gtk_binding_entry_add_signal (binding_set, +- quick_bookmark_keyvals[i], GDK_MOD1_MASK, +- "quick-bookmark", +- 1, G_TYPE_INT, i); +- + _gtk_file_chooser_install_properties (gobject_class); + } + + static void +@@ -797,7 +465,6 @@ + iface->select_all = gtk_file_chooser_default_select_all; + iface->unselect_all = gtk_file_chooser_default_unselect_all; + iface->get_paths = gtk_file_chooser_default_get_paths; +- iface->get_preview_path = gtk_file_chooser_default_get_preview_path; + iface->get_file_system = gtk_file_chooser_default_get_file_system; + iface->set_current_folder = gtk_file_chooser_default_set_current_folder; + iface->get_current_folder = gtk_file_chooser_default_get_current_folder; +@@ -805,9 +472,12 @@ + iface->add_filter = gtk_file_chooser_default_add_filter; + iface->remove_filter = gtk_file_chooser_default_remove_filter; + iface->list_filters = gtk_file_chooser_default_list_filters; ++ ++ /* these are only stubs */ ++ iface->get_preview_path = gtk_file_chooser_default_get_preview_path; + iface->add_shortcut_folder = gtk_file_chooser_default_add_shortcut_folder; + iface->remove_shortcut_folder = gtk_file_chooser_default_remove_shortcut_folder; +- iface->list_shortcut_folders = gtk_file_chooser_default_list_shortcut_folders; ++ + } + + static void +@@ -827,87 +497,29 @@ + access ("MARK: *** CREATE FILE CHOOSER", F_OK); + #endif + impl->local_only = TRUE; +- impl->preview_widget_active = TRUE; +- impl->use_preview_label = TRUE; + impl->select_multiple = FALSE; + impl->show_hidden = FALSE; ++ impl->show_create_folder = TRUE; + impl->icon_size = FALLBACK_ICON_SIZE; + impl->load_state = LOAD_EMPTY; + impl->reload_state = RELOAD_EMPTY; + impl->pending_select_paths = NULL; +- impl->location_mode = LOCATION_MODE_PATH_BAR; +- impl->operation_mode = OPERATION_MODE_BROWSE; ++ impl->location_mode = LOCATION_MODE_FILENAME_ENTRY; ++ impl->path_history = NULL; + +- gtk_box_set_spacing (GTK_BOX (impl), 12); ++ gtk_box_set_spacing (GTK_BOX (impl), DEFAULT_SPACING); + + impl->tooltips = gtk_tooltips_new (); + g_object_ref_sink (impl->tooltips); + ++ if (!impl->root_folder) ++ impl->root_folder = g_strdup ("/"); ++ + profile_end ("end", NULL); + } + +-/* Frees the data columns for the specified iter in the shortcuts model*/ +-static void +-shortcuts_free_row_data (GtkFileChooserDefault *impl, +- GtkTreeIter *iter) +-{ +- gpointer col_data; +- ShortcutType shortcut_type; +- GtkFileSystemHandle *handle; + +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- SHORTCUTS_COL_HANDLE, &handle, +- -1); +- +- if (handle) +- gtk_file_system_cancel_operation (handle); +- +- if (!(shortcut_type == SHORTCUT_TYPE_PATH || +- shortcut_type == SHORTCUT_TYPE_VOLUME) || +- !col_data) +- return; +- +- if (shortcut_type == SHORTCUT_TYPE_VOLUME) +- { +- GtkFileSystemVolume *volume; +- +- volume = col_data; +- gtk_file_system_volume_free (impl->file_system, volume); +- } +- else +- { +- GtkFilePath *path; +- +- g_assert (shortcut_type == SHORTCUT_TYPE_PATH); +- +- path = col_data; +- gtk_file_path_free (path); +- } +-} +- +-/* Frees all the data columns in the shortcuts model */ + static void +-shortcuts_free (GtkFileChooserDefault *impl) +-{ +- GtkTreeIter iter; +- +- if (!impl->shortcuts_model) +- return; +- +- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter)) +- do +- { +- shortcuts_free_row_data (impl, &iter); +- } +- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter)); +- +- g_object_unref (impl->shortcuts_model); +- impl->shortcuts_model = NULL; +-} +- +-static void + pending_select_paths_free (GtkFileChooserDefault *impl) + { + GSList *l; +@@ -964,19 +576,28 @@ + } + + static void +-gtk_file_chooser_default_finalize (GObject *object) ++path_history_free (GtkFileChooserDefault *impl) + { +- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object); + GSList *l; + +- if (impl->shortcuts_pane_filter_model) +- g_object_unref (impl->shortcuts_pane_filter_model); ++ for (l = impl->path_history; l; l = l->next) ++ { ++ GtkFilePath *path; + +- if (impl->shortcuts_combo_filter_model) +- g_object_unref (impl->shortcuts_combo_filter_model); ++ path = l->data; ++ gtk_file_path_free (path); ++ } + +- shortcuts_free (impl); ++ g_slist_free (impl->path_history); ++ impl->path_history = NULL; ++} + ++static void ++gtk_file_chooser_default_finalize (GObject *object) ++{ ++ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object); ++ GSList *l; ++ + g_object_unref (impl->file_system); + + g_free (impl->browse_files_last_selected_name); +@@ -999,8 +620,7 @@ + if (impl->current_folder) + gtk_file_path_free (impl->current_folder); + +- if (impl->preview_path) +- gtk_file_path_free (impl->preview_path); ++ path_history_free (impl); + + load_remove_timer (impl); + +@@ -1011,15 +631,18 @@ + if (impl->sort_model) + g_object_unref (impl->sort_model); + +- search_clear_model (impl, FALSE); +- recent_clear_model (impl, FALSE); ++ if (impl->list_press_path) ++ { ++ gtk_tree_path_free (impl->list_press_path); ++ impl->list_press_path = NULL; ++ } + +- g_free (impl->preview_display_name); +- + g_free (impl->edited_new_text); + + g_object_unref (impl->tooltips); + ++ g_free (impl->root_folder); ++ + G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->finalize (object); + } + +@@ -1104,28 +727,6 @@ + path, error); + } + +-/* Shows an error dialog about not being able to add a bookmark */ +-static void +-error_adding_bookmark_dialog (GtkFileChooserDefault *impl, +- const GtkFilePath *path, +- GError *error) +-{ +- error_dialog (impl, +- _("Could not add a bookmark"), +- path, error); +-} +- +-/* Shows an error dialog about not being able to remove a bookmark */ +-static void +-error_removing_bookmark_dialog (GtkFileChooserDefault *impl, +- const GtkFilePath *path, +- GError *error) +-{ +- error_dialog (impl, +- _("Could not remove bookmark"), +- path, error); +-} +- + /* Shows an error dialog about not being able to create a folder */ + static void + error_creating_folder_dialog (GtkFileChooserDefault *impl, +@@ -1146,9 +747,9 @@ + GError *error) + { + error_dialog (impl, +- _("The folder could not be created, as a file with the same " +- "name already exists. Try using a different name for the " +- "folder, or rename the file first."), ++ _("The folder could not be created, as a file with the same name " ++ "already exists. Try using a different name for the folder, " ++ "or rename the file first."), + path, error); + } + +@@ -1175,514 +776,108 @@ + + /* Changes folders, displaying an error dialog if this fails */ + static gboolean +-change_folder_and_display_error (GtkFileChooserDefault *impl, +- const GtkFilePath *path, +- gboolean clear_entry) ++change_folder (GtkFileChooserDefault *impl, const GtkFilePath *path, ++ gboolean errormsg) + { + GError *error; + gboolean result; + GtkFilePath *path_copy; ++ gchar * file_name; + + g_return_val_if_fail (path != NULL, FALSE); + +- profile_start ("start", (char *) path); +- +- /* We copy the path because of this case: +- * +- * list_row_activated() +- * fetches path from model; path belongs to the model (*) +- * calls change_folder_and_display_error() +- * calls _gtk_file_chooser_set_current_folder_path() +- * changing folders fails, sets model to NULL, thus freeing the path in (*) +- */ +- + path_copy = gtk_file_path_copy (path); ++ file_name = gtk_file_system_path_to_filename (impl->file_system, path_copy); + +- error = NULL; +- result = gtk_file_chooser_default_update_current_folder (GTK_FILE_CHOOSER (impl), path_copy, TRUE, clear_entry, &error); ++ if (!file_name) ++ { ++ gtk_file_path_free (path_copy); ++ return 0; ++ } + +- if (!result) +- error_changing_folder_dialog (impl, path_copy, error); ++ if (impl->root_folder && file_name[0] == '/' && file_name[1] == 0) ++ { ++ /* If changing to / and we have root_folder, change into it instead */ ++ gtk_file_path_free (path_copy); ++ path_copy = gtk_file_system_filename_to_path (impl->file_system, ++ impl->root_folder); + +- gtk_file_path_free (path_copy); ++ gtk_widget_set_sensitive (impl->up_button, FALSE); ++ } ++ else if (impl->root_folder && ++ strcmp (file_name, impl->root_folder) && ++ !strncmp (file_name, impl->root_folder, strlen (file_name))) ++ { ++ /* refuse to change below the root */ ++ gtk_file_path_free (path_copy); ++ g_free (file_name); ++ return 0; ++ } ++ else if (!strcmp (file_name, impl->root_folder)) ++ { ++ gtk_widget_set_sensitive (impl->up_button, FALSE); ++ } ++ else if (impl->current_folder && !strcmp (file_name, "/media")) ++ { ++ /* Asked to changed into /media -- if we are already in a media ++ * child folder, we refuse, but if we are in the root, we permit this ++ */ ++ gchar *name = ++ gtk_file_system_path_to_filename (impl->file_system, ++ impl->current_folder); + +- profile_end ("end", (char *) path); ++ if (name && !strncmp (name, "/media", 6)) ++ { ++ g_free (name); ++ gtk_file_path_free (path_copy); ++ g_free (file_name); ++ return 0; ++ } + +- return result; +-} +- +-static void +-update_preview_widget_visibility (GtkFileChooserDefault *impl) +-{ +- if (impl->use_preview_label) +- { +- if (!impl->preview_label) +- { +- impl->preview_label = gtk_label_new (impl->preview_display_name); +- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_label, FALSE, FALSE, 0); +- gtk_box_reorder_child (GTK_BOX (impl->preview_box), impl->preview_label, 0); +- gtk_label_set_ellipsize (GTK_LABEL (impl->preview_label), PANGO_ELLIPSIZE_MIDDLE); +- gtk_widget_show (impl->preview_label); +- } +- } ++ gtk_widget_set_sensitive (impl->up_button, TRUE); ++ } ++ else if (!strncmp (file_name, "/media/", 7)) ++ { ++ /* Changing into a media child -- if it is an immediate child, disable ++ * the Up button ++ */ ++ gchar * p = file_name + 7; ++ gchar * q = strchr (p, '/'); ++ if (!q) ++ gtk_widget_set_sensitive (impl->up_button, FALSE); ++ else ++ gtk_widget_set_sensitive (impl->up_button, TRUE); ++ } + else +- { +- if (impl->preview_label) +- { +- gtk_widget_destroy (impl->preview_label); +- impl->preview_label = NULL; +- } +- } ++ { ++ gtk_widget_set_sensitive (impl->up_button, TRUE); ++ } + +- if (impl->preview_widget_active && impl->preview_widget) +- gtk_widget_show (impl->preview_box); +- else +- gtk_widget_hide (impl->preview_box); + +- g_signal_emit_by_name (impl, "default-size-changed"); +-} ++ error = NULL; ++ result = _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), path_copy, &error); + +-static void +-set_preview_widget (GtkFileChooserDefault *impl, +- GtkWidget *preview_widget) +-{ +- if (preview_widget == impl->preview_widget) +- return; ++ if (errormsg && !result) ++ error_changing_folder_dialog (impl, path_copy, error); + +- if (impl->preview_widget) +- gtk_container_remove (GTK_CONTAINER (impl->preview_box), +- impl->preview_widget); ++ gtk_label_set_text (GTK_LABEL (impl->location_label), file_name); + +- impl->preview_widget = preview_widget; +- if (impl->preview_widget) +- { +- gtk_widget_show (impl->preview_widget); +- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_widget, TRUE, TRUE, 0); +- gtk_box_reorder_child (GTK_BOX (impl->preview_box), +- impl->preview_widget, +- (impl->use_preview_label && impl->preview_label) ? 1 : 0); +- } ++ gtk_file_path_free (path_copy); ++ g_free (file_name); + +- update_preview_widget_visibility (impl); ++ return result; + } + +-/* Renders a "Search" icon at an appropriate size for a tree view */ +-static GdkPixbuf * +-render_search_icon (GtkFileChooserDefault *impl) ++static gboolean ++change_folder_and_display_error (GtkFileChooserDefault *impl, ++ const GtkFilePath *path) + { +- return gtk_widget_render_icon (GTK_WIDGET (impl), GTK_STOCK_FIND, GTK_ICON_SIZE_MENU, NULL); ++ return change_folder (impl, path, TRUE); + } + +-static GdkPixbuf * +-render_recent_icon (GtkFileChooserDefault *impl) +-{ +- GtkIconTheme *theme; +- GdkPixbuf *retval; + +- if (gtk_widget_has_screen (GTK_WIDGET (impl))) +- theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl))); +- else +- theme = gtk_icon_theme_get_default (); +- +- retval = gtk_icon_theme_load_icon (theme, "document-open-recent", +- impl->icon_size, 0, +- NULL); +- +- /* fallback */ +- if (!retval) +- retval = gtk_widget_render_icon (GTK_WIDGET (impl), GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); +- +- return retval; +-} +- +- +-/* Re-reads all the icons for the shortcuts, used when the theme changes */ +-struct ReloadIconsData +-{ +- GtkFileChooserDefault *impl; +- GtkTreeRowReference *row_ref; +-}; +- +-static void +-shortcuts_reload_icons_get_info_cb (GtkFileSystemHandle *handle, +- const GtkFileInfo *info, +- const GError *error, +- gpointer user_data) +-{ +- GdkPixbuf *pixbuf; +- GtkTreeIter iter; +- GtkTreePath *path; +- gboolean cancelled = handle->cancelled; +- struct ReloadIconsData *data = user_data; +- +- if (!g_slist_find (data->impl->reload_icon_handles, handle)) +- goto out; +- +- data->impl->reload_icon_handles = g_slist_remove (data->impl->reload_icon_handles, handle); +- +- if (cancelled || error) +- goto out; +- +- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->impl), +- data->impl->icon_size, NULL); +- +- path = gtk_tree_row_reference_get_path (data->row_ref); +- gtk_tree_model_get_iter (GTK_TREE_MODEL (data->impl->shortcuts_model), &iter, path); +- gtk_list_store_set (data->impl->shortcuts_model, &iter, +- SHORTCUTS_COL_PIXBUF, pixbuf, +- -1); +- gtk_tree_path_free (path); +- +- if (pixbuf) +- g_object_unref (pixbuf); +- +-out: +- gtk_tree_row_reference_free (data->row_ref); +- g_object_unref (data->impl); +- g_free (data); +- +- g_object_unref (handle); +-} +- +-static void +-shortcuts_reload_icons (GtkFileChooserDefault *impl) +-{ +- GSList *l; +- GtkTreeIter iter; +- +- profile_start ("start", NULL); +- +- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter)) +- goto out; +- +- for (l = impl->reload_icon_handles; l; l = l->next) +- { +- GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data); +- gtk_file_system_cancel_operation (handle); +- } +- g_slist_free (impl->reload_icon_handles); +- impl->reload_icon_handles = NULL; +- +- do +- { +- gpointer data; +- ShortcutType shortcut_type; +- gboolean pixbuf_visible; +- GdkPixbuf *pixbuf; +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_DATA, &data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- SHORTCUTS_COL_PIXBUF_VISIBLE, &pixbuf_visible, +- -1); +- +- pixbuf = NULL; +- if (pixbuf_visible) +- { +- if (shortcut_type == SHORTCUT_TYPE_VOLUME) +- { +- GtkFileSystemVolume *volume; +- +- volume = data; +- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl), +- impl->icon_size, NULL); +- } +- else if (shortcut_type == SHORTCUT_TYPE_PATH) +- { +- if (gtk_file_system_path_is_local (impl->file_system, (GtkFilePath *)data)) +- { +- const GtkFilePath *path; +- struct ReloadIconsData *info; +- GtkTreePath *tree_path; +- GtkFileSystemHandle *handle; +- +- path = data; +- +- info = g_new0 (struct ReloadIconsData, 1); +- info->impl = g_object_ref (impl); +- tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter); +- info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), tree_path); +- gtk_tree_path_free (tree_path); +- +- handle = gtk_file_system_get_info (impl->file_system, path, +- GTK_FILE_INFO_ICON, +- shortcuts_reload_icons_get_info_cb, +- info); +- impl->reload_icon_handles = g_slist_append (impl->reload_icon_handles, handle); +- } +- else +- { +- GtkIconTheme *icon_theme; +- +- /* Don't call get_info for remote paths to avoid latency and +- * auth dialogs. +- * If we switch to a better bookmarks file format (XBEL), we +- * should use mime info to get a better icon. +- */ +- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl))); +- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-share", +- impl->icon_size, 0, NULL); +- } +- } +- else if (shortcut_type == SHORTCUT_TYPE_SEARCH) +- { +- pixbuf = render_search_icon (impl); +- } +- else if (shortcut_type == SHORTCUT_TYPE_RECENT) +- { +- pixbuf = render_recent_icon (impl); +- } +- +- gtk_list_store_set (impl->shortcuts_model, &iter, +- SHORTCUTS_COL_PIXBUF, pixbuf, +- -1); +- +- if (pixbuf) +- g_object_unref (pixbuf); +- +- } +- } +- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model),&iter)); +- +- out: +- +- profile_end ("end", NULL); +-} +- +-static void +-shortcuts_find_folder (GtkFileChooserDefault *impl, +- GtkFilePath *folder) +-{ +- GtkTreeSelection *selection; +- int pos; +- GtkTreePath *path; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view)); +- +- g_assert (folder != NULL); +- pos = shortcut_find_position (impl, folder); +- if (pos == -1) +- { +- gtk_tree_selection_unselect_all (selection); +- return; +- } +- +- path = gtk_tree_path_new_from_indices (pos, -1); +- gtk_tree_selection_select_path (selection, path); +- gtk_tree_path_free (path); +-} +- +-/* If a shortcut corresponds to the current folder, selects it */ +-static void +-shortcuts_find_current_folder (GtkFileChooserDefault *impl) +-{ +- shortcuts_find_folder (impl, impl->current_folder); +-} +- +-/* Removes the specified number of rows from the shortcuts list */ +-static void +-shortcuts_remove_rows (GtkFileChooserDefault *impl, +- int start_row, +- int n_rows) +-{ +- GtkTreePath *path; +- +- path = gtk_tree_path_new_from_indices (start_row, -1); +- +- for (; n_rows; n_rows--) +- { +- GtkTreeIter iter; +- +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path)) +- g_assert_not_reached (); +- +- shortcuts_free_row_data (impl, &iter); +- gtk_list_store_remove (impl->shortcuts_model, &iter); +- } +- +- gtk_tree_path_free (path); +-} +- +-static void +-shortcuts_update_count (GtkFileChooserDefault *impl, +- ShortcutsIndex type, +- gint value) +-{ +- switch (type) +- { +- case SHORTCUTS_HOME: +- if (value < 0) +- impl->has_home = FALSE; +- else +- impl->has_home = TRUE; +- break; +- +- case SHORTCUTS_DESKTOP: +- if (value < 0) +- impl->has_desktop = FALSE; +- else +- impl->has_desktop = TRUE; +- break; +- +- case SHORTCUTS_VOLUMES: +- impl->num_volumes += value; +- break; +- +- case SHORTCUTS_SHORTCUTS: +- impl->num_shortcuts += value; +- break; +- +- case SHORTCUTS_BOOKMARKS: +- impl->num_bookmarks += value; +- break; +- +- case SHORTCUTS_CURRENT_FOLDER: +- if (value < 0) +- impl->shortcuts_current_folder_active = FALSE; +- else +- impl->shortcuts_current_folder_active = TRUE; +- break; +- +- default: +- /* nothing */ +- break; +- } +-} +- +-struct ShortcutsInsertRequest +-{ +- GtkFileChooserDefault *impl; +- GtkFilePath *parent_path; +- GtkFilePath *path; +- int pos; +- char *label_copy; +- GtkTreeRowReference *row_ref; +- ShortcutsIndex type; +- gboolean name_only; +- gboolean removable; +-}; +- +-static void +-get_file_info_finished (GtkFileSystemHandle *handle, +- const GtkFileInfo *info, +- const GError *error, +- gpointer data) +-{ +- gint pos = -1; +- gboolean cancelled = handle->cancelled; +- GdkPixbuf *pixbuf; +- GtkTreePath *path; +- GtkTreeIter iter; +- GtkFileSystemHandle *model_handle; +- struct ShortcutsInsertRequest *request = data; +- +- path = gtk_tree_row_reference_get_path (request->row_ref); +- if (!path) +- /* Handle doesn't exist anymore in the model */ +- goto out; +- +- pos = gtk_tree_path_get_indices (path)[0]; +- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->shortcuts_model), +- &iter, path); +- gtk_tree_path_free (path); +- +- /* validate handle, else goto out */ +- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->shortcuts_model), &iter, +- SHORTCUTS_COL_HANDLE, &model_handle, +- -1); +- if (handle != model_handle) +- goto out; +- +- /* set the handle to NULL in the model (we unref later on) */ +- gtk_list_store_set (request->impl->shortcuts_model, &iter, +- SHORTCUTS_COL_HANDLE, NULL, +- -1); +- +- if (cancelled) +- goto out; +- +- if (!info) +- { +- gtk_list_store_remove (request->impl->shortcuts_model, &iter); +- shortcuts_update_count (request->impl, request->type, -1); +- +- if (request->type == SHORTCUTS_HOME) +- { +- const char *home = g_get_home_dir (); +- GtkFilePath *home_path; +- +- home_path = gtk_file_system_filename_to_path (request->impl->file_system, home); +- error_getting_info_dialog (request->impl, home_path, g_error_copy (error)); +- gtk_file_path_free (home_path); +- } +- else if (request->type == SHORTCUTS_CURRENT_FOLDER) +- { +- /* Remove the current folder separator */ +- gint separator_pos = shortcuts_get_index (request->impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR); +- shortcuts_remove_rows (request->impl, separator_pos, 1); +- } +- +- goto out; +- } +- +- if (!request->label_copy) +- request->label_copy = g_strdup (gtk_file_info_get_display_name (info)); +- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl), +- request->impl->icon_size, NULL); +- +- gtk_list_store_set (request->impl->shortcuts_model, &iter, +- SHORTCUTS_COL_PIXBUF, pixbuf, +- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE, +- SHORTCUTS_COL_NAME, request->label_copy, +- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_PATH, +- SHORTCUTS_COL_REMOVABLE, request->removable, +- -1); +- +- if (request->impl->shortcuts_pane_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_pane_filter_model)); +- +- if (request->impl->shortcuts_combo_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_combo_filter_model)); +- +- if (request->type == SHORTCUTS_CURRENT_FOLDER && +- request->impl->save_folder_combo != NULL) +- { +- /* The current folder is updated via _activate_iter(), don't +- * have save_folder_combo_changed_cb() call _activate_iter() +- * again. +- */ +- g_signal_handlers_block_by_func (request->impl->save_folder_combo, +- G_CALLBACK (save_folder_combo_changed_cb), +- request->impl); +- +- if (request->impl->has_search) +- pos -= 1; +- +- if (request->impl->has_recent) +- pos -= 2; +- +- gtk_combo_box_set_active (GTK_COMBO_BOX (request->impl->save_folder_combo), pos); +- g_signal_handlers_unblock_by_func (request->impl->save_folder_combo, +- G_CALLBACK (save_folder_combo_changed_cb), +- request->impl); +- } +- +- if (pixbuf) +- g_object_unref (pixbuf); +- +-out: +- g_object_unref (request->impl); +- gtk_file_path_free (request->parent_path); +- gtk_file_path_free (request->path); +- gtk_tree_row_reference_free (request->row_ref); +- g_free (request->label_copy); +- g_free (request); +- +- g_object_unref (handle); +-} +- + /* FIXME: GtkFileSystem needs a function to split a remote path +- * into hostname and path components, or maybe just have a ++ * into hostname and path components, or maybe just have a + * gtk_file_system_path_get_display_name(). + * + * This function is also used in gtkfilechooserbutton.c +@@ -1692,11 +887,11 @@ + { + const gchar *path, *start, *end, *p; + gchar *host, *label; +- ++ + start = strstr (uri, "://"); + start += 3; + path = strchr (start, '/'); +- ++ + if (path) + end = path; + else +@@ -1711,719 +906,25 @@ + { + start = p + 1; + } +- ++ + p = strchr (start, ':'); + if (p && p < end) + end = p; +- ++ + host = g_strndup (start, end - start); + +- /* Translators: the first string is a path and the second string +- * is a hostname. Nautilus and the panel contain the same string +- * to translate. ++ /* Translators: the first string is a path and the second string ++ * is a hostname. Nautilus and the panel contain the same string ++ * to translate. + */ + label = g_strdup_printf (_("%1$s on %2$s"), path, host); +- ++ + g_free (host); + + return label; + } + +-/* Inserts a path in the shortcuts tree, making a copy of it; alternatively, +- * inserts a volume. A position of -1 indicates the end of the tree. +- */ +-static void +-shortcuts_insert_path (GtkFileChooserDefault *impl, +- int pos, +- ShortcutType shortcut_type, +- GtkFileSystemVolume *volume, +- const GtkFilePath *path, +- const char *label, +- gboolean removable, +- ShortcutsIndex type) +-{ +- char *label_copy; +- GdkPixbuf *pixbuf = NULL; +- gpointer data = NULL; +- GtkTreeIter iter; +- GtkIconTheme *icon_theme; + +- profile_start ("start", (shortcut_type == SHORTCUT_TYPE_VOLUME) ? "volume" +- : ((shortcut_type == SHORTCUT_TYPE_PATH) ? (char *) path : NULL)); +- +- if (shortcut_type == SHORTCUT_TYPE_VOLUME) +- { +- data = volume; +- label_copy = gtk_file_system_volume_get_display_name (impl->file_system, volume); +- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl), +- impl->icon_size, NULL); +- } +- else if (shortcut_type == SHORTCUT_TYPE_PATH) +- { +- if (gtk_file_system_path_is_local (impl->file_system, path)) +- { +- struct ShortcutsInsertRequest *request; +- GtkFileSystemHandle *handle; +- GtkTreePath *p; +- +- request = g_new0 (struct ShortcutsInsertRequest, 1); +- request->impl = g_object_ref (impl); +- request->path = gtk_file_path_copy (path); +- request->name_only = TRUE; +- request->removable = removable; +- request->pos = pos; +- request->type = type; +- if (label) +- request->label_copy = g_strdup (label); +- +- if (pos == -1) +- gtk_list_store_append (impl->shortcuts_model, &iter); +- else +- gtk_list_store_insert (impl->shortcuts_model, &iter, pos); +- +- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter); +- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), p); +- gtk_tree_path_free (p); +- +- handle = gtk_file_system_get_info (request->impl->file_system, request->path, +- GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_HIDDEN | GTK_FILE_INFO_ICON, +- get_file_info_finished, request); +- +- gtk_list_store_set (impl->shortcuts_model, &iter, +- SHORTCUTS_COL_DATA, gtk_file_path_copy (path), +- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_PATH, +- SHORTCUTS_COL_HANDLE, handle, +- -1); +- +- shortcuts_update_count (impl, type, 1); +- +- return; +- } +- else +- { +- /* Don't call get_info for remote paths to avoid latency and +- * auth dialogs. +- */ +- data = gtk_file_path_copy (path); +- if (label) +- label_copy = g_strdup (label); +- else +- { +- gchar *uri; +- +- uri = gtk_file_system_path_to_uri (impl->file_system, path); +- +- label_copy = _gtk_file_chooser_label_for_uri (uri); +- +- g_free (uri); +- } +- +- /* If we switch to a better bookmarks file format (XBEL), we +- * should use mime info to get a better icon. +- */ +- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl))); +- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-share", +- impl->icon_size, 0, NULL); +- } +- } +- else +- { +- g_assert_not_reached (); +- +- return; +- } +- +- if (pos == -1) +- gtk_list_store_append (impl->shortcuts_model, &iter); +- else +- gtk_list_store_insert (impl->shortcuts_model, &iter, pos); +- +- shortcuts_update_count (impl, type, 1); +- +- gtk_list_store_set (impl->shortcuts_model, &iter, +- SHORTCUTS_COL_PIXBUF, pixbuf, +- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE, +- SHORTCUTS_COL_NAME, label_copy, +- SHORTCUTS_COL_DATA, data, +- SHORTCUTS_COL_TYPE, shortcut_type, +- SHORTCUTS_COL_REMOVABLE, removable, +- SHORTCUTS_COL_HANDLE, NULL, +- -1); +- +- if (impl->shortcuts_pane_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model)); +- +- if (impl->shortcuts_combo_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model)); +- +- if (type == SHORTCUTS_CURRENT_FOLDER && impl->save_folder_combo != NULL) +- { +- /* The current folder is updated via _activate_iter(), don't +- * have save_folder_combo_changed_cb() call _activate_iter() +- * again. +- */ +- gint combo_pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER); +- +- if (impl->has_search) +- combo_pos -= 1; +- +- if (impl->has_recent) +- combo_pos -= 2; +- +- g_signal_handlers_block_by_func (impl->save_folder_combo, +- G_CALLBACK (save_folder_combo_changed_cb), +- impl); +- +- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), combo_pos); +- g_signal_handlers_unblock_by_func (impl->save_folder_combo, +- G_CALLBACK (save_folder_combo_changed_cb), +- impl); +- } +- +- g_free (label_copy); +- +- if (pixbuf) +- g_object_unref (pixbuf); +- +- profile_end ("end", NULL); +-} +- +-static void +-shortcuts_append_search (GtkFileChooserDefault *impl) +-{ +- GdkPixbuf *pixbuf; +- GtkTreeIter iter; +- +- pixbuf = render_search_icon (impl); +- +- gtk_list_store_append (impl->shortcuts_model, &iter); +- gtk_list_store_set (impl->shortcuts_model, &iter, +- SHORTCUTS_COL_PIXBUF, pixbuf, +- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE, +- SHORTCUTS_COL_NAME, _("Search"), +- SHORTCUTS_COL_DATA, NULL, +- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_SEARCH, +- SHORTCUTS_COL_REMOVABLE, FALSE, +- -1); +- +- if (pixbuf) +- g_object_unref (pixbuf); +- +- impl->has_search = TRUE; +-} +- +-static void +-shortcuts_append_recent (GtkFileChooserDefault *impl) +-{ +- GdkPixbuf *pixbuf; +- GtkTreeIter iter; +- +- pixbuf = render_recent_icon (impl); +- +- gtk_list_store_append (impl->shortcuts_model, &iter); +- gtk_list_store_set (impl->shortcuts_model, &iter, +- SHORTCUTS_COL_PIXBUF, pixbuf, +- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE, +- SHORTCUTS_COL_NAME, _("Recently Used"), +- SHORTCUTS_COL_DATA, NULL, +- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_RECENT, +- SHORTCUTS_COL_REMOVABLE, FALSE, +- -1); +- +- if (pixbuf) +- g_object_unref (pixbuf); +- +- impl->has_recent = TRUE; +-} +- +-/* Appends an item for the user's home directory to the shortcuts model */ +-static void +-shortcuts_append_home (GtkFileChooserDefault *impl) +-{ +- const char *home; +- GtkFilePath *home_path; +- +- profile_start ("start", NULL); +- +- home = g_get_home_dir (); +- if (home == NULL) +- { +- profile_end ("end - no home directory!?", NULL); +- return; +- } +- +- home_path = gtk_file_system_filename_to_path (impl->file_system, home); +- +- shortcuts_insert_path (impl, -1, SHORTCUT_TYPE_PATH, NULL, home_path, NULL, FALSE, SHORTCUTS_HOME); +- impl->has_home = TRUE; +- +- gtk_file_path_free (home_path); +- +- profile_end ("end", NULL); +-} +- +-/* Appends the ~/Desktop directory to the shortcuts model */ +-static void +-shortcuts_append_desktop (GtkFileChooserDefault *impl) +-{ +- const char *name; +- GtkFilePath *path; +- +- profile_start ("start", NULL); +- +- name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); +- path = gtk_file_system_filename_to_path (impl->file_system, name); +- shortcuts_insert_path (impl, -1, SHORTCUT_TYPE_PATH, NULL, path, _("Desktop"), FALSE, SHORTCUTS_DESKTOP); +- impl->has_desktop = TRUE; +- +- /* We do not actually pop up an error dialog if there is no desktop directory +- * because some people may really not want to have one. +- */ +- +- gtk_file_path_free (path); +- +- profile_end ("end", NULL); +-} +- +-/* Appends a list of GtkFilePath to the shortcuts model; returns how many were inserted */ +-static int +-shortcuts_append_paths (GtkFileChooserDefault *impl, +- GSList *paths) +-{ +- int start_row; +- int num_inserted; +- gchar *label; +- +- profile_start ("start", NULL); +- +- /* As there is no separator now, we want to start there. +- */ +- start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR); +- num_inserted = 0; +- +- for (; paths; paths = paths->next) +- { +- GtkFilePath *path; +- +- path = paths->data; +- +- if (impl->local_only && +- !gtk_file_system_path_is_local (impl->file_system, path)) +- continue; +- +- label = gtk_file_system_get_bookmark_label (impl->file_system, path); +- +- /* NULL GError, but we don't really want to show error boxes here */ +- shortcuts_insert_path (impl, start_row + num_inserted, SHORTCUT_TYPE_PATH, NULL, path, label, TRUE, SHORTCUTS_BOOKMARKS); +- num_inserted++; +- +- g_free (label); +- } +- +- profile_end ("end", NULL); +- +- return num_inserted; +-} +- +-/* Returns the index for the corresponding item in the shortcuts bar */ +-static int +-shortcuts_get_index (GtkFileChooserDefault *impl, +- ShortcutsIndex where) +-{ +- int n; +- +- n = 0; +- +- if (where == SHORTCUTS_SEARCH) +- goto out; +- +- n += impl->has_search ? 1 : 0; +- +- if (where == SHORTCUTS_RECENT) +- goto out; +- +- n += impl->has_recent ? 1 : 0; +- +- if (where == SHORTCUTS_RECENT_SEPARATOR) +- goto out; +- +- n += impl->has_recent ? 1 : 0; +- +- if (where == SHORTCUTS_HOME) +- goto out; +- +- n += impl->has_home ? 1 : 0; +- +- if (where == SHORTCUTS_DESKTOP) +- goto out; +- +- n += impl->has_desktop ? 1 : 0; +- +- if (where == SHORTCUTS_VOLUMES) +- goto out; +- +- n += impl->num_volumes; +- +- if (where == SHORTCUTS_SHORTCUTS) +- goto out; +- +- n += impl->num_shortcuts; +- +- if (where == SHORTCUTS_BOOKMARKS_SEPARATOR) +- goto out; +- +- /* If there are no bookmarks there won't be a separator */ +- n += (impl->num_bookmarks > 0) ? 1 : 0; +- +- if (where == SHORTCUTS_BOOKMARKS) +- goto out; +- +- n += impl->num_bookmarks; +- +- if (where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR) +- goto out; +- +- n += 1; +- +- if (where == SHORTCUTS_CURRENT_FOLDER) +- goto out; +- +- g_assert_not_reached (); +- +- out: +- +- return n; +-} +- +-/* Adds all the file system volumes to the shortcuts model */ +-static void +-shortcuts_add_volumes (GtkFileChooserDefault *impl) +-{ +- int start_row; +- GSList *list, *l; +- int n; +- gboolean old_changing_folders; +- +- profile_start ("start", NULL); +- +- +- old_changing_folders = impl->changing_folder; +- impl->changing_folder = TRUE; +- +- start_row = shortcuts_get_index (impl, SHORTCUTS_VOLUMES); +- shortcuts_remove_rows (impl, start_row, impl->num_volumes); +- impl->num_volumes = 0; +- +- list = gtk_file_system_list_volumes (impl->file_system); +- +- n = 0; +- +- for (l = list; l; l = l->next) +- { +- GtkFileSystemVolume *volume; +- +- volume = l->data; +- +- if (impl->local_only) +- { +- if (gtk_file_system_volume_get_is_mounted (impl->file_system, volume)) +- { +- GtkFilePath *base_path; +- +- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume); +- if (base_path != NULL) +- { +- gboolean is_local = gtk_file_system_path_is_local (impl->file_system, base_path); +- gtk_file_path_free (base_path); +- +- if (!is_local) +- { +- gtk_file_system_volume_free (impl->file_system, volume); +- continue; +- } +- } +- } +- } +- +- shortcuts_insert_path (impl, start_row + n, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_VOLUMES); +- n++; +- } +- +- impl->num_volumes = n; +- g_slist_free (list); +- +- if (impl->shortcuts_pane_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model)); +- +- if (impl->shortcuts_combo_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model)); +- +- impl->changing_folder = old_changing_folders; +- +- profile_end ("end", NULL); +-} +- +-/* Inserts a separator node in the shortcuts list */ +-static void +-shortcuts_insert_separator (GtkFileChooserDefault *impl, +- ShortcutsIndex where) +-{ +- GtkTreeIter iter; +- +- g_assert (where == SHORTCUTS_RECENT_SEPARATOR || +- where == SHORTCUTS_BOOKMARKS_SEPARATOR || +- where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR); +- +- gtk_list_store_insert (impl->shortcuts_model, &iter, +- shortcuts_get_index (impl, where)); +- gtk_list_store_set (impl->shortcuts_model, &iter, +- SHORTCUTS_COL_PIXBUF, NULL, +- SHORTCUTS_COL_PIXBUF_VISIBLE, FALSE, +- SHORTCUTS_COL_NAME, NULL, +- SHORTCUTS_COL_DATA, NULL, +- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_SEPARATOR, +- -1); +-} +- +-/* Updates the list of bookmarks */ +-static void +-shortcuts_add_bookmarks (GtkFileChooserDefault *impl) +-{ +- GSList *bookmarks; +- gboolean old_changing_folders; +- GtkTreeIter iter; +- GtkFilePath *list_selected = NULL; +- GtkFilePath *combo_selected = NULL; +- ShortcutType shortcut_type; +- gpointer col_data; +- +- profile_start ("start", NULL); +- +- old_changing_folders = impl->changing_folder; +- impl->changing_folder = TRUE; +- +- if (shortcuts_get_selected (impl, &iter)) +- { +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), +- &iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- -1); +- +- if (col_data && shortcut_type == SHORTCUT_TYPE_PATH) +- list_selected = gtk_file_path_copy (col_data); +- } +- +- if (impl->save_folder_combo && +- gtk_combo_box_get_active_iter (GTK_COMBO_BOX (impl->save_folder_combo), +- &iter)) +- { +- GtkTreeIter child_iter; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model), +- &child_iter, +- &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), +- &child_iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- -1); +- +- if (col_data && shortcut_type == SHORTCUT_TYPE_PATH) +- combo_selected = gtk_file_path_copy (col_data); +- } +- +- if (impl->num_bookmarks > 0) +- shortcuts_remove_rows (impl, +- shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR), +- impl->num_bookmarks + 1); +- +- impl->num_bookmarks = 0; +- +- bookmarks = gtk_file_system_list_bookmarks (impl->file_system); +- shortcuts_append_paths (impl, bookmarks); +- gtk_file_paths_free (bookmarks); +- +- if (impl->num_bookmarks > 0) +- shortcuts_insert_separator (impl, SHORTCUTS_BOOKMARKS_SEPARATOR); +- +- if (impl->shortcuts_pane_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model)); +- +- if (impl->shortcuts_combo_filter_model) +- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model)); +- +- if (list_selected) +- { +- shortcuts_find_folder (impl, list_selected); +- gtk_file_path_free (list_selected); +- } +- +- if (combo_selected) +- { +- gint pos; +- +- pos = shortcut_find_position (impl, combo_selected); +- if (pos != -1) +- { +- if (impl->has_search) +- pos -= 1; +- +- if (impl->has_recent) +- pos -= 2; +- +- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos); +- } +- +- gtk_file_path_free (combo_selected); +- } +- +- impl->changing_folder = old_changing_folders; +- +- profile_end ("end", NULL); +-} +- +-/* Appends a separator and a row to the shortcuts list for the current folder */ +-static void +-shortcuts_add_current_folder (GtkFileChooserDefault *impl) +-{ +- int pos; +- gboolean success; +- +- g_assert (!impl->shortcuts_current_folder_active); +- +- success = TRUE; +- +- g_assert (impl->current_folder != NULL); +- +- pos = shortcut_find_position (impl, impl->current_folder); +- if (pos == -1) +- { +- GtkFileSystemVolume *volume; +- GtkFilePath *base_path; +- +- /* Separator */ +- +- shortcuts_insert_separator (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR); +- +- /* Item */ +- +- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER); +- +- volume = gtk_file_system_get_volume_for_path (impl->file_system, impl->current_folder); +- if (volume) +- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume); +- else +- base_path = NULL; +- +- if (base_path && +- strcmp (gtk_file_path_get_string (base_path), gtk_file_path_get_string (impl->current_folder)) == 0) +- { +- shortcuts_insert_path (impl, pos, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER); +- } +- else +- { +- shortcuts_insert_path (impl, pos, SHORTCUT_TYPE_PATH, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER); +- if (volume) +- gtk_file_system_volume_free (impl->file_system, volume); +- } +- +- if (base_path) +- gtk_file_path_free (base_path); +- } +- else if (impl->save_folder_combo != NULL) +- { +- if (impl->has_search) +- pos -= 1; +- +- if (impl->has_recent) +- pos -= 2; /* + separator */ +- +- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos); +- } +-} +- +-/* Updates the current folder row in the shortcuts model */ +-static void +-shortcuts_update_current_folder (GtkFileChooserDefault *impl) +-{ +- int pos; +- +- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR); +- +- if (impl->shortcuts_current_folder_active) +- { +- shortcuts_remove_rows (impl, pos, 2); +- impl->shortcuts_current_folder_active = FALSE; +- } +- +- shortcuts_add_current_folder (impl); +-} +- +-/* Filter function used for the shortcuts filter model */ +-static gboolean +-shortcuts_pane_filter_cb (GtkTreeModel *model, +- GtkTreeIter *iter, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- GtkTreePath *path; +- int pos; +- +- impl = GTK_FILE_CHOOSER_DEFAULT (data); +- +- path = gtk_tree_model_get_path (model, iter); +- if (!path) +- return FALSE; +- +- pos = *gtk_tree_path_get_indices (path); +- gtk_tree_path_free (path); +- +- return (pos < shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR)); +-} +- +-/* Creates the list model for shortcuts */ +-static void +-shortcuts_model_create (GtkFileChooserDefault *impl) +-{ +- /* Keep this order in sync with the SHORCUTS_COL_* enum values */ +- impl->shortcuts_model = gtk_list_store_new (SHORTCUTS_COL_NUM_COLUMNS, +- GDK_TYPE_PIXBUF, /* pixbuf */ +- G_TYPE_STRING, /* name */ +- G_TYPE_POINTER, /* path or volume */ +- G_TYPE_INT, /* ShortcutType */ +- G_TYPE_BOOLEAN, /* removable */ +- G_TYPE_BOOLEAN, /* pixbuf cell visibility */ +- G_TYPE_POINTER); /* GtkFileSystemHandle */ +- +- if (search_is_possible (impl)) +- { +- shortcuts_append_search (impl); +- } +- +- if (impl->recent_manager) +- { +- shortcuts_append_recent (impl); +- shortcuts_insert_separator (impl, SHORTCUTS_RECENT_SEPARATOR); +- } +- +- if (impl->file_system) +- { +- shortcuts_append_home (impl); +- shortcuts_append_desktop (impl); +- shortcuts_add_volumes (impl); +- } +- +- impl->shortcuts_pane_filter_model = shortcuts_pane_model_filter_new (impl, +- GTK_TREE_MODEL (impl->shortcuts_model), +- NULL); +- +- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model), +- shortcuts_pane_filter_cb, +- impl, +- NULL); +-} +- + /* Callback used when the "New Folder" button is clicked */ + static void + new_folder_button_clicked (GtkButton *button, +@@ -2472,7 +973,7 @@ + goto out; + + if (!error) +- change_folder_and_display_error (impl, path, FALSE); ++ change_folder_and_display_error (impl, path); + else + error_creating_folder_dialog (impl, path, g_error_copy (error)); + +@@ -2488,7 +989,7 @@ + edited_idle_cb (GtkFileChooserDefault *impl) + { + GDK_THREADS_ENTER (); +- ++ + g_source_destroy (impl->edited_idle); + impl->edited_idle = NULL; + +@@ -2558,10 +1059,10 @@ + const gchar *new_text, + GtkFileChooserDefault *impl) + { +- /* work around bug #154921 */ +- g_object_set (cell_renderer_text, ++ /* work around bug #154921 */ ++ g_object_set (cell_renderer_text, + "mode", GTK_CELL_RENDERER_MODE_INERT, NULL); +- queue_edited_idle (impl, new_text); ++ queue_edited_idle (impl, new_text); + } + + /* Callback used from the text cell renderer when the new folder edition gets +@@ -2571,10 +1072,10 @@ + renderer_editing_canceled_cb (GtkCellRendererText *cell_renderer_text, + GtkFileChooserDefault *impl) + { +- /* work around bug #154921 */ +- g_object_set (cell_renderer_text, ++ /* work around bug #154921 */ ++ g_object_set (cell_renderer_text, + "mode", GTK_CELL_RENDERER_MODE_INERT, NULL); +- queue_edited_idle (impl, NULL); ++ queue_edited_idle (impl, NULL); + } + + /* Creates the widgets for the filter combo box */ +@@ -2587,253 +1088,9 @@ + g_signal_connect (impl->filter_combo, "changed", + G_CALLBACK (filter_combo_changed), impl); + +- gtk_widget_set_tooltip_text (impl->filter_combo, +- _("Select which types of files are shown")); +- + return impl->filter_combo; + } + +-static GtkWidget * +-button_new (GtkFileChooserDefault *impl, +- const char *text, +- const char *stock_id, +- gboolean sensitive, +- gboolean show, +- GCallback callback) +-{ +- GtkWidget *button; +- GtkWidget *image; +- +- button = gtk_button_new_with_mnemonic (text); +- image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON); +- gtk_button_set_image (GTK_BUTTON (button), image); +- +- gtk_widget_set_sensitive (button, sensitive); +- g_signal_connect (button, "clicked", callback, impl); +- +- if (show) +- gtk_widget_show (button); +- +- return button; +-} +- +-/* Looks for a path among the shortcuts; returns its index or -1 if it doesn't exist */ +-static int +-shortcut_find_position (GtkFileChooserDefault *impl, +- const GtkFilePath *path) +-{ +- GtkTreeIter iter; +- int i; +- int current_folder_separator_idx; +- +- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter)) +- return -1; +- +- current_folder_separator_idx = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR); +- +-#if 0 +- /* FIXME: is this still needed? */ +- if (current_folder_separator_idx >= impl->shortcuts_model->length) +- return -1; +-#endif +- +- for (i = 0; i < current_folder_separator_idx; i++) +- { +- gpointer col_data; +- ShortcutType shortcut_type; +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- -1); +- +- if (col_data) +- { +- if (shortcut_type == SHORTCUT_TYPE_VOLUME) +- { +- GtkFileSystemVolume *volume; +- GtkFilePath *base_path; +- gboolean exists; +- +- volume = col_data; +- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume); +- +- exists = base_path && strcmp (gtk_file_path_get_string (path), +- gtk_file_path_get_string (base_path)) == 0; +- g_free (base_path); +- +- if (exists) +- return i; +- } +- else if (shortcut_type == SHORTCUT_TYPE_PATH) +- { +- GtkFilePath *model_path; +- +- model_path = col_data; +- +- if (model_path && gtk_file_path_compare (model_path, path) == 0) +- return i; +- } +- } +- +- if (i < current_folder_separator_idx - 1) +- { +- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter)) +- g_assert_not_reached (); +- } +- } +- +- return -1; +-} +- +-/* Tries to add a bookmark from a path name */ +-static gboolean +-shortcuts_add_bookmark_from_path (GtkFileChooserDefault *impl, +- const GtkFilePath *path, +- int pos) +-{ +- GError *error; +- +- g_return_val_if_fail (path != NULL, FALSE); +- +- if (shortcut_find_position (impl, path) != -1) +- return FALSE; +- +- error = NULL; +- if (!gtk_file_system_insert_bookmark (impl->file_system, path, pos, &error)) +- { +- error_adding_bookmark_dialog (impl, path, error); +- return FALSE; +- } +- +- return TRUE; +-} +- +-static void +-add_bookmark_foreach_cb (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *iter, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- GtkFileSystemModel *fs_model; +- GtkTreeIter child_iter; +- const GtkFilePath *file_path; +- +- impl = (GtkFileChooserDefault *) data; +- +- switch (impl->operation_mode) +- { +- case OPERATION_MODE_BROWSE: +- fs_model = impl->browse_files_model; +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter); +- file_path = _gtk_file_system_model_get_path (fs_model, &child_iter); +- break; +- +- case OPERATION_MODE_SEARCH: +- search_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_PATH, &file_path, +- -1); +- break; +- +- case OPERATION_MODE_RECENT: +- recent_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_PATH, &file_path, +- -1); +- break; +- } +- +- shortcuts_add_bookmark_from_path (impl, file_path, -1); +-} +- +-/* Adds a bookmark from the currently selected item in the file list */ +-static void +-bookmarks_add_selected_folder (GtkFileChooserDefault *impl) +-{ +- GtkTreeSelection *selection; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- +- if (gtk_tree_selection_count_selected_rows (selection) == 0) +- shortcuts_add_bookmark_from_path (impl, impl->current_folder, -1); +- else +- gtk_tree_selection_selected_foreach (selection, +- add_bookmark_foreach_cb, +- impl); +-} +- +-/* Callback used when the "Add bookmark" button is clicked */ +-static void +-add_bookmark_button_clicked_cb (GtkButton *button, +- GtkFileChooserDefault *impl) +-{ +- bookmarks_add_selected_folder (impl); +-} +- +-/* Returns TRUE plus an iter in the shortcuts_model if a row is selected; +- * returns FALSE if no shortcut is selected. +- */ +-static gboolean +-shortcuts_get_selected (GtkFileChooserDefault *impl, +- GtkTreeIter *iter) +-{ +- GtkTreeSelection *selection; +- GtkTreeIter parent_iter; +- +- if (!impl->browse_shortcuts_tree_view) +- return FALSE; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view)); +- +- if (!gtk_tree_selection_get_selected (selection, NULL, &parent_iter)) +- return FALSE; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model), +- iter, +- &parent_iter); +- return TRUE; +-} +- +-/* Removes the selected bookmarks */ +-static void +-remove_selected_bookmarks (GtkFileChooserDefault *impl) +-{ +- GtkTreeIter iter; +- gpointer col_data; +- GtkFilePath *path; +- gboolean removable; +- GError *error; +- +- if (!shortcuts_get_selected (impl, &iter)) +- return; +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_REMOVABLE, &removable, +- -1); +- +- if (!removable) +- return; +- +- g_assert (col_data != NULL); +- +- path = col_data; +- +- error = NULL; +- if (!gtk_file_system_remove_bookmark (impl->file_system, path, &error)) +- error_removing_bookmark_dialog (impl, path, error); +-} +- +-/* Callback used when the "Remove bookmark" button is clicked */ +-static void +-remove_bookmark_button_clicked_cb (GtkButton *button, +- GtkFileChooserDefault *impl) +-{ +- remove_selected_bookmarks (impl); +-} +- + struct selection_check_closure { + GtkFileChooserDefault *impl; + int num_selected; +@@ -2856,29 +1113,11 @@ + closure = data; + closure->num_selected++; + +- switch (closure->impl->operation_mode) +- { +- case OPERATION_MODE_BROWSE: +- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter); +- info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter); +- is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE; +- break; ++ gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter); + +- case OPERATION_MODE_SEARCH: +- search_get_valid_child_iter (closure->impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->search_model), &child_iter, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- break; ++ info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter); ++ is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE; + +- case OPERATION_MODE_RECENT: +- recent_get_valid_child_iter (closure->impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- break; +- } +- + closure->all_folders = closure->all_folders && is_folder; + closure->all_files = closure->all_files && !is_folder; + } +@@ -2920,1126 +1159,6 @@ + const GtkFilePath *path; + }; + +-static void +-get_selected_path_foreach_cb (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *iter, +- gpointer data) +-{ +- struct get_selected_path_closure *closure; +- GtkTreeIter child_iter; +- +- closure = data; +- +- switch (closure->impl->operation_mode) +- { +- case OPERATION_MODE_BROWSE: +- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter); +- closure->path = _gtk_file_system_model_get_path (closure->impl->browse_files_model, &child_iter); +- break; +- +- case OPERATION_MODE_SEARCH: +- search_get_valid_child_iter (closure->impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->search_model), &child_iter, +- SEARCH_MODEL_COL_PATH, &closure->path, +- -1); +- break; +- +- case OPERATION_MODE_RECENT: +- recent_get_valid_child_iter (closure->impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter, +- RECENT_MODEL_COL_PATH, &closure->path, +- -1); +- break; +- } +-} +- +-/* Returns a selected path from the file list */ +-static const GtkFilePath * +-get_selected_path (GtkFileChooserDefault *impl) +-{ +- struct get_selected_path_closure closure; +- GtkTreeSelection *selection; +- +- closure.impl = impl; +- closure.path = NULL; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- gtk_tree_selection_selected_foreach (selection, +- get_selected_path_foreach_cb, +- &closure); +- +- return closure.path; +-} +- +-typedef struct { +- GtkFileChooserDefault *impl; +- gchar *tip; +-} UpdateTooltipData; +- +-static void +-update_tooltip (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *iter, +- gpointer data) +-{ +- UpdateTooltipData *udata = data; +- GtkTreeIter child_iter; +- const GtkFileInfo *info; +- +- if (udata->tip == NULL) +- { +- const gchar *display_name; +- +- switch (udata->impl->operation_mode) +- { +- case OPERATION_MODE_BROWSE: +- gtk_tree_model_sort_convert_iter_to_child_iter (udata->impl->sort_model, +- &child_iter, +- iter); +- info = _gtk_file_system_model_get_info (udata->impl->browse_files_model, &child_iter); +- display_name = gtk_file_info_get_display_name (info); +- break; +- +- case OPERATION_MODE_SEARCH: +- search_get_valid_child_iter (udata->impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (udata->impl->search_model), &child_iter, +- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name, +- -1); +- break; +- +- case OPERATION_MODE_RECENT: +- recent_get_valid_child_iter (udata->impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (udata->impl->recent_model), &child_iter, +- RECENT_MODEL_COL_DISPLAY_NAME, &display_name, +- -1); +- break; +- } +- +- udata->tip = g_strdup_printf (_("Add the folder '%s' to the bookmarks"), +- display_name); +- } +-} +- +- +-/* Sensitize the "add bookmark" button if all the selected items are folders, or +- * if there are no selected items *and* the current folder is not in the +- * bookmarks list. De-sensitize the button otherwise. +- */ +-static void +-bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl) +-{ +- gint num_selected; +- gboolean all_folders; +- gboolean active; +- gchar *tip; +- +- selection_check (impl, &num_selected, NULL, &all_folders); +- +- if (num_selected == 0) +- active = (impl->current_folder != NULL) && (shortcut_find_position (impl, impl->current_folder) == -1); +- else if (num_selected == 1) +- { +- const GtkFilePath *path; +- +- path = get_selected_path (impl); +- active = all_folders && (shortcut_find_position (impl, path) == -1); +- } +- else +- active = all_folders; +- +- gtk_widget_set_sensitive (impl->browse_shortcuts_add_button, active); +- +- if (impl->browse_files_popup_menu_add_shortcut_item) +- gtk_widget_set_sensitive (impl->browse_files_popup_menu_add_shortcut_item, +- (num_selected == 0) ? FALSE : active); +- +- if (active) +- { +- if (num_selected == 0) +- tip = g_strdup_printf (_("Add the current folder to the bookmarks")); +- else if (num_selected > 1) +- tip = g_strdup_printf (_("Add the selected folders to the bookmarks")); +- else +- { +- GtkTreeSelection *selection; +- UpdateTooltipData data; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- data.impl = impl; +- data.tip = NULL; +- gtk_tree_selection_selected_foreach (selection, update_tooltip, &data); +- tip = data.tip; +- } +- +- gtk_widget_set_tooltip_text (impl->browse_shortcuts_add_button, tip); +- g_free (tip); +- } +-} +- +-/* Sets the sensitivity of the "remove bookmark" button depending on whether a +- * bookmark row is selected in the shortcuts tree. +- */ +-static void +-bookmarks_check_remove_sensitivity (GtkFileChooserDefault *impl) +-{ +- GtkTreeIter iter; +- gboolean removable = FALSE; +- gchar *name = NULL; +- +- if (shortcuts_get_selected (impl, &iter)) +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_REMOVABLE, &removable, +- SHORTCUTS_COL_NAME, &name, +- -1); +- +- gtk_widget_set_sensitive (impl->browse_shortcuts_remove_button, removable); +- +- if (removable) +- { +- gchar *tip; +- +- tip = g_strdup_printf (_("Remove the bookmark '%s'"), name); +- gtk_widget_set_tooltip_text (impl->browse_shortcuts_remove_button, tip); +- g_free (tip); +- } +- +- g_free (name); +-} +- +-static void +-shortcuts_check_popup_sensitivity (GtkFileChooserDefault *impl) +-{ +- GtkTreeIter iter; +- gboolean removable = FALSE; +- +- if (impl->browse_shortcuts_popup_menu == NULL) +- return; +- +- if (shortcuts_get_selected (impl, &iter)) +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_REMOVABLE, &removable, +- -1); +- +- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_remove_item, removable); +- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_rename_item, removable); +-} +- +-/* GtkWidget::drag-begin handler for the shortcuts list. */ +-static void +-shortcuts_drag_begin_cb (GtkWidget *widget, +- GdkDragContext *context, +- GtkFileChooserDefault *impl) +-{ +-#if 0 +- impl->shortcuts_drag_context = g_object_ref (context); +-#endif +-} +- +-#if 0 +-/* Removes the idle handler for outside drags */ +-static void +-shortcuts_cancel_drag_outside_idle (GtkFileChooserDefault *impl) +-{ +- if (!impl->shortcuts_drag_outside_idle) +- return; +- +- g_source_destroy (impl->shortcuts_drag_outside_idle); +- impl->shortcuts_drag_outside_idle = NULL; +-} +-#endif +- +-/* GtkWidget::drag-end handler for the shortcuts list. */ +-static void +-shortcuts_drag_end_cb (GtkWidget *widget, +- GdkDragContext *context, +- GtkFileChooserDefault *impl) +-{ +-#if 0 +- g_object_unref (impl->shortcuts_drag_context); +- +- shortcuts_cancel_drag_outside_idle (impl); +- +- if (!impl->shortcuts_drag_outside) +- return; +- +- gtk_button_clicked (GTK_BUTTON (impl->browse_shortcuts_remove_button)); +- +- impl->shortcuts_drag_outside = FALSE; +-#endif +-} +- +-/* GtkWidget::drag-data-delete handler for the shortcuts list. */ +-static void +-shortcuts_drag_data_delete_cb (GtkWidget *widget, +- GdkDragContext *context, +- GtkFileChooserDefault *impl) +-{ +- g_signal_stop_emission_by_name (widget, "drag_data_delete"); +-} +- +-#if 0 +-/* Creates a suitable drag cursor to indicate that the selected bookmark will be +- * deleted or not. +- */ +-static void +-shortcuts_drag_set_delete_cursor (GtkFileChooserDefault *impl, +- gboolean delete) +-{ +- GtkTreeView *tree_view; +- GtkTreeIter iter; +- GtkTreePath *path; +- GdkPixmap *row_pixmap; +- GdkBitmap *mask; +- int row_pixmap_y; +- int cell_y; +- +- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view); +- +- /* Find the selected path and get its drag pixmap */ +- +- if (!shortcuts_get_selected (impl, &iter)) +- g_assert_not_reached (); +- +- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter); +- +- row_pixmap = gtk_tree_view_create_row_drag_icon (tree_view, path); +- gtk_tree_path_free (path); +- +- mask = NULL; +- row_pixmap_y = 0; +- +- if (delete) +- { +- GdkPixbuf *pixbuf; +- +- pixbuf = gtk_widget_render_icon (impl->browse_shortcuts_tree_view, +- GTK_STOCK_DELETE, +- GTK_ICON_SIZE_DND, +- NULL); +- if (pixbuf) +- { +- GdkPixmap *composite; +- int row_pixmap_width, row_pixmap_height; +- int pixbuf_width, pixbuf_height; +- int composite_width, composite_height; +- int pixbuf_x, pixbuf_y; +- GdkGC *gc, *mask_gc; +- GdkColor color; +- GdkBitmap *pixbuf_mask; +- +- /* Create pixmap and mask for composite image */ +- +- gdk_drawable_get_size (row_pixmap, &row_pixmap_width, &row_pixmap_height); +- pixbuf_width = gdk_pixbuf_get_width (pixbuf); +- pixbuf_height = gdk_pixbuf_get_height (pixbuf); +- +- composite_width = MAX (row_pixmap_width, pixbuf_width); +- composite_height = MAX (row_pixmap_height, pixbuf_height); +- +- row_pixmap_y = (composite_height - row_pixmap_height) / 2; +- +- if (gtk_widget_get_direction (impl->browse_shortcuts_tree_view) == GTK_TEXT_DIR_RTL) +- pixbuf_x = 0; +- else +- pixbuf_x = composite_width - pixbuf_width; +- +- pixbuf_y = (composite_height - pixbuf_height) / 2; +- +- composite = gdk_pixmap_new (row_pixmap, composite_width, composite_height, -1); +- gc = gdk_gc_new (composite); +- +- mask = gdk_pixmap_new (row_pixmap, composite_width, composite_height, 1); +- mask_gc = gdk_gc_new (mask); +- color.pixel = 0; +- gdk_gc_set_foreground (mask_gc, &color); +- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, 0, composite_width, composite_height); +- +- color.red = 0xffff; +- color.green = 0xffff; +- color.blue = 0xffff; +- gdk_gc_set_rgb_fg_color (gc, &color); +- gdk_draw_rectangle (composite, gc, TRUE, 0, 0, composite_width, composite_height); +- +- /* Composite the row pixmap and the pixbuf */ +- +- gdk_pixbuf_render_pixmap_and_mask_for_colormap +- (pixbuf, +- gtk_widget_get_colormap (impl->browse_shortcuts_tree_view), +- NULL, &pixbuf_mask, 128); +- gdk_draw_drawable (mask, mask_gc, pixbuf_mask, +- 0, 0, +- pixbuf_x, pixbuf_y, +- pixbuf_width, pixbuf_height); +- g_object_unref (pixbuf_mask); +- +- gdk_draw_drawable (composite, gc, row_pixmap, +- 0, 0, +- 0, row_pixmap_y, +- row_pixmap_width, row_pixmap_height); +- color.pixel = 1; +- gdk_gc_set_foreground (mask_gc, &color); +- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, row_pixmap_y, row_pixmap_width, row_pixmap_height); +- +- gdk_draw_pixbuf (composite, gc, pixbuf, +- 0, 0, +- pixbuf_x, pixbuf_y, +- pixbuf_width, pixbuf_height, +- GDK_RGB_DITHER_MAX, +- 0, 0); +- +- g_object_unref (pixbuf); +- g_object_unref (row_pixmap); +- +- row_pixmap = composite; +- } +- } +- +- /* The hotspot offsets here are copied from gtk_tree_view_drag_begin(), ugh */ +- +- gtk_tree_view_get_path_at_pos (tree_view, +- tree_view->priv->press_start_x, +- tree_view->priv->press_start_y, +- NULL, +- NULL, +- NULL, +- &cell_y); +- +- gtk_drag_set_icon_pixmap (impl->shortcuts_drag_context, +- gdk_drawable_get_colormap (row_pixmap), +- row_pixmap, +- mask, +- tree_view->priv->press_start_x + 1, +- row_pixmap_y + cell_y + 1); +- +- g_object_unref (row_pixmap); +- if (mask) +- g_object_unref (mask); +-} +- +-/* We set the delete cursor and the shortcuts_drag_outside flag in an idle +- * handler so that we can tell apart the drag_leave event that comes right +- * before a drag_drop, from a normal drag_leave. We don't want to set the +- * cursor nor the flag in the latter case. +- */ +-static gboolean +-shortcuts_drag_outside_idle_cb (GtkFileChooserDefault *impl) +-{ +- GDK_THREADS_ENTER (); +- +- shortcuts_drag_set_delete_cursor (impl, TRUE); +- impl->shortcuts_drag_outside = TRUE; +- +- shortcuts_cancel_drag_outside_idle (impl); +- +- GDK_THREADS_LEAVE (); +- +- return FALSE; +-} +-#endif +- +-/* GtkWidget::drag-leave handler for the shortcuts list. We unhighlight the +- * drop position. +- */ +-static void +-shortcuts_drag_leave_cb (GtkWidget *widget, +- GdkDragContext *context, +- guint time_, +- GtkFileChooserDefault *impl) +-{ +-#if 0 +- if (gtk_drag_get_source_widget (context) == widget && !impl->shortcuts_drag_outside_idle) +- { +- impl->shortcuts_drag_outside_idle = g_idle_source_new (); +- g_source_set_closure (impl->shortcuts_drag_outside_idle, +- g_cclosure_new_object (G_CALLBACK (shortcuts_drag_outside_idle_cb), +- G_OBJECT (impl))); +- g_source_attach (impl->shortcuts_drag_outside_idle, NULL); +- } +-#endif +- +- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), +- NULL, +- GTK_TREE_VIEW_DROP_BEFORE); +- +- g_signal_stop_emission_by_name (widget, "drag_leave"); +-} +- +-/* Computes the appropriate row and position for dropping */ +-static void +-shortcuts_compute_drop_position (GtkFileChooserDefault *impl, +- int x, +- int y, +- GtkTreePath **path, +- GtkTreeViewDropPosition *pos) +-{ +- GtkTreeView *tree_view; +- GtkTreeViewColumn *column; +- int cell_y; +- GdkRectangle cell; +- int row; +- int bookmarks_index; +- +- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view); +- +- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS); +- +- if (!gtk_tree_view_get_path_at_pos (tree_view, +- x, +- y - TREE_VIEW_HEADER_HEIGHT (tree_view), +- path, +- &column, +- NULL, +- &cell_y)) +- { +- row = bookmarks_index + impl->num_bookmarks - 1; +- *path = gtk_tree_path_new_from_indices (row, -1); +- *pos = GTK_TREE_VIEW_DROP_AFTER; +- return; +- } +- +- row = *gtk_tree_path_get_indices (*path); +- gtk_tree_view_get_background_area (tree_view, *path, column, &cell); +- gtk_tree_path_free (*path); +- +- if (row < bookmarks_index) +- { +- row = bookmarks_index; +- *pos = GTK_TREE_VIEW_DROP_BEFORE; +- } +- else if (row > bookmarks_index + impl->num_bookmarks - 1) +- { +- row = bookmarks_index + impl->num_bookmarks - 1; +- *pos = GTK_TREE_VIEW_DROP_AFTER; +- } +- else +- { +- if (cell_y < cell.height / 2) +- *pos = GTK_TREE_VIEW_DROP_BEFORE; +- else +- *pos = GTK_TREE_VIEW_DROP_AFTER; +- } +- +- *path = gtk_tree_path_new_from_indices (row, -1); +-} +- +-/* GtkWidget::drag-motion handler for the shortcuts list. We basically +- * implement the destination side of DnD by hand, due to limitations in +- * GtkTreeView's DnD API. +- */ +-static gboolean +-shortcuts_drag_motion_cb (GtkWidget *widget, +- GdkDragContext *context, +- gint x, +- gint y, +- guint time_, +- GtkFileChooserDefault *impl) +-{ +- GtkTreePath *path; +- GtkTreeViewDropPosition pos; +- GdkDragAction action; +- +-#if 0 +- if (gtk_drag_get_source_widget (context) == widget) +- { +- shortcuts_cancel_drag_outside_idle (impl); +- +- if (impl->shortcuts_drag_outside) +- { +- shortcuts_drag_set_delete_cursor (impl, FALSE); +- impl->shortcuts_drag_outside = FALSE; +- } +- } +-#endif +- +- if (context->suggested_action == GDK_ACTION_COPY || +- (context->actions & GDK_ACTION_COPY) != 0) +- action = GDK_ACTION_COPY; +- else if (context->suggested_action == GDK_ACTION_MOVE || +- (context->actions & GDK_ACTION_MOVE) != 0) +- action = GDK_ACTION_MOVE; +- else +- { +- action = 0; +- goto out; +- } +- +- shortcuts_compute_drop_position (impl, x, y, &path, &pos); +- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), path, pos); +- gtk_tree_path_free (path); +- +- out: +- +- g_signal_stop_emission_by_name (widget, "drag_motion"); +- +- if (action != 0) +- { +- gdk_drag_status (context, action, time_); +- return TRUE; +- } +- else +- return FALSE; +-} +- +-/* GtkWidget::drag-drop handler for the shortcuts list. */ +-static gboolean +-shortcuts_drag_drop_cb (GtkWidget *widget, +- GdkDragContext *context, +- gint x, +- gint y, +- guint time_, +- GtkFileChooserDefault *impl) +-{ +-#if 0 +- shortcuts_cancel_drag_outside_idle (impl); +-#endif +- +- g_signal_stop_emission_by_name (widget, "drag_drop"); +- return TRUE; +-} +- +-/* Parses a "text/uri-list" string and inserts its URIs as bookmarks */ +-static void +-shortcuts_drop_uris (GtkFileChooserDefault *impl, +- const char *data, +- int position) +-{ +- gchar **uris; +- gint i; +- +- uris = g_uri_list_extract_uris (data); +- +- for (i = 0; uris[i]; i++) +- { +- char *uri; +- GtkFilePath *path; +- +- uri = uris[i]; +- path = gtk_file_system_uri_to_path (impl->file_system, uri); +- +- if (path) +- { +- if (shortcuts_add_bookmark_from_path (impl, path, position)) +- position++; +- +- gtk_file_path_free (path); +- } +- else +- { +- GError *error = NULL; +- +- g_set_error (&error, +- GTK_FILE_CHOOSER_ERROR, +- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, +- _("Could not add a bookmark for '%s' " +- "because it is an invalid path name."), +- uri); +- error_adding_bookmark_dialog (impl, path, error); +- } +- } +- +- g_strfreev (uris); +-} +- +-/* Reorders the selected bookmark to the specified position */ +-static void +-shortcuts_reorder (GtkFileChooserDefault *impl, +- int new_position) +-{ +- GtkTreeIter iter; +- gpointer col_data; +- ShortcutType shortcut_type; +- GtkTreePath *path; +- int old_position; +- int bookmarks_index; +- const GtkFilePath *file_path; +- GtkFilePath *file_path_copy; +- GError *error; +- gchar *name; +- +- /* Get the selected path */ +- +- if (!shortcuts_get_selected (impl, &iter)) +- g_assert_not_reached (); +- +- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter); +- old_position = *gtk_tree_path_get_indices (path); +- gtk_tree_path_free (path); +- +- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS); +- old_position -= bookmarks_index; +- g_assert (old_position >= 0 && old_position < impl->num_bookmarks); +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_NAME, &name, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- -1); +- g_assert (col_data != NULL); +- g_assert (shortcut_type == SHORTCUT_TYPE_PATH); +- +- file_path = col_data; +- file_path_copy = gtk_file_path_copy (file_path); /* removal below will free file_path, so we need a copy */ +- +- /* Remove the path from the old position and insert it in the new one */ +- +- if (new_position > old_position) +- new_position--; +- +- if (old_position == new_position) +- goto out; +- +- error = NULL; +- if (gtk_file_system_remove_bookmark (impl->file_system, file_path_copy, &error)) +- { +- shortcuts_add_bookmark_from_path (impl, file_path_copy, new_position); +- gtk_file_system_set_bookmark_label (impl->file_system, file_path_copy, name); +- } +- else +- error_adding_bookmark_dialog (impl, file_path_copy, error); +- +- out: +- +- gtk_file_path_free (file_path_copy); +-} +- +-/* Callback used when we get the drag data for the bookmarks list. We add the +- * received URIs as bookmarks if they are folders. +- */ +-static void +-shortcuts_drag_data_received_cb (GtkWidget *widget, +- GdkDragContext *context, +- gint x, +- gint y, +- GtkSelectionData *selection_data, +- guint info, +- guint time_, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- GtkTreePath *tree_path; +- GtkTreeViewDropPosition tree_pos; +- int position; +- int bookmarks_index; +- +- impl = GTK_FILE_CHOOSER_DEFAULT (data); +- +- /* Compute position */ +- +- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS); +- +- shortcuts_compute_drop_position (impl, x, y, &tree_path, &tree_pos); +- position = *gtk_tree_path_get_indices (tree_path); +- gtk_tree_path_free (tree_path); +- +- if (tree_pos == GTK_TREE_VIEW_DROP_AFTER) +- position++; +- +- g_assert (position >= bookmarks_index); +- position -= bookmarks_index; +- +- if (selection_data->target == gdk_atom_intern_static_string ("text/uri-list")) +- shortcuts_drop_uris (impl, (const char *) selection_data->data, position); +- else if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW")) +- shortcuts_reorder (impl, position); +- +- g_signal_stop_emission_by_name (widget, "drag_data_received"); +-} +- +-/* Callback used when the selection in the shortcuts tree changes */ +-static void +-shortcuts_selection_changed_cb (GtkTreeSelection *selection, +- GtkFileChooserDefault *impl) +-{ +- bookmarks_check_remove_sensitivity (impl); +- shortcuts_check_popup_sensitivity (impl); +-} +- +-static gboolean +-shortcuts_row_separator_func (GtkTreeModel *model, +- GtkTreeIter *iter, +- gpointer data) +-{ +- ShortcutType shortcut_type; +- +- gtk_tree_model_get (model, iter, SHORTCUTS_COL_TYPE, &shortcut_type, -1); +- +- return shortcut_type == SHORTCUT_TYPE_SEPARATOR; +-} +- +-/* Since GtkTreeView has a keybinding attached to '/', we need to catch +- * keypresses before the TreeView gets them. +- */ +-static gboolean +-tree_view_keybinding_cb (GtkWidget *tree_view, +- GdkEventKey *event, +- GtkFileChooserDefault *impl) +-{ +- if ((event->keyval == GDK_slash +- || event->keyval == GDK_KP_Divide +-#ifdef G_OS_UNIX +- || event->keyval == GDK_asciitilde +-#endif +- ) && ! (event->state & (~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask ()))) +- { +- location_popup_handler (impl, event->string); +- return TRUE; +- } +- +- return FALSE; +-} +- +-/* Callback used when the file list's popup menu is detached */ +-static void +-shortcuts_popup_menu_detach_cb (GtkWidget *attach_widget, +- GtkMenu *menu) +-{ +- GtkFileChooserDefault *impl; +- +- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault"); +- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl)); +- +- impl->browse_shortcuts_popup_menu = NULL; +- impl->browse_shortcuts_popup_menu_remove_item = NULL; +- impl->browse_shortcuts_popup_menu_rename_item = NULL; +-} +- +-static void +-remove_shortcut_cb (GtkMenuItem *item, +- GtkFileChooserDefault *impl) +-{ +- remove_selected_bookmarks (impl); +-} +- +-/* Rename the selected bookmark */ +-static void +-rename_selected_bookmark (GtkFileChooserDefault *impl) +-{ +- GtkTreeIter iter; +- GtkTreePath *path; +- GtkTreeViewColumn *column; +- GtkCellRenderer *cell; +- GList *renderers; +- +- if (shortcuts_get_selected (impl, &iter)) +- { +- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter); +- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), 0); +- renderers = gtk_tree_view_column_get_cell_renderers (column); +- cell = g_list_nth_data (renderers, 1); +- g_list_free (renderers); +- g_object_set (cell, "editable", TRUE, NULL); +- gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), +- path, column, cell, TRUE); +- gtk_tree_path_free (path); +- } +-} +- +-static void +-rename_shortcut_cb (GtkMenuItem *item, +- GtkFileChooserDefault *impl) +-{ +- rename_selected_bookmark (impl); +-} +- +-/* Constructs the popup menu for the file list if needed */ +-static void +-shortcuts_build_popup_menu (GtkFileChooserDefault *impl) +-{ +- GtkWidget *item; +- +- if (impl->browse_shortcuts_popup_menu) +- return; +- +- impl->browse_shortcuts_popup_menu = gtk_menu_new (); +- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_shortcuts_popup_menu), +- impl->browse_shortcuts_tree_view, +- shortcuts_popup_menu_detach_cb); +- +- item = gtk_image_menu_item_new_with_label (_("Remove")); +- impl->browse_shortcuts_popup_menu_remove_item = item; +- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), +- gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU)); +- g_signal_connect (item, "activate", +- G_CALLBACK (remove_shortcut_cb), impl); +- gtk_widget_show (item); +- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item); +- +- item = gtk_menu_item_new_with_label (_("Rename...")); +- impl->browse_shortcuts_popup_menu_rename_item = item; +- g_signal_connect (item, "activate", +- G_CALLBACK (rename_shortcut_cb), impl); +- gtk_widget_show (item); +- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item); +- +- shortcuts_check_popup_sensitivity (impl); +-} +- +-static void +-shortcuts_update_popup_menu (GtkFileChooserDefault *impl) +-{ +- shortcuts_build_popup_menu (impl); +-} +- +-static void +-popup_position_func (GtkMenu *menu, +- gint *x, +- gint *y, +- gboolean *push_in, +- gpointer user_data); +- +-static void +-shortcuts_popup_menu (GtkFileChooserDefault *impl, +- GdkEventButton *event) +-{ +- shortcuts_update_popup_menu (impl); +- if (event) +- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu), +- NULL, NULL, NULL, NULL, +- event->button, event->time); +- else +- { +- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu), +- NULL, NULL, +- popup_position_func, impl->browse_shortcuts_tree_view, +- 0, GDK_CURRENT_TIME); +- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), +- FALSE); +- } +-} +- +-/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */ +-static gboolean +-shortcuts_popup_menu_cb (GtkWidget *widget, +- GtkFileChooserDefault *impl) +-{ +- shortcuts_popup_menu (impl, NULL); +- return TRUE; +-} +- +-/* Callback used when a button is pressed on the shortcuts list. +- * We trap button 3 to bring up a popup menu. +- */ +-static gboolean +-shortcuts_button_press_event_cb (GtkWidget *widget, +- GdkEventButton *event, +- GtkFileChooserDefault *impl) +-{ +- static gboolean in_press = FALSE; +- gboolean handled; +- +- if (in_press) +- return FALSE; +- +- if (event->button != 3) +- return FALSE; +- +- in_press = TRUE; +- handled = gtk_widget_event (impl->browse_shortcuts_tree_view, (GdkEvent *) event); +- in_press = FALSE; +- +- if (!handled) +- return FALSE; +- +- shortcuts_popup_menu (impl, event); +- return TRUE; +-} +- +-static void +-shortcuts_edited (GtkCellRenderer *cell, +- gchar *path_string, +- gchar *new_text, +- GtkFileChooserDefault *impl) +-{ +- GtkTreePath *path; +- GtkTreeIter iter; +- GtkFilePath *shortcut; +- +- g_object_set (cell, "editable", FALSE, NULL); +- +- path = gtk_tree_path_new_from_string (path_string); +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path)) +- g_assert_not_reached (); +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_DATA, &shortcut, +- -1); +- gtk_tree_path_free (path); +- +- gtk_file_system_set_bookmark_label (impl->file_system, shortcut, new_text); +-} +- +-static void +-shortcuts_editing_canceled (GtkCellRenderer *cell, +- GtkFileChooserDefault *impl) +-{ +- g_object_set (cell, "editable", FALSE, NULL); +-} +- +-/* Creates the widgets for the shortcuts and bookmarks tree */ +-static GtkWidget * +-shortcuts_list_create (GtkFileChooserDefault *impl) +-{ +- GtkWidget *swin; +- GtkTreeSelection *selection; +- GtkTreeViewColumn *column; +- GtkCellRenderer *renderer; +- +- /* Scrolled window */ +- +- swin = gtk_scrolled_window_new (NULL, NULL); +- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin), +- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); +- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin), +- GTK_SHADOW_IN); +- gtk_widget_show (swin); +- +- /* Tree */ +- +- impl->browse_shortcuts_tree_view = gtk_tree_view_new (); +-#ifdef PROFILE_FILE_CHOOSER +- g_object_set_data (G_OBJECT (impl->browse_shortcuts_tree_view), "fmq-name", "shortcuts"); +-#endif +- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event", +- G_CALLBACK (tree_view_keybinding_cb), impl); +- g_signal_connect (impl->browse_shortcuts_tree_view, "popup_menu", +- G_CALLBACK (shortcuts_popup_menu_cb), impl); +- g_signal_connect (impl->browse_shortcuts_tree_view, "button_press_event", +- G_CALLBACK (shortcuts_button_press_event_cb), impl); +- /* Accessible object name for the file chooser's shortcuts pane */ +- atk_object_set_name (gtk_widget_get_accessible (impl->browse_shortcuts_tree_view), _("Places")); +- +- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), impl->shortcuts_pane_filter_model); +- +- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), +- GDK_BUTTON1_MASK, +- shortcuts_source_targets, +- num_shortcuts_source_targets, +- GDK_ACTION_MOVE); +- +- gtk_drag_dest_set (impl->browse_shortcuts_tree_view, +- GTK_DEST_DEFAULT_ALL, +- shortcuts_dest_targets, +- num_shortcuts_dest_targets, +- GDK_ACTION_COPY | GDK_ACTION_MOVE); +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view)); +- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); +- gtk_tree_selection_set_select_function (selection, +- shortcuts_select_func, +- impl, NULL); +- +- g_signal_connect (selection, "changed", +- G_CALLBACK (shortcuts_selection_changed_cb), impl); +- +- g_signal_connect (impl->browse_shortcuts_tree_view, "row_activated", +- G_CALLBACK (shortcuts_row_activated_cb), impl); +- +- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event", +- G_CALLBACK (shortcuts_key_press_event_cb), impl); +- +- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_begin", +- G_CALLBACK (shortcuts_drag_begin_cb), impl); +- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_end", +- G_CALLBACK (shortcuts_drag_end_cb), impl); +- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_delete", +- G_CALLBACK (shortcuts_drag_data_delete_cb), impl); +- +- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_leave", +- G_CALLBACK (shortcuts_drag_leave_cb), impl); +- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_motion", +- G_CALLBACK (shortcuts_drag_motion_cb), impl); +- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_drop", +- G_CALLBACK (shortcuts_drag_drop_cb), impl); +- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_received", +- G_CALLBACK (shortcuts_drag_data_received_cb), impl); +- +- gtk_container_add (GTK_CONTAINER (swin), impl->browse_shortcuts_tree_view); +- gtk_widget_show (impl->browse_shortcuts_tree_view); +- +- /* Column */ +- +- column = gtk_tree_view_column_new (); +- /* Column header for the file chooser's shortcuts pane */ +- gtk_tree_view_column_set_title (column, _("_Places")); +- +- renderer = gtk_cell_renderer_pixbuf_new (); +- gtk_tree_view_column_pack_start (column, renderer, FALSE); +- gtk_tree_view_column_set_attributes (column, renderer, +- "pixbuf", SHORTCUTS_COL_PIXBUF, +- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE, +- NULL); +- +- renderer = gtk_cell_renderer_text_new (); +- g_signal_connect (renderer, "edited", +- G_CALLBACK (shortcuts_edited), impl); +- g_signal_connect (renderer, "editing-canceled", +- G_CALLBACK (shortcuts_editing_canceled), impl); +- gtk_tree_view_column_pack_start (column, renderer, TRUE); +- gtk_tree_view_column_set_attributes (column, renderer, +- "text", SHORTCUTS_COL_NAME, +- NULL); +- +- gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), +- shortcuts_row_separator_func, +- NULL, NULL); +- +- gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), column); +- +- return swin; +-} +- +-/* Creates the widgets for the shortcuts/bookmarks pane */ +-static GtkWidget * +-shortcuts_pane_create (GtkFileChooserDefault *impl, +- GtkSizeGroup *size_group) +-{ +- GtkWidget *vbox; +- GtkWidget *hbox; +- GtkWidget *widget; +- +- vbox = gtk_vbox_new (FALSE, 6); +- gtk_widget_show (vbox); +- +- /* Shortcuts tree */ +- +- widget = shortcuts_list_create (impl); +- gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0); +- +- /* Box for buttons */ +- +- hbox = gtk_hbox_new (TRUE, 6); +- gtk_size_group_add_widget (size_group, hbox); +- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); +- gtk_widget_show (hbox); +- +- /* Add bookmark button */ +- +- impl->browse_shortcuts_add_button = button_new (impl, +- _("_Add"), +- GTK_STOCK_ADD, +- FALSE, +- TRUE, +- G_CALLBACK (add_bookmark_button_clicked_cb)); +- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_add_button, TRUE, TRUE, 0); +- gtk_widget_set_tooltip_text (impl->browse_shortcuts_add_button, +- _("Add the selected folder to the Bookmarks")); +- +- /* Remove bookmark button */ +- +- impl->browse_shortcuts_remove_button = button_new (impl, +- _("_Remove"), +- GTK_STOCK_REMOVE, +- FALSE, +- TRUE, +- G_CALLBACK (remove_bookmark_button_clicked_cb)); +- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_remove_button, TRUE, TRUE, 0); +- gtk_widget_set_tooltip_text (impl->browse_shortcuts_remove_button, +- _("Remove the selected bookmark")); +- +- return vbox; +-} +- + /* Handles key press events on the file list, so that we can trap Enter to + * activate the default button on our own. Also, checks to see if '/' has been + * pressed. See comment by tree_view_keybinding_cb() for more details. +@@ -4056,17 +1175,6 @@ + + modifiers = gtk_accelerator_get_default_mod_mask (); + +- if ((event->keyval == GDK_slash +- || event->keyval == GDK_KP_Divide +-#ifdef G_OS_UNIX +- || event->keyval == GDK_asciitilde +-#endif +- ) && ! (event->state & (~GDK_SHIFT_MASK & modifiers))) +- { +- location_popup_handler (impl, event->string); +- return TRUE; +- } +- + if ((event->keyval == GDK_Return + || event->keyval == GDK_ISO_Enter + || event->keyval == GDK_KP_Enter +@@ -4091,474 +1199,66 @@ + return FALSE; + } + +-/* Callback used when the file list's popup menu is detached */ +-static void +-popup_menu_detach_cb (GtkWidget *attach_widget, +- GtkMenu *menu) ++static gboolean ++list_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data) + { +- GtkFileChooserDefault *impl; ++ GtkTreeView * tree = GTK_TREE_VIEW (widget); ++ GtkFileChooserDefault *impl = data; ++ GtkTreePath *path; + +- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault"); +- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl)); +- +- impl->browse_files_popup_menu = NULL; +- impl->browse_files_popup_menu_add_shortcut_item = NULL; +- impl->browse_files_popup_menu_hidden_files_item = NULL; +-} +- +-/* Callback used when the "Add to Bookmarks" menu item is activated */ +-static void +-add_to_shortcuts_cb (GtkMenuItem *item, +- GtkFileChooserDefault *impl) +-{ +- bookmarks_add_selected_folder (impl); +-} +- +-/* Callback used when the "Show Hidden Files" menu item is toggled */ +-static void +-show_hidden_toggled_cb (GtkCheckMenuItem *item, +- GtkFileChooserDefault *impl) +-{ +- g_object_set (impl, +- "show-hidden", gtk_check_menu_item_get_active (item), +- NULL); +-} +- +-/* Shows an error dialog about not being able to select a dragged file */ +-static void +-error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl, +- const GtkFilePath *path, +- GError *error) +-{ +- error_dialog (impl, +- _("Could not select file"), +- path, error); +-} +- +-static void +-file_list_drag_data_select_uris (GtkFileChooserDefault *impl, +- gchar **uris) +-{ +- int i; +- char *uri; +- GtkFileChooser *chooser = GTK_FILE_CHOOSER (impl); +- +- for (i = 1; uris[i]; i++) ++ if (event->type != GDK_BUTTON_PRESS || ++ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y, ++ &path, NULL, NULL, NULL)) + { +- GtkFilePath *path; +- +- uri = uris[i]; +- path = gtk_file_system_uri_to_path (impl->file_system, uri); +- +- if (path) +- { +- GError *error = NULL; +- +- gtk_file_chooser_default_select_path (chooser, path, &error); +- if (error) +- error_selecting_dragged_file_dialog (impl, path, error); +- +- gtk_file_path_free (path); +- } ++ return FALSE; + } +-} + +-struct FileListDragData +-{ +- GtkFileChooserDefault *impl; +- gchar **uris; +- GtkFilePath *path; +-}; ++ impl->list_press_time = event->time; ++ impl->list_press_path = path; + +-static void +-file_list_drag_data_received_get_info_cb (GtkFileSystemHandle *handle, +- const GtkFileInfo *info, +- const GError *error, +- gpointer user_data) +-{ +- gboolean cancelled = handle->cancelled; +- struct FileListDragData *data = user_data; +- GtkFileChooser *chooser = GTK_FILE_CHOOSER (data->impl); +- +- if (handle != data->impl->file_list_drag_data_received_handle) +- goto out; +- +- data->impl->file_list_drag_data_received_handle = NULL; +- +- if (cancelled || error) +- goto out; +- +- if ((data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) && +- data->uris[1] == 0 && !error && +- gtk_file_info_get_is_folder (info)) +- change_folder_and_display_error (data->impl, data->path, FALSE); +- else +- { +- GError *error = NULL; +- +- gtk_file_chooser_default_unselect_all (chooser); +- gtk_file_chooser_default_select_path (chooser, data->path, &error); +- if (error) +- error_selecting_dragged_file_dialog (data->impl, data->path, error); +- else +- browse_files_center_selected_row (data->impl); +- } +- +- if (data->impl->select_multiple) +- file_list_drag_data_select_uris (data->impl, data->uris); +- +-out: +- g_object_unref (data->impl); +- g_strfreev (data->uris); +- gtk_file_path_free (data->path); +- g_free (data); +- +- g_object_unref (handle); ++ return FALSE; + } + +-static void +-file_list_drag_data_received_cb (GtkWidget *widget, +- GdkDragContext *context, +- gint x, +- gint y, +- GtkSelectionData *selection_data, +- guint info, +- guint time_, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- GtkFileChooser *chooser; +- gchar **uris; +- char *uri; +- GtkFilePath *path; +- GError *error = NULL; +- +- impl = GTK_FILE_CHOOSER_DEFAULT (data); +- chooser = GTK_FILE_CHOOSER (data); +- +- /* Parse the text/uri-list string, navigate to the first one */ +- uris = g_uri_list_extract_uris ((const char *) selection_data->data); +- if (uris[0]) +- { +- uri = uris[0]; +- path = gtk_file_system_uri_to_path (impl->file_system, uri); +- +- if (path) +- { +- struct FileListDragData *data; +- +- data = g_new0 (struct FileListDragData, 1); +- data->impl = g_object_ref (impl); +- data->uris = uris; +- data->path = path; +- +- if (impl->file_list_drag_data_received_handle) +- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle); +- +- impl->file_list_drag_data_received_handle = +- gtk_file_system_get_info (impl->file_system, path, +- GTK_FILE_INFO_IS_FOLDER, +- file_list_drag_data_received_get_info_cb, +- data); +- goto out; +- } +- else +- { +- g_set_error (&error, +- GTK_FILE_CHOOSER_ERROR, +- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, +- _("Could not select file '%s' " +- "because it is an invalid path name."), +- uri); +- error_selecting_dragged_file_dialog (impl, NULL, error); +- } +- +- if (impl->select_multiple) +- file_list_drag_data_select_uris (impl, uris); +- } +- +- g_strfreev (uris); +- +-out: +- g_signal_stop_emission_by_name (widget, "drag_data_received"); +-} +- +-/* Don't do anything with the drag_drop signal */ + static gboolean +-file_list_drag_drop_cb (GtkWidget *widget, +- GdkDragContext *context, +- gint x, +- gint y, +- guint time_, +- GtkFileChooserDefault *impl) ++list_button_release (GtkWidget *widget, GdkEventButton *event, gpointer data) + { +- g_signal_stop_emission_by_name (widget, "drag_drop"); +- return TRUE; +-} ++ GtkTreeView * tree = GTK_TREE_VIEW (widget); ++ GtkFileChooserDefault *impl = data; ++ GtkTreePath *path = NULL; ++ gboolean retval = FALSE; + +-/* Disable the normal tree drag motion handler, it makes it look like you're +- dropping the dragged item onto a tree item */ +-static gboolean +-file_list_drag_motion_cb (GtkWidget *widget, +- GdkDragContext *context, +- gint x, +- gint y, +- guint time_, +- GtkFileChooserDefault *impl) +-{ +- g_signal_stop_emission_by_name (widget, "drag_motion"); +- return TRUE; +-} +- +-/* Constructs the popup menu for the file list if needed */ +-static void +-file_list_build_popup_menu (GtkFileChooserDefault *impl) +-{ +- GtkWidget *item; +- +- if (impl->browse_files_popup_menu) +- return; +- +- impl->browse_files_popup_menu = gtk_menu_new (); +- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_files_popup_menu), +- impl->browse_files_tree_view, +- popup_menu_detach_cb); +- +- item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks")); +- impl->browse_files_popup_menu_add_shortcut_item = item; +- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), +- gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU)); +- gtk_widget_set_sensitive (item, FALSE); +- g_signal_connect (item, "activate", +- G_CALLBACK (add_to_shortcuts_cb), impl); +- gtk_widget_show (item); +- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item); +- +- item = gtk_separator_menu_item_new (); +- gtk_widget_show (item); +- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item); +- +- item = gtk_check_menu_item_new_with_mnemonic (_("Show _Hidden Files")); +- impl->browse_files_popup_menu_hidden_files_item = item; +- g_signal_connect (item, "toggled", +- G_CALLBACK (show_hidden_toggled_cb), impl); +- gtk_widget_show (item); +- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item); +-} +- +-/* Updates the popup menu for the file list, creating it if necessary */ +-static void +-file_list_update_popup_menu (GtkFileChooserDefault *impl) +-{ +- file_list_build_popup_menu (impl); +- +- /* FIXME - handle OPERATION_MODE_SEARCH and OPERATION_MODE_RECENT */ +- +- /* The sensitivity of the Add to Bookmarks item is set in +- * bookmarks_check_add_sensitivity() +- */ +- +- g_signal_handlers_block_by_func (impl->browse_files_popup_menu_hidden_files_item, +- G_CALLBACK (show_hidden_toggled_cb), impl); +- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_hidden_files_item), +- impl->show_hidden); +- g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_hidden_files_item, +- G_CALLBACK (show_hidden_toggled_cb), impl); +-} +- +-static void +-popup_position_func (GtkMenu *menu, +- gint *x, +- gint *y, +- gboolean *push_in, +- gpointer user_data) +-{ +- GtkWidget *widget = GTK_WIDGET (user_data); +- GdkScreen *screen = gtk_widget_get_screen (widget); +- GtkRequisition req; +- gint monitor_num; +- GdkRectangle monitor; +- +- g_return_if_fail (GTK_WIDGET_REALIZED (widget)); +- +- gdk_window_get_origin (widget->window, x, y); +- +- gtk_widget_size_request (GTK_WIDGET (menu), &req); +- +- *x += (widget->allocation.width - req.width) / 2; +- *y += (widget->allocation.height - req.height) / 2; +- +- monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y); +- gtk_menu_set_monitor (menu, monitor_num); +- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); +- +- *x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width)); +- *y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height)); +- +- *push_in = FALSE; +-} +- +-static void +-file_list_popup_menu (GtkFileChooserDefault *impl, +- GdkEventButton *event) +-{ +- file_list_update_popup_menu (impl); +- if (event) +- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu), +- NULL, NULL, NULL, NULL, +- event->button, event->time); +- else ++ if (!impl->list_press_time || ++ !impl->list_press_path || ++ event->type != GDK_BUTTON_RELEASE || ++ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y, ++ &path, NULL, NULL, NULL)) + { +- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu), +- NULL, NULL, +- popup_position_func, impl->browse_files_tree_view, +- 0, GDK_CURRENT_TIME); +- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_files_popup_menu), +- FALSE); ++ goto done; + } + +-} +- +-/* Callback used for the GtkWidget::popup-menu signal of the file list */ +-static gboolean +-list_popup_menu_cb (GtkWidget *widget, +- GtkFileChooserDefault *impl) +-{ +- file_list_popup_menu (impl, NULL); +- return TRUE; +-} +- +-/* Callback used when a button is pressed on the file list. We trap button 3 to +- * bring up a popup menu. +- */ +-static gboolean +-list_button_press_event_cb (GtkWidget *widget, +- GdkEventButton *event, +- GtkFileChooserDefault *impl) +-{ +- static gboolean in_press = FALSE; +- gboolean handled; +- +- if (in_press) +- return FALSE; +- +- if (event->button != 3) +- return FALSE; +- +- in_press = TRUE; +- handled = gtk_widget_event (impl->browse_files_tree_view, (GdkEvent *) event); +- in_press = FALSE; +- +- file_list_popup_menu (impl, event); +- return TRUE; +-} +- +-/* Sets the sort column IDs for the file list based on the operation mode */ +-static void +-file_list_set_sort_column_ids (GtkFileChooserDefault *impl) +-{ +- int name_id, mtime_id; +- +- name_id = mtime_id = 0; +- +- switch (impl->operation_mode) ++ if (event->time - impl->list_press_time > LONG_CLICK_LENGTH && ++ !gtk_tree_path_compare (impl->list_press_path, path)) + { +- case OPERATION_MODE_BROWSE: +- name_id = FILE_LIST_COL_NAME; +- mtime_id = FILE_LIST_COL_MTIME; +- break; +- case OPERATION_MODE_SEARCH: +- name_id = SEARCH_MODEL_COL_PATH; +- mtime_id = SEARCH_MODEL_COL_STAT; +- break; +- case OPERATION_MODE_RECENT: +- name_id = RECENT_MODEL_COL_PATH; +- mtime_id = RECENT_MODEL_COL_INFO; +- break; ++ retval = TRUE; ++ list_row_activated (tree, path, NULL, impl); + } + +- gtk_tree_view_column_set_sort_column_id (impl->list_name_column, name_id); +- gtk_tree_view_column_set_sort_column_id (impl->list_mtime_column, mtime_id); +-} ++ done: ++ if (path) ++ gtk_tree_path_free (path); + +-static gboolean +-file_list_query_tooltip_cb (GtkWidget *widget, +- gint x, +- gint y, +- gboolean keyboard_tip, +- GtkTooltip *tooltip, +- gpointer user_data) +-{ +- GtkFileChooserDefault *impl = user_data; +- GtkTreeIter iter, child_iter; +- GtkTreePath *path = NULL; +- GtkFilePath *file_path = NULL; +- gchar *filename; ++ impl->list_press_time = 0; + +- if (impl->operation_mode == OPERATION_MODE_BROWSE) +- return FALSE; +- +- +- gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (impl->browse_files_tree_view), +- &x, &y, +- keyboard_tip, +- NULL, &path, NULL); +- +- if (!path) +- return FALSE; +- +- switch (impl->operation_mode) ++ if (impl->list_press_path) + { +- case OPERATION_MODE_SEARCH: +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path)) +- { +- gtk_tree_path_free (path); +- return FALSE; +- } +- +- search_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_PATH, &file_path, +- -1); +- break; +- +- case OPERATION_MODE_RECENT: +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path)) +- { +- gtk_tree_path_free (path); +- return FALSE; +- } +- +- recent_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_PATH, &file_path, +- -1); +- break; +- +- case OPERATION_MODE_BROWSE: +- g_assert_not_reached (); +- return FALSE; ++ gtk_tree_path_free (impl->list_press_path); ++ impl->list_press_path = NULL; + } + +- if (!file_path) +- { +- gtk_tree_path_free (path); +- return FALSE; +- } +- +- filename = gtk_file_system_path_to_filename (impl->file_system, file_path); +- gtk_tooltip_set_text (tooltip, filename); +- gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (impl->browse_files_tree_view), +- tooltip, +- path); +- +- g_free (filename); +- gtk_tree_path_free (path); +- +- return TRUE; ++ return FALSE; + } + ++ + /* Creates the widgets for the file list */ + static GtkWidget * + create_file_list (GtkFileChooserDefault *impl) +@@ -4572,7 +1272,7 @@ + + swin = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin), +- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); ++ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin), + GTK_SHADOW_IN); + +@@ -4588,41 +1288,19 @@ + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE); + gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view); + +- gtk_drag_dest_set (impl->browse_files_tree_view, +- GTK_DEST_DEFAULT_ALL, +- file_list_dest_targets, +- num_file_list_dest_targets, +- GDK_ACTION_COPY | GDK_ACTION_MOVE); +- + g_signal_connect (impl->browse_files_tree_view, "row_activated", + G_CALLBACK (list_row_activated), impl); + g_signal_connect (impl->browse_files_tree_view, "key_press_event", + G_CALLBACK (trap_activate_cb), impl); +- g_signal_connect (impl->browse_files_tree_view, "popup_menu", +- G_CALLBACK (list_popup_menu_cb), impl); + g_signal_connect (impl->browse_files_tree_view, "button_press_event", +- G_CALLBACK (list_button_press_event_cb), impl); ++ G_CALLBACK (list_button_press), impl); ++ g_signal_connect (impl->browse_files_tree_view, "button_release_event", ++ G_CALLBACK (list_button_release), impl); + +- g_signal_connect (impl->browse_files_tree_view, "drag_data_received", +- G_CALLBACK (file_list_drag_data_received_cb), impl); +- g_signal_connect (impl->browse_files_tree_view, "drag_drop", +- G_CALLBACK (file_list_drag_drop_cb), impl); +- g_signal_connect (impl->browse_files_tree_view, "drag_motion", +- G_CALLBACK (file_list_drag_motion_cb), impl); +- +- g_object_set (impl->browse_files_tree_view, "has-tooltip", TRUE, NULL); +- g_signal_connect (impl->browse_files_tree_view, "query-tooltip", +- G_CALLBACK (file_list_query_tooltip_cb), impl); +- + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); + gtk_tree_selection_set_select_function (selection, + list_select_func, + impl, NULL); +- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_files_tree_view), +- GDK_BUTTON1_MASK, +- file_list_source_targets, +- num_file_list_source_targets, +- GDK_ACTION_COPY); + + g_signal_connect (selection, "changed", + G_CALLBACK (list_selection_changed), impl); +@@ -4666,7 +1344,6 @@ + gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_SIZE); + gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column); + #endif +- + /* Modification time column */ + + column = gtk_tree_view_column_new (); +@@ -4677,276 +1354,221 @@ + gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_column_set_cell_data_func (column, renderer, + list_mtime_data_func, impl, NULL); ++ gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_MTIME); + gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column); +- impl->list_mtime_column = column; +- +- file_list_set_sort_column_ids (impl); +- + gtk_widget_show_all (swin); + + return swin; + } + +-static GtkWidget * +-create_path_bar (GtkFileChooserDefault *impl) ++static void ++up_button_clicked_cb (GtkButton *button, gpointer data) + { +- GtkWidget *path_bar; ++ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data); ++ up_folder_handler (impl); ++} + +- path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL); +- _gtk_path_bar_set_file_system (GTK_PATH_BAR (path_bar), impl->file_system); ++static void ++volume_button_clicked_cb (GtkButton *button, gpointer data) ++{ ++ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data); ++ GtkFilePath * path = g_object_get_data (G_OBJECT (button), "file-path"); + +- return path_bar; ++ change_folder_and_display_error (impl, path); + } + +-/* Creates the widgets for the files/folders pane */ + static GtkWidget * +-file_pane_create (GtkFileChooserDefault *impl, +- GtkSizeGroup *size_group) ++create_bar (GtkFileChooserDefault *impl) + { +- GtkWidget *vbox; +- GtkWidget *hbox; +- GtkWidget *widget; ++ GSList *list, *l; ++ int n; ++ GtkWidget *bar = gtk_hbox_new (FALSE, DEFAULT_SPACING); ++ GtkWidget *img; ++ GtkWidget *label; + +- vbox = gtk_vbox_new (FALSE, 6); +- gtk_widget_show (vbox); ++ /* first the Up button */ ++ img = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON); ++ gtk_widget_show (img); + +- /* Box for lists and preview */ ++ impl->up_button = gtk_button_new (); ++ gtk_container_add (GTK_CONTAINER (impl->up_button), img); ++ gtk_widget_show (impl->up_button); ++ gtk_widget_set_sensitive (impl->up_button, FALSE); ++ gtk_button_set_focus_on_click (GTK_BUTTON (impl->up_button), FALSE); + +- hbox = gtk_hbox_new (FALSE, PREVIEW_HBOX_SPACING); +- gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); +- gtk_widget_show (hbox); ++ g_signal_connect (impl->up_button, "clicked", ++ G_CALLBACK (up_button_clicked_cb), impl); ++ gtk_box_pack_start (GTK_BOX(bar), impl->up_button, FALSE, FALSE, 0); + +- /* File list */ ++ impl->num_volumes = 0; ++ list = gtk_file_system_list_volumes (impl->file_system); + +- widget = create_file_list (impl); +- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); ++ n = 0; + +- /* Preview */ ++ for (l = list; l; l = l->next, n++) ++ { ++ GtkFileSystemVolume *volume; ++ GdkPixbuf *pixbuf; ++ GtkWidget *button; ++ GtkWidget *image; ++ GtkFilePath *base_path; ++ gchar * file_name = NULL; + +- impl->preview_box = gtk_vbox_new (FALSE, 12); +- gtk_box_pack_start (GTK_BOX (hbox), impl->preview_box, FALSE, FALSE, 0); +- /* Don't show preview box initially */ ++ volume = l->data; ++ base_path = ++ gtk_file_system_volume_get_base_path (impl->file_system, volume); + +- /* Filter combo */ ++ if (impl->local_only) ++ { ++ gboolean is_local = ++ gtk_file_system_path_is_local (impl->file_system, base_path); + +- impl->filter_combo_hbox = gtk_hbox_new (FALSE, 12); ++ if (!is_local) ++ { ++ gtk_file_path_free (base_path); ++ gtk_file_system_volume_free (impl->file_system, volume); ++ continue; ++ } ++ } + +- widget = filter_create (impl); ++#if 0 ++ label_copy = ++ gtk_file_system_volume_get_display_name (impl->file_system, volume); ++#endif ++ pixbuf = ++ gtk_file_system_volume_render_icon (impl->file_system, volume, ++ GTK_WIDGET (impl), ++ impl->icon_size, NULL); + +- gtk_widget_show (widget); +- gtk_box_pack_end (GTK_BOX (impl->filter_combo_hbox), widget, FALSE, FALSE, 0); ++ button = gtk_button_new (); ++ image = gtk_image_new_from_pixbuf (pixbuf); ++ g_object_unref (G_OBJECT (pixbuf)); ++ gtk_container_add (GTK_CONTAINER (button), image); ++ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); + +- gtk_size_group_add_widget (size_group, impl->filter_combo_hbox); +- gtk_box_pack_end (GTK_BOX (vbox), impl->filter_combo_hbox, FALSE, FALSE, 0); ++ file_name = ++ gtk_file_system_path_to_filename (impl->file_system, base_path); + +- return vbox; +-} ++ if (file_name && impl->root_folder && ++ strcmp (file_name, impl->root_folder) && ++ !strncmp (file_name, impl->root_folder, strlen (file_name))) ++ { ++ /* The base path is below the root folder; we replace it with ++ * the root folder ++ */ ++ gtk_file_path_free (base_path); ++ base_path = gtk_file_system_filename_to_path (impl->file_system, ++ impl->root_folder); ++ } + +-/* Callback used when the "Browse for more folders" expander is toggled */ +-static void +-expander_changed_cb (GtkExpander *expander, +- GParamSpec *pspec, +- GtkFileChooserDefault *impl) +-{ +- impl->expand_folders = gtk_expander_get_expanded(GTK_EXPANDER (impl->save_expander)); +- update_appearance (impl); +-} ++ g_free (file_name); ++ gtk_widget_show_all (button); + +-/* Callback used when the selection changes in the save folder combo box */ +-static void +-save_folder_combo_changed_cb (GtkComboBox *combo, +- GtkFileChooserDefault *impl) +-{ +- GtkTreeIter iter; ++ g_object_set_data (G_OBJECT (button), "file-path", base_path); + +- if (impl->changing_folder) +- return; ++ g_signal_connect (button, "clicked", ++ G_CALLBACK (volume_button_clicked_cb), impl); + +- if (gtk_combo_box_get_active_iter (combo, &iter)) +- { +- GtkTreeIter child_iter; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model), +- &child_iter, +- &iter); +- shortcuts_activate_iter (impl, &child_iter); +- } +-} ++ gtk_box_pack_start (GTK_BOX(bar), button, FALSE, FALSE, 0); ++ } + +-/* Filter function used to filter out the Search item and its separator. +- * Used for the "Save in folder" combo box, so that these items do not appear in it. +- */ +-static gboolean +-shortcuts_combo_filter_func (GtkTreeModel *model, +- GtkTreeIter *iter, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- GtkTreePath *tree_path; +- gint *indices; +- int idx; +- gboolean retval; ++ impl->num_volumes = n; ++ g_slist_free (list); + +- impl = GTK_FILE_CHOOSER_DEFAULT (data); ++ label = impl->location_label = gtk_label_new (NULL); ++ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START); ++ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); ++ gtk_label_set_text (GTK_LABEL (label), impl->root_folder); ++ gtk_widget_show (label); ++ gtk_box_pack_start (GTK_BOX(bar), label, TRUE, TRUE, 0); + +- g_assert (model == GTK_TREE_MODEL (impl->shortcuts_model)); ++ gtk_widget_show (bar); + +- tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), iter); +- g_assert (tree_path != NULL); ++ return bar; ++} + +- indices = gtk_tree_path_get_indices (tree_path); +- +- retval = TRUE; +- +- if (impl->has_search) +- { +- idx = shortcuts_get_index (impl, SHORTCUTS_SEARCH); +- if (idx == indices[0]) +- retval = FALSE; +- } +- +- if (impl->has_recent) +- { +- idx = shortcuts_get_index (impl, SHORTCUTS_RECENT); +- if (idx == indices[0]) +- retval = FALSE; +- else +- { +- idx = shortcuts_get_index (impl, SHORTCUTS_RECENT_SEPARATOR); +- if (idx == indices[0]) +- retval = FALSE; +- } +- } +- +- gtk_tree_path_free (tree_path); +- +- return retval; +- } +- +-/* Creates the combo box with the save folders */ ++/* Creates the widgets for the files/folders pane */ + static GtkWidget * +-save_folder_combo_create (GtkFileChooserDefault *impl) ++file_pane_create (GtkFileChooserDefault *impl) + { +- GtkWidget *combo; +- GtkCellRenderer *cell; ++ GtkWidget *vbox; ++ GtkWidget *hbox; ++ GtkWidget *widget; ++ vbox = gtk_vbox_new (FALSE, DEFAULT_SPACING); ++ gtk_widget_show (vbox); + +- impl->shortcuts_combo_filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->shortcuts_model), NULL); +- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model), +- shortcuts_combo_filter_func, +- impl, +- NULL); ++ /* The volume bar and 'Create Folder' button */ ++ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING); ++ gtk_widget_show (hbox); ++ impl->bar = create_bar (impl); ++ gtk_widget_show_all (impl->bar); ++ gtk_box_pack_start (GTK_BOX (hbox), impl->bar, TRUE, TRUE, 0); + +- combo = g_object_new (GTK_TYPE_COMBO_BOX, +- "model", impl->shortcuts_combo_filter_model, +- "focus-on-click", FALSE, +- NULL); +- gtk_widget_show (combo); ++ /* Create Folder */ ++ widget = gtk_image_new_from_icon_name ("folder-new", GTK_ICON_SIZE_BUTTON); ++ gtk_widget_show (widget); ++ impl->browse_new_folder_button = gtk_button_new (); ++ gtk_container_add (GTK_CONTAINER (impl->browse_new_folder_button), widget); ++ gtk_button_set_focus_on_click (GTK_BUTTON (impl->browse_new_folder_button), ++ FALSE); + +- cell = gtk_cell_renderer_pixbuf_new (); +- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE); +- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell, +- "pixbuf", SHORTCUTS_COL_PIXBUF, +- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE, +- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE, +- NULL); ++ g_signal_connect (impl->browse_new_folder_button, "clicked", ++ G_CALLBACK (new_folder_button_clicked), impl); ++ gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0); + +- cell = gtk_cell_renderer_text_new (); +- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE); +- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell, +- "text", SHORTCUTS_COL_NAME, +- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE, +- NULL); ++ widget = filter_create (impl); ++ gtk_widget_hide (widget); ++ gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + +- gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), +- shortcuts_row_separator_func, +- NULL, NULL); ++ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + +- g_signal_connect (combo, "changed", +- G_CALLBACK (save_folder_combo_changed_cb), impl); ++ /* Box for lists */ ++ hbox = gtk_hbox_new (FALSE, LIST_HBOX_SPACING); ++ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); ++ gtk_widget_show (hbox); + +- return combo; ++ /* File list */ ++ ++ widget = create_file_list (impl); ++ gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); ++ ++ return vbox; + } + + /* Creates the widgets specific to Save mode */ +-static void ++static GtkWidget * + save_widgets_create (GtkFileChooserDefault *impl) + { + GtkWidget *vbox; +- GtkWidget *table; ++ GtkWidget *hbox; + GtkWidget *widget; +- GtkWidget *alignment; + +- if (impl->save_widgets != NULL) +- return; ++ vbox = gtk_vbox_new (FALSE, 0); ++ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING); + +- location_switch_to_path_bar (impl); +- +- vbox = gtk_vbox_new (FALSE, 12); +- +- table = gtk_table_new (2, 2, FALSE); +- gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); +- gtk_widget_show (table); +- gtk_table_set_row_spacings (GTK_TABLE (table), 12); +- gtk_table_set_col_spacings (GTK_TABLE (table), 12); +- +- /* Label */ +- +- widget = gtk_label_new_with_mnemonic (_("_Name:")); ++ widget = gtk_label_new (_("Name:")); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); +- gtk_table_attach (GTK_TABLE (table), widget, +- 0, 1, 0, 1, +- GTK_FILL, GTK_FILL, +- 0, 0); ++ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + +- /* Location entry */ +- + impl->location_entry = _gtk_file_chooser_entry_new (TRUE); + _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), + impl->file_system); +- gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45); ++/* gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45); */ + gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE); +- gtk_table_attach (GTK_TABLE (table), impl->location_entry, +- 1, 2, 0, 1, +- GTK_EXPAND | GTK_FILL, 0, +- 0, 0); ++ gtk_box_pack_start (GTK_BOX (hbox), impl->location_entry, ++ TRUE, TRUE, 0); ++ + gtk_widget_show (impl->location_entry); +- gtk_label_set_mnemonic_widget (GTK_LABEL (widget), impl->location_entry); + +- /* Folder combo */ +- impl->save_folder_label = gtk_label_new (NULL); +- gtk_misc_set_alignment (GTK_MISC (impl->save_folder_label), 0.0, 0.5); +- gtk_table_attach (GTK_TABLE (table), impl->save_folder_label, +- 0, 1, 1, 2, +- GTK_FILL, GTK_FILL, +- 0, 0); +- gtk_widget_show (impl->save_folder_label); ++ gtk_widget_show (hbox); ++ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + +- impl->save_folder_combo = save_folder_combo_create (impl); +- gtk_table_attach (GTK_TABLE (table), impl->save_folder_combo, +- 1, 2, 1, 2, +- GTK_EXPAND | GTK_FILL, GTK_FILL, +- 0, 0); +- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->save_folder_combo); +- +- /* Expander */ +- alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0); +- gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0); +- +- impl->save_expander = gtk_expander_new_with_mnemonic (_("_Browse for other folders")); +- gtk_container_add (GTK_CONTAINER (alignment), impl->save_expander); +- g_signal_connect (impl->save_expander, "notify::expanded", +- G_CALLBACK (expander_changed_cb), +- impl); +- gtk_widget_show_all (alignment); +- +- impl->save_widgets = vbox; +- gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0); +- gtk_box_reorder_child (GTK_BOX (impl), impl->save_widgets, 0); +- gtk_widget_show (impl->save_widgets); ++ return vbox; + } + + /* Destroys the widgets specific to Save mode */ ++/* ??? */ + static void + save_widgets_destroy (GtkFileChooserDefault *impl) + { +@@ -4956,313 +1578,17 @@ + gtk_widget_destroy (impl->save_widgets); + impl->save_widgets = NULL; + impl->location_entry = NULL; +- impl->save_folder_label = NULL; +- impl->save_folder_combo = NULL; +- impl->save_expander = NULL; + } + +-/* Turns on the path bar widget. Can be called even if we are already in that +- * mode. +- */ +-static void +-location_switch_to_path_bar (GtkFileChooserDefault *impl) +-{ +- if (impl->location_entry) +- { +- gtk_widget_destroy (impl->location_entry); +- impl->location_entry = NULL; +- } +- +- gtk_widget_hide (impl->location_entry_box); +-} +- +-/* Sets the full path of the current folder as the text in the location entry. */ +-static void +-location_entry_set_initial_text (GtkFileChooserDefault *impl) +-{ +- char *text; +- +- if (!impl->current_folder) +- return; +- +- if (gtk_file_system_path_is_local (impl->file_system, impl->current_folder)) +- { +- char *filename; +- +- filename = gtk_file_system_path_to_filename (impl->file_system, impl->current_folder); +- if (filename) +- { +- text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); +- g_free (filename); +- } +- else +- text = NULL; +- } +- else +- text = gtk_file_system_path_to_uri (impl->file_system, impl->current_folder); +- +- if (text) +- { +- gboolean need_slash; +- int len; +- +- len = strlen (text); +- need_slash = (text[len - 1] != G_DIR_SEPARATOR); +- +- if (need_slash) +- { +- char *slash_text; +- +- slash_text = g_new (char, len + 2); +- strcpy (slash_text, text); +- slash_text[len] = G_DIR_SEPARATOR; +- slash_text[len + 1] = 0; +- +- g_free (text); +- text = slash_text; +- } +- +- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), text); +- g_free (text); +- } +-} +- +-/* Turns on the location entry. Can be called even if we are already in that +- * mode. +- */ +-static void +-location_switch_to_filename_entry (GtkFileChooserDefault *impl) +-{ +- /* when in search or recent files mode, we are not showing the +- * location_entry_box container, so there's no point in switching +- * to it. +- */ +- if (impl->operation_mode == OPERATION_MODE_SEARCH || +- impl->operation_mode == OPERATION_MODE_RECENT) +- return; +- +- if (impl->location_entry) +- gtk_widget_destroy (impl->location_entry); +- +- /* Box */ +- +- gtk_widget_show (impl->location_entry_box); +- +- /* Entry */ +- +- impl->location_entry = _gtk_file_chooser_entry_new (TRUE); +- _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), +- impl->file_system); +- gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE); +- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action); +- +- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_entry, TRUE, TRUE, 0); +- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->location_label), impl->location_entry); +- +- /* Configure the entry */ +- +- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->current_folder); +- +- /* Done */ +- +- gtk_widget_show (impl->location_entry); +- gtk_widget_grab_focus (impl->location_entry); +-} +- +-/* Sets a new location mode. set_buttons determines whether the toggle button +- * for the mode will also be changed. +- */ +-static void +-location_mode_set (GtkFileChooserDefault *impl, +- LocationMode new_mode, +- gboolean set_button) +-{ +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- { +- GtkWindow *toplevel; +- GtkWidget *current_focus; +- gboolean button_active; +- gboolean switch_to_file_list; +- +- switch (new_mode) +- { +- case LOCATION_MODE_PATH_BAR: +- button_active = FALSE; +- +- /* The location_entry will disappear when we switch to path bar mode. So, +- * we'll focus the file list in that case, to avoid having a window with +- * no focused widget. +- */ +- toplevel = get_toplevel (GTK_WIDGET (impl)); +- switch_to_file_list = FALSE; +- if (toplevel) +- { +- current_focus = gtk_window_get_focus (toplevel); +- if (!current_focus || current_focus == impl->location_entry) +- switch_to_file_list = TRUE; +- } +- +- location_switch_to_path_bar (impl); +- +- if (switch_to_file_list) +- gtk_widget_grab_focus (impl->browse_files_tree_view); +- +- break; +- +- case LOCATION_MODE_FILENAME_ENTRY: +- button_active = TRUE; +- location_switch_to_filename_entry (impl); +- break; +- +- default: +- g_assert_not_reached (); +- return; +- } +- +- if (set_button) +- { +- g_signal_handlers_block_by_func (impl->location_button, +- G_CALLBACK (location_button_toggled_cb), impl); +- +- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->location_button), button_active); +- +- g_signal_handlers_unblock_by_func (impl->location_button, +- G_CALLBACK (location_button_toggled_cb), impl); +- } +- } +- +- impl->location_mode = new_mode; +-} +- +-static void +-location_toggle_popup_handler (GtkFileChooserDefault *impl) +-{ +- /* If the file entry is not visible, show it. +- * If it is visible, turn it off only if it is focused. Otherwise, switch to the entry. +- */ +- if (impl->location_mode == LOCATION_MODE_PATH_BAR) +- { +- location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY, TRUE); +- } +- else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY) +- { +- if (GTK_WIDGET_HAS_FOCUS (impl->location_entry)) +- { +- location_mode_set (impl, LOCATION_MODE_PATH_BAR, TRUE); +- } +- else +- { +- gtk_widget_grab_focus (impl->location_entry); +- } +- } +-} +- +-/* Callback used when one of the location mode buttons is toggled */ +-static void +-location_button_toggled_cb (GtkToggleButton *toggle, +- GtkFileChooserDefault *impl) +-{ +- gboolean is_active; +- LocationMode new_mode; +- +- is_active = gtk_toggle_button_get_active (toggle); +- +- if (is_active) +- { +- g_assert (impl->location_mode == LOCATION_MODE_PATH_BAR); +- new_mode = LOCATION_MODE_FILENAME_ENTRY; +- } +- else +- { +- g_assert (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY); +- new_mode = LOCATION_MODE_PATH_BAR; +- } +- +- location_mode_set (impl, new_mode, FALSE); +-} +- +-/* Creates a toggle button for the location entry. */ +-static void +-location_button_create (GtkFileChooserDefault *impl) +-{ +- GtkWidget *image; +- const char *str; +- +- image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON); +- gtk_widget_show (image); +- +- impl->location_button = g_object_new (GTK_TYPE_TOGGLE_BUTTON, +- "image", image, +- NULL); +- +- g_signal_connect (impl->location_button, "toggled", +- G_CALLBACK (location_button_toggled_cb), impl); +- +- str = _("Type a file name"); +- +- gtk_widget_set_tooltip_text (impl->location_button, str); +- atk_object_set_name (gtk_widget_get_accessible (impl->location_button), str); +-} +- + /* Creates the main hpaned with the widgets shared by Open and Save mode */ + static GtkWidget * + browse_widgets_create (GtkFileChooserDefault *impl) + { +- GtkWidget *vbox; +- GtkWidget *hbox; +- GtkWidget *hpaned; + GtkWidget *widget; +- GtkSizeGroup *size_group; + +- /* size group is used by the [+][-] buttons and the filter combo */ +- size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); +- vbox = gtk_vbox_new (FALSE, 12); ++ widget = file_pane_create (impl); + +- /* Location widgets */ +- hbox = gtk_hbox_new (FALSE, 12); +- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); +- gtk_widget_show (hbox); +- impl->browse_path_bar_hbox = hbox; +- +- location_button_create (impl); +- gtk_box_pack_start (GTK_BOX (hbox), impl->location_button, FALSE, FALSE, 0); +- +- /* Path bar */ +- +- impl->browse_path_bar = create_path_bar (impl); +- g_signal_connect (impl->browse_path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl); +- gtk_widget_show_all (impl->browse_path_bar); +- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_path_bar, TRUE, TRUE, 0); +- +- /* Create Folder */ +- impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder")); +- g_signal_connect (impl->browse_new_folder_button, "clicked", +- G_CALLBACK (new_folder_button_clicked), impl); +- gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0); +- +- /* Box for the location label and entry */ +- +- impl->location_entry_box = gtk_hbox_new (FALSE, 12); +- gtk_box_pack_start (GTK_BOX (vbox), impl->location_entry_box, FALSE, FALSE, 0); +- +- impl->location_label = gtk_label_new_with_mnemonic (_("_Location:")); +- gtk_widget_show (impl->location_label); +- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_label, FALSE, FALSE, 0); +- +- /* Paned widget */ +- hpaned = gtk_hpaned_new (); +- gtk_widget_show (hpaned); +- gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0); +- +- widget = shortcuts_pane_create (impl, size_group); +- gtk_paned_pack1 (GTK_PANED (hpaned), widget, FALSE, FALSE); +- widget = file_pane_create (impl, size_group); +- gtk_paned_pack2 (GTK_PANED (hpaned), widget, TRUE, FALSE); +- +- g_object_unref (size_group); +- +- return vbox; ++ return widget; + } + + static GObject* +@@ -5284,20 +1610,14 @@ + + gtk_widget_push_composite_child (); + +- /* Recent files manager */ +- recent_manager_update (impl); ++ /* Widgets for Save mode */ ++ impl->save_widgets = save_widgets_create (impl); ++ gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0); + +- /* Shortcuts model */ +- shortcuts_model_create (impl); +- + /* The browse widgets */ + impl->browse_widgets = browse_widgets_create (impl); + gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets, TRUE, TRUE, 0); + +- /* Alignment to hold extra widget */ +- impl->extra_align = gtk_alignment_new (0.0, 0.5, 1.0, 1.0); +- gtk_box_pack_start (GTK_BOX (impl), impl->extra_align, FALSE, FALSE, 0); +- + gtk_widget_pop_composite_child (); + update_appearance (impl); + +@@ -5306,35 +1626,7 @@ + return object; + } + +-/* Sets the extra_widget by packing it in the appropriate place */ + static void +-set_extra_widget (GtkFileChooserDefault *impl, +- GtkWidget *extra_widget) +-{ +- if (extra_widget) +- { +- g_object_ref (extra_widget); +- /* FIXME: is this right ? */ +- gtk_widget_show (extra_widget); +- } +- +- if (impl->extra_widget) +- { +- gtk_container_remove (GTK_CONTAINER (impl->extra_align), impl->extra_widget); +- g_object_unref (impl->extra_widget); +- } +- +- impl->extra_widget = extra_widget; +- if (impl->extra_widget) +- { +- gtk_container_add (GTK_CONTAINER (impl->extra_align), impl->extra_widget); +- gtk_widget_show (impl->extra_align); +- } +- else +- gtk_widget_hide (impl->extra_align); +-} +- +-static void + set_local_only (GtkFileChooserDefault *impl, + gboolean local_only) + { +@@ -5342,12 +1634,6 @@ + { + impl->local_only = local_only; + +- if (impl->shortcuts_model && impl->file_system) +- { +- shortcuts_add_volumes (impl); +- shortcuts_add_bookmarks (impl); +- } +- + if (local_only && + !gtk_file_system_path_is_local (impl->file_system, impl->current_folder)) + { +@@ -5374,21 +1660,9 @@ + volumes_changed_cb (GtkFileSystem *file_system, + GtkFileChooserDefault *impl) + { +- shortcuts_add_volumes (impl); ++ /* FIXME -- update the bar */ + } + +-/* Callback used when the set of bookmarks changes in the file system */ +-static void +-bookmarks_changed_cb (GtkFileSystem *file_system, +- GtkFileChooserDefault *impl) +-{ +- shortcuts_add_bookmarks (impl); +- +- bookmarks_check_add_sensitivity (impl); +- bookmarks_check_remove_sensitivity (impl); +- shortcuts_check_popup_sensitivity (impl); +-} +- + /* Sets the file chooser to multiple selection mode */ + static void + set_select_multiple (GtkFileChooserDefault *impl, +@@ -5408,8 +1682,6 @@ + + impl->select_multiple = select_multiple; + g_object_notify (G_OBJECT (impl), "select-multiple"); +- +- check_preview_change (impl); + } + + static void +@@ -5422,8 +1694,6 @@ + { + g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id); + impl->volumes_changed_id = 0; +- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id); +- impl->bookmarks_changed_id = 0; + g_object_unref (impl->file_system); + } + +@@ -5459,14 +1729,28 @@ + impl->volumes_changed_id = g_signal_connect (impl->file_system, "volumes-changed", + G_CALLBACK (volumes_changed_cb), + impl); +- impl->bookmarks_changed_id = g_signal_connect (impl->file_system, "bookmarks-changed", +- G_CALLBACK (bookmarks_changed_cb), +- impl); + } + + profile_end ("end", NULL); + } + ++static void ++show_new_folder_button (GtkFileChooserDefault *impl) ++{ ++ if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || ++ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) && ++ impl->show_create_folder) ++ { ++ gtk_widget_show (impl->browse_new_folder_button); ++ gtk_misc_set_alignment (GTK_MISC (impl->location_label), 0.5, 0.5); ++ } ++ else ++ { ++ gtk_widget_hide (impl->browse_new_folder_button); ++ gtk_misc_set_alignment (GTK_MISC (impl->location_label), 1.0, 0.5); ++ } ++} ++ + /* This function is basically a do_all function. + * + * It sets the visibility on all the widgets based on the current state, and +@@ -5478,33 +1762,9 @@ + if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || + impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + { +- const char *text; ++ gtk_widget_show (impl->save_widgets); ++ gtk_widget_show (impl->browse_widgets); + +- gtk_widget_hide (impl->location_button); +- save_widgets_create (impl); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) +- text = _("Save in _folder:"); +- else +- text = _("Create in _folder:"); +- +- gtk_label_set_text_with_mnemonic (GTK_LABEL (impl->save_folder_label), text); +- +- if (gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander))) +- { +- gtk_widget_set_sensitive (impl->save_folder_label, FALSE); +- gtk_widget_set_sensitive (impl->save_folder_combo, FALSE); +- gtk_widget_show (impl->browse_widgets); +- } +- else +- { +- gtk_widget_set_sensitive (impl->save_folder_label, TRUE); +- gtk_widget_set_sensitive (impl->save_folder_combo, TRUE); +- gtk_widget_hide (impl->browse_widgets); +- } +- +- gtk_widget_show (impl->browse_new_folder_button); +- + if (impl->select_multiple) + { + g_warning ("Save mode cannot be set in conjunction with multiple selection mode. " +@@ -5515,23 +1775,12 @@ + else if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || + impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) + { +- gtk_widget_show (impl->location_button); +- save_widgets_destroy (impl); ++ gtk_widget_hide (impl->save_widgets); + gtk_widget_show (impl->browse_widgets); +- location_mode_set (impl, impl->location_mode, TRUE); + } + +- if (impl->location_entry) +- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action); ++ show_new_folder_button (impl); + +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN) +- gtk_widget_hide (impl->browse_new_folder_button); +- else +- gtk_widget_show (impl->browse_new_folder_button); +- +- /* This *is* needed; we need to redraw the file list because the "sensitivity" +- * of files may change depending whether we are in a file or folder-only mode. +- */ + gtk_widget_queue_draw (impl->browse_files_tree_view); + + g_signal_emit_by_name (impl, "default-size-changed"); +@@ -5556,8 +1805,7 @@ + { + gtk_file_chooser_default_unselect_all (GTK_FILE_CHOOSER (impl)); + +- if ((action == GTK_FILE_CHOOSER_ACTION_SAVE || +- action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) ++ if ((action == GTK_FILE_CHOOSER_ACTION_SAVE || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + && impl->select_multiple) + { + g_warning ("Tried to change the file chooser action to SAVE or CREATE_FOLDER, but " +@@ -5584,29 +1832,10 @@ + set_local_only (impl, g_value_get_boolean (value)); + break; + +- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET: +- set_preview_widget (impl, g_value_get_object (value)); +- break; +- +- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE: +- impl->preview_widget_active = g_value_get_boolean (value); +- update_preview_widget_visibility (impl); +- break; +- +- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL: +- impl->use_preview_label = g_value_get_boolean (value); +- update_preview_widget_visibility (impl); +- break; +- +- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET: +- set_extra_widget (impl, g_value_get_object (value)); +- break; +- + case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE: + { + gboolean select_multiple = g_value_get_boolean (value); +- if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) ++ if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + && select_multiple) + { + g_warning ("Tried to set the file chooser to multiple selection mode, but this is " +@@ -5639,6 +1868,51 @@ + } + break; + ++ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER: ++ { ++ GtkFilePath * path; ++ gchar * new_root = g_strdup (g_value_get_string (value)); ++ ++ if (!new_root) ++ { ++ new_root = g_strdup ("/"); ++ } ++ ++ path = gtk_file_system_filename_to_path (impl->file_system, ++ new_root); ++ if (change_folder (impl, path, FALSE)) ++ { ++ g_free (impl->root_folder); ++ impl->root_folder = new_root; ++ } ++ else ++ { ++ g_warning ("Unable to set [%s] as root folder", new_root); ++ g_free (new_root); ++ } ++ ++ gtk_file_path_free (path); ++ } ++ break; ++ ++ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER: ++ { ++ gboolean show = g_value_get_boolean (value); ++ if (show != impl->show_create_folder) ++ { ++ impl->show_create_folder = show; ++ show_new_folder_button (impl); ++ } ++ } ++ break; ++ ++ /* These are not supported */ ++ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET: ++ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE: ++ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL: ++ case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET: ++ break; ++ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -5667,30 +1941,34 @@ + g_value_set_boolean (value, impl->local_only); + break; + +- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET: +- g_value_set_object (value, impl->preview_widget); ++ case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE: ++ g_value_set_boolean (value, impl->select_multiple); + break; + +- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE: +- g_value_set_boolean (value, impl->preview_widget_active); ++ case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN: ++ g_value_set_boolean (value, impl->show_hidden); + break; + +- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL: +- g_value_set_boolean (value, impl->use_preview_label); ++ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER: ++ g_value_set_string (value, impl->root_folder); + break; + +- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET: +- g_value_set_object (value, impl->extra_widget); ++ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER: ++ g_value_set_boolean (value, impl->show_create_folder); + break; + +- case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE: +- g_value_set_boolean (value, impl->select_multiple); ++ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET: ++ g_value_set_object (value, NULL); + break; + +- case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN: +- g_value_set_boolean (value, impl->show_hidden); ++ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE: ++ g_value_set_boolean (value, FALSE); + break; + ++ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL: ++ g_value_set_boolean (value, FALSE); ++ break; ++ + case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION: + g_value_set_boolean (value, impl->do_overwrite_confirmation); + break; +@@ -5723,24 +2001,12 @@ + GSList *l; + GtkFileChooserDefault *impl = (GtkFileChooserDefault *) object; + +- if (impl->extra_widget) +- { +- g_object_unref (impl->extra_widget); +- impl->extra_widget = NULL; +- } +- + if (impl->volumes_changed_id > 0) + { + g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id); + impl->volumes_changed_id = 0; + } + +- if (impl->bookmarks_changed_id > 0) +- { +- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id); +- impl->bookmarks_changed_id = 0; +- } +- + pending_select_paths_free (impl); + + /* cancel all pending operations */ +@@ -5766,23 +2032,6 @@ + impl->reload_icon_handles = NULL; + } + +- if (impl->loading_shortcuts) +- { +- for (l = impl->loading_shortcuts; l; l = l->next) +- { +- GtkFileSystemHandle *handle =l->data; +- gtk_file_system_cancel_operation (handle); +- } +- g_slist_free (impl->loading_shortcuts); +- impl->loading_shortcuts = NULL; +- } +- +- if (impl->file_list_drag_data_received_handle) +- { +- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle); +- impl->file_list_drag_data_received_handle = NULL; +- } +- + if (impl->update_current_folder_handle) + { + gtk_file_system_cancel_operation (impl->update_current_folder_handle); +@@ -5807,15 +2056,6 @@ + impl->update_from_entry_handle = NULL; + } + +- if (impl->shortcuts_activate_iter_handle) +- { +- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle); +- impl->shortcuts_activate_iter_handle = NULL; +- } +- +- search_stop_searching (impl, TRUE); +- recent_stop_loading (impl); +- + remove_settings_signal (impl, gtk_widget_get_screen (GTK_WIDGET (impl))); + + G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->dispose (object); +@@ -5828,12 +2068,7 @@ + static void + gtk_file_chooser_default_show_all (GtkWidget *widget) + { +- GtkFileChooserDefault *impl = (GtkFileChooserDefault *) widget; +- + gtk_widget_show (widget); +- +- if (impl->extra_widget) +- gtk_widget_show_all (impl->extra_widget); + } + + /* Handler for GtkWindow::set-focus; this is where we save the last-focused +@@ -5894,7 +2129,6 @@ + else + impl->icon_size = FALLBACK_ICON_SIZE; + +- shortcuts_reload_icons (impl); + gtk_widget_queue_resize (impl->browse_files_tree_view); + + profile_end ("end", NULL); +@@ -5912,8 +2146,8 @@ + + name = g_param_spec_get_name (pspec); + +- if (strcmp (name, "gtk-icon-theme-name") == 0 || +- strcmp (name, "gtk-icon-sizes") == 0) ++ if (strcmp (name, "gtk-icon-theme-name") == 0 ++ || strcmp (name, "gtk-icon-sizes") == 0) + change_icon_theme (impl); + + profile_end ("end", NULL); +@@ -5948,24 +2182,6 @@ + } + + static void +-recent_manager_update (GtkFileChooserDefault *impl) +-{ +- GtkRecentManager *manager; +- +- profile_start ("start", NULL); +- +- if (gtk_widget_has_screen (GTK_WIDGET (impl))) +- manager = gtk_recent_manager_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl))); +- else +- manager = gtk_recent_manager_get_default (); +- +- if (impl->recent_manager != manager) +- impl->recent_manager = manager; +- +- profile_end ("end", NULL); +-} +- +-static void + gtk_file_chooser_default_style_set (GtkWidget *widget, + GtkStyle *previous_style) + { +@@ -6005,7 +2221,6 @@ + + remove_settings_signal (impl, previous_screen); + check_icon_theme (impl); +- recent_manager_update (impl); + + g_signal_emit_by_name (widget, "default-size-changed"); + +@@ -6032,15 +2247,6 @@ + + impl->default_width = allocation->width; + impl->default_height = allocation->height; +- +- if (impl->preview_widget_active && +- impl->preview_widget && +- GTK_WIDGET_DRAWABLE (impl->preview_widget)) +- impl->default_width -= impl->preview_widget->allocation.width + PREVIEW_HBOX_SPACING; +- +- if (impl->extra_widget && +- GTK_WIDGET_DRAWABLE (impl->extra_widget)) +- impl->default_height -= GTK_BOX (widget)->spacing + impl->extra_widget->allocation.height; + } + + static gboolean +@@ -6094,23 +2300,18 @@ + settings_load (GtkFileChooserDefault *impl) + { + GtkFileChooserSettings *settings; +- LocationMode location_mode; + gboolean show_hidden; + gboolean expand_folders; + + settings = _gtk_file_chooser_settings_new (); + +- location_mode = _gtk_file_chooser_settings_get_location_mode (settings); + show_hidden = _gtk_file_chooser_settings_get_show_hidden (settings); + expand_folders = _gtk_file_chooser_settings_get_expand_folders (settings); + + g_object_unref (settings); + +- location_mode_set (impl, location_mode, TRUE); + gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (impl), show_hidden); + impl->expand_folders = expand_folders; +- if (impl->save_expander) +- gtk_expander_set_expanded (GTK_EXPANDER (impl->save_expander), expand_folders); + } + + static void +@@ -6120,7 +2321,6 @@ + + settings = _gtk_file_chooser_settings_new (); + +- _gtk_file_chooser_settings_set_location_mode (settings, impl->location_mode); + _gtk_file_chooser_settings_set_show_hidden (settings, gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl))); + _gtk_file_chooser_settings_set_expand_folders (settings, impl->expand_folders); + +@@ -6143,44 +2343,32 @@ + + GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->map (widget); + +- if (impl->operation_mode == OPERATION_MODE_BROWSE) ++ switch (impl->reload_state) + { +- switch (impl->reload_state) +- { +- case RELOAD_EMPTY: +- /* The user didn't explicitly give us a folder to +- * display, so we'll use the cwd +- */ +- current_working_dir = g_get_current_dir (); +- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (impl), +- current_working_dir); +- g_free (current_working_dir); +- break; +- +- case RELOAD_HAS_FOLDER: +- /* Nothing; we are already loading or loaded, so we +- * don't need to reload +- */ +- break; ++ case RELOAD_EMPTY: ++ /* The user didn't explicitly give us a folder to display, so we'll use the cwd */ ++ current_working_dir = g_get_current_dir (); ++ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (impl), current_working_dir); ++ g_free (current_working_dir); ++ break; + +- case RELOAD_WAS_UNMAPPED: +- /* Just reload the current folder; else continue +- * the pending load. +- */ +- if (impl->current_folder) +- { +- pending_select_paths_store_selection (impl); +- change_folder_and_display_error (impl, impl->current_folder, FALSE); +- } +- break; ++ case RELOAD_HAS_FOLDER: ++ /* Nothing; we are already loading or loaded, so we don't need to reload */ ++ break; + +- default: +- g_assert_not_reached (); +- } ++ case RELOAD_WAS_UNMAPPED: ++ /* Just reload the current folder; else continue the pending load. */ ++ if (impl->current_folder) ++ { ++ pending_select_paths_store_selection (impl); ++ change_folder_and_display_error (impl, impl->current_folder); ++ } ++ break; ++ ++ default: ++ g_assert_not_reached (); + } + +- bookmarks_changed_cb (impl->file_system, impl); +- + settings_load (impl); + + profile_end ("end", NULL); +@@ -6244,8 +2432,8 @@ + + #define COMPARE_DIRECTORIES \ + GtkFileChooserDefault *impl = user_data; \ +- const GtkFileInfo *info_a = _gtk_file_system_model_get_info (impl->browse_files_model, a); \ +- const GtkFileInfo *info_b = _gtk_file_system_model_get_info (impl->browse_files_model, b); \ ++ const GtkFileInfo *info_a = _gtk_file_system_model_get_info (impl->browse_files_model, a); \ ++ const GtkFileInfo *info_b = _gtk_file_system_model_get_info (impl->browse_files_model, b); \ + gboolean dir_a, dir_b; \ + \ + if (info_a) \ +@@ -6387,6 +2575,8 @@ + + profile_start ("start", NULL); + ++ GDK_THREADS_ENTER (); ++ + impl = GTK_FILE_CHOOSER_DEFAULT (data); + g_assert (impl->load_state == LOAD_PRELOAD); + g_assert (impl->load_timeout_id != 0); +@@ -6397,6 +2587,8 @@ + + load_set_model (impl); + ++ GDK_THREADS_LEAVE (); ++ + profile_end ("end", NULL); + + return FALSE; +@@ -6409,7 +2601,7 @@ + g_assert (impl->load_timeout_id == 0); + g_assert (impl->load_state != LOAD_PRELOAD); + +- impl->load_timeout_id = gdk_threads_add_timeout (MAX_LOADING_TIME, load_timeout_cb, impl); ++ impl->load_timeout_id = g_timeout_add (MAX_LOADING_TIME, load_timeout_cb, impl); + impl->load_state = LOAD_PRELOAD; + } + +@@ -6494,12 +2686,10 @@ + gpointer user_data) + { + gboolean have_hidden; +- gboolean have_filtered; + GSList *l; + struct ShowAndSelectPathsData *data = user_data; + + have_hidden = FALSE; +- have_filtered = FALSE; + + for (l = data->paths; l; l = l->next) + { +@@ -6515,12 +2705,9 @@ + if (!have_hidden) + have_hidden = gtk_file_info_get_is_hidden (info); + +- if (!have_filtered) +- have_filtered = !gtk_file_info_get_is_folder (info) && get_is_file_filtered (data->impl, path, info); +- + gtk_file_info_free (info); + +- if (have_hidden && have_filtered) ++ if (have_hidden) + break; /* we now have all the information we need */ + } + } +@@ -6534,9 +2721,6 @@ + if (have_hidden) + g_object_set (data->impl, "show-hidden", TRUE, NULL); + +- if (have_filtered) +- set_current_filter (data->impl, NULL); +- + for (l = data->paths; l; l = l->next) + { + const GtkFilePath *path; +@@ -6644,6 +2828,12 @@ + * but rather on behalf of something else like GtkFileChooserButton. In + * that case, the chooser's selection should be what the caller expects, + * as the user can't see that something else got selected. See bug #165264. ++ * ++ * Also, we don't select the first file if we are not in OPEN mode. Doing ++ * so would change the contents of the filename entry for SAVE or ++ * CREATE_FOLDER, which is undesired; in SELECT_FOLDER, we don't want to ++ * select a *different* folder from the one into which the user just ++ * navigated. + */ + if (GTK_WIDGET_MAPPED (impl) && impl->action == GTK_FILE_CHOOSER_ACTION_OPEN) + browse_files_select_first_row (impl); +@@ -6690,11 +2880,17 @@ + profile_end ("end", NULL); + } + +-static void +-stop_loading_and_clear_list_model (GtkFileChooserDefault *impl) ++/* Gets rid of the old list model and creates a new one for the current folder */ ++static gboolean ++set_list_model (GtkFileChooserDefault *impl, ++ GError **error) + { ++ g_assert (impl->current_folder != NULL); ++ ++ profile_start ("start", NULL); ++ + load_remove_timer (impl); /* This changes the state to LOAD_EMPTY */ +- ++ + if (impl->browse_files_model) + { + g_object_unref (impl->browse_files_model); +@@ -6706,21 +2902,7 @@ + g_object_unref (impl->sort_model); + impl->sort_model = NULL; + } +- +- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL); +-} + +-/* Gets rid of the old list model and creates a new one for the current folder */ +-static gboolean +-set_list_model (GtkFileChooserDefault *impl, +- GError **error) +-{ +- g_assert (impl->current_folder != NULL); +- +- profile_start ("start", NULL); +- +- stop_loading_and_clear_list_model (impl); +- + set_busy_cursor (impl, TRUE); + gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL); + +@@ -6794,17 +2976,10 @@ + struct update_chooser_entry_selected_foreach_closure closure; + const char *file_part; + +- /* no need to update the file chooser's entry if there's no entry */ +- if (impl->operation_mode == OPERATION_MODE_SEARCH || +- impl->operation_mode == OPERATION_MODE_RECENT || +- !impl->location_entry) +- return; +- + if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE + || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN +- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY))) ++ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ++ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)) + return; + + g_assert (impl->location_entry != NULL); +@@ -6822,45 +2997,39 @@ + else if (closure.num_selected == 1) + { + GtkTreeIter child_iter; +- +- if (impl->operation_mode == OPERATION_MODE_BROWSE) +- { +- const GtkFileInfo *info; +- gboolean change_entry; ++ const GtkFileInfo *info; ++ gboolean change_entry; + +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, +- &child_iter, +- &closure.first_selected_iter); ++ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, ++ &child_iter, ++ &closure.first_selected_iter); + +- info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); ++ info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); + +- /* If the cursor moved to the row of the newly created folder, +- * retrieving info will return NULL. +- */ +- if (!info) +- return; ++ /* If the cursor moved to the row of the newly created folder, ++ * retrieving info will return NULL. ++ */ ++ if (!info) ++ return; + +- g_free (impl->browse_files_last_selected_name); +- impl->browse_files_last_selected_name = +- g_strdup (gtk_file_info_get_display_name (info)); ++ g_free (impl->browse_files_last_selected_name); ++ impl->browse_files_last_selected_name = g_strdup (gtk_file_info_get_display_name (info)); + +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) +- change_entry = !gtk_file_info_get_is_folder (info); /* We don't want the name to change when clicking on a folder... */ +- else +- change_entry = TRUE; /* ... unless we are in one of the folder modes */ ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ++ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) ++ change_entry = !gtk_file_info_get_is_folder (info); /* We don't want the name to change when clicking on a folder... */ ++ else ++ change_entry = TRUE; /* ... unless we are in one of the folder modes */ + +- if (change_entry) +- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), +- impl->browse_files_last_selected_name); ++ if (change_entry) ++ _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->browse_files_last_selected_name); + +- return; +- } ++ return; + } + else + { +- g_assert (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)); ++ g_assert (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ++ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)); + + /* Multiple selection, so just clear the entry. */ + +@@ -6957,7 +3126,7 @@ + + /* get parent path and try to change the folder to that */ + if (gtk_file_system_get_parent (impl->file_system, data->path, &parent_path, NULL) && +- parent_path != NULL) ++ parent_path) + { + gtk_file_path_free (data->path); + data->path = parent_path; +@@ -6998,9 +3167,6 @@ + if (!gtk_file_info_get_is_folder (info)) + goto out; + +- if (!_gtk_path_bar_set_path (GTK_PATH_BAR (impl->browse_path_bar), data->path, data->keep_trail, NULL)) +- goto out; +- + if (impl->current_folder != data->path) + { + if (impl->current_folder) +@@ -7011,17 +3177,6 @@ + impl->reload_state = RELOAD_HAS_FOLDER; + } + +- /* Update the widgets that may trigger a folder change themselves. */ +- +- if (!impl->changing_folder) +- { +- impl->changing_folder = TRUE; +- +- shortcuts_update_current_folder (impl); +- +- impl->changing_folder = FALSE; +- } +- + /* Set the folder on the save entry */ + + if (impl->location_entry) +@@ -7041,13 +3196,7 @@ + + /* Refresh controls */ + +- shortcuts_find_current_folder (impl); +- + g_signal_emit_by_name (impl, "current-folder-changed", 0); +- +- check_preview_change (impl); +- bookmarks_check_add_sensitivity (impl); +- + g_signal_emit_by_name (impl, "selection-changed", 0); + + out: +@@ -7069,18 +3218,6 @@ + + profile_start ("start", (char *) path); + +- switch (impl->operation_mode) +- { +- case OPERATION_MODE_SEARCH: +- search_switch_to_browse_mode (impl); +- break; +- case OPERATION_MODE_RECENT: +- recent_switch_to_browse_mode (impl); +- break; +- case OPERATION_MODE_BROWSE: +- break; +- } +- + g_assert (path != NULL); + + if (impl->local_only && +@@ -7123,10 +3260,6 @@ + { + GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); + +- if (impl->operation_mode == OPERATION_MODE_SEARCH || +- impl->operation_mode == OPERATION_MODE_RECENT) +- return NULL; +- + if (impl->reload_state == RELOAD_EMPTY) + { + char *current_working_dir; +@@ -7151,8 +3284,8 @@ + { + GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); + +- g_return_if_fail (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER); ++ g_return_if_fail (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ++ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER); + + pending_select_paths_free (impl); + _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), name); +@@ -7187,14 +3320,10 @@ + return FALSE; + + if (!parent_path) +- return _gtk_file_chooser_set_current_folder_path (chooser, path, error); ++ return _gtk_file_chooser_set_current_folder_path (chooser, path, error); + +- if (impl->operation_mode == OPERATION_MODE_SEARCH || +- impl->operation_mode == OPERATION_MODE_RECENT || +- impl->load_state == LOAD_EMPTY) +- { +- same_path = FALSE; +- } ++ if (impl->load_state == LOAD_EMPTY) ++ same_path = FALSE; + else + { + g_assert (impl->current_folder != NULL); +@@ -7289,17 +3418,6 @@ + gtk_file_chooser_default_select_all (GtkFileChooser *chooser) + { + GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); +- +- if (impl->operation_mode == OPERATION_MODE_SEARCH || +- impl->operation_mode == OPERATION_MODE_RECENT) +- { +- GtkTreeSelection *selection; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- gtk_tree_selection_select_all (selection); +- return; +- } +- + if (impl->select_multiple) + gtk_tree_model_foreach (GTK_TREE_MODEL (impl->sort_model), + maybe_select, impl); +@@ -7340,9 +3458,8 @@ + + g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE + || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN +- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)); ++ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ++ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + + chooser_entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry); + +@@ -7439,14 +3556,7 @@ + struct get_paths_closure info; + GtkWindow *toplevel; + GtkWidget *current_focus; +- gboolean file_list_seen; + +- if (impl->operation_mode == OPERATION_MODE_SEARCH) +- return search_get_selected_paths (impl); +- +- if (impl->operation_mode == OPERATION_MODE_RECENT) +- return recent_get_selected_paths (impl); +- + info.impl = impl; + info.result = NULL; + info.path_from_entry = NULL; +@@ -7457,14 +3567,12 @@ + else + current_focus = NULL; + +- file_list_seen = FALSE; + if (current_focus == impl->browse_files_tree_view) + { + GtkTreeSelection *selection; + + file_list: + +- file_list_seen = TRUE; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); + gtk_tree_selection_selected_foreach (selection, get_paths_foreach, &info); + +@@ -7499,12 +3607,8 @@ + return NULL; + } + +- if (info.path_from_entry) +- info.result = g_slist_prepend (info.result, info.path_from_entry); +- else if (!file_list_seen) +- goto file_list; +- else +- return NULL; ++ g_assert (info.path_from_entry != NULL); ++ info.result = g_slist_prepend (info.result, info.path_from_entry); + } + else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view) + goto file_list; +@@ -7512,9 +3616,9 @@ + goto file_entry; + else + { +- /* The focus is on a dialog's action area button or something else */ +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) ++ /* The focus is on a dialog's action area button or something else */ ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ++ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + goto file_entry; + else + goto file_list; +@@ -7533,17 +3637,6 @@ + return g_slist_reverse (info.result); + } + +-static GtkFilePath * +-gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser) +-{ +- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); +- +- if (impl->preview_path) +- return gtk_file_path_copy (impl->preview_path); +- else +- return NULL; +-} +- + static GtkFileSystem * + gtk_file_chooser_default_get_file_system (GtkFileChooser *chooser) + { +@@ -7558,9 +3651,9 @@ + gboolean show) + { + if (show) +- gtk_widget_show (impl->filter_combo_hbox); ++ gtk_widget_show (impl->filter_combo); + else +- gtk_widget_hide (impl->filter_combo_hbox); ++ gtk_widget_hide (impl->filter_combo); + } + + static void +@@ -7588,7 +3683,7 @@ + if (!g_slist_find (impl->filters, impl->current_filter)) + set_current_filter (impl, filter); + +- show_filters (impl, TRUE); ++ show_filters (impl, g_slist_length (impl->filters) > 1); + } + + static void +@@ -7627,8 +3722,7 @@ + + g_object_unref (filter); + +- if (!impl->filters) +- show_filters (impl, FALSE); ++ show_filters (impl, g_slist_length (impl->filters) > 1); + } + + static GSList * +@@ -7639,234 +3733,6 @@ + return g_slist_copy (impl->filters); + } + +-/* Returns the position in the shortcuts tree where the nth specified shortcut would appear */ +-static int +-shortcuts_get_pos_for_shortcut_folder (GtkFileChooserDefault *impl, +- int pos) +-{ +- return pos + shortcuts_get_index (impl, SHORTCUTS_SHORTCUTS); +-} +- +-struct AddShortcutData +-{ +- GtkFileChooserDefault *impl; +- GtkFilePath *path; +-}; +- +-static void +-add_shortcut_get_info_cb (GtkFileSystemHandle *handle, +- const GtkFileInfo *info, +- const GError *error, +- gpointer user_data) +-{ +- int pos; +- gboolean cancelled = handle->cancelled; +- struct AddShortcutData *data = user_data; +- +- if (!g_slist_find (data->impl->loading_shortcuts, handle)) +- goto out; +- +- data->impl->loading_shortcuts = g_slist_remove (data->impl->loading_shortcuts, handle); +- +- if (cancelled || error || !gtk_file_info_get_is_folder (info)) +- goto out; +- +- pos = shortcuts_get_pos_for_shortcut_folder (data->impl, data->impl->num_shortcuts); +- +- shortcuts_insert_path (data->impl, pos, SHORTCUT_TYPE_PATH, NULL, data->path, NULL, FALSE, SHORTCUTS_SHORTCUTS); +- +-out: +- g_object_unref (data->impl); +- gtk_file_path_free (data->path); +- g_free (data); +- +- g_object_unref (handle); +-} +- +-static gboolean +-gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser, +- const GtkFilePath *path, +- GError **error) +-{ +- GtkFileSystemHandle *handle; +- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); +- struct AddShortcutData *data; +- GSList *l; +- int pos; +- +- /* Avoid adding duplicates */ +- pos = shortcut_find_position (impl, path); +- if (pos >= 0 && pos < shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR)) +- { +- gchar *uri; +- +- uri = gtk_file_system_path_to_uri (impl->file_system, path); +- /* translators, "Shortcut" means "Bookmark" here */ +- g_set_error (error, +- GTK_FILE_CHOOSER_ERROR, +- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS, +- _("Shortcut %s already exists"), +- uri); +- g_free (uri); +- +- return FALSE; +- } +- +- for (l = impl->loading_shortcuts; l; l = l->next) +- { +- GtkFileSystemHandle *h = l->data; +- GtkFilePath *p; +- +- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key"); +- if (p && !gtk_file_path_compare (path, p)) +- { +- gchar *uri; +- +- uri = gtk_file_system_path_to_uri (impl->file_system, path); +- g_set_error (error, +- GTK_FILE_CHOOSER_ERROR, +- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS, +- _("Shortcut %s already exists"), +- uri); +- g_free (uri); +- +- return FALSE; +- } +- } +- +- data = g_new0 (struct AddShortcutData, 1); +- data->impl = g_object_ref (impl); +- data->path = gtk_file_path_copy (path); +- +- handle = gtk_file_system_get_info (impl->file_system, path, +- GTK_FILE_INFO_IS_FOLDER, +- add_shortcut_get_info_cb, data); +- +- if (!handle) +- return FALSE; +- +- impl->loading_shortcuts = g_slist_append (impl->loading_shortcuts, handle); +- g_object_set_data (G_OBJECT (handle), "add-shortcut-path-key", data->path); +- +- return TRUE; +-} +- +-static gboolean +-gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, +- const GtkFilePath *path, +- GError **error) +-{ +- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); +- int pos; +- GtkTreeIter iter; +- GSList *l; +- char *uri; +- int i; +- +- for (l = impl->loading_shortcuts; l; l = l->next) +- { +- GtkFileSystemHandle *h = l->data; +- GtkFilePath *p; +- +- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key"); +- if (p && !gtk_file_path_compare (path, p)) +- { +- impl->loading_shortcuts = g_slist_remove (impl->loading_shortcuts, h); +- gtk_file_system_cancel_operation (h); +- return TRUE; +- } +- } +- +- if (impl->num_shortcuts == 0) +- goto out; +- +- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0); +- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos)) +- g_assert_not_reached (); +- +- for (i = 0; i < impl->num_shortcuts; i++) +- { +- gpointer col_data; +- ShortcutType shortcut_type; +- GtkFilePath *shortcut; +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- -1); +- g_assert (col_data != NULL); +- g_assert (shortcut_type == SHORTCUT_TYPE_PATH); +- +- shortcut = col_data; +- if (gtk_file_path_compare (shortcut, path) == 0) +- { +- shortcuts_remove_rows (impl, pos + i, 1); +- impl->num_shortcuts--; +- return TRUE; +- } +- +- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter)) +- g_assert_not_reached (); +- } +- +- out: +- +- uri = gtk_file_system_path_to_uri (impl->file_system, path); +- /* translators, "Shortcut" means "Bookmark" here */ +- g_set_error (error, +- GTK_FILE_CHOOSER_ERROR, +- GTK_FILE_CHOOSER_ERROR_NONEXISTENT, +- _("Shortcut %s does not exist"), +- uri); +- g_free (uri); +- +- return FALSE; +-} +- +-static GSList * +-gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser) +-{ +- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); +- int pos; +- GtkTreeIter iter; +- int i; +- GSList *list; +- +- if (impl->num_shortcuts == 0) +- return NULL; +- +- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0); +- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos)) +- g_assert_not_reached (); +- +- list = NULL; +- +- for (i = 0; i < impl->num_shortcuts; i++) +- { +- gpointer col_data; +- ShortcutType shortcut_type; +- GtkFilePath *shortcut; +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- -1); +- g_assert (col_data != NULL); +- g_assert (shortcut_type == SHORTCUT_TYPE_PATH); +- +- shortcut = col_data; +- list = g_slist_prepend (list, gtk_file_path_copy (shortcut)); +- +- if (i != impl->num_shortcuts - 1) +- { +- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter)) +- g_assert_not_reached (); +- } +- } +- +- return g_slist_reverse (list); +-} +- + /* Guesses a size based upon font sizes */ + static void + find_good_size_from_style (GtkWidget *widget, +@@ -7911,25 +3777,9 @@ + gint *default_height) + { + GtkFileChooserDefault *impl; +- GtkRequisition req; + + impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed); + find_good_size_from_style (GTK_WIDGET (chooser_embed), default_width, default_height); +- +- if (impl->preview_widget_active && +- impl->preview_widget && +- GTK_WIDGET_VISIBLE (impl->preview_widget)) +- { +- gtk_widget_size_request (impl->preview_box, &req); +- *default_width += PREVIEW_HBOX_SPACING + req.width; +- } +- +- if (impl->extra_widget && +- GTK_WIDGET_VISIBLE (impl->extra_widget)) +- { +- gtk_widget_size_request (impl->extra_align, &req); +- *default_height += GTK_BOX (chooser_embed)->spacing + req.height; +- } + } + + static gboolean +@@ -7940,8 +3790,7 @@ + impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed); + + return (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander))); ++ impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + } + + struct switch_folder_closure { +@@ -7988,7 +3837,7 @@ + + g_assert (closure.path && closure.num_selected == 1); + +- change_folder_and_display_error (impl, closure.path, FALSE); ++ change_folder_and_display_error (impl, closure.path); + } + + /* Gets the GtkFileInfo for the selected row in the file list; assumes single +@@ -8187,24 +4036,7 @@ + } + } + +-/* Gives the focus to the browse tree view only if it is visible */ + static void +-focus_browse_tree_view_if_possible (GtkFileChooserDefault *impl) +-{ +- gboolean do_focus; +- +- if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- && !gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander))) +- do_focus = FALSE; +- else +- do_focus = TRUE; +- +- if (do_focus) +- gtk_widget_grab_focus (impl->browse_files_tree_view); +-} +- +-static void + action_create_folder_cb (GtkFileSystemHandle *handle, + const GtkFilePath *path, + const GError *error, +@@ -8300,7 +4132,7 @@ + else + { + /* This will display an error, which is what we want */ +- change_folder_and_display_error (data->impl, data->parent_path, FALSE); ++ change_folder_and_display_error (data->impl, data->parent_path); + } + + out: +@@ -8378,51 +4210,7 @@ + g_object_unref (handle); + } + +-static void +-paste_text_received (GtkClipboard *clipboard, +- const gchar *text, +- GtkFileChooserDefault *impl) +-{ +- GtkFilePath *path; + +- if (!text) +- return; +- +- path = gtk_file_system_uri_to_path (impl->file_system, text); +- if (!path) +- { +- if (!g_path_is_absolute (text)) +- { +- location_popup_handler (impl, text); +- return; +- } +- +- path = gtk_file_system_filename_to_path (impl->file_system, text); +- if (!path) +- { +- location_popup_handler (impl, text); +- return; +- } +- } +- +- if (!gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (impl), path, NULL)) +- location_popup_handler (impl, text); +- +- gtk_file_path_free (path); +-} +- +-/* Handler for the "location-popup-on-paste" keybinding signal */ +-static void +-location_popup_on_paste_handler (GtkFileChooserDefault *impl) +-{ +- GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl), +- GDK_SELECTION_CLIPBOARD); +- gtk_clipboard_request_text (clipboard, +- (GtkClipboardTextReceivedFunc) paste_text_received, +- impl); +-} +- +- + /* Implementation for GtkFileChooserEmbed::should_respond() */ + static gboolean + gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) +@@ -8469,12 +4257,6 @@ + + g_assert (impl->action >= GTK_FILE_CHOOSER_ACTION_OPEN && impl->action <= GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER); + +- if (impl->operation_mode == OPERATION_MODE_SEARCH) +- return search_should_respond (impl); +- +- if (impl->operation_mode == OPERATION_MODE_RECENT) +- return recent_should_respond (impl); +- + selection_check (impl, &num_selected, &all_files, &all_folders); + + if (num_selected > 2) +@@ -8533,9 +4315,8 @@ + + g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE + || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN +- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)); ++ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ++ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + + entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry); + check_save_entry (impl, &path, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder); +@@ -8548,14 +4329,14 @@ + error = NULL; + if (is_folder) + { +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ++ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) + { +- change_folder_and_display_error (impl, path, TRUE); ++ change_folder_and_display_error (impl, path); + retval = FALSE; + } +- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) ++ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ++ || GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + { + /* The folder already exists, so we do not need to create it. + * Just respond to terminate the dialog. +@@ -8598,37 +4379,13 @@ + gtk_file_path_free (path); + return retval; + } +- else if (impl->toplevel_last_focus_widget == impl->browse_shortcuts_tree_view) +- { +- /* The focus is on a dialog's action area button, *and* the widget that +- * was focused immediately before it is the shortcuts list. Switch to the +- * selected shortcut and tell the caller not to respond. +- */ +- GtkTreeIter iter; +- +- if (shortcuts_get_selected (impl, &iter)) +- { +- shortcuts_activate_iter (impl, &iter); +- +- focus_browse_tree_view_if_possible (impl); +- } +- else +- goto file_list; +- +- return FALSE; +- } + else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view) + { + /* The focus is on a dialog's action area button, *and* the widget that +- * was focused immediately before it is the file list. ++ * was focused immediately before it is the file list. + */ + goto file_list; + } +- else if (impl->operation_mode == OPERATION_MODE_SEARCH && impl->toplevel_last_focus_widget == impl->search_entry) +- { +- search_entry_activate_cb (GTK_ENTRY (impl->search_entry), impl); +- return FALSE; +- } + else if (impl->location_entry && impl->toplevel_last_focus_widget == impl->location_entry) + { + /* The focus is on a dialog's action area button, *and* the widget that +@@ -8657,17 +4414,16 @@ + + impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed); + +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ++ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) + { +- if (impl->location_mode == LOCATION_MODE_PATH_BAR) + widget = impl->browse_files_tree_view; +- else +- widget = impl->location_entry; + } +- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- widget = impl->location_entry; ++ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ++ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) ++ { ++ widget = impl->location_entry; ++ } + else + { + g_assert_not_reached (); +@@ -8678,1475 +4434,7 @@ + gtk_widget_grab_focus (widget); + } + +-/* Callback used from gtk_tree_selection_selected_foreach(); gets the selected GtkFilePaths */ + static void +-search_selected_foreach_get_path_cb (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *iter, +- gpointer data) +-{ +- GSList **list; +- const GtkFilePath *file_path; +- GtkFilePath *file_path_copy; +- +- list = data; +- +- gtk_tree_model_get (model, iter, SEARCH_MODEL_COL_PATH, &file_path, -1); +- file_path_copy = gtk_file_path_copy (file_path); +- *list = g_slist_prepend (*list, file_path_copy); +-} +- +-/* Constructs a list of the selected paths in search mode */ +-static GSList * +-search_get_selected_paths (GtkFileChooserDefault *impl) +-{ +- GSList *result; +- GtkTreeSelection *selection; +- +- result = NULL; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- gtk_tree_selection_selected_foreach (selection, search_selected_foreach_get_path_cb, &result); +- result = g_slist_reverse (result); +- +- return result; +-} +- +-/* Called from ::should_respond(). We return whether there are selected files +- * in the search list. +- */ +-static gboolean +-search_should_respond (GtkFileChooserDefault *impl) +-{ +- GtkTreeSelection *selection; +- +- g_assert (impl->operation_mode == OPERATION_MODE_SEARCH); +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- return (gtk_tree_selection_count_selected_rows (selection) != 0); +-} +- +-struct SearchHitInsertRequest +-{ +- GtkFileChooserDefault *impl; +- GtkFilePath *path; +- GtkTreeRowReference *row_ref; +-}; +- +-static void +-search_hit_get_info_cb (GtkFileSystemHandle *handle, +- const GtkFileInfo *info, +- const GError *error, +- gpointer data) +-{ +- gboolean cancelled = handle->cancelled; +- GdkPixbuf *pixbuf = NULL; +- GtkTreePath *path; +- GtkTreeIter iter; +- GtkFileSystemHandle *model_handle; +- gboolean is_folder = FALSE; +- char *mime_type; +- char *display_name; +- struct SearchHitInsertRequest *request = data; +- +- if (!request->impl->search_model) +- goto out; +- +- path = gtk_tree_row_reference_get_path (request->row_ref); +- if (!path) +- goto out; +- +- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->search_model), +- &iter, path); +- gtk_tree_path_free (path); +- +- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->search_model), &iter, +- SEARCH_MODEL_COL_HANDLE, &model_handle, +- -1); +- if (handle != model_handle) +- goto out; +- +- /* set the handle to NULL in the model */ +- gtk_list_store_set (request->impl->search_model, &iter, +- SEARCH_MODEL_COL_HANDLE, NULL, +- -1); +- +- if (cancelled) +- goto out; +- +- if (!info) +- { +- gtk_list_store_remove (request->impl->search_model, &iter); +- goto out; +- } +- +- display_name = g_strdup (gtk_file_info_get_display_name (info)); +- mime_type = g_strdup (gtk_file_info_get_mime_type (info)); +- is_folder = gtk_file_info_get_is_folder (info); +- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl), +- request->impl->icon_size, NULL); +- +- gtk_list_store_set (request->impl->search_model, &iter, +- SEARCH_MODEL_COL_PIXBUF, pixbuf, +- SEARCH_MODEL_COL_DISPLAY_NAME, display_name, +- SEARCH_MODEL_COL_MIME_TYPE, mime_type, +- SEARCH_MODEL_COL_IS_FOLDER, is_folder, +- -1); +- +- if (pixbuf) +- g_object_unref (pixbuf); +- +-out: +- g_object_unref (request->impl); +- gtk_file_path_free (request->path); +- gtk_tree_row_reference_free (request->row_ref); +- g_free (request); +- +- g_object_unref (handle); +-} +- +-/* Adds one hit from the search engine to the search_model */ +-static void +-search_add_hit (GtkFileChooserDefault *impl, +- gchar *uri) +-{ +- GtkFilePath *path; +- char *filename; +- char *tmp; +- char *collation_key; +- struct stat statbuf; +- struct stat *statbuf_copy; +- GtkTreeIter iter; +- GtkTreePath *p; +- GtkFileSystemHandle *handle; +- struct SearchHitInsertRequest *request; +- +- path = gtk_file_system_uri_to_path (impl->file_system, uri); +- if (!path) +- return; +- +- filename = gtk_file_system_path_to_filename (impl->file_system, path); +- if (!filename) +- { +- gtk_file_path_free (path); +- return; +- } +- +- if (stat (filename, &statbuf) != 0) +- { +- gtk_file_path_free (path); +- g_free (filename); +- return; +- } +- +- statbuf_copy = g_new (struct stat, 1); +- *statbuf_copy = statbuf; +- +- tmp = g_filename_display_name (filename); +- collation_key = g_utf8_collate_key_for_filename (tmp, -1); +- g_free (tmp); +- +- request = g_new0 (struct SearchHitInsertRequest, 1); +- request->impl = g_object_ref (impl); +- request->path = gtk_file_path_copy (path); +- +- gtk_list_store_append (impl->search_model, &iter); +- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->search_model), &iter); +- +- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->search_model), p); +- gtk_tree_path_free (p); +- +- handle = gtk_file_system_get_info (impl->file_system, path, +- GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_ICON | GTK_FILE_INFO_MIME_TYPE | GTK_FILE_INFO_DISPLAY_NAME, +- search_hit_get_info_cb, +- request); +- +- gtk_list_store_set (impl->search_model, &iter, +- SEARCH_MODEL_COL_PATH, path, +- SEARCH_MODEL_COL_COLLATION_KEY, collation_key, +- SEARCH_MODEL_COL_STAT, statbuf_copy, +- SEARCH_MODEL_COL_HANDLE, handle, +- -1); +-} +- +-/* Callback used from GtkSearchEngine when we get new hits */ +-static void +-search_engine_hits_added_cb (GtkSearchEngine *engine, +- GList *hits, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- GList *l; +- +- impl = GTK_FILE_CHOOSER_DEFAULT (data); +- +- for (l = hits; l; l = l->next) +- search_add_hit (impl, (gchar*)l->data); +-} +- +-/* Callback used from GtkSearchEngine when the query is done running */ +-static void +-search_engine_finished_cb (GtkSearchEngine *engine, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- +- impl = GTK_FILE_CHOOSER_DEFAULT (data); +- +-#if 0 +- /* EB: setting the model here will avoid loads of row events, +- * but it'll make the search look like blocked. +- */ +- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), +- GTK_TREE_MODEL (impl->search_model_filter)); +-#endif +- +- /* FMQ: if search was empty, say that we got no hits */ +- set_busy_cursor (impl, FALSE); +-} +- +-/* Displays a generic error when we cannot create a GtkSearchEngine. +- * It would be better if _gtk_search_engine_new() gave us a GError +- * with a better message, but it doesn't do that right now. +- */ +-static void +-search_error_could_not_create_client (GtkFileChooserDefault *impl) +-{ +- error_message (impl, +- _("Could not start the search process"), +- _("The program was not able to create a connection to the indexer " +- "daemon. Please make sure it is running.")); +-} +- +-static void +-search_engine_error_cb (GtkSearchEngine *engine, +- const gchar *message, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- +- impl = GTK_FILE_CHOOSER_DEFAULT (data); +- +- search_stop_searching (impl, TRUE); +- error_message (impl, _("Could not send the search request"), message); +- +- set_busy_cursor (impl, FALSE); +-} +- +-/* Frees the data in the search_model */ +-static void +-search_clear_model (GtkFileChooserDefault *impl, +- gboolean remove_from_treeview) +-{ +- GtkTreeModel *model; +- GtkTreeIter iter; +- +- if (!impl->search_model) +- return; +- +- model = GTK_TREE_MODEL (impl->search_model); +- +- if (gtk_tree_model_get_iter_first (model, &iter)) +- do +- { +- GtkFilePath *path; +- gchar *display_name; +- gchar *collation_key; +- struct stat *statbuf; +- GtkFileSystemHandle *handle; +- +- gtk_tree_model_get (model, &iter, +- SEARCH_MODEL_COL_PATH, &path, +- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name, +- SEARCH_MODEL_COL_COLLATION_KEY, &collation_key, +- SEARCH_MODEL_COL_STAT, &statbuf, +- SEARCH_MODEL_COL_HANDLE, &handle, +- -1); +- +- if (handle) +- gtk_file_system_cancel_operation (handle); +- +- gtk_file_path_free (path); +- g_free (display_name); +- g_free (collation_key); +- g_free (statbuf); +- } +- while (gtk_tree_model_iter_next (model, &iter)); +- +- g_object_unref (impl->search_model); +- impl->search_model = NULL; +- +- g_object_unref (impl->search_model_filter); +- impl->search_model_filter = NULL; +- +- g_object_unref (impl->search_model_sort); +- impl->search_model_sort = NULL; +- +- if (remove_from_treeview) +- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL); +-} +- +-/* Stops any ongoing searches; does not touch the search_model */ +-static void +-search_stop_searching (GtkFileChooserDefault *impl, +- gboolean remove_query) +-{ +- if (remove_query && impl->search_query) +- { +- g_object_unref (impl->search_query); +- impl->search_query = NULL; +- } +- +- if (impl->search_engine) +- { +- _gtk_search_engine_stop (impl->search_engine); +- +- g_object_unref (impl->search_engine); +- impl->search_engine = NULL; +- } +-} +- +-/* Stops any pending searches, clears the file list, and switches back to OPERATION_MODE_BROWSE */ +-static void +-search_switch_to_browse_mode (GtkFileChooserDefault *impl) +-{ +- g_assert (impl->operation_mode != OPERATION_MODE_BROWSE); +- +- search_stop_searching (impl, FALSE); +- search_clear_model (impl, TRUE); +- +- gtk_widget_destroy (impl->search_hbox); +- impl->search_hbox = NULL; +- impl->search_entry = NULL; +- +- gtk_widget_show (impl->browse_path_bar); +- gtk_widget_show (impl->browse_new_folder_button); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- { +- gtk_widget_show (impl->location_button); +- +- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY) +- gtk_widget_show (impl->location_entry_box); +- } +- +- impl->operation_mode = OPERATION_MODE_BROWSE; +- +- file_list_set_sort_column_ids (impl); +-} +- +-/* Sort callback from the path column */ +-static gint +-search_column_path_sort_func (GtkTreeModel *model, +- GtkTreeIter *a, +- GtkTreeIter *b, +- gpointer user_data) +-{ +- GtkFileChooserDefault *impl = user_data; +- GtkTreeIter child_a, child_b; +- const char *collation_key_a, *collation_key_b; +- gboolean is_folder_a, is_folder_b; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a); +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b); +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_a, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_a, +- SEARCH_MODEL_COL_COLLATION_KEY, &collation_key_a, +- -1); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_b, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_b, +- SEARCH_MODEL_COL_COLLATION_KEY, &collation_key_b, +- -1); +- +- if (!collation_key_a) +- return 1; +- +- if (!collation_key_b) +- return -1; +- +- /* always show folders first */ +- if (is_folder_a != is_folder_b) +- return is_folder_a ? 1 : -1; +- +- return strcmp (collation_key_a, collation_key_b); +-} +- +-/* Sort callback from the modification time column */ +-static gint +-search_column_mtime_sort_func (GtkTreeModel *model, +- GtkTreeIter *a, +- GtkTreeIter *b, +- gpointer user_data) +-{ +- GtkFileChooserDefault *impl = user_data; +- GtkTreeIter child_a, child_b; +- const struct stat *statbuf_a, *statbuf_b; +- gboolean is_folder_a, is_folder_b; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a); +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b); +- +- /* Note that although we store a whole struct stat in the model, we only +- * compare the mtime here. If we add another column relative to a struct stat +- * (e.g. a file size column), we'll want another sort callback similar to this +- * one as well. +- */ +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_a, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_a, +- SEARCH_MODEL_COL_STAT, &statbuf_a, +- -1); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_b, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_b, +- SEARCH_MODEL_COL_STAT, &statbuf_b, +- -1); +- +- if (!statbuf_a) +- return 1; +- +- if (!statbuf_b) +- return -1; +- +- if (is_folder_a != is_folder_b) +- return is_folder_a ? 1 : -1; +- +- if (statbuf_a->st_mtime < statbuf_b->st_mtime) +- return -1; +- else if (statbuf_a->st_mtime > statbuf_b->st_mtime) +- return 1; +- else +- return 0; +-} +- +-static gboolean +-search_get_is_filtered (GtkFileChooserDefault *impl, +- const GtkFilePath *path, +- const gchar *display_name, +- const gchar *mime_type) +-{ +- GtkFileFilterInfo filter_info; +- GtkFileFilterFlags needed; +- gboolean result; +- +- if (!impl->current_filter) +- return FALSE; +- +- filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE; +- needed = gtk_file_filter_get_needed (impl->current_filter); +- +- filter_info.display_name = display_name; +- filter_info.mime_type = mime_type; +- +- if (needed & GTK_FILE_FILTER_FILENAME) +- { +- filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path); +- if (filter_info.filename) +- filter_info.contains |= GTK_FILE_FILTER_FILENAME; +- } +- else +- filter_info.filename = NULL; +- +- if (needed & GTK_FILE_FILTER_URI) +- { +- filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path); +- if (filter_info.uri) +- filter_info.contains |= GTK_FILE_FILTER_URI; +- } +- else +- filter_info.uri = NULL; +- +- result = gtk_file_filter_filter (impl->current_filter, &filter_info); +- +- if (filter_info.filename) +- g_free ((gchar *) filter_info.filename); +- if (filter_info.uri) +- g_free ((gchar *) filter_info.uri); +- +- return !result; +- +-} +- +-/* Visibility function for the recent filter model */ +-static gboolean +-search_model_visible_func (GtkTreeModel *model, +- GtkTreeIter *iter, +- gpointer user_data) +-{ +- GtkFileChooserDefault *impl = user_data; +- GtkFilePath *file_path; +- gchar *display_name, *mime_type; +- gboolean is_folder; +- +- if (!impl->current_filter) +- return TRUE; +- +- gtk_tree_model_get (model, iter, +- SEARCH_MODEL_COL_PATH, &file_path, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name, +- SEARCH_MODEL_COL_MIME_TYPE, &mime_type, +- -1); +- +- if (!display_name) +- return TRUE; +- +- if (is_folder) +- return TRUE; +- +- return !search_get_is_filtered (impl, file_path, display_name, mime_type); +-} +- +-/* Creates the search_model and puts it in the tree view */ +-static void +-search_setup_model (GtkFileChooserDefault *impl) +-{ +- g_assert (impl->search_model == NULL); +- g_assert (impl->search_model_filter == NULL); +- g_assert (impl->search_model_sort == NULL); +- +- /* We store these columns in the search model: +- * +- * SEARCH_MODEL_COL_PATH - a GtkFilePath for the hit's URI, stored as a +- * pointer not as a GTK_TYPE_FILE_PATH +- * SEARCH_MODEL_COL_DISPLAY_NAME - a string with the display name, stored +- * as a pointer not as a G_TYPE_STRING +- * SEARCH_MODEL_COL_COLLATION_KEY - collation key for the filename, stored +- * as a pointer not as a G_TYPE_STRING +- * SEARCH_MODEL_COL_STAT - pointer to a struct stat +- * SEARCH_MODEL_COL_HANDLE - handle used when getting the hit's info +- * SEARCH_MODEL_COL_PIXBUF - GdkPixbuf for the hit's icon +- * SEARCH_MODEL_COL_MIME_TYPE - a string with the hit's MIME type +- * SEARCH_MODEL_COL_IS_FOLDER - a boolean flag for folders +- * +- * Keep this in sync with the enumeration defined near the beginning +- * of this file. +- */ +- impl->search_model = gtk_list_store_new (SEARCH_MODEL_COL_NUM_COLUMNS, +- G_TYPE_POINTER, +- G_TYPE_POINTER, +- G_TYPE_POINTER, +- G_TYPE_POINTER, +- G_TYPE_POINTER, +- GDK_TYPE_PIXBUF, +- G_TYPE_POINTER, +- G_TYPE_BOOLEAN); +- +- impl->search_model_filter = +- GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->search_model), NULL)); +- gtk_tree_model_filter_set_visible_func (impl->search_model_filter, +- search_model_visible_func, +- impl, NULL); +- +- impl->search_model_sort = +- GTK_TREE_MODEL_SORT (search_model_sort_new (impl, GTK_TREE_MODEL (impl->search_model_filter))); +- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort), +- SEARCH_MODEL_COL_PATH, +- search_column_path_sort_func, +- impl, NULL); +- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort), +- SEARCH_MODEL_COL_STAT, +- search_column_mtime_sort_func, +- impl, NULL); +- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->search_model_sort), +- SEARCH_MODEL_COL_STAT, +- GTK_SORT_DESCENDING); +- +- /* EB: setting the model here will make the hits list update feel +- * more "alive" than setting the model at the end of the search +- * run +- */ +- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), +- GTK_TREE_MODEL (impl->search_model_sort)); +-} +- +-static void +-search_get_valid_child_iter (GtkFileChooserDefault *impl, +- GtkTreeIter *child_iter, +- GtkTreeIter *iter) +-{ +- GtkTreeIter middle; +- +- if (!impl->search_model) +- return; +- +- if (!impl->search_model_filter || !impl->search_model_sort) +- return; +- +- /* pass 1: get the iterator in the filter model */ +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->search_model_sort, +- &middle, iter); +- +- /* pass 2: get the iterator in the real model */ +- gtk_tree_model_filter_convert_iter_to_child_iter (impl->search_model_filter, +- child_iter, &middle); +-} +- +-/* Creates a new query with the specified text and launches it */ +-static void +-search_start_query (GtkFileChooserDefault *impl, +- const gchar *query_text) +-{ +- search_stop_searching (impl, FALSE); +- search_clear_model (impl, TRUE); +- search_setup_model (impl); +- set_busy_cursor (impl, TRUE); +- +- if (impl->search_engine == NULL) +- impl->search_engine = _gtk_search_engine_new (); +- +- if (!impl->search_engine) +- { +- set_busy_cursor (impl, FALSE); +- search_error_could_not_create_client (impl); /* lame; we don't get an error code or anything */ +- return; +- } +- +- if (!impl->search_query) +- { +- impl->search_query = _gtk_query_new (); +- _gtk_query_set_text (impl->search_query, query_text); +- } +- +- _gtk_search_engine_set_query (impl->search_engine, impl->search_query); +- +- g_signal_connect (impl->search_engine, "hits-added", +- G_CALLBACK (search_engine_hits_added_cb), impl); +- g_signal_connect (impl->search_engine, "finished", +- G_CALLBACK (search_engine_finished_cb), impl); +- g_signal_connect (impl->search_engine, "error", +- G_CALLBACK (search_engine_error_cb), impl); +- +- _gtk_search_engine_start (impl->search_engine); +-} +- +-/* Callback used when the user presses Enter while typing on the search +- * entry; starts the query +- */ +-static void +-search_entry_activate_cb (GtkEntry *entry, +- gpointer data) +-{ +- GtkFileChooserDefault *impl; +- const char *text; +- +- impl = GTK_FILE_CHOOSER_DEFAULT (data); +- +- text = gtk_entry_get_text (GTK_ENTRY (impl->search_entry)); +- if (strlen (text) == 0) +- return; +- +- /* reset any existing query object */ +- if (impl->search_query) +- { +- g_object_unref (impl->search_query); +- impl->search_query = NULL; +- } +- +- search_start_query (impl, text); +-} +- +-/* Hides the path bar and creates the search entry */ +-static void +-search_setup_widgets (GtkFileChooserDefault *impl) +-{ +- GtkWidget *label; +- +- impl->search_hbox = gtk_hbox_new (FALSE, 12); +- +- /* Label */ +- +- label = gtk_label_new_with_mnemonic (_("_Search:")); +- gtk_box_pack_start (GTK_BOX (impl->search_hbox), label, FALSE, FALSE, 0); +- +- /* Entry */ +- +- impl->search_entry = gtk_entry_new (); +- gtk_label_set_mnemonic_widget (GTK_LABEL (label), impl->search_entry); +- g_signal_connect (impl->search_entry, "activate", +- G_CALLBACK (search_entry_activate_cb), +- impl); +- gtk_box_pack_start (GTK_BOX (impl->search_hbox), impl->search_entry, TRUE, TRUE, 0); +- +- /* if there already is a query, restart it */ +- if (impl->search_query) +- { +- gchar *query = _gtk_query_get_text (impl->search_query); +- +- if (query) +- { +- gtk_entry_set_text (GTK_ENTRY (impl->search_entry), query); +- search_start_query (impl, query); +- +- g_free (query); +- } +- else +- { +- g_object_unref (impl->search_query); +- impl->search_query = NULL; +- } +- } +- +- gtk_widget_hide (impl->browse_path_bar); +- gtk_widget_hide (impl->browse_new_folder_button); +- +- /* Box for search widgets */ +- gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->search_hbox, TRUE, TRUE, 0); +- gtk_widget_show_all (impl->search_hbox); +- +- /* Hide the location widgets temporarily */ +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- { +- gtk_widget_hide (impl->location_button); +- gtk_widget_hide (impl->location_entry_box); +- } +- +- gtk_widget_grab_focus (impl->search_entry); +- +- /* FMQ: hide the filter combo? */ +-} +- +-/* Main entry point to the searching functions; this gets called when the user +- * activates the Search shortcut. +- */ +-static void +-search_activate (GtkFileChooserDefault *impl) +-{ +- OperationMode previous_mode; +- +- if (impl->operation_mode == OPERATION_MODE_SEARCH) +- { +- gtk_widget_grab_focus (impl->search_entry); +- return; +- } +- +- previous_mode = impl->operation_mode; +- impl->operation_mode = OPERATION_MODE_SEARCH; +- +- switch (previous_mode) +- { +- case OPERATION_MODE_RECENT: +- recent_stop_loading (impl); +- recent_clear_model (impl, TRUE); +- break; +- +- case OPERATION_MODE_BROWSE: +- stop_loading_and_clear_list_model (impl); +- break; +- +- case OPERATION_MODE_SEARCH: +- g_assert_not_reached (); +- break; +- } +- +- g_assert (impl->search_hbox == NULL); +- g_assert (impl->search_entry == NULL); +- g_assert (impl->search_model == NULL); +- g_assert (impl->search_model_filter == NULL); +- +- search_setup_widgets (impl); +- file_list_set_sort_column_ids (impl); +-} +- +-/* +- * Recent files support +- */ +- +-/* Frees the data in the recent_model */ +-static void +-recent_clear_model (GtkFileChooserDefault *impl, +- gboolean remove_from_treeview) +-{ +- GtkTreeModel *model; +- GtkTreeIter iter; +- +- if (!impl->recent_model) +- return; +- +- model = GTK_TREE_MODEL (impl->recent_model); +- +- if (remove_from_treeview) +- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL); +- +- if (gtk_tree_model_get_iter_first (model, &iter)) +- { +- do +- { +- GtkFilePath *file_path; +- GtkFileSystemHandle *handle; +- GtkRecentInfo *recent_info; +- gchar *display_name; +- +- gtk_tree_model_get (model, &iter, +- RECENT_MODEL_COL_DISPLAY_NAME, &display_name, +- RECENT_MODEL_COL_PATH, &file_path, +- RECENT_MODEL_COL_HANDLE, &handle, +- RECENT_MODEL_COL_INFO, &recent_info, +- -1); +- +- if (handle) +- gtk_file_system_cancel_operation (handle); +- +- gtk_file_path_free (file_path); +- gtk_recent_info_unref (recent_info); +- g_free (display_name); +- } +- while (gtk_tree_model_iter_next (model, &iter)); +- } +- +- g_object_unref (impl->recent_model); +- impl->recent_model = NULL; +- +- g_object_unref (impl->recent_model_filter); +- impl->recent_model_filter = NULL; +- +- g_object_unref (impl->recent_model_sort); +- impl->recent_model_sort = NULL; +-} +- +-/* Stops any ongoing loading of the recent files list; does +- * not touch the recent_model +- */ +-static void +-recent_stop_loading (GtkFileChooserDefault *impl) +-{ +- if (impl->load_recent_id) +- { +- g_source_remove (impl->load_recent_id); +- impl->load_recent_id = 0; +- } +-} +- +-/* Stops any pending load, clears the file list, and switches +- * back to OPERATION_MODE_BROWSE +- */ +-static void +-recent_switch_to_browse_mode (GtkFileChooserDefault *impl) +-{ +- g_assert (impl->operation_mode != OPERATION_MODE_BROWSE); +- +- recent_stop_loading (impl); +- recent_clear_model (impl, TRUE); +- +- gtk_widget_show (impl->browse_path_bar); +- gtk_widget_show (impl->browse_new_folder_button); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- { +- gtk_widget_show (impl->location_button); +- +- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY) +- gtk_widget_show (impl->location_entry_box); +- } +- +- impl->operation_mode = OPERATION_MODE_BROWSE; +- +- file_list_set_sort_column_ids (impl); +-} +- +-/* Sort callback from the modification time column */ +-static gint +-recent_column_mtime_sort_func (GtkTreeModel *model, +- GtkTreeIter *a, +- GtkTreeIter *b, +- gpointer user_data) +-{ +- GtkFileChooserDefault *impl = user_data; +- GtkTreeIter child_a, child_b; +- GtkRecentInfo *info_a, *info_b; +- gboolean is_folder_a, is_folder_b; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a); +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b); +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_a, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder_a, +- RECENT_MODEL_COL_INFO, &info_a, +- -1); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_b, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder_b, +- RECENT_MODEL_COL_INFO, &info_b, +- -1); +- +- if (!info_a) +- return 1; +- +- if (!info_b) +- return -1; +- +- /* folders always go first */ +- if (is_folder_a != is_folder_b) +- return is_folder_a ? 1 : -1; +- +- if (gtk_recent_info_get_modified (info_a) < gtk_recent_info_get_modified (info_b)) +- return -1; +- else if (gtk_recent_info_get_modified (info_a) > gtk_recent_info_get_modified (info_b)) +- return 1; +- else +- return 0; +-} +- +-static gint +-recent_column_path_sort_func (GtkTreeModel *model, +- GtkTreeIter *a, +- GtkTreeIter *b, +- gpointer user_data) +-{ +- GtkFileChooserDefault *impl = user_data; +- GtkTreeIter child_a, child_b; +- gboolean is_folder_a, is_folder_b; +- gchar *name_a, *name_b; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a); +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b); +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_a, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder_a, +- RECENT_MODEL_COL_DISPLAY_NAME, &name_a, +- -1); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_b, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder_b, +- RECENT_MODEL_COL_DISPLAY_NAME, &name_b, +- -1); +- +- if (!name_a) +- return 1; +- +- if (!name_b) +- return -1; +- +- if (is_folder_a != is_folder_b) +- return is_folder_a ? 1 : -1; +- +- return strcmp (name_a, name_b); +-} +- +-static gboolean +-recent_get_is_filtered (GtkFileChooserDefault *impl, +- const GtkFilePath *path, +- GtkRecentInfo *recent_info) +-{ +- GtkFileFilterInfo filter_info; +- GtkFileFilterFlags needed; +- gboolean result; +- +- if (!impl->current_filter) +- return FALSE; +- +- filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE; +- needed = gtk_file_filter_get_needed (impl->current_filter); +- +- filter_info.display_name = gtk_recent_info_get_display_name (recent_info); +- filter_info.mime_type = gtk_recent_info_get_mime_type (recent_info); +- +- if (needed & GTK_FILE_FILTER_FILENAME) +- { +- filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path); +- if (filter_info.filename) +- filter_info.contains |= GTK_FILE_FILTER_FILENAME; +- } +- else +- filter_info.filename = NULL; +- +- if (needed & GTK_FILE_FILTER_URI) +- { +- filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path); +- if (filter_info.uri) +- filter_info.contains |= GTK_FILE_FILTER_URI; +- } +- else +- filter_info.uri = NULL; +- +- result = gtk_file_filter_filter (impl->current_filter, &filter_info); +- +- if (filter_info.filename) +- g_free ((gchar *) filter_info.filename); +- if (filter_info.uri) +- g_free ((gchar *) filter_info.uri); +- +- return !result; +-} +- +-/* Visibility function for the recent filter model */ +-static gboolean +-recent_model_visible_func (GtkTreeModel *model, +- GtkTreeIter *iter, +- gpointer user_data) +-{ +- GtkFileChooserDefault *impl = user_data; +- GtkFilePath *file_path; +- GtkRecentInfo *recent_info; +- gboolean is_folder; +- +- if (!impl->current_filter) +- return TRUE; +- +- gtk_tree_model_get (model, iter, +- RECENT_MODEL_COL_INFO, &recent_info, +- RECENT_MODEL_COL_PATH, &file_path, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- if (!recent_info) +- return TRUE; +- +- if (is_folder) +- return TRUE; +- +- return !recent_get_is_filtered (impl, file_path, recent_info); +-} +- +-static void +-recent_setup_model (GtkFileChooserDefault *impl) +-{ +- g_assert (impl->recent_model == NULL); +- g_assert (impl->recent_model_filter == NULL); +- g_assert (impl->recent_model_sort == NULL); +- +- /* We store these columns in the search model: +- * +- * RECENT_MODEL_COL_PATH - a pointer to GtkFilePath for the hit's URI, +- * stored as a pointer and not as a GTK_TYPE_FILE_PATH; +- * RECENT_MODEL_COL_DISPLAY_NAME - a string with the display name, +- * stored as a pointer and not as a G_TYPE_STRING; +- * RECENT_MODEL_COL_INFO - GtkRecentInfo, stored as a pointer and not +- * as a GTK_TYPE_RECENT_INFO; +- * RECENT_MODEL_COL_IS_FOLDER - boolean flag; +- * RECENT_MODEL_COL_HANDLE - GtkFileSystemHandle, stored as a pointer +- * and not as a GTK_TYPE_FILE_SYSTEM_HANDLE; +- * +- * Keep this in sync with the enumeration defined near the beginning of +- * this file. +- */ +- impl->recent_model = gtk_list_store_new (RECENT_MODEL_COL_NUM_COLUMNS, +- G_TYPE_POINTER, +- G_TYPE_POINTER, +- G_TYPE_POINTER, +- G_TYPE_BOOLEAN, +- G_TYPE_POINTER); +- +- impl->recent_model_filter = +- GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->recent_model), NULL)); +- gtk_tree_model_filter_set_visible_func (impl->recent_model_filter, +- recent_model_visible_func, +- impl, +- NULL); +- +- /* this is the model that will actually be added to +- * the browse_files_tree_view widget; remember: we are +- * stuffing the real model into a filter model and then +- * into a sort model; this means we'll have to translate +- * the child iterator *twice* to get from a path or an +- * iterator coming from the tree view widget to the +- * real data inside the model. +- */ +- impl->recent_model_sort = +- GTK_TREE_MODEL_SORT (recent_model_sort_new (impl, GTK_TREE_MODEL (impl->recent_model_filter))); +- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort), +- RECENT_MODEL_COL_PATH, +- recent_column_path_sort_func, +- impl, NULL); +- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort), +- RECENT_MODEL_COL_INFO, +- recent_column_mtime_sort_func, +- impl, NULL); +- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model_sort), +- RECENT_MODEL_COL_INFO, +- GTK_SORT_DESCENDING); +-} +- +-typedef struct +-{ +- GtkFileChooserDefault *impl; +- GList *items; +- gint n_items; +- gint n_loaded_items; +- guint needs_sorting : 1; +-} RecentLoadData; +- +-static void +-recent_idle_cleanup (gpointer data) +-{ +- RecentLoadData *load_data = data; +- GtkFileChooserDefault *impl = load_data->impl; +- +- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), +- GTK_TREE_MODEL (impl->recent_model_sort)); +- +- set_busy_cursor (impl, FALSE); +- +- impl->load_recent_id = 0; +- +- if (load_data->items) +- { +- g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL); +- g_list_free (load_data->items); +- } +- +- g_free (load_data); +-} +- +-struct RecentItemInsertRequest +-{ +- GtkFileChooserDefault *impl; +- GtkFilePath *path; +- GtkTreeRowReference *row_ref; +-}; +- +-static void +-recent_item_get_info_cb (GtkFileSystemHandle *handle, +- const GtkFileInfo *info, +- const GError *error, +- gpointer data) +-{ +- gboolean cancelled = handle->cancelled; +- GtkTreePath *path; +- GtkTreeIter iter; +- GtkFileSystemHandle *model_handle; +- gboolean is_folder = FALSE; +- struct RecentItemInsertRequest *request = data; +- +- if (!request->impl->recent_model) +- goto out; +- +- path = gtk_tree_row_reference_get_path (request->row_ref); +- if (!path) +- goto out; +- +- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->recent_model), +- &iter, path); +- gtk_tree_path_free (path); +- +- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->recent_model), &iter, +- RECENT_MODEL_COL_HANDLE, &model_handle, +- -1); +- if (handle != model_handle) +- goto out; +- +- gtk_list_store_set (request->impl->recent_model, &iter, +- RECENT_MODEL_COL_HANDLE, NULL, +- -1); +- +- if (cancelled) +- goto out; +- +- if (!info) +- { +- gtk_list_store_remove (request->impl->recent_model, &iter); +- goto out; +- } +- +- is_folder = gtk_file_info_get_is_folder (info); +- +- gtk_list_store_set (request->impl->recent_model, &iter, +- RECENT_MODEL_COL_IS_FOLDER, is_folder, +- -1); +- +-out: +- g_object_unref (request->impl); +- gtk_file_path_free (request->path); +- gtk_tree_row_reference_free (request->row_ref); +- g_free (request); +- +- g_object_unref (handle); +-} +- +-static gint +-recent_sort_mru (gconstpointer a, +- gconstpointer b) +-{ +- GtkRecentInfo *info_a = (GtkRecentInfo *) a; +- GtkRecentInfo *info_b = (GtkRecentInfo *) b; +- +- return (gtk_recent_info_get_modified (info_b) - gtk_recent_info_get_modified (info_a)); +-} +- +-static gint +-get_recent_files_limit (GtkWidget *widget) +-{ +- GtkSettings *settings; +- gint limit; +- +- if (gtk_widget_has_screen (widget)) +- settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget)); +- else +- settings = gtk_settings_get_default (); +- +- g_object_get (G_OBJECT (settings), "gtk-recent-files-limit", &limit, NULL); +- +- return limit; +-} +- +-static gboolean +-recent_idle_load (gpointer data) +-{ +- RecentLoadData *load_data = data; +- GtkFileChooserDefault *impl = load_data->impl; +- GtkTreeIter iter; +- GtkTreePath *p; +- GtkRecentInfo *info; +- const gchar *uri, *display_name; +- GtkFilePath *path; +- GtkFileSystemHandle *handle; +- struct RecentItemInsertRequest *request; +- +- if (!impl->recent_manager) +- return FALSE; +- +- /* first iteration: load all the items */ +- if (!load_data->items) +- { +- load_data->items = gtk_recent_manager_get_items (impl->recent_manager); +- if (!load_data->items) +- return FALSE; +- +- load_data->needs_sorting = TRUE; +- +- return TRUE; +- } +- +- /* second iteration: preliminary MRU sorting and clamping */ +- if (load_data->needs_sorting) +- { +- gint limit; +- +- load_data->items = g_list_sort (load_data->items, recent_sort_mru); +- load_data->n_items = g_list_length (load_data->items); +- +- limit = get_recent_files_limit (GTK_WIDGET (impl)); +- +- if (limit != -1 && (load_data->n_items > limit)) +- { +- GList *clamp, *l; +- +- clamp = g_list_nth (load_data->items, limit - 1); +- if (G_LIKELY (clamp)) +- { +- l = clamp->next; +- clamp->next = NULL; +- +- g_list_foreach (l, (GFunc) gtk_recent_info_unref, NULL); +- g_list_free (l); +- +- load_data->n_items = limit; +- } +- } +- +- load_data->n_loaded_items = 0; +- load_data->needs_sorting = FALSE; +- +- return TRUE; +- } +- +- info = g_list_nth_data (load_data->items, load_data->n_loaded_items); +- g_assert (info != NULL); +- +- uri = gtk_recent_info_get_uri (info); +- display_name = gtk_recent_info_get_display_name (info); +- path = gtk_file_system_uri_to_path (impl->file_system, uri); +- if (!path) +- goto load_next; +- +- gtk_list_store_append (impl->recent_model, &iter); +- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->recent_model), &iter); +- +- request = g_new0 (struct RecentItemInsertRequest, 1); +- request->impl = g_object_ref (impl); +- request->path = gtk_file_path_copy (path); +- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->recent_model), p); +- gtk_tree_path_free (p); +- +- handle = gtk_file_system_get_info (impl->file_system, path, +- GTK_FILE_INFO_IS_FOLDER, +- recent_item_get_info_cb, +- request); +- +- gtk_list_store_set (impl->recent_model, &iter, +- RECENT_MODEL_COL_PATH, path, +- RECENT_MODEL_COL_DISPLAY_NAME, g_strdup (display_name), +- RECENT_MODEL_COL_INFO, gtk_recent_info_ref (info), +- RECENT_MODEL_COL_HANDLE, handle, +- -1); +- +-load_next: +- +- load_data->n_loaded_items += 1; +- +- /* finished loading items */ +- if (load_data->n_loaded_items == load_data->n_items) +- { +- g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL); +- g_list_free (load_data->items); +- load_data->items = NULL; +- +- return FALSE; +- } +- +- return TRUE; +-} +- +-static void +-recent_start_loading (GtkFileChooserDefault *impl) +-{ +- RecentLoadData *load_data; +- +- recent_stop_loading (impl); +- recent_clear_model (impl, TRUE); +- recent_setup_model (impl); +- set_busy_cursor (impl, TRUE); +- +- if (!impl->recent_manager) +- recent_manager_update (impl); +- +- g_assert (impl->load_recent_id == 0); +- +- load_data = g_new (RecentLoadData, 1); +- load_data->impl = impl; +- load_data->items = NULL; +- load_data->n_items = 0; +- load_data->n_loaded_items = 0; +- load_data->needs_sorting = TRUE; +- +- /* begin lazy loading the recent files into the model */ +- impl->load_recent_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30, +- recent_idle_load, +- load_data, +- recent_idle_cleanup); +-} +- +-static void +-recent_selected_foreach_get_path_cb (GtkTreeModel *model, +- GtkTreePath *path, +- GtkTreeIter *iter, +- gpointer data) +-{ +- GSList **list; +- const GtkFilePath *file_path; +- GtkFilePath *file_path_copy; +- +- list = data; +- +- gtk_tree_model_get (model, iter, RECENT_MODEL_COL_PATH, &file_path, -1); +- file_path_copy = gtk_file_path_copy (file_path); +- *list = g_slist_prepend (*list, file_path_copy); +-} +- +-/* Constructs a list of the selected paths in recent files mode */ +-static GSList * +-recent_get_selected_paths (GtkFileChooserDefault *impl) +-{ +- GSList *result; +- GtkTreeSelection *selection; +- +- result = NULL; +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- gtk_tree_selection_selected_foreach (selection, recent_selected_foreach_get_path_cb, &result); +- result = g_slist_reverse (result); +- +- return result; +-} +- +-/* Called from ::should_respond(). We return whether there are selected +- * files in the recent files list. +- */ +-static gboolean +-recent_should_respond (GtkFileChooserDefault *impl) +-{ +- GtkTreeSelection *selection; +- +- g_assert (impl->operation_mode == OPERATION_MODE_RECENT); +- +- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); +- return (gtk_tree_selection_count_selected_rows (selection) != 0); +-} +- +-/* Hide the location widgets temporarily */ +-static void +-recent_hide_entry (GtkFileChooserDefault *impl) +-{ +- gtk_widget_hide (impl->browse_path_bar); +- gtk_widget_hide (impl->browse_new_folder_button); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- { +- gtk_widget_hide (impl->location_button); +- gtk_widget_hide (impl->location_entry_box); +- } +-} +- +-/* Main entry point to the recent files functions; this gets called when +- * the user activates the Recently Used shortcut. +- */ +-static void +-recent_activate (GtkFileChooserDefault *impl) +-{ +- OperationMode previous_mode; +- +- if (impl->operation_mode == OPERATION_MODE_RECENT) +- return; +- +- previous_mode = impl->operation_mode; +- impl->operation_mode = OPERATION_MODE_RECENT; +- +- switch (previous_mode) +- { +- case OPERATION_MODE_SEARCH: +- search_stop_searching (impl, FALSE); +- search_clear_model (impl, TRUE); +- +- gtk_widget_destroy (impl->search_hbox); +- impl->search_hbox = NULL; +- impl->search_entry = NULL; +- break; +- +- case OPERATION_MODE_BROWSE: +- stop_loading_and_clear_list_model (impl); +- break; +- +- case OPERATION_MODE_RECENT: +- g_assert_not_reached (); +- break; +- } +- +- recent_hide_entry (impl); +- file_list_set_sort_column_ids (impl); +- recent_start_loading (impl); +-} +- +-/* convert an iterator coming from the model bound to +- * browse_files_tree_view to an interator inside the +- * real recent_model +- */ +-static void +-recent_get_valid_child_iter (GtkFileChooserDefault *impl, +- GtkTreeIter *child_iter, +- GtkTreeIter *iter) +-{ +- GtkTreeIter middle; +- +- if (!impl->recent_model) +- return; +- +- if (!impl->recent_model_filter || !impl->recent_model_sort) +- return; +- +- /* pass 1: get the iterator in the filter model */ +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->recent_model_sort, +- &middle, iter); +- +- /* pass 2: get the iterator in the real model */ +- gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, +- child_iter, +- &middle); +-} +- +- +-static void + set_current_filter (GtkFileChooserDefault *impl, + GtkFileFilter *filter) + { +@@ -10175,12 +4463,6 @@ + if (impl->browse_files_model) + install_list_model_filter (impl); + +- if (impl->search_model_filter) +- gtk_tree_model_filter_refilter (impl->search_model_filter); +- +- if (impl->recent_model_filter) +- gtk_tree_model_filter_refilter (impl->recent_model_filter); +- + g_object_notify (G_OBJECT (impl), "filter"); + } + } +@@ -10195,355 +4477,7 @@ + set_current_filter (impl, new_filter); + } + +-static void +-check_preview_change (GtkFileChooserDefault *impl) +-{ +- GtkTreePath *cursor_path; +- const GtkFilePath *new_path; +- const char *new_display_name; +- +- gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL); +- new_path = NULL; +- new_display_name = NULL; +- if (cursor_path) +- { +- GtkTreeIter child_iter; +- +- if (impl->operation_mode == OPERATION_MODE_BROWSE) +- { +- if (impl->sort_model) +- { +- GtkTreeIter iter; +- const GtkFileInfo *new_info; +- +- gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, cursor_path); +- gtk_tree_path_free (cursor_path); +- +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter); +- +- new_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); +- new_info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); +- if (new_info) +- new_display_name = gtk_file_info_get_display_name (new_info); +- } +- } +- else if (impl->operation_mode == OPERATION_MODE_SEARCH) +- { +- GtkTreeIter iter; +- +- gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), +- &iter, cursor_path); +- gtk_tree_path_free (cursor_path); +- +- search_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_PATH, &new_path, +- SEARCH_MODEL_COL_DISPLAY_NAME, &new_display_name, +- -1); +- } +- else if (impl->operation_mode == OPERATION_MODE_RECENT) +- { +- GtkTreeIter iter; +- +- gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), +- &iter, cursor_path); +- gtk_tree_path_free (cursor_path); +- +- recent_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_PATH, &new_path, +- RECENT_MODEL_COL_DISPLAY_NAME, &new_display_name, +- -1); +- } +- } +- +- if (new_path != impl->preview_path && +- !(new_path && impl->preview_path && +- gtk_file_path_compare (new_path, impl->preview_path) == 0)) +- { +- if (impl->preview_path) +- { +- gtk_file_path_free (impl->preview_path); +- g_free (impl->preview_display_name); +- } +- +- if (new_path) +- { +- impl->preview_path = gtk_file_path_copy (new_path); +- impl->preview_display_name = g_strdup (new_display_name); +- } +- else +- { +- impl->preview_path = NULL; +- impl->preview_display_name = NULL; +- } +- +- if (impl->use_preview_label && impl->preview_label) +- gtk_label_set_text (GTK_LABEL (impl->preview_label), impl->preview_display_name); +- +- g_signal_emit_by_name (impl, "update-preview"); +- } +-} +- +-static void +-shortcuts_activate_volume_mount_cb (GtkFileSystemHandle *handle, +- GtkFileSystemVolume *volume, +- const GError *error, +- gpointer data) +-{ +- GtkFilePath *path; +- gboolean cancelled = handle->cancelled; +- GtkFileChooserDefault *impl = data; +- +- if (handle != impl->shortcuts_activate_iter_handle) +- goto out; +- +- impl->shortcuts_activate_iter_handle = NULL; +- +- set_busy_cursor (impl, FALSE); +- +- if (cancelled) +- goto out; +- +- if (error) +- { +- char *msg; +- +- msg = g_strdup_printf (_("Could not mount %s"), +- gtk_file_system_volume_get_display_name (impl->file_system, volume)); +- error_message (impl, msg, error->message); +- g_free (msg); +- +- goto out; +- } +- +- path = gtk_file_system_volume_get_base_path (impl->file_system, volume); +- if (path != NULL) +- { +- change_folder_and_display_error (impl, path, FALSE); +- focus_browse_tree_view_if_possible (impl); +- +- gtk_file_path_free (path); +- } +- +-out: +- g_object_unref (impl); +- g_object_unref (handle); +-} +- +- +-/* Activates a volume by mounting it if necessary and then switching to its +- * base path. +- */ +-static void +-shortcuts_activate_volume (GtkFileChooserDefault *impl, +- GtkFileSystemVolume *volume) +-{ +- GtkFilePath *path; +- +- switch (impl->operation_mode) +- { +- case OPERATION_MODE_BROWSE: +- break; +- case OPERATION_MODE_SEARCH: +- search_switch_to_browse_mode (impl); +- break; +- case OPERATION_MODE_RECENT: +- recent_switch_to_browse_mode (impl); +- break; +- } +- +- /* We ref the file chooser since volume_mount() may run a main loop, and the +- * user could close the file chooser window in the meantime. +- */ +- g_object_ref (impl); +- +- if (!gtk_file_system_volume_get_is_mounted (impl->file_system, volume)) +- { +- set_busy_cursor (impl, TRUE); +- +- impl->shortcuts_activate_iter_handle = +- gtk_file_system_volume_mount (impl->file_system, volume, +- shortcuts_activate_volume_mount_cb, +- g_object_ref (impl)); +- } +- else +- { +- path = gtk_file_system_volume_get_base_path (impl->file_system, volume); +- if (path != NULL) +- { +- change_folder_and_display_error (impl, path, FALSE); +- gtk_file_path_free (path); +- } +- } +- +- g_object_unref (impl); +-} +- +-/* Opens the folder or volume at the specified iter in the shortcuts model */ +-struct ShortcutsActivateData +-{ +- GtkFileChooserDefault *impl; +- GtkFilePath *path; +-}; +- +-static void +-shortcuts_activate_get_info_cb (GtkFileSystemHandle *handle, +- const GtkFileInfo *info, +- const GError *error, +- gpointer user_data) +-{ +- gboolean cancelled = handle->cancelled; +- struct ShortcutsActivateData *data = user_data; +- +- if (handle != data->impl->shortcuts_activate_iter_handle) +- goto out; +- +- data->impl->shortcuts_activate_iter_handle = NULL; +- +- if (cancelled) +- goto out; +- +- if (!error && gtk_file_info_get_is_folder (info)) +- { +- change_folder_and_display_error (data->impl, data->path, FALSE); +- focus_browse_tree_view_if_possible (data->impl); +- } +- else +- gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (data->impl), +- data->path, +- NULL); +- +-out: +- g_object_unref (data->impl); +- gtk_file_path_free (data->path); +- g_free (data); +- +- g_object_unref (handle); +-} +- +-static void +-shortcuts_activate_iter (GtkFileChooserDefault *impl, +- GtkTreeIter *iter) +-{ +- gpointer col_data; +- ShortcutType shortcut_type; +- +- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY && impl->action != GTK_FILE_CHOOSER_ACTION_SAVE) +- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), ""); +- +- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter, +- SHORTCUTS_COL_DATA, &col_data, +- SHORTCUTS_COL_TYPE, &shortcut_type, +- -1); +- +- if (impl->shortcuts_activate_iter_handle) +- { +- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle); +- impl->shortcuts_activate_iter_handle = NULL; +- } +- +- if (shortcut_type == SHORTCUT_TYPE_SEPARATOR) +- return; +- else if (shortcut_type == SHORTCUT_TYPE_VOLUME) +- { +- GtkFileSystemVolume *volume; +- +- volume = col_data; +- +- shortcuts_activate_volume (impl, volume); +- } +- else if (shortcut_type == SHORTCUT_TYPE_PATH) +- { +- struct ShortcutsActivateData *data; +- +- data = g_new0 (struct ShortcutsActivateData, 1); +- data->impl = g_object_ref (impl); +- data->path = gtk_file_path_copy (col_data); +- +- impl->shortcuts_activate_iter_handle = +- gtk_file_system_get_info (impl->file_system, data->path, +- GTK_FILE_INFO_IS_FOLDER, +- shortcuts_activate_get_info_cb, data); +- } +- else if (shortcut_type == SHORTCUT_TYPE_SEARCH) +- { +- search_activate (impl); +- } +- else if (shortcut_type == SHORTCUT_TYPE_RECENT) +- { +- recent_activate (impl); +- } +-} +- +-/* Callback used when a row in the shortcuts list is activated */ +-static void +-shortcuts_row_activated_cb (GtkTreeView *tree_view, +- GtkTreePath *path, +- GtkTreeViewColumn *column, +- GtkFileChooserDefault *impl) +-{ +- GtkTreeIter iter; +- GtkTreeIter child_iter; +- +- if (!gtk_tree_model_get_iter (impl->shortcuts_pane_filter_model, &iter, path)) +- return; +- +- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model), +- &child_iter, +- &iter); +- shortcuts_activate_iter (impl, &child_iter); +-} +- +-/* Handler for GtkWidget::key-press-event on the shortcuts list */ + static gboolean +-shortcuts_key_press_event_cb (GtkWidget *widget, +- GdkEventKey *event, +- GtkFileChooserDefault *impl) +-{ +- guint modifiers; +- +- modifiers = gtk_accelerator_get_default_mod_mask (); +- +- if ((event->keyval == GDK_BackSpace +- || event->keyval == GDK_Delete +- || event->keyval == GDK_KP_Delete) +- && (event->state & modifiers) == 0) +- { +- remove_selected_bookmarks (impl); +- return TRUE; +- } +- +- if ((event->keyval == GDK_F2) +- && (event->state & modifiers) == 0) +- { +- rename_selected_bookmark (impl); +- return TRUE; +- } +- +- return FALSE; +-} +- +-static gboolean +-shortcuts_select_func (GtkTreeSelection *selection, +- GtkTreeModel *model, +- GtkTreePath *path, +- gboolean path_currently_selected, +- gpointer data) +-{ +- GtkFileChooserDefault *impl = data; +- GtkTreeIter filter_iter; +- ShortcutType shortcut_type; +- +- if (!gtk_tree_model_get_iter (impl->shortcuts_pane_filter_model, &filter_iter, path)) +- g_assert_not_reached (); +- +- gtk_tree_model_get (impl->shortcuts_pane_filter_model, &filter_iter, SHORTCUTS_COL_TYPE, &shortcut_type, -1); +- +- return shortcut_type != SHORTCUT_TYPE_SEPARATOR; +-} +- +-static gboolean + list_select_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, +@@ -10556,55 +4490,17 @@ + impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + { + GtkTreeIter iter, child_iter; ++ const GtkFileInfo *info; + +- switch (impl->operation_mode) +- { +- case OPERATION_MODE_SEARCH: +- { +- gboolean is_folder; ++ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path)) ++ return FALSE; ++ ++ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter); + +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path)) +- return FALSE; ++ info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); + +- search_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- if (!is_folder) +- return FALSE; +- } +- break; +- +- case OPERATION_MODE_RECENT: +- { +- gboolean is_folder; +- +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path)) +- return FALSE; +- +- recent_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- if (!is_folder) +- return FALSE; +- } +- break; +- +- case OPERATION_MODE_BROWSE: +- { +- const GtkFileInfo *info; +- +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path)) +- return FALSE; +- +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter); +- info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); +- if (info && !gtk_file_info_get_is_folder (info)) +- return FALSE; +- } +- break; +- } ++ if (info && !gtk_file_info_get_is_folder (info)) ++ return FALSE; + } + + return TRUE; +@@ -10615,8 +4511,7 @@ + GtkFileChooserDefault *impl) + { + /* See if we are in the new folder editable row for Save mode */ +- if (impl->operation_mode == OPERATION_MODE_BROWSE && +- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) + { + const GtkFileInfo *info; + gboolean had_selection; +@@ -10634,9 +4529,6 @@ + if (impl->location_entry) + update_chooser_entry (impl); + +- check_preview_change (impl); +- bookmarks_check_add_sensitivity (impl); +- + g_signal_emit_by_name (impl, "selection-changed", 0); + } + +@@ -10647,107 +4539,30 @@ + GtkTreeViewColumn *column, + GtkFileChooserDefault *impl) + { +- GtkTreeIter iter; +- GtkTreeIter child_iter; ++ GtkTreeIter iter, child_iter; ++ const GtkFileInfo *info; + +- switch (impl->operation_mode) +- { +- case OPERATION_MODE_SEARCH: +- { +- GtkFilePath *file_path; +- gboolean is_folder; ++ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path)) ++ return; + +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path)) +- return; ++ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter); + +- search_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_PATH, &file_path, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- if (is_folder) +- { +- change_folder_and_display_error (impl, file_path, FALSE); +- return; +- } ++ info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); + +- g_signal_emit_by_name (impl, "file-activated"); +- } +- break; ++ if (gtk_file_info_get_is_folder (info)) ++ { ++ const GtkFilePath *file_path; + +- case OPERATION_MODE_RECENT: +- { +- GtkFilePath *file_path; +- gboolean is_folder; ++ file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); + +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path)) +- return; +- +- recent_get_valid_child_iter (impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_PATH, &file_path, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); ++ change_folder_and_display_error (impl, file_path); + +- if (is_folder) +- { +- change_folder_and_display_error (impl, file_path, FALSE); +- return; +- } +- +- g_signal_emit_by_name (impl, "file-activated"); +- } +- break; +- +- case OPERATION_MODE_BROWSE: +- { +- const GtkFileInfo *info; +- +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path)) +- return; +- +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, +- &child_iter, &iter); +- info = _gtk_file_system_model_get_info (impl->browse_files_model, +- &child_iter); +- +- if (gtk_file_info_get_is_folder (info)) +- { +- const GtkFilePath *file_path; +- +- file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); +- change_folder_and_display_error (impl, file_path, FALSE); +- return; +- } +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) +- g_signal_emit_by_name (impl, "file-activated"); +- } +- break; ++ return; + } +-} + +-static void +-path_bar_clicked (GtkPathBar *path_bar, +- GtkFilePath *file_path, +- GtkFilePath *child_path, +- gboolean child_is_hidden, +- GtkFileChooserDefault *impl) +-{ +- if (child_path) +- pending_select_paths_add (impl, child_path); +- +- if (!change_folder_and_display_error (impl, file_path, FALSE)) +- return; +- +- /* Say we have "/foo/bar/[.baz]" and the user clicks on "bar". We should then +- * show hidden files so that ".baz" appears in the file list, as it will still +- * be shown in the path bar: "/foo/[bar]/.baz" +- */ +- if (child_is_hidden) +- g_object_set (impl, "show-hidden", TRUE, NULL); ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || ++ impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) ++ g_signal_emit_by_name (impl, "file-activated"); + } + + static const GtkFileInfo * +@@ -10772,83 +4587,40 @@ + { + GtkFileChooserDefault *impl = data; + GtkTreeIter child_iter; +- GdkPixbuf *pixbuf = NULL; ++ const GtkFilePath *path; ++ GdkPixbuf *pixbuf; ++ const GtkFileInfo *info; + gboolean sensitive = TRUE; + + profile_start ("start", NULL); + +- switch (impl->operation_mode) +- { +- case OPERATION_MODE_SEARCH: +- { +- GtkTreeIter child_iter; +- gboolean is_folder; ++ info = get_list_file_info (impl, iter); + +- search_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_PIXBUF, &pixbuf, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- sensitive = is_folder; +- } +- break; ++ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, ++ &child_iter, ++ iter); ++ path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); + +- case OPERATION_MODE_RECENT: +- { +- GtkTreeIter child_iter; +- GtkRecentInfo *info; +- gboolean is_folder; ++ if (path) ++ { ++ pixbuf = NULL; + +- recent_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_INFO, &info, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- pixbuf = gtk_recent_info_get_icon (info, impl->icon_size); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- sensitive = is_folder; +- } +- break; +- +- case OPERATION_MODE_BROWSE: +- { +- const GtkFileInfo *info; +- const GtkFilePath *path; +- +- info = get_list_file_info (impl, iter); +- +- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, +- &child_iter, +- iter); +- path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); +- if (path) +- { +- if (info) +- { +- /* FIXME: NULL GError */ +- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (impl), +- impl->icon_size, NULL); +- } +- } +- else +- { +- /* We are on the editable row */ +- pixbuf = NULL; +- } +- +- if (info && +- (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)) +- sensitive = gtk_file_info_get_is_folder (info); +- } +- break; ++ if (info) ++ { ++ /* FIXME: NULL GError */ ++ pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (impl), ++ impl->icon_size, NULL); ++ } + } ++ else ++ { ++ /* We are on the editable row */ ++ pixbuf = NULL; ++ } ++ ++ if (info && (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || ++ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)) ++ sensitive = gtk_file_info_get_is_folder (info); + + g_object_set (cell, + "pixbuf", pixbuf, +@@ -10869,85 +4641,21 @@ + gpointer data) + { + GtkFileChooserDefault *impl = data; +- const GtkFileInfo *info; ++ const GtkFileInfo *info = get_list_file_info (impl, iter); + gboolean sensitive = TRUE; + +- if (impl->operation_mode == OPERATION_MODE_SEARCH) +- { +- GtkTreeIter child_iter; +- gchar *display_name; +- gboolean is_folder; +- +- search_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- { +- sensitive = is_folder; +- } +- +- g_object_set (cell, +- "text", display_name, +- "sensitive", sensitive, +- "ellipsize", PANGO_ELLIPSIZE_END, +- NULL); +- +- return; +- } +- +- if (impl->operation_mode == OPERATION_MODE_RECENT) +- { +- GtkTreeIter child_iter; +- GtkRecentInfo *recent_info; +- gchar *display_name; +- gboolean is_folder; +- +- recent_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_INFO, &recent_info, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- display_name = gtk_recent_info_get_short_name (recent_info); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- { +- sensitive = is_folder; +- } +- +- g_object_set (cell, +- "text", display_name, +- "sensitive", sensitive, +- "ellipsize", PANGO_ELLIPSIZE_END, +- NULL); +- +- g_free (display_name); +- +- return; +- } +- +- info = get_list_file_info (impl, iter); +- sensitive = TRUE; +- + if (!info) + { + g_object_set (cell, + "text", _("Type name of new folder"), +- "sensitive", TRUE, +- "ellipsize", PANGO_ELLIPSIZE_NONE, + NULL); + + return; + } + + +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ++ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + { + sensitive = gtk_file_info_get_is_folder (info); + } +@@ -10955,7 +4663,6 @@ + g_object_set (cell, + "text", gtk_file_info_get_display_name (info), + "sensitive", sensitive, +- "ellipsize", PANGO_ELLIPSIZE_END, + NULL); + } + +@@ -11017,142 +4724,64 @@ + gpointer data) + { + GtkFileChooserDefault *impl; +- time_t time_mtime; +- gchar *date_str = NULL; ++ const GtkFileInfo *info; ++ GtkFileTime time_mtime; ++ GDate mtime, now; ++ int days_diff; ++ char buf[256]; + gboolean sensitive = TRUE; + + impl = data; + +- if (impl->operation_mode == OPERATION_MODE_SEARCH) ++ info = get_list_file_info (impl, iter); ++ if (!info) + { +- GtkTreeIter child_iter; +- struct stat *statbuf; +- gboolean is_folder; +- +- search_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, +- SEARCH_MODEL_COL_STAT, &statbuf, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- if (statbuf) +- time_mtime = statbuf->st_mtime; +- else +- time_mtime = 0; +- +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- sensitive = is_folder; ++ g_object_set (cell, ++ "text", "", ++ "sensitive", TRUE, ++ NULL); ++ return; + } +- else if (impl->operation_mode == OPERATION_MODE_RECENT) +- { +- GtkTreeIter child_iter; +- GtkRecentInfo *info; +- gboolean is_folder; + +- recent_get_valid_child_iter (impl, &child_iter, iter); +- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, +- RECENT_MODEL_COL_INFO, &info, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); ++ time_mtime = gtk_file_info_get_modification_time (info); + +- if (info) +- time_mtime = gtk_recent_info_get_modified (info); +- else +- time_mtime = 0; +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- sensitive = is_folder; +- } ++ if (time_mtime == 0) ++ strcpy (buf, _("Unknown")); + else + { +- const GtkFileInfo *info; +- +- info = get_list_file_info (impl, iter); +- if (!info) +- { +- g_object_set (cell, +- "text", "", +- "sensitive", TRUE, +- NULL); +- return; +- } +- +- time_mtime = (time_t) gtk_file_info_get_modification_time (info); +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- sensitive = gtk_file_info_get_is_folder (info); +- } +- +- if (G_UNLIKELY (time_mtime == 0)) +- date_str = g_strdup (_("Unknown")); +- else +- { +- GDate mtime, now; +- gint days_diff; +- struct tm tm_mtime; + time_t time_now; +- const gchar *format; +- gchar *locale_format = NULL; +- gchar buf[256]; +- +-#ifdef HAVE_LOCALTIME_R +- localtime_r ((time_t *) &time_mtime, &tm_mtime); +-#else +- { +- struct tm *ptm = localtime ((time_t *) &time_mtime); +- +- if (!ptm) +- { +- g_warning ("ptm != NULL failed"); +- +- g_object_set (cell, +- "text", _("Unknown"), +- "sensitive", sensitive, +- NULL); +- return; +- } +- else +- memcpy ((void *) &tm_mtime, (void *) ptm, sizeof (struct tm)); +- } +-#endif /* HAVE_LOCALTIME_R */ +- + g_date_set_time_t (&mtime, time_mtime); + time_now = time (NULL); + g_date_set_time_t (&now, time_now); + + days_diff = g_date_get_julian (&now) - g_date_get_julian (&mtime); + +- /* Translators: %H means "hours" and %M means "minutes" */ + if (days_diff == 0) +- format = _("Today at %H:%M"); ++ strcpy (buf, _("Today")); + else if (days_diff == 1) +- format = _("Yesterday at %H:%M"); ++ strcpy (buf, _("Yesterday")); + else + { ++ char *format; ++ + if (days_diff > 1 && days_diff < 7) + format = "%A"; /* Days from last week */ + else + format = "%x"; /* Any other date */ +- } + +- locale_format = g_locale_from_utf8 (format, -1, NULL, NULL, NULL); +- +- if (strftime (buf, sizeof (buf), locale_format, &tm_mtime) != 0) +- date_str = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL); +- else +- date_str = g_strdup (_("Unknown")); +- +- g_free (locale_format); ++ if (g_date_strftime (buf, sizeof (buf), format, &mtime) == 0) ++ strcpy (buf, _("Unknown")); ++ } + } + ++ if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || ++ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) ++ sensitive = gtk_file_info_get_is_folder (info); ++ + g_object_set (cell, +- "text", date_str, ++ "text", buf, + "sensitive", sensitive, + NULL); +- g_free (date_str); + } + + GtkWidget * +@@ -11163,437 +4792,73 @@ + NULL); + } + ++/* Handler for the "up-folder" keybinding signal */ + static void +-location_set_user_text (GtkFileChooserDefault *impl, +- const gchar *path) ++up_folder_handler (GtkFileChooserDefault *impl) + { +- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), path); +- gtk_editable_set_position (GTK_EDITABLE (impl->location_entry), -1); +-} ++ GtkFilePath * parent; ++ pending_select_paths_add (impl, impl->current_folder); + +-static void +-location_popup_handler (GtkFileChooserDefault *impl, +- const gchar *path) +-{ +- if (impl->operation_mode != OPERATION_MODE_BROWSE) +- { +- GtkWidget *widget_to_focus; +- +- /* This will give us the location widgets back */ +- switch (impl->operation_mode) +- { +- case OPERATION_MODE_SEARCH: +- search_switch_to_browse_mode (impl); +- break; +- case OPERATION_MODE_RECENT: +- recent_switch_to_browse_mode (impl); +- break; +- case OPERATION_MODE_BROWSE: +- g_assert_not_reached (); +- break; +- } ++ if (gtk_file_system_get_parent (impl->file_system, impl->current_folder, ++ &parent, NULL) && parent) ++ { ++ impl->path_history = g_slist_prepend (impl->path_history, ++ gtk_file_path_copy (impl->current_folder)); + +- if (impl->current_folder) +- change_folder_and_display_error (impl, impl->current_folder, FALSE); +- +- if (impl->location_mode == LOCATION_MODE_PATH_BAR) +- widget_to_focus = impl->browse_files_tree_view; +- else +- widget_to_focus = impl->location_entry; +- +- gtk_widget_grab_focus (widget_to_focus); +- return; +- } +- +- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || +- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) +- { +- LocationMode new_mode; +- +- if (path != NULL) +- { +- /* since the user typed something, we unconditionally want to turn on the entry */ +- new_mode = LOCATION_MODE_FILENAME_ENTRY; +- } +- else if (impl->location_mode == LOCATION_MODE_PATH_BAR) +- new_mode = LOCATION_MODE_FILENAME_ENTRY; +- else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY) +- new_mode = LOCATION_MODE_PATH_BAR; +- else +- { +- g_assert_not_reached (); +- return; +- } +- +- location_mode_set (impl, new_mode, TRUE); +- if (new_mode == LOCATION_MODE_FILENAME_ENTRY) +- { +- if (path != NULL) +- location_set_user_text (impl, path); +- else +- { +- location_entry_set_initial_text (impl); +- gtk_editable_select_region (GTK_EDITABLE (impl->location_entry), 0, -1); +- } +- } +- } +- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || +- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) +- { +- gtk_widget_grab_focus (impl->location_entry); +- if (path != NULL) +- location_set_user_text (impl, path); +- } +- else +- g_assert_not_reached (); ++ change_folder_and_display_error (impl, parent); ++ gtk_file_path_free (parent); ++ } + } + +-/* Handler for the "up-folder" keybinding signal */ +-static void +-up_folder_handler (GtkFileChooserDefault *impl) +-{ +- _gtk_path_bar_up (GTK_PATH_BAR (impl->browse_path_bar)); +-} +- + /* Handler for the "down-folder" keybinding signal */ + static void + down_folder_handler (GtkFileChooserDefault *impl) + { +- _gtk_path_bar_down (GTK_PATH_BAR (impl->browse_path_bar)); +-} ++ if (impl->path_history) ++ { ++ GtkFilePath * path = impl->path_history->data; + +-/* Switches to the shortcut in the specified index */ +-static void +-switch_to_shortcut (GtkFileChooserDefault *impl, +- int pos) +-{ +- GtkTreeIter iter; +- +- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos)) +- g_assert_not_reached (); +- +- shortcuts_activate_iter (impl, &iter); +- focus_browse_tree_view_if_possible (impl); ++ change_folder_and_display_error (impl, path); ++ impl->path_history = g_slist_remove (impl->path_history, path); ++ gtk_file_path_free (path); ++ } + } + + /* Handler for the "home-folder" keybinding signal */ + static void + home_folder_handler (GtkFileChooserDefault *impl) + { +- if (impl->has_home) +- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_HOME)); + } + +-/* Handler for the "desktop-folder" keybinding signal */ + static void +-desktop_folder_handler (GtkFileChooserDefault *impl) +-{ +- if (impl->has_desktop) +- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_DESKTOP)); +-} +- +-/* Handler for the "search-shortcut" keybinding signal */ +-static void +-search_shortcut_handler (GtkFileChooserDefault *impl) +-{ +- if (impl->has_search) +- { +- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_SEARCH)); +- +- /* we want the entry widget to grab the focus the first +- * time, not the browse_files_tree_view widget. +- */ +- if (impl->search_entry) +- gtk_widget_grab_focus (impl->search_entry); +- } +-} +- +-/* Handler for the "recent-shortcut" keybinding signal */ +-static void +-recent_shortcut_handler (GtkFileChooserDefault *impl) +-{ +- if (impl->has_recent) +- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_RECENT)); +-} +- +-static void +-quick_bookmark_handler (GtkFileChooserDefault *impl, +- gint bookmark_index) +-{ +- int bookmark_pos; +- GtkTreePath *path; +- +- if (bookmark_index < 0 || bookmark_index >= impl->num_bookmarks) +- return; +- +- bookmark_pos = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS) + bookmark_index; +- +- path = gtk_tree_path_new_from_indices (bookmark_pos, -1); +- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), +- path, NULL, +- FALSE, 0.0, 0.0); +- gtk_tree_path_free (path); +- +- switch_to_shortcut (impl, bookmark_pos); +-} +- +-static void + show_hidden_handler (GtkFileChooserDefault *impl) + { +- g_object_set (impl, +- "show-hidden", !impl->show_hidden, +- NULL); + } + +- +-/* Drag and drop interfaces */ +- +-static void +-_shortcuts_pane_model_filter_class_init (ShortcutsPaneModelFilterClass *class) ++static GtkFilePath * ++gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser) + { ++ return NULL; + } + +-static void +-_shortcuts_pane_model_filter_init (ShortcutsPaneModelFilter *model) +-{ +- model->impl = NULL; +-} +- +-/* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */ + static gboolean +-shortcuts_pane_model_filter_row_draggable (GtkTreeDragSource *drag_source, +- GtkTreePath *path) ++gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser, ++ const GtkFilePath *path, ++ GError **error) + { +- ShortcutsPaneModelFilter *model; +- int pos; +- int bookmarks_pos; +- +- model = SHORTCUTS_PANE_MODEL_FILTER (drag_source); +- +- pos = *gtk_tree_path_get_indices (path); +- bookmarks_pos = shortcuts_get_index (model->impl, SHORTCUTS_BOOKMARKS); +- +- return (pos >= bookmarks_pos && pos < bookmarks_pos + model->impl->num_bookmarks); +-} +- +-/* GtkTreeDragSource::drag_data_get implementation for the shortcuts filter model */ +-static gboolean +-shortcuts_pane_model_filter_drag_data_get (GtkTreeDragSource *drag_source, +- GtkTreePath *path, +- GtkSelectionData *selection_data) +-{ +- ShortcutsPaneModelFilter *model; +- +- model = SHORTCUTS_PANE_MODEL_FILTER (drag_source); +- +- /* FIXME */ +- +- return FALSE; +-} +- +-/* Fill the GtkTreeDragSourceIface vtable */ +-static void +-shortcuts_pane_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface) +-{ +- iface->row_draggable = shortcuts_pane_model_filter_row_draggable; +- iface->drag_data_get = shortcuts_pane_model_filter_drag_data_get; +-} +- +-#if 0 +-/* Fill the GtkTreeDragDestIface vtable */ +-static void +-shortcuts_pane_model_filter_drag_dest_iface_init (GtkTreeDragDestIface *iface) +-{ +- iface->drag_data_received = shortcuts_pane_model_filter_drag_data_received; +- iface->row_drop_possible = shortcuts_pane_model_filter_row_drop_possible; +-} +-#endif +- +-static GtkTreeModel * +-shortcuts_pane_model_filter_new (GtkFileChooserDefault *impl, +- GtkTreeModel *child_model, +- GtkTreePath *root) +-{ +- ShortcutsPaneModelFilter *model; +- +- model = g_object_new (SHORTCUTS_PANE_MODEL_FILTER_TYPE, +- "child-model", child_model, +- "virtual-root", root, +- NULL); +- +- model->impl = impl; +- +- return GTK_TREE_MODEL (model); +-} +- +- +- +-static gboolean +-recent_model_sort_row_draggable (GtkTreeDragSource *drag_source, +- GtkTreePath *path) +-{ +- RecentModelSort *model; +- GtkTreeIter iter, child_iter; +- gboolean is_folder; +- +- model = RECENT_MODEL_SORT (drag_source); +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path)) + return FALSE; +- +- recent_get_valid_child_iter (model->impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->recent_model), &child_iter, +- RECENT_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- return is_folder; + } + + static gboolean +-recent_model_sort_drag_data_get (GtkTreeDragSource *drag_source, +- GtkTreePath *path, +- GtkSelectionData *selection_data) ++gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, ++ const GtkFilePath *path, ++ GError **error) + { +- RecentModelSort *model; +- GtkTreeIter iter, child_iter; +- GtkFilePath *file_path; +- gchar **uris; +- +- model = RECENT_MODEL_SORT (drag_source); +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path)) +- return FALSE; +- +- recent_get_valid_child_iter (model->impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->recent_model), &child_iter, +- RECENT_MODEL_COL_PATH, &file_path, +- -1); +- g_assert (file_path != NULL); +- +- uris = g_new (gchar *, 2); +- uris[0] = gtk_file_system_path_to_uri (model->impl->file_system, file_path); +- uris[1] = NULL; +- +- gtk_selection_data_set_uris (selection_data, uris); +- +- g_strfreev (uris); +- +- return TRUE; ++ return TRUE; + } + +-static void +-recent_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface) ++static GSList * ++gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser) + { +- iface->row_draggable = recent_model_sort_row_draggable; +- iface->drag_data_get = recent_model_sort_drag_data_get; ++ return NULL; + } +- +-static void +-_recent_model_sort_class_init (RecentModelSortClass *klass) +-{ +- +-} +- +-static void +-_recent_model_sort_init (RecentModelSort *model) +-{ +- model->impl = NULL; +-} +- +-static GtkTreeModel * +-recent_model_sort_new (GtkFileChooserDefault *impl, +- GtkTreeModel *child_model) +-{ +- RecentModelSort *model; +- +- model = g_object_new (RECENT_MODEL_SORT_TYPE, +- "model", child_model, +- NULL); +- model->impl = impl; +- +- return GTK_TREE_MODEL (model); +-} +- +- +- +-static gboolean +-search_model_sort_row_draggable (GtkTreeDragSource *drag_source, +- GtkTreePath *path) +-{ +- SearchModelSort *model; +- GtkTreeIter iter, child_iter; +- gboolean is_folder; +- +- model = SEARCH_MODEL_SORT (drag_source); +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path)) +- return FALSE; +- +- search_get_valid_child_iter (model->impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->search_model), &child_iter, +- SEARCH_MODEL_COL_IS_FOLDER, &is_folder, +- -1); +- +- return is_folder; +-} +- +-static gboolean +-search_model_sort_drag_data_get (GtkTreeDragSource *drag_source, +- GtkTreePath *path, +- GtkSelectionData *selection_data) +-{ +- SearchModelSort *model; +- GtkTreeIter iter, child_iter; +- GtkFilePath *file_path; +- gchar **uris; +- +- model = SEARCH_MODEL_SORT (drag_source); +- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path)) +- return FALSE; +- +- search_get_valid_child_iter (model->impl, &child_iter, &iter); +- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->search_model), &child_iter, +- RECENT_MODEL_COL_PATH, &file_path, +- -1); +- g_assert (file_path != NULL); +- +- uris = g_new (gchar *, 2); +- uris[0] = gtk_file_system_path_to_uri (model->impl->file_system, file_path); +- uris[1] = NULL; +- +- gtk_selection_data_set_uris (selection_data, uris); +- +- g_strfreev (uris); +- +- return TRUE; +-} +- +-static void +-search_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface) +-{ +- iface->row_draggable = search_model_sort_row_draggable; +- iface->drag_data_get = search_model_sort_drag_data_get; +-} +- +-static void +-_search_model_sort_class_init (SearchModelSortClass *klass) +-{ +- +-} +- +-static void +-_search_model_sort_init (SearchModelSort *model) +-{ +- model->impl = NULL; +-} +- +-static GtkTreeModel * +-search_model_sort_new (GtkFileChooserDefault *impl, +- GtkTreeModel *child_model) +-{ +- SearchModelSort *model; +- +- model = g_object_new (SEARCH_MODEL_SORT_TYPE, +- "model", child_model, +- NULL); +- model->impl = impl; +- +- return GTK_TREE_MODEL (model); +-} +Index: gtk+-2.12.5/gtk/gtkfilechooserprivate.h +=================================================================== +--- gtk+-2.12.5/gtk/gtkfilechooserprivate.h (revision 19337) ++++ gtk+-2.12.5/gtk/gtkfilechooserprivate.h (working copy) +@@ -25,9 +25,6 @@ + #include "gtkfilesystem.h" + #include "gtkfilesystemmodel.h" + #include "gtkliststore.h" +-#include "gtkrecentmanager.h" +-#include "gtksearchengine.h" +-#include "gtkquery.h" + #include "gtktooltips.h" + #include "gtktreemodelsort.h" + #include "gtktreestore.h" +@@ -146,12 +143,6 @@ + LOCATION_MODE_FILENAME_ENTRY + } LocationMode; + +-typedef enum { +- OPERATION_MODE_BROWSE, +- OPERATION_MODE_SEARCH, +- OPERATION_MODE_RECENT +-} OperationMode; +- + struct _GtkFileChooserDefault + { + GtkVBox parent_instance; +@@ -162,53 +153,19 @@ + + /* Save mode widgets */ + GtkWidget *save_widgets; ++ GtkWidget *save_file_name_entry; + +- GtkWidget *save_folder_label; +- GtkWidget *save_folder_combo; +- GtkWidget *save_expander; +- + /* The file browsing widgets */ + GtkWidget *browse_widgets; +- GtkWidget *browse_shortcuts_tree_view; +- GtkWidget *browse_shortcuts_add_button; +- GtkWidget *browse_shortcuts_remove_button; +- GtkWidget *browse_shortcuts_popup_menu; +- GtkWidget *browse_shortcuts_popup_menu_remove_item; +- GtkWidget *browse_shortcuts_popup_menu_rename_item; + GtkWidget *browse_files_tree_view; +- GtkWidget *browse_files_popup_menu; +- GtkWidget *browse_files_popup_menu_add_shortcut_item; +- GtkWidget *browse_files_popup_menu_hidden_files_item; + GtkWidget *browse_new_folder_button; +- GtkWidget *browse_path_bar_hbox; +- GtkWidget *browse_path_bar; ++ GtkWidget *bar; ++ GtkWidget *up_button; + + GtkFileSystemModel *browse_files_model; +- char *browse_files_last_selected_name; ++ char *browse_files_last_selected_name; /* ??? */ + +- /* OPERATION_MODE_SEARCH */ +- GtkWidget *search_hbox; +- GtkWidget *search_entry; +- GtkSearchEngine *search_engine; +- GtkQuery *search_query; +- GtkListStore *search_model; +- GtkTreeModelFilter *search_model_filter; +- GtkTreeModelSort *search_model_sort; +- +- /* OPERATION_MODE_RECENT */ +- GtkRecentManager *recent_manager; +- GtkListStore *recent_model; +- guint load_recent_id; +- GtkTreeModelFilter *recent_model_filter; +- GtkTreeModelSort *recent_model_sort; +- +- GtkWidget *filter_combo_hbox; + GtkWidget *filter_combo; +- GtkWidget *preview_box; +- GtkWidget *preview_label; +- GtkWidget *preview_widget; +- GtkWidget *extra_align; +- GtkWidget *extra_widget; + + GtkWidget *location_button; + GtkWidget *location_entry_box; +@@ -217,23 +174,13 @@ + LocationMode location_mode; + + GtkListStore *shortcuts_model; ++ GtkTreeModel *shortcuts_filter_model; + +- /* Filter for the shortcuts pane. We filter out the "current folder" row and +- * the separator that we use for the "Save in folder" combo. +- */ +- GtkTreeModel *shortcuts_pane_filter_model; +- +- /* Filter for the "Save in folder" combo. We filter out the Search row and +- * its separator. +- */ +- GtkTreeModel *shortcuts_combo_filter_model; +- + GtkTreeModelSort *sort_model; + + /* Handles */ + GSList *loading_shortcuts; + GSList *reload_icon_handles; +- GtkFileSystemHandle *file_list_drag_data_received_handle; + GtkFileSystemHandle *update_current_folder_handle; + GtkFileSystemHandle *show_and_select_paths_handle; + GtkFileSystemHandle *should_respond_get_info_handle; +@@ -246,9 +193,8 @@ + ReloadState reload_state; + guint load_timeout_id; + +- OperationMode operation_mode; +- + GSList *pending_select_paths; ++ GSList *path_history; + + GtkFileFilter *current_filter; + GSList *filters; +@@ -256,20 +202,16 @@ + GtkTooltips *tooltips; + + int num_volumes; +- int num_shortcuts; +- int num_bookmarks; + + gulong volumes_changed_id; +- gulong bookmarks_changed_id; + + GtkFilePath *current_volume_path; + GtkFilePath *current_folder; +- GtkFilePath *preview_path; +- char *preview_display_name; + + GtkTreeViewColumn *list_name_column; + GtkCellRenderer *list_name_renderer; +- GtkTreeViewColumn *list_mtime_column; ++ guint32 list_press_time; ++ GtkTreePath *list_press_path; + + GSource *edited_idle; + char *edited_new_text; +@@ -280,10 +222,7 @@ + gulong toplevel_set_focus_id; + GtkWidget *toplevel_last_focus_widget; + +-#if 0 +- GdkDragContext *shortcuts_drag_context; +- GSource *shortcuts_drag_outside_idle; +-#endif ++ gchar * root_folder; + + gint default_width; + gint default_height; +@@ -291,23 +230,13 @@ + /* Flags */ + + guint local_only : 1; +- guint preview_widget_active : 1; +- guint use_preview_label : 1; + guint select_multiple : 1; + guint show_hidden : 1; ++ guint show_create_folder : 1; + guint do_overwrite_confirmation : 1; + guint list_sort_ascending : 1; + guint changing_folder : 1; +- guint shortcuts_current_folder_active : 1; + guint expand_folders : 1; +- guint has_home : 1; +- guint has_desktop : 1; +- guint has_search : 1; +- guint has_recent : 1; +- +-#if 0 +- guint shortcuts_drag_outside : 1; +-#endif + }; + + +Index: gtk+-2.12.5/tests/autotestfilechooser.c +=================================================================== +--- gtk+-2.12.5/tests/autotestfilechooser.c (revision 19337) ++++ gtk+-2.12.5/tests/autotestfilechooser.c (working copy) +@@ -510,9 +510,6 @@ + && (impl->location_mode == LOCATION_MODE_PATH_BAR + ? impl->location_entry == NULL + : impl->location_entry != NULL) +- && impl->save_folder_label == NULL +- && impl->save_folder_combo == NULL +- && impl->save_expander == NULL + && GTK_IS_CONTAINER (impl->browse_widgets) && GTK_WIDGET_DRAWABLE (impl->browse_widgets)); + } + else if (has_action (save_actions, G_N_ELEMENTS (save_actions), impl->action)) +@@ -523,9 +520,6 @@ + */ + passed = passed && (GTK_IS_CONTAINER (impl->save_widgets) && GTK_WIDGET_DRAWABLE (impl->save_widgets) + && impl->location_entry != NULL && GTK_WIDGET_DRAWABLE (impl->location_entry) +- && GTK_IS_LABEL (impl->save_folder_label) && GTK_WIDGET_DRAWABLE (impl->save_folder_label) +- && GTK_IS_COMBO_BOX (impl->save_folder_combo) && GTK_WIDGET_DRAWABLE (impl->save_folder_combo) +- && GTK_IS_EXPANDER (impl->save_expander) && GTK_WIDGET_DRAWABLE (impl->save_expander) + && GTK_IS_CONTAINER (impl->browse_widgets)); + + /* FIXME: we are in a SAVE mode; test the visibility and sensitivity of +@@ -1026,11 +1020,6 @@ + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir); + sleep_in_main_loop (500); + +- g_signal_emit_by_name (impl->browse_path_bar, "path-clicked", +- (GtkFilePath *) cwd_path, +- (GtkFilePath *) base_dir_path, +- FALSE); +- sleep_in_main_loop (500); + passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter); + + log_test (passed, "test_folder_switch_and_filters(): filter after changing folder"); diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-props.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-props.patch new file mode 100644 index 0000000000..7d55f3cbb9 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-props.patch @@ -0,0 +1,57 @@ +Index: gtk+-2.12.3/gtk/gtkfilechooser.c +=================================================================== +--- gtk+-2.12.3.orig/gtk/gtkfilechooser.c 2007-12-04 16:52:08.000000000 +0000 ++++ gtk+-2.12.3/gtk/gtkfilechooser.c 2008-01-02 13:15:38.000000000 +0000 +@@ -272,6 +272,20 @@ + "if necessary."), + FALSE, + GTK_PARAM_READWRITE)); ++ ++ g_object_interface_install_property (g_iface, ++ g_param_spec_string ("root-folder", ++ P_("File System Root"), ++ P_("Root folder for the file system below which the user should not be able to switch"), ++ NULL, ++ G_PARAM_WRITABLE)); ++ ++ g_object_interface_install_property (g_iface, ++ g_param_spec_boolean ("show-create-folder", ++ P_("Show Create Folder button"), ++ P_("Whether the Create Folder button should be visible on the bar"), ++ TRUE, ++ G_PARAM_READWRITE)); + } + + /** +Index: gtk+-2.12.3/gtk/gtkfilechooserutils.h +=================================================================== +--- gtk+-2.12.3.orig/gtk/gtkfilechooserutils.h 2007-12-04 16:52:08.000000000 +0000 ++++ gtk+-2.12.3/gtk/gtkfilechooserutils.h 2008-01-02 13:15:17.000000000 +0000 +@@ -41,7 +41,9 @@ + GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE, + GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN, + GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION, +- GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION ++ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER, ++ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER, ++ GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER + } GtkFileChooserProp; + + void _gtk_file_chooser_install_properties (GObjectClass *klass); +Index: gtk+-2.12.3/gtk/gtkfilechooserutils.c +=================================================================== +--- gtk+-2.12.3.orig/gtk/gtkfilechooserutils.c 2007-12-04 16:52:08.000000000 +0000 ++++ gtk+-2.12.3/gtk/gtkfilechooserutils.c 2008-01-02 13:15:17.000000000 +0000 +@@ -117,6 +117,12 @@ + g_object_class_override_property (klass, + GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION, + "do-overwrite-confirmation"); ++ g_object_class_override_property (klass, ++ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER, ++ "root-folder"); ++ g_object_class_override_property (klass, ++ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER, ++ "show-create-folder"); + } + + /** diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-sizefix.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-sizefix.patch new file mode 100644 index 0000000000..694b059b9a --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filechooser-sizefix.patch @@ -0,0 +1,35 @@ +--- gtk+-2.12.7.orig/gtk/gtkfilechooserdialog.c ++++ gtk+-2.12.7/gtk/gtkfilechooserdialog.c +@@ -165,10 +165,10 @@ + gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + + if (width) +- *width = MIN (*width, (monitor.width * 3) / 4); ++ *width = MIN (*width, monitor.width); + + if (height) +- *height = MIN (*height, (monitor.height * 3) / 4); ++ *height = MIN (*height, monitor.height); + } + + static void +@@ -183,6 +183,7 @@ + + priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog); + ++#if 0 + /* Unset any previously set size */ + gtk_widget_set_size_request (GTK_WIDGET (dialog), -1, -1); + +@@ -209,6 +210,11 @@ + /* Ideal target size plus any extra size */ + width = default_width + width + (2 * GTK_CONTAINER (dialog)->border_width); + height = default_height + height + (2 * GTK_CONTAINER (dialog)->border_width); ++#endif ++ ++ /* for small screens we just hard code a sensible value */ ++ width = 350; ++ height = 350; + + if (GTK_WIDGET_REALIZED (dialog)) + clamp_to_screen (GTK_WIDGET (dialog), &width, &height); diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/filesystem-volumes.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filesystem-volumes.patch new file mode 100644 index 0000000000..826fd6bee0 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/filesystem-volumes.patch @@ -0,0 +1,198 @@ +Index: gtk+-2.12.3/gtk/gtkfilesystemunix.c +=================================================================== +--- gtk+-2.12.3.orig/gtk/gtkfilesystemunix.c 2007-12-04 16:52:08.000000000 +0000 ++++ gtk+-2.12.3/gtk/gtkfilesystemunix.c 2008-01-02 13:15:02.000000000 +0000 +@@ -38,6 +38,7 @@ + #include <errno.h> + #include <string.h> + #include <sys/stat.h> ++#include <sys/statvfs.h> + #include <sys/types.h> + #include <pwd.h> + #ifdef HAVE_UNISTD_H +@@ -474,7 +475,55 @@ + static GSList * + gtk_file_system_unix_list_volumes (GtkFileSystem *file_system) + { +- return g_slist_append (NULL, get_root_volume ()); ++ struct statvfs stv; ++ struct stat st; ++ GSList * l = g_slist_append (NULL, get_root_volume ()); ++ ++ if (!statvfs ("/.", &stv)) ++ { ++ fsblkcnt_t root_blocks = stv.f_blocks; ++ fsfilcnt_t root_files = stv.f_files; ++ ++ GDir * dir; ++ if ((dir = g_dir_open ("/media", 0, NULL)) != NULL) ++ { ++ const gchar * name; ++ while ((name = g_dir_read_name (dir)) != NULL) ++ { ++ gchar * abs_name; ++ ++ /* Skip ram disks */ ++ if (!strcmp (name, "ram")) ++ continue; ++ ++ abs_name = g_strconcat ("/media/", name, NULL); ++ ++ if (!stat (abs_name, &st) && S_ISDIR (st.st_mode)) ++ { ++ gchar * dot = g_strconcat (abs_name, "/.", NULL); ++ if (!statvfs (dot, &stv) && ++ (stv.f_blocks != root_blocks || ++ stv.f_files != root_files)) ++ { ++ GtkFilePath * path = ++ gtk_file_system_filename_to_path (file_system, ++ abs_name); ++ ++ if (path) ++ l = g_slist_append (l, path); ++ } ++ ++ g_free (dot); ++ } ++ ++ g_free (abs_name); ++ } ++ ++ g_dir_close (dir); ++ } ++ } ++ ++ return l; + } + + static GtkFileSystemVolume * +@@ -488,13 +537,18 @@ + remove_trailing_slash (const char *filename) + { + int len; +- ++ + len = strlen (filename); + +- if (len > 1 && filename[len - 1] == '/') +- return g_strndup (filename, len - 1); +- else +- return g_memdup (filename, len + 1); ++ if (len > 1) ++ { ++ gchar *c = g_utf8_prev_char (filename + len); ++ ++ if (c && *c == '/') ++ return g_strndup (filename, len - 1); ++ } ++ ++ return g_memdup (filename, len + 1); + } + + /* Delay callback dispatching +@@ -1128,7 +1182,7 @@ + gtk_file_system_unix_volume_get_base_path (GtkFileSystem *file_system, + GtkFileSystemVolume *volume) + { +- return gtk_file_path_new_dup ("/"); ++ return gtk_file_path_copy ((GtkFilePath*)volume); + } + + static gboolean +@@ -1162,7 +1216,32 @@ + gtk_file_system_unix_volume_get_display_name (GtkFileSystem *file_system, + GtkFileSystemVolume *volume) + { +- return g_strdup (_("File System")); /* Same as Nautilus */ ++ gchar * slash; ++ gchar * path; ++ gchar * c; ++ ++ g_return_val_if_fail (file_system && volume, NULL); ++ ++ path = gtk_file_system_path_to_filename (file_system, (GtkFilePath*) volume); ++ ++ g_return_val_if_fail (path && *path, NULL); ++ ++ if (path[0] == '/' && !path[1]) ++ return g_strdup (_("Filesystem")); /* Same as Nautilus */ ++ ++ /* Now the media volumes */ ++ /* strip trailing / if any */ ++ c = g_utf8_prev_char (path + strlen(path)); ++ ++ if (*c == '/') ++ *c = 0; ++ ++ slash = g_utf8_strrchr (path, -1, '/'); ++ ++ if (!slash) ++ return g_strdup (path); ++ ++ return g_strdup (slash + 1); + } + + static IconType +@@ -1250,10 +1329,57 @@ + GtkFileSystemVolume *volume, + GError **error) + { +- /* FIXME: maybe we just always want to return GTK_STOCK_HARDDISK here? +- * or the new tango icon name? +- */ +- return g_strdup ("gnome-dev-harddisk"); ++ gchar * c; ++ gchar * slash; ++ gchar * path = NULL; ++ GtkFilePath * fpath; ++ const gchar * id = NULL; ++ ++ g_return_val_if_fail (file_system && volume, NULL); ++ ++ fpath = gtk_file_system_volume_get_base_path (file_system, volume); ++ ++ if (!fpath) ++ goto out; ++ ++ path = gtk_file_system_path_to_filename (file_system, fpath); ++ gtk_file_path_free (fpath); ++ ++ if (!path || !*path || (*path == '/' && !path[1])) ++ goto out; ++ ++ /* Now the media volumes */ ++ /* strip trailing / if any */ ++ c = g_utf8_prev_char (path + strlen(path)); ++ ++ if (*c == '/') ++ *c = 0; ++ ++ slash = g_utf8_strrchr (path, -1, '/'); ++ ++ if (slash) ++ { ++ slash++; ++ ++ if (!strcmp (slash, "card")) ++ id = "gnome-dev-media-sdmmc"; ++ else if (!strcmp (slash, "cf")) ++ id = "gnome-dev-media-cf"; ++ else if (!strncmp (slash, "mmc", 3)) ++ id = "gnome-dev-media-sdmmc"; ++ else if (!strcmp (slash, "usbhdd")) ++ id = "gnome-dev-removable-usb"; ++ else ++ id = "gnome-dev-removable"; ++ } ++ ++ out: ++ g_free (path); ++ ++ if (!id) ++ id = "gnome-fs-blockdev"; ++ ++ return g_strdup (id); + } + + static char * diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/gtklabel-resize-patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/gtklabel-resize-patch new file mode 100644 index 0000000000..df29656343 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/gtklabel-resize-patch @@ -0,0 +1,10 @@ +--- gtk+-2.4.3/gtk/gtklabel.c~ 2004-06-11 13:50:34.000000000 +0100 ++++ gtk+-2.4.3/gtk/gtklabel.c 2004-07-05 13:33:57.000000000 +0100 +@@ -1623,6 +1623,7 @@ + + /* We have to clear the layout, fonts etc. may have changed */ + gtk_label_clear_layout (label); ++ gtk_widget_queue_resize (GTK_WIDGET (label)); + } + + static void diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/hardcoded_libtool.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/hardcoded_libtool.patch new file mode 100644 index 0000000000..1c2cd0576d --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/hardcoded_libtool.patch @@ -0,0 +1,29 @@ +--- /tmp/configure.in 2007-01-08 17:50:49.000000000 +0100 ++++ gtk+-2.10.7/configure.in 2007-01-08 17:52:33.495251000 +0100 +@@ -371,7 +371,7 @@ + case $enable_explicit_deps in + auto) + export SED +- deplibs_check_method=`(./libtool --config; echo 'eval echo $deplibs_check_method') | sh` ++ deplibs_check_method=`($host_alias-libtool --config; echo 'eval echo $deplibs_check_method') | sh` + if test "x$deplibs_check_method" '!=' xpass_all || test "x$enable_static" = xyes ; then + enable_explicit_deps=yes + else +@@ -773,7 +773,7 @@ + dnl Now we check to see if our libtool supports shared lib deps + dnl (in a rather ugly way even) + if $dynworks; then +- pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} ./libtool --config" ++ pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} $host_alias-libtool --config" + pixbuf_deplibs_check=`$pixbuf_libtool_config | \ + grep '^[[a-z_]]*check[[a-z_]]*_method=[['\''"]]' | \ + sed 's/.*[['\''"]]\(.*\)[['\''"]]$/\1/'` +@@ -1611,7 +1611,7 @@ + # We are using gmodule-no-export now, but I'm leaving the stripping + # code in place for now, since pango and atk still require gmodule. + export SED +-export_dynamic=`(./libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh` ++export_dynamic=`($host_alias-libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh` + if test -n "$export_dynamic"; then + GDK_PIXBUF_DEP_LIBS=`echo $GDK_PIXBUF_DEP_LIBS | sed -e "s/$export_dynamic//"` + GDK_PIXBUF_XLIB_DEP_LIBS=`echo $GDK_PIXBUF_XLIB_DEP_LIBS | sed -e "s/$export_dynamic//"` diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/menu-deactivate.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/menu-deactivate.patch new file mode 100644 index 0000000000..cfb8849e9f --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/menu-deactivate.patch @@ -0,0 +1,51 @@ +--- gtk+-2.10.0/gtk/gtkmenushell.c.orig 2006-07-05 17:17:34.000000000 +0200 ++++ gtk+-2.10.0/gtk/gtkmenushell.c 2006-07-05 17:19:01.000000000 +0200 +@@ -42,7 +42,7 @@ + #include "gtkintl.h" + #include "gtkalias.h" + +-#define MENU_SHELL_TIMEOUT 500 ++#define MENU_SHELL_TIMEOUT 2000 + + #define PACK_DIRECTION(m) \ + (GTK_IS_MENU_BAR (m) \ +@@ -203,6 +203,8 @@ + + G_DEFINE_TYPE (GtkMenuShell, gtk_menu_shell, GTK_TYPE_CONTAINER) + ++static int last_crossing_time; ++ + static void + gtk_menu_shell_class_init (GtkMenuShellClass *klass) + { +@@ -517,6 +519,7 @@ + gtk_grab_add (GTK_WIDGET (menu_shell)); + menu_shell->have_grab = TRUE; + menu_shell->active = TRUE; ++ last_crossing_time = 0; + } + } + +@@ -669,6 +672,13 @@ + menu_shell->activate_time = 0; + deactivate = FALSE; + } ++ ++ if (last_crossing_time != 0 ++ && ((event->time - last_crossing_time) < 500)) ++ { ++ last_crossing_time = 0; ++ deactivate = FALSE; ++ } + + if (deactivate) + { +@@ -716,6 +726,8 @@ + { + menu_item = gtk_get_event_widget ((GdkEvent*) event); + ++ last_crossing_time = event->time; ++ + if (!menu_item || + (GTK_IS_MENU_ITEM (menu_item) && + !_gtk_menu_item_is_selectable (menu_item))) diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/no-demos.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/no-demos.patch new file mode 100644 index 0000000000..0fc4c48d1a --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/no-demos.patch @@ -0,0 +1,10 @@ +--- gtk+-2.10.1/Makefile.am.orig 2006-08-08 12:37:30.000000000 +0100 ++++ gtk+-2.10.1/Makefile.am 2006-08-08 12:37:48.000000000 +0100 +@@ -1,6 +1,6 @@ + ## Makefile.am for GTK+ + +-SRC_SUBDIRS = gdk-pixbuf gdk gtk modules demos tests perf contrib ++SRC_SUBDIRS = gdk-pixbuf gdk gtk modules tests perf contrib + SUBDIRS = po po-properties $(SRC_SUBDIRS) docs m4macros + + # require automake 1.4 diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/pangoxft2.10.6.diff b/meta/recipes-gnome/gtk+/gtk+-2.12.7/pangoxft2.10.6.diff new file mode 100644 index 0000000000..63828cec63 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/pangoxft2.10.6.diff @@ -0,0 +1,2456 @@ +http://mail.gnome.org/archives/performance-list/2006-October/msg00063.html + +From: Xan Lópe +To: ext Matt Hoosier +Cc: performance-list gnome org +Subject: Re: [patch] Remove pangocairo from Gtk+ 2.8.20 +Date: Mon, 30 Oct 2006 14:31:56 +0200 +Hi, + +I've upgraded your patch against GTK+ 2.10.6, and we are getting great +performance figures compared to GTK+ 2.10.6 with pangocairo too +(basically at the level of GTK+ 2.6.10 again). Right now I'm working on +a python/cairo script to get some nice graphics from a torture test +session with several GTK+s, hope to get it ready soon. + +Index: gtk+-2.10.6/configure.in +=================================================================== +--- gtk+-2.10.6.orig/configure.in 2006-10-30 12:59:28.000000000 +0000 ++++ gtk+-2.10.6/configure.in 2006-10-30 12:59:30.000000000 +0000 +@@ -1435,7 +1435,7 @@ + if test "x$gdktarget" = "xwin32"; then + PANGO_PACKAGES="pangowin32 pangocairo" + else +- PANGO_PACKAGES="pango pangocairo" ++ PANGO_PACKAGES="pango pangocairo pangoxft" + fi + + AC_MSG_CHECKING(Pango flags) +Index: gtk+-2.10.6/gdk/gdkaliasdef.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/gdkaliasdef.c 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/gdkaliasdef.c 2006-10-30 12:59:30.000000000 +0000 +@@ -1799,9 +1799,6 @@ + #undef gdk_pango_context_get + extern __typeof (gdk_pango_context_get) gdk_pango_context_get __attribute((alias("IA__gdk_pango_context_get"), visibility("default"))); + +-#undef gdk_pango_context_get_for_screen +-extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default"))); +- + #ifndef GDK_DISABLE_DEPRECATED + #undef gdk_pango_context_set_colormap + extern __typeof (gdk_pango_context_set_colormap) gdk_pango_context_set_colormap __attribute((alias("IA__gdk_pango_context_set_colormap"), visibility("default"))); +@@ -1836,6 +1833,13 @@ + + #endif + #endif ++#if IN_HEADER(__GDK_PANGO_H__) ++#if IN_FILE(__GDK_PANGO_X11_C__) ++#undef gdk_pango_context_get_for_screen ++extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default"))); ++ ++#endif ++#endif + #if IN_HEADER(__GDK_PIXBUF_H__) + #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__) + #undef gdk_pixbuf_get_from_drawable +Index: gtk+-2.10.6/gdk/gdkalias.h +=================================================================== +--- gtk+-2.10.6.orig/gdk/gdkalias.h 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/gdkalias.h 2006-10-30 12:59:30.000000000 +0000 +@@ -1796,9 +1796,6 @@ + extern __typeof (gdk_pango_context_get) IA__gdk_pango_context_get __attribute((visibility("hidden"))); + #define gdk_pango_context_get IA__gdk_pango_context_get + +-extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden"))); +-#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen +- + #ifndef GDK_DISABLE_DEPRECATED + extern __typeof (gdk_pango_context_set_colormap) IA__gdk_pango_context_set_colormap __attribute((visibility("hidden"))); + #define gdk_pango_context_set_colormap IA__gdk_pango_context_set_colormap +@@ -1833,6 +1830,13 @@ + + #endif + #endif ++#if IN_HEADER(__GDK_PANGO_H__) ++#if IN_FILE(__GDK_PANGO_X11_C__) ++extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden"))); ++#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen ++ ++#endif ++#endif + #if IN_HEADER(__GDK_PIXBUF_H__) + #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__) + extern __typeof (gdk_pixbuf_get_from_drawable) IA__gdk_pixbuf_get_from_drawable __attribute((visibility("hidden"))); +Index: gtk+-2.10.6/gdk/gdkdraw.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/gdkdraw.c 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/gdkdraw.c 2006-10-30 12:59:30.000000000 +0000 +@@ -909,9 +909,9 @@ + { + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); +- +- real_draw_glyphs (drawable, gc, NULL, font, +- x, y, glyphs); ++ ++ ++ GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs); + } + + /** +@@ -949,8 +949,9 @@ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + +- real_draw_glyphs (drawable, gc, matrix, font, +- x / PANGO_SCALE, y / PANGO_SCALE, glyphs); ++ if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed) ++ GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed (drawable, gc, matrix, ++ font, x, y, glyphs); + } + + /** +@@ -974,28 +975,12 @@ + GdkTrapezoid *trapezoids, + gint n_trapezoids) + { +- cairo_t *cr; +- int i; +- + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL); + +- cr = gdk_cairo_create (drawable); +- _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE); +- +- for (i = 0; i < n_trapezoids; i++) +- { +- cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1); +- cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y1); +- cairo_line_to (cr, trapezoids[i].x22, trapezoids[i].y2); +- cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y2); +- cairo_close_path (cr); +- } +- +- cairo_fill (cr); +- +- cairo_destroy (cr); ++ GDK_DRAWABLE_GET_CLASS (drawable)->draw_trapezoids (drawable, gc, ++ trapezoids, n_trapezoids); + } + + /** +Index: gtk+-2.10.6/gdk/gdkpango.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/gdkpango.c 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/gdkpango.c 2006-10-30 12:59:30.000000000 +0000 +@@ -50,19 +50,34 @@ + GdkBitmap *stipple[MAX_RENDER_PART + 1]; + gboolean embossed; + +- cairo_t *cr; +- PangoRenderPart last_part; ++ /* When switching between the normal and shadow copies when ++ * drawing shadows we can get unexpected recursion into the ++ * drawing functions; the 'in_emboss' flag guards against that. ++ */ ++ gboolean in_emboss; + + /* Current target */ + GdkDrawable *drawable; + GdkGC *base_gc; + + gboolean gc_changed; ++ ++ /* Cached GC, derived from base_gc */ ++ GdkGC *gc; ++ PangoColor gc_color; ++ gboolean gc_color_set; ++ GdkBitmap *gc_stipple; ++ ++ /* we accumulate trapezoids for the same PangoRenderPart */ ++ GArray *trapezoids; ++ PangoRenderPart trapezoid_part; + }; + + static PangoAttrType gdk_pango_attr_stipple_type; + static PangoAttrType gdk_pango_attr_embossed_type; + ++static void flush_trapezoids (GdkPangoRenderer *gdk_renderer); ++ + enum { + PROP_0, + PROP_SCREEN +@@ -77,6 +92,10 @@ + GdkPangoRendererPrivate *priv = gdk_renderer->priv; + int i; + ++ if (priv->gc) ++ g_object_unref (priv->gc); ++ if (priv->gc_stipple) ++ g_object_unref (priv->gc_stipple); + if (priv->base_gc) + g_object_unref (priv->base_gc); + if (priv->drawable) +@@ -86,6 +105,8 @@ + if (priv->stipple[i]) + g_object_unref (priv->stipple[i]); + ++ g_array_free (priv->trapezoids, TRUE); ++ + G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object); + } + +@@ -112,25 +133,6 @@ + return object; + } + +-/* Adjusts matrix and color for the renderer to draw the secondary +- * "shadow" copy for embossed text */ +-static void +-emboss_context (cairo_t *cr) +-{ +- cairo_matrix_t tmp_matrix; +- +- /* The gymnastics here to adjust the matrix are because we want +- * to offset by +1,+1 in device-space, not in user-space, +- * so we can't just draw the layout at x + 1, y + 1 +- */ +- cairo_get_matrix (cr, &tmp_matrix); +- tmp_matrix.x0 += 1.0; +- tmp_matrix.y0 += 1.0; +- cairo_set_matrix (cr, &tmp_matrix); +- +- cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); +-} +- + static inline gboolean + color_equal (PangoColor *c1, PangoColor *c2) + { +@@ -146,74 +148,154 @@ + return FALSE; + } + +-static cairo_t * +-get_cairo_context (GdkPangoRenderer *gdk_renderer, +- PangoRenderPart part) ++/* Adjusts matrix and color for the renderer to draw the secondar ++ * "shadow" copy for embossed text */ ++static void ++emboss_renderer (PangoRenderer *renderer, ++ PangoRenderPart part, ++ PangoMatrix **save_matrix, ++ PangoColor **save_color) ++{ ++ GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; ++ static const PangoColor white = { 0xffff, 0xffff, 0xffff }; ++ PangoMatrix tmp_matrix = PANGO_MATRIX_INIT; ++ ++ priv->in_emboss = TRUE; ++ ++ *save_color = pango_renderer_get_color (renderer, part); ++ if (*save_color) ++ *save_color = pango_color_copy (*save_color); ++ ++ *save_matrix = renderer->matrix; ++ if (*save_matrix) ++ { ++ *save_matrix = pango_matrix_copy (*save_matrix); ++ tmp_matrix = **save_matrix; ++ } ++ ++ /* The gymnastics here to adjust the matrix are because we want ++ * to offset by +1,+1 in device-space, not in user-space, ++ * so we can't just draw the layout at x + 1, y + 1 ++ */ ++ tmp_matrix.x0 += 1; ++ tmp_matrix.y0 += 1; ++ ++ pango_renderer_set_matrix (renderer, &tmp_matrix); ++ pango_renderer_set_color (renderer, part, &white); ++} ++ ++/* Restores from emboss_renderer() */ ++static void ++unemboss_renderer (PangoRenderer *renderer, ++ PangoRenderPart part, ++ PangoMatrix **save_matrix, ++ PangoColor **save_color) ++{ ++ GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; ++ pango_renderer_set_matrix (renderer, *save_matrix); ++ pango_renderer_set_color (renderer, part, *save_color); ++ ++ if (*save_matrix) ++ pango_matrix_free (*save_matrix); ++ if (*save_color) ++ pango_color_free (*save_color); ++ ++ priv->in_emboss = FALSE; ++} ++ ++/* Gets the GC for drawing @part. This make involve copying the base GC ++ * for the renderer, in which case we keep a one-GC cache. */ ++static GdkGC * ++get_gc (GdkPangoRenderer *gdk_renderer, ++ PangoRenderPart part) + { + PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer); ++ PangoColor *color; ++ GdkBitmap *stipple; + GdkPangoRendererPrivate *priv = gdk_renderer->priv; + +- if (!priv->cr) ++ color = pango_renderer_get_color (renderer, part); ++ ++ if (part <= MAX_RENDER_PART) ++ stipple = priv->stipple[part]; ++ else ++ stipple = NULL; ++ ++ if (!color && !stipple) /* nothing override, use base_gc */ ++ return priv->base_gc; ++ else + { +- const PangoMatrix *matrix; ++ gboolean new_stipple = FALSE; ++ gboolean new_color = FALSE; + +- priv->cr = gdk_cairo_create (priv->drawable); ++ if (stipple != priv->gc_stipple) ++ new_stipple = TRUE; + +- matrix = pango_renderer_get_matrix (renderer); +- if (matrix) ++ if ((priv->gc_color_set && !color) || ++ (!priv->gc_color_set && color) || ++ priv->gc_color.red != color->red || ++ priv->gc_color.green != color->green || ++ priv->gc_color.blue != color->blue) ++ new_color = TRUE; ++ ++ if (!priv->gc) + { +- cairo_matrix_t cairo_matrix; +- +- cairo_matrix_init (&cairo_matrix, +- matrix->xx, matrix->yx, +- matrix->xy, matrix->yy, +- matrix->x0, matrix->y0); +- cairo_set_matrix (priv->cr, &cairo_matrix); ++ priv->gc = gdk_gc_new (priv->drawable); ++ gdk_gc_copy (priv->gc, priv->base_gc); ++ } ++ else if (new_color && priv->gc_color_set && !color) ++ { ++ /* We have to recopy the original GC onto the cached GC ++ * to get the default color */ ++ new_stipple = TRUE; ++ gdk_gc_copy (priv->gc, priv->base_gc); ++ } ++ else if (new_stipple && priv->gc_stipple && !stipple) ++ { ++ /* Similarly, we need to make a new copy to restore to the ++ * default stipple state (the caller may have set a stipple ++ * on the GC, and even if not, gdk_gc_set_stipple (gc, NULL) ++ * doesn't work currently to restore to the default X stipple) */ ++ new_color = TRUE; ++ gdk_gc_copy (priv->gc, priv->base_gc); + } +- } +- +- if (part != priv->last_part) +- { +- PangoColor *pango_color; +- GdkColor *color; +- GdkColor tmp_color; +- gboolean changed; + +- pango_color = pango_renderer_get_color (renderer, part); +- +- if (priv->last_part != -1) +- changed = priv->gc_changed || +- priv->stipple[priv->last_part] != priv->stipple[part] || +- !color_equal (pango_color, +- pango_renderer_get_color (renderer, priv->last_part)); +- else +- changed = TRUE; +- +- if (changed) ++ if (new_color) + { +- if (pango_color) ++ if (color) + { +- tmp_color.red = pango_color->red; +- tmp_color.green = pango_color->green; +- tmp_color.blue = pango_color->blue; ++ GdkColor gdk_color; ++ ++ gdk_color.red = color->red; ++ gdk_color.green = color->green; ++ gdk_color.blue = color->blue; + +- color = &tmp_color; ++ gdk_gc_set_rgb_fg_color (priv->gc, &gdk_color); ++ ++ priv->gc_color = *color; ++ priv->gc_color_set = TRUE; + } + else +- color = NULL; ++ priv->gc_color_set = FALSE; ++ } + +- _gdk_gc_update_context (priv->base_gc, +- priv->cr, +- color, +- priv->stipple[part], +- priv->gc_changed); ++ if (new_stipple) ++ { ++ if (priv->gc_stipple) ++ g_object_unref (priv->gc_stipple); ++ ++ if (stipple) ++ { ++ gdk_gc_set_stipple (priv->gc, stipple); ++ gdk_gc_set_fill (priv->gc, GDK_STIPPLED); ++ priv->gc_stipple = g_object_ref (stipple); ++ } ++ else ++ priv->gc_stipple = NULL; + } + +- priv->last_part = part; +- priv->gc_changed = FALSE; ++ return priv->gc; + } +- +- return priv->cr; + } + + static void +@@ -225,133 +307,78 @@ + { + GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); + GdkPangoRendererPrivate *priv = gdk_renderer->priv; +- cairo_t *cr; + +- cr = get_cairo_context (gdk_renderer, +- PANGO_RENDER_PART_FOREGROUND); ++ flush_trapezoids (gdk_renderer); + +- if (priv->embossed) ++ if (!priv->in_emboss && priv->embossed) + { +- cairo_save (cr); +- emboss_context (cr); +- cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE); +- pango_cairo_show_glyph_string (cr, font, glyphs); +- cairo_restore (cr); +- } +- +- cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE); +- pango_cairo_show_glyph_string (cr, font, glyphs); +-} +- +-/* Draws an error underline that looks like one of: +- * H E H +- * /\ /\ /\ /\ /\ - +- * A/ \ / \ / \ A/ \ / \ | +- * \ \ / \ / /D \ \ / \ | +- * \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square +- * \ /\ F / \ F /\ \ | +- * \ / \ / \ / \ \G | +- * \ / \ / \ / \ / | +- * \/ \/ \/ \/ - +- * B B +- * |----| +- * unit_width = (HEIGHT_SQUARES - 1) * square +- * +- * The x, y, width, height passed in give the desired bounding box; +- * x/width are adjusted to make the underline a integer number of units +- * wide. +- */ +-#define HEIGHT_SQUARES 2.5 ++ PangoMatrix *save_matrix; ++ PangoColor *save_color; + +-/* Cut-and-pasted between here and pango/pango/pangocairo-render.c */ ++ emboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); ++ gdk_draw_glyphs_transformed (priv->drawable, ++ get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), ++ renderer->matrix, font, x, y, glyphs); ++ unemboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); ++ } ++ ++ gdk_draw_glyphs_transformed (priv->drawable, ++ get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), ++ renderer->matrix, font, x, y, glyphs); ++} ++ ++/* Outputs any pending trapezoids, we do this when the part or ++ * part color changes, when we are about to draw text, etc. */ + static void +-draw_error_underline (cairo_t *cr, +- double x, +- double y, +- double width, +- double height) +-{ +- double square = height / HEIGHT_SQUARES; +- double unit_width = (HEIGHT_SQUARES - 1) * square; +- int width_units = (width + unit_width / 2) / unit_width; +- double y_top, y_bottom; +- int i; ++flush_trapezoids (GdkPangoRenderer *gdk_renderer) ++{ ++ GdkPangoRendererPrivate *priv = gdk_renderer->priv; + +- x += (width - width_units * unit_width) / 2; +- width = width_units * unit_width; ++ if (!priv->trapezoids || priv->trapezoids->len == 0) ++ return; + +- y_top = y; +- y_bottom = y + height; +- +- /* Bottom of squiggle */ +- cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */ +- for (i = 0; i < width_units; i += 2) +- { +- double x_middle = x + (i + 1) * unit_width; +- double x_right = x + (i + 2) * unit_width; +- +- cairo_line_to (cr, x_middle, y_bottom); /* B */ +- +- if (i + 1 == width_units) +- /* Nothing */; +- else if (i + 2 == width_units) +- cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */ +- else +- cairo_line_to (cr, x_right, y_top + square); /* C */ +- } +- +- /* Top of squiggle */ +- for (i -= 2; i >= 0; i -= 2) +- { +- double x_left = x + i * unit_width; +- double x_middle = x + (i + 1) * unit_width; +- double x_right = x + (i + 2) * unit_width; +- +- if (i + 1 == width_units) +- cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */ +- else { +- if (i + 2 == width_units) +- cairo_line_to (cr, x_right, y_top); /* E */ +- cairo_line_to (cr, x_middle, y_bottom - square); /* F */ +- } +- +- cairo_line_to (cr, x_left, y_top); /* H */ +- } ++ gdk_draw_trapezoids (priv->drawable, ++ get_gc (gdk_renderer, priv->trapezoid_part), ++ (GdkTrapezoid *)priv->trapezoids->data, ++ priv->trapezoids->len); + +- cairo_close_path (cr); +- cairo_fill (cr); ++ g_array_set_size (priv->trapezoids, 0); + } + ++/* Draws a single trapezoid ... we don't draw it immediately, but rather ++ * cache it to join together with other trapezoids that form part of the ++ * same logical shape */ + static void +-gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, +- PangoRenderPart part, +- int x, +- int y, +- int width, +- int height) ++gdk_pango_renderer_draw_trapezoid (PangoRenderer *renderer, ++ PangoRenderPart part, ++ double y1, ++ double x11, ++ double x21, ++ double y2, ++ double x12, ++ double x22) + { + GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); +- GdkPangoRendererPrivate *priv = gdk_renderer->priv; +- cairo_t *cr; +- +- cr = get_cairo_context (gdk_renderer, part); +- +- if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) +- { +- cairo_save (cr); +- emboss_context (cr); +- cairo_rectangle (cr, +- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, +- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); ++ GdkTrapezoid trap; + +- cairo_fill (cr); +- cairo_restore (cr); +- } ++ if (!gdk_renderer->priv->trapezoids) ++ gdk_renderer->priv->trapezoids = g_array_new (FALSE, FALSE, ++ sizeof (GdkTrapezoid)); ++ ++ if (gdk_renderer->priv->trapezoids->len > 0 && ++ gdk_renderer->priv->trapezoid_part != part) ++ flush_trapezoids (gdk_renderer); ++ ++ gdk_renderer->priv->trapezoid_part = part; ++ ++ trap.y1 = y1; ++ trap.x11 = x11 / 2; ++ trap.x21 = x21; ++ trap.y2 = y2; ++ trap.x12 = x12; ++ trap.x22 = x22; + +- cairo_rectangle (cr, +- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, +- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); +- cairo_fill (cr); ++ g_array_append_val (gdk_renderer->priv->trapezoids, trap); + } + + static void +@@ -363,23 +390,51 @@ + { + GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); + GdkPangoRendererPrivate *priv = gdk_renderer->priv; +- cairo_t *cr; +- +- cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE); +- +- if (priv->embossed) ++ ++ if (!priv->in_emboss && priv->embossed) + { +- cairo_save (cr); +- emboss_context (cr); +- draw_error_underline (cr, +- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, +- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); +- cairo_restore (cr); ++ PangoMatrix *save_matrix; ++ PangoColor *save_color; ++ ++ emboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); ++ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, ++ x, y, width, height); ++ unemboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); + } + +- draw_error_underline (cr, +- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, +- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); ++ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, ++ x, y, width, height); ++} ++ ++/* We can't handle embossing at the level of trapezoids, because when an ++ * underline is split into multiple trapezoids, the normal and shadow ++ * trapezoids will be drawn mixed together. Instead, we have to emboss ++ * and entire rectangle or error underline ++ */ ++static void ++gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, ++ PangoRenderPart part, ++ int x, ++ int y, ++ int width, ++ int height) ++{ ++ GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); ++ GdkPangoRendererPrivate *priv = gdk_renderer->priv; ++ ++ if (!priv->in_emboss && priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) ++ { ++ PangoMatrix *save_matrix; ++ PangoColor *save_color; ++ ++ emboss_renderer (renderer, part, &save_matrix, &save_color); ++ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, ++ x, y, width, height); ++ unemboss_renderer (renderer, part, &save_matrix, &save_color); ++ } ++ ++ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, ++ x, y, width, height); + } + + static void +@@ -388,8 +443,8 @@ + { + GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); + +- if (gdk_renderer->priv->last_part == part) +- gdk_renderer->priv->last_part = (PangoRenderPart)-1; ++ if (part == gdk_renderer->priv->trapezoid_part) ++ flush_trapezoids (gdk_renderer); + } + + static void +@@ -410,13 +465,8 @@ + { + GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); + GdkPangoRendererPrivate *priv = gdk_renderer->priv; +- +- if (priv->cr) +- { +- cairo_destroy (priv->cr); +- priv->cr = NULL; +- } +- priv->last_part = (PangoRenderPart)-1; ++ ++ flush_trapezoids (gdk_renderer); + } + + static void +@@ -515,7 +565,6 @@ + GDK_TYPE_PANGO_RENDERER, + GdkPangoRendererPrivate); + +- renderer->priv->last_part = (PangoRenderPart)-1; + renderer->priv->gc_changed = TRUE; + } + +@@ -527,6 +576,7 @@ + PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); + + renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs; ++ renderer_class->draw_trapezoid = gdk_pango_renderer_draw_trapezoid; + renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle; + renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline; + renderer_class->part_changed = gdk_pango_renderer_part_changed; +@@ -647,6 +697,8 @@ + + priv = gdk_renderer->priv; + ++ flush_trapezoids (gdk_renderer); ++ + if (priv->drawable != drawable) + { + if (priv->drawable) +@@ -681,6 +733,8 @@ + + priv = gdk_renderer->priv; + ++ flush_trapezoids (gdk_renderer); ++ + if (priv->base_gc != gc) + { + if (priv->base_gc) +@@ -689,6 +743,20 @@ + if (priv->base_gc) + g_object_ref (priv->base_gc); + ++ if (priv->gc) ++ { ++ g_object_unref (priv->gc); ++ priv->gc = NULL; ++ } ++ ++ priv->gc_color_set = FALSE; ++ ++ if (priv->gc_stipple) ++ { ++ g_object_unref (priv->gc_stipple); ++ priv->gc_stipple = NULL; ++ } ++ + priv->gc_changed = TRUE; + } + } +@@ -1414,50 +1482,5 @@ + return gdk_pango_context_get_for_screen (gdk_screen_get_default ()); + } + +-/** +- * gdk_pango_context_get_for_screen: +- * @screen: the #GdkScreen for which the context is to be created. +- * +- * Creates a #PangoContext for @screen. +- * +- * The context must be freed when you're finished with it. +- * +- * When using GTK+, normally you should use gtk_widget_get_pango_context() +- * instead of this function, to get the appropriate context for +- * the widget you intend to render text onto. +- * +- * The newly created context will have the default font options +- * (see #cairo_font_options_t) for the screen; if these options +- * change it will not be updated. Using gtk_widget_get_pango_context() +- * is more convenient if you want to keep a context around and track +- * changes to the screen's font rendering settings. +- * +- * Return value: a new #PangoContext for @screen +- * +- * Since: 2.2 +- **/ +-PangoContext * +-gdk_pango_context_get_for_screen (GdkScreen *screen) +-{ +- PangoFontMap *fontmap; +- PangoContext *context; +- const cairo_font_options_t *options; +- double dpi; +- +- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); +- +- fontmap = pango_cairo_font_map_get_default (); +- +- context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); +- +- options = gdk_screen_get_font_options (screen); +- pango_cairo_context_set_font_options (context, options); +- +- dpi = gdk_screen_get_resolution (screen); +- pango_cairo_context_set_resolution (context, dpi); +- +- return context; +-} +- + #define __GDK_PANGO_C__ + #include "gdkaliasdef.c" +Index: gtk+-2.10.6/gdk/gdk.symbols +=================================================================== +--- gtk+-2.10.6.orig/gdk/gdk.symbols 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/gdk.symbols 2006-10-30 12:59:30.000000000 +0000 +@@ -861,7 +861,6 @@ + gdk_pango_attr_embossed_new + gdk_pango_attr_stipple_new + gdk_pango_context_get +-gdk_pango_context_get_for_screen + #ifndef GDK_DISABLE_DEPRECATED + gdk_pango_context_set_colormap + #endif +@@ -877,6 +876,12 @@ + #endif + #endif + ++#if IN_HEADER(__GDK_PANGO_H__) ++#if IN_FILE(__GDK_PANGO_X11_C__) ++gdk_pango_context_get_for_screen ++#endif ++#endif ++ + #if IN_HEADER(__GDK_PIXBUF_H__) + #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__) + gdk_pixbuf_get_from_drawable +Index: gtk+-2.10.6/gdk/gdkwindow.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/gdkwindow.c 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/gdkwindow.c 2006-10-30 12:59:30.000000000 +0000 +@@ -1834,9 +1834,14 @@ + } + else + { +- method->cr = cairo_create (paint->surface); ++ /*method->cr = cairo_create (paint->surface); + +- gdk_cairo_set_source_color (method->cr, &private->bg_color); ++ gdk_cairo_set_source_color (method->cr, &private->bg_color);*/ ++ GdkGC *gc = _gdk_drawable_get_scratch_gc (paint->pixmap, FALSE); ++ ++ gdk_gc_set_foreground (gc, &(private->bg_color)); ++ ++ method->gc = g_object_ref (gc); + } + } + +Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.c 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c 2006-10-30 12:59:30.000000000 +0000 +@@ -190,7 +190,8 @@ + display_x11->leader_window_title_set = FALSE; + + display_x11->have_render = GDK_UNKNOWN; +- ++ display_x11->have_render_with_trapezoids = GDK_UNKNOWN; ++ + #ifdef HAVE_XFIXES + if (XFixesQueryExtension (display_x11->xdisplay, + &display_x11->xfixes_event_base, +Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.h 2006-10-30 12:58:29.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h 2006-10-30 12:59:30.000000000 +0000 +@@ -78,6 +78,7 @@ + gboolean use_xshm; + gboolean have_shm_pixmaps; + GdkTristate have_render; ++ GdkTristate have_render_with_trapezoids; + gboolean have_xfixes; + gint xfixes_event_base; + +Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.c 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c 2006-10-30 12:59:30.000000000 +0000 +@@ -26,6 +26,8 @@ + + #include <config.h> + ++#include <pango/pangoxft.h> ++ + #include "gdkx.h" + #include "gdkregion-generic.h" + +@@ -106,7 +108,21 @@ + GdkGC *gc, + GdkPoint *points, + gint npoints); +- ++ ++static void gdk_x11_draw_glyphs (GdkDrawable *drawable, ++ GdkGC *gc, ++ PangoFont *font, ++ gint x, ++ gint y, ++ PangoGlyphString *glyphs); ++static void gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable, ++ GdkGC *gc, ++ PangoMatrix *matrix, ++ PangoFont *font, ++ gint x, ++ gint y, ++ PangoGlyphString *glyphs); ++ + static void gdk_x11_draw_image (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, +@@ -129,6 +145,11 @@ + gint x_dither, + gint y_dither); + ++static void gdk_x11_draw_trapezoids (GdkDrawable *drawable, ++ GdkGC *gc, ++ GdkTrapezoid *trapezoids, ++ gint n_trapezoids); ++ + static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable); + + static void gdk_x11_set_colormap (GdkDrawable *drawable, +@@ -163,8 +184,11 @@ + drawable_class->draw_points = gdk_x11_draw_points; + drawable_class->draw_segments = gdk_x11_draw_segments; + drawable_class->draw_lines = gdk_x11_draw_lines; ++ drawable_class->draw_glyphs = gdk_x11_draw_glyphs; ++ drawable_class->draw_glyphs_transformed = gdk_x11_draw_glyphs_transformed; + drawable_class->draw_image = gdk_x11_draw_image; + drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf; ++ drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids; + + drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface; + +@@ -327,6 +351,72 @@ + return x11display->have_render == GDK_YES; + } + ++gboolean ++_gdk_x11_have_render_with_trapezoids (GdkDisplay *display) ++{ ++ Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); ++ GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); ++ ++ if (x11display->have_render_with_trapezoids == GDK_UNKNOWN) ++ { ++ x11display->have_render_with_trapezoids = GDK_NO; ++ if (_gdk_x11_have_render (display)) ++ { ++ /* ++ * Require protocol >= 0.4 for CompositeTrapezoids support. ++ */ ++ int major_version, minor_version; ++ ++#define XRENDER_TETRAPEZOIDS_MAJOR 0 ++#define XRENDER_TETRAPEZOIDS_MINOR 4 ++ ++ if (XRenderQueryVersion (xdisplay, &major_version, ++ &minor_version)) ++ if ((major_version == XRENDER_TETRAPEZOIDS_MAJOR) && ++ (minor_version >= XRENDER_TETRAPEZOIDS_MINOR)) ++ x11display->have_render_with_trapezoids = GDK_YES; ++ } ++ } ++ ++ return x11display->have_render_with_trapezoids == GDK_YES; ++} ++ ++static XftDraw * ++gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable) ++{ ++ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); ++ ++ if (impl->xft_draw == NULL) ++ { ++ GdkColormap *colormap = gdk_drawable_get_colormap (drawable); ++ ++ if (colormap) ++ { ++ GdkVisual *visual; ++ ++ visual = gdk_colormap_get_visual (colormap); ++ ++ impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid, ++ GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap)); ++ } ++ else if (gdk_drawable_get_depth (drawable) == 1) ++ { ++ impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid); ++ } ++ else ++ { ++ g_warning ("Using Xft rendering requires the drawable argument to\n" ++ "have a specified colormap. All windows have a colormap,\n" ++ "however, pixmaps only have colormap by default if they\n" ++ "were created with a non-NULL window argument. Otherwise\n" ++ "a colormap must be set on them with gdk_drawable_set_colormap"); ++ return NULL; ++ } ++ } ++ ++ return impl->xft_draw; ++} ++ + static Picture + gdk_x11_drawable_get_picture (GdkDrawable *drawable) + { +@@ -393,6 +483,57 @@ + } + } + ++static void ++gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable, ++ GdkGC *gc) ++{ ++ XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable); ++ GdkRegion *clip_region = _gdk_gc_get_clip_region (gc); ++ ++ if (gc && clip_region) ++ { ++ GdkRegionBox *boxes = clip_region->rects; ++ gint n_boxes = clip_region->numRects; ++#if 0 /* Until XftDrawSetClipRectangles is there */ ++ XRectangle *rects = g_new (XRectangle, n_boxes); ++ int i; ++ ++ for (i=0; i < n_boxes; i++) ++ { ++ rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT); ++ rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT); ++ rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x; ++ rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y; ++ } ++ XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes); ++ ++ g_free (rects); ++#else ++ Region xregion = XCreateRegion (); ++ int i; ++ ++ for (i=0; i < n_boxes; i++) ++ { ++ XRectangle rect; ++ ++ rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT); ++ rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT); ++ rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x; ++ rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y; ++ ++ XUnionRectWithRegion (&rect, xregion, xregion); ++ } ++ ++ XftDrawSetClip (xft_draw, xregion); ++ XDestroyRegion (xregion); ++#endif ++ } ++ else ++ { ++ XftDrawSetClip (xft_draw, NULL); ++ } ++} ++ + /***************************************************** + * X11 specific implementations of generic functions * + *****************************************************/ +@@ -780,6 +921,45 @@ + } + + static void ++gdk_x11_draw_glyphs (GdkDrawable *drawable, ++ GdkGC *gc, ++ PangoFont *font, ++ gint x, ++ gint y, ++ PangoGlyphString *glyphs) ++{ ++ gdk_x11_draw_glyphs_transformed (drawable, gc, NULL, ++ font, ++ x * PANGO_SCALE, ++ y * PANGO_SCALE, ++ glyphs); ++} ++ ++static void ++gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable, ++ GdkGC *gc, ++ PangoMatrix *matrix, ++ PangoFont *font, ++ gint x, ++ gint y, ++ PangoGlyphString *glyphs) ++{ ++ GdkDrawableImplX11 *impl; ++ PangoRenderer *renderer; ++ ++ impl = GDK_DRAWABLE_IMPL_X11 (drawable); ++ ++ g_return_if_fail (PANGO_XFT_IS_FONT (font)); ++ ++ renderer = _gdk_x11_renderer_get (drawable, gc); ++ if (matrix) ++ pango_renderer_set_matrix (renderer, matrix); ++ pango_renderer_draw_glyphs (renderer, font, glyphs, x, y); ++ if (matrix) ++ pango_renderer_set_matrix (renderer, NULL); ++} ++ ++static void + gdk_x11_draw_image (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, +@@ -1444,6 +1624,47 @@ + } + + static void ++gdk_x11_draw_trapezoids (GdkDrawable *drawable, ++ GdkGC *gc, ++ GdkTrapezoid *trapezoids, ++ gint n_trapezoids) ++{ ++ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; ++ GdkDisplay *display = gdk_screen_get_display (screen); ++ XTrapezoid *xtrapezoids; ++ gint i; ++ ++ if (!_gdk_x11_have_render_with_trapezoids (display)) ++ { ++ GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper; ++ GDK_DRAWABLE_CLASS (_gdk_drawable_impl_x11_parent_class)->draw_trapezoids (wrapper, gc, ++ trapezoids, n_trapezoids); ++ return; ++ } ++ ++ xtrapezoids = g_new (XTrapezoid, n_trapezoids); ++ ++ for (i = 0; i < n_trapezoids; i++) ++ { ++ xtrapezoids[i].top = XDoubleToFixed (trapezoids[i].y1); ++ xtrapezoids[i].bottom = XDoubleToFixed (trapezoids[i].y2); ++ xtrapezoids[i].left.p1.x = XDoubleToFixed (trapezoids[i].x11); ++ xtrapezoids[i].left.p1.y = XDoubleToFixed (trapezoids[i].y1); ++ xtrapezoids[i].left.p2.x = XDoubleToFixed (trapezoids[i].x12); ++ xtrapezoids[i].left.p2.y = XDoubleToFixed (trapezoids[i].y2); ++ xtrapezoids[i].right.p1.x = XDoubleToFixed (trapezoids[i].x21); ++ xtrapezoids[i].right.p1.y = XDoubleToFixed (trapezoids[i].y1); ++ xtrapezoids[i].right.p2.x = XDoubleToFixed (trapezoids[i].x22); ++ xtrapezoids[i].right.p2.y = XDoubleToFixed (trapezoids[i].y2); ++ } ++ ++ _gdk_x11_drawable_draw_xtrapezoids (drawable, gc, ++ xtrapezoids, n_trapezoids); ++ ++ g_free (xtrapezoids); ++} ++ ++static void + gdk_x11_cairo_surface_destroy (void *data) + { + GdkDrawableImplX11 *impl = data; +@@ -1498,5 +1719,89 @@ + return impl->cairo_surface; + } + ++void ++_gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable, ++ GdkGC *gc, ++ XTrapezoid *xtrapezoids, ++ int n_trapezoids) ++{ ++ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; ++ GdkDisplay *display = gdk_screen_get_display (screen); ++ GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); ++ ++ XftDraw *draw; ++ ++ if (!_gdk_x11_have_render_with_trapezoids (display)) ++ { ++ /* This is the case of drawing the borders of the unknown glyph box ++ * without render on the display, we need to feed it back to ++ * fallback code. Not efficient, but doesn't matter. ++ */ ++ GdkTrapezoid *trapezoids = g_new (GdkTrapezoid, n_trapezoids); ++ int i; ++ ++ for (i = 0; i < n_trapezoids; i++) ++ { ++ trapezoids[i].y1 = XFixedToDouble (xtrapezoids[i].top); ++ trapezoids[i].y2 = XFixedToDouble (xtrapezoids[i].bottom); ++ trapezoids[i].x11 = XFixedToDouble (xtrapezoids[i].left.p1.x); ++ trapezoids[i].x12 = XFixedToDouble (xtrapezoids[i].left.p2.x); ++ trapezoids[i].x21 = XFixedToDouble (xtrapezoids[i].right.p1.x); ++ trapezoids[i].x22 = XFixedToDouble (xtrapezoids[i].right.p2.x); ++ } ++ ++ gdk_x11_draw_trapezoids (drawable, gc, trapezoids, n_trapezoids); ++ g_free (trapezoids); ++ ++ return; ++ } ++ ++ gdk_x11_drawable_update_xft_clip (drawable, gc); ++ draw = gdk_x11_drawable_get_xft_draw (drawable); ++ ++ if (!x11display->mask_format) ++ x11display->mask_format = XRenderFindStandardFormat (x11display->xdisplay, ++ PictStandardA8); ++ ++ XRenderCompositeTrapezoids (x11display->xdisplay, PictOpOver, ++ _gdk_x11_gc_get_fg_picture (gc), ++ XftDrawPicture (draw), ++ x11display->mask_format, ++ - gc->ts_x_origin, - gc->ts_y_origin, ++ xtrapezoids, n_trapezoids); ++} ++ ++void ++_gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable, ++ GdkGC *gc, ++ XftFont *xft_font, ++ XftGlyphSpec *glyphs, ++ gint n_glyphs) ++{ ++ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; ++ GdkDisplay *display = gdk_screen_get_display (screen); ++ GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); ++ XftDraw *draw; ++ ++ gdk_x11_drawable_update_xft_clip (drawable, gc); ++ draw = gdk_x11_drawable_get_xft_draw (drawable); ++ ++ if (_gdk_x11_have_render (display)) ++ { ++ XftGlyphSpecRender (x11display->xdisplay, PictOpOver, ++ _gdk_x11_gc_get_fg_picture (gc), ++ xft_font, ++ XftDrawPicture (draw), ++ - gc->ts_x_origin, - gc->ts_y_origin, ++ glyphs, n_glyphs); ++ } ++ else ++ { ++ XftColor color; ++ ++ _gdk_gc_x11_get_fg_xft_color (gc, &color); ++ XftDrawGlyphSpec (draw, &color, xft_font, glyphs, n_glyphs); ++ } ++} + #define __GDK_DRAWABLE_X11_C__ + #include "gdkaliasdef.c" +Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.h 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h 2006-10-30 12:59:30.000000000 +0000 +@@ -33,6 +33,7 @@ + + #include <X11/Xlib.h> + #include <X11/extensions/Xrender.h> ++#include <X11/Xft/Xft.h> + + G_BEGIN_DECLS + +@@ -68,6 +69,8 @@ + Window xid; + GdkScreen *screen; + ++ XftDraw *xft_draw; ++ + Picture picture; + cairo_surface_t *cairo_surface; + }; +@@ -92,7 +95,15 @@ + /* Note that the following take GdkDrawableImplX11, not the wrapper drawable */ + void _gdk_x11_drawable_finish (GdkDrawable *drawable); + void _gdk_x11_drawable_update_size (GdkDrawable *drawable); +- ++void _gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable, ++ GdkGC *gc, ++ XTrapezoid *xtrapezoids, ++ int n_trapezoids); ++void _gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable, ++ GdkGC *gc, ++ XftFont *xft_font, ++ XftGlyphSpec *glyphs, ++ gint n_glyphs); + G_END_DECLS + + #endif /* __GDK_DRAWABLE_X11_H__ */ +Index: gtk+-2.10.6/gdk/x11/gdkgc-x11.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkgc-x11.c 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkgc-x11.c 2006-10-30 12:59:30.000000000 +0000 +@@ -80,7 +80,10 @@ + gdk_gc_x11_finalize (GObject *object) + { + GdkGCX11 *x11_gc = GDK_GC_X11 (object); +- ++ ++ if (x11_gc->fg_picture != None) ++ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture); ++ + XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc)); + + G_OBJECT_CLASS (_gdk_gc_x11_parent_class)->finalize (object); +@@ -110,7 +113,7 @@ + + private->dirty_mask = 0; + private->have_clip_mask = FALSE; +- ++ + private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; + + private->depth = gdk_drawable_get_depth (drawable); +@@ -339,6 +342,18 @@ + } + + static void ++clear_fg_picture (GdkGC *gc) ++{ ++ GdkGCX11 *x11_gc = GDK_GC_X11 (gc); ++ ++ if (x11_gc->fg_picture != None) ++ { ++ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture); ++ x11_gc->fg_picture = None; ++ } ++} ++ ++static void + gdk_x11_gc_set_values (GdkGC *gc, + GdkGCValues *values, + GdkGCValuesMask values_mask) +@@ -367,6 +382,29 @@ + x11_gc->have_clip_mask = values->clip_mask != NULL; + } + ++ if (values_mask & GDK_GC_BACKGROUND) ++ { ++ if (_gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED) ++ clear_fg_picture (gc); ++ } ++ ++ if (values_mask & GDK_GC_FILL) ++ { ++ clear_fg_picture (gc); ++ } ++ ++ if (values_mask & GDK_GC_STIPPLE) ++ { ++ if (_gdk_gc_get_fill (gc) == GDK_STIPPLED || _gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED) ++ clear_fg_picture (gc); ++ } ++ ++ if (values_mask & GDK_GC_TILE) ++ { ++ if (_gdk_gc_get_fill (gc) == GDK_TILED) ++ clear_fg_picture (gc); ++ } ++ + gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask); + + XChangeGC (GDK_GC_XDISPLAY (gc), +@@ -642,6 +680,8 @@ + x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask; + x11_dst_gc->have_clip_region = x11_src_gc->have_clip_region; + x11_dst_gc->have_clip_mask = x11_src_gc->have_clip_mask; ++ ++ clear_fg_picture (dst_gc); + } + + /** +@@ -701,5 +741,359 @@ + return gc_x11->xgc; + } + ++/* Various bits of the below are roughly cribbed from XFree86 ++ * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard ++ */ ++ ++static XRenderPictFormat * ++foreground_format (GdkGC *gc) ++{ ++ XRenderPictFormat pf; ++ ++ pf.type = PictTypeDirect; ++ pf.depth = 32; ++ pf.direct.redMask = 0xff; ++ pf.direct.greenMask = 0xff; ++ pf.direct.blueMask = 0xff; ++ pf.direct.alphaMask = 0xff; ++ ++ return XRenderFindFormat (GDK_GC_XDISPLAY (gc), ++ (PictFormatType | ++ PictFormatDepth | ++ PictFormatRedMask | ++ PictFormatGreenMask | ++ PictFormatBlueMask | ++ PictFormatAlphaMask), ++ &pf, ++ 0); ++} ++ ++static Picture ++make_fg_tile_picture (GdkGC *gc) ++{ ++ GdkGCX11 *x11_gc = GDK_GC_X11 (gc); ++ GdkVisual *visual = gdk_drawable_get_visual (_gdk_gc_get_tile (gc)); ++ XRenderPictFormat *format = NULL; ++ ++ if (visual) ++ { ++ format = XRenderFindVisualFormat (GDK_GC_XDISPLAY (gc), ++ GDK_VISUAL_XVISUAL (visual)); ++ } ++ else if (x11_gc->depth == 1) ++ { ++ format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc), ++ PictStandardA1); ++ } ++ ++ if (format) ++ { ++ XRenderPictureAttributes pa; ++ pa.repeat = True; ++ ++ return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), ++ GDK_PIXMAP_XID (_gdk_gc_get_tile (gc)), ++ format, ++ CPRepeat, &pa); ++ } ++ ++ return None; ++} ++ ++static Picture ++make_stipple_picture (GdkGC *gc) ++{ ++ XRenderPictFormat *format = NULL; ++ XRenderPictureAttributes pa; ++ ++ format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc), ++ PictStandardA1); ++ ++ pa.repeat = True; ++ return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), ++ GDK_PIXMAP_XID (_gdk_gc_get_stipple (gc)), ++ format, ++ CPRepeat, &pa); ++} ++ ++static Picture ++make_color_picture (GdkGC *gc, ++ XRenderColor *color) ++{ ++ GdkGCX11 *x11_gc = GDK_GC_X11 (gc); ++ XRenderPictureAttributes pa; ++ XRenderPictFormat *pix_format = foreground_format (gc); ++ Pixmap pix; ++ Picture picture; ++ ++ if (!pix_format) ++ return None; ++ ++ pix = XCreatePixmap (GDK_GC_XDISPLAY (gc), ++ GDK_SCREEN_XROOTWIN (x11_gc->screen), ++ 1, 1, pix_format->depth); ++ pa.repeat = True; ++ picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc), ++ pix, ++ pix_format, ++ CPRepeat, &pa); ++ XFreePixmap (GDK_GC_XDISPLAY (gc), pix); ++ ++ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, ++ picture, color, ++ 0, 0, 1, 1); ++ ++ return picture; ++} ++ ++static void ++get_bg_color (GdkGC *gc, ++ XRenderColor *render_color) ++{ ++ GdkColormap *cmap; ++ ++ cmap = gdk_gc_get_colormap (gc); ++ ++ if (cmap) ++ { ++ GdkColor color; ++ ++ gdk_colormap_query_color (cmap, _gdk_gc_get_bg_pixel (gc), &color); ++ ++ render_color->alpha = 0xffff; ++ render_color->red = color.red; ++ render_color->green = color.green; ++ render_color->blue = color.blue; ++ } ++ else /* Not worth warning, just use black */ ++ { ++ render_color->alpha = 0xffff; ++ render_color->red = 0; ++ render_color->green = 0; ++ render_color->blue = 0; ++ } ++} ++ ++/** ++ * _gdk_x11_gc_get_fg_picture: ++ * @gc: a #GdkGC ++ * ++ * Gets a Xrender Picture object suitable for being the source ++ * drawable for drawing with the foreground the graphics context. ++ * ++ * Return value: a Picture, owned by the GC; this cannot be ++ * used over subsequent modification of the GC. ++ **/ ++Picture ++_gdk_x11_gc_get_fg_picture (GdkGC *gc) ++{ ++ GdkGCX11 *x11_gc; ++ gboolean new = FALSE; ++ XftColor xftcolor; ++ GdkFill fill; ++ int width, height; ++ ++ g_return_val_if_fail (GDK_IS_GC_X11 (gc), None); ++ ++ if (!_gdk_x11_have_render (GDK_GC_DISPLAY (gc))) ++ return None; ++ ++ x11_gc = GDK_GC_X11 (gc); ++ ++ fill = GDK_SOLID; ++ width = 1; ++ height = 1; ++ ++ switch (_gdk_gc_get_fill (gc)) ++ { ++ case GDK_SOLID: ++ break; ++ case GDK_TILED: ++ if (_gdk_gc_get_tile (gc)) ++ { ++ if (!x11_gc->fg_picture) ++ x11_gc->fg_picture = make_fg_tile_picture (gc); ++ ++ if (x11_gc->fg_picture != None) ++ return x11_gc->fg_picture; ++ } ++ break; ++ case GDK_STIPPLED: ++ case GDK_OPAQUE_STIPPLED: ++ if (_gdk_gc_get_stipple (gc)) ++ { ++ gdk_drawable_get_size (_gdk_gc_get_stipple (gc), &width, &height); ++ fill = _gdk_gc_get_fill (gc); ++ } ++ break; ++ } ++ ++ if (x11_gc->fg_picture == None) ++ { ++ XRenderPictureAttributes pa; ++ XRenderPictFormat *pix_format = foreground_format (gc); ++ Pixmap pix; ++ ++ if (!pix_format) ++ return None; ++ ++ pix = XCreatePixmap (GDK_GC_XDISPLAY (gc), ++ GDK_SCREEN_XROOTWIN (x11_gc->screen), ++ width, height, pix_format->depth); ++ pa.repeat = True; ++ x11_gc->fg_picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc), ++ pix, ++ pix_format, ++ CPRepeat, &pa); ++ XFreePixmap (GDK_GC_XDISPLAY (gc), pix); ++ ++ new = TRUE; ++ } ++ ++ _gdk_gc_x11_get_fg_xft_color (gc, &xftcolor); ++ ++ if (x11_gc->fg_picture_color.alpha != 0xffff || ++ x11_gc->fg_picture_color.red != xftcolor.color.red || ++ x11_gc->fg_picture_color.green != xftcolor.color.green || ++ x11_gc->fg_picture_color.blue != xftcolor.color.blue) ++ { ++ x11_gc->fg_picture_color.alpha = 0xffff; ++ x11_gc->fg_picture_color.red = xftcolor.color.red; ++ x11_gc->fg_picture_color.green = xftcolor.color.green; ++ x11_gc->fg_picture_color.blue = xftcolor.color.blue; ++ ++ new = TRUE; ++ } ++ ++ switch (fill) ++ { ++ case GDK_SOLID: ++ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, ++ x11_gc->fg_picture, &x11_gc->fg_picture_color, ++ 0, 0, width, height); ++ break; ++ case GDK_STIPPLED: ++ { ++ Picture stipple_picture = make_stipple_picture (gc); ++ ++ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, ++ x11_gc->fg_picture, &x11_gc->fg_picture_color, ++ 0, 0, width, height); ++ XRenderComposite (GDK_GC_XDISPLAY (gc), ++ PictOpInReverse, ++ stipple_picture, None, x11_gc->fg_picture, ++ 0, 0, 0, 0, 0, 0, width, height); ++ ++ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture); ++ } ++ break; ++ case GDK_OPAQUE_STIPPLED: ++ { ++ XRenderColor bg_color; ++ ++ Picture stipple_picture = make_stipple_picture (gc); ++ Picture fg_picture = make_color_picture (gc, &x11_gc->fg_picture_color); ++ ++ get_bg_color (gc, &bg_color); ++ ++ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, ++ x11_gc->fg_picture, &bg_color, ++ 0, 0, width, height); ++ XRenderComposite (GDK_GC_XDISPLAY (gc), ++ PictOpOver, ++ fg_picture, stipple_picture, x11_gc->fg_picture, ++ 0, 0, 0, 0, 0, 0, width, height); ++ ++ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture); ++ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), fg_picture); ++ } ++ break; ++ case GDK_TILED: ++ g_assert_not_reached (); /* handled above */ ++ break; ++ } ++ ++ return x11_gc->fg_picture; ++} ++ ++/** ++ * _gdk_gc_x11_get_fg_xft_color: ++ * @gc: a #GdkGC ++ * @xftcolor: location to store the color ++ * ++ * Gets the foreground color of the GC as a XftColor. ++ **/ ++void ++_gdk_gc_x11_get_fg_xft_color (GdkGC *gc, ++ XftColor *xftcolor) ++{ ++ GdkGCX11 *x11_gc; ++ GdkColormap *cmap; ++ GdkColor color; ++ ++ g_return_if_fail (GDK_IS_GC_X11 (gc)); ++ ++ x11_gc = GDK_GC_X11 (gc); ++ ++ cmap = gdk_gc_get_colormap (gc); ++ ++ xftcolor->pixel = _gdk_gc_get_fg_pixel (gc); ++ ++ if (cmap) ++ { ++ gdk_colormap_query_color (cmap, xftcolor->pixel, &color); ++ xftcolor->color.alpha = 0xffff; ++ xftcolor->color.red = color.red; ++ xftcolor->color.green = color.green; ++ xftcolor->color.blue = color.blue; ++ } ++ else if (x11_gc->depth == 1) ++ { ++ /* Drawing with Xft on a bitmap is a bit bizzare; it ++ * takes alpha >= 0x8000 to mean 'set to 1' and ++ * alpha < 0x8000 to mean 'set to 0'. ++ */ ++ if (xftcolor->pixel) ++ { ++ xftcolor->color.red = 0xffff; ++ xftcolor->color.green = 0xffff; ++ xftcolor->color.blue = 0xffff; ++ xftcolor->color.alpha = 0xffff; ++ } ++ else ++ { ++ xftcolor->color.red = 0; ++ xftcolor->color.green = 0; ++ xftcolor->color.blue = 0; ++ xftcolor->color.alpha = 0; ++ } ++ } ++ else ++ { ++ g_warning ("Using Xft rendering requires the GC argument to have a\n" ++ "specified colormap. If the GC was created for a drawable\n" ++ "with a colormap, the colormap will be set on the GC\n" ++ "automatically. Otherwise, a colormap must be set on it with" ++ "gdk_gc_set_colormap"); ++ } ++} ++ ++void ++_gdk_windowing_gc_get_foreground (GdkGC *gc, ++ GdkColor *color) ++{ ++ GdkColormap *cmap; ++ ++ g_return_if_fail (GDK_IS_GC_X11 (gc)); ++ ++ color->pixel = _gdk_gc_get_fg_pixel (gc); ++ ++ cmap = gdk_gc_get_colormap (gc); ++ ++ if (cmap) ++ gdk_colormap_query_color (cmap, _gdk_gc_get_fg_pixel (gc), color); ++ else ++ g_warning ("No colormap in _gdk_windowing_gc_get_foreground"); ++} + #define __GDK_GC_X11_C__ + #include "gdkaliasdef.c" +Index: gtk+-2.10.6/gdk/x11/gdkprivate-x11.h +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkprivate-x11.h 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkprivate-x11.h 2006-10-30 12:59:30.000000000 +0000 +@@ -63,6 +63,9 @@ + guint have_clip_region : 1; + guint have_clip_mask : 1; + guint depth : 8; ++ ++ Picture fg_picture; ++ XRenderColor fg_picture_color; + }; + + struct _GdkGCX11Class +@@ -102,6 +105,11 @@ + GType _gdk_gc_x11_get_type (void); + + gboolean _gdk_x11_have_render (GdkDisplay *display); ++gboolean _gdk_x11_have_render_with_trapezoids (GdkDisplay *display); ++ ++Picture _gdk_x11_gc_get_fg_picture (GdkGC *gc); ++void _gdk_gc_x11_get_fg_xft_color (GdkGC *gc, ++ XftColor *xftcolor); + + GdkGC *_gdk_x11_gc_new (GdkDrawable *drawable, + GdkGCValues *values, +Index: gtk+-2.10.6/gdk/x11/gdkwindow-x11.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkwindow-x11.c 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkwindow-x11.c 2006-10-30 12:59:30.000000000 +0000 +@@ -1114,7 +1114,8 @@ + { + GdkWindowObject *private = (GdkWindowObject *)window; + GdkToplevelX11 *toplevel; +- ++ GdkDrawableImplX11 *draw_impl; ++ + g_return_if_fail (GDK_IS_WINDOW (window)); + + _gdk_selection_window_destroyed (window); +@@ -1126,6 +1127,11 @@ + if (toplevel) + gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel); + ++ draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); ++ ++ if (draw_impl->xft_draw) ++ XftDrawDestroy (draw_impl->xft_draw); ++ + _gdk_x11_drawable_finish (private->impl); + + if (!recursing && !foreign_destroy) +Index: gtk+-2.10.6/gdk/x11/Makefile.am +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/Makefile.am 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/Makefile.am 2006-10-30 12:59:30.000000000 +0000 +@@ -37,6 +37,7 @@ + gdkinput.c \ + gdkkeys-x11.c \ + gdkmain-x11.c \ ++ gdkpango-x11.c \ + gdkpixmap-x11.c \ + gdkpixmap-x11.h \ + gdkproperty-x11.c \ +Index: gtk+-2.10.6/gtk/gtkcalendar.c +=================================================================== +--- gtk+-2.10.6.orig/gtk/gtkcalendar.c 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gtk/gtkcalendar.c 2006-10-30 12:59:30.000000000 +0000 +@@ -1821,7 +1821,7 @@ + } + } + +- ++ + /**************************************** + * Repainting * + ****************************************/ +@@ -1831,7 +1831,7 @@ + { + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); +- cairo_t *cr; ++ GdkGC *gc; + char buffer[255]; + int x, y; + gint header_width; +@@ -1849,7 +1849,7 @@ + else + year_left = !priv->year_before; + +- cr = gdk_cairo_create (priv->header_win); ++ gc = calendar->gc; + + header_width = widget->allocation.width - 2 * widget->style->xthickness; + +@@ -1902,9 +1902,9 @@ + - (max_year_width - logical_rect.width)/2); + + +- gdk_cairo_set_source_color (cr, HEADER_FG_COLOR (GTK_WIDGET (calendar))); +- cairo_move_to (cr, x, y); +- pango_cairo_show_layout (cr, layout); ++ gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar))); ++ gdk_draw_layout (priv->header_win, gc, x, y, layout); ++ + + /* Draw month */ + g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]); +@@ -1924,19 +1924,19 @@ + else + x = 3 + priv->arrow_width + (max_month_width - logical_rect.width)/2; + +- cairo_move_to (cr, x, y); +- pango_cairo_show_layout (cr, layout); +- ++ gdk_draw_layout (priv->header_win, gc, x, y, layout); ++ ++ gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar))); ++ + g_object_unref (layout); +- cairo_destroy (cr); + } + + static void + calendar_paint_day_names (GtkCalendar *calendar) + { + GtkWidget *widget = GTK_WIDGET (calendar); ++ GdkGC *gc; + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); +- cairo_t *cr; + char buffer[255]; + int day,i; + int day_width, cal_width; +@@ -1946,8 +1946,7 @@ + gint focus_padding; + gint focus_width; + +- cr = gdk_cairo_create (priv->day_name_win); +- ++ gc = calendar->gc; + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, + "focus-padding", &focus_padding, +@@ -1961,22 +1960,19 @@ + * Draw rectangles as inverted background for the labels. + */ + +- gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); +- cairo_rectangle (cr, +- CALENDAR_MARGIN, CALENDAR_MARGIN, +- cal_width-CALENDAR_MARGIN * 2, +- priv->day_name_h - CALENDAR_MARGIN); +- cairo_fill (cr); +- ++ gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); ++ gdk_draw_rectangle (priv->day_name_win, gc, TRUE, ++ CALENDAR_MARGIN, CALENDAR_MARGIN, ++ cal_width-CALENDAR_MARGIN * 2, ++ priv->day_name_h - CALENDAR_MARGIN); ++ + if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) +- { +- cairo_rectangle (cr, +- CALENDAR_MARGIN, +- priv->day_name_h - CALENDAR_YSEP, +- priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN, +- CALENDAR_YSEP); +- cairo_fill (cr); +- } ++ gdk_draw_rectangle (priv->day_name_win, gc, TRUE, ++ CALENDAR_MARGIN, ++ priv->day_name_h - CALENDAR_YSEP, ++ priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN, ++ CALENDAR_YSEP); ++ + + /* + * Write the labels +@@ -1984,7 +1980,7 @@ + + layout = gtk_widget_create_pango_layout (widget, NULL); + +- gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget)); ++ gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); + for (i = 0; i < 7; i++) + { + if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) +@@ -1997,19 +1993,18 @@ + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + +- cairo_move_to (cr, +- (CALENDAR_MARGIN + +- + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? +- (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0)) +- : 0) +- + day_wid_sep * i +- + (day_width - logical_rect.width)/2), +- CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y); +- pango_cairo_show_layout (cr, layout); ++ gdk_draw_layout (priv->day_name_win, gc, ++ (CALENDAR_MARGIN + ++ + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? ++ (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0)) ++ : 0) ++ + day_wid_sep * i ++ + (day_width - logical_rect.width)/2), ++ CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y, ++ layout); + } + + g_object_unref (layout); +- cairo_destroy (cr); + } + + static void +@@ -2017,7 +2012,7 @@ + { + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); +- cairo_t *cr; ++ GdkGC *gc; + gint row, week = 0, year; + gint x_loc; + char buffer[32]; +@@ -2027,7 +2022,7 @@ + gint focus_padding; + gint focus_width; + +- cr = gdk_cairo_create (priv->week_win); ++ gc = calendar->gc; + + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, +@@ -2038,20 +2033,20 @@ + * Draw a rectangle as inverted background for the labels. + */ + +- gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); ++ gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); + if (priv->day_name_win) +- cairo_rectangle (cr, +- CALENDAR_MARGIN, +- 0, +- priv->week_width - CALENDAR_MARGIN, +- priv->main_h - CALENDAR_MARGIN); ++ gdk_draw_rectangle (priv->week_win, gc, TRUE, ++ CALENDAR_MARGIN, ++ 0, ++ priv->week_width - CALENDAR_MARGIN, ++ priv->main_h - CALENDAR_MARGIN); + else +- cairo_rectangle (cr, +- CALENDAR_MARGIN, +- CALENDAR_MARGIN, +- priv->week_width - CALENDAR_MARGIN, +- priv->main_h - 2 * CALENDAR_MARGIN); +- cairo_fill (cr); ++ gdk_draw_rectangle (priv->week_win, gc, TRUE, ++ CALENDAR_MARGIN, ++ CALENDAR_MARGIN, ++ priv->week_width - CALENDAR_MARGIN, ++ priv->main_h - 2 * CALENDAR_MARGIN); ++ + + /* + * Write the labels +@@ -2059,7 +2054,7 @@ + + layout = gtk_widget_create_pango_layout (widget, NULL); + +- gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget)); ++ gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); + day_height = calendar_row_height (calendar); + for (row = 0; row < 6; row++) + { +@@ -2095,12 +2090,10 @@ + - logical_rect.width + - CALENDAR_XSEP - focus_padding - focus_width); + +- cairo_move_to (cr, x_loc, y_loc); +- pango_cairo_show_layout (cr, layout); ++ gdk_draw_layout (priv->week_win, gc, x_loc, y_loc, layout); + } + + g_object_unref (layout); +- cairo_destroy (cr); + } + + static void +@@ -2149,7 +2142,7 @@ + { + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); +- cairo_t *cr; ++ GdkGC *gc; + GdkColor *text_color; + gchar buffer[32]; + gint day; +@@ -2162,7 +2155,7 @@ + g_return_if_fail (row < 6); + g_return_if_fail (col < 7); + +- cr = gdk_cairo_create (priv->main_win); ++ gc = calendar->gc; + + day = calendar->day[row][col]; + +@@ -2170,11 +2163,11 @@ + + if (calendar->day_month[row][col] == MONTH_PREV) + { +- text_color = PREV_MONTH_COLOR (widget); ++ gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar))); + } + else if (calendar->day_month[row][col] == MONTH_NEXT) + { +- text_color = NEXT_MONTH_COLOR (widget); ++ gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar))); + } + else + { +@@ -2188,16 +2181,16 @@ + #endif + if (calendar->selected_day == day) + { +- gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); +- gdk_cairo_rectangle (cr, &day_rect); +- cairo_fill (cr); ++ gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (GTK_WIDGET (calendar))); ++ gdk_draw_rectangle (priv->main_win, gc, TRUE, day_rect.x, day_rect.y, ++ day_rect.width, day_rect.height); + } + if (calendar->selected_day == day) +- text_color = SELECTED_FG_COLOR (widget); ++ gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar))); + else if (calendar->marked_date[day-1]) +- text_color = MARKED_COLOR (widget); ++ gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar))); + else +- text_color = NORMAL_DAY_COLOR (widget); ++ gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar))); + } + + /* Translators: this defines whether the day numbers should use +@@ -2219,16 +2212,13 @@ + x_loc -= logical_rect.width; + y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2; + +- gdk_cairo_set_source_color (cr, text_color); +- cairo_move_to (cr, x_loc, y_loc); +- pango_cairo_show_layout (cr, layout); ++ gdk_draw_layout (priv->main_win, gc, ++ x_loc, y_loc, layout); + + if (calendar->marked_date[day-1] + && calendar->day_month[row][col] == MONTH_CURRENT) +- { +- cairo_move_to (cr, x_loc - 1, y_loc); +- pango_cairo_show_layout (cr, layout); +- } ++ gdk_draw_layout (priv->main_win, gc, ++ x_loc-1, y_loc, layout); + + if (GTK_WIDGET_HAS_FOCUS (calendar) + && calendar->focus_row == row && calendar->focus_col == col) +@@ -2253,7 +2243,6 @@ + } + + g_object_unref (layout); +- cairo_destroy (cr); + } + + static void +Index: gtk+-2.10.6/gtk/gtkentry.c +=================================================================== +--- gtk+-2.10.6.orig/gtk/gtkentry.c 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gtk/gtkentry.c 2006-10-30 12:59:30.000000000 +0000 +@@ -3333,7 +3333,6 @@ + if (GTK_WIDGET_DRAWABLE (entry)) + { + PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); +- cairo_t *cr; + gint x, y; + gint start_pos, end_pos; + +@@ -3341,56 +3340,60 @@ + + get_layout_position (entry, &x, &y); + +- cr = gdk_cairo_create (entry->text_area); +- +- cairo_move_to (cr, x, y); +- gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); +- pango_cairo_show_layout (cr, layout); +- ++ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], ++ x, y, ++ layout); ++ + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) + { + gint *ranges; + gint n_ranges, i; + PangoRectangle logical_rect; +- GdkColor *selection_color, *text_color; ++ GdkGC *selection_gc, *text_gc; + GtkBorder inner_border; +- ++ GdkRegion *clip_region; ++ + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); + + if (GTK_WIDGET_HAS_FOCUS (entry)) + { +- selection_color = &widget->style->base [GTK_STATE_SELECTED]; +- text_color = &widget->style->text [GTK_STATE_SELECTED]; ++ selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; ++ text_gc = widget->style->text_gc [GTK_STATE_SELECTED]; + } + else + { +- selection_color = &widget->style->base [GTK_STATE_ACTIVE]; +- text_color = &widget->style->text [GTK_STATE_ACTIVE]; ++ selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; ++ text_gc = widget->style->text_gc [GTK_STATE_ACTIVE]; + } +- ++ ++ clip_region = gdk_region_new (); + _gtk_entry_effective_inner_border (entry, &inner_border); + + for (i = 0; i < n_ranges; ++i) +- cairo_rectangle (cr, +- inner_border.left - entry->scroll_offset + ranges[2 * i], +- y, +- ranges[2 * i + 1], +- logical_rect.height); ++ { ++ GdkRectangle rect; + +- cairo_clip (cr); +- +- gdk_cairo_set_source_color (cr, selection_color); +- cairo_paint (cr); ++ rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i]; ++ rect.y = y; ++ rect.width = ranges[2 * i + 1]; ++ rect.height = logical_rect.height; ++ ++ gdk_draw_rectangle (entry->text_area, selection_gc, TRUE, ++ rect.x, rect.y, rect.width, rect.height); + +- cairo_move_to (cr, x, y); +- gdk_cairo_set_source_color (cr, text_color); +- pango_cairo_show_layout (cr, layout); ++ gdk_region_union_with_rect (clip_region, &rect); ++ } + ++ gdk_gc_set_clip_region (text_gc, clip_region); ++ gdk_draw_layout (entry->text_area, text_gc, ++ x, y, ++ layout); ++ gdk_gc_set_clip_region (text_gc, NULL); ++ ++ gdk_region_destroy (clip_region); + g_free (ranges); + } +- +- cairo_destroy (cr); + } + } + +Index: gtk+-2.10.6/gtk/gtkwidget.c +=================================================================== +--- gtk+-2.10.6.orig/gtk/gtkwidget.c 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gtk/gtkwidget.c 2006-10-30 12:59:30.000000000 +0000 +@@ -5445,7 +5445,8 @@ + GdkScreen *screen; + + update_pango_context (widget, context); +- ++/* TODO: Figure out the proper way to handle this in a pangoxft setting ++ + screen = gtk_widget_get_screen_unchecked (widget); + if (screen) + { +@@ -5453,7 +5454,7 @@ + gdk_screen_get_resolution (screen)); + pango_cairo_context_set_font_options (context, + gdk_screen_get_font_options (screen)); +- } ++ }*/ + } + } + +Index: gtk+-2.10.6/gdk/x11/gdkpango-x11.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkpango-x11.c 2006-10-30 12:59:30.000000000 +0000 +@@ -0,0 +1,174 @@ ++/* GDK - The GIMP Drawing Kit ++ * Copyright (C) 2000 Red Hat, Inc. ++ * ++ * 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. ++ */ ++ ++#include <config.h> ++#include <stdlib.h> ++ ++#include "gdkx.h" ++#include "gdkdisplay-x11.h" ++#include "gdkpango.h" ++#include <pango/pangoxft.h> ++#include <pango/pangoxft-render.h> ++#include "gdkalias.h" ++ ++#include <math.h> ++ ++typedef struct _GdkX11Renderer GdkX11Renderer; ++typedef struct _GdkX11RendererClass GdkX11RendererClass; ++ ++#define GDK_TYPE_X11_RENDERER (_gdk_x11_renderer_get_type()) ++#define GDK_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_RENDERER, GdkX11Renderer)) ++#define GDK_IS_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_RENDERER)) ++#define GDK_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_RENDERER, GdkX11RendererClass)) ++#define GDK_IS_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_RENDERER)) ++#define GDK_X11_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_RENDERER, GdkX11RendererClass)) ++ ++#define MAX_RENDER_PART PANGO_RENDER_PART_STRIKETHROUGH ++ ++struct _GdkX11Renderer ++{ ++ PangoXftRenderer parent_instance; ++ ++ XRenderPictFormat *mask_format; ++ ++ GdkDrawable *drawable; ++ GdkGC *gc; ++}; ++ ++struct _GdkX11RendererClass ++{ ++ PangoXftRendererClass parent_class; ++}; ++ ++G_DEFINE_TYPE (GdkX11Renderer, _gdk_x11_renderer, PANGO_TYPE_XFT_RENDERER) ++ ++static void ++gdk_x11_renderer_finalize (GObject *object) ++{ ++ G_OBJECT_CLASS (_gdk_x11_renderer_parent_class)->finalize (object); ++} ++ ++static void ++gdk_x11_renderer_composite_trapezoids (PangoXftRenderer *xftrenderer, ++ PangoRenderPart part, ++ XTrapezoid *trapezoids, ++ int n_trapezoids) ++{ ++ /* Because we only use this renderer for "draw_glyphs()" calls, we ++ * won't hit this code path much. However, it is hit for drawing ++ * the "unknown glyph" hex squares. We can safely ignore the part, ++ */ ++ GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer); ++ ++ _gdk_x11_drawable_draw_xtrapezoids (x11_renderer->drawable, ++ x11_renderer->gc, ++ trapezoids, n_trapezoids); ++ ++} ++ ++static void ++gdk_x11_renderer_composite_glyphs (PangoXftRenderer *xftrenderer, ++ XftFont *xft_font, ++ XftGlyphSpec *glyphs, ++ gint n_glyphs) ++{ ++ GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer); ++ ++ _gdk_x11_drawable_draw_xft_glyphs (x11_renderer->drawable, ++ x11_renderer->gc, ++ xft_font, glyphs, n_glyphs); ++} ++ ++static void ++_gdk_x11_renderer_init (GdkX11Renderer *renderer) ++{ ++} ++ ++static void ++_gdk_x11_renderer_class_init (GdkX11RendererClass *klass) ++{ ++ PangoXftRendererClass *xftrenderer_class = PANGO_XFT_RENDERER_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ xftrenderer_class->composite_glyphs = gdk_x11_renderer_composite_glyphs; ++ xftrenderer_class->composite_trapezoids = gdk_x11_renderer_composite_trapezoids; ++ ++ object_class->finalize = gdk_x11_renderer_finalize; ++} ++ ++PangoRenderer * ++_gdk_x11_renderer_get (GdkDrawable *drawable, ++ GdkGC *gc) ++{ ++ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; ++ GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); ++ GdkX11Renderer *x11_renderer; ++ ++ if (!screen_x11->renderer) ++ { ++ screen_x11->renderer = g_object_new (GDK_TYPE_X11_RENDERER, ++ "display", GDK_SCREEN_XDISPLAY (screen), ++ "screen", GDK_SCREEN_XNUMBER (screen), ++ NULL); ++ } ++ ++ x11_renderer = GDK_X11_RENDERER (screen_x11->renderer); ++ ++ x11_renderer->drawable = drawable; ++ x11_renderer->gc = gc; ++ ++ return screen_x11->renderer; ++} ++ ++/** ++ * gdk_pango_context_get_for_screen: ++ * @screen: the #GdkScreen for which the context is to be created. ++ * ++ * Creates a #PangoContext for @screen. ++ * ++ * The context must be freed when you're finished with it. ++ * ++ * When using GTK+, normally you should use gtk_widget_get_pango_context() ++ * instead of this function, to get the appropriate context for ++ * the widget you intend to render text onto. ++ * ++ * Return value: a new #PangoContext for @screen ++ * ++ * Since: 2.2 ++ **/ ++PangoContext * ++gdk_pango_context_get_for_screen (GdkScreen *screen) ++{ ++ PangoContext *context; ++ ++ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); ++ ++ if (screen->closed) ++ return NULL; ++ ++ context = pango_xft_get_context (GDK_SCREEN_XDISPLAY (screen), ++ GDK_SCREEN_X11 (screen)->screen_num); ++ ++ g_object_set_data (G_OBJECT (context), "gdk-pango-screen", screen); ++ ++ return context; ++} ++ ++#define __GDK_PANGO_X11_C__ ++#include "gdkaliasdef.c" +Index: gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c +=================================================================== +--- gtk+-2.10.6.orig/gdk/x11/gdkpixmap-x11.c 2006-10-30 12:58:30.000000000 +0000 ++++ gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c 2006-10-30 12:59:30.000000000 +0000 +@@ -119,6 +119,9 @@ + { + GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl); + ++ if (draw_impl->xft_draw) ++ XftDrawDestroy (draw_impl->xft_draw); ++ + _gdk_x11_drawable_finish (GDK_DRAWABLE (draw_impl)); + } + +--- gtk+-2.10.6.orig/gtk/gtkcalendar.c.orig 2006-11-14 14:39:34.000000000 -0800 ++++ gtk+-2.10.6/gtk/gtkcalendar.c 2006-11-14 14:37:34.000000000 -0800 +@@ -1495,6 +1495,10 @@ gtk_calendar_realize (GtkWidget *widget) + BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); + gdk_window_show (priv->main_win); + gdk_window_set_user_data (priv->main_win, widget); ++ ++ /* Set widgets gc */ ++ calendar->gc = gdk_gc_new (widget->window); ++ + gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget)); + gdk_window_show (widget->window); + gdk_window_set_user_data (widget->window, widget); diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/range-no-redraw.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/range-no-redraw.patch new file mode 100644 index 0000000000..14387b8a2e --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/range-no-redraw.patch @@ -0,0 +1,127 @@ +5f084ea0849d5967a3c22821542ecaaa8accb398 +diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c +index bd95351..64e0e59 100644 +--- gtk/gtkrange.c ++++ gtk/gtkrange.c +@@ -109,6 +109,8 @@ struct _GtkRangeLayout + GtkSensitivityType upper_sensitivity; + + gdouble fill_level; ++ ++ guint motion_idle_id; + }; + + +@@ -205,6 +207,8 @@ static gboolean gtk_range_real_change_value (GtkRange *range, + static void gtk_range_update_value (GtkRange *range); + static gboolean gtk_range_key_press (GtkWidget *range, + GdkEventKey *event); ++static void gtk_range_add_motion_idle (GtkRange *range); ++static void gtk_range_remove_motion_idle (GtkRange *range); + + + static guint signals[LAST_SIGNAL]; +@@ -1167,6 +1171,7 @@ gtk_range_destroy (GtkObject *object) + + gtk_range_remove_step_timer (range); + gtk_range_remove_update_timer (range); ++ gtk_range_remove_motion_idle (range); + + if (range->adjustment) + { +@@ -1276,6 +1281,7 @@ gtk_range_unrealize (GtkWidget *widget) + + gtk_range_remove_step_timer (range); + gtk_range_remove_update_timer (range); ++ gtk_range_remove_motion_idle (range); + + gdk_window_set_user_data (range->event_window, NULL); + gdk_window_destroy (range->event_window); +@@ -2165,7 +2171,7 @@ gtk_range_motion_notify (GtkWidget *widget, + gtk_widget_queue_draw (widget); + + if (range->layout->grab_location == MOUSE_SLIDER) +- update_slider_position (range, x, y); ++ gtk_range_add_motion_idle (range); + + /* We handled the event if the mouse was in the range_rect */ + return range->layout->mouse_location != MOUSE_OUTSIDE; +@@ -3335,9 +3341,10 @@ initial_timeout (gpointer data) + g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL); + + range = GTK_RANGE (data); +- range->timer->timeout_id = gdk_threads_add_timeout (timeout * SCROLL_DELAY_FACTOR, +- second_timeout, +- range); ++ range->timer->timeout_id = ++ gdk_threads_add_timeout (timeout * SCROLL_DELAY_FACTOR, ++ second_timeout, ++ range); + /* remove self */ + return FALSE; + } +@@ -3357,9 +3364,8 @@ gtk_range_add_step_timer (GtkRange *range, + + range->timer = g_new (GtkRangeStepTimer, 1); + +- range->timer->timeout_id = gdk_threads_add_timeout (timeout, +- initial_timeout, +- range); ++ range->timer->timeout_id = ++ gdk_threads_add_timeout (timeout, initial_timeout, range); + range->timer->step = step; + + gtk_range_scroll (range, range->timer->step); +@@ -3397,9 +3403,8 @@ gtk_range_reset_update_timer (GtkRange *range) + { + gtk_range_remove_update_timer (range); + +- range->update_timeout_id = gdk_threads_add_timeout (UPDATE_DELAY, +- update_timeout, +- range); ++ range->update_timeout_id = ++ gdk_threads_add_timeout (UPDATE_DELAY, update_timeout, range); + } + + static void +@@ -3412,5 +3417,40 @@ gtk_range_remove_update_timer (GtkRange *range) + } + } + ++static gboolean ++motion_idle (gpointer data) ++{ ++ GtkRange *range = data; ++ GtkRangeLayout *layout = range->layout; ++ ++ update_slider_position (range, layout->mouse_x, layout->mouse_y); ++ ++ layout->motion_idle_id = 0; ++ ++ return FALSE; ++} ++ ++static void ++gtk_range_add_motion_idle (GtkRange *range) ++{ ++ if (!range->layout->motion_idle_id) ++ { ++ range->layout->motion_idle_id = ++ gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW, ++ motion_idle, range, ++ NULL); ++ } ++} ++ ++static void ++gtk_range_remove_motion_idle (GtkRange *range) ++{ ++ if (range->layout->motion_idle_id != 0) ++ { ++ g_source_remove (range->layout->motion_idle_id); ++ range->layout->motion_idle_id = 0; ++ } ++} ++ + #define __GTK_RANGE_C__ + #include "gtkaliasdef.c" diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/run-iconcache.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/run-iconcache.patch new file mode 100644 index 0000000000..ac15e9ab24 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/run-iconcache.patch @@ -0,0 +1,19 @@ +--- /tmp/Makefile.am 2007-01-08 17:44:47.000000000 +0100 ++++ gtk+-2.10.7/gtk/Makefile.am 2007-01-08 17:45:17.025251000 +0100 +@@ -1128,11 +1128,11 @@ + ./gtk-update-icon-cache + endif + +-gtkbuiltincache.h: @REBUILD@ stamp-icons +- $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT) +- $(gtk_update_icon_cache_program) --force --ignore-theme-index \ +- --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \ +- mv gtkbuiltincache.h.tmp gtkbuiltincache.h ++#gtkbuiltincache.h: @REBUILD@ stamp-icons ++# $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT) ++# $(gtk_update_icon_cache_program) --force --ignore-theme-index \ ++# --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \ ++# mv gtkbuiltincache.h.tmp gtkbuiltincache.h + + EXTRA_DIST += \ + $(STOCK_ICONS) \ diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/scrolled-placement.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/scrolled-placement.patch new file mode 100644 index 0000000000..a0b50c8cac --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/scrolled-placement.patch @@ -0,0 +1,22 @@ +Index: gdk/x11/gdksettings.c +=================================================================== +--- gdk/x11/gdksettings.c (revision 18493) ++++ gdk/x11/gdksettings.c (working copy) +@@ -65,7 +65,8 @@ + "Xft/RGBA\0" "gtk-xft-rgba\0" + "Xft/DPI\0" "gtk-xft-dpi\0" + "Net/FallbackIconTheme\0" "gtk-fallback-icon-theme\0" +- "Gtk/TouchscreenMode\0" "gtk-touchscreen-mode\0"; ++ "Gtk/TouchscreenMode\0" "gtk-touchscreen-mode\0" ++ "Gtk/ScrolledWindowPlacement\0" "gtk-scrolled-window-placement\0"; + + static const struct + { +@@ -107,5 +108,6 @@ + { 1197, 1206 }, + { 1219, 1227 }, + { 1239, 1261 }, +- { 1285, 1305 } ++ { 1285, 1305 }, ++ { 1326, 1354 } + }; diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/toggle-font.diff b/meta/recipes-gnome/gtk+/gtk+-2.12.7/toggle-font.diff new file mode 100644 index 0000000000..59ad150b2f --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/toggle-font.diff @@ -0,0 +1,100 @@ +Index: gtk/gtkcellrenderertoggle.c +=================================================================== +--- gtk/gtkcellrenderertoggle.c (revision 18523) ++++ gtk/gtkcellrenderertoggle.c (working copy) +@@ -71,6 +71,8 @@ + PROP_INDICATOR_SIZE + }; + ++/* This is a hard-coded default which promptly gets overridden by a size ++ calculated from the font size. */ + #define TOGGLE_WIDTH 13 + + static guint toggle_cell_signals[LAST_SIGNAL] = { 0 }; +@@ -80,8 +82,9 @@ + typedef struct _GtkCellRendererTogglePrivate GtkCellRendererTogglePrivate; + struct _GtkCellRendererTogglePrivate + { +- gint indicator_size; +- ++ gint indicator_size; /* This is the real size */ ++ gint override_size; /* This is the size set from the indicator-size property */ ++ GtkWidget *cached_widget; + guint inconsistent : 1; + }; + +@@ -104,6 +107,7 @@ + GTK_CELL_RENDERER (celltoggle)->ypad = 2; + + priv->indicator_size = TOGGLE_WIDTH; ++ priv->override_size = 0; + priv->inconsistent = FALSE; + } + +@@ -210,7 +214,7 @@ + g_value_set_boolean (value, celltoggle->radio); + break; + case PROP_INDICATOR_SIZE: +- g_value_set_int (value, priv->indicator_size); ++ g_value_set_int (value, priv->override_size ? priv->override_size : priv->indicator_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +@@ -245,7 +249,7 @@ + celltoggle->radio = g_value_get_boolean (value); + break; + case PROP_INDICATOR_SIZE: +- priv->indicator_size = g_value_get_int (value); ++ priv->override_size = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +@@ -273,6 +277,27 @@ + } + + static void ++on_widget_style_set (GtkWidget *widget, GtkStyle *previous, gpointer user_data) ++{ ++ GtkCellRendererTogglePrivate *priv = user_data; ++ PangoContext *context; ++ PangoFontMetrics *metrics; ++ int height; ++ ++ context = gtk_widget_get_pango_context (widget); ++ metrics = pango_context_get_metrics (context, ++ widget->style->font_desc, ++ pango_context_get_language (context)); ++ ++ height = pango_font_metrics_get_ascent (metrics) + ++ pango_font_metrics_get_descent (metrics); ++ ++ pango_font_metrics_unref (metrics); ++ ++ priv->indicator_size = PANGO_PIXELS (height * 0.85); ++} ++ ++static void + gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *cell_area, +@@ -287,6 +312,20 @@ + + priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (cell); + ++ if (priv->override_size) { ++ priv->indicator_size = priv->override_size; ++ } else if (priv->cached_widget != widget) { ++ if (priv->cached_widget) { ++ g_object_remove_weak_pointer (widget, &priv->cached_widget); ++ g_signal_handlers_disconnect_by_func (priv->cached_widget, on_widget_style_set, priv); ++ } ++ priv->cached_widget = widget; ++ g_object_add_weak_pointer (widget, &priv->cached_widget); ++ g_signal_connect (widget, "style-set", on_widget_style_set, priv); ++ ++ on_widget_style_set (widget, NULL, priv); ++ } ++ + calc_width = (gint) cell->xpad * 2 + priv->indicator_size; + calc_height = (gint) cell->ypad * 2 + priv->indicator_size; + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.12.7/xsettings.patch b/meta/recipes-gnome/gtk+/gtk+-2.12.7/xsettings.patch new file mode 100644 index 0000000000..b63e262d34 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.12.7/xsettings.patch @@ -0,0 +1,16 @@ +--- gtk+-2.4.4/gdk/x11/gdkevents-x11.c.old Sun Aug 22 17:14:00 2004 ++++ gtk+-2.4.4/gdk/x11/gdkevents-x11.c Sun Aug 22 17:14:00 2004 +@@ -2827,10 +2827,9 @@ + { + GdkScreenX11 *screen = data; + +- if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent)) +- return GDK_FILTER_REMOVE; +- else +- return GDK_FILTER_CONTINUE; ++ xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent); ++ ++ return GDK_FILTER_CONTINUE; + } + + static void diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch b/meta/recipes-gnome/gtk+/gtk+-2.16.6/0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch new file mode 100644 index 0000000000..e0d6ab9522 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch @@ -0,0 +1,31 @@ +From 69b9441eab2a7215509687dc22b48b6f212d22aa Mon Sep 17 00:00:00 2001 +From: Rob Bradford <rob@linux.intel.com> +Date: Thu, 4 Jun 2009 15:43:20 +0100 +Subject: [PATCH] =?utf-8?q?bgo#584832=20=E2=80=93=20Duplicate=20the=20exec=20string=20returned=20by=20gtk=5Frecent=5Finfo=5Fget=5Fapplication=5Finfo?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +This function states that the caller is responsible for freeing the string +passed returned by reference. Unfortunately if you do this you get a crash +since the internal value is returned without being duplicated. +--- + gtk/gtkrecentmanager.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/gtk/gtkrecentmanager.c b/gtk/gtkrecentmanager.c +index 317b3d5..d062572 100644 +--- a/gtk/gtkrecentmanager.c ++++ b/gtk/gtkrecentmanager.c +@@ -1764,7 +1764,7 @@ gtk_recent_info_get_application_info (GtkRecentInfo *info, + } + + if (app_exec) +- *app_exec = ai->exec; ++ *app_exec = g_strdup (ai->exec); + + if (count) + *count = ai->count; +-- +1.6.3.1 + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/cellrenderer-cairo.patch b/meta/recipes-gnome/gtk+/gtk+-2.16.6/cellrenderer-cairo.patch new file mode 100644 index 0000000000..4439e69fb6 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/cellrenderer-cairo.patch @@ -0,0 +1,32 @@ +Index: gtk/gtkcellrenderer.c +=================================================================== +RCS file: /cvs/gnome/gtk+/gtk/gtkcellrenderer.c,v +retrieving revision 1.55 +diff -u -r1.55 gtkcellrenderer.c +--- gtk/gtkcellrenderer.c 14 May 2006 04:25:28 -0000 1.55 ++++ gtk/gtkcellrenderer.c 30 Jun 2006 10:57:43 -0000 +@@ -551,6 +551,7 @@ + + if (cell->cell_background_set && !selected) + { ++#ifdef USE_CAIRO_INTERNALLY + cairo_t *cr = gdk_cairo_create (window); + + gdk_cairo_rectangle (cr, background_area); +@@ -558,6 +559,16 @@ + cairo_fill (cr); + + cairo_destroy (cr); ++#else ++ GdkGC *gc; ++ ++ gc = gdk_gc_new (window); ++ gdk_gc_set_rgb_fg_color (gc, &priv->cell_background); ++ gdk_draw_rectangle (window, gc, TRUE, ++ background_area->x, background_area->y, ++ background_area->width, background_area->height); ++ g_object_unref (gc); ++#endif + } + + GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell, diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/disable-gio-png-sniff-test.diff b/meta/recipes-gnome/gtk+/gtk+-2.16.6/disable-gio-png-sniff-test.diff new file mode 100644 index 0000000000..5c64ac04de --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/disable-gio-png-sniff-test.diff @@ -0,0 +1,97 @@ +Index: gtk+-2.14.2/configure.in +=================================================================== +--- gtk+-2.14.2.orig/configure.in 2008-09-23 16:32:42.000000000 +0100 ++++ gtk+-2.14.2/configure.in 2008-09-23 16:37:13.000000000 +0100 +@@ -1025,48 +1025,50 @@ + # check one of the variables here + AM_CONDITIONAL(INCLUDE_GDIPLUS, [test x"$INCLUDE_gdip_ico" = xyes]) + +-if test x$gio_can_sniff = x; then +- AC_MSG_CHECKING([if gio can sniff png]) +- gtk_save_LIBS="$LIBS" +- gtk_save_CFLAGS="$CFLAGS" +- LIBS="`$PKG_CONFIG --libs gio-2.0`" +- CFLAGS="`$PKG_CONFIG --cflags gio-2.0`" +- AC_RUN_IFELSE([AC_LANG_SOURCE([[ +- #include <gio/gio.h> +- static const gsize data_size = 159; +- static const guint8 data[] = +- { +- 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, +- 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, +- 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00, +- 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, +- 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, +- 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, +- 0x49, 0x4d, 0x45, 0x07, 0xd8, 0x07, 0x0f, 0x10, 0x08, 0x15, 0x61, 0xd8, +- 0x35, 0x37, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, +- 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, +- 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, +- 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, 0x54, 0x08, +- 0xd7, 0x63, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x05, 0xfe, 0x02, 0xfe, 0xdc, +- 0xcc, 0x59, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, +- 0x42, 0x60, 0x82 +- }; +- int +- main (int argc, char **argv) +- { +- char *content_type; +- char *image_png; +- content_type = g_content_type_guess (NULL, data, data_size, NULL); +- image_png = g_content_type_from_mime_type ("image/png"); +- return !!strcmp (content_type, image_png); +- }]])], +- [gio_can_sniff=yes +- AC_DEFINE(GDK_PIXBUF_USE_GIO_MIME, 1, [Define if gio can sniff image data])], +- [gio_can_sniff=no]) +- AC_MSG_RESULT($gio_can_sniff) +- LIBS="$gtk_save_LIBS" +- CFLAGS="$gtk_save_CFLAGS" +-fi ++# Disabled due to cross-compile ++#if test x$gio_can_sniff = x; then ++# AC_MSG_CHECKING([if gio can sniff png]) ++# gtk_save_LIBS="$LIBS" ++# gtk_save_CFLAGS="$CFLAGS" ++# LIBS="`$PKG_CONFIG --libs gio-2.0`" ++# CFLAGS="`$PKG_CONFIG --cflags gio-2.0`" ++# AC_RUN_IFELSE([AC_LANG_SOURCE([[ ++# #include <gio/gio.h> ++# static const gsize data_size = 159; ++# static const guint8 data[] = ++# { ++# 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, ++# 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, ++# 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00, ++# 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, ++# 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, ++# 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, ++# 0x49, 0x4d, 0x45, 0x07, 0xd8, 0x07, 0x0f, 0x10, 0x08, 0x15, 0x61, 0xd8, ++# 0x35, 0x37, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, ++# 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, ++# 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, ++# 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, 0x54, 0x08, ++# 0xd7, 0x63, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x05, 0xfe, 0x02, 0xfe, 0xdc, ++# 0xcc, 0x59, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, ++# 0x42, 0x60, 0x82 ++# }; ++# int ++# main (int argc, char **argv) ++# { ++# char *content_type; ++# char *image_png; ++# content_type = g_content_type_guess (NULL, data, data_size, NULL); ++# image_png = g_content_type_from_mime_type ("image/png"); ++# return !!strcmp (content_type, image_png); ++# }]])], ++# [gio_can_sniff=yes ++# [gio_can_sniff=no]) ++# AC_MSG_RESULT($gio_can_sniff) ++# LIBS="$gtk_save_LIBS" ++# CFLAGS="$gtk_save_CFLAGS" ++#fi ++ ++AC_DEFINE(GDK_PIXBUF_USE_GIO_MIME, 1, [Define if gio can sniff image data])], + + # + # Allow building some or all immodules included diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/entry-cairo.patch b/meta/recipes-gnome/gtk+/gtk+-2.16.6/entry-cairo.patch new file mode 100644 index 0000000000..3313e7f132 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/entry-cairo.patch @@ -0,0 +1,103 @@ +Index: gtk/gtkentry.c +=================================================================== +RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v +retrieving revision 1.317 +diff -u -r1.317 gtkentry.c +--- gtk/gtkentry.c 29 Jun 2006 09:18:05 -0000 1.317 ++++ gtk/gtkentry.c 2 Jul 2006 14:14:24 -0000 +@@ -3337,7 +3337,9 @@ + if (GTK_WIDGET_DRAWABLE (entry)) + { + PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); ++#ifdef USE_CAIRO_INTERNALLY + cairo_t *cr; ++#endif + gint x, y; + gint start_pos, end_pos; + +@@ -3345,23 +3347,35 @@ + + get_layout_position (entry, &x, &y); + ++#ifdef USE_CAIRO_INTERNALLY + cr = gdk_cairo_create (entry->text_area); + + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); + pango_cairo_show_layout (cr, layout); ++#else ++ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], ++ x, y, ++ layout); ++#endif + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) + { + gint *ranges; + gint n_ranges, i; + PangoRectangle logical_rect; +- GdkColor *selection_color, *text_color; + GtkBorder inner_border; ++#ifdef USE_CAIRO_INTERNALLY ++ GdkColor *selection_color, *text_color; ++#else ++ GdkGC *selection_gc, *text_gc; ++ GdkRegion *clip_region; ++#endif + + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); + ++#ifdef USE_CAIRO_INTERNALLY + if (GTK_WIDGET_HAS_FOCUS (entry)) + { + selection_color = &widget->style->base [GTK_STATE_SELECTED]; +@@ -3390,11 +3404,46 @@ + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, text_color); + pango_cairo_show_layout (cr, layout); +- ++#else ++ if (GTK_WIDGET_HAS_FOCUS (entry)) ++ { ++ selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; ++ text_gc = widget->style->text_gc [GTK_STATE_SELECTED]; ++ } ++ else ++ { ++ selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; ++ text_gc = widget->style->text_gc [GTK_STATE_ACTIVE]; ++ } ++ ++ clip_region = gdk_region_new (); ++ for (i = 0; i < n_ranges; ++i) ++ { ++ GdkRectangle rect; ++ ++ rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i]; ++ rect.y = y; ++ rect.width = ranges[2 * i + 1]; ++ rect.height = logical_rect.height; ++ ++ gdk_draw_rectangle (entry->text_area, selection_gc, TRUE, ++ rect.x, rect.y, rect.width, rect.height); ++ ++ gdk_region_union_with_rect (clip_region, &rect); ++ } ++ ++ gdk_gc_set_clip_region (text_gc, clip_region); ++ gdk_draw_layout (entry->text_area, text_gc, ++ x, y, ++ layout); ++ gdk_gc_set_clip_region (text_gc, NULL); ++ gdk_region_destroy (clip_region); ++#endif + g_free (ranges); + } +- ++#ifdef USE_CAIRO_INTERNALLY + cairo_destroy (cr); ++#endif + } + } + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/hardcoded_libtool.patch b/meta/recipes-gnome/gtk+/gtk+-2.16.6/hardcoded_libtool.patch new file mode 100644 index 0000000000..82fbbac8d7 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/hardcoded_libtool.patch @@ -0,0 +1,31 @@ +Index: gtk+-2.14.2/configure.in +=================================================================== +--- gtk+-2.14.2.orig/configure.in 2008-09-23 15:52:44.000000000 +0100 ++++ gtk+-2.14.2/configure.in 2008-09-23 15:53:51.000000000 +0100 +@@ -401,7 +401,7 @@ + case $enable_explicit_deps in + auto) + export SED +- deplibs_check_method=`(./libtool --config; echo 'eval echo \"$deplibs_check_method\"') | sh` ++ deplibs_check_method=`(./$host_alias-libtool --config; echo 'eval echo \"$deplibs_check_method\"') | sh` + if test "x$deplibs_check_method" '!=' xpass_all || test "x$enable_static" = xyes ; then + enable_explicit_deps=yes + else +@@ -759,7 +759,7 @@ + dnl Now we check to see if our libtool supports shared lib deps + dnl (in a rather ugly way even) + if $dynworks; then +- pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} ./libtool --config" ++ pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} $host_alias-libtool --config" + pixbuf_deplibs_check=`$pixbuf_libtool_config | \ + grep '^[[a-z_]]*check[[a-z_]]*_method=[['\''"]]' | \ + sed 's/.*[['\''"]]\(.*\)[['\''"]]$/\1/'` +@@ -1893,7 +1893,7 @@ + # We are using gmodule-no-export now, but I'm leaving the stripping + # code in place for now, since pango and atk still require gmodule. + export SED +-export_dynamic=`(./libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh` ++export_dynamic=`($host_alias-libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh` + if test -n "$export_dynamic"; then + GDK_PIXBUF_DEP_LIBS=`echo $GDK_PIXBUF_DEP_LIBS | sed -e "s/$export_dynamic//"` + GDK_PIXBUF_XLIB_DEP_LIBS=`echo $GDK_PIXBUF_XLIB_DEP_LIBS | sed -e "s/$export_dynamic//"` diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/no-demos.patch b/meta/recipes-gnome/gtk+/gtk+-2.16.6/no-demos.patch new file mode 100644 index 0000000000..0fc4c48d1a --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/no-demos.patch @@ -0,0 +1,10 @@ +--- gtk+-2.10.1/Makefile.am.orig 2006-08-08 12:37:30.000000000 +0100 ++++ gtk+-2.10.1/Makefile.am 2006-08-08 12:37:48.000000000 +0100 +@@ -1,6 +1,6 @@ + ## Makefile.am for GTK+ + +-SRC_SUBDIRS = gdk-pixbuf gdk gtk modules demos tests perf contrib ++SRC_SUBDIRS = gdk-pixbuf gdk gtk modules tests perf contrib + SUBDIRS = po po-properties $(SRC_SUBDIRS) docs m4macros + + # require automake 1.4 diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/run-iconcache.patch b/meta/recipes-gnome/gtk+/gtk+-2.16.6/run-iconcache.patch new file mode 100644 index 0000000000..ac15e9ab24 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/run-iconcache.patch @@ -0,0 +1,19 @@ +--- /tmp/Makefile.am 2007-01-08 17:44:47.000000000 +0100 ++++ gtk+-2.10.7/gtk/Makefile.am 2007-01-08 17:45:17.025251000 +0100 +@@ -1128,11 +1128,11 @@ + ./gtk-update-icon-cache + endif + +-gtkbuiltincache.h: @REBUILD@ stamp-icons +- $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT) +- $(gtk_update_icon_cache_program) --force --ignore-theme-index \ +- --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \ +- mv gtkbuiltincache.h.tmp gtkbuiltincache.h ++#gtkbuiltincache.h: @REBUILD@ stamp-icons ++# $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT) ++# $(gtk_update_icon_cache_program) --force --ignore-theme-index \ ++# --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \ ++# mv gtkbuiltincache.h.tmp gtkbuiltincache.h + + EXTRA_DIST += \ + $(STOCK_ICONS) \ diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/toggle-font.diff b/meta/recipes-gnome/gtk+/gtk+-2.16.6/toggle-font.diff new file mode 100644 index 0000000000..59ad150b2f --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/toggle-font.diff @@ -0,0 +1,100 @@ +Index: gtk/gtkcellrenderertoggle.c +=================================================================== +--- gtk/gtkcellrenderertoggle.c (revision 18523) ++++ gtk/gtkcellrenderertoggle.c (working copy) +@@ -71,6 +71,8 @@ + PROP_INDICATOR_SIZE + }; + ++/* This is a hard-coded default which promptly gets overridden by a size ++ calculated from the font size. */ + #define TOGGLE_WIDTH 13 + + static guint toggle_cell_signals[LAST_SIGNAL] = { 0 }; +@@ -80,8 +82,9 @@ + typedef struct _GtkCellRendererTogglePrivate GtkCellRendererTogglePrivate; + struct _GtkCellRendererTogglePrivate + { +- gint indicator_size; +- ++ gint indicator_size; /* This is the real size */ ++ gint override_size; /* This is the size set from the indicator-size property */ ++ GtkWidget *cached_widget; + guint inconsistent : 1; + }; + +@@ -104,6 +107,7 @@ + GTK_CELL_RENDERER (celltoggle)->ypad = 2; + + priv->indicator_size = TOGGLE_WIDTH; ++ priv->override_size = 0; + priv->inconsistent = FALSE; + } + +@@ -210,7 +214,7 @@ + g_value_set_boolean (value, celltoggle->radio); + break; + case PROP_INDICATOR_SIZE: +- g_value_set_int (value, priv->indicator_size); ++ g_value_set_int (value, priv->override_size ? priv->override_size : priv->indicator_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +@@ -245,7 +249,7 @@ + celltoggle->radio = g_value_get_boolean (value); + break; + case PROP_INDICATOR_SIZE: +- priv->indicator_size = g_value_get_int (value); ++ priv->override_size = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +@@ -273,6 +277,27 @@ + } + + static void ++on_widget_style_set (GtkWidget *widget, GtkStyle *previous, gpointer user_data) ++{ ++ GtkCellRendererTogglePrivate *priv = user_data; ++ PangoContext *context; ++ PangoFontMetrics *metrics; ++ int height; ++ ++ context = gtk_widget_get_pango_context (widget); ++ metrics = pango_context_get_metrics (context, ++ widget->style->font_desc, ++ pango_context_get_language (context)); ++ ++ height = pango_font_metrics_get_ascent (metrics) + ++ pango_font_metrics_get_descent (metrics); ++ ++ pango_font_metrics_unref (metrics); ++ ++ priv->indicator_size = PANGO_PIXELS (height * 0.85); ++} ++ ++static void + gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *cell_area, +@@ -287,6 +312,20 @@ + + priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (cell); + ++ if (priv->override_size) { ++ priv->indicator_size = priv->override_size; ++ } else if (priv->cached_widget != widget) { ++ if (priv->cached_widget) { ++ g_object_remove_weak_pointer (widget, &priv->cached_widget); ++ g_signal_handlers_disconnect_by_func (priv->cached_widget, on_widget_style_set, priv); ++ } ++ priv->cached_widget = widget; ++ g_object_add_weak_pointer (widget, &priv->cached_widget); ++ g_signal_connect (widget, "style-set", on_widget_style_set, priv); ++ ++ on_widget_style_set (widget, NULL, priv); ++ } ++ + calc_width = (gint) cell->xpad * 2 + priv->indicator_size; + calc_height = (gint) cell->ypad * 2 + priv->indicator_size; + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.16.6/xsettings.patch b/meta/recipes-gnome/gtk+/gtk+-2.16.6/xsettings.patch new file mode 100644 index 0000000000..b63e262d34 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.16.6/xsettings.patch @@ -0,0 +1,16 @@ +--- gtk+-2.4.4/gdk/x11/gdkevents-x11.c.old Sun Aug 22 17:14:00 2004 ++++ gtk+-2.4.4/gdk/x11/gdkevents-x11.c Sun Aug 22 17:14:00 2004 +@@ -2827,10 +2827,9 @@ + { + GdkScreenX11 *screen = data; + +- if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent)) +- return GDK_FILTER_REMOVE; +- else +- return GDK_FILTER_CONTINUE; ++ xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent); ++ ++ return GDK_FILTER_CONTINUE; + } + + static void diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch new file mode 100644 index 0000000000..ee55f9cc3b --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch @@ -0,0 +1,28 @@ +From 69b9441eab2a7215509687dc22b48b6f212d22aa Mon Sep 17 00:00:00 2001 +From: Rob Bradford <rob@linux.intel.com> +Date: Thu, 4 Jun 2009 15:43:20 +0100 +Subject: [PATCH] =?utf-8?q?bgo#584832=20=E2=80=93=20Duplicate=20the=20exec=20string=20returned=20by=20gtk=5Frecent=5Finfo=5Fget=5Fapplication=5Finfo?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +This function states that the caller is responsible for freeing the string +passed returned by reference. Unfortunately if you do this you get a crash +since the internal value is returned without being duplicated. +--- + gtk/gtkrecentmanager.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +Index: gtk+-2.21.2/gtk/gtkrecentmanager.c +=================================================================== +--- gtk+-2.21.2.orig/gtk/gtkrecentmanager.c 2010-06-22 18:11:30.000000000 +0800 ++++ gtk+-2.21.2/gtk/gtkrecentmanager.c 2010-06-22 18:11:53.000000000 +0800 +@@ -1766,7 +1766,7 @@ + } + + if (app_exec) +- *app_exec = ai->exec; ++ *app_exec = g_strdup (ai->exec); + + if (count) + *count = ai->count; diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/cellrenderer-cairo.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/cellrenderer-cairo.patch new file mode 100644 index 0000000000..92ce643125 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/cellrenderer-cairo.patch @@ -0,0 +1,29 @@ +Index: gtk/gtkcellrenderer.c +=================================================================== +--- gtk/gtkcellrenderer.c.orig 2010-06-22 17:21:22.000000000 +0800 ++++ gtk/gtkcellrenderer.c 2010-06-22 17:21:25.000000000 +0800 +@@ -566,6 +566,7 @@ + + if (cell->cell_background_set && !selected) + { ++#ifdef USE_CAIRO_INTERNALLY + cairo_t *cr = gdk_cairo_create (window); + + gdk_cairo_rectangle (cr, background_area); +@@ -573,6 +574,16 @@ + cairo_fill (cr); + + cairo_destroy (cr); ++#else ++ GdkGC *gc; ++ ++ gc = gdk_gc_new (window); ++ gdk_gc_set_rgb_fg_color (gc, &priv->cell_background); ++ gdk_draw_rectangle (window, gc, TRUE, ++ background_area->x, background_area->y, ++ background_area->width, background_area->height); ++ g_object_unref (gc); ++#endif + } + + GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell, diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/configurefix.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/configurefix.patch new file mode 100644 index 0000000000..7f6c73be49 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/configurefix.patch @@ -0,0 +1,85 @@ +Index: gtk+-2.21.2/docs/faq/Makefile.am +=================================================================== +--- gtk+-2.21.2.orig/docs/faq/Makefile.am 2010-04-09 10:29:53.000000000 +0800 ++++ gtk+-2.21.2/docs/faq/Makefile.am 2010-06-22 17:39:24.000000000 +0800 +@@ -3,34 +3,36 @@ + EXTRA_DIST += \ + gtk-faq.sgml + +-if HAVE_DOCBOOK ++ + html: ++if HAVE_DOCBOOK + if test -w $(srcdir); then \ + (cd $(srcdir); \ + db2html gtk-faq.sgml; \ + test -d html && rm -r html; \ + mv gtk-faq html); \ + fi +- +-pdf: +- if test -w $(srcdir); then \ +- (cd $(srcdir); db2pdf gtk-faq.sgml); \ +- fi +- +-dist-hook: html +- cp -Rp $(srcdir)/html $(distdir) + else +-html: + echo "***" + echo "*** Warning: FAQ not built" + echo "***" ++endif + + pdf: ++if HAVE_DOCBOOK ++ if test -w $(srcdir); then \ ++ (cd $(srcdir); db2pdf gtk-faq.sgml); \ ++ fi ++else + echo "***" + echo "*** Warning: FAQ not built" + echo "***" ++endif + +-dist-hook: ++dist-hook: html ++if HAVE_DOCBOOK ++ cp -Rp $(srcdir)/html $(distdir) ++else + echo "***" + echo "*** Warning: FAQ not built" + echo "*** DISTRIBUTION IS INCOMPLETE" +Index: gtk+-2.21.2/gtk-doc.make +=================================================================== +--- gtk+-2.21.2.orig/gtk-doc.make 2010-05-28 00:01:48.000000000 +0800 ++++ gtk+-2.21.2/gtk-doc.make 2010-06-22 17:39:24.000000000 +0800 +@@ -23,7 +23,7 @@ + + TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE) + +-EXTRA_DIST = \ ++EXTRA_DIST += \ + $(content_files) \ + $(HTML_IMAGES) \ + $(DOC_MAIN_SGML_FILE) \ +Index: gtk+-2.21.2/gtk/tests/Makefile.am +=================================================================== +--- gtk+-2.21.2.orig/gtk/tests/Makefile.am 2010-06-10 20:53:46.000000000 +0800 ++++ gtk+-2.21.2/gtk/tests/Makefile.am 2010-06-22 17:39:24.000000000 +0800 +@@ -58,13 +58,13 @@ + # this doesn't work in make distcheck, since running + # on a naked X server creates slightly different event + # sequences than running on a normal desktop +-# TEST_PROGS += crossingevents ++#TEST_PROGS += crossingevents + crossingevents_SOURCES = crossingevents.c + crossingevents_LDADD = $(progs_ldadd) + + # this doesn't work in make distcheck, since it doesn't + # find file-chooser-test-dir +-# TEST_PROGS += filechooser ++#TEST_PROGS += filechooser + filechooser_SOURCES = filechooser.c pixbuf-init.c + filechooser_LDADD = $(progs_ldadd) + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/disable-gio-png-sniff-test.diff b/meta/recipes-gnome/gtk+/gtk+-2.20.1/disable-gio-png-sniff-test.diff new file mode 100644 index 0000000000..13ae61ef88 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/disable-gio-png-sniff-test.diff @@ -0,0 +1,97 @@ +Index: gtk+-2.21.2/configure.in +=================================================================== +--- gtk+-2.21.2.orig/configure.in 2010-06-22 18:14:40.000000000 +0800 ++++ gtk+-2.21.2/configure.in 2010-06-22 18:14:58.000000000 +0800 +@@ -1072,48 +1072,50 @@ + # check one of the variables here + AM_CONDITIONAL(INCLUDE_GDIPLUS, [test x"$INCLUDE_gdip_ico" = xyes]) + +-if test x$gio_can_sniff = x; then +- AC_MSG_CHECKING([if gio can sniff png]) +- gtk_save_LIBS="$LIBS" +- gtk_save_CFLAGS="$CFLAGS" +- LIBS="`$PKG_CONFIG --libs gio-2.0`" +- CFLAGS="`$PKG_CONFIG --cflags gio-2.0`" +- AC_RUN_IFELSE([AC_LANG_SOURCE([[ +- #include <gio/gio.h> +- static const gsize data_size = 159; +- static const guint8 data[] = +- { +- 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, +- 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, +- 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00, +- 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, +- 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, +- 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, +- 0x49, 0x4d, 0x45, 0x07, 0xd8, 0x07, 0x0f, 0x10, 0x08, 0x15, 0x61, 0xd8, +- 0x35, 0x37, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, +- 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, +- 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, +- 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, 0x54, 0x08, +- 0xd7, 0x63, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x05, 0xfe, 0x02, 0xfe, 0xdc, +- 0xcc, 0x59, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, +- 0x42, 0x60, 0x82 +- }; +- int +- main (int argc, char **argv) +- { +- char *content_type; +- char *image_png; +- content_type = g_content_type_guess (NULL, data, data_size, NULL); +- image_png = g_content_type_from_mime_type ("image/png"); +- return !!strcmp (content_type, image_png); +- }]])], +- [gio_can_sniff=yes +- AC_DEFINE(GDK_PIXBUF_USE_GIO_MIME, 1, [Define if gio can sniff image data])], +- [gio_can_sniff=no]) +- AC_MSG_RESULT($gio_can_sniff) +- LIBS="$gtk_save_LIBS" +- CFLAGS="$gtk_save_CFLAGS" +-fi ++# Disabled due to cross-compile ++#if test x$gio_can_sniff = x; then ++# AC_MSG_CHECKING([if gio can sniff png]) ++# gtk_save_LIBS="$LIBS" ++# gtk_save_CFLAGS="$CFLAGS" ++# LIBS="`$PKG_CONFIG --libs gio-2.0`" ++# CFLAGS="`$PKG_CONFIG --cflags gio-2.0`" ++# AC_RUN_IFELSE([AC_LANG_SOURCE([[ ++# #include <gio/gio.h> ++# static const gsize data_size = 159; ++# static const guint8 data[] = ++# { ++# 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, ++# 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, ++# 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00, ++# 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, ++# 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, ++# 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, ++# 0x49, 0x4d, 0x45, 0x07, 0xd8, 0x07, 0x0f, 0x10, 0x08, 0x15, 0x61, 0xd8, ++# 0x35, 0x37, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, ++# 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, ++# 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, ++# 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, 0x54, 0x08, ++# 0xd7, 0x63, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x05, 0xfe, 0x02, 0xfe, 0xdc, ++# 0xcc, 0x59, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, ++# 0x42, 0x60, 0x82 ++# }; ++# int ++# main (int argc, char **argv) ++# { ++# char *content_type; ++# char *image_png; ++# content_type = g_content_type_guess (NULL, data, data_size, NULL); ++# image_png = g_content_type_from_mime_type ("image/png"); ++# return !!strcmp (content_type, image_png); ++# }]])], ++# [gio_can_sniff=yes ++# [gio_can_sniff=no]) ++# AC_MSG_RESULT($gio_can_sniff) ++# LIBS="$gtk_save_LIBS" ++# CFLAGS="$gtk_save_CFLAGS" ++#fi ++ ++AC_DEFINE(GDK_PIXBUF_USE_GIO_MIME, 1, [Define if gio can sniff image data])], + + # + # Allow building some or all immodules included diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/entry-cairo.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/entry-cairo.patch new file mode 100644 index 0000000000..3313e7f132 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/entry-cairo.patch @@ -0,0 +1,103 @@ +Index: gtk/gtkentry.c +=================================================================== +RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v +retrieving revision 1.317 +diff -u -r1.317 gtkentry.c +--- gtk/gtkentry.c 29 Jun 2006 09:18:05 -0000 1.317 ++++ gtk/gtkentry.c 2 Jul 2006 14:14:24 -0000 +@@ -3337,7 +3337,9 @@ + if (GTK_WIDGET_DRAWABLE (entry)) + { + PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); ++#ifdef USE_CAIRO_INTERNALLY + cairo_t *cr; ++#endif + gint x, y; + gint start_pos, end_pos; + +@@ -3345,23 +3347,35 @@ + + get_layout_position (entry, &x, &y); + ++#ifdef USE_CAIRO_INTERNALLY + cr = gdk_cairo_create (entry->text_area); + + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); + pango_cairo_show_layout (cr, layout); ++#else ++ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], ++ x, y, ++ layout); ++#endif + + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) + { + gint *ranges; + gint n_ranges, i; + PangoRectangle logical_rect; +- GdkColor *selection_color, *text_color; + GtkBorder inner_border; ++#ifdef USE_CAIRO_INTERNALLY ++ GdkColor *selection_color, *text_color; ++#else ++ GdkGC *selection_gc, *text_gc; ++ GdkRegion *clip_region; ++#endif + + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); + ++#ifdef USE_CAIRO_INTERNALLY + if (GTK_WIDGET_HAS_FOCUS (entry)) + { + selection_color = &widget->style->base [GTK_STATE_SELECTED]; +@@ -3390,11 +3404,46 @@ + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, text_color); + pango_cairo_show_layout (cr, layout); +- ++#else ++ if (GTK_WIDGET_HAS_FOCUS (entry)) ++ { ++ selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; ++ text_gc = widget->style->text_gc [GTK_STATE_SELECTED]; ++ } ++ else ++ { ++ selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; ++ text_gc = widget->style->text_gc [GTK_STATE_ACTIVE]; ++ } ++ ++ clip_region = gdk_region_new (); ++ for (i = 0; i < n_ranges; ++i) ++ { ++ GdkRectangle rect; ++ ++ rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i]; ++ rect.y = y; ++ rect.width = ranges[2 * i + 1]; ++ rect.height = logical_rect.height; ++ ++ gdk_draw_rectangle (entry->text_area, selection_gc, TRUE, ++ rect.x, rect.y, rect.width, rect.height); ++ ++ gdk_region_union_with_rect (clip_region, &rect); ++ } ++ ++ gdk_gc_set_clip_region (text_gc, clip_region); ++ gdk_draw_layout (entry->text_area, text_gc, ++ x, y, ++ layout); ++ gdk_gc_set_clip_region (text_gc, NULL); ++ gdk_region_destroy (clip_region); ++#endif + g_free (ranges); + } +- ++#ifdef USE_CAIRO_INTERNALLY + cairo_destroy (cr); ++#endif + } + } + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/hardcoded_libtool.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/hardcoded_libtool.patch new file mode 100644 index 0000000000..66be74475b --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/hardcoded_libtool.patch @@ -0,0 +1,31 @@ +Index: gtk+-2.21.2/configure.in +=================================================================== +--- gtk+-2.21.2.orig/configure.in 2010-06-22 17:21:41.000000000 +0800 ++++ gtk+-2.21.2/configure.in 2010-06-22 17:28:59.000000000 +0800 +@@ -425,7 +425,7 @@ + case $enable_explicit_deps in + auto) + export SED +- deplibs_check_method=`(./libtool --config; echo 'eval echo \"$deplibs_check_method\"') | sh` ++ deplibs_check_method=`(./$host_alias-libtool --config; echo 'eval echo \"$deplibs_check_method\"') | sh` + if test "x$deplibs_check_method" '!=' xpass_all || test "x$enable_static" = xyes ; then + enable_explicit_deps=yes + else +@@ -804,7 +804,7 @@ + dnl Now we check to see if our libtool supports shared lib deps + dnl (in a rather ugly way even) + if $dynworks; then +- pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} ./libtool --config" ++ pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} $host_alias-libtool --config" + pixbuf_deplibs_check=`$pixbuf_libtool_config | \ + grep '^[[a-z_]]*check[[a-z_]]*_method=[['\''"]]' | \ + sed 's/.*[['\''"]]\(.*\)[['\''"]]$/\1/'` +@@ -1974,7 +1974,7 @@ + # We are using gmodule-no-export now, but I'm leaving the stripping + # code in place for now, since pango and atk still require gmodule. + export SED +-export_dynamic=`(./libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh` ++export_dynamic=`($host_alias-libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh` + if test -n "$export_dynamic"; then + GDK_PIXBUF_DEP_LIBS=`echo $GDK_PIXBUF_DEP_LIBS | sed -e "s/$export_dynamic//"` + GDK_PIXBUF_XLIB_DEP_LIBS=`echo $GDK_PIXBUF_XLIB_DEP_LIBS | sed -e "s/$export_dynamic//"` diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/no-demos.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/no-demos.patch new file mode 100644 index 0000000000..0fc4c48d1a --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/no-demos.patch @@ -0,0 +1,10 @@ +--- gtk+-2.10.1/Makefile.am.orig 2006-08-08 12:37:30.000000000 +0100 ++++ gtk+-2.10.1/Makefile.am 2006-08-08 12:37:48.000000000 +0100 +@@ -1,6 +1,6 @@ + ## Makefile.am for GTK+ + +-SRC_SUBDIRS = gdk-pixbuf gdk gtk modules demos tests perf contrib ++SRC_SUBDIRS = gdk-pixbuf gdk gtk modules tests perf contrib + SUBDIRS = po po-properties $(SRC_SUBDIRS) docs m4macros + + # require automake 1.4 diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/run-iconcache.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/run-iconcache.patch new file mode 100644 index 0000000000..518875e6fd --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/run-iconcache.patch @@ -0,0 +1,21 @@ +Index: gtk+-2.21.2/gtk/Makefile.am +=================================================================== +--- gtk+-2.21.2.orig/gtk/Makefile.am 2010-06-22 17:21:41.000000000 +0800 ++++ gtk+-2.21.2/gtk/Makefile.am 2010-06-22 17:28:12.000000000 +0800 +@@ -1376,11 +1376,11 @@ + ./gtk-update-icon-cache + endif + +-gtkbuiltincache.h: @REBUILD@ stamp-icons +- $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT) $(GTK_UPDATE_ICON_CACHE_MANIFEST) +- $(gtk_update_icon_cache_program) --force --ignore-theme-index \ +- --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \ +- mv gtkbuiltincache.h.tmp gtkbuiltincache.h ++#gtkbuiltincache.h: @REBUILD@ stamp-icons ++# $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT) $(GTK_UPDATE_ICON_CACHE_MANIFEST) ++# $(gtk_update_icon_cache_program) --force --ignore-theme-index \ ++# --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \ ++# mv gtkbuiltincache.h.tmp gtkbuiltincache.h + + EXTRA_DIST += \ + $(STOCK_ICONS) \ diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/toggle-font.diff b/meta/recipes-gnome/gtk+/gtk+-2.20.1/toggle-font.diff new file mode 100644 index 0000000000..4853628c82 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/toggle-font.diff @@ -0,0 +1,100 @@ +Index: gtk/gtkcellrenderertoggle.c +=================================================================== +--- gtk/gtkcellrenderertoggle.c.orig 2010-06-22 18:11:33.000000000 +0800 ++++ gtk/gtkcellrenderertoggle.c 2010-06-22 18:11:43.000000000 +0800 +@@ -71,6 +71,8 @@ + PROP_INDICATOR_SIZE + }; + ++/* This is a hard-coded default which promptly gets overridden by a size ++ calculated from the font size. */ + #define TOGGLE_WIDTH 13 + + static guint toggle_cell_signals[LAST_SIGNAL] = { 0 }; +@@ -80,8 +82,9 @@ + typedef struct _GtkCellRendererTogglePrivate GtkCellRendererTogglePrivate; + struct _GtkCellRendererTogglePrivate + { +- gint indicator_size; +- ++ gint indicator_size; /* This is the real size */ ++ gint override_size; /* This is the size set from the indicator-size property */ ++ GtkWidget *cached_widget; + guint inconsistent : 1; + }; + +@@ -104,6 +107,7 @@ + GTK_CELL_RENDERER (celltoggle)->ypad = 2; + + priv->indicator_size = TOGGLE_WIDTH; ++ priv->override_size = 0; + priv->inconsistent = FALSE; + } + +@@ -210,7 +214,7 @@ + g_value_set_boolean (value, celltoggle->radio); + break; + case PROP_INDICATOR_SIZE: +- g_value_set_int (value, priv->indicator_size); ++ g_value_set_int (value, priv->override_size ? priv->override_size : priv->indicator_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +@@ -245,7 +249,7 @@ + celltoggle->radio = g_value_get_boolean (value); + break; + case PROP_INDICATOR_SIZE: +- priv->indicator_size = g_value_get_int (value); ++ priv->override_size = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); +@@ -273,6 +277,27 @@ + } + + static void ++on_widget_style_set (GtkWidget *widget, GtkStyle *previous, gpointer user_data) ++{ ++ GtkCellRendererTogglePrivate *priv = user_data; ++ PangoContext *context; ++ PangoFontMetrics *metrics; ++ int height; ++ ++ context = gtk_widget_get_pango_context (widget); ++ metrics = pango_context_get_metrics (context, ++ widget->style->font_desc, ++ pango_context_get_language (context)); ++ ++ height = pango_font_metrics_get_ascent (metrics) + ++ pango_font_metrics_get_descent (metrics); ++ ++ pango_font_metrics_unref (metrics); ++ ++ priv->indicator_size = PANGO_PIXELS (height * 0.85); ++} ++ ++static void + gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *cell_area, +@@ -287,6 +312,20 @@ + + priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (cell); + ++ if (priv->override_size) { ++ priv->indicator_size = priv->override_size; ++ } else if (priv->cached_widget != widget) { ++ if (priv->cached_widget) { ++ g_object_remove_weak_pointer (widget, &priv->cached_widget); ++ g_signal_handlers_disconnect_by_func (priv->cached_widget, on_widget_style_set, priv); ++ } ++ priv->cached_widget = widget; ++ g_object_add_weak_pointer (widget, &priv->cached_widget); ++ g_signal_connect (widget, "style-set", on_widget_style_set, priv); ++ ++ on_widget_style_set (widget, NULL, priv); ++ } ++ + calc_width = (gint) cell->xpad * 2 + priv->indicator_size; + calc_height = (gint) cell->ypad * 2 + priv->indicator_size; + diff --git a/meta/recipes-gnome/gtk+/gtk+-2.20.1/xsettings.patch b/meta/recipes-gnome/gtk+/gtk+-2.20.1/xsettings.patch new file mode 100644 index 0000000000..84231e9b91 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+-2.20.1/xsettings.patch @@ -0,0 +1,18 @@ +Index: gtk+-2.21.2/gdk/x11/gdkevents-x11.c +=================================================================== +--- gtk+-2.21.2.orig/gdk/x11/gdkevents-x11.c 2010-06-22 17:28:04.000000000 +0800 ++++ gtk+-2.21.2/gdk/x11/gdkevents-x11.c 2010-06-22 17:28:06.000000000 +0800 +@@ -3062,10 +3062,9 @@ + { + GdkScreenX11 *screen = data; + +- if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent)) +- return GDK_FILTER_REMOVE; +- else +- return GDK_FILTER_CONTINUE; ++ xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent); ++ ++ return GDK_FILTER_CONTINUE; + } + + static Bool diff --git a/meta/recipes-gnome/gtk+/gtk+.inc b/meta/recipes-gnome/gtk+/gtk+.inc new file mode 100644 index 0000000000..f7fa00d5c4 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+.inc @@ -0,0 +1,85 @@ +DESCRIPTION = "GTK+ is a multi-platform toolkit for creating graphical user interfaces. Offering a complete \ +set of widgets, GTK+ is suitable for projects ranging from small one-off projects to complete application suites." +HOMEPAGE = "http://www.gtk.org" +BUGTRACKER = "https://bugzilla.gnome.org/" + +LICENSE = "LGPLv2 & LGPLv2+ & LGPLv2.1+" + +SECTION = "libs" +PRIORITY = "optional" +DEPENDS = "glib-2.0 pango atk jpeg libpng libxext libxcursor gtk-doc-native libxrandr \ + libgcrypt libxdamage libxrender libxcomposite cairo" + +inherit autotools pkgconfig + +FILES_${PN} = "${bindir}/gdk-pixbuf-query-loaders \ + ${bindir}/gtk-update-icon-cache \ + ${bindir}/gtk-query-immodules-2.0 \ + ${libdir}/lib*${SOLIBS} \ + ${datadir}/themes ${sysconfdir} \ + ${libdir}/gtk-2.0/${LIBV}/engines/libpixmap.so" + +FILES_${PN}-dev += " \ + ${datadir}/gtk-2.0/include \ + ${libdir}/gtk-2.0/include \ + ${libdir}/gtk-2.0/${LIBV}/loaders/*.la \ + ${libdir}/gtk-2.0/${LIBV}/immodules/*.la \ + ${libdir}/gtk-2.0/${LIBV}/engines/*.la \ + ${bindir}/gdk-pixbuf-csource \ + ${bindir}/gtk-builder-convert" + +FILES_${PN}-dbg += " \ + ${libdir}/gtk-2.0/${LIBV}/loaders/.debug/* \ + ${libdir}/gtk-2.0/${LIBV}/immodules/.debug/* \ + ${libdir}/gtk-2.0/${LIBV}/engines/.debug/* \ + ${libdir}/gtk-2.0/${LIBV}/printbackends/.debug/*" + +BASE_RRECOMMENDS = "ttf-dejavu-sans" +BASE_RRECOMMENDS_angstrom = "ttf-dejavu-sans gdk-pixbuf-loader-png gdk-pixbuf-loader-jpeg gdk-pixbuf-loader-gif gdk-pixbuf-loader-xpm" +BASE_RRECOMMENDS_poky = "gdk-pixbuf-loader-png gdk-pixbuf-loader-jpeg gdk-pixbuf-loader-gif gdk-pixbuf-loader-xpm shared-mime-info" +BASE_RRECOMMENDS_moblin = "gdk-pixbuf-loader-png gdk-pixbuf-loader-jpeg gdk-pixbuf-loader-gif gdk-pixbuf-loader-xpm shared-mime-info" + +GLIBC_RRECOMMENDS= "${BASE_RRECOMMENDS} glibc-gconv-iso8859-1" + +RRECOMMENDS_${PN} = "${BASE_RRECOMMENDS}" +RRECOMMENDS_${PN}_linux = "${GLIBC_RRECOMMENDS}" +RRECOMMENDS_${PN}_linux-gnueabi = "${GLIBC_RRECOMMENDS}" + +do_install () { + autotools_do_install + + install -d ${D}${sysconfdir}/gtk-2.0 + + mkdir -p ${D}${libdir}/gtk-2.0/include + install -m 0644 gdk/gdkconfig.h ${D}${libdir}/gtk-2.0/include/gdkconfig.h + + install -m 0644 gtk/gtkfilechooserprivate.h ${D}${includedir}/gtk-2.0/gtk/ + install -m 0644 gtk/gtkfilechooserutils.h ${D}${includedir}/gtk-2.0/gtk/ + install -m 0644 gtk/gtkfilesystemmodel.h ${D}${includedir}/gtk-2.0/gtk/ +} + +SYSROOT_PREPROCESS_FUNCS += "gtk_sysroot_preprocess" + +gtk_sysroot_preprocess () { + if [ -e ${D}${bindir}/gtk-builder-convert ]; then + install -d ${SYSROOT_DESTDIR}${STAGING_BINDIR_CROSS}/ + install -m 755 ${D}${bindir}/gtk-builder-convert ${SYSROOT_DESTDIR}${STAGING_BINDIR_CROSS}/ + fi +} + +postinst_prologue() { +if [ "x$D" != "x" ]; then + exit 1 +fi + +} + +postinst_pixbufloader() { +if [ "x$D" != "x" ]; then + exit 1 +fi + +gdk-pixbuf-query-loaders > ${sysconfdir}/gtk-2.0/gdk-pixbuf.loaders + +test -x ${bindir}/gtk-update-icon-cache && gtk-update-icon-cache -q ${datadir}/icons/hicolor +} diff --git a/meta/recipes-gnome/gtk+/gtk+_2.12.7.bb b/meta/recipes-gnome/gtk+/gtk+_2.12.7.bb new file mode 100644 index 0000000000..d829308513 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+_2.12.7.bb @@ -0,0 +1,50 @@ +require gtk+.inc + +PR = "r9" + +SRC_URI = "http://download.gnome.org/sources/gtk+/2.12/gtk+-${PV}.tar.bz2 \ + file://xsettings.patch;patch=1 \ + file://run-iconcache.patch;patch=1 \ + file://disable-print.patch;patch=1 \ + file://hardcoded_libtool.patch;patch=1 \ + file://no-demos.patch;patch=1 \ + file://cellrenderer-cairo.patch;patch=1;pnum=0 \ + file://entry-cairo.patch;patch=1;pnum=0 \ + file://toggle-font.diff;patch=1;pnum=0 \ + file://scrolled-placement.patch;patch=1;pnum=0 \ + file://filesystem-volumes.patch;patch=1 \ + file://filechooser-props.patch;patch=1 \ + file://filechooser-default.patch;patch=1 \ + file://filechooser-sizefix.patch;patch=1 \ +# temporary +# file://gtklabel-resize-patch;patch=1 \ +# file://menu-deactivate.patch;patch=1 \ +# file://combo-arrow-size.patch;patch=1;pnum=0 \ +# die die die +# file://pangoxft2.10.6.diff;patch=1 \ + " + +EXTRA_OECONF = "--without-libtiff --disable-xkb --disable-glibtest --enable-display-migration" + +LIBV = "2.10.0" + +PACKAGES_DYNAMIC += "gdk-pixbuf-loader-* gtk-immodule-* gtk-printbackend-*" + +python populate_packages_prepend () { + import os.path + + prologue = bb.data.getVar("postinst_prologue", d, 1) + postinst_pixbufloader = bb.data.getVar("postinst_pixbufloader", d, 1) + + gtk_libdir = bb.data.expand('${libdir}/gtk-2.0/${LIBV}', d) + loaders_root = os.path.join(gtk_libdir, 'loaders') + immodules_root = os.path.join(gtk_libdir, 'immodules') + printmodules_root = os.path.join(gtk_libdir, 'printbackends'); + + do_split_packages(d, loaders_root, '^libpixbufloader-(.*)\.so$', 'gdk-pixbuf-loader-%s', 'GDK pixbuf loader for %s', postinst_pixbufloader) + do_split_packages(d, immodules_root, '^im-(.*)\.so$', 'gtk-immodule-%s', 'GTK input module for %s', prologue + 'gtk-query-immodules-2.0 > /etc/gtk-2.0/gtk.immodules') + do_split_packages(d, printmodules_root, '^libprintbackend-(.*)\.so$', 'gtk-printbackend-%s', 'GTK printbackend module for %s') + + if (bb.data.getVar('DEBIAN_NAMES', d, 1)): + bb.data.setVar('PKG_${PN}', 'libgtk-2.0', d) +} diff --git a/meta/recipes-gnome/gtk+/gtk+_2.16.6.bb b/meta/recipes-gnome/gtk+/gtk+_2.16.6.bb new file mode 100644 index 0000000000..becd2bc29c --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+_2.16.6.bb @@ -0,0 +1,49 @@ +require gtk+.inc + +PR = "r5" + +SRC_URI = "http://download.gnome.org/sources/gtk+/2.16/gtk+-${PV}.tar.bz2 \ + file://xsettings.patch;patch=1 \ + file://run-iconcache.patch;patch=1 \ + file://hardcoded_libtool.patch;patch=1 \ + file://no-demos.patch;patch=1 \ + file://cellrenderer-cairo.patch;patch=1;pnum=0 \ + file://toggle-font.diff;patch=1;pnum=0 \ + file://0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch;patch=1 \ +# TO MERGE +# file://entry-cairo.patch;patch=1;pnum=0 \ +# file://filesystem-volumes.patch;patch=1 \ +# file://filechooser-props.patch;patch=1 \ +# file://filechooser-default.patch;patch=1 \ +# file://filechooser-sizefix.patch;patch=1 \ +# temporary +# file://gtklabel-resize-patch;patch=1 \ +# file://menu-deactivate.patch;patch=1 \ +# file://combo-arrow-size.patch;patch=1;pnum=0 \ + file://disable-gio-png-sniff-test.diff;patch=1 \ + " + +EXTRA_OECONF = "--without-libtiff --without-libjasper --disable-xkb --disable-glibtest --disable-cups" + +LIBV = "2.10.0" + +PACKAGES_DYNAMIC += "gdk-pixbuf-loader-* gtk-immodule-* gtk-printbackend-*" + +python populate_packages_prepend () { + import os.path + + prologue = bb.data.getVar("postinst_prologue", d, 1) + postinst_pixbufloader = bb.data.getVar("postinst_pixbufloader", d, 1) + + gtk_libdir = bb.data.expand('${libdir}/gtk-2.0/${LIBV}', d) + loaders_root = os.path.join(gtk_libdir, 'loaders') + immodules_root = os.path.join(gtk_libdir, 'immodules') + printmodules_root = os.path.join(gtk_libdir, 'printbackends'); + + do_split_packages(d, loaders_root, '^libpixbufloader-(.*)\.so$', 'gdk-pixbuf-loader-%s', 'GDK pixbuf loader for %s', postinst_pixbufloader) + do_split_packages(d, immodules_root, '^im-(.*)\.so$', 'gtk-immodule-%s', 'GTK input module for %s', prologue + 'gtk-query-immodules-2.0 > /etc/gtk-2.0/gtk.immodules') + do_split_packages(d, printmodules_root, '^libprintbackend-(.*)\.so$', 'gtk-printbackend-%s', 'GTK printbackend module for %s') + + if (bb.data.getVar('DEBIAN_NAMES', d, 1)): + bb.data.setVar('PKG_${PN}', 'libgtk-2.0', d) +} diff --git a/meta/recipes-gnome/gtk+/gtk+_2.20.1.bb b/meta/recipes-gnome/gtk+/gtk+_2.20.1.bb new file mode 100644 index 0000000000..00de6950a3 --- /dev/null +++ b/meta/recipes-gnome/gtk+/gtk+_2.20.1.bb @@ -0,0 +1,54 @@ +require gtk+.inc + +LIC_FILES_CHKSUM = "file://COPYING;md5=3bf50002aefd002f49e7bb854063f7e7 \ + file://gtk/gtk.h;endline=27;md5=c59e0b4490dd135a5726ebf851f9b17f \ + file://gdk/gdk.h;endline=27;md5=07db285ec208fb3e0bf7d861b0614202 \ + file://tests/testgtk.c;endline=27;md5=262db5db5f776f9863e56df31423e24c" +PR = "r0" + +SRC_URI = "http://download.gnome.org/sources/gtk+/2.20/gtk+-${PV}.tar.bz2 \ + file://xsettings.patch;patch=1 \ + file://run-iconcache.patch;patch=1 \ + file://hardcoded_libtool.patch;patch=1 \ + file://no-demos.patch;patch=1 \ + file://cellrenderer-cairo.patch;patch=1;pnum=0 \ + file://toggle-font.diff;patch=1;pnum=0 \ + file://0001-bgo-584832-Duplicate-the-exec-string-returned-by-gtk.patch;patch=1 \ +# TO MERGE +# file://entry-cairo.patch;patch=1;pnum=0 \ +# file://filesystem-volumes.patch;patch=1 \ +# file://filechooser-props.patch;patch=1 \ +# file://filechooser-default.patch;patch=1 \ +# file://filechooser-sizefix.patch;patch=1 \ +# temporary +# file://gtklabel-resize-patch;patch=1 \ +# file://menu-deactivate.patch;patch=1 \ +# file://combo-arrow-size.patch;patch=1;pnum=0 \ + file://disable-gio-png-sniff-test.diff;patch=1 \ + file://configurefix.patch;patch=1 \ + " + +EXTRA_OECONF = "--without-libtiff --without-libjasper --disable-xkb --disable-glibtest --disable-cups" + +LIBV = "2.10.0" + +PACKAGES_DYNAMIC += "gdk-pixbuf-loader-* gtk-immodule-* gtk-printbackend-*" + +python populate_packages_prepend () { + import os.path + + prologue = bb.data.getVar("postinst_prologue", d, 1) + postinst_pixbufloader = bb.data.getVar("postinst_pixbufloader", d, 1) + + gtk_libdir = bb.data.expand('${libdir}/gtk-2.0/${LIBV}', d) + loaders_root = os.path.join(gtk_libdir, 'loaders') + immodules_root = os.path.join(gtk_libdir, 'immodules') + printmodules_root = os.path.join(gtk_libdir, 'printbackends'); + + do_split_packages(d, loaders_root, '^libpixbufloader-(.*)\.so$', 'gdk-pixbuf-loader-%s', 'GDK pixbuf loader for %s', postinst_pixbufloader) + do_split_packages(d, immodules_root, '^im-(.*)\.so$', 'gtk-immodule-%s', 'GTK input module for %s', prologue + 'gtk-query-immodules-2.0 > /etc/gtk-2.0/gtk.immodules') + do_split_packages(d, printmodules_root, '^libprintbackend-(.*)\.so$', 'gtk-printbackend-%s', 'GTK printbackend module for %s') + + if (bb.data.getVar('DEBIAN_NAMES', d, 1)): + bb.data.setVar('PKG_${PN}', 'libgtk-2.0', d) +} |