aboutsummaryrefslogtreecommitdiffstats
path: root/src/gtkutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkutil.c')
-rw-r--r--src/gtkutil.c116
1 files changed, 69 insertions, 47 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c
index dfc5b63f375..4dbef65dedf 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1,6 +1,6 @@
1/* Functions for creating and updating GTK widgets. 1/* Functions for creating and updating GTK widgets.
2 2
3Copyright (C) 2003-2011 Free Software Foundation, Inc. 3Copyright (C) 2003-2012 Free Software Foundation, Inc.
4 4
5This file is part of GNU Emacs. 5This file is part of GNU Emacs.
6 6
@@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20#include <config.h> 20#include <config.h>
21 21
22#ifdef USE_GTK 22#ifdef USE_GTK
23#include <float.h>
23#include <signal.h> 24#include <signal.h>
24#include <stdio.h> 25#include <stdio.h>
25#include <setjmp.h> 26#include <setjmp.h>
@@ -126,7 +127,7 @@ xg_set_screen (GtkWidget *w, FRAME_PTR f)
126 127
127 Returns non-zero if display could be opened, zero if display could not 128 Returns non-zero if display could be opened, zero if display could not
128 be opened, and less than zero if the GTK version doesn't support 129 be opened, and less than zero if the GTK version doesn't support
129 multipe displays. */ 130 multiple displays. */
130 131
131void 132void
132xg_display_open (char *display_name, Display **dpy) 133xg_display_open (char *display_name, Display **dpy)
@@ -269,8 +270,8 @@ xg_get_pixbuf_from_pixmap (FRAME_PTR f, Pixmap pix)
269 GDK_COLORSPACE_RGB, 270 GDK_COLORSPACE_RGB,
270 FALSE, 271 FALSE,
271 xim->bitmap_unit, 272 xim->bitmap_unit,
272 (int) width, 273 width,
273 (int) height, 274 height,
274 xim->bytes_per_line, 275 xim->bytes_per_line,
275 NULL, 276 NULL,
276 NULL); 277 NULL);
@@ -347,7 +348,7 @@ file_for_image (Lisp_Object image)
347 348
348/* For the image defined in IMG, make and return a GtkImage. For displays with 349/* For the image defined in IMG, make and return a GtkImage. For displays with
349 8 planes or less we must make a GdkPixbuf and apply the mask manually. 350 8 planes or less we must make a GdkPixbuf and apply the mask manually.
350 Otherwise the highlightning and dimming the tool bar code in GTK does 351 Otherwise the highlighting and dimming the tool bar code in GTK does
351 will look bad. For display with more than 8 planes we just use the 352 will look bad. For display with more than 8 planes we just use the
352 pixmap and mask directly. For monochrome displays, GTK doesn't seem 353 pixmap and mask directly. For monochrome displays, GTK doesn't seem
353 able to use external pixmaps, it looks bad whatever we do. 354 able to use external pixmaps, it looks bad whatever we do.
@@ -421,7 +422,7 @@ xg_get_image_for_pixmap (FRAME_PTR f,
421static void 422static void
422xg_set_cursor (GtkWidget *w, GdkCursor *cursor) 423xg_set_cursor (GtkWidget *w, GdkCursor *cursor)
423{ 424{
424 GdkWindow *window = gtk_widget_get_window(w); 425 GdkWindow *window = gtk_widget_get_window (w);
425 GList *children = gdk_window_peek_children (window); 426 GList *children = gdk_window_peek_children (window);
426 427
427 gdk_window_set_cursor (window, cursor); 428 gdk_window_set_cursor (window, cursor);
@@ -487,7 +488,8 @@ get_utf8_string (const char *str)
487 if (!utf8_str) 488 if (!utf8_str)
488 { 489 {
489 /* Probably some control characters in str. Escape them. */ 490 /* Probably some control characters in str. Escape them. */
490 size_t nr_bad = 0; 491 ptrdiff_t len;
492 ptrdiff_t nr_bad = 0;
491 gsize bytes_read; 493 gsize bytes_read;
492 gsize bytes_written; 494 gsize bytes_written;
493 unsigned char *p = (unsigned char *)str; 495 unsigned char *p = (unsigned char *)str;
@@ -511,7 +513,10 @@ get_utf8_string (const char *str)
511 } 513 }
512 if (cp) g_free (cp); 514 if (cp) g_free (cp);
513 515
514 up = utf8_str = xmalloc (strlen (str) + nr_bad * 4 + 1); 516 len = strlen (str);
517 if ((min (PTRDIFF_MAX, SIZE_MAX) - len - 1) / 4 < nr_bad)
518 memory_full (SIZE_MAX);
519 up = utf8_str = xmalloc (len + nr_bad * 4 + 1);
515 p = (unsigned char *)str; 520 p = (unsigned char *)str;
516 521
517 while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read, 522 while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
@@ -563,7 +568,7 @@ xg_check_special_colors (struct frame *f,
563 GtkStyleContext *gsty 568 GtkStyleContext *gsty
564 = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); 569 = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
565 GdkRGBA col; 570 GdkRGBA col;
566 char buf[64]; 571 char buf[sizeof "rgbi://" + 3 * (DBL_MAX_10_EXP + sizeof "-1.000000" - 1)];
567 int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED; 572 int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED;
568 if (get_fg) 573 if (get_fg)
569 gtk_style_context_get_color (gsty, state, &col); 574 gtk_style_context_get_color (gsty, state, &col);
@@ -647,7 +652,6 @@ qttip_cb (GtkWidget *widget,
647 /* Change stupid Gtk+ default line wrapping. */ 652 /* Change stupid Gtk+ default line wrapping. */
648 p = gtk_widget_get_parent (x->ttip_lbl); 653 p = gtk_widget_get_parent (x->ttip_lbl);
649 list = gtk_container_get_children (GTK_CONTAINER (p)); 654 list = gtk_container_get_children (GTK_CONTAINER (p));
650 iter;
651 for (iter = list; iter; iter = g_list_next (iter)) 655 for (iter = list; iter; iter = g_list_next (iter))
652 { 656 {
653 GtkWidget *w = GTK_WIDGET (iter->data); 657 GtkWidget *w = GTK_WIDGET (iter->data);
@@ -794,7 +798,7 @@ xg_set_geometry (FRAME_PTR f)
794 int xneg = f->size_hint_flags & XNegative; 798 int xneg = f->size_hint_flags & XNegative;
795 int top = f->top_pos; 799 int top = f->top_pos;
796 int yneg = f->size_hint_flags & YNegative; 800 int yneg = f->size_hint_flags & YNegative;
797 char geom_str[32]; 801 char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)];
798 802
799 if (xneg) 803 if (xneg)
800 left = -left; 804 left = -left;
@@ -887,7 +891,7 @@ xg_frame_resized (FRAME_PTR f, int pixelwidth, int pixelheight)
887 } 891 }
888} 892}
889 893
890/* Resize the outer window of frame F after chainging the height. 894/* Resize the outer window of frame F after changing the height.
891 COLUMNS/ROWS is the size the edit area shall have after the resize. */ 895 COLUMNS/ROWS is the size the edit area shall have after the resize. */
892 896
893void 897void
@@ -983,6 +987,7 @@ xg_win_to_widget (Display *dpy, Window wdesc)
983 { 987 {
984 GdkEvent event; 988 GdkEvent event;
985 event.any.window = gdkwin; 989 event.any.window = gdkwin;
990 event.any.type = GDK_NOTHING;
986 gwdesc = gtk_get_event_widget (&event); 991 gwdesc = gtk_get_event_widget (&event);
987 } 992 }
988 993
@@ -1095,6 +1100,14 @@ xg_create_frame_widgets (FRAME_PTR f)
1095 else 1100 else
1096 wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL); 1101 wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1097 1102
1103 /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu
1104 has backported it to Gtk+ 2.0 and they add the resize grip for
1105 Gtk+ 2.0 applications also. But it has a bug that makes Emacs loop
1106 forever, so disable the grip. */
1107#if GTK_MAJOR_VERSION < 3 && defined (HAVE_GTK_WINDOW_SET_HAS_RESIZE_GRIP)
1108 gtk_window_set_has_resize_grip (GTK_WINDOW (wtop), FALSE);
1109#endif
1110
1098 xg_set_screen (wtop, f); 1111 xg_set_screen (wtop, f);
1099 1112
1100 wvbox = gtk_vbox_new (FALSE, 0); 1113 wvbox = gtk_vbox_new (FALSE, 0);
@@ -1291,10 +1304,13 @@ x_wm_set_size_hint (FRAME_PTR f, long int flags, int user_position)
1291 1304
1292 hint_flags |= GDK_HINT_BASE_SIZE; 1305 hint_flags |= GDK_HINT_BASE_SIZE;
1293 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0) + FRAME_TOOLBAR_WIDTH (f); 1306 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0) + FRAME_TOOLBAR_WIDTH (f);
1294 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0) 1307 /* Use one row here so base_height does not become zero.
1308 Gtk+ and/or Unity on Ubuntu 12.04 can't handle it. */
1309 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1)
1295 + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); 1310 + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
1296 1311
1297 check_frame_size (f, &min_rows, &min_cols); 1312 check_frame_size (f, &min_rows, &min_cols);
1313 if (min_rows > 0) --min_rows; /* We used one row in base_height = ... 1); */
1298 1314
1299 size_hints.base_width = base_width; 1315 size_hints.base_width = base_width;
1300 size_hints.base_height = base_height; 1316 size_hints.base_height = base_height;
@@ -1418,7 +1434,7 @@ get_dialog_title (char key)
1418/* Callback for dialogs that get WM_DELETE_WINDOW. We pop down 1434/* Callback for dialogs that get WM_DELETE_WINDOW. We pop down
1419 the dialog, but return TRUE so the event does not propagate further 1435 the dialog, but return TRUE so the event does not propagate further
1420 in GTK. This prevents GTK from destroying the dialog widget automatically 1436 in GTK. This prevents GTK from destroying the dialog widget automatically
1421 and we can always destrou the widget manually, regardles of how 1437 and we can always destroy the widget manually, regardless of how
1422 it was popped down (button press or WM_DELETE_WINDOW). 1438 it was popped down (button press or WM_DELETE_WINDOW).
1423 W is the dialog widget. 1439 W is the dialog widget.
1424 EVENT is the GdkEvent that represents WM_DELETE_WINDOW (not used). 1440 EVENT is the GdkEvent that represents WM_DELETE_WINDOW (not used).
@@ -1728,8 +1744,9 @@ xg_toggle_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data)
1728 PROMPT is a prompt to show to the user. May not be NULL. 1744 PROMPT is a prompt to show to the user. May not be NULL.
1729 DEFAULT_FILENAME is a default selection to be displayed. May be NULL. 1745 DEFAULT_FILENAME is a default selection to be displayed. May be NULL.
1730 If MUSTMATCH_P is non-zero, the returned file name must be an existing 1746 If MUSTMATCH_P is non-zero, the returned file name must be an existing
1731 file. *FUNC is set to a function that can be used to retrieve the 1747 file. (Actually, this only has cosmetic effects, the user can
1732 selected file name from the returned widget. 1748 still enter a non-existing file.) *FUNC is set to a function that
1749 can be used to retrieve the selected file name from the returned widget.
1733 1750
1734 Returns the created widget. */ 1751 Returns the created widget. */
1735 1752
@@ -1908,12 +1925,12 @@ xg_get_file_name (FRAME_PTR f,
1908 int filesel_done = 0; 1925 int filesel_done = 0;
1909 xg_get_file_func func; 1926 xg_get_file_func func;
1910 1927
1911#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN) 1928#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
1912 /* I really don't know why this is needed, but without this the GLIBC add on 1929 /* I really don't know why this is needed, but without this the GLIBC add on
1913 library linuxthreads hangs when the Gnome file chooser backend creates 1930 library linuxthreads hangs when the Gnome file chooser backend creates
1914 threads. */ 1931 threads. */
1915 sigblock (sigmask (__SIGRTMIN)); 1932 sigblock (sigmask (__SIGRTMIN));
1916#endif /* HAVE_GTK_AND_PTHREAD */ 1933#endif /* HAVE_PTHREAD */
1917 1934
1918#ifdef HAVE_GTK_FILE_SELECTION_NEW 1935#ifdef HAVE_GTK_FILE_SELECTION_NEW
1919 1936
@@ -1933,7 +1950,7 @@ xg_get_file_name (FRAME_PTR f,
1933 1950
1934 filesel_done = xg_dialog_run (f, w); 1951 filesel_done = xg_dialog_run (f, w);
1935 1952
1936#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN) 1953#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
1937 sigunblock (sigmask (__SIGRTMIN)); 1954 sigunblock (sigmask (__SIGRTMIN));
1938#endif 1955#endif
1939 1956
@@ -1961,9 +1978,9 @@ xg_get_font_name (FRAME_PTR f, const char *default_name)
1961 char *fontname = NULL; 1978 char *fontname = NULL;
1962 int done = 0; 1979 int done = 0;
1963 1980
1964#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN) 1981#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
1965 sigblock (sigmask (__SIGRTMIN)); 1982 sigblock (sigmask (__SIGRTMIN));
1966#endif /* HAVE_GTK_AND_PTHREAD */ 1983#endif /* HAVE_PTHREAD */
1967 1984
1968 w = gtk_font_selection_dialog_new ("Pick a font"); 1985 w = gtk_font_selection_dialog_new ("Pick a font");
1969 if (!default_name) 1986 if (!default_name)
@@ -1975,7 +1992,7 @@ xg_get_font_name (FRAME_PTR f, const char *default_name)
1975 1992
1976 done = xg_dialog_run (f, w); 1993 done = xg_dialog_run (f, w);
1977 1994
1978#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN) 1995#if defined (HAVE_PTHREAD) && defined (__SIGRTMIN)
1979 sigunblock (sigmask (__SIGRTMIN)); 1996 sigunblock (sigmask (__SIGRTMIN));
1980#endif 1997#endif
1981 1998
@@ -2289,7 +2306,7 @@ tearoff_activate (GtkWidget *widget, gpointer client_data)
2289 2306
2290 2307
2291/* Create a menu item widget, and connect the callbacks. 2308/* Create a menu item widget, and connect the callbacks.
2292 ITEM decribes the menu item. 2309 ITEM describes the menu item.
2293 F is the frame the created menu belongs to. 2310 F is the frame the created menu belongs to.
2294 SELECT_CB is the callback to use when a menu item is selected. 2311 SELECT_CB is the callback to use when a menu item is selected.
2295 HIGHLIGHT_CB is the callback to call when entering/leaving menu items. 2312 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
@@ -2358,7 +2375,7 @@ xg_create_one_menuitem (widget_value *item,
2358 HIGHLIGHT_CB is the callback to call when entering/leaving menu items. 2375 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
2359 POP_UP_P is non-zero if we shall create a popup menu. 2376 POP_UP_P is non-zero if we shall create a popup menu.
2360 MENU_BAR_P is non-zero if we shall create a menu bar. 2377 MENU_BAR_P is non-zero if we shall create a menu bar.
2361 ADD_TEAROFF_P is non-zero if we shall add a teroff menu item. Ignored 2378 ADD_TEAROFF_P is non-zero if we shall add a tearoff menu item. Ignored
2362 if MENU_BAR_P is non-zero. 2379 if MENU_BAR_P is non-zero.
2363 TOPMENU is the topmost GtkWidget that others shall be placed under. 2380 TOPMENU is the topmost GtkWidget that others shall be placed under.
2364 It may be NULL, in that case we create the appropriate widget 2381 It may be NULL, in that case we create the appropriate widget
@@ -3039,7 +3056,7 @@ xg_update_submenu (GtkWidget *submenu,
3039 } 3056 }
3040 } 3057 }
3041 3058
3042 /* Remove widgets from first structual change. */ 3059 /* Remove widgets from first structural change. */
3043 if (iter) 3060 if (iter)
3044 { 3061 {
3045 /* If we are adding new menu items below, we must remove from 3062 /* If we are adding new menu items below, we must remove from
@@ -3250,6 +3267,7 @@ xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
3250 gw = gdk_x11_window_lookup_for_display (gdpy, event->xbutton.window); 3267 gw = gdk_x11_window_lookup_for_display (gdpy, event->xbutton.window);
3251 if (! gw) return 0; 3268 if (! gw) return 0;
3252 gevent.any.window = gw; 3269 gevent.any.window = gw;
3270 gevent.any.type = GDK_NOTHING;
3253 gwdesc = gtk_get_event_widget (&gevent); 3271 gwdesc = gtk_get_event_widget (&gevent);
3254 if (! gwdesc) return 0; 3272 if (! gwdesc) return 0;
3255 if (! GTK_IS_MENU_BAR (gwdesc) 3273 if (! GTK_IS_MENU_BAR (gwdesc)
@@ -3297,8 +3315,8 @@ static int scroll_bar_width_for_theme;
3297static struct 3315static struct
3298{ 3316{
3299 GtkWidget **widgets; 3317 GtkWidget **widgets;
3300 int max_size; 3318 ptrdiff_t max_size;
3301 int used; 3319 ptrdiff_t used;
3302} id_to_widget; 3320} id_to_widget;
3303 3321
3304/* Grow this much every time we need to allocate more */ 3322/* Grow this much every time we need to allocate more */
@@ -3307,17 +3325,20 @@ static struct
3307 3325
3308/* Store the widget pointer W in id_to_widget and return the integer index. */ 3326/* Store the widget pointer W in id_to_widget and return the integer index. */
3309 3327
3310static int 3328static ptrdiff_t
3311xg_store_widget_in_map (GtkWidget *w) 3329xg_store_widget_in_map (GtkWidget *w)
3312{ 3330{
3313 int i; 3331 ptrdiff_t i;
3314 3332
3315 if (id_to_widget.max_size == id_to_widget.used) 3333 if (id_to_widget.max_size == id_to_widget.used)
3316 { 3334 {
3317 int new_size = id_to_widget.max_size + ID_TO_WIDGET_INCR; 3335 ptrdiff_t new_size;
3336 if (TYPE_MAXIMUM (Window) - ID_TO_WIDGET_INCR < id_to_widget.max_size)
3337 memory_full (SIZE_MAX);
3318 3338
3319 id_to_widget.widgets = xrealloc (id_to_widget.widgets, 3339 new_size = id_to_widget.max_size + ID_TO_WIDGET_INCR;
3320 sizeof (GtkWidget *)*new_size); 3340 id_to_widget.widgets = xnrealloc (id_to_widget.widgets,
3341 new_size, sizeof (GtkWidget *));
3321 3342
3322 for (i = id_to_widget.max_size; i < new_size; ++i) 3343 for (i = id_to_widget.max_size; i < new_size; ++i)
3323 id_to_widget.widgets[i] = 0; 3344 id_to_widget.widgets[i] = 0;
@@ -3346,7 +3367,7 @@ xg_store_widget_in_map (GtkWidget *w)
3346 Called when scroll bar is destroyed. */ 3367 Called when scroll bar is destroyed. */
3347 3368
3348static void 3369static void
3349xg_remove_widget_from_map (int idx) 3370xg_remove_widget_from_map (ptrdiff_t idx)
3350{ 3371{
3351 if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0) 3372 if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0)
3352 { 3373 {
@@ -3358,7 +3379,7 @@ xg_remove_widget_from_map (int idx)
3358/* Get the widget pointer at IDX from id_to_widget. */ 3379/* Get the widget pointer at IDX from id_to_widget. */
3359 3380
3360static GtkWidget * 3381static GtkWidget *
3361xg_get_widget_from_map (int idx) 3382xg_get_widget_from_map (ptrdiff_t idx)
3362{ 3383{
3363 if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0) 3384 if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0)
3364 return id_to_widget.widgets[idx]; 3385 return id_to_widget.widgets[idx];
@@ -3397,10 +3418,10 @@ xg_get_default_scrollbar_width (void)
3397/* Return the scrollbar id for X Window WID on display DPY. 3418/* Return the scrollbar id for X Window WID on display DPY.
3398 Return -1 if WID not in id_to_widget. */ 3419 Return -1 if WID not in id_to_widget. */
3399 3420
3400int 3421ptrdiff_t
3401xg_get_scroll_id_for_window (Display *dpy, Window wid) 3422xg_get_scroll_id_for_window (Display *dpy, Window wid)
3402{ 3423{
3403 int idx; 3424 ptrdiff_t idx;
3404 GtkWidget *w; 3425 GtkWidget *w;
3405 3426
3406 w = xg_win_to_widget (dpy, wid); 3427 w = xg_win_to_widget (dpy, wid);
@@ -3422,7 +3443,7 @@ xg_get_scroll_id_for_window (Display *dpy, Window wid)
3422static void 3443static void
3423xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data) 3444xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
3424{ 3445{
3425 int id = (intptr_t) data; 3446 intptr_t id = (intptr_t) data;
3426 xg_remove_widget_from_map (id); 3447 xg_remove_widget_from_map (id);
3427} 3448}
3428 3449
@@ -3497,7 +3518,7 @@ xg_create_scroll_bar (FRAME_PTR f,
3497/* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ 3518/* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */
3498 3519
3499void 3520void
3500xg_remove_scroll_bar (FRAME_PTR f, int scrollbar_id) 3521xg_remove_scroll_bar (FRAME_PTR f, ptrdiff_t scrollbar_id)
3501{ 3522{
3502 GtkWidget *w = xg_get_widget_from_map (scrollbar_id); 3523 GtkWidget *w = xg_get_widget_from_map (scrollbar_id);
3503 if (w) 3524 if (w)
@@ -3516,7 +3537,7 @@ xg_remove_scroll_bar (FRAME_PTR f, int scrollbar_id)
3516 3537
3517void 3538void
3518xg_update_scrollbar_pos (FRAME_PTR f, 3539xg_update_scrollbar_pos (FRAME_PTR f,
3519 int scrollbar_id, 3540 ptrdiff_t scrollbar_id,
3520 int top, 3541 int top,
3521 int left, 3542 int left,
3522 int width, 3543 int width,
@@ -3647,7 +3668,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
3647 gtk_adjustment_set_page_size (adj, size); 3668 gtk_adjustment_set_page_size (adj, size);
3648 gtk_adjustment_set_step_increment (adj, new_step); 3669 gtk_adjustment_set_step_increment (adj, new_step);
3649 /* Assume a page increment is about 95% of the page size */ 3670 /* Assume a page increment is about 95% of the page size */
3650 gtk_adjustment_set_page_increment (adj,(int) (0.95*size)); 3671 gtk_adjustment_set_page_increment (adj, size - size / 20);
3651 changed = 1; 3672 changed = 1;
3652 } 3673 }
3653 } 3674 }
@@ -4212,6 +4233,7 @@ xg_make_tool_item (FRAME_PTR f,
4212 GtkToolItem *ti = gtk_tool_item_new (); 4233 GtkToolItem *ti = gtk_tool_item_new ();
4213 GtkWidget *vb = horiz ? gtk_hbox_new (FALSE, 0) : gtk_vbox_new (FALSE, 0); 4234 GtkWidget *vb = horiz ? gtk_hbox_new (FALSE, 0) : gtk_vbox_new (FALSE, 0);
4214 GtkWidget *wb = gtk_button_new (); 4235 GtkWidget *wb = gtk_button_new ();
4236 /* The eventbox is here so we can have tooltips on disabled items. */
4215 GtkWidget *weventbox = gtk_event_box_new (); 4237 GtkWidget *weventbox = gtk_event_box_new ();
4216 4238
4217 if (wimage && !text_image) 4239 if (wimage && !text_image)
@@ -4227,7 +4249,7 @@ xg_make_tool_item (FRAME_PTR f,
4227 gtk_container_add (GTK_CONTAINER (weventbox), wb); 4249 gtk_container_add (GTK_CONTAINER (weventbox), wb);
4228 gtk_container_add (GTK_CONTAINER (ti), weventbox); 4250 gtk_container_add (GTK_CONTAINER (ti), weventbox);
4229 4251
4230 if (wimage) 4252 if (wimage || label)
4231 { 4253 {
4232 intptr_t ii = i; 4254 intptr_t ii = i;
4233 gpointer gi = (gpointer) ii; 4255 gpointer gi = (gpointer) ii;
@@ -4252,7 +4274,7 @@ xg_make_tool_item (FRAME_PTR f,
4252#endif 4274#endif
4253 gtk_tool_item_set_homogeneous (ti, FALSE); 4275 gtk_tool_item_set_homogeneous (ti, FALSE);
4254 4276
4255 /* Callback to save modifyer mask (Shift/Control, etc). GTK makes 4277 /* Callback to save modifier mask (Shift/Control, etc). GTK makes
4256 no distinction based on modifiers in the activate callback, 4278 no distinction based on modifiers in the activate callback,
4257 so we have to do it ourselves. */ 4279 so we have to do it ourselves. */
4258 g_signal_connect (wb, "button-release-event", 4280 g_signal_connect (wb, "button-release-event",
@@ -4292,21 +4314,21 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
4292 GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage); 4314 GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage);
4293 4315
4294 /* Check if the tool icon matches. */ 4316 /* Check if the tool icon matches. */
4295 if (stock_name) 4317 if (stock_name && wimage)
4296 { 4318 {
4297 old = g_object_get_data (G_OBJECT (wimage), 4319 old = g_object_get_data (G_OBJECT (wimage),
4298 XG_TOOL_BAR_STOCK_NAME); 4320 XG_TOOL_BAR_STOCK_NAME);
4299 if (!old || strcmp (old, stock_name)) 4321 if (!old || strcmp (old, stock_name))
4300 return 1; 4322 return 1;
4301 } 4323 }
4302 else if (icon_name) 4324 else if (icon_name && wimage)
4303 { 4325 {
4304 old = g_object_get_data (G_OBJECT (wimage), 4326 old = g_object_get_data (G_OBJECT (wimage),
4305 XG_TOOL_BAR_ICON_NAME); 4327 XG_TOOL_BAR_ICON_NAME);
4306 if (!old || strcmp (old, icon_name)) 4328 if (!old || strcmp (old, icon_name))
4307 return 1; 4329 return 1;
4308 } 4330 }
4309 else 4331 else if (wimage)
4310 { 4332 {
4311 gpointer gold_img = g_object_get_data (G_OBJECT (wimage), 4333 gpointer gold_img = g_object_get_data (G_OBJECT (wimage),
4312 XG_TOOL_BAR_IMAGE_DATA); 4334 XG_TOOL_BAR_IMAGE_DATA);
@@ -4321,7 +4343,7 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
4321 return 1; 4343 return 1;
4322 4344
4323 /* Ensure label is correct. */ 4345 /* Ensure label is correct. */
4324 if (label) 4346 if (label && wlbl)
4325 gtk_label_set_text (GTK_LABEL (wlbl), label); 4347 gtk_label_set_text (GTK_LABEL (wlbl), label);
4326 return 0; 4348 return 0;
4327} 4349}
@@ -4430,7 +4452,7 @@ update_frame_tool_bar (FRAME_PTR f)
4430 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); 4452 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
4431 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); 4453 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
4432 int idx; 4454 int idx;
4433 int img_id; 4455 ptrdiff_t img_id;
4434 int icon_size = 0; 4456 int icon_size = 0;
4435 struct image *img = NULL; 4457 struct image *img = NULL;
4436 Lisp_Object image; 4458 Lisp_Object image;