/* 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.
#include <config.h>
#ifdef USE_GTK
-#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
#include <X11/Xft/Xft.h>
#endif
+#ifdef HAVE_GTK3
+#include <gtk/gtkx.h>
+#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))
#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)
+#ifndef GDK_KEY_g
+#define GDK_KEY_g GDK_g
+#endif
+#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);
+}
+
\f
/***********************************************************************
Display handling functions
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);
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);
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.
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
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);
}
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);
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)
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;
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;
}
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);
}
{
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;
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);
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))),
hierarchy-changed. */
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_tooltip_set_text (x->ttip_widget, SSDATA (encoded_string));
+ 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;
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);
}
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);
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;
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.
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. */
GtkWidget *wtop;
GtkWidget *wvbox, *whbox;
GtkWidget *wfixed;
- GdkColor bg;
GtkRcStyle *style;
char *title = 0;
/* 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.
/* 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. */
/* Must use g_strdup because gtk_widget_modify_style does g_free. */
style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("<none>");
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
{
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;
{
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;
}
}
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);
}
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
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);
/* 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);
g_main_loop_quit (dd->loop);
g_main_loop_unref (dd->loop);
-
+
UNBLOCK_INPUT;
return Qnil;
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);
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. */
(void) xg_maybe_add_timer (&dd);
g_main_loop_run (dd.loop);
-
+
dd.w = 0;
unbind_to (count, Qnil);
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;
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);
int mustmatch_p, int only_dir_p,
xg_get_file_func *func)
{
- char message[1024];
+ char msgbuf[1024];
- GtkWidget *filewin, *wtoggle, *wbox, *wmessage;
+ GtkWidget *filewin, *wtoggle, *wbox, *wmessage IF_LINT (= NULL);
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;
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);
}
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. */
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
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. */
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);
}
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);
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);
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))
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);
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. */
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;
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);
static void
xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
{
- int id = (int) (EMACS_INT) data; /* The EMACS_INT cast avoids a warning. */
+ int id = (intptr_t) data;
xg_remove_widget_from_map (id);
}
{
GtkWidget *wscroll;
GtkWidget *webox;
+ intptr_t scroll_id;
+#ifdef HAVE_GTK3
+ GtkAdjustment *vadj;
+#else
GtkObject *vadj;
- int scroll_id;
+#endif
/* Page, step increment values are not so important here, they
will be corrected in x_set_toolkit_scroll_bar_thumb. */
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);
- /* The EMACS_INT cast avoids a warning. */
g_signal_connect (G_OBJECT (wscroll),
"destroy",
G_CALLBACK (xg_gtk_scroll_destroy),
- (gpointer) (EMACS_INT) scroll_id);
+ (gpointer) scroll_id);
g_signal_connect (G_OBJECT (wscroll),
"change-value",
scroll_callback,
"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
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);
gdouble shown;
gdouble top;
int size, value;
+ int old_size;
int new_step;
int changed = 0;
/* Assume all lines are of equal size. */
new_step = size / max (1, FRAME_LINES (f));
- if ((int) gtk_adjustment_get_page_size (adj) != size
- || (int) gtk_adjustment_get_step_increment (adj) != new_step)
- {
- gtk_adjustment_set_page_size (adj, size);
- gtk_adjustment_set_step_increment (adj, new_step);
- /* Assume a page increment is about 95% of the page size */
- gtk_adjustment_set_page_increment (adj,(int) (0.95*size));
- changed = 1;
- }
-
- if (changed || (int) gtk_range_get_value (GTK_RANGE (wscroll)) != value)
+ old_size = gtk_adjustment_get_page_size (adj);
+ if (old_size != size)
+ {
+ int old_step = gtk_adjustment_get_step_increment (adj);
+ if (old_step != new_step)
+ {
+ gtk_adjustment_set_page_size (adj, size);
+ gtk_adjustment_set_step_increment (adj, new_step);
+ /* Assume a page increment is about 95% of the page size */
+ gtk_adjustment_set_page_increment (adj,(int) (0.95*size));
+ changed = 1;
+ }
+ }
+
+ if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
{
BLOCK_INPUT;
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);
GtkWidget *w = gtk_grab_get_current ();
retval = w != 0 && GTK_IS_SCROLLBAR (w);
}
-
+
return retval;
}
GdkEventButton *event,
gpointer user_data)
{
- /* Casts to avoid warnings when gpointer is 64 bits and int is 32 bits */
- gpointer ptr = (gpointer) (EMACS_INT) event->state;
+ intptr_t state = event->state;
+ gpointer ptr = (gpointer) state;
g_object_set_data (G_OBJECT (widget), XG_TOOL_BAR_LAST_MODIFIER, ptr);
return FALSE;
}
static void
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);
+ intptr_t idx = (intptr_t) client_data;
+ gpointer gmod = g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER);
+ intptr_t mod = (intptr_t) gmod;
FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
Lisp_Object key, frame;
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);
{
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);
}
{
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;
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;
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);
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);
{
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)
{
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)
GdkEventCrossing *event,
gpointer client_data)
{
- /* The EMACS_INT cast avoids a warning. */
- int idx = (int) (EMACS_INT) client_data;
+ intptr_t idx = (intptr_t) client_data;
FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
Lisp_Object help, frame;
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,
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;
return FALSE;
}
+#endif
#ifdef HAVE_GTK_ORIENTABLE_SET_ORIENTATION
#define toolbar_set_orientation(w, o) \
x->toolbar_widget);
}
- if (into_hbox)
+ if (into_hbox)
{
gtk_handle_box_set_handle_position (GTK_HANDLE_BOX (x->handlebox_widget),
GTK_POS_TOP);
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);
if (wimage)
{
- /* The EMACS_INT cast avoids a warning. */
+ intptr_t ii = i;
+ gpointer gi = (gpointer) ii;
+
g_signal_connect (G_OBJECT (ti), "create-menu-proxy",
G_CALLBACK (xg_tool_bar_menu_proxy),
- (gpointer) (EMACS_INT) i);
+ gi);
g_signal_connect (G_OBJECT (wb), "clicked",
G_CALLBACK (xg_tool_bar_callback),
- (gpointer) (EMACS_INT) i);
+ gi);
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
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
g_signal_connect (G_OBJECT (weventbox),
"enter-notify-event",
G_CALLBACK (xg_tool_bar_help_callback),
- (gpointer) (EMACS_INT) i);
+ gi);
g_signal_connect (G_OBJECT (weventbox),
"leave-notify-event",
G_CALLBACK (xg_tool_bar_help_callback),
- (gpointer) (EMACS_INT) i);
+ gi);
}
-
+
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)
{
- 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;
+ old = g_object_get_data (G_OBJECT (wimage),
+ XG_TOOL_BAR_ICON_NAME);
+ if (!old || strcmp (old, icon_name))
+ return 1;
}
+ else
+ {
+ 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;
+ }
+
+ /* Check button configuration and label. */
+ if ((horiz ? GTK_IS_VBOX (vb) : GTK_IS_HBOX (vb))
+ || (label ? (wlbl == NULL) : (wlbl != NULL)))
+ 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));
+ /* Ensure label is correct. */
+ if (label)
+ gtk_label_set_text (GTK_LABEL (wlbl), label);
+ return 0;
}
static int
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;
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)
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;
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));
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;
}
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))
{
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,
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);
}
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),
/* 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) */