X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/e1e18511e3a9c914db7a7a6fbae5737f7cf96553..c5101a77a4066d979698d356c3a9c7f387007359:/src/gtkutil.c
diff --git a/src/gtkutil.c b/src/gtkutil.c
index dbd48eb527..4e5ecce76c 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1,6 +1,6 @@
/* Functions for creating and updating GTK widgets.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+
+Copyright (C) 2003-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see . */
#include
#ifdef USE_GTK
-#include
#include
#include
#include
@@ -41,15 +40,16 @@ along with GNU Emacs. If not, see . */
#include
#endif
+#ifdef HAVE_GTK3
+#include
+#endif
+
#define FRAME_TOTAL_PIXEL_HEIGHT(f) \
(FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
#define FRAME_TOTAL_PIXEL_WIDTH(f) \
(FRAME_PIXEL_WIDTH (f) + FRAME_TOOLBAR_WIDTH (f))
-/* Avoid "differ in sign" warnings */
-#define SSDATA(x) ((char *) SDATA (x))
-
#ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
#define gtk_widget_set_has_window(w, b) \
(gtk_fixed_set_has_window (GTK_FIXED (w), b))
@@ -73,6 +73,26 @@ along with GNU Emacs. If not, see . */
#define remove_submenu(w) gtk_menu_item_remove_submenu ((w))
#endif
+#ifndef HAVE_GTK3
+#ifdef USE_GTK_TOOLTIP
+#define gdk_window_get_screen(w) gdk_drawable_get_screen (w)
+#endif
+#define gdk_window_get_geometry(w, a, b, c, d) \
+ gdk_window_get_geometry (w, a, b, c, d, 0)
+#define gdk_x11_window_lookup_for_display(d, w) \
+ gdk_xid_table_lookup_for_display (d, w)
+#define GDK_KEY_g GDK_g
+#endif
+
+#define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x))
+
+/* Get the current value of the range, truncated to an integer. */
+static int
+int_gtk_range_get_value (GtkRange *range)
+{
+ return gtk_range_get_value (range);
+}
+
/***********************************************************************
Display handling functions
@@ -90,7 +110,7 @@ static GdkDisplay *gdpy_def;
static void
xg_set_screen (GtkWidget *w, FRAME_PTR f)
{
- if (FRAME_X_DISPLAY (f) != GDK_DISPLAY ())
+ if (FRAME_X_DISPLAY (f) != DEFAULT_GDK_DISPLAY ())
{
GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
GdkScreen *gscreen = gdk_display_get_default_screen (gdpy);
@@ -231,29 +251,55 @@ xg_create_default_cursor (Display *dpy)
return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR);
}
+static GdkPixbuf *
+xg_get_pixbuf_from_pixmap (FRAME_PTR f, Pixmap pix)
+{
+ int iunused;
+ GdkPixbuf *tmp_buf;
+ Window wunused;
+ unsigned int width, height, uunused;
+ XImage *xim;
+
+ XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused,
+ &width, &height, &uunused, &uunused);
+
+ xim = XGetImage (FRAME_X_DISPLAY (f), pix, 0, 0, width, height,
+ ~0, XYPixmap);
+ if (!xim) return 0;
+
+ tmp_buf = gdk_pixbuf_new_from_data ((guchar *) xim->data,
+ GDK_COLORSPACE_RGB,
+ FALSE,
+ xim->bitmap_unit,
+ (int) width,
+ (int) height,
+ xim->bytes_per_line,
+ NULL,
+ NULL);
+ XDestroyImage (xim);
+ return tmp_buf;
+}
+
/* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */
static GdkPixbuf *
-xg_get_pixbuf_from_pix_and_mask (GdkPixmap *gpix,
- GdkPixmap *gmask,
- GdkColormap *cmap)
+xg_get_pixbuf_from_pix_and_mask (FRAME_PTR f,
+ Pixmap pix,
+ Pixmap mask)
{
int width, height;
GdkPixbuf *icon_buf, *tmp_buf;
- gdk_drawable_get_size (gpix, &width, &height);
- tmp_buf = gdk_pixbuf_get_from_drawable (NULL, gpix, cmap,
- 0, 0, 0, 0, width, height);
+ tmp_buf = xg_get_pixbuf_from_pixmap (f, pix);
icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0);
g_object_unref (G_OBJECT (tmp_buf));
- if (gmask)
+ width = gdk_pixbuf_get_width (icon_buf);
+ height = gdk_pixbuf_get_height (icon_buf);
+
+ if (mask)
{
- GdkPixbuf *mask_buf = gdk_pixbuf_get_from_drawable (NULL,
- gmask,
- NULL,
- 0, 0, 0, 0,
- width, height);
+ GdkPixbuf *mask_buf = xg_get_pixbuf_from_pixmap (f, mask);
guchar *pixels = gdk_pixbuf_get_pixels (icon_buf);
guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf);
int rowstride = gdk_pixbuf_get_rowstride (icon_buf);
@@ -318,10 +364,6 @@ xg_get_image_for_pixmap (FRAME_PTR f,
GtkWidget *widget,
GtkImage *old_widget)
{
- GdkPixmap *gpix;
- GdkPixmap *gmask;
- GdkDisplay *gdpy;
- GdkColormap *cmap;
GdkPixbuf *icon_buf;
/* If we have a file, let GTK do all the image handling.
@@ -349,10 +391,6 @@ xg_get_image_for_pixmap (FRAME_PTR f,
on a monochrome display, and sometimes bad on all displays with
certain themes. */
- gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
- gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap);
- gmask = img->mask ? gdk_pixmap_foreign_new_for_display (gdpy, img->mask) : 0;
-
/* This is a workaround to make icons look good on pseudo color
displays. Apparently GTK expects the images to have an alpha
channel. If they don't, insensitive and activated icons will
@@ -362,18 +400,17 @@ xg_get_image_for_pixmap (FRAME_PTR f,
not associated with the img->pixmap. The img->pixmap may be removed
by clearing the image cache and then the tool bar redraw fails, since
Gtk+ assumes the pixmap is always there. */
- cmap = gtk_widget_get_colormap (widget);
- icon_buf = xg_get_pixbuf_from_pix_and_mask (gpix, gmask, cmap);
-
- if (! old_widget)
- old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf));
- else
- gtk_image_set_from_pixbuf (old_widget, icon_buf);
+ icon_buf = xg_get_pixbuf_from_pix_and_mask (f, img->pixmap, img->mask);
- g_object_unref (G_OBJECT (icon_buf));
+ if (icon_buf)
+ {
+ if (! old_widget)
+ old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf));
+ else
+ gtk_image_set_from_pixbuf (old_widget, icon_buf);
- g_object_unref (G_OBJECT (gpix));
- if (gmask) g_object_unref (G_OBJECT (gmask));
+ g_object_unref (G_OBJECT (icon_buf));
+ }
return GTK_WIDGET (old_widget);
}
@@ -457,22 +494,22 @@ get_utf8_string (const char *str)
gsize bytes_written;
unsigned char *p = (unsigned char *)str;
char *cp, *up;
- GError *error = NULL;
+ GError *err = NULL;
while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
- &bytes_written, &error))
- && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
+ &bytes_written, &err))
+ && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
{
++nr_bad;
p += bytes_written+1;
- g_error_free (error);
- error = NULL;
+ g_error_free (err);
+ err = NULL;
}
- if (error)
+ if (err)
{
- g_error_free (error);
- error = NULL;
+ g_error_free (err);
+ err = NULL;
}
if (cp) g_free (cp);
@@ -480,16 +517,16 @@ get_utf8_string (const char *str)
p = (unsigned char *)str;
while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
- &bytes_written, &error))
- && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
+ &bytes_written, &err))
+ && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
{
strncpy (up, (char *)p, bytes_written);
sprintf (up + bytes_written, "\\%03o", p[bytes_written]);
up[bytes_written+4] = '\0';
up += bytes_written+4;
p += bytes_written+1;
- g_error_free (error);
- error = NULL;
+ g_error_free (err);
+ err = NULL;
}
if (cp)
@@ -497,10 +534,10 @@ get_utf8_string (const char *str)
strcat (utf8_str, cp);
g_free (cp);
}
- if (error)
+ if (err)
{
- g_error_free (error);
- error = NULL;
+ g_error_free (err);
+ err = NULL;
}
}
return utf8_str;
@@ -516,28 +553,43 @@ xg_check_special_colors (struct frame *f,
XColor *color)
{
int success_p = 0;
- if (FRAME_GTK_WIDGET (f))
- {
- if (strcmp ("gtk_selection_bg_color", color_name) == 0)
- {
- GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
- color->red = gsty->bg[GTK_STATE_SELECTED].red;
- color->green = gsty->bg[GTK_STATE_SELECTED].green;
- color->blue = gsty->bg[GTK_STATE_SELECTED].blue;
- color->pixel = gsty->bg[GTK_STATE_SELECTED].pixel;
- success_p = 1;
- }
- else if (strcmp ("gtk_selection_fg_color", color_name) == 0)
- {
- GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
- color->red = gsty->fg[GTK_STATE_SELECTED].red;
- color->green = gsty->fg[GTK_STATE_SELECTED].green;
- color->blue = gsty->fg[GTK_STATE_SELECTED].blue;
- color->pixel = gsty->fg[GTK_STATE_SELECTED].pixel;
- success_p = 1;
- }
- }
+ int get_bg = strcmp ("gtk_selection_bg_color", color_name) == 0;
+ int get_fg = !get_bg && strcmp ("gtk_selection_fg_color", color_name) == 0;
+ if (! FRAME_GTK_WIDGET (f) || ! (get_bg || get_fg))
+ return success_p;
+
+ BLOCK_INPUT;
+ {
+#ifdef HAVE_GTK3
+ GtkStyleContext *gsty
+ = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
+ GdkRGBA col;
+ char buf[64];
+ int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED;
+ if (get_fg)
+ gtk_style_context_get_color (gsty, state, &col);
+ else
+ gtk_style_context_get_background_color (gsty, state, &col);
+
+ sprintf (buf, "rgbi:%lf/%lf/%lf", col.red, col.green, col.blue);
+ success_p = XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ buf, color);
+#else
+ GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
+ GdkColor *grgb = get_bg
+ ? &gsty->bg[GTK_STATE_SELECTED]
+ : &gsty->fg[GTK_STATE_SELECTED];
+
+ color->red = grgb->red;
+ color->green = grgb->green;
+ color->blue = grgb->blue;
+ color->pixel = grgb->pixel;
+ success_p = 1;
+#endif
+
+ }
+ UNBLOCK_INPUT;
return success_p;
}
@@ -560,7 +612,7 @@ hierarchy_ch_cb (GtkWidget *widget,
FRAME_PTR f = (FRAME_PTR) user_data;
struct x_output *x = f->output_data.x;
GtkWidget *top = gtk_widget_get_toplevel (x->ttip_lbl);
-
+
if (! top || ! GTK_IS_WINDOW (top))
gtk_widget_hide (previous_toplevel);
}
@@ -581,7 +633,7 @@ qttip_cb (GtkWidget *widget,
{
FRAME_PTR f = (FRAME_PTR) user_data;
struct x_output *x = f->output_data.x;
- if (x->ttip_widget == NULL)
+ if (x->ttip_widget == NULL)
{
g_object_set (G_OBJECT (widget), "has-tooltip", FALSE, NULL);
x->ttip_widget = tooltip;
@@ -590,6 +642,8 @@ qttip_cb (GtkWidget *widget,
g_object_ref (G_OBJECT (x->ttip_lbl));
gtk_tooltip_set_custom (tooltip, x->ttip_lbl);
x->ttip_window = GTK_WINDOW (gtk_widget_get_toplevel (x->ttip_lbl));
+ /* ATK needs an empty title for some reason. */
+ gtk_window_set_title (x->ttip_window, "");
/* Realize so we can safely get screen later on. */
gtk_widget_realize (GTK_WIDGET (x->ttip_window));
gtk_widget_realize (x->ttip_lbl);
@@ -629,17 +683,17 @@ xg_prepare_tooltip (FRAME_PTR f,
encoded_string = ENCODE_UTF_8 (string);
widget = GTK_WIDGET (x->ttip_lbl);
gwin = gtk_widget_get_window (GTK_WIDGET (x->ttip_window));
- screen = gdk_drawable_get_screen (gwin);
+ screen = gdk_window_get_screen (gwin);
settings = gtk_settings_get_for_screen (screen);
g_object_get (settings, "gtk-enable-tooltips", &tt_enabled, NULL);
- if (tt_enabled)
+ if (tt_enabled)
{
g_object_set (settings, "gtk-enable-tooltips", FALSE, NULL);
/* Record that we disabled it so it can be enabled again. */
g_object_set_data (G_OBJECT (x->ttip_window), "restore-tt",
(gpointer)f);
}
-
+
/* Prevent Gtk+ from hiding tooltip on mouse move and such. */
g_object_set_data (G_OBJECT
(gtk_widget_get_display (GTK_WIDGET (x->ttip_window))),
@@ -650,10 +704,10 @@ xg_prepare_tooltip (FRAME_PTR f,
gtk_tooltip_set_custom (x->ttip_widget, widget);
gtk_tooltip_set_text (x->ttip_widget, SDATA (encoded_string));
- gtk_widget_size_request (GTK_WIDGET (x->ttip_window), &req);
+ gtk_widget_get_preferred_size (GTK_WIDGET (x->ttip_window), NULL, &req);
if (width) *width = req.width;
if (height) *height = req.height;
-
+
UNBLOCK_INPUT;
return 1;
@@ -696,7 +750,7 @@ xg_hide_tooltip (FRAME_PTR f)
if (g_object_get_data (G_OBJECT (win), "restore-tt"))
{
GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win));
- GdkScreen *screen = gdk_drawable_get_screen (gwin);
+ GdkScreen *screen = gdk_window_get_screen (gwin);
GtkSettings *settings = gtk_settings_get_for_screen (screen);
g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
}
@@ -797,10 +851,10 @@ xg_frame_resized (FRAME_PTR f, int pixelwidth, int pixelheight)
if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f)))
gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
0, 0,
- &pixelwidth, &pixelheight, 0);
+ &pixelwidth, &pixelheight);
else return;
}
-
+
rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
@@ -910,8 +964,8 @@ xg_win_to_widget (Display *dpy, Window wdesc)
BLOCK_INPUT;
- gdkwin = gdk_xid_table_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
- wdesc);
+ gdkwin = gdk_x11_window_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
+ wdesc);
if (gdkwin)
{
GdkEvent event;
@@ -923,14 +977,29 @@ xg_win_to_widget (Display *dpy, Window wdesc)
return gwdesc;
}
-/* Fill in the GdkColor C so that it represents PIXEL.
- W is the widget that color will be used for. Used to find colormap. */
+/* Set the background of widget W to PIXEL. */
static void
-xg_pix_to_gcolor (GtkWidget *w, long unsigned int pixel, GdkColor *c)
+xg_set_widget_bg (FRAME_PTR f, GtkWidget *w, long unsigned int pixel)
{
+#ifdef HAVE_GTK3
+ GdkRGBA bg;
+ XColor xbg;
+ xbg.pixel = pixel;
+ if (XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &xbg))
+ {
+ bg.red = (double)xbg.red/65536.0;
+ bg.green = (double)xbg.green/65536.0;
+ bg.blue = (double)xbg.blue/65536.0;
+ bg.alpha = 1.0;
+ gtk_widget_override_background_color (w, GTK_STATE_FLAG_NORMAL, &bg);
+ }
+#else
+ GdkColor bg;
GdkColormap *map = gtk_widget_get_colormap (w);
- gdk_colormap_query_color (map, pixel, c);
+ gdk_colormap_query_color (map, pixel, &bg);
+ gtk_widget_modify_bg (FRAME_GTK_WIDGET (f), GTK_STATE_NORMAL, &bg);
+#endif
}
/* Callback called when the gtk theme changes.
@@ -953,6 +1022,28 @@ style_changed_cb (GObject *go,
kbd_buffer_store_event (&event);
}
+/* Called when a delete-event occurs on WIDGET. */
+
+static gboolean
+delete_cb (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+#ifdef HAVE_GTK3
+ /* The event doesn't arrive in the normal event loop. Send event
+ here. */
+ FRAME_PTR f = (FRAME_PTR) user_data;
+ struct input_event ie;
+
+ EVENT_INIT (ie);
+ ie.kind = DELETE_WINDOW_EVENT;
+ XSETFRAME (ie.frame_or_window, f);
+ kbd_buffer_store_event (&ie);
+#endif
+
+ return TRUE;
+}
+
/* Create and set up the GTK widgets for frame F.
Return 0 if creation failed, non-zero otherwise. */
@@ -962,7 +1053,6 @@ xg_create_frame_widgets (FRAME_PTR f)
GtkWidget *wtop;
GtkWidget *wvbox, *whbox;
GtkWidget *wfixed;
- GdkColor bg;
GtkRcStyle *style;
char *title = 0;
@@ -1029,7 +1119,7 @@ xg_create_frame_widgets (FRAME_PTR f)
/* Add callback to do nothing on WM_DELETE_WINDOW. The default in
GTK is to destroy the widget. We want Emacs to do that instead. */
g_signal_connect (G_OBJECT (wtop), "delete-event",
- G_CALLBACK (gtk_true), 0);
+ G_CALLBACK (delete_cb), f);
/* Convert our geometry parameters into a geometry string
and specify it.
@@ -1057,9 +1147,9 @@ xg_create_frame_widgets (FRAME_PTR f)
/* Since GTK clears its window by filling with the background color,
we must keep X and GTK background in sync. */
- xg_pix_to_gcolor (wfixed, FRAME_BACKGROUND_PIXEL (f), &bg);
- gtk_widget_modify_bg (wfixed, GTK_STATE_NORMAL, &bg);
+ xg_set_widget_bg (f, wfixed, FRAME_BACKGROUND_PIXEL (f));
+#ifndef HAVE_GTK3
/* Also, do not let any background pixmap to be set, this looks very
bad as Emacs overwrites the background pixmap with its own idea
of background color. */
@@ -1068,13 +1158,16 @@ xg_create_frame_widgets (FRAME_PTR f)
/* Must use g_strdup because gtk_widget_modify_style does g_free. */
style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("");
gtk_widget_modify_style (wfixed, style);
+#else
+ gtk_widget_set_can_focus (wfixed, TRUE);
+#endif
#ifdef USE_GTK_TOOLTIP
/* Steal a tool tip window we can move ourselves. */
f->output_data.x->ttip_widget = 0;
f->output_data.x->ttip_lbl = 0;
f->output_data.x->ttip_window = 0;
- gtk_widget_set_tooltip_text (wtop, "Dummy text");
+ gtk_widget_set_tooltip_text (wtop, "Dummy text");
g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
#endif
@@ -1104,7 +1197,9 @@ xg_free_frame_widgets (FRAME_PTR f)
{
if (FRAME_GTK_OUTER_WIDGET (f))
{
+#ifdef USE_GTK_TOOLTIP
struct x_output *x = f->output_data.x;
+#endif
gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
FRAME_GTK_OUTER_WIDGET (f) = 0;
@@ -1224,11 +1319,8 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
{
if (FRAME_GTK_WIDGET (f))
{
- GdkColor gdk_bg;
-
BLOCK_INPUT;
- xg_pix_to_gcolor (FRAME_GTK_WIDGET (f), bg, &gdk_bg);
- gtk_widget_modify_bg (FRAME_GTK_WIDGET (f), GTK_STATE_NORMAL, &gdk_bg);
+ xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f));
UNBLOCK_INPUT;
}
}
@@ -1240,11 +1332,10 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
void
xg_set_frame_icon (FRAME_PTR f, Pixmap icon_pixmap, Pixmap icon_mask)
{
- GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
- GdkPixmap *gpix = gdk_pixmap_foreign_new_for_display (gdpy, icon_pixmap);
- GdkPixmap *gmask = gdk_pixmap_foreign_new_for_display (gdpy, icon_mask);
- GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (gpix, gmask, NULL);
-
+ GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (f,
+ icon_pixmap,
+ icon_mask);
+ if (gp)
gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), gp);
}
@@ -1326,8 +1417,6 @@ create_dialog (widget_value *wv,
GtkDialog *wd = GTK_DIALOG (wdialog);
GtkBox *cur_box = GTK_BOX (gtk_dialog_get_action_area (wd));
widget_value *item;
- GtkWidget *wvbox;
- GtkWidget *whbox_up;
GtkWidget *whbox_down;
/* If the number of buttons is greater than 4, make two rows of buttons
@@ -1343,8 +1432,8 @@ create_dialog (widget_value *wv,
if (make_two_rows)
{
- wvbox = gtk_vbox_new (TRUE, button_spacing);
- whbox_up = gtk_hbox_new (FALSE, 0);
+ GtkWidget *wvbox = gtk_vbox_new (TRUE, button_spacing);
+ GtkWidget *whbox_up = gtk_hbox_new (FALSE, 0);
whbox_down = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (cur_box, wvbox, FALSE, FALSE, 0);
@@ -1381,7 +1470,7 @@ create_dialog (widget_value *wv,
/* Try to make dialog look better. Must realize first so
the widget can calculate the size it needs. */
gtk_widget_realize (w);
- gtk_widget_size_request (w, &req);
+ gtk_widget_get_preferred_size (w, NULL, &req);
gtk_box_set_spacing (wvbox, req.height);
if (item->value && strlen (item->value) > 0)
button_spacing = 2*req.width/strlen (item->value);
@@ -1453,7 +1542,7 @@ pop_down_dialog (Lisp_Object arg)
g_main_loop_quit (dd->loop);
g_main_loop_unref (dd->loop);
-
+
UNBLOCK_INPUT;
return Qnil;
@@ -1466,7 +1555,7 @@ static gboolean
xg_maybe_add_timer (gpointer data)
{
struct xg_dialog_data *dd = (struct xg_dialog_data *) data;
- EMACS_TIME next_time = timer_check (1);
+ EMACS_TIME next_time = timer_check ();
long secs = EMACS_SECS (next_time);
long usecs = EMACS_USECS (next_time);
@@ -1481,7 +1570,7 @@ xg_maybe_add_timer (gpointer data)
return FALSE;
}
-
+
/* Pops up a modal dialog W and waits for response.
We don't use gtk_dialog_run because we want to process emacs timers.
The dialog W is not destroyed when this function returns. */
@@ -1515,7 +1604,7 @@ xg_dialog_run (FRAME_PTR f, GtkWidget *w)
(void) xg_maybe_add_timer (&dd);
g_main_loop_run (dd.loop);
-
+
dd.w = 0;
unbind_to (count, Qnil);
@@ -1533,7 +1622,6 @@ int
xg_uses_old_file_dialog (void)
{
#ifdef HAVE_GTK_FILE_SELECTION_NEW
- extern int x_gtk_use_old_file_dialog;
return x_gtk_use_old_file_dialog;
#else
return 0;
@@ -1574,8 +1662,6 @@ xg_toggle_visibility_cb (GtkWidget *widget, gpointer data)
static void
xg_toggle_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data)
{
- extern int x_gtk_show_hidden_files;
-
if (strcmp (arg1->name, "show-hidden") == 0)
{
GtkWidget *wtoggle = GTK_WIDGET (user_data);
@@ -1616,16 +1702,13 @@ xg_get_file_with_chooser (FRAME_PTR f,
int mustmatch_p, int only_dir_p,
xg_get_file_func *func)
{
- char message[1024];
+ char msgbuf[1024];
GtkWidget *filewin, *wtoggle, *wbox, *wmessage;
GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
GtkFileChooserAction action = (mustmatch_p ?
GTK_FILE_CHOOSER_ACTION_OPEN :
GTK_FILE_CHOOSER_ACTION_SAVE);
- extern int x_gtk_show_hidden_files;
- extern int x_gtk_file_dialog_help_text;
-
if (only_dir_p)
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
@@ -1655,16 +1738,16 @@ xg_get_file_with_chooser (FRAME_PTR f,
if (x_gtk_file_dialog_help_text)
{
- message[0] = '\0';
+ msgbuf[0] = '\0';
/* Gtk+ 2.10 has the file name text entry box integrated in the dialog.
Show the C-l help text only for versions < 2.10. */
if (gtk_check_version (2, 10, 0) && action != GTK_FILE_CHOOSER_ACTION_SAVE)
- strcat (message, "\nType C-l to display a file name text entry box.\n");
- strcat (message, "\nIf you don't like this file selector, use the "
+ strcat (msgbuf, "\nType C-l to display a file name text entry box.\n");
+ strcat (msgbuf, "\nIf you don't like this file selector, use the "
"corresponding\nkey binding or customize "
"use-file-dialog to turn it off.");
- wmessage = gtk_label_new (message);
+ wmessage = gtk_label_new (msgbuf);
gtk_widget_show (wmessage);
}
@@ -2127,54 +2210,6 @@ make_menu_item (const char *utf8_label,
return w;
}
-/* Return non-zero if LABEL specifies a separator (GTK only has one
- separator type) */
-
-static const char* separator_names[] = {
- "space",
- "no-line",
- "single-line",
- "double-line",
- "single-dashed-line",
- "double-dashed-line",
- "shadow-etched-in",
- "shadow-etched-out",
- "shadow-etched-in-dash",
- "shadow-etched-out-dash",
- "shadow-double-etched-in",
- "shadow-double-etched-out",
- "shadow-double-etched-in-dash",
- "shadow-double-etched-out-dash",
- 0,
-};
-
-static int
-xg_separator_p (const char *label)
-{
- if (! label) return 0;
- else if (strlen (label) > 3
- && strncmp (label, "--", 2) == 0
- && label[2] != '-')
- {
- int i;
-
- label += 2;
- for (i = 0; separator_names[i]; ++i)
- if (strcmp (label, separator_names[i]) == 0)
- return 1;
- }
- else
- {
- /* Old-style separator, maybe. It's a separator if it contains
- only dashes. */
- while (*label == '-')
- ++label;
- if (*label == 0) return 1;
- }
-
- return 0;
-}
-
static int xg_detached_menus;
/* Returns non-zero if there are detached menus. */
@@ -2373,7 +2408,7 @@ create_menus (widget_value *data,
GtkWidget *w;
if (pop_up_p && !item->contents && !item->call_data
- && !xg_separator_p (item->name))
+ && !menu_separator_name_p (item->name))
{
char *utf8_label;
/* A title for a popup. We do the same as GTK does when
@@ -2386,7 +2421,7 @@ create_menus (widget_value *data,
gtk_widget_set_sensitive (w, FALSE);
if (utf8_label) g_free (utf8_label);
}
- else if (xg_separator_p (item->name))
+ else if (menu_separator_name_p (item->name))
{
group = NULL;
/* GTK only have one separator type. */
@@ -2498,7 +2533,7 @@ xg_create_widget (const char *type, const char *name, FRAME_PTR f, widget_value
static const char *
xg_get_menu_item_label (GtkMenuItem *witem)
{
- GtkLabel *wlabel = GTK_LABEL (gtk_bin_get_child (GTK_BIN (witem)));
+ GtkLabel *wlabel = GTK_LABEL (XG_BIN_CHILD (witem));
return gtk_label_get_label (wlabel);
}
@@ -2651,7 +2686,7 @@ xg_update_menubar (GtkWidget *menubar,
Rename X to B (minibuf to C-mode menu).
If the X menu hasn't been invoked, the menu under B
is up to date when leaving the minibuffer. */
- GtkLabel *wlabel = GTK_LABEL (gtk_bin_get_child (GTK_BIN (witem)));
+ GtkLabel *wlabel = GTK_LABEL (XG_BIN_CHILD (witem));
char *utf8_label = get_utf8_string (val->name);
GtkWidget *submenu = gtk_menu_item_get_submenu (witem);
@@ -2750,7 +2785,7 @@ xg_update_menu_item (widget_value *val,
const char *old_key = 0;
xg_menu_item_cb_data *cb_data;
- wchild = gtk_bin_get_child (GTK_BIN (w));
+ wchild = XG_BIN_CHILD (w);
utf8_label = get_utf8_string (val->name);
utf8_key = get_utf8_string (val->key);
@@ -2909,7 +2944,7 @@ xg_update_submenu (GtkWidget *submenu,
if (GTK_IS_SEPARATOR_MENU_ITEM (w))
{
- if (! xg_separator_p (cur->name))
+ if (! menu_separator_name_p (cur->name))
break;
}
else if (GTK_IS_CHECK_MENU_ITEM (w))
@@ -2932,7 +2967,7 @@ xg_update_submenu (GtkWidget *submenu,
GtkWidget *sub;
if (cur->button_type != BUTTON_TYPE_NONE ||
- xg_separator_p (cur->name))
+ menu_separator_name_p (cur->name))
break;
xg_update_menu_item (cur, w, select_cb, highlight_cb, cl_data);
@@ -3073,6 +3108,23 @@ xg_modify_menubar_widgets (GtkWidget *menubar, FRAME_PTR f, widget_value *val,
gtk_widget_show_all (menubar);
}
+/* Callback called when the menu bar W is mapped.
+ Used to find the height of the menu bar if we didn't get it
+ after showing the widget. */
+
+static void
+menubar_map_cb (GtkWidget *w, gpointer user_data)
+{
+ GtkRequisition req;
+ FRAME_PTR f = (FRAME_PTR) user_data;
+ gtk_widget_get_preferred_size (w, NULL, &req);
+ if (FRAME_MENUBAR_HEIGHT (f) != req.height)
+ {
+ FRAME_MENUBAR_HEIGHT (f) = req.height;
+ xg_height_or_width_changed (f);
+ }
+}
+
/* Recompute all the widgets of frame F, when the menu bar has been
changed. Value is non-zero if widgets were updated. */
@@ -3094,10 +3146,20 @@ xg_update_frame_menubar (FRAME_PTR f)
FALSE, FALSE, 0);
gtk_box_reorder_child (GTK_BOX (x->vbox_widget), x->menubar_widget, 0);
+ g_signal_connect (x->menubar_widget, "map", G_CALLBACK (menubar_map_cb), f);
gtk_widget_show_all (x->menubar_widget);
- gtk_widget_size_request (x->menubar_widget, &req);
- FRAME_MENUBAR_HEIGHT (f) = req.height;
- xg_height_or_width_changed (f);
+ gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req);
+
+ /* If menu bar doesn't know its height yet, cheat a little so the frame
+ doesn't jump so much when resized later in menubar_map_cb. */
+ if (req.height == 0)
+ req.height = 23;
+
+ if (FRAME_MENUBAR_HEIGHT (f) != req.height)
+ {
+ FRAME_MENUBAR_HEIGHT (f) = req.height;
+ xg_height_or_width_changed (f);
+ }
UNBLOCK_INPUT;
return 1;
@@ -3147,7 +3209,7 @@ xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
return 0;
gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
- gw = gdk_xid_table_lookup_for_display (gdpy, event->xbutton.window);
+ gw = gdk_x11_window_lookup_for_display (gdpy, event->xbutton.window);
if (! gw) return 0;
gevent.any.window = gw;
gwdesc = gtk_get_event_widget (&gevent);
@@ -3311,8 +3373,12 @@ xg_create_scroll_bar (FRAME_PTR f,
{
GtkWidget *wscroll;
GtkWidget *webox;
- GtkObject *vadj;
int scroll_id;
+#ifdef HAVE_GTK3
+ GtkAdjustment *vadj;
+#else
+ GtkObject *vadj;
+#endif
/* Page, step increment values are not so important here, they
will be corrected in x_set_toolkit_scroll_bar_thumb. */
@@ -3322,7 +3388,9 @@ xg_create_scroll_bar (FRAME_PTR f,
wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj));
webox = gtk_event_box_new ();
gtk_widget_set_name (wscroll, scroll_bar_name);
+#ifndef HAVE_GTK3
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
+#endif
g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
scroll_id = xg_store_widget_in_map (wscroll);
@@ -3340,7 +3408,7 @@ xg_create_scroll_bar (FRAME_PTR f,
"button-release-event",
end_callback,
(gpointer) bar);
-
+
/* The scroll bar widget does not draw on a window of its own. Instead
it draws on the parent window, in this case the edit widget. So
whenever the edit widget is cleared, the scroll bar needs to redraw
@@ -3429,11 +3497,11 @@ xg_update_scrollbar_pos (FRAME_PTR f,
FRAME_X_WINDOW (f),
oldx, oldy, oldw, oldh, 0);
}
-
+
/* GTK does not redraw until the main loop is entered again, but
if there are no X events pending we will not enter it. So we sync
here to get some events. */
-
+
x_sync (f);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
@@ -3501,7 +3569,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
changed = 1;
}
- if (changed || (int) gtk_range_get_value (GTK_RANGE (wscroll)) != value)
+ if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
{
BLOCK_INPUT;
@@ -3509,7 +3577,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
ignore_gtk_scrollbar to make the callback do nothing */
xg_ignore_gtk_scrollbar = 1;
- if ((int) gtk_range_get_value (GTK_RANGE (wscroll)) != value)
+ if (int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value);
else if (changed)
gtk_adjustment_changed (adj);
@@ -3548,7 +3616,7 @@ xg_event_is_for_scrollbar (FRAME_PTR f, XEvent *event)
GtkWidget *w = gtk_grab_get_current ();
retval = w != 0 && GTK_IS_SCROLLBAR (w);
}
-
+
return retval;
}
@@ -3605,8 +3673,8 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
{
/* The EMACS_INT cast avoids a warning. */
int idx = (int) (EMACS_INT) client_data;
- int mod = (int) (EMACS_INT) g_object_get_data (G_OBJECT (w),
- XG_TOOL_BAR_LAST_MODIFIER);
+ gpointer gmod = g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER);
+ int mod = (int) (EMACS_INT) gmod;
FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
Lisp_Object key, frame;
@@ -3636,7 +3704,7 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
this is written. */
event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), mod);
kbd_buffer_store_event (&event);
-
+
/* Return focus to the frame after we have clicked on a detached
tool bar button. */
Fx_focus_frame (frame);
@@ -3673,7 +3741,7 @@ xg_tool_bar_proxy_help_callback (GtkWidget *w,
{
GtkWidget *wbutton = GTK_WIDGET (g_object_get_data (G_OBJECT (w),
XG_TOOL_BAR_PROXY_BUTTON));
-
+
return xg_tool_bar_help_callback (wbutton, event, client_data);
}
@@ -3682,7 +3750,8 @@ xg_get_tool_bar_widgets (GtkWidget *vb, GtkWidget **wimage)
{
GList *clist = gtk_container_get_children (GTK_CONTAINER (vb));
GtkWidget *c1 = (GtkWidget *) clist->data;
- GtkWidget *c2 = (GtkWidget *) clist->next->data;
+ GtkWidget *c2 = clist->next ? (GtkWidget *) clist->next->data : NULL;
+
*wimage = GTK_IS_IMAGE (c1) ? c1 : c2;
g_list_free (clist);
return GTK_IS_LABEL (c1) ? c1 : c2;
@@ -3697,14 +3766,13 @@ xg_get_tool_bar_widgets (GtkWidget *vb, GtkWidget **wimage)
static gboolean
xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data)
{
- GtkWidget *weventbox = gtk_bin_get_child (GTK_BIN (toolitem));
- GtkButton *wbutton = GTK_BUTTON (gtk_bin_get_child (GTK_BIN (weventbox)));
- GtkWidget *vb = gtk_bin_get_child (GTK_BIN (wbutton));
+ GtkButton *wbutton = GTK_BUTTON (XG_BIN_CHILD (XG_BIN_CHILD (toolitem)));
+ GtkWidget *vb = XG_BIN_CHILD (wbutton);
GtkWidget *c1;
GtkLabel *wlbl = GTK_LABEL (xg_get_tool_bar_widgets (vb, &c1));
GtkImage *wimage = GTK_IMAGE (c1);
GtkWidget *wmenuitem = gtk_image_menu_item_new_with_label
- (gtk_label_get_text (wlbl));
+ (wlbl ? gtk_label_get_text (wlbl) : "");
GtkWidget *wmenuimage;
@@ -3716,6 +3784,8 @@ xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data)
GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (wbutton));
GtkImageType store_type = gtk_image_get_storage_type (wimage);
+ g_object_set (G_OBJECT (settings), "gtk-menu-images", TRUE, NULL);
+
if (store_type == GTK_IMAGE_STOCK)
{
gchar *stock_id;
@@ -3774,7 +3844,7 @@ xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data)
G_CALLBACK (xg_tool_bar_proxy_callback),
user_data);
-
+
g_object_set_data (G_OBJECT (wmenuitem), XG_TOOL_BAR_PROXY_BUTTON,
(gpointer) wbutton);
gtk_tool_item_set_proxy_menu_item (toolitem, "Emacs toolbar item", wmenuitem);
@@ -3810,7 +3880,6 @@ xg_tool_bar_detach_callback (GtkHandleBox *wbox,
gpointer client_data)
{
FRAME_PTR f = (FRAME_PTR) client_data;
- extern int x_gtk_whole_detached_tool_bar;
g_object_set (G_OBJECT (w), "show-arrow", !x_gtk_whole_detached_tool_bar,
NULL);
@@ -3819,8 +3888,8 @@ xg_tool_bar_detach_callback (GtkHandleBox *wbox,
{
GtkRequisition req, req2;
FRAME_X_OUTPUT (f)->toolbar_detached = 1;
- gtk_widget_size_request (GTK_WIDGET (wbox), &req);
- gtk_widget_size_request (w, &req2);
+ gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req);
+ gtk_widget_get_preferred_size (w, NULL, &req2);
req.width -= req2.width;
req.height -= req2.height;
if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
@@ -3854,8 +3923,8 @@ xg_tool_bar_attach_callback (GtkHandleBox *wbox,
{
GtkRequisition req, req2;
FRAME_X_OUTPUT (f)->toolbar_detached = 0;
- gtk_widget_size_request (GTK_WIDGET (wbox), &req);
- gtk_widget_size_request (w, &req2);
+ gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req);
+ gtk_widget_get_preferred_size (w, NULL, &req2);
req.width += req2.width;
req.height += req2.height;
if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
@@ -3920,6 +3989,7 @@ xg_tool_bar_help_callback (GtkWidget *w,
Returns FALSE to tell GTK to keep processing this event. */
+#ifndef HAVE_GTK3
static gboolean
xg_tool_bar_item_expose_callback (GtkWidget *w,
GdkEventExpose *event,
@@ -3928,7 +3998,6 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
gint width, height;
gdk_drawable_get_size (event->window, &width, &height);
-
event->area.x -= width > event->area.width ? width-event->area.width : 0;
event->area.y -= height > event->area.height ? height-event->area.height : 0;
@@ -3940,6 +4009,7 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
return FALSE;
}
+#endif
#ifdef HAVE_GTK_ORIENTABLE_SET_ORIENTATION
#define toolbar_set_orientation(w, o) \
@@ -3972,8 +4042,10 @@ xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
x->toolbar_widget);
}
- if (into_hbox)
+ if (into_hbox)
{
+ gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (x->handlebox_widget),
+ GTK_POS_TOP);
gtk_box_pack_start (GTK_BOX (x->hbox_widget), x->handlebox_widget,
FALSE, FALSE, 0);
@@ -3986,6 +4058,8 @@ xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
else
{
int vbox_pos = x->menubar_widget ? 1 : 0;
+ gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (x->handlebox_widget),
+ GTK_POS_LEFT);
gtk_box_pack_start (GTK_BOX (x->vbox_widget), x->handlebox_widget,
FALSE, FALSE, 0);
@@ -4052,23 +4126,17 @@ xg_make_tool_item (FRAME_PTR f,
GtkWidget *wimage,
GtkWidget **wbutton,
const char *label,
- int i)
+ int i, int horiz, int text_image)
{
GtkToolItem *ti = gtk_tool_item_new ();
- Lisp_Object style = Ftool_bar_get_system_style ();
- int both_horiz = EQ (style, Qboth_horiz);
- int text_image = EQ (style, Qtext_image_horiz);
-
- GtkWidget *vb = both_horiz || text_image
- ? gtk_hbox_new (FALSE, 0) : gtk_vbox_new (FALSE, 0);
+ GtkWidget *vb = horiz ? gtk_hbox_new (FALSE, 0) : gtk_vbox_new (FALSE, 0);
GtkWidget *wb = gtk_button_new ();
GtkWidget *weventbox = gtk_event_box_new ();
- if (wimage && ! text_image)
+ if (wimage && !text_image)
gtk_box_pack_start (GTK_BOX (vb), wimage, TRUE, TRUE, 0);
-
- gtk_box_pack_start (GTK_BOX (vb), gtk_label_new (label), TRUE, TRUE, 0);
-
+ if (label)
+ gtk_box_pack_start (GTK_BOX (vb), gtk_label_new (label), TRUE, TRUE, 0);
if (wimage && text_image)
gtk_box_pack_start (GTK_BOX (vb), wimage, TRUE, TRUE, 0);
@@ -4091,13 +4159,14 @@ xg_make_tool_item (FRAME_PTR f,
g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f);
+#ifndef HAVE_GTK3
/* Catch expose events to overcome an annoying redraw bug, see
comment for xg_tool_bar_item_expose_callback. */
g_signal_connect (G_OBJECT (ti),
"expose-event",
G_CALLBACK (xg_tool_bar_item_expose_callback),
0);
-
+#endif
gtk_tool_item_set_homogeneous (ti, FALSE);
/* Callback to save modifyer mask (Shift/Control, etc). GTK makes
@@ -4108,7 +4177,7 @@ xg_make_tool_item (FRAME_PTR f,
NULL);
g_object_set_data (G_OBJECT (wb), XG_FRAME_DATA, (gpointer)f);
-
+
/* Use enter/leave notify to show help. We use the events
rather than the GtkButton specific signals "enter" and
"leave", so we can have only one callback. The event
@@ -4123,63 +4192,55 @@ xg_make_tool_item (FRAME_PTR f,
G_CALLBACK (xg_tool_bar_help_callback),
(gpointer) (EMACS_INT) i);
}
-
+
if (wbutton) *wbutton = wb;
return ti;
}
-static void
-xg_show_toolbar_item (GtkToolItem *ti)
+static int
+xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
+ const char *icon_name, const struct image *img,
+ const char *label, int horiz)
{
- Lisp_Object style = Ftool_bar_get_system_style ();
- int both_horiz = EQ (style, Qboth_horiz);
- int text_image = EQ (style, Qtext_image_horiz);
-
- int horiz = both_horiz || text_image;
- int show_label = ! EQ (style, Qimage);
- int show_image = ! EQ (style, Qtext);
-
- GtkWidget *weventbox = gtk_bin_get_child (GTK_BIN (ti));
- GtkWidget *wbutton = gtk_bin_get_child (GTK_BIN (weventbox));
- GtkWidget *vb = gtk_bin_get_child (GTK_BIN (wbutton));
+ gpointer old;
GtkWidget *wimage;
+ GtkWidget *vb = XG_BIN_CHILD (wbutton);
GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage);
- GtkWidget *new_box = NULL;
- if (GTK_IS_VBOX (vb) && horiz)
- new_box = gtk_hbox_new (FALSE, 0);
- else if (GTK_IS_HBOX (vb) && !horiz && show_label && show_image)
- new_box = gtk_vbox_new (FALSE, 0);
-
- if (!new_box && horiz)
- gtk_box_reorder_child (GTK_BOX (vb), wlbl, text_image ? 0 : 1);
- else if (new_box)
+ /* Check if the tool icon matches. */
+ if (stock_name)
+ {
+ old = g_object_get_data (G_OBJECT (wimage),
+ XG_TOOL_BAR_STOCK_NAME);
+ if (!old || strcmp (old, stock_name))
+ return 1;
+ }
+ else if (icon_name)
+ {
+ old = g_object_get_data (G_OBJECT (wimage),
+ XG_TOOL_BAR_ICON_NAME);
+ if (!old || strcmp (old, icon_name))
+ return 1;
+ }
+ else
{
- g_object_ref (G_OBJECT (wimage));
- g_object_ref (G_OBJECT (wlbl));
- gtk_container_remove (GTK_CONTAINER (vb), wimage);
- gtk_container_remove (GTK_CONTAINER (vb), wlbl);
- gtk_widget_destroy (GTK_WIDGET (vb));
- if (! text_image)
- gtk_box_pack_start (GTK_BOX (new_box), wimage, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (new_box), wlbl, TRUE, TRUE, 0);
- if (text_image)
- gtk_box_pack_start (GTK_BOX (new_box), wimage, TRUE, TRUE, 0);
- gtk_container_add (GTK_CONTAINER (wbutton), new_box);
- g_object_unref (G_OBJECT (wimage));
- g_object_unref (G_OBJECT (wlbl));
- vb = new_box;
+ gpointer gold_img = g_object_get_data (G_OBJECT (wimage),
+ XG_TOOL_BAR_IMAGE_DATA);
+ Pixmap old_img = (Pixmap) gold_img;
+ if (old_img != img->pixmap)
+ return 1;
}
- if (show_label) gtk_widget_show (wlbl);
- else gtk_widget_hide (wlbl);
- if (show_image) gtk_widget_show (wimage);
- else gtk_widget_hide (wimage);
- gtk_widget_show (GTK_WIDGET (weventbox));
- gtk_widget_show (GTK_WIDGET (vb));
- gtk_widget_show (GTK_WIDGET (wbutton));
- gtk_widget_show (GTK_WIDGET (ti));
+ /* Check button configuration and label. */
+ if ((horiz ? GTK_IS_VBOX (vb) : GTK_IS_HBOX (vb))
+ || (label ? (wlbl == NULL) : (wlbl != NULL)))
+ return 1;
+
+ /* Ensure label is correct. */
+ if (label)
+ gtk_label_set_text (GTK_LABEL (wlbl), label);
+ return 0;
}
static int
@@ -4189,7 +4250,7 @@ xg_update_tool_bar_sizes (FRAME_PTR f)
GtkRequisition req;
int nl = 0, nr = 0, nt = 0, nb = 0;
- gtk_widget_size_request (GTK_WIDGET (x->handlebox_widget), &req);
+ gtk_widget_get_preferred_size (GTK_WIDGET (x->handlebox_widget), NULL, &req);
if (x->toolbar_in_hbox)
{
int pos;
@@ -4208,7 +4269,7 @@ xg_update_tool_bar_sizes (FRAME_PTR f)
if (pos == 0 || (pos == 1 && x->menubar_widget)) nt = req.height;
else nb = req.height;
}
-
+
if (nl != FRAME_TOOLBAR_LEFT_WIDTH (f)
|| nr != FRAME_TOOLBAR_RIGHT_WIDTH (f)
|| nt != FRAME_TOOLBAR_TOP_HEIGHT (f)
@@ -4232,13 +4293,15 @@ xg_update_tool_bar_sizes (FRAME_PTR f)
void
update_frame_tool_bar (FRAME_PTR f)
{
- int i;
+ int i, j;
struct x_output *x = f->output_data.x;
int hmargin = 0, vmargin = 0;
GtkToolbar *wtoolbar;
GtkToolItem *ti;
GtkTextDirection dir;
int pack_tool_bar = x->handlebox_widget == NULL;
+ Lisp_Object style;
+ int text_image, horiz;
if (! FRAME_GTK_WIDGET (f))
return;
@@ -4274,8 +4337,12 @@ update_frame_tool_bar (FRAME_PTR f)
wtoolbar = GTK_TOOLBAR (x->toolbar_widget);
dir = gtk_widget_get_direction (GTK_WIDGET (wtoolbar));
-
- for (i = 0; i < f->n_tool_bar_items; ++i)
+
+ style = Ftool_bar_get_system_style ();
+ text_image = EQ (style, Qtext_image_horiz);
+ horiz = EQ (style, Qboth_horiz) || text_image;
+
+ for (i = j = 0; i < f->n_tool_bar_items; ++i)
{
int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
@@ -4290,26 +4357,48 @@ update_frame_tool_bar (FRAME_PTR f)
char *icon_name = NULL;
Lisp_Object rtl;
GtkWidget *wbutton = NULL;
- GtkWidget *weventbox;
Lisp_Object specified_file;
- const char *label = (STRINGP (PROP (TOOL_BAR_ITEM_LABEL))
- ? SSDATA (PROP (TOOL_BAR_ITEM_LABEL)) : "");
-
- ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), i);
-
- if (ti)
- {
- weventbox = gtk_bin_get_child (GTK_BIN (ti));
- wbutton = gtk_bin_get_child (GTK_BIN (weventbox));
- }
-
-
- image = PROP (TOOL_BAR_ITEM_IMAGES);
+ int vert_only = ! NILP (PROP (TOOL_BAR_ITEM_VERT_ONLY));
+ const char *label
+ = (EQ (style, Qimage) || (vert_only && horiz)) ? NULL
+ : STRINGP (PROP (TOOL_BAR_ITEM_LABEL))
+ ? SSDATA (PROP (TOOL_BAR_ITEM_LABEL))
+ : "";
+
+ ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), j);
+
+ /* If this is a separator, use a gtk separator item. */
+ if (EQ (PROP (TOOL_BAR_ITEM_TYPE), Qt))
+ {
+ if (ti == NULL || !GTK_IS_SEPARATOR_TOOL_ITEM (ti))
+ {
+ if (ti)
+ gtk_container_remove (GTK_CONTAINER (wtoolbar),
+ GTK_WIDGET (ti));
+ ti = gtk_separator_tool_item_new ();
+ gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j);
+ }
+ j++;
+ continue;
+ }
+
+ /* Otherwise, the tool-bar item is an ordinary button. */
+
+ if (ti && GTK_IS_SEPARATOR_TOOL_ITEM (ti))
+ {
+ gtk_container_remove (GTK_CONTAINER (wtoolbar), GTK_WIDGET (ti));
+ ti = NULL;
+ }
+
+ if (ti) wbutton = XG_BIN_CHILD (XG_BIN_CHILD (ti));
/* Ignore invalid image specifications. */
+ image = PROP (TOOL_BAR_ITEM_IMAGES);
if (!valid_image_p (image))
{
- if (wbutton) gtk_widget_hide (wbutton);
+ if (ti)
+ gtk_container_remove (GTK_CONTAINER (wtoolbar),
+ GTK_WIDGET (ti));
continue;
}
@@ -4345,16 +4434,13 @@ update_frame_tool_bar (FRAME_PTR f)
if (stock_name == NULL && icon_name == NULL)
{
- /* No stock image, or stock item not known. Try regular image. */
-
- /* If image is a vector, choose the image according to the
+ /* No stock image, or stock item not known. Try regular
+ image. If image is a vector, choose it according to the
button state. */
if (dir == GTK_TEXT_DIR_RTL
&& !NILP (rtl = PROP (TOOL_BAR_ITEM_RTL_IMAGE))
&& STRINGP (rtl))
- {
- image = find_rtl_image (f, image, rtl);
- }
+ image = find_rtl_image (f, image, rtl);
if (VECTORP (image))
{
@@ -4380,21 +4466,31 @@ update_frame_tool_bar (FRAME_PTR f)
if (img->load_failed_p || img->pixmap == None)
{
if (ti)
- gtk_widget_hide_all (GTK_WIDGET (ti));
- else
- {
- /* Insert an empty (non-image) button */
- ti = xg_make_tool_item (f, NULL, NULL, "", i);
- gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, -1);
- }
+ gtk_container_remove (GTK_CONTAINER (wtoolbar),
+ GTK_WIDGET (ti));
continue;
}
}
+ /* If there is an existing widget, check if it's stale; if so,
+ remove it and make a new tool item from scratch. */
+ if (ti && xg_tool_item_stale_p (wbutton, stock_name, icon_name,
+ img, label, horiz))
+ {
+ gtk_container_remove (GTK_CONTAINER (wtoolbar),
+ GTK_WIDGET (ti));
+ ti = NULL;
+ }
+
if (ti == NULL)
{
GtkWidget *w;
- if (stock_name)
+
+ /* Save the image so we can see if an update is needed the
+ next time we call xg_tool_item_match_p. */
+ if (EQ (style, Qtext))
+ w = NULL;
+ else if (stock_name)
{
w = gtk_image_new_from_stock (stock_name, icon_size);
g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_STOCK_NAME,
@@ -4411,92 +4507,34 @@ update_frame_tool_bar (FRAME_PTR f)
else
{
w = xg_get_image_for_pixmap (f, img, x->widget, NULL);
- /* Save the image so we can see if an update is needed when
- this function is called again. */
g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA,
(gpointer)img->pixmap);
}
- gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin);
- ti = xg_make_tool_item (f, w, &wbutton, label, i);
- gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, -1);
- gtk_widget_set_sensitive (wbutton, enabled_p);
- }
- else
- {
- GtkWidget *vb = gtk_bin_get_child (GTK_BIN (wbutton));
- GtkWidget *wimage;
- GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage);
-
- Pixmap old_img = (Pixmap)g_object_get_data (G_OBJECT (wimage),
- XG_TOOL_BAR_IMAGE_DATA);
- gpointer old_stock_name = g_object_get_data (G_OBJECT (wimage),
- XG_TOOL_BAR_STOCK_NAME);
- gpointer old_icon_name = g_object_get_data (G_OBJECT (wimage),
- XG_TOOL_BAR_ICON_NAME);
- gtk_label_set_text (GTK_LABEL (wlbl), label);
- if (stock_name &&
- (! old_stock_name || strcmp (old_stock_name, stock_name) != 0))
- {
- gtk_image_set_from_stock (GTK_IMAGE (wimage),
- stock_name, icon_size);
- g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
- (gpointer) xstrdup (stock_name),
- (GDestroyNotify) xfree);
- g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
- NULL);
- g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME,
- NULL);
- }
- else if (icon_name &&
- (! old_icon_name || strcmp (old_icon_name, icon_name) != 0))
- {
- gtk_image_set_from_icon_name (GTK_IMAGE (wimage),
- icon_name, icon_size);
- g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME,
- (gpointer) xstrdup (icon_name),
- (GDestroyNotify) xfree);
- g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
- NULL);
- g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
- NULL);
- }
- else if (img && old_img != img->pixmap)
- {
- (void) xg_get_image_for_pixmap (f, img, x->widget,
- GTK_IMAGE (wimage));
- g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
- (gpointer)img->pixmap);
-
- g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
- NULL);
- g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME,
- NULL);
- }
-
- gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin);
-
- gtk_widget_set_sensitive (wbutton, enabled_p);
+ if (w) gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin);
+ ti = xg_make_tool_item (f, w, &wbutton, label, i, horiz, text_image);
+ gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j);
}
- xg_show_toolbar_item (ti);
#undef PROP
+
+ gtk_widget_set_sensitive (wbutton, enabled_p);
+ j++;
}
- /* Remove buttons not longer needed. We just hide them so they
- can be reused later on. */
+ /* Remove buttons not longer needed. */
do
{
- ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), i++);
- if (ti) gtk_widget_hide_all (GTK_WIDGET (ti));
+ ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), j);
+ if (ti)
+ gtk_container_remove (GTK_CONTAINER (wtoolbar), GTK_WIDGET (ti));
} while (ti != NULL);
if (f->n_tool_bar_items != 0)
{
if (pack_tool_bar)
xg_pack_tool_bar (f, f->tool_bar_position);
- gtk_widget_show (x->toolbar_widget);
- gtk_widget_show (x->handlebox_widget);
+ gtk_widget_show_all (GTK_WIDGET (x->handlebox_widget));
if (xg_update_tool_bar_sizes (f))
xg_height_or_width_changed (f);
}
@@ -4518,7 +4556,7 @@ free_frame_tool_bar (FRAME_PTR f)
BLOCK_INPUT;
/* We may have created the toolbar_widget in xg_create_tool_bar, but
not the x->handlebox_widget which is created in xg_pack_tool_bar. */
- if (is_packed)
+ if (is_packed)
{
if (x->toolbar_in_hbox)
gtk_container_remove (GTK_CONTAINER (x->hbox_widget),
@@ -4609,17 +4647,14 @@ xg_initialize (void)
/* Make dialogs close on C-g. Since file dialog inherits from
dialog, this works for them also. */
binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_DIALOG));
- gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK,
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
"close", 0);
/* Make menus close on C-g. */
binding_set = gtk_binding_set_by_class (g_type_class_ref
(GTK_TYPE_MENU_SHELL));
- gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK,
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
"cancel", 0);
}
#endif /* USE_GTK */
-
-/* arch-tag: fe7104da-bc1e-4aba-9bd1-f349c528f7e3
- (do not change this comment) */