aboutsummaryrefslogtreecommitdiffstats
path: root/src/gtkutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkutil.c')
-rw-r--r--src/gtkutil.c338
1 files changed, 217 insertions, 121 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 6ecd5d624af..754f61e366d 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -40,6 +40,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
40#include <X11/Xft/Xft.h> 40#include <X11/Xft/Xft.h>
41#endif 41#endif
42 42
43#ifdef HAVE_GTK3
44#include <gtk/gtkx.h>
45#endif
46
43#define FRAME_TOTAL_PIXEL_HEIGHT(f) \ 47#define FRAME_TOTAL_PIXEL_HEIGHT(f) \
44 (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) 48 (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
45 49
@@ -69,8 +73,26 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
69#define remove_submenu(w) gtk_menu_item_remove_submenu ((w)) 73#define remove_submenu(w) gtk_menu_item_remove_submenu ((w))
70#endif 74#endif
71 75
76#ifndef HAVE_GTK3
77#ifdef USE_GTK_TOOLTIP
78#define gdk_window_get_screen(w) gdk_drawable_get_screen (w)
79#endif
80#define gdk_window_get_geometry(w, a, b, c, d) \
81 gdk_window_get_geometry (w, a, b, c, d, 0)
82#define gdk_x11_window_lookup_for_display(d, w) \
83 gdk_xid_table_lookup_for_display (d, w)
84#define GDK_KEY_g GDK_g
85#endif
86
72#define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x)) 87#define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x))
73 88
89/* Get the current value of the range, truncated to an integer. */
90static int
91int_gtk_range_get_value (GtkRange *range)
92{
93 return gtk_range_get_value (range);
94}
95
74 96
75/*********************************************************************** 97/***********************************************************************
76 Display handling functions 98 Display handling functions
@@ -88,7 +110,7 @@ static GdkDisplay *gdpy_def;
88static void 110static void
89xg_set_screen (GtkWidget *w, FRAME_PTR f) 111xg_set_screen (GtkWidget *w, FRAME_PTR f)
90{ 112{
91 if (FRAME_X_DISPLAY (f) != GDK_DISPLAY ()) 113 if (FRAME_X_DISPLAY (f) != DEFAULT_GDK_DISPLAY ())
92 { 114 {
93 GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); 115 GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
94 GdkScreen *gscreen = gdk_display_get_default_screen (gdpy); 116 GdkScreen *gscreen = gdk_display_get_default_screen (gdpy);
@@ -229,29 +251,55 @@ xg_create_default_cursor (Display *dpy)
229 return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR); 251 return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR);
230} 252}
231 253
254static GdkPixbuf *
255xg_get_pixbuf_from_pixmap (FRAME_PTR f, Pixmap pix)
256{
257 int iunused;
258 GdkPixbuf *tmp_buf;
259 Window wunused;
260 unsigned int width, height, uunused;
261 XImage *xim;
262
263 XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused,
264 &width, &height, &uunused, &uunused);
265
266 xim = XGetImage (FRAME_X_DISPLAY (f), pix, 0, 0, width, height,
267 ~0, XYPixmap);
268 if (!xim) return 0;
269
270 tmp_buf = gdk_pixbuf_new_from_data ((guchar *) xim->data,
271 GDK_COLORSPACE_RGB,
272 FALSE,
273 xim->bitmap_unit,
274 (int) width,
275 (int) height,
276 xim->bytes_per_line,
277 NULL,
278 NULL);
279 XDestroyImage (xim);
280 return tmp_buf;
281}
282
232/* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */ 283/* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */
233 284
234static GdkPixbuf * 285static GdkPixbuf *
235xg_get_pixbuf_from_pix_and_mask (GdkPixmap *gpix, 286xg_get_pixbuf_from_pix_and_mask (FRAME_PTR f,
236 GdkPixmap *gmask, 287 Pixmap pix,
237 GdkColormap *cmap) 288 Pixmap mask)
238{ 289{
239 int width, height; 290 int width, height;
240 GdkPixbuf *icon_buf, *tmp_buf; 291 GdkPixbuf *icon_buf, *tmp_buf;
241 292
242 gdk_drawable_get_size (gpix, &width, &height); 293 tmp_buf = xg_get_pixbuf_from_pixmap (f, pix);
243 tmp_buf = gdk_pixbuf_get_from_drawable (NULL, gpix, cmap,
244 0, 0, 0, 0, width, height);
245 icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0); 294 icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0);
246 g_object_unref (G_OBJECT (tmp_buf)); 295 g_object_unref (G_OBJECT (tmp_buf));
247 296
248 if (gmask) 297 width = gdk_pixbuf_get_width (icon_buf);
298 height = gdk_pixbuf_get_height (icon_buf);
299
300 if (mask)
249 { 301 {
250 GdkPixbuf *mask_buf = gdk_pixbuf_get_from_drawable (NULL, 302 GdkPixbuf *mask_buf = xg_get_pixbuf_from_pixmap (f, mask);
251 gmask,
252 NULL,
253 0, 0, 0, 0,
254 width, height);
255 guchar *pixels = gdk_pixbuf_get_pixels (icon_buf); 303 guchar *pixels = gdk_pixbuf_get_pixels (icon_buf);
256 guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf); 304 guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf);
257 int rowstride = gdk_pixbuf_get_rowstride (icon_buf); 305 int rowstride = gdk_pixbuf_get_rowstride (icon_buf);
@@ -316,10 +364,6 @@ xg_get_image_for_pixmap (FRAME_PTR f,
316 GtkWidget *widget, 364 GtkWidget *widget,
317 GtkImage *old_widget) 365 GtkImage *old_widget)
318{ 366{
319 GdkPixmap *gpix;
320 GdkPixmap *gmask;
321 GdkDisplay *gdpy;
322 GdkColormap *cmap;
323 GdkPixbuf *icon_buf; 367 GdkPixbuf *icon_buf;
324 368
325 /* If we have a file, let GTK do all the image handling. 369 /* If we have a file, let GTK do all the image handling.
@@ -347,10 +391,6 @@ xg_get_image_for_pixmap (FRAME_PTR f,
347 on a monochrome display, and sometimes bad on all displays with 391 on a monochrome display, and sometimes bad on all displays with
348 certain themes. */ 392 certain themes. */
349 393
350 gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
351 gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap);
352 gmask = img->mask ? gdk_pixmap_foreign_new_for_display (gdpy, img->mask) : 0;
353
354 /* This is a workaround to make icons look good on pseudo color 394 /* This is a workaround to make icons look good on pseudo color
355 displays. Apparently GTK expects the images to have an alpha 395 displays. Apparently GTK expects the images to have an alpha
356 channel. If they don't, insensitive and activated icons will 396 channel. If they don't, insensitive and activated icons will
@@ -360,18 +400,17 @@ xg_get_image_for_pixmap (FRAME_PTR f,
360 not associated with the img->pixmap. The img->pixmap may be removed 400 not associated with the img->pixmap. The img->pixmap may be removed
361 by clearing the image cache and then the tool bar redraw fails, since 401 by clearing the image cache and then the tool bar redraw fails, since
362 Gtk+ assumes the pixmap is always there. */ 402 Gtk+ assumes the pixmap is always there. */
363 cmap = gtk_widget_get_colormap (widget); 403 icon_buf = xg_get_pixbuf_from_pix_and_mask (f, img->pixmap, img->mask);
364 icon_buf = xg_get_pixbuf_from_pix_and_mask (gpix, gmask, cmap);
365 404
366 if (! old_widget) 405 if (icon_buf)
367 old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf)); 406 {
368 else 407 if (! old_widget)
369 gtk_image_set_from_pixbuf (old_widget, icon_buf); 408 old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf));
370 409 else
371 g_object_unref (G_OBJECT (icon_buf)); 410 gtk_image_set_from_pixbuf (old_widget, icon_buf);
372 411
373 g_object_unref (G_OBJECT (gpix)); 412 g_object_unref (G_OBJECT (icon_buf));
374 if (gmask) g_object_unref (G_OBJECT (gmask)); 413 }
375 414
376 return GTK_WIDGET (old_widget); 415 return GTK_WIDGET (old_widget);
377} 416}
@@ -455,22 +494,22 @@ get_utf8_string (const char *str)
455 gsize bytes_written; 494 gsize bytes_written;
456 unsigned char *p = (unsigned char *)str; 495 unsigned char *p = (unsigned char *)str;
457 char *cp, *up; 496 char *cp, *up;
458 GError *error = NULL; 497 GError *err = NULL;
459 498
460 while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read, 499 while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
461 &bytes_written, &error)) 500 &bytes_written, &err))
462 && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE) 501 && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
463 { 502 {
464 ++nr_bad; 503 ++nr_bad;
465 p += bytes_written+1; 504 p += bytes_written+1;
466 g_error_free (error); 505 g_error_free (err);
467 error = NULL; 506 err = NULL;
468 } 507 }
469 508
470 if (error) 509 if (err)
471 { 510 {
472 g_error_free (error); 511 g_error_free (err);
473 error = NULL; 512 err = NULL;
474 } 513 }
475 if (cp) g_free (cp); 514 if (cp) g_free (cp);
476 515
@@ -478,16 +517,16 @@ get_utf8_string (const char *str)
478 p = (unsigned char *)str; 517 p = (unsigned char *)str;
479 518
480 while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read, 519 while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
481 &bytes_written, &error)) 520 &bytes_written, &err))
482 && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE) 521 && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
483 { 522 {
484 strncpy (up, (char *)p, bytes_written); 523 strncpy (up, (char *)p, bytes_written);
485 sprintf (up + bytes_written, "\\%03o", p[bytes_written]); 524 sprintf (up + bytes_written, "\\%03o", p[bytes_written]);
486 up[bytes_written+4] = '\0'; 525 up[bytes_written+4] = '\0';
487 up += bytes_written+4; 526 up += bytes_written+4;
488 p += bytes_written+1; 527 p += bytes_written+1;
489 g_error_free (error); 528 g_error_free (err);
490 error = NULL; 529 err = NULL;
491 } 530 }
492 531
493 if (cp) 532 if (cp)
@@ -495,10 +534,10 @@ get_utf8_string (const char *str)
495 strcat (utf8_str, cp); 534 strcat (utf8_str, cp);
496 g_free (cp); 535 g_free (cp);
497 } 536 }
498 if (error) 537 if (err)
499 { 538 {
500 g_error_free (error); 539 g_error_free (err);
501 error = NULL; 540 err = NULL;
502 } 541 }
503 } 542 }
504 return utf8_str; 543 return utf8_str;
@@ -514,28 +553,43 @@ xg_check_special_colors (struct frame *f,
514 XColor *color) 553 XColor *color)
515{ 554{
516 int success_p = 0; 555 int success_p = 0;
517 if (FRAME_GTK_WIDGET (f)) 556 int get_bg = strcmp ("gtk_selection_bg_color", color_name) == 0;
518 { 557 int get_fg = !get_bg && strcmp ("gtk_selection_fg_color", color_name) == 0;
519 if (strcmp ("gtk_selection_bg_color", color_name) == 0)
520 {
521 GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
522 color->red = gsty->bg[GTK_STATE_SELECTED].red;
523 color->green = gsty->bg[GTK_STATE_SELECTED].green;
524 color->blue = gsty->bg[GTK_STATE_SELECTED].blue;
525 color->pixel = gsty->bg[GTK_STATE_SELECTED].pixel;
526 success_p = 1;
527 }
528 else if (strcmp ("gtk_selection_fg_color", color_name) == 0)
529 {
530 GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
531 color->red = gsty->fg[GTK_STATE_SELECTED].red;
532 color->green = gsty->fg[GTK_STATE_SELECTED].green;
533 color->blue = gsty->fg[GTK_STATE_SELECTED].blue;
534 color->pixel = gsty->fg[GTK_STATE_SELECTED].pixel;
535 success_p = 1;
536 }
537 }
538 558
559 if (! FRAME_GTK_WIDGET (f) || ! (get_bg || get_fg))
560 return success_p;
561
562 BLOCK_INPUT;
563 {
564#ifdef HAVE_GTK3
565 GtkStyleContext *gsty
566 = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
567 GdkRGBA col;
568 char buf[64];
569 int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED;
570 if (get_fg)
571 gtk_style_context_get_color (gsty, state, &col);
572 else
573 gtk_style_context_get_background_color (gsty, state, &col);
574
575 sprintf (buf, "rgbi:%lf/%lf/%lf", col.red, col.green, col.blue);
576 success_p = XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
577 buf, color);
578#else
579 GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
580 GdkColor *grgb = get_bg
581 ? &gsty->bg[GTK_STATE_SELECTED]
582 : &gsty->fg[GTK_STATE_SELECTED];
583
584 color->red = grgb->red;
585 color->green = grgb->green;
586 color->blue = grgb->blue;
587 color->pixel = grgb->pixel;
588 success_p = 1;
589#endif
590
591 }
592 UNBLOCK_INPUT;
539 return success_p; 593 return success_p;
540} 594}
541 595
@@ -629,7 +683,7 @@ xg_prepare_tooltip (FRAME_PTR f,
629 encoded_string = ENCODE_UTF_8 (string); 683 encoded_string = ENCODE_UTF_8 (string);
630 widget = GTK_WIDGET (x->ttip_lbl); 684 widget = GTK_WIDGET (x->ttip_lbl);
631 gwin = gtk_widget_get_window (GTK_WIDGET (x->ttip_window)); 685 gwin = gtk_widget_get_window (GTK_WIDGET (x->ttip_window));
632 screen = gdk_drawable_get_screen (gwin); 686 screen = gdk_window_get_screen (gwin);
633 settings = gtk_settings_get_for_screen (screen); 687 settings = gtk_settings_get_for_screen (screen);
634 g_object_get (settings, "gtk-enable-tooltips", &tt_enabled, NULL); 688 g_object_get (settings, "gtk-enable-tooltips", &tt_enabled, NULL);
635 if (tt_enabled) 689 if (tt_enabled)
@@ -650,7 +704,7 @@ xg_prepare_tooltip (FRAME_PTR f,
650 gtk_tooltip_set_custom (x->ttip_widget, widget); 704 gtk_tooltip_set_custom (x->ttip_widget, widget);
651 705
652 gtk_tooltip_set_text (x->ttip_widget, SDATA (encoded_string)); 706 gtk_tooltip_set_text (x->ttip_widget, SDATA (encoded_string));
653 gtk_widget_size_request (GTK_WIDGET (x->ttip_window), &req); 707 gtk_widget_get_preferred_size (GTK_WIDGET (x->ttip_window), NULL, &req);
654 if (width) *width = req.width; 708 if (width) *width = req.width;
655 if (height) *height = req.height; 709 if (height) *height = req.height;
656 710
@@ -696,7 +750,7 @@ xg_hide_tooltip (FRAME_PTR f)
696 if (g_object_get_data (G_OBJECT (win), "restore-tt")) 750 if (g_object_get_data (G_OBJECT (win), "restore-tt"))
697 { 751 {
698 GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win)); 752 GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win));
699 GdkScreen *screen = gdk_drawable_get_screen (gwin); 753 GdkScreen *screen = gdk_window_get_screen (gwin);
700 GtkSettings *settings = gtk_settings_get_for_screen (screen); 754 GtkSettings *settings = gtk_settings_get_for_screen (screen);
701 g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL); 755 g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
702 } 756 }
@@ -797,7 +851,7 @@ xg_frame_resized (FRAME_PTR f, int pixelwidth, int pixelheight)
797 if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f))) 851 if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f)))
798 gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)), 852 gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
799 0, 0, 853 0, 0,
800 &pixelwidth, &pixelheight, 0); 854 &pixelwidth, &pixelheight);
801 else return; 855 else return;
802 } 856 }
803 857
@@ -910,8 +964,8 @@ xg_win_to_widget (Display *dpy, Window wdesc)
910 964
911 BLOCK_INPUT; 965 BLOCK_INPUT;
912 966
913 gdkwin = gdk_xid_table_lookup_for_display (gdk_x11_lookup_xdisplay (dpy), 967 gdkwin = gdk_x11_window_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
914 wdesc); 968 wdesc);
915 if (gdkwin) 969 if (gdkwin)
916 { 970 {
917 GdkEvent event; 971 GdkEvent event;
@@ -923,14 +977,29 @@ xg_win_to_widget (Display *dpy, Window wdesc)
923 return gwdesc; 977 return gwdesc;
924} 978}
925 979
926/* Fill in the GdkColor C so that it represents PIXEL. 980/* Set the background of widget W to PIXEL. */
927 W is the widget that color will be used for. Used to find colormap. */
928 981
929static void 982static void
930xg_pix_to_gcolor (GtkWidget *w, long unsigned int pixel, GdkColor *c) 983xg_set_widget_bg (FRAME_PTR f, GtkWidget *w, long unsigned int pixel)
931{ 984{
985#ifdef HAVE_GTK3
986 GdkRGBA bg;
987 XColor xbg;
988 xbg.pixel = pixel;
989 if (XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &xbg))
990 {
991 bg.red = (double)xbg.red/65536.0;
992 bg.green = (double)xbg.green/65536.0;
993 bg.blue = (double)xbg.blue/65536.0;
994 bg.alpha = 1.0;
995 gtk_widget_override_background_color (w, GTK_STATE_FLAG_NORMAL, &bg);
996 }
997#else
998 GdkColor bg;
932 GdkColormap *map = gtk_widget_get_colormap (w); 999 GdkColormap *map = gtk_widget_get_colormap (w);
933 gdk_colormap_query_color (map, pixel, c); 1000 gdk_colormap_query_color (map, pixel, &bg);
1001 gtk_widget_modify_bg (FRAME_GTK_WIDGET (f), GTK_STATE_NORMAL, &bg);
1002#endif
934} 1003}
935 1004
936/* Callback called when the gtk theme changes. 1005/* Callback called when the gtk theme changes.
@@ -953,6 +1022,28 @@ style_changed_cb (GObject *go,
953 kbd_buffer_store_event (&event); 1022 kbd_buffer_store_event (&event);
954} 1023}
955 1024
1025/* Called when a delete-event occurs on WIDGET. */
1026
1027static gboolean
1028delete_cb (GtkWidget *widget,
1029 GdkEvent *event,
1030 gpointer user_data)
1031{
1032#ifdef HAVE_GTK3
1033 /* The event doesn't arrive in the normal event loop. Send event
1034 here. */
1035 FRAME_PTR f = (FRAME_PTR) user_data;
1036 struct input_event ie;
1037
1038 EVENT_INIT (ie);
1039 ie.kind = DELETE_WINDOW_EVENT;
1040 XSETFRAME (ie.frame_or_window, f);
1041 kbd_buffer_store_event (&ie);
1042#endif
1043
1044 return TRUE;
1045}
1046
956/* Create and set up the GTK widgets for frame F. 1047/* Create and set up the GTK widgets for frame F.
957 Return 0 if creation failed, non-zero otherwise. */ 1048 Return 0 if creation failed, non-zero otherwise. */
958 1049
@@ -962,7 +1053,6 @@ xg_create_frame_widgets (FRAME_PTR f)
962 GtkWidget *wtop; 1053 GtkWidget *wtop;
963 GtkWidget *wvbox, *whbox; 1054 GtkWidget *wvbox, *whbox;
964 GtkWidget *wfixed; 1055 GtkWidget *wfixed;
965 GdkColor bg;
966 GtkRcStyle *style; 1056 GtkRcStyle *style;
967 char *title = 0; 1057 char *title = 0;
968 1058
@@ -1029,7 +1119,7 @@ xg_create_frame_widgets (FRAME_PTR f)
1029 /* Add callback to do nothing on WM_DELETE_WINDOW. The default in 1119 /* Add callback to do nothing on WM_DELETE_WINDOW. The default in
1030 GTK is to destroy the widget. We want Emacs to do that instead. */ 1120 GTK is to destroy the widget. We want Emacs to do that instead. */
1031 g_signal_connect (G_OBJECT (wtop), "delete-event", 1121 g_signal_connect (G_OBJECT (wtop), "delete-event",
1032 G_CALLBACK (gtk_true), 0); 1122 G_CALLBACK (delete_cb), f);
1033 1123
1034 /* Convert our geometry parameters into a geometry string 1124 /* Convert our geometry parameters into a geometry string
1035 and specify it. 1125 and specify it.
@@ -1057,9 +1147,9 @@ xg_create_frame_widgets (FRAME_PTR f)
1057 1147
1058 /* Since GTK clears its window by filling with the background color, 1148 /* Since GTK clears its window by filling with the background color,
1059 we must keep X and GTK background in sync. */ 1149 we must keep X and GTK background in sync. */
1060 xg_pix_to_gcolor (wfixed, FRAME_BACKGROUND_PIXEL (f), &bg); 1150 xg_set_widget_bg (f, wfixed, FRAME_BACKGROUND_PIXEL (f));
1061 gtk_widget_modify_bg (wfixed, GTK_STATE_NORMAL, &bg);
1062 1151
1152#ifndef HAVE_GTK3
1063 /* Also, do not let any background pixmap to be set, this looks very 1153 /* Also, do not let any background pixmap to be set, this looks very
1064 bad as Emacs overwrites the background pixmap with its own idea 1154 bad as Emacs overwrites the background pixmap with its own idea
1065 of background color. */ 1155 of background color. */
@@ -1068,6 +1158,9 @@ xg_create_frame_widgets (FRAME_PTR f)
1068 /* Must use g_strdup because gtk_widget_modify_style does g_free. */ 1158 /* Must use g_strdup because gtk_widget_modify_style does g_free. */
1069 style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("<none>"); 1159 style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("<none>");
1070 gtk_widget_modify_style (wfixed, style); 1160 gtk_widget_modify_style (wfixed, style);
1161#else
1162 gtk_widget_set_can_focus (wfixed, TRUE);
1163#endif
1071 1164
1072#ifdef USE_GTK_TOOLTIP 1165#ifdef USE_GTK_TOOLTIP
1073 /* Steal a tool tip window we can move ourselves. */ 1166 /* Steal a tool tip window we can move ourselves. */
@@ -1104,7 +1197,9 @@ xg_free_frame_widgets (FRAME_PTR f)
1104{ 1197{
1105 if (FRAME_GTK_OUTER_WIDGET (f)) 1198 if (FRAME_GTK_OUTER_WIDGET (f))
1106 { 1199 {
1200#ifdef USE_GTK_TOOLTIP
1107 struct x_output *x = f->output_data.x; 1201 struct x_output *x = f->output_data.x;
1202#endif
1108 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); 1203 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
1109 FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */ 1204 FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
1110 FRAME_GTK_OUTER_WIDGET (f) = 0; 1205 FRAME_GTK_OUTER_WIDGET (f) = 0;
@@ -1224,11 +1319,8 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
1224{ 1319{
1225 if (FRAME_GTK_WIDGET (f)) 1320 if (FRAME_GTK_WIDGET (f))
1226 { 1321 {
1227 GdkColor gdk_bg;
1228
1229 BLOCK_INPUT; 1322 BLOCK_INPUT;
1230 xg_pix_to_gcolor (FRAME_GTK_WIDGET (f), bg, &gdk_bg); 1323 xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f));
1231 gtk_widget_modify_bg (FRAME_GTK_WIDGET (f), GTK_STATE_NORMAL, &gdk_bg);
1232 UNBLOCK_INPUT; 1324 UNBLOCK_INPUT;
1233 } 1325 }
1234} 1326}
@@ -1240,11 +1332,10 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
1240void 1332void
1241xg_set_frame_icon (FRAME_PTR f, Pixmap icon_pixmap, Pixmap icon_mask) 1333xg_set_frame_icon (FRAME_PTR f, Pixmap icon_pixmap, Pixmap icon_mask)
1242{ 1334{
1243 GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); 1335 GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (f,
1244 GdkPixmap *gpix = gdk_pixmap_foreign_new_for_display (gdpy, icon_pixmap); 1336 icon_pixmap,
1245 GdkPixmap *gmask = gdk_pixmap_foreign_new_for_display (gdpy, icon_mask); 1337 icon_mask);
1246 GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (gpix, gmask, NULL); 1338 if (gp)
1247
1248 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), gp); 1339 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), gp);
1249} 1340}
1250 1341
@@ -1326,8 +1417,6 @@ create_dialog (widget_value *wv,
1326 GtkDialog *wd = GTK_DIALOG (wdialog); 1417 GtkDialog *wd = GTK_DIALOG (wdialog);
1327 GtkBox *cur_box = GTK_BOX (gtk_dialog_get_action_area (wd)); 1418 GtkBox *cur_box = GTK_BOX (gtk_dialog_get_action_area (wd));
1328 widget_value *item; 1419 widget_value *item;
1329 GtkWidget *wvbox;
1330 GtkWidget *whbox_up;
1331 GtkWidget *whbox_down; 1420 GtkWidget *whbox_down;
1332 1421
1333 /* If the number of buttons is greater than 4, make two rows of buttons 1422 /* If the number of buttons is greater than 4, make two rows of buttons
@@ -1343,8 +1432,8 @@ create_dialog (widget_value *wv,
1343 1432
1344 if (make_two_rows) 1433 if (make_two_rows)
1345 { 1434 {
1346 wvbox = gtk_vbox_new (TRUE, button_spacing); 1435 GtkWidget *wvbox = gtk_vbox_new (TRUE, button_spacing);
1347 whbox_up = gtk_hbox_new (FALSE, 0); 1436 GtkWidget *whbox_up = gtk_hbox_new (FALSE, 0);
1348 whbox_down = gtk_hbox_new (FALSE, 0); 1437 whbox_down = gtk_hbox_new (FALSE, 0);
1349 1438
1350 gtk_box_pack_start (cur_box, wvbox, FALSE, FALSE, 0); 1439 gtk_box_pack_start (cur_box, wvbox, FALSE, FALSE, 0);
@@ -1381,7 +1470,7 @@ create_dialog (widget_value *wv,
1381 /* Try to make dialog look better. Must realize first so 1470 /* Try to make dialog look better. Must realize first so
1382 the widget can calculate the size it needs. */ 1471 the widget can calculate the size it needs. */
1383 gtk_widget_realize (w); 1472 gtk_widget_realize (w);
1384 gtk_widget_size_request (w, &req); 1473 gtk_widget_get_preferred_size (w, NULL, &req);
1385 gtk_box_set_spacing (wvbox, req.height); 1474 gtk_box_set_spacing (wvbox, req.height);
1386 if (item->value && strlen (item->value) > 0) 1475 if (item->value && strlen (item->value) > 0)
1387 button_spacing = 2*req.width/strlen (item->value); 1476 button_spacing = 2*req.width/strlen (item->value);
@@ -1613,7 +1702,7 @@ xg_get_file_with_chooser (FRAME_PTR f,
1613 int mustmatch_p, int only_dir_p, 1702 int mustmatch_p, int only_dir_p,
1614 xg_get_file_func *func) 1703 xg_get_file_func *func)
1615{ 1704{
1616 char message[1024]; 1705 char msgbuf[1024];
1617 1706
1618 GtkWidget *filewin, *wtoggle, *wbox, *wmessage; 1707 GtkWidget *filewin, *wtoggle, *wbox, *wmessage;
1619 GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); 1708 GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
@@ -1649,16 +1738,16 @@ xg_get_file_with_chooser (FRAME_PTR f,
1649 1738
1650 if (x_gtk_file_dialog_help_text) 1739 if (x_gtk_file_dialog_help_text)
1651 { 1740 {
1652 message[0] = '\0'; 1741 msgbuf[0] = '\0';
1653 /* Gtk+ 2.10 has the file name text entry box integrated in the dialog. 1742 /* Gtk+ 2.10 has the file name text entry box integrated in the dialog.
1654 Show the C-l help text only for versions < 2.10. */ 1743 Show the C-l help text only for versions < 2.10. */
1655 if (gtk_check_version (2, 10, 0) && action != GTK_FILE_CHOOSER_ACTION_SAVE) 1744 if (gtk_check_version (2, 10, 0) && action != GTK_FILE_CHOOSER_ACTION_SAVE)
1656 strcat (message, "\nType C-l to display a file name text entry box.\n"); 1745 strcat (msgbuf, "\nType C-l to display a file name text entry box.\n");
1657 strcat (message, "\nIf you don't like this file selector, use the " 1746 strcat (msgbuf, "\nIf you don't like this file selector, use the "
1658 "corresponding\nkey binding or customize " 1747 "corresponding\nkey binding or customize "
1659 "use-file-dialog to turn it off."); 1748 "use-file-dialog to turn it off.");
1660 1749
1661 wmessage = gtk_label_new (message); 1750 wmessage = gtk_label_new (msgbuf);
1662 gtk_widget_show (wmessage); 1751 gtk_widget_show (wmessage);
1663 } 1752 }
1664 1753
@@ -3028,7 +3117,7 @@ menubar_map_cb (GtkWidget *w, gpointer user_data)
3028{ 3117{
3029 GtkRequisition req; 3118 GtkRequisition req;
3030 FRAME_PTR f = (FRAME_PTR) user_data; 3119 FRAME_PTR f = (FRAME_PTR) user_data;
3031 gtk_widget_size_request (w, &req); 3120 gtk_widget_get_preferred_size (w, NULL, &req);
3032 if (FRAME_MENUBAR_HEIGHT (f) != req.height) 3121 if (FRAME_MENUBAR_HEIGHT (f) != req.height)
3033 { 3122 {
3034 FRAME_MENUBAR_HEIGHT (f) = req.height; 3123 FRAME_MENUBAR_HEIGHT (f) = req.height;
@@ -3059,7 +3148,7 @@ xg_update_frame_menubar (FRAME_PTR f)
3059 3148
3060 g_signal_connect (x->menubar_widget, "map", G_CALLBACK (menubar_map_cb), f); 3149 g_signal_connect (x->menubar_widget, "map", G_CALLBACK (menubar_map_cb), f);
3061 gtk_widget_show_all (x->menubar_widget); 3150 gtk_widget_show_all (x->menubar_widget);
3062 gtk_widget_size_request (x->menubar_widget, &req); 3151 gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req);
3063 3152
3064 /* If menu bar doesn't know its height yet, cheat a little so the frame 3153 /* If menu bar doesn't know its height yet, cheat a little so the frame
3065 doesn't jump so much when resized later in menubar_map_cb. */ 3154 doesn't jump so much when resized later in menubar_map_cb. */
@@ -3120,7 +3209,7 @@ xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
3120 return 0; 3209 return 0;
3121 3210
3122 gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); 3211 gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
3123 gw = gdk_xid_table_lookup_for_display (gdpy, event->xbutton.window); 3212 gw = gdk_x11_window_lookup_for_display (gdpy, event->xbutton.window);
3124 if (! gw) return 0; 3213 if (! gw) return 0;
3125 gevent.any.window = gw; 3214 gevent.any.window = gw;
3126 gwdesc = gtk_get_event_widget (&gevent); 3215 gwdesc = gtk_get_event_widget (&gevent);
@@ -3284,8 +3373,12 @@ xg_create_scroll_bar (FRAME_PTR f,
3284{ 3373{
3285 GtkWidget *wscroll; 3374 GtkWidget *wscroll;
3286 GtkWidget *webox; 3375 GtkWidget *webox;
3287 GtkObject *vadj;
3288 int scroll_id; 3376 int scroll_id;
3377#ifdef HAVE_GTK3
3378 GtkAdjustment *vadj;
3379#else
3380 GtkObject *vadj;
3381#endif
3289 3382
3290 /* Page, step increment values are not so important here, they 3383 /* Page, step increment values are not so important here, they
3291 will be corrected in x_set_toolkit_scroll_bar_thumb. */ 3384 will be corrected in x_set_toolkit_scroll_bar_thumb. */
@@ -3295,7 +3388,9 @@ xg_create_scroll_bar (FRAME_PTR f,
3295 wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj)); 3388 wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj));
3296 webox = gtk_event_box_new (); 3389 webox = gtk_event_box_new ();
3297 gtk_widget_set_name (wscroll, scroll_bar_name); 3390 gtk_widget_set_name (wscroll, scroll_bar_name);
3391#ifndef HAVE_GTK3
3298 gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); 3392 gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
3393#endif
3299 g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); 3394 g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
3300 3395
3301 scroll_id = xg_store_widget_in_map (wscroll); 3396 scroll_id = xg_store_widget_in_map (wscroll);
@@ -3474,7 +3569,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
3474 changed = 1; 3569 changed = 1;
3475 } 3570 }
3476 3571
3477 if (changed || (int) gtk_range_get_value (GTK_RANGE (wscroll)) != value) 3572 if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
3478 { 3573 {
3479 BLOCK_INPUT; 3574 BLOCK_INPUT;
3480 3575
@@ -3482,7 +3577,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
3482 ignore_gtk_scrollbar to make the callback do nothing */ 3577 ignore_gtk_scrollbar to make the callback do nothing */
3483 xg_ignore_gtk_scrollbar = 1; 3578 xg_ignore_gtk_scrollbar = 1;
3484 3579
3485 if ((int) gtk_range_get_value (GTK_RANGE (wscroll)) != value) 3580 if (int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
3486 gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value); 3581 gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value);
3487 else if (changed) 3582 else if (changed)
3488 gtk_adjustment_changed (adj); 3583 gtk_adjustment_changed (adj);
@@ -3578,8 +3673,8 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
3578{ 3673{
3579 /* The EMACS_INT cast avoids a warning. */ 3674 /* The EMACS_INT cast avoids a warning. */
3580 int idx = (int) (EMACS_INT) client_data; 3675 int idx = (int) (EMACS_INT) client_data;
3581 int mod = (int) (EMACS_INT) g_object_get_data (G_OBJECT (w), 3676 gpointer gmod = g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER);
3582 XG_TOOL_BAR_LAST_MODIFIER); 3677 int mod = (int) (EMACS_INT) gmod;
3583 3678
3584 FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA); 3679 FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
3585 Lisp_Object key, frame; 3680 Lisp_Object key, frame;
@@ -3793,8 +3888,8 @@ xg_tool_bar_detach_callback (GtkHandleBox *wbox,
3793 { 3888 {
3794 GtkRequisition req, req2; 3889 GtkRequisition req, req2;
3795 FRAME_X_OUTPUT (f)->toolbar_detached = 1; 3890 FRAME_X_OUTPUT (f)->toolbar_detached = 1;
3796 gtk_widget_size_request (GTK_WIDGET (wbox), &req); 3891 gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req);
3797 gtk_widget_size_request (w, &req2); 3892 gtk_widget_get_preferred_size (w, NULL, &req2);
3798 req.width -= req2.width; 3893 req.width -= req2.width;
3799 req.height -= req2.height; 3894 req.height -= req2.height;
3800 if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0) 3895 if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
@@ -3828,8 +3923,8 @@ xg_tool_bar_attach_callback (GtkHandleBox *wbox,
3828 { 3923 {
3829 GtkRequisition req, req2; 3924 GtkRequisition req, req2;
3830 FRAME_X_OUTPUT (f)->toolbar_detached = 0; 3925 FRAME_X_OUTPUT (f)->toolbar_detached = 0;
3831 gtk_widget_size_request (GTK_WIDGET (wbox), &req); 3926 gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req);
3832 gtk_widget_size_request (w, &req2); 3927 gtk_widget_get_preferred_size (w, NULL, &req2);
3833 req.width += req2.width; 3928 req.width += req2.width;
3834 req.height += req2.height; 3929 req.height += req2.height;
3835 if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0) 3930 if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
@@ -3894,6 +3989,7 @@ xg_tool_bar_help_callback (GtkWidget *w,
3894 3989
3895 Returns FALSE to tell GTK to keep processing this event. */ 3990 Returns FALSE to tell GTK to keep processing this event. */
3896 3991
3992#ifndef HAVE_GTK3
3897static gboolean 3993static gboolean
3898xg_tool_bar_item_expose_callback (GtkWidget *w, 3994xg_tool_bar_item_expose_callback (GtkWidget *w,
3899 GdkEventExpose *event, 3995 GdkEventExpose *event,
@@ -3902,7 +3998,6 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
3902 gint width, height; 3998 gint width, height;
3903 3999
3904 gdk_drawable_get_size (event->window, &width, &height); 4000 gdk_drawable_get_size (event->window, &width, &height);
3905
3906 event->area.x -= width > event->area.width ? width-event->area.width : 0; 4001 event->area.x -= width > event->area.width ? width-event->area.width : 0;
3907 event->area.y -= height > event->area.height ? height-event->area.height : 0; 4002 event->area.y -= height > event->area.height ? height-event->area.height : 0;
3908 4003
@@ -3914,6 +4009,7 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
3914 4009
3915 return FALSE; 4010 return FALSE;
3916} 4011}
4012#endif
3917 4013
3918#ifdef HAVE_GTK_ORIENTABLE_SET_ORIENTATION 4014#ifdef HAVE_GTK_ORIENTABLE_SET_ORIENTATION
3919#define toolbar_set_orientation(w, o) \ 4015#define toolbar_set_orientation(w, o) \
@@ -4063,13 +4159,14 @@ xg_make_tool_item (FRAME_PTR f,
4063 4159
4064 g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f); 4160 g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f);
4065 4161
4162#ifndef HAVE_GTK3
4066 /* Catch expose events to overcome an annoying redraw bug, see 4163 /* Catch expose events to overcome an annoying redraw bug, see
4067 comment for xg_tool_bar_item_expose_callback. */ 4164 comment for xg_tool_bar_item_expose_callback. */
4068 g_signal_connect (G_OBJECT (ti), 4165 g_signal_connect (G_OBJECT (ti),
4069 "expose-event", 4166 "expose-event",
4070 G_CALLBACK (xg_tool_bar_item_expose_callback), 4167 G_CALLBACK (xg_tool_bar_item_expose_callback),
4071 0); 4168 0);
4072 4169#endif
4073 gtk_tool_item_set_homogeneous (ti, FALSE); 4170 gtk_tool_item_set_homogeneous (ti, FALSE);
4074 4171
4075 /* Callback to save modifyer mask (Shift/Control, etc). GTK makes 4172 /* Callback to save modifyer mask (Shift/Control, etc). GTK makes
@@ -4128,9 +4225,9 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
4128 } 4225 }
4129 else 4226 else
4130 { 4227 {
4131 Pixmap old_img 4228 gpointer gold_img = g_object_get_data (G_OBJECT (wimage),
4132 = (Pixmap) g_object_get_data (G_OBJECT (wimage), 4229 XG_TOOL_BAR_IMAGE_DATA);
4133 XG_TOOL_BAR_IMAGE_DATA); 4230 Pixmap old_img = (Pixmap) gold_img;
4134 if (old_img != img->pixmap) 4231 if (old_img != img->pixmap)
4135 return 1; 4232 return 1;
4136 } 4233 }
@@ -4153,7 +4250,7 @@ xg_update_tool_bar_sizes (FRAME_PTR f)
4153 GtkRequisition req; 4250 GtkRequisition req;
4154 int nl = 0, nr = 0, nt = 0, nb = 0; 4251 int nl = 0, nr = 0, nt = 0, nb = 0;
4155 4252
4156 gtk_widget_size_request (GTK_WIDGET (x->handlebox_widget), &req); 4253 gtk_widget_get_preferred_size (GTK_WIDGET (x->handlebox_widget), NULL, &req);
4157 if (x->toolbar_in_hbox) 4254 if (x->toolbar_in_hbox)
4158 { 4255 {
4159 int pos; 4256 int pos;
@@ -4203,7 +4300,6 @@ update_frame_tool_bar (FRAME_PTR f)
4203 GtkToolItem *ti; 4300 GtkToolItem *ti;
4204 GtkTextDirection dir; 4301 GtkTextDirection dir;
4205 int pack_tool_bar = x->handlebox_widget == NULL; 4302 int pack_tool_bar = x->handlebox_widget == NULL;
4206
4207 Lisp_Object style; 4303 Lisp_Object style;
4208 int text_image, horiz; 4304 int text_image, horiz;
4209 4305
@@ -4551,13 +4647,13 @@ xg_initialize (void)
4551 /* Make dialogs close on C-g. Since file dialog inherits from 4647 /* Make dialogs close on C-g. Since file dialog inherits from
4552 dialog, this works for them also. */ 4648 dialog, this works for them also. */
4553 binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_DIALOG)); 4649 binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_DIALOG));
4554 gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK, 4650 gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
4555 "close", 0); 4651 "close", 0);
4556 4652
4557 /* Make menus close on C-g. */ 4653 /* Make menus close on C-g. */
4558 binding_set = gtk_binding_set_by_class (g_type_class_ref 4654 binding_set = gtk_binding_set_by_class (g_type_class_ref
4559 (GTK_TYPE_MENU_SHELL)); 4655 (GTK_TYPE_MENU_SHELL));
4560 gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK, 4656 gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
4561 "cancel", 0); 4657 "cancel", 0);
4562} 4658}
4563 4659