1 /* Functions for creating and updating GTK widgets.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
29 #include "blockinput.h"
30 #include "syssignal.h"
34 #include "termhooks.h"
38 #include <gdk/gdkkeysyms.h>
41 #include <X11/Xft/Xft.h>
44 #define FRAME_TOTAL_PIXEL_HEIGHT(f) \
45 (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
47 /* Avoid "differ in sign" warnings */
48 #define SSDATA(x) ((char *) SDATA (x))
51 /***********************************************************************
52 Display handling functions
53 ***********************************************************************/
55 #ifdef HAVE_GTK_MULTIDISPLAY
57 /* Keep track of the default display, or NULL if there is none. Emacs
58 may close all its displays. */
60 static GdkDisplay
*gdpy_def
;
62 /* Return the GdkDisplay that corresponds to the X display DPY. */
65 xg_get_gdk_display (dpy
)
68 return gdk_x11_lookup_xdisplay (dpy
);
71 /* When the GTK widget W is to be created on a display for F that
72 is not the default display, set the display for W.
73 W can be a GtkMenu or a GtkWindow widget. */
80 if (FRAME_X_DISPLAY (f
) != GDK_DISPLAY ())
82 GdkDisplay
*gdpy
= gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f
));
83 GdkScreen
*gscreen
= gdk_display_get_default_screen (gdpy
);
86 gtk_menu_set_screen (GTK_MENU (w
), gscreen
);
88 gtk_window_set_screen (GTK_WINDOW (w
), gscreen
);
93 #else /* not HAVE_GTK_MULTIDISPLAY */
95 /* Make some defines so we can use the GTK 2.2 functions when
96 compiling with GTK 2.0. */
98 #define xg_set_screen(w, f)
99 #define gdk_xid_table_lookup_for_display(dpy, w) gdk_xid_table_lookup (w)
100 #define gdk_pixmap_foreign_new_for_display(dpy, p) gdk_pixmap_foreign_new (p)
101 #define gdk_cursor_new_for_display(dpy, c) gdk_cursor_new (c)
102 #define gdk_x11_lookup_xdisplay(dpy) 0
103 #define GdkDisplay void
105 #endif /* not HAVE_GTK_MULTIDISPLAY */
107 /* Open a display named by DISPLAY_NAME. The display is returned in *DPY.
108 *DPY is set to NULL if the display can't be opened.
110 Returns non-zero if display could be opened, zero if display could not
111 be opened, and less than zero if the GTK version doesn't support
115 xg_display_open (display_name
, dpy
)
119 #ifdef HAVE_GTK_MULTIDISPLAY
122 gdpy
= gdk_display_open (display_name
);
123 if (!gdpy_def
&& gdpy
)
126 gdk_display_manager_set_default_display (gdk_display_manager_get (),
130 *dpy
= gdpy
? GDK_DISPLAY_XDISPLAY (gdpy
) : NULL
;
133 #else /* not HAVE_GTK_MULTIDISPLAY */
136 #endif /* not HAVE_GTK_MULTIDISPLAY */
140 /* Close display DPY. */
143 xg_display_close (Display
*dpy
)
145 #ifdef HAVE_GTK_MULTIDISPLAY
146 GdkDisplay
*gdpy
= gdk_x11_lookup_xdisplay (dpy
);
148 /* If this is the default display, try to change it before closing.
149 If there is no other display to use, gdpy_def is set to NULL, and
150 the next call to xg_display_open resets the default display. */
151 if (gdk_display_get_default () == gdpy
)
153 struct x_display_info
*dpyinfo
;
154 GdkDisplay
*gdpy_new
= NULL
;
156 /* Find another display. */
157 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
158 if (dpyinfo
->display
!= dpy
)
160 gdpy_new
= gdk_x11_lookup_xdisplay (dpyinfo
->display
);
161 gdk_display_manager_set_default_display (gdk_display_manager_get (),
168 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 10
169 /* GTK 2.2-2.8 has a bug that makes gdk_display_close crash (bug
170 http://bugzilla.gnome.org/show_bug.cgi?id=85715). This way we
171 can continue running, but there will be memory leaks. */
172 g_object_run_dispose (G_OBJECT (gdpy
));
174 /* This seems to be fixed in GTK 2.10. */
175 gdk_display_close (gdpy
);
177 #endif /* HAVE_GTK_MULTIDISPLAY */
181 /***********************************************************************
183 ***********************************************************************/
184 /* The timer for scroll bar repetition and menu bar timeouts.
185 NULL if no timer is started. */
186 static struct atimer
*xg_timer
;
189 /* The next two variables and functions are taken from lwlib. */
190 static widget_value
*widget_value_free_list
;
191 static int malloc_cpt
;
193 /* Allocate a widget_value structure, either by taking one from the
194 widget_value_free_list or by malloc:ing a new one.
196 Return a pointer to the allocated structure. */
199 malloc_widget_value ()
202 if (widget_value_free_list
)
204 wv
= widget_value_free_list
;
205 widget_value_free_list
= wv
->free_list
;
210 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
213 memset (wv
, 0, sizeof (widget_value
));
217 /* This is analogous to free. It frees only what was allocated
218 by malloc_widget_value, and no substructures. */
221 free_widget_value (wv
)
229 /* When the number of already allocated cells is too big,
236 wv
->free_list
= widget_value_free_list
;
237 widget_value_free_list
= wv
;
242 /* Create and return the cursor to be used for popup menus and
243 scroll bars on display DPY. */
246 xg_create_default_cursor (dpy
)
249 GdkDisplay
*gdpy
= gdk_x11_lookup_xdisplay (dpy
);
250 return gdk_cursor_new_for_display (gdpy
, GDK_LEFT_PTR
);
253 /* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */
256 xg_get_pixbuf_from_pix_and_mask (gpix
, gmask
, cmap
)
261 int x
, y
, width
, height
, rowstride
, mask_rowstride
;
262 GdkPixbuf
*icon_buf
, *tmp_buf
;
266 gdk_drawable_get_size (gpix
, &width
, &height
);
267 tmp_buf
= gdk_pixbuf_get_from_drawable (NULL
, gpix
, cmap
,
268 0, 0, 0, 0, width
, height
);
269 icon_buf
= gdk_pixbuf_add_alpha (tmp_buf
, FALSE
, 0, 0, 0);
270 g_object_unref (G_OBJECT (tmp_buf
));
274 GdkPixbuf
*mask_buf
= gdk_pixbuf_get_from_drawable (NULL
,
279 guchar
*pixels
= gdk_pixbuf_get_pixels (icon_buf
);
280 guchar
*mask_pixels
= gdk_pixbuf_get_pixels (mask_buf
);
281 int rowstride
= gdk_pixbuf_get_rowstride (icon_buf
);
282 int mask_rowstride
= gdk_pixbuf_get_rowstride (mask_buf
);
285 for (y
= 0; y
< height
; ++y
)
287 guchar
*iconptr
, *maskptr
;
290 iconptr
= pixels
+ y
* rowstride
;
291 maskptr
= mask_pixels
+ y
* mask_rowstride
;
293 for (x
= 0; x
< width
; ++x
)
295 /* In a bitmap, RGB is either 255/255/255 or 0/0/0. Checking
296 just R is sufficient. */
298 iconptr
[3] = 0; /* 0, 1, 2 is R, G, B. 3 is alpha. */
300 iconptr
+= rowstride
/width
;
301 maskptr
+= mask_rowstride
/width
;
305 g_object_unref (G_OBJECT (mask_buf
));
312 file_for_image (image
)
315 Lisp_Object specified_file
= Qnil
;
317 extern Lisp_Object QCfile
;
319 for (tail
= XCDR (image
);
320 NILP (specified_file
) && CONSP (tail
) && CONSP (XCDR (tail
));
321 tail
= XCDR (XCDR (tail
)))
322 if (EQ (XCAR (tail
), QCfile
))
323 specified_file
= XCAR (XCDR (tail
));
325 return specified_file
;
328 /* For the image defined in IMG, make and return a GtkImage. For displays with
329 8 planes or less we must make a GdkPixbuf and apply the mask manually.
330 Otherwise the highlightning and dimming the tool bar code in GTK does
331 will look bad. For display with more than 8 planes we just use the
332 pixmap and mask directly. For monochrome displays, GTK doesn't seem
333 able to use external pixmaps, it looks bad whatever we do.
334 The image is defined on the display where frame F is.
335 WIDGET is used to find the GdkColormap to use for the GdkPixbuf.
336 If OLD_WIDGET is NULL, a new widget is constructed and returned.
337 If OLD_WIDGET is not NULL, that widget is modified. */
340 xg_get_image_for_pixmap (f
, img
, widget
, old_widget
)
344 GtkImage
*old_widget
;
352 /* If we have a file, let GTK do all the image handling.
353 This seems to be the only way to make insensitive and activated icons
354 look good in all cases. */
355 Lisp_Object specified_file
= file_for_image (img
->spec
);
358 /* We already loaded the image once before calling this
359 function, so this only fails if the image file has been removed.
360 In that case, use the pixmap already loaded. */
362 if (STRINGP (specified_file
)
363 && STRINGP (file
= x_find_image_file (specified_file
)))
366 old_widget
= GTK_IMAGE (gtk_image_new_from_file (SSDATA (file
)));
368 gtk_image_set_from_file (old_widget
, SSDATA (file
));
370 return GTK_WIDGET (old_widget
);
373 /* No file, do the image handling ourselves. This will look very bad
374 on a monochrome display, and sometimes bad on all displays with
377 gdpy
= gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f
));
378 gpix
= gdk_pixmap_foreign_new_for_display (gdpy
, img
->pixmap
);
379 gmask
= img
->mask
? gdk_pixmap_foreign_new_for_display (gdpy
, img
->mask
) : 0;
381 /* This is a workaround to make icons look good on pseudo color
382 displays. Apparently GTK expects the images to have an alpha
383 channel. If they don't, insensitive and activated icons will
384 look bad. This workaround does not work on monochrome displays,
385 and is strictly not needed on true color/static color displays (i.e.
386 16 bits and higher). But we do it anyway so we get a pixbuf that is
387 not associated with the img->pixmap. The img->pixmap may be removed
388 by clearing the image cache and then the tool bar redraw fails, since
389 Gtk+ assumes the pixmap is always there. */
390 cmap
= gtk_widget_get_colormap (widget
);
391 icon_buf
= xg_get_pixbuf_from_pix_and_mask (gpix
, gmask
, cmap
);
394 old_widget
= GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf
));
396 gtk_image_set_from_pixbuf (old_widget
, icon_buf
);
398 g_object_unref (G_OBJECT (icon_buf
));
400 g_object_unref (G_OBJECT (gpix
));
401 if (gmask
) g_object_unref (G_OBJECT (gmask
));
403 return GTK_WIDGET (old_widget
);
407 /* Set CURSOR on W and all widgets W contain. We must do like this
408 for scroll bars and menu because they create widgets internally,
409 and it is those widgets that are visible. */
412 xg_set_cursor (w
, cursor
)
416 GList
*children
= gdk_window_peek_children (w
->window
);
418 gdk_window_set_cursor (w
->window
, cursor
);
420 /* The scroll bar widget has more than one GDK window (had to look at
421 the source to figure this out), and there is no way to set cursor
422 on widgets in GTK. So we must set the cursor for all GDK windows.
425 for ( ; children
; children
= g_list_next (children
))
426 gdk_window_set_cursor (GDK_WINDOW (children
->data
), cursor
);
429 /* Timer function called when a timeout occurs for xg_timer.
430 This function processes all GTK events in a recursive event loop.
431 This is done because GTK timer events are not seen by Emacs event
432 detection, Emacs only looks for X events. When a scroll bar has the
433 pointer (detected by button press/release events below) an Emacs
434 timer is started, and this function can then check if the GTK timer
435 has expired by calling the GTK event loop.
436 Also, when a menu is active, it has a small timeout before it
437 pops down the sub menu under it. */
440 xg_process_timeouts (timer
)
441 struct atimer
*timer
;
444 /* Ideally we would like to just handle timer events, like the Xt version
445 of this does in xterm.c, but there is no such feature in GTK. */
446 while (gtk_events_pending ())
447 gtk_main_iteration ();
451 /* Start the xg_timer with an interval of 0.1 seconds, if not already started.
452 xg_process_timeouts is called when the timer expires. The timer
453 started is continuous, i.e. runs until xg_stop_timer is called. */
461 EMACS_SET_SECS_USECS (interval
, 0, 100000);
462 xg_timer
= start_atimer (ATIMER_CONTINUOUS
,
469 /* Stop the xg_timer if started. */
476 cancel_atimer (xg_timer
);
481 /* Insert NODE into linked LIST. */
484 xg_list_insert (xg_list_node
*list
, xg_list_node
*node
)
486 xg_list_node
*list_start
= list
->next
;
488 if (list_start
) list_start
->prev
= node
;
489 node
->next
= list_start
;
494 /* Remove NODE from linked LIST. */
497 xg_list_remove (xg_list_node
*list
, xg_list_node
*node
)
499 xg_list_node
*list_start
= list
->next
;
500 if (node
== list_start
)
502 list
->next
= node
->next
;
503 if (list
->next
) list
->next
->prev
= 0;
507 node
->prev
->next
= node
->next
;
508 if (node
->next
) node
->next
->prev
= node
->prev
;
512 /* Allocate and return a utf8 version of STR. If STR is already
513 utf8 or NULL, just return STR.
514 If not, a new string is allocated and the caller must free the result
518 get_utf8_string (str
)
521 char *utf8_str
= str
;
523 if (!str
) return NULL
;
525 /* If not UTF-8, try current locale. */
526 if (!g_utf8_validate (str
, -1, NULL
))
527 utf8_str
= g_locale_to_utf8 (str
, -1, 0, 0, 0);
531 /* Probably some control characters in str. Escape them. */
535 unsigned char *p
= (unsigned char *)str
;
537 GError
*error
= NULL
;
539 while (! (cp
= g_locale_to_utf8 ((char *)p
, -1, &bytes_read
,
540 &bytes_written
, &error
))
541 && error
->code
== G_CONVERT_ERROR_ILLEGAL_SEQUENCE
)
544 p
+= bytes_written
+1;
545 g_error_free (error
);
551 g_error_free (error
);
556 up
= utf8_str
= xmalloc (strlen (str
) + nr_bad
* 4 + 1);
557 p
= (unsigned char *)str
;
559 while (! (cp
= g_locale_to_utf8 ((char *)p
, -1, &bytes_read
,
560 &bytes_written
, &error
))
561 && error
->code
== G_CONVERT_ERROR_ILLEGAL_SEQUENCE
)
563 strncpy (up
, (char *)p
, bytes_written
);
564 sprintf (up
+ bytes_written
, "\\%03o", p
[bytes_written
]);
565 up
[bytes_written
+4] = '\0';
566 up
+= bytes_written
+4;
567 p
+= bytes_written
+1;
568 g_error_free (error
);
574 strcat (utf8_str
, cp
);
579 g_error_free (error
);
588 /***********************************************************************
589 General functions for creating widgets, resizing, events, e.t.c.
590 ***********************************************************************/
592 /* Make a geometry string and pass that to GTK. It seems this is the
593 only way to get geometry position right if the user explicitly
594 asked for a position when starting Emacs.
595 F is the frame we shall set geometry for. */
601 if (f
->size_hint_flags
& USPosition
)
603 int left
= f
->left_pos
;
604 int xneg
= f
->size_hint_flags
& XNegative
;
605 int top
= f
->top_pos
;
606 int yneg
= f
->size_hint_flags
& YNegative
;
614 sprintf (geom_str
, "=%dx%d%c%d%c%d",
615 FRAME_PIXEL_WIDTH (f
),
616 FRAME_TOTAL_PIXEL_HEIGHT (f
),
617 (xneg
? '-' : '+'), left
,
618 (yneg
? '-' : '+'), top
);
620 if (!gtk_window_parse_geometry (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)),
622 fprintf (stderr
, "Failed to parse: '%s'\n", geom_str
);
624 else if (f
->size_hint_flags
& PPosition
)
625 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)),
626 f
->left_pos
, f
->top_pos
);
629 /* Function to handle resize of our frame. As we have a Gtk+ tool bar
630 and a Gtk+ menu bar, we get resize events for the edit part of the
631 frame only. We let Gtk+ deal with the Gtk+ parts.
632 F is the frame to resize.
633 PIXELWIDTH, PIXELHEIGHT is the new size in pixels. */
636 xg_frame_resized (f
, pixelwidth
, pixelheight
)
638 int pixelwidth
, pixelheight
;
642 if (pixelwidth
== -1 && pixelheight
== -1)
644 if (FRAME_GTK_WIDGET (f
) && GTK_WIDGET_MAPPED (FRAME_GTK_WIDGET (f
)))
645 gdk_window_get_geometry(FRAME_GTK_WIDGET (f
)->window
, 0, 0,
646 &pixelwidth
, &pixelheight
, 0);
651 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, pixelheight
);
652 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, pixelwidth
);
654 if (columns
!= FRAME_COLS (f
)
655 || rows
!= FRAME_LINES (f
)
656 || pixelwidth
!= FRAME_PIXEL_WIDTH (f
)
657 || pixelheight
!= FRAME_PIXEL_HEIGHT (f
))
659 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
660 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
662 change_frame_size (f
, rows
, columns
, 0, 1, 0);
663 SET_FRAME_GARBAGED (f
);
664 cancel_mouse_face (f
);
672 gdk_window_process_all_updates ();
674 while (gtk_events_pending ())
676 gtk_main_iteration ();
677 gdk_window_process_all_updates ();
682 /* Resize the outer window of frame F after chainging the height.
683 COLUMNS/ROWS is the size the edit area shall have after the resize. */
686 xg_frame_set_char_size (f
, cols
, rows
)
691 int pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
)
692 + FRAME_MENUBAR_HEIGHT (f
) + FRAME_TOOLBAR_HEIGHT (f
);
695 if (FRAME_PIXEL_HEIGHT (f
) == 0)
698 /* Take into account the size of the scroll bar. Always use the
699 number of columns occupied by the scroll bar here otherwise we
700 might end up with a frame width that is not a multiple of the
701 frame's character width which is bad for vertically split
703 f
->scroll_bar_actual_width
704 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
706 compute_fringe_widths (f
, 0);
708 /* FRAME_TEXT_COLS_TO_PIXEL_WIDTH uses scroll_bar_actual_width, so call it
709 after calculating that value. */
710 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
712 /* Must resize our top level widget. Font size may have changed,
713 but not rows/cols. */
714 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)),
715 pixelwidth
, pixelheight
);
716 x_wm_set_size_hint (f
, 0, 0);
718 /* We can not call change_frame_size for a mapped frame,
719 we can not set pixel width/height either. The window manager may
720 override our resize request, XMonad does this all the time.
721 The best we can do is try to sync, so lisp code sees the updated
722 size as fast as possible.
723 For unmapped windows, we can set rows/cols. When
724 the frame is mapped again we will (hopefully) get the correct size. */
725 if (f
->async_visible
)
729 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
730 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
731 change_frame_size (f
, rows
, cols
, 0, 1, 0);
732 SET_FRAME_GARBAGED (f
);
733 cancel_mouse_face (f
);
737 /* Handle height changes (i.e. add/remove menu/toolbar).
738 The policy is to keep the number of editable lines. */
741 xg_height_changed (f
)
744 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)),
745 FRAME_PIXEL_WIDTH (f
), FRAME_TOTAL_PIXEL_HEIGHT (f
));
746 f
->output_data
.x
->hint_flags
= 0;
747 x_wm_set_size_hint (f
, 0, 0);
750 /* Convert an X Window WSESC on display DPY to its corresponding GtkWidget.
751 Must be done like this, because GtkWidget:s can have "hidden"
752 X Window that aren't accessible.
754 Return 0 if no widget match WDESC. */
757 xg_win_to_widget (dpy
, wdesc
)
762 GtkWidget
*gwdesc
= 0;
766 gdkwin
= gdk_xid_table_lookup_for_display (gdk_x11_lookup_xdisplay (dpy
),
771 event
.any
.window
= gdkwin
;
772 gwdesc
= gtk_get_event_widget (&event
);
779 /* Fill in the GdkColor C so that it represents PIXEL.
780 W is the widget that color will be used for. Used to find colormap. */
783 xg_pix_to_gcolor (w
, pixel
, c
)
788 GdkColormap
*map
= gtk_widget_get_colormap (w
);
789 gdk_colormap_query_color (map
, pixel
, c
);
792 /* Create and set up the GTK widgets for frame F.
793 Return 0 if creation failed, non-zero otherwise. */
796 xg_create_frame_widgets (f
)
809 if (FRAME_X_EMBEDDED_P (f
))
810 wtop
= gtk_plug_new (f
->output_data
.x
->parent_desc
);
812 wtop
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
814 xg_set_screen (wtop
, f
);
816 wvbox
= gtk_vbox_new (FALSE
, 0);
817 wfixed
= gtk_fixed_new (); /* Must have this to place scroll bars */
819 if (! wtop
|| ! wvbox
|| ! wfixed
)
821 if (wtop
) gtk_widget_destroy (wtop
);
822 if (wvbox
) gtk_widget_destroy (wvbox
);
823 if (wfixed
) gtk_widget_destroy (wfixed
);
829 /* Use same names as the Xt port does. I.e. Emacs.pane.emacs by default */
830 gtk_widget_set_name (wtop
, EMACS_CLASS
);
831 gtk_widget_set_name (wvbox
, "pane");
832 gtk_widget_set_name (wfixed
, SSDATA (Vx_resource_name
));
834 /* If this frame has a title or name, set it in the title bar. */
835 if (! NILP (f
->title
)) title
= SSDATA (ENCODE_UTF_8 (f
->title
));
836 else if (! NILP (f
->name
)) title
= SSDATA (ENCODE_UTF_8 (f
->name
));
838 if (title
) gtk_window_set_title (GTK_WINDOW (wtop
), title
);
840 FRAME_GTK_OUTER_WIDGET (f
) = wtop
;
841 FRAME_GTK_WIDGET (f
) = wfixed
;
842 f
->output_data
.x
->vbox_widget
= wvbox
;
844 gtk_fixed_set_has_window (GTK_FIXED (wfixed
), TRUE
);
846 gtk_container_add (GTK_CONTAINER (wtop
), wvbox
);
847 gtk_box_pack_end (GTK_BOX (wvbox
), wfixed
, TRUE
, TRUE
, 0);
849 if (FRAME_EXTERNAL_TOOL_BAR (f
))
850 update_frame_tool_bar (f
);
852 /* We don't want this widget double buffered, because we draw on it
853 with regular X drawing primitives, so from a GTK/GDK point of
854 view, the widget is totally blank. When an expose comes, this
855 will make the widget blank, and then Emacs redraws it. This flickers
856 a lot, so we turn off double buffering. */
857 gtk_widget_set_double_buffered (wfixed
, FALSE
);
859 gtk_window_set_wmclass (GTK_WINDOW (wtop
),
860 SSDATA (Vx_resource_name
),
861 SSDATA (Vx_resource_class
));
863 /* Add callback to do nothing on WM_DELETE_WINDOW. The default in
864 GTK is to destroy the widget. We want Emacs to do that instead. */
865 g_signal_connect (G_OBJECT (wtop
), "delete-event",
866 G_CALLBACK (gtk_true
), 0);
868 /* Convert our geometry parameters into a geometry string
870 GTK will itself handle calculating the real position this way. */
872 int grav
= gtk_window_get_gravity (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
873 f
->win_gravity
= grav
;
875 gtk_widget_add_events (wfixed
,
876 GDK_POINTER_MOTION_MASK
878 | GDK_BUTTON_PRESS_MASK
879 | GDK_BUTTON_RELEASE_MASK
881 | GDK_ENTER_NOTIFY_MASK
882 | GDK_LEAVE_NOTIFY_MASK
883 | GDK_FOCUS_CHANGE_MASK
885 | GDK_VISIBILITY_NOTIFY_MASK
);
887 /* Must realize the windows so the X window gets created. It is used
888 by callers of this function. */
889 gtk_widget_realize (wfixed
);
890 FRAME_X_WINDOW (f
) = GTK_WIDGET_TO_X_WIN (wfixed
);
892 /* Since GTK clears its window by filling with the background color,
893 we must keep X and GTK background in sync. */
894 xg_pix_to_gcolor (wfixed
, FRAME_BACKGROUND_PIXEL (f
), &bg
);
895 gtk_widget_modify_bg (wfixed
, GTK_STATE_NORMAL
, &bg
);
897 /* Also, do not let any background pixmap to be set, this looks very
898 bad as Emacs overwrites the background pixmap with its own idea
899 of background color. */
900 style
= gtk_widget_get_modifier_style (wfixed
);
902 /* Must use g_strdup because gtk_widget_modify_style does g_free. */
903 style
->bg_pixmap_name
[GTK_STATE_NORMAL
] = g_strdup ("<none>");
904 gtk_widget_modify_style (wfixed
, style
);
906 /* GTK does not set any border, and they look bad with GTK. */
907 /* That they look bad is no excuse for imposing this here. --Stef
908 It should be done by providing the proper default in Fx_create_Frame.
910 f->internal_border_width = 0; */
917 /* Set the normal size hints for the window manager, for frame F.
918 FLAGS is the flags word to use--or 0 meaning preserve the flags
919 that the window now has.
920 If USER_POSITION is nonzero, we set the User Position
921 flag (this is useful when FLAGS is 0). */
924 x_wm_set_size_hint (f
, flags
, user_position
)
929 /* Don't set size hints during initialization; that apparently leads
930 to a race condition. See the thread at
931 http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */
932 if (NILP (Vafter_init_time
) || !FRAME_GTK_OUTER_WIDGET (f
))
935 /* Must use GTK routines here, otherwise GTK resets the size hints
936 to its own defaults. */
937 GdkGeometry size_hints
;
939 int base_width
, base_height
;
940 int min_rows
= 0, min_cols
= 0;
941 int win_gravity
= f
->win_gravity
;
945 memset (&size_hints
, 0, sizeof (size_hints
));
946 f
->output_data
.x
->size_hints
= size_hints
;
947 f
->output_data
.x
->hint_flags
= hint_flags
;
950 flags
= f
->size_hint_flags
;
952 size_hints
= f
->output_data
.x
->size_hints
;
953 hint_flags
= f
->output_data
.x
->hint_flags
;
955 hint_flags
|= GDK_HINT_RESIZE_INC
| GDK_HINT_MIN_SIZE
;
956 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
957 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
959 hint_flags
|= GDK_HINT_BASE_SIZE
;
960 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
961 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0)
962 + FRAME_MENUBAR_HEIGHT (f
) + FRAME_TOOLBAR_HEIGHT (f
);
964 check_frame_size (f
, &min_rows
, &min_cols
);
966 size_hints
.base_width
= base_width
;
967 size_hints
.base_height
= base_height
;
968 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
969 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
971 /* These currently have a one to one mapping with the X values, but I
972 don't think we should rely on that. */
973 hint_flags
|= GDK_HINT_WIN_GRAVITY
;
974 size_hints
.win_gravity
= 0;
975 if (win_gravity
== NorthWestGravity
)
976 size_hints
.win_gravity
= GDK_GRAVITY_NORTH_WEST
;
977 else if (win_gravity
== NorthGravity
)
978 size_hints
.win_gravity
= GDK_GRAVITY_NORTH
;
979 else if (win_gravity
== NorthEastGravity
)
980 size_hints
.win_gravity
= GDK_GRAVITY_NORTH_EAST
;
981 else if (win_gravity
== WestGravity
)
982 size_hints
.win_gravity
= GDK_GRAVITY_WEST
;
983 else if (win_gravity
== CenterGravity
)
984 size_hints
.win_gravity
= GDK_GRAVITY_CENTER
;
985 else if (win_gravity
== EastGravity
)
986 size_hints
.win_gravity
= GDK_GRAVITY_EAST
;
987 else if (win_gravity
== SouthWestGravity
)
988 size_hints
.win_gravity
= GDK_GRAVITY_SOUTH_WEST
;
989 else if (win_gravity
== SouthGravity
)
990 size_hints
.win_gravity
= GDK_GRAVITY_SOUTH
;
991 else if (win_gravity
== SouthEastGravity
)
992 size_hints
.win_gravity
= GDK_GRAVITY_SOUTH_EAST
;
993 else if (win_gravity
== StaticGravity
)
994 size_hints
.win_gravity
= GDK_GRAVITY_STATIC
;
996 if (flags
& PPosition
) hint_flags
|= GDK_HINT_POS
;
997 if (flags
& USPosition
) hint_flags
|= GDK_HINT_USER_POS
;
998 if (flags
& USSize
) hint_flags
|= GDK_HINT_USER_SIZE
;
1002 hint_flags
&= ~GDK_HINT_POS
;
1003 hint_flags
|= GDK_HINT_USER_POS
;
1006 if (hint_flags
!= f
->output_data
.x
->hint_flags
1007 || memcmp (&size_hints
,
1008 &f
->output_data
.x
->size_hints
,
1009 sizeof (size_hints
)) != 0)
1012 gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)),
1013 NULL
, &size_hints
, hint_flags
);
1014 f
->output_data
.x
->size_hints
= size_hints
;
1015 f
->output_data
.x
->hint_flags
= hint_flags
;
1020 /* Change background color of a frame.
1021 Since GTK uses the background color to clear the window, we must
1022 keep the GTK and X colors in sync.
1023 F is the frame to change,
1024 BG is the pixel value to change to. */
1027 xg_set_background_color (f
, bg
)
1031 if (FRAME_GTK_WIDGET (f
))
1036 xg_pix_to_gcolor (FRAME_GTK_WIDGET (f
), bg
, &gdk_bg
);
1037 gtk_widget_modify_bg (FRAME_GTK_WIDGET (f
), GTK_STATE_NORMAL
, &gdk_bg
);
1043 /* Set the frame icon to ICON_PIXMAP/MASK. This must be done with GTK
1044 functions so GTK does not overwrite the icon. */
1047 xg_set_frame_icon (f
, icon_pixmap
, icon_mask
)
1052 GdkDisplay
*gdpy
= gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f
));
1053 GdkPixmap
*gpix
= gdk_pixmap_foreign_new_for_display (gdpy
, icon_pixmap
);
1054 GdkPixmap
*gmask
= gdk_pixmap_foreign_new_for_display (gdpy
, icon_mask
);
1055 GdkPixbuf
*gp
= xg_get_pixbuf_from_pix_and_mask (gpix
, gmask
, NULL
);
1057 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)), gp
);
1062 /***********************************************************************
1064 ***********************************************************************/
1065 /* Return the dialog title to use for a dialog of type KEY.
1066 This is the encoding used by lwlib. We use the same for GTK. */
1069 get_dialog_title (char key
)
1079 title
= "Information";
1098 /* Callback for dialogs that get WM_DELETE_WINDOW. We pop down
1099 the dialog, but return TRUE so the event does not propagate further
1100 in GTK. This prevents GTK from destroying the dialog widget automatically
1101 and we can always destrou the widget manually, regardles of how
1102 it was popped down (button press or WM_DELETE_WINDOW).
1103 W is the dialog widget.
1104 EVENT is the GdkEvent that represents WM_DELETE_WINDOW (not used).
1105 user_data is NULL (not used).
1107 Returns TRUE to end propagation of event. */
1110 dialog_delete_callback (w
, event
, user_data
)
1115 gtk_widget_unmap (w
);
1119 /* Create a popup dialog window. See also xg_create_widget below.
1120 WV is a widget_value describing the dialog.
1121 SELECT_CB is the callback to use when a button has been pressed.
1122 DEACTIVATE_CB is the callback to use when the dialog pops down.
1124 Returns the GTK dialog widget. */
1127 create_dialog (wv
, select_cb
, deactivate_cb
)
1129 GCallback select_cb
;
1130 GCallback deactivate_cb
;
1132 char *title
= get_dialog_title (wv
->name
[0]);
1133 int total_buttons
= wv
->name
[1] - '0';
1134 int right_buttons
= wv
->name
[4] - '0';
1137 int button_spacing
= 10;
1138 GtkWidget
*wdialog
= gtk_dialog_new ();
1142 GtkWidget
*whbox_up
;
1143 GtkWidget
*whbox_down
;
1145 /* If the number of buttons is greater than 4, make two rows of buttons
1146 instead. This looks better. */
1147 int make_two_rows
= total_buttons
> 4;
1149 if (right_buttons
== 0) right_buttons
= total_buttons
/2;
1150 left_buttons
= total_buttons
- right_buttons
;
1152 gtk_window_set_title (GTK_WINDOW (wdialog
), title
);
1153 gtk_widget_set_name (wdialog
, "emacs-dialog");
1155 cur_box
= GTK_BOX (GTK_DIALOG (wdialog
)->action_area
);
1159 wvbox
= gtk_vbox_new (TRUE
, button_spacing
);
1160 whbox_up
= gtk_hbox_new (FALSE
, 0);
1161 whbox_down
= gtk_hbox_new (FALSE
, 0);
1163 gtk_box_pack_start (cur_box
, wvbox
, FALSE
, FALSE
, 0);
1164 gtk_box_pack_start (GTK_BOX (wvbox
), whbox_up
, FALSE
, FALSE
, 0);
1165 gtk_box_pack_start (GTK_BOX (wvbox
), whbox_down
, FALSE
, FALSE
, 0);
1167 cur_box
= GTK_BOX (whbox_up
);
1170 g_signal_connect (G_OBJECT (wdialog
), "delete-event",
1171 G_CALLBACK (dialog_delete_callback
), 0);
1175 g_signal_connect (G_OBJECT (wdialog
), "close", deactivate_cb
, 0);
1176 g_signal_connect (G_OBJECT (wdialog
), "response", deactivate_cb
, 0);
1179 for (item
= wv
->contents
; item
; item
= item
->next
)
1181 char *utf8_label
= get_utf8_string (item
->value
);
1185 if (item
->name
&& strcmp (item
->name
, "message") == 0)
1187 /* This is the text part of the dialog. */
1188 w
= gtk_label_new (utf8_label
);
1189 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (wdialog
)->vbox
),
1192 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (wdialog
)->vbox
), w
,
1194 gtk_misc_set_alignment (GTK_MISC (w
), 0.1, 0.5);
1196 /* Try to make dialog look better. Must realize first so
1197 the widget can calculate the size it needs. */
1198 gtk_widget_realize (w
);
1199 gtk_widget_size_request (w
, &req
);
1200 gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (wdialog
)->vbox
),
1202 if (item
->value
&& strlen (item
->value
) > 0)
1203 button_spacing
= 2*req
.width
/strlen (item
->value
);
1207 /* This is one button to add to the dialog. */
1208 w
= gtk_button_new_with_label (utf8_label
);
1209 if (! item
->enabled
)
1210 gtk_widget_set_sensitive (w
, FALSE
);
1212 g_signal_connect (G_OBJECT (w
), "clicked",
1213 select_cb
, item
->call_data
);
1215 gtk_box_pack_start (cur_box
, w
, TRUE
, TRUE
, button_spacing
);
1216 if (++button_nr
== left_buttons
)
1219 cur_box
= GTK_BOX (whbox_down
);
1221 gtk_box_pack_start (cur_box
,
1228 if (utf8_label
&& utf8_label
!= item
->value
)
1229 g_free (utf8_label
);
1237 /***********************************************************************
1238 File dialog functions
1239 ***********************************************************************/
1240 /* Return non-zero if the old file selection dialog is being used.
1241 Return zero if not. */
1244 xg_uses_old_file_dialog ()
1246 #ifdef HAVE_GTK_FILE_BOTH
1247 extern int x_gtk_use_old_file_dialog
;
1248 return x_gtk_use_old_file_dialog
;
1249 #else /* ! HAVE_GTK_FILE_BOTH */
1251 #ifdef HAVE_GTK_FILE_SELECTION_NEW
1257 #endif /* ! HAVE_GTK_FILE_BOTH */
1261 /* Function that is called when the file or font dialogs pop down.
1262 W is the dialog widget, RESPONSE is the response code.
1263 USER_DATA is what we passed in to g_signal_connect (pointer to int). */
1266 xg_dialog_response_cb (w
,
1273 int *ptr
= (int *) user_data
;
1278 /* Destroy the dialog. This makes it pop down. */
1281 pop_down_dialog (arg
)
1284 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
1286 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
1291 typedef char * (*xg_get_file_func
) P_ ((GtkWidget
*));
1293 #ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW
1295 /* Return the selected file for file chooser dialog W.
1296 The returned string must be free:d. */
1299 xg_get_file_name_from_chooser (w
)
1302 return gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w
));
1305 /* Callback called when the "Show hidden files" toggle is pressed.
1306 WIDGET is the toggle widget, DATA is the file chooser dialog. */
1309 xg_toggle_visibility_cb (widget
, data
)
1313 GtkFileChooser
*dialog
= GTK_FILE_CHOOSER (data
);
1315 g_object_get (G_OBJECT (dialog
), "show-hidden", &visible
, NULL
);
1316 g_object_set (G_OBJECT (dialog
), "show-hidden", !visible
, NULL
);
1320 /* Callback called when a property changes in a file chooser.
1321 GOBJECT is the file chooser dialog, ARG1 describes the property.
1322 USER_DATA is the toggle widget in the file chooser dialog.
1323 We use this to update the "Show hidden files" toggle when the user
1324 changes that property by right clicking in the file list. */
1327 xg_toggle_notify_cb (gobject
, arg1
, user_data
)
1332 extern int x_gtk_show_hidden_files
;
1334 if (strcmp (arg1
->name
, "show-hidden") == 0)
1336 GtkFileChooser
*dialog
= GTK_FILE_CHOOSER (gobject
);
1337 GtkWidget
*wtoggle
= GTK_WIDGET (user_data
);
1338 gboolean visible
, toggle_on
;
1340 g_object_get (G_OBJECT (gobject
), "show-hidden", &visible
, NULL
);
1341 toggle_on
= gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wtoggle
));
1343 if (!!visible
!= !!toggle_on
)
1345 g_signal_handlers_block_by_func (G_OBJECT (wtoggle
),
1346 G_CALLBACK (xg_toggle_visibility_cb
),
1348 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle
), visible
);
1349 g_signal_handlers_unblock_by_func
1350 (G_OBJECT (wtoggle
),
1351 G_CALLBACK (xg_toggle_visibility_cb
),
1354 x_gtk_show_hidden_files
= visible
;
1358 /* Read a file name from the user using a file chooser dialog.
1359 F is the current frame.
1360 PROMPT is a prompt to show to the user. May not be NULL.
1361 DEFAULT_FILENAME is a default selection to be displayed. May be NULL.
1362 If MUSTMATCH_P is non-zero, the returned file name must be an existing
1363 file. *FUNC is set to a function that can be used to retrieve the
1364 selected file name from the returned widget.
1366 Returns the created widget. */
1369 xg_get_file_with_chooser (f
, prompt
, default_filename
,
1370 mustmatch_p
, only_dir_p
, func
)
1373 char *default_filename
;
1374 int mustmatch_p
, only_dir_p
;
1375 xg_get_file_func
*func
;
1379 GtkWidget
*filewin
, *wtoggle
, *wbox
, *wmessage
;
1380 GtkWindow
*gwin
= GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
));
1381 GtkFileChooserAction action
= (mustmatch_p
?
1382 GTK_FILE_CHOOSER_ACTION_OPEN
:
1383 GTK_FILE_CHOOSER_ACTION_SAVE
);
1384 extern int x_gtk_show_hidden_files
;
1385 extern int x_gtk_file_dialog_help_text
;
1389 action
= GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
;
1391 filewin
= gtk_file_chooser_dialog_new (prompt
, gwin
, action
,
1392 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
1393 (mustmatch_p
|| only_dir_p
?
1394 GTK_STOCK_OPEN
: GTK_STOCK_OK
),
1397 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (filewin
), TRUE
);
1399 wbox
= gtk_vbox_new (FALSE
, 0);
1400 gtk_widget_show (wbox
);
1401 wtoggle
= gtk_check_button_new_with_label ("Show hidden files.");
1403 if (x_gtk_show_hidden_files
)
1405 g_object_set (G_OBJECT (filewin
), "show-hidden", TRUE
, NULL
);
1406 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle
), TRUE
);
1408 gtk_widget_show (wtoggle
);
1409 g_signal_connect (G_OBJECT (wtoggle
), "clicked",
1410 G_CALLBACK (xg_toggle_visibility_cb
), filewin
);
1411 g_signal_connect (G_OBJECT (filewin
), "notify",
1412 G_CALLBACK (xg_toggle_notify_cb
), wtoggle
);
1414 if (x_gtk_file_dialog_help_text
)
1417 /* Gtk+ 2.10 has the file name text entry box integrated in the dialog.
1418 Show the C-l help text only for versions < 2.10. */
1419 if (gtk_check_version (2, 10, 0) && action
!= GTK_FILE_CHOOSER_ACTION_SAVE
)
1420 strcat (message
, "\nType C-l to display a file name text entry box.\n");
1421 strcat (message
, "\nIf you don't like this file selector, use the "
1422 "corresponding\nkey binding or customize "
1423 "use-file-dialog to turn it off.");
1425 wmessage
= gtk_label_new (message
);
1426 gtk_widget_show (wmessage
);
1429 gtk_box_pack_start (GTK_BOX (wbox
), wtoggle
, FALSE
, FALSE
, 0);
1430 if (x_gtk_file_dialog_help_text
)
1431 gtk_box_pack_start (GTK_BOX (wbox
), wmessage
, FALSE
, FALSE
, 0);
1432 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (filewin
), wbox
);
1434 if (default_filename
)
1437 struct gcpro gcpro1
;
1438 char *utf8_filename
;
1441 file
= build_string (default_filename
);
1443 /* File chooser does not understand ~/... in the file name. It must be
1444 an absolute name starting with /. */
1445 if (default_filename
[0] != '/')
1446 file
= Fexpand_file_name (file
, Qnil
);
1448 utf8_filename
= SSDATA (ENCODE_UTF_8 (file
));
1449 if (! NILP (Ffile_directory_p (file
)))
1450 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filewin
),
1454 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filewin
),
1456 if (action
== GTK_FILE_CHOOSER_ACTION_SAVE
)
1458 char *cp
= strrchr (utf8_filename
, '/');
1460 else cp
= utf8_filename
;
1461 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filewin
), cp
);
1468 *func
= xg_get_file_name_from_chooser
;
1471 #endif /* HAVE_GTK_FILE_CHOOSER_DIALOG_NEW */
1473 #ifdef HAVE_GTK_FILE_SELECTION_NEW
1475 /* Return the selected file for file selector dialog W.
1476 The returned string must be free:d. */
1479 xg_get_file_name_from_selector (w
)
1482 GtkFileSelection
*filesel
= GTK_FILE_SELECTION (w
);
1483 return xstrdup ((char*) gtk_file_selection_get_filename (filesel
));
1486 /* Create a file selection dialog.
1487 F is the current frame.
1488 PROMPT is a prompt to show to the user. May not be NULL.
1489 DEFAULT_FILENAME is a default selection to be displayed. May be NULL.
1490 If MUSTMATCH_P is non-zero, the returned file name must be an existing
1491 file. *FUNC is set to a function that can be used to retrieve the
1492 selected file name from the returned widget.
1494 Returns the created widget. */
1497 xg_get_file_with_selection (f
, prompt
, default_filename
,
1498 mustmatch_p
, only_dir_p
, func
)
1501 char *default_filename
;
1502 int mustmatch_p
, only_dir_p
;
1503 xg_get_file_func
*func
;
1506 GtkFileSelection
*filesel
;
1508 filewin
= gtk_file_selection_new (prompt
);
1509 filesel
= GTK_FILE_SELECTION (filewin
);
1511 if (default_filename
)
1512 gtk_file_selection_set_filename (filesel
, default_filename
);
1516 /* The selection_entry part of filesel is not documented. */
1517 gtk_widget_set_sensitive (filesel
->selection_entry
, FALSE
);
1518 gtk_file_selection_hide_fileop_buttons (filesel
);
1521 *func
= xg_get_file_name_from_selector
;
1525 #endif /* HAVE_GTK_FILE_SELECTION_NEW */
1527 /* Read a file name from the user using a file dialog, either the old
1528 file selection dialog, or the new file chooser dialog. Which to use
1529 depends on what the GTK version used has, and what the value of
1530 gtk-use-old-file-dialog.
1531 F is the current frame.
1532 PROMPT is a prompt to show to the user. May not be NULL.
1533 DEFAULT_FILENAME is a default selection to be displayed. May be NULL.
1534 If MUSTMATCH_P is non-zero, the returned file name must be an existing
1537 Returns a file name or NULL if no file was selected.
1538 The returned string must be freed by the caller. */
1541 xg_get_file_name (f
, prompt
, default_filename
, mustmatch_p
, only_dir_p
)
1544 char *default_filename
;
1545 int mustmatch_p
, only_dir_p
;
1548 int count
= SPECPDL_INDEX ();
1550 int filesel_done
= 0;
1551 xg_get_file_func func
;
1553 #if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
1554 /* I really don't know why this is needed, but without this the GLIBC add on
1555 library linuxthreads hangs when the Gnome file chooser backend creates
1557 sigblock (sigmask (__SIGRTMIN
));
1558 #endif /* HAVE_GTK_AND_PTHREAD */
1560 #ifdef HAVE_GTK_FILE_BOTH
1562 if (xg_uses_old_file_dialog ())
1563 w
= xg_get_file_with_selection (f
, prompt
, default_filename
,
1564 mustmatch_p
, only_dir_p
, &func
);
1566 w
= xg_get_file_with_chooser (f
, prompt
, default_filename
,
1567 mustmatch_p
, only_dir_p
, &func
);
1569 #else /* not HAVE_GTK_FILE_BOTH */
1571 #ifdef HAVE_GTK_FILE_SELECTION_NEW
1572 w
= xg_get_file_with_selection (f
, prompt
, default_filename
,
1573 mustmatch_p
, only_dir_p
, &func
);
1575 #ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW
1576 w
= xg_get_file_with_chooser (f
, prompt
, default_filename
,
1577 mustmatch_p
, only_dir_p
, &func
);
1580 #endif /* HAVE_GTK_FILE_BOTH */
1582 xg_set_screen (w
, f
);
1583 gtk_widget_set_name (w
, "emacs-filedialog");
1584 gtk_window_set_transient_for (GTK_WINDOW (w
),
1585 GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
1586 gtk_window_set_destroy_with_parent (GTK_WINDOW (w
), TRUE
);
1587 gtk_window_set_modal (GTK_WINDOW (w
), TRUE
);
1589 g_signal_connect (G_OBJECT (w
),
1591 G_CALLBACK (xg_dialog_response_cb
),
1594 /* Don't destroy the widget if closed by the window manager close button. */
1595 g_signal_connect (G_OBJECT (w
), "delete-event", G_CALLBACK (gtk_true
), NULL
);
1597 gtk_widget_show (w
);
1599 record_unwind_protect (pop_down_dialog
, make_save_value (w
, 0));
1600 while (! filesel_done
)
1602 x_menu_wait_for_event (0);
1603 gtk_main_iteration ();
1606 #if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
1607 sigunblock (sigmask (__SIGRTMIN
));
1610 if (filesel_done
== GTK_RESPONSE_OK
)
1613 unbind_to (count
, Qnil
);
1618 #ifdef HAVE_FREETYPE
1619 /* Pop up a GTK font selector and return the name of the font the user
1620 selects, as a C string. The returned font name follows GTK's own
1623 `FAMILY [VALUE1 VALUE2] SIZE'
1625 This can be parsed using font_parse_fcname in font.c.
1626 DEFAULT_NAME, if non-zero, is the default font name. */
1629 xg_get_font_name (f
, default_name
)
1634 int count
= SPECPDL_INDEX ();
1635 char *fontname
= NULL
;
1638 #if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
1639 sigblock (sigmask (__SIGRTMIN
));
1640 #endif /* HAVE_GTK_AND_PTHREAD */
1642 w
= gtk_font_selection_dialog_new ("Pick a font");
1644 gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (w
),
1647 xg_set_screen (w
, f
);
1648 gtk_widget_set_name (w
, "emacs-fontdialog");
1649 gtk_window_set_transient_for (GTK_WINDOW (w
),
1650 GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
1651 gtk_window_set_destroy_with_parent (GTK_WINDOW (w
), TRUE
);
1652 gtk_window_set_modal (GTK_WINDOW (w
), TRUE
);
1654 g_signal_connect (G_OBJECT (w
), "response",
1655 G_CALLBACK (xg_dialog_response_cb
), &done
);
1657 /* Don't destroy the widget if closed by the window manager close button. */
1658 g_signal_connect (G_OBJECT (w
), "delete-event", G_CALLBACK (gtk_true
), NULL
);
1660 gtk_widget_show (w
);
1662 record_unwind_protect (pop_down_dialog
, make_save_value (w
, 0));
1665 x_menu_wait_for_event (0);
1666 gtk_main_iteration ();
1669 #if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
1670 sigunblock (sigmask (__SIGRTMIN
));
1673 if (done
== GTK_RESPONSE_OK
)
1674 fontname
= gtk_font_selection_dialog_get_font_name
1675 ((GtkFontSelectionDialog
*) w
);
1677 unbind_to (count
, Qnil
);
1681 #endif /* HAVE_FREETYPE */
1685 /***********************************************************************
1687 ***********************************************************************/
1689 /* The name of menu items that can be used for customization. Since GTK
1690 RC files are very crude and primitive, we have to set this on all
1691 menu item names so a user can easily customize menu items. */
1693 #define MENU_ITEM_NAME "emacs-menuitem"
1696 /* Linked list of all allocated struct xg_menu_cb_data. Used for marking
1697 during GC. The next member points to the items. */
1698 static xg_list_node xg_menu_cb_list
;
1700 /* Linked list of all allocated struct xg_menu_item_cb_data. Used for marking
1701 during GC. The next member points to the items. */
1702 static xg_list_node xg_menu_item_cb_list
;
1704 /* Allocate and initialize CL_DATA if NULL, otherwise increase ref_count.
1705 F is the frame CL_DATA will be initialized for.
1706 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
1708 The menu bar and all sub menus under the menu bar in a frame
1709 share the same structure, hence the reference count.
1711 Returns CL_DATA if CL_DATA is not NULL, or a pointer to a newly
1712 allocated xg_menu_cb_data if CL_DATA is NULL. */
1714 static xg_menu_cb_data
*
1715 make_cl_data (cl_data
, f
, highlight_cb
)
1716 xg_menu_cb_data
*cl_data
;
1718 GCallback highlight_cb
;
1722 cl_data
= (xg_menu_cb_data
*) xmalloc (sizeof (*cl_data
));
1724 cl_data
->menu_bar_vector
= f
->menu_bar_vector
;
1725 cl_data
->menu_bar_items_used
= f
->menu_bar_items_used
;
1726 cl_data
->highlight_cb
= highlight_cb
;
1727 cl_data
->ref_count
= 0;
1729 xg_list_insert (&xg_menu_cb_list
, &cl_data
->ptrs
);
1732 cl_data
->ref_count
++;
1737 /* Update CL_DATA with values from frame F and with HIGHLIGHT_CB.
1738 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
1740 When the menu bar is updated, menu items may have been added and/or
1741 removed, so menu_bar_vector and menu_bar_items_used change. We must
1742 then update CL_DATA since it is used to determine which menu
1743 item that is invoked in the menu.
1744 HIGHLIGHT_CB could change, there is no check that the same
1745 function is given when modifying a menu bar as was given when
1746 creating the menu bar. */
1749 update_cl_data (cl_data
, f
, highlight_cb
)
1750 xg_menu_cb_data
*cl_data
;
1752 GCallback highlight_cb
;
1757 cl_data
->menu_bar_vector
= f
->menu_bar_vector
;
1758 cl_data
->menu_bar_items_used
= f
->menu_bar_items_used
;
1759 cl_data
->highlight_cb
= highlight_cb
;
1763 /* Decrease reference count for CL_DATA.
1764 If reference count is zero, free CL_DATA. */
1767 unref_cl_data (cl_data
)
1768 xg_menu_cb_data
*cl_data
;
1770 if (cl_data
&& cl_data
->ref_count
> 0)
1772 cl_data
->ref_count
--;
1773 if (cl_data
->ref_count
== 0)
1775 xg_list_remove (&xg_menu_cb_list
, &cl_data
->ptrs
);
1781 /* Function that marks all lisp data during GC. */
1788 for (iter
= xg_menu_cb_list
.next
; iter
; iter
= iter
->next
)
1789 mark_object (((xg_menu_cb_data
*) iter
)->menu_bar_vector
);
1791 for (iter
= xg_menu_item_cb_list
.next
; iter
; iter
= iter
->next
)
1793 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) iter
;
1795 if (! NILP (cb_data
->help
))
1796 mark_object (cb_data
->help
);
1801 /* Callback called when a menu item is destroyed. Used to free data.
1802 W is the widget that is being destroyed (not used).
1803 CLIENT_DATA points to the xg_menu_item_cb_data associated with the W. */
1806 menuitem_destroy_callback (w
, client_data
)
1808 gpointer client_data
;
1812 xg_menu_item_cb_data
*data
= (xg_menu_item_cb_data
*) client_data
;
1813 xg_list_remove (&xg_menu_item_cb_list
, &data
->ptrs
);
1818 /* Callback called when the pointer enters/leaves a menu item.
1819 W is the parent of the menu item.
1820 EVENT is either an enter event or leave event.
1821 CLIENT_DATA is not used.
1823 Returns FALSE to tell GTK to keep processing this event. */
1826 menuitem_highlight_callback (w
, event
, client_data
)
1828 GdkEventCrossing
*event
;
1829 gpointer client_data
;
1832 GtkWidget
*subwidget
;
1833 xg_menu_item_cb_data
*data
;
1835 ev
.crossing
= *event
;
1836 subwidget
= gtk_get_event_widget (&ev
);
1837 data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (subwidget
),
1841 if (! NILP (data
->help
) && data
->cl_data
->highlight_cb
)
1843 gpointer call_data
= event
->type
== GDK_LEAVE_NOTIFY
? 0 : data
;
1844 GtkCallback func
= (GtkCallback
) data
->cl_data
->highlight_cb
;
1845 (*func
) (subwidget
, call_data
);
1852 /* Callback called when a menu is destroyed. Used to free data.
1853 W is the widget that is being destroyed (not used).
1854 CLIENT_DATA points to the xg_menu_cb_data associated with W. */
1857 menu_destroy_callback (w
, client_data
)
1859 gpointer client_data
;
1861 unref_cl_data ((xg_menu_cb_data
*) client_data
);
1864 /* Callback called when a menu does a grab or ungrab. That means the
1865 menu has been activated or deactivated.
1866 Used to start a timer so the small timeout the menus in GTK uses before
1867 popping down a menu is seen by Emacs (see xg_process_timeouts above).
1868 W is the widget that does the grab (not used).
1869 UNGRAB_P is TRUE if this is an ungrab, FALSE if it is a grab.
1870 CLIENT_DATA is NULL (not used). */
1872 /* Keep track of total number of grabs. */
1873 static int menu_grab_callback_cnt
;
1876 menu_grab_callback (GtkWidget
*widget
,
1878 gpointer client_data
)
1880 if (ungrab_p
) menu_grab_callback_cnt
--;
1881 else menu_grab_callback_cnt
++;
1883 if (menu_grab_callback_cnt
> 0 && ! xg_timer
) xg_start_timer ();
1884 else if (menu_grab_callback_cnt
== 0 && xg_timer
) xg_stop_timer ();
1887 /* Make a GTK widget that contains both UTF8_LABEL and UTF8_KEY (both
1888 must be non-NULL) and can be inserted into a menu item.
1890 Returns the GtkHBox. */
1893 make_widget_for_menu_item (utf8_label
, utf8_key
)
1901 wbox
= gtk_hbox_new (FALSE
, 0);
1902 wlbl
= gtk_label_new (utf8_label
);
1903 wkey
= gtk_label_new (utf8_key
);
1905 gtk_misc_set_alignment (GTK_MISC (wlbl
), 0.0, 0.5);
1906 gtk_misc_set_alignment (GTK_MISC (wkey
), 0.0, 0.5);
1908 gtk_box_pack_start (GTK_BOX (wbox
), wlbl
, TRUE
, TRUE
, 0);
1909 gtk_box_pack_start (GTK_BOX (wbox
), wkey
, FALSE
, FALSE
, 0);
1911 gtk_widget_set_name (wlbl
, MENU_ITEM_NAME
);
1912 gtk_widget_set_name (wkey
, MENU_ITEM_NAME
);
1913 gtk_widget_set_name (wbox
, MENU_ITEM_NAME
);
1918 /* Make and return a menu item widget with the key to the right.
1919 UTF8_LABEL is the text for the menu item (GTK uses UTF8 internally).
1920 UTF8_KEY is the text representing the key binding.
1921 ITEM is the widget_value describing the menu item.
1923 GROUP is an in/out parameter. If the menu item to be created is not
1924 part of any radio menu group, *GROUP contains NULL on entry and exit.
1925 If the menu item to be created is part of a radio menu group, on entry
1926 *GROUP contains the group to use, or NULL if this is the first item
1927 in the group. On exit, *GROUP contains the radio item group.
1929 Unfortunately, keys don't line up as nicely as in Motif,
1930 but the MacOS X version doesn't either, so I guess that is OK. */
1933 make_menu_item (utf8_label
, utf8_key
, item
, group
)
1940 GtkWidget
*wtoadd
= 0;
1942 /* It has been observed that some menu items have a NULL name field.
1943 This will lead to this function being called with a NULL utf8_label.
1944 GTK crashes on that so we set a blank label. Why there is a NULL
1945 name remains to be investigated. */
1946 if (! utf8_label
) utf8_label
= " ";
1949 wtoadd
= make_widget_for_menu_item (utf8_label
, utf8_key
);
1951 if (item
->button_type
== BUTTON_TYPE_TOGGLE
)
1954 if (utf8_key
) w
= gtk_check_menu_item_new ();
1955 else w
= gtk_check_menu_item_new_with_label (utf8_label
);
1956 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w
), item
->selected
);
1958 else if (item
->button_type
== BUTTON_TYPE_RADIO
)
1960 if (utf8_key
) w
= gtk_radio_menu_item_new (*group
);
1961 else w
= gtk_radio_menu_item_new_with_label (*group
, utf8_label
);
1962 *group
= gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (w
));
1964 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w
), TRUE
);
1969 if (utf8_key
) w
= gtk_menu_item_new ();
1970 else w
= gtk_menu_item_new_with_label (utf8_label
);
1973 if (wtoadd
) gtk_container_add (GTK_CONTAINER (w
), wtoadd
);
1974 if (! item
->enabled
) gtk_widget_set_sensitive (w
, FALSE
);
1979 /* Return non-zero if LABEL specifies a separator (GTK only has one
1982 static char* separator_names
[] = {
1987 "single-dashed-line",
1988 "double-dashed-line",
1990 "shadow-etched-out",
1991 "shadow-etched-in-dash",
1992 "shadow-etched-out-dash",
1993 "shadow-double-etched-in",
1994 "shadow-double-etched-out",
1995 "shadow-double-etched-in-dash",
1996 "shadow-double-etched-out-dash",
2001 xg_separator_p (char *label
)
2003 if (! label
) return 0;
2004 else if (strlen (label
) > 3
2005 && strncmp (label
, "--", 2) == 0
2011 for (i
= 0; separator_names
[i
]; ++i
)
2012 if (strcmp (label
, separator_names
[i
]) == 0)
2017 /* Old-style separator, maybe. It's a separator if it contains
2019 while (*label
== '-')
2021 if (*label
== 0) return 1;
2027 static int xg_detached_menus
;
2029 /* Returns non-zero if there are detached menus. */
2032 xg_have_tear_offs ()
2034 return xg_detached_menus
> 0;
2037 /* Callback invoked when a detached menu window is removed. Here we
2038 decrease the xg_detached_menus count.
2039 WIDGET is the top level window that is removed (the parent of the menu).
2040 CLIENT_DATA is not used. */
2043 tearoff_remove (widget
, client_data
)
2045 gpointer client_data
;
2047 if (xg_detached_menus
> 0) --xg_detached_menus
;
2050 /* Callback invoked when a menu is detached. It increases the
2051 xg_detached_menus count.
2052 WIDGET is the GtkTearoffMenuItem.
2053 CLIENT_DATA is not used. */
2056 tearoff_activate (widget
, client_data
)
2058 gpointer client_data
;
2060 GtkWidget
*menu
= gtk_widget_get_parent (widget
);
2061 if (gtk_menu_get_tearoff_state (GTK_MENU (menu
)))
2063 ++xg_detached_menus
;
2064 g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget
)),
2066 G_CALLBACK (tearoff_remove
), 0);
2071 /* Create a menu item widget, and connect the callbacks.
2072 ITEM decribes the menu item.
2073 F is the frame the created menu belongs to.
2074 SELECT_CB is the callback to use when a menu item is selected.
2075 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
2076 CL_DATA points to the callback data to be used for this menu.
2077 GROUP is an in/out parameter. If the menu item to be created is not
2078 part of any radio menu group, *GROUP contains NULL on entry and exit.
2079 If the menu item to be created is part of a radio menu group, on entry
2080 *GROUP contains the group to use, or NULL if this is the first item
2081 in the group. On exit, *GROUP contains the radio item group.
2083 Returns the created GtkWidget. */
2086 xg_create_one_menuitem (item
, f
, select_cb
, highlight_cb
, cl_data
, group
)
2089 GCallback select_cb
;
2090 GCallback highlight_cb
;
2091 xg_menu_cb_data
*cl_data
;
2097 xg_menu_item_cb_data
*cb_data
;
2099 utf8_label
= get_utf8_string (item
->name
);
2100 utf8_key
= get_utf8_string (item
->key
);
2102 w
= make_menu_item (utf8_label
, utf8_key
, item
, group
);
2104 if (utf8_label
&& utf8_label
!= item
->name
) g_free (utf8_label
);
2105 if (utf8_key
&& utf8_key
!= item
->key
) g_free (utf8_key
);
2107 cb_data
= xmalloc (sizeof (xg_menu_item_cb_data
));
2109 xg_list_insert (&xg_menu_item_cb_list
, &cb_data
->ptrs
);
2111 cb_data
->select_id
= 0;
2112 cb_data
->help
= item
->help
;
2113 cb_data
->cl_data
= cl_data
;
2114 cb_data
->call_data
= item
->call_data
;
2116 g_signal_connect (G_OBJECT (w
),
2118 G_CALLBACK (menuitem_destroy_callback
),
2121 /* Put cb_data in widget, so we can get at it when modifying menubar */
2122 g_object_set_data (G_OBJECT (w
), XG_ITEM_DATA
, cb_data
);
2124 /* final item, not a submenu */
2125 if (item
->call_data
&& ! item
->contents
)
2129 = g_signal_connect (G_OBJECT (w
), "activate", select_cb
, cb_data
);
2135 static GtkWidget
*create_menus
P_ ((widget_value
*, FRAME_PTR
, GCallback
,
2136 GCallback
, GCallback
, int, int, int,
2137 GtkWidget
*, xg_menu_cb_data
*, char *));
2139 /* Create a full menu tree specified by DATA.
2140 F is the frame the created menu belongs to.
2141 SELECT_CB is the callback to use when a menu item is selected.
2142 DEACTIVATE_CB is the callback to use when a sub menu is not shown anymore.
2143 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
2144 POP_UP_P is non-zero if we shall create a popup menu.
2145 MENU_BAR_P is non-zero if we shall create a menu bar.
2146 ADD_TEAROFF_P is non-zero if we shall add a teroff menu item. Ignored
2147 if MENU_BAR_P is non-zero.
2148 TOPMENU is the topmost GtkWidget that others shall be placed under.
2149 It may be NULL, in that case we create the appropriate widget
2150 (menu bar or menu item depending on POP_UP_P and MENU_BAR_P)
2151 CL_DATA is the callback data we shall use for this menu, or NULL
2152 if we haven't set the first callback yet.
2153 NAME is the name to give to the top level menu if this function
2154 creates it. May be NULL to not set any name.
2156 Returns the top level GtkWidget. This is TOPLEVEL if TOPLEVEL is
2159 This function calls itself to create submenus. */
2162 create_menus (data
, f
, select_cb
, deactivate_cb
, highlight_cb
,
2163 pop_up_p
, menu_bar_p
, add_tearoff_p
, topmenu
, cl_data
, name
)
2166 GCallback select_cb
;
2167 GCallback deactivate_cb
;
2168 GCallback highlight_cb
;
2173 xg_menu_cb_data
*cl_data
;
2177 GtkWidget
*wmenu
= topmenu
;
2178 GSList
*group
= NULL
;
2184 wmenu
= gtk_menu_new ();
2185 xg_set_screen (wmenu
, f
);
2186 /* Connect this to the menu instead of items so we get enter/leave for
2187 disabled items also. TODO: Still does not get enter/leave for
2188 disabled items in detached menus. */
2189 g_signal_connect (G_OBJECT (wmenu
),
2190 "enter-notify-event",
2191 G_CALLBACK (menuitem_highlight_callback
),
2193 g_signal_connect (G_OBJECT (wmenu
),
2194 "leave-notify-event",
2195 G_CALLBACK (menuitem_highlight_callback
),
2200 wmenu
= gtk_menu_bar_new ();
2201 // Set width of menu bar to a small value so it doesn't enlarge
2202 // a small initial frame size. The width will be set to the
2203 // width of the frame later on when it is added to a container.
2204 // height -1: Natural height.
2205 gtk_widget_set_size_request (wmenu
, 1, -1);
2208 /* Put cl_data on the top menu for easier access. */
2209 cl_data
= make_cl_data (cl_data
, f
, highlight_cb
);
2210 g_object_set_data (G_OBJECT (wmenu
), XG_FRAME_DATA
, (gpointer
)cl_data
);
2211 g_signal_connect (G_OBJECT (wmenu
), "destroy",
2212 G_CALLBACK (menu_destroy_callback
), cl_data
);
2215 gtk_widget_set_name (wmenu
, name
);
2218 g_signal_connect (G_OBJECT (wmenu
),
2219 "selection-done", deactivate_cb
, 0);
2221 g_signal_connect (G_OBJECT (wmenu
),
2222 "grab-notify", G_CALLBACK (menu_grab_callback
), 0);
2225 if (! menu_bar_p
&& add_tearoff_p
)
2227 GtkWidget
*tearoff
= gtk_tearoff_menu_item_new ();
2228 gtk_menu_shell_append (GTK_MENU_SHELL (wmenu
), tearoff
);
2230 g_signal_connect (G_OBJECT (tearoff
), "activate",
2231 G_CALLBACK (tearoff_activate
), 0);
2234 for (item
= data
; item
; item
= item
->next
)
2238 if (pop_up_p
&& !item
->contents
&& !item
->call_data
2239 && !xg_separator_p (item
->name
))
2242 /* A title for a popup. We do the same as GTK does when
2243 creating titles, but it does not look good. */
2245 utf8_label
= get_utf8_string (item
->name
);
2247 gtk_menu_set_title (GTK_MENU (wmenu
), utf8_label
);
2248 w
= gtk_menu_item_new_with_label (utf8_label
);
2249 gtk_widget_set_sensitive (w
, FALSE
);
2250 if (utf8_label
&& utf8_label
!= item
->name
) g_free (utf8_label
);
2252 else if (xg_separator_p (item
->name
))
2255 /* GTK only have one separator type. */
2256 w
= gtk_separator_menu_item_new ();
2260 w
= xg_create_one_menuitem (item
,
2262 item
->contents
? 0 : select_cb
,
2267 /* Create a possibly empty submenu for menu bar items, since some
2268 themes don't highlight items correctly without it. */
2269 if (item
->contents
|| menu_bar_p
)
2271 GtkWidget
*submenu
= create_menus (item
->contents
,
2282 gtk_menu_item_set_submenu (GTK_MENU_ITEM (w
), submenu
);
2286 gtk_menu_shell_append (GTK_MENU_SHELL (wmenu
), w
);
2287 gtk_widget_set_name (w
, MENU_ITEM_NAME
);
2293 /* Create a menubar, popup menu or dialog, depending on the TYPE argument.
2294 TYPE can be "menubar", "popup" for popup menu, or "dialog" for a dialog
2295 with some text and buttons.
2296 F is the frame the created item belongs to.
2297 NAME is the name to use for the top widget.
2298 VAL is a widget_value structure describing items to be created.
2299 SELECT_CB is the callback to use when a menu item is selected or
2300 a dialog button is pressed.
2301 DEACTIVATE_CB is the callback to use when an item is deactivated.
2302 For a menu, when a sub menu is not shown anymore, for a dialog it is
2303 called when the dialog is popped down.
2304 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
2306 Returns the widget created. */
2309 xg_create_widget (type
, name
, f
, val
,
2310 select_cb
, deactivate_cb
, highlight_cb
)
2315 GCallback select_cb
;
2316 GCallback deactivate_cb
;
2317 GCallback highlight_cb
;
2320 int menu_bar_p
= strcmp (type
, "menubar") == 0;
2321 int pop_up_p
= strcmp (type
, "popup") == 0;
2323 if (strcmp (type
, "dialog") == 0)
2325 w
= create_dialog (val
, select_cb
, deactivate_cb
);
2326 xg_set_screen (w
, f
);
2327 gtk_window_set_transient_for (GTK_WINDOW (w
),
2328 GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f
)));
2329 gtk_window_set_destroy_with_parent (GTK_WINDOW (w
), TRUE
);
2330 gtk_widget_set_name (w
, "emacs-dialog");
2331 gtk_window_set_modal (GTK_WINDOW (w
), TRUE
);
2333 else if (menu_bar_p
|| pop_up_p
)
2335 w
= create_menus (val
->contents
,
2347 /* Set the cursor to an arrow for popup menus when they are mapped.
2348 This is done by default for menu bar menus. */
2351 /* Must realize so the GdkWindow inside the widget is created. */
2352 gtk_widget_realize (w
);
2353 xg_set_cursor (w
, FRAME_X_DISPLAY_INFO (f
)->xg_cursor
);
2358 fprintf (stderr
, "bad type in xg_create_widget: %s, doing nothing\n",
2365 /* Return the label for menu item WITEM. */
2368 xg_get_menu_item_label (witem
)
2371 GtkLabel
*wlabel
= GTK_LABEL (gtk_bin_get_child (GTK_BIN (witem
)));
2372 return gtk_label_get_label (wlabel
);
2375 /* Return non-zero if the menu item WITEM has the text LABEL. */
2378 xg_item_label_same_p (witem
, label
)
2383 char *utf8_label
= get_utf8_string (label
);
2384 const char *old_label
= witem
? xg_get_menu_item_label (witem
) : 0;
2386 if (! old_label
&& ! utf8_label
)
2388 else if (old_label
&& utf8_label
)
2389 is_same
= strcmp (utf8_label
, old_label
) == 0;
2391 if (utf8_label
&& utf8_label
!= label
) g_free (utf8_label
);
2396 /* Destroy widgets in LIST. */
2399 xg_destroy_widgets (list
)
2404 for (iter
= list
; iter
; iter
= g_list_next (iter
))
2406 GtkWidget
*w
= GTK_WIDGET (iter
->data
);
2408 /* Destroying the widget will remove it from the container it is in. */
2409 gtk_widget_destroy (w
);
2413 /* Update the top level names in MENUBAR (i.e. not submenus).
2414 F is the frame the menu bar belongs to.
2415 *LIST is a list with the current menu bar names (menu item widgets).
2416 ITER is the item within *LIST that shall be updated.
2417 POS is the numerical position, starting at 0, of ITER in *LIST.
2418 VAL describes what the menu bar shall look like after the update.
2419 SELECT_CB is the callback to use when a menu item is selected.
2420 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
2421 CL_DATA points to the callback data to be used for this menu bar.
2423 This function calls itself to walk through the menu bar names. */
2426 xg_update_menubar (menubar
, f
, list
, iter
, pos
, val
,
2427 select_cb
, deactivate_cb
, highlight_cb
, cl_data
)
2434 GCallback select_cb
;
2435 GCallback deactivate_cb
;
2436 GCallback highlight_cb
;
2437 xg_menu_cb_data
*cl_data
;
2439 if (! iter
&& ! val
)
2441 else if (iter
&& ! val
)
2443 /* Item(s) have been removed. Remove all remaining items. */
2444 xg_destroy_widgets (iter
);
2450 else if (! iter
&& val
)
2452 /* Item(s) added. Add all new items in one call. */
2453 create_menus (val
, f
, select_cb
, deactivate_cb
, highlight_cb
,
2454 0, 1, 0, menubar
, cl_data
, 0);
2460 /* Below this neither iter or val is NULL */
2461 else if (xg_item_label_same_p (GTK_MENU_ITEM (iter
->data
), val
->name
))
2463 /* This item is still the same, check next item. */
2465 iter
= g_list_next (iter
);
2468 else /* This item is changed. */
2470 GtkMenuItem
*witem
= GTK_MENU_ITEM (iter
->data
);
2471 GtkMenuItem
*witem2
= 0;
2472 int val_in_menubar
= 0;
2473 int iter_in_new_menubar
= 0;
2477 /* See if the changed entry (val) is present later in the menu bar */
2479 iter2
&& ! val_in_menubar
;
2480 iter2
= g_list_next (iter2
))
2482 witem2
= GTK_MENU_ITEM (iter2
->data
);
2483 val_in_menubar
= xg_item_label_same_p (witem2
, val
->name
);
2486 /* See if the current entry (iter) is present later in the
2487 specification for the new menu bar. */
2488 for (cur
= val
; cur
&& ! iter_in_new_menubar
; cur
= cur
->next
)
2489 iter_in_new_menubar
= xg_item_label_same_p (witem
, cur
->name
);
2491 if (val_in_menubar
&& ! iter_in_new_menubar
)
2495 /* This corresponds to:
2500 gtk_widget_ref (GTK_WIDGET (witem
));
2501 gtk_container_remove (GTK_CONTAINER (menubar
), GTK_WIDGET (witem
));
2502 gtk_widget_destroy (GTK_WIDGET (witem
));
2504 /* Must get new list since the old changed. */
2505 g_list_free (*list
);
2506 *list
= iter
= gtk_container_get_children (GTK_CONTAINER (menubar
));
2507 while (nr
-- > 0) iter
= g_list_next (iter
);
2509 else if (! val_in_menubar
&& ! iter_in_new_menubar
)
2511 /* This corresponds to:
2514 Rename B to X. This might seem to be a strange thing to do,
2515 since if there is a menu under B it will be totally wrong for X.
2516 But consider editing a C file. Then there is a C-mode menu
2517 (corresponds to B above).
2518 If then doing C-x C-f the minibuf menu (X above) replaces the
2519 C-mode menu. When returning from the minibuffer, we get
2520 back the C-mode menu. Thus we do:
2521 Rename B to X (C-mode to minibuf menu)
2522 Rename X to B (minibuf to C-mode menu).
2523 If the X menu hasn't been invoked, the menu under B
2524 is up to date when leaving the minibuffer. */
2525 GtkLabel
*wlabel
= GTK_LABEL (gtk_bin_get_child (GTK_BIN (witem
)));
2526 char *utf8_label
= get_utf8_string (val
->name
);
2527 GtkWidget
*submenu
= gtk_menu_item_get_submenu (witem
);
2529 gtk_label_set_text (wlabel
, utf8_label
);
2531 /* If this item has a submenu that has been detached, change
2532 the title in the WM decorations also. */
2533 if (submenu
&& gtk_menu_get_tearoff_state (GTK_MENU (submenu
)))
2534 /* Set the title of the detached window. */
2535 gtk_menu_set_title (GTK_MENU (submenu
), utf8_label
);
2537 iter
= g_list_next (iter
);
2541 else if (! val_in_menubar
&& iter_in_new_menubar
)
2543 /* This corresponds to:
2550 GtkWidget
*w
= xg_create_one_menuitem (val
,
2557 /* Create a possibly empty submenu for menu bar items, since some
2558 themes don't highlight items correctly without it. */
2559 GtkWidget
*submenu
= create_menus (NULL
, f
,
2560 select_cb
, deactivate_cb
,
2562 0, 0, 0, 0, cl_data
, 0);
2563 gtk_widget_set_name (w
, MENU_ITEM_NAME
);
2564 gtk_menu_shell_insert (GTK_MENU_SHELL (menubar
), w
, pos
);
2565 gtk_menu_item_set_submenu (GTK_MENU_ITEM (w
), submenu
);
2567 g_list_free (*list
);
2568 *list
= iter
= gtk_container_get_children (GTK_CONTAINER (menubar
));
2569 while (nr
-- > 0) iter
= g_list_next (iter
);
2570 iter
= g_list_next (iter
);
2574 else /* if (val_in_menubar && iter_in_new_menubar) */
2577 /* This corresponds to:
2582 gtk_widget_ref (GTK_WIDGET (witem2
));
2583 gtk_container_remove (GTK_CONTAINER (menubar
), GTK_WIDGET (witem2
));
2584 gtk_menu_shell_insert (GTK_MENU_SHELL (menubar
),
2585 GTK_WIDGET (witem2
), pos
);
2586 gtk_widget_unref (GTK_WIDGET (witem2
));
2588 g_list_free (*list
);
2589 *list
= iter
= gtk_container_get_children (GTK_CONTAINER (menubar
));
2590 while (nr
-- > 0) iter
= g_list_next (iter
);
2591 if (iter
) iter
= g_list_next (iter
);
2597 /* Update the rest of the menu bar. */
2598 xg_update_menubar (menubar
, f
, list
, iter
, pos
, val
,
2599 select_cb
, deactivate_cb
, highlight_cb
, cl_data
);
2602 /* Update the menu item W so it corresponds to VAL.
2603 SELECT_CB is the callback to use when a menu item is selected.
2604 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
2605 CL_DATA is the data to set in the widget for menu invocation. */
2608 xg_update_menu_item (val
, w
, select_cb
, highlight_cb
, cl_data
)
2611 GCallback select_cb
;
2612 GCallback highlight_cb
;
2613 xg_menu_cb_data
*cl_data
;
2620 const char *old_label
= 0;
2621 const char *old_key
= 0;
2622 xg_menu_item_cb_data
*cb_data
;
2624 wchild
= gtk_bin_get_child (GTK_BIN (w
));
2625 utf8_label
= get_utf8_string (val
->name
);
2626 utf8_key
= get_utf8_string (val
->key
);
2628 /* See if W is a menu item with a key. See make_menu_item above. */
2629 if (GTK_IS_HBOX (wchild
))
2631 GList
*list
= gtk_container_get_children (GTK_CONTAINER (wchild
));
2633 wlbl
= GTK_LABEL (list
->data
);
2634 wkey
= GTK_LABEL (list
->next
->data
);
2639 /* Remove the key and keep just the label. */
2640 gtk_widget_ref (GTK_WIDGET (wlbl
));
2641 gtk_container_remove (GTK_CONTAINER (w
), wchild
);
2642 gtk_container_add (GTK_CONTAINER (w
), GTK_WIDGET (wlbl
));
2647 else /* Just a label. */
2649 wlbl
= GTK_LABEL (wchild
);
2651 /* Check if there is now a key. */
2654 GtkWidget
*wtoadd
= make_widget_for_menu_item (utf8_label
, utf8_key
);
2655 GList
*list
= gtk_container_get_children (GTK_CONTAINER (wtoadd
));
2657 wlbl
= GTK_LABEL (list
->data
);
2658 wkey
= GTK_LABEL (list
->next
->data
);
2661 gtk_container_remove (GTK_CONTAINER (w
), wchild
);
2662 gtk_container_add (GTK_CONTAINER (w
), wtoadd
);
2667 if (wkey
) old_key
= gtk_label_get_label (wkey
);
2668 if (wlbl
) old_label
= gtk_label_get_label (wlbl
);
2670 if (wkey
&& utf8_key
&& (! old_key
|| strcmp (utf8_key
, old_key
) != 0))
2671 gtk_label_set_text (wkey
, utf8_key
);
2673 if (! old_label
|| strcmp (utf8_label
, old_label
) != 0)
2674 gtk_label_set_text (wlbl
, utf8_label
);
2676 if (utf8_key
&& utf8_key
!= val
->key
) g_free (utf8_key
);
2677 if (utf8_label
&& utf8_label
!= val
->name
) g_free (utf8_label
);
2679 if (! val
->enabled
&& GTK_WIDGET_SENSITIVE (w
))
2680 gtk_widget_set_sensitive (w
, FALSE
);
2681 else if (val
->enabled
&& ! GTK_WIDGET_SENSITIVE (w
))
2682 gtk_widget_set_sensitive (w
, TRUE
);
2684 cb_data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (w
),
2688 cb_data
->call_data
= val
->call_data
;
2689 cb_data
->help
= val
->help
;
2690 cb_data
->cl_data
= cl_data
;
2692 /* We assume the callback functions don't change. */
2693 if (val
->call_data
&& ! val
->contents
)
2695 /* This item shall have a select callback. */
2696 if (! cb_data
->select_id
)
2698 = g_signal_connect (G_OBJECT (w
), "activate",
2699 select_cb
, cb_data
);
2701 else if (cb_data
->select_id
)
2703 g_signal_handler_disconnect (w
, cb_data
->select_id
);
2704 cb_data
->select_id
= 0;
2709 /* Update the toggle menu item W so it corresponds to VAL. */
2712 xg_update_toggle_item (val
, w
)
2716 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w
), val
->selected
);
2719 /* Update the radio menu item W so it corresponds to VAL. */
2722 xg_update_radio_item (val
, w
)
2726 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (w
), val
->selected
);
2729 /* Update the sub menu SUBMENU and all its children so it corresponds to VAL.
2730 SUBMENU may be NULL, in that case a new menu is created.
2731 F is the frame the menu bar belongs to.
2732 VAL describes the contents of the menu bar.
2733 SELECT_CB is the callback to use when a menu item is selected.
2734 DEACTIVATE_CB is the callback to use when a sub menu is not shown anymore.
2735 HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
2736 CL_DATA is the call back data to use for any newly created items.
2738 Returns the updated submenu widget, that is SUBMENU unless SUBMENU
2742 xg_update_submenu (submenu
, f
, val
,
2743 select_cb
, deactivate_cb
, highlight_cb
, cl_data
)
2747 GCallback select_cb
;
2748 GCallback deactivate_cb
;
2749 GCallback highlight_cb
;
2750 xg_menu_cb_data
*cl_data
;
2752 GtkWidget
*newsub
= submenu
;
2756 int has_tearoff_p
= 0;
2757 GList
*first_radio
= 0;
2760 list
= gtk_container_get_children (GTK_CONTAINER (submenu
));
2762 for (cur
= val
, iter
= list
;
2764 iter
= g_list_next (iter
), cur
= cur
->next
)
2766 GtkWidget
*w
= GTK_WIDGET (iter
->data
);
2768 /* Skip tearoff items, they have no counterpart in val. */
2769 if (GTK_IS_TEAROFF_MENU_ITEM (w
))
2772 iter
= g_list_next (iter
);
2773 if (iter
) w
= GTK_WIDGET (iter
->data
);
2777 /* Remember first radio button in a group. If we get a mismatch in
2778 a radio group we must rebuild the whole group so that the connections
2779 in GTK becomes correct. */
2780 if (cur
->button_type
== BUTTON_TYPE_RADIO
&& ! first_radio
)
2782 else if (cur
->button_type
!= BUTTON_TYPE_RADIO
2783 && ! GTK_IS_RADIO_MENU_ITEM (w
))
2786 if (GTK_IS_SEPARATOR_MENU_ITEM (w
))
2788 if (! xg_separator_p (cur
->name
))
2791 else if (GTK_IS_CHECK_MENU_ITEM (w
))
2793 if (cur
->button_type
!= BUTTON_TYPE_TOGGLE
)
2795 xg_update_toggle_item (cur
, w
);
2796 xg_update_menu_item (cur
, w
, select_cb
, highlight_cb
, cl_data
);
2798 else if (GTK_IS_RADIO_MENU_ITEM (w
))
2800 if (cur
->button_type
!= BUTTON_TYPE_RADIO
)
2802 xg_update_radio_item (cur
, w
);
2803 xg_update_menu_item (cur
, w
, select_cb
, highlight_cb
, cl_data
);
2805 else if (GTK_IS_MENU_ITEM (w
))
2807 GtkMenuItem
*witem
= GTK_MENU_ITEM (w
);
2810 if (cur
->button_type
!= BUTTON_TYPE_NONE
||
2811 xg_separator_p (cur
->name
))
2814 xg_update_menu_item (cur
, w
, select_cb
, highlight_cb
, cl_data
);
2816 sub
= gtk_menu_item_get_submenu (witem
);
2817 if (sub
&& ! cur
->contents
)
2819 /* Not a submenu anymore. */
2820 gtk_widget_ref (sub
);
2821 gtk_menu_item_remove_submenu (witem
);
2822 gtk_widget_destroy (sub
);
2824 else if (cur
->contents
)
2828 nsub
= xg_update_submenu (sub
, f
, cur
->contents
,
2829 select_cb
, deactivate_cb
,
2830 highlight_cb
, cl_data
);
2832 /* If this item just became a submenu, we must set it. */
2834 gtk_menu_item_set_submenu (witem
, nsub
);
2839 /* Structural difference. Remove everything from here and down
2845 /* Remove widgets from first structual change. */
2848 /* If we are adding new menu items below, we must remove from
2849 first radio button so that radio groups become correct. */
2850 if (cur
&& first_radio
) xg_destroy_widgets (first_radio
);
2851 else xg_destroy_widgets (iter
);
2856 /* More items added. Create them. */
2857 newsub
= create_menus (cur
,
2870 if (list
) g_list_free (list
);
2875 /* Update the MENUBAR.
2876 F is the frame the menu bar belongs to.
2877 VAL describes the contents of the menu bar.
2878 If DEEP_P is non-zero, rebuild all but the top level menu names in
2879 the MENUBAR. If DEEP_P is zero, just rebuild the names in the menubar.
2880 SELECT_CB is the callback to use when a menu item is selected.
2881 DEACTIVATE_CB is the callback to use when a sub menu is not shown anymore.
2882 HIGHLIGHT_CB is the callback to call when entering/leaving menu items. */
2885 xg_modify_menubar_widgets (menubar
, f
, val
, deep_p
,
2886 select_cb
, deactivate_cb
, highlight_cb
)
2891 GCallback select_cb
;
2892 GCallback deactivate_cb
;
2893 GCallback highlight_cb
;
2895 xg_menu_cb_data
*cl_data
;
2896 GList
*list
= gtk_container_get_children (GTK_CONTAINER (menubar
));
2900 cl_data
= (xg_menu_cb_data
*) g_object_get_data (G_OBJECT (menubar
),
2903 xg_update_menubar (menubar
, f
, &list
, list
, 0, val
->contents
,
2904 select_cb
, deactivate_cb
, highlight_cb
, cl_data
);
2910 /* Update all sub menus.
2911 We must keep the submenus (GTK menu item widgets) since the
2912 X Window in the XEvent that activates the menu are those widgets. */
2914 /* Update cl_data, menu_item things in F may have changed. */
2915 update_cl_data (cl_data
, f
, highlight_cb
);
2917 for (cur
= val
->contents
; cur
; cur
= cur
->next
)
2924 /* Find sub menu that corresponds to val and update it. */
2925 for (iter
= list
; iter
; iter
= g_list_next (iter
))
2927 witem
= GTK_MENU_ITEM (iter
->data
);
2928 if (xg_item_label_same_p (witem
, cur
->name
))
2930 sub
= gtk_menu_item_get_submenu (witem
);
2935 newsub
= xg_update_submenu (sub
,
2942 /* sub may still be NULL. If we just updated non deep and added
2943 a new menu bar item, it has no sub menu yet. So we set the
2944 newly created sub menu under witem. */
2947 xg_set_screen (newsub
, f
);
2948 gtk_menu_item_set_submenu (witem
, newsub
);
2954 gtk_widget_show_all (menubar
);
2957 /* Recompute all the widgets of frame F, when the menu bar has been
2958 changed. Value is non-zero if widgets were updated. */
2961 xg_update_frame_menubar (f
)
2964 struct x_output
*x
= f
->output_data
.x
;
2967 if (!x
->menubar_widget
|| GTK_WIDGET_MAPPED (x
->menubar_widget
))
2972 gtk_box_pack_start (GTK_BOX (x
->vbox_widget
), x
->menubar_widget
,
2974 gtk_box_reorder_child (GTK_BOX (x
->vbox_widget
), x
->menubar_widget
, 0);
2976 gtk_widget_show_all (x
->menubar_widget
);
2977 gtk_widget_size_request (x
->menubar_widget
, &req
);
2978 FRAME_MENUBAR_HEIGHT (f
) = req
.height
;
2979 xg_height_changed (f
);
2985 /* Get rid of the menu bar of frame F, and free its storage.
2986 This is used when deleting a frame, and when turning off the menu bar. */
2989 free_frame_menubar (f
)
2992 struct x_output
*x
= f
->output_data
.x
;
2994 if (x
->menubar_widget
)
2998 gtk_container_remove (GTK_CONTAINER (x
->vbox_widget
), x
->menubar_widget
);
2999 /* The menubar and its children shall be deleted when removed from
3001 x
->menubar_widget
= 0;
3002 FRAME_MENUBAR_HEIGHT (f
) = 0;
3003 xg_height_changed (f
);
3010 /***********************************************************************
3011 Scroll bar functions
3012 ***********************************************************************/
3015 /* Setting scroll bar values invokes the callback. Use this variable
3016 to indicate that callback should do nothing. */
3018 int xg_ignore_gtk_scrollbar
;
3020 /* Xlib's `Window' fits in 32 bits. But we want to store pointers, and they
3021 may be larger than 32 bits. Keep a mapping from integer index to widget
3022 pointers to get around the 32 bit limitation. */
3026 GtkWidget
**widgets
;
3031 /* Grow this much every time we need to allocate more */
3033 #define ID_TO_WIDGET_INCR 32
3035 /* Store the widget pointer W in id_to_widget and return the integer index. */
3038 xg_store_widget_in_map (w
)
3043 if (id_to_widget
.max_size
== id_to_widget
.used
)
3045 int new_size
= id_to_widget
.max_size
+ ID_TO_WIDGET_INCR
;
3047 id_to_widget
.widgets
= xrealloc (id_to_widget
.widgets
,
3048 sizeof (GtkWidget
*)*new_size
);
3050 for (i
= id_to_widget
.max_size
; i
< new_size
; ++i
)
3051 id_to_widget
.widgets
[i
] = 0;
3052 id_to_widget
.max_size
= new_size
;
3055 /* Just loop over the array and find a free place. After all,
3056 how many scroll bars are we creating? Should be a small number.
3057 The check above guarantees we will find a free place. */
3058 for (i
= 0; i
< id_to_widget
.max_size
; ++i
)
3060 if (! id_to_widget
.widgets
[i
])
3062 id_to_widget
.widgets
[i
] = w
;
3063 ++id_to_widget
.used
;
3069 /* Should never end up here */
3073 /* Remove pointer at IDX from id_to_widget.
3074 Called when scroll bar is destroyed. */
3077 xg_remove_widget_from_map (idx
)
3080 if (idx
< id_to_widget
.max_size
&& id_to_widget
.widgets
[idx
] != 0)
3082 id_to_widget
.widgets
[idx
] = 0;
3083 --id_to_widget
.used
;
3087 /* Get the widget pointer at IDX from id_to_widget. */
3090 xg_get_widget_from_map (idx
)
3093 if (idx
< id_to_widget
.max_size
&& id_to_widget
.widgets
[idx
] != 0)
3094 return id_to_widget
.widgets
[idx
];
3099 /* Return the scrollbar id for X Window WID on display DPY.
3100 Return -1 if WID not in id_to_widget. */
3103 xg_get_scroll_id_for_window (dpy
, wid
)
3110 w
= xg_win_to_widget (dpy
, wid
);
3114 for (idx
= 0; idx
< id_to_widget
.max_size
; ++idx
)
3115 if (id_to_widget
.widgets
[idx
] == w
)
3122 /* Callback invoked when scroll bar WIDGET is destroyed.
3123 DATA is the index into id_to_widget for WIDGET.
3124 We free pointer to last scroll bar values here and remove the index. */
3127 xg_gtk_scroll_destroy (widget
, data
)
3132 int id
= (int) (EMACS_INT
) data
; /* The EMACS_INT cast avoids a warning. */
3134 p
= g_object_get_data (G_OBJECT (widget
), XG_LAST_SB_DATA
);
3136 xg_remove_widget_from_map (id
);
3139 /* Callback for button press/release events. Used to start timer so that
3140 the scroll bar repetition timer in GTK gets handled.
3141 Also, sets bar->dragging to Qnil when dragging (button release) is done.
3142 WIDGET is the scroll bar widget the event is for (not used).
3143 EVENT contains the event.
3144 USER_DATA points to the struct scrollbar structure.
3146 Returns FALSE to tell GTK that it shall continue propagate the event
3150 scroll_bar_button_cb (widget
, event
, user_data
)
3152 GdkEventButton
*event
;
3155 if (event
->type
== GDK_BUTTON_PRESS
&& ! xg_timer
)
3157 else if (event
->type
== GDK_BUTTON_RELEASE
)
3159 struct scroll_bar
*bar
= (struct scroll_bar
*) user_data
;
3160 if (xg_timer
) xg_stop_timer ();
3161 bar
->dragging
= Qnil
;
3167 /* Create a scroll bar widget for frame F. Store the scroll bar
3169 SCROLL_CALLBACK is the callback to invoke when the value of the
3171 SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used
3172 to set resources for the widget. */
3175 xg_create_scroll_bar (f
, bar
, scroll_callback
, scroll_bar_name
)
3177 struct scroll_bar
*bar
;
3178 GCallback scroll_callback
;
3179 char *scroll_bar_name
;
3186 /* Page, step increment values are not so important here, they
3187 will be corrected in x_set_toolkit_scroll_bar_thumb. */
3188 vadj
= gtk_adjustment_new (XG_SB_MIN
, XG_SB_MIN
, XG_SB_MAX
,
3191 wscroll
= gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj
));
3192 webox
= gtk_event_box_new ();
3193 gtk_widget_set_name (wscroll
, scroll_bar_name
);
3194 gtk_range_set_update_policy (GTK_RANGE (wscroll
), GTK_UPDATE_CONTINUOUS
);
3196 scroll_id
= xg_store_widget_in_map (wscroll
);
3198 g_signal_connect (G_OBJECT (wscroll
),
3202 /* The EMACS_INT cast avoids a warning. */
3203 g_signal_connect (G_OBJECT (wscroll
),
3205 G_CALLBACK (xg_gtk_scroll_destroy
),
3206 (gpointer
) (EMACS_INT
) scroll_id
);
3208 /* Connect to button press and button release to detect if any scroll bar
3210 g_signal_connect (G_OBJECT (wscroll
),
3211 "button-press-event",
3212 G_CALLBACK (scroll_bar_button_cb
),
3214 g_signal_connect (G_OBJECT (wscroll
),
3215 "button-release-event",
3216 G_CALLBACK (scroll_bar_button_cb
),
3219 /* The scroll bar widget does not draw on a window of its own. Instead
3220 it draws on the parent window, in this case the edit widget. So
3221 whenever the edit widget is cleared, the scroll bar needs to redraw
3222 also, which causes flicker. Put an event box between the edit widget
3223 and the scroll bar, so the scroll bar instead draws itself on the
3224 event box window. */
3225 gtk_fixed_put (GTK_FIXED (f
->output_data
.x
->edit_widget
), webox
, -1, -1);
3226 gtk_container_add (GTK_CONTAINER (webox
), wscroll
);
3229 /* Set the cursor to an arrow. */
3230 xg_set_cursor (webox
, FRAME_X_DISPLAY_INFO (f
)->xg_cursor
);
3232 bar
->x_window
= scroll_id
;
3235 /* Make the scroll bar represented by SCROLLBAR_ID visible. */
3238 xg_show_scroll_bar (scrollbar_id
)
3241 GtkWidget
*w
= xg_get_widget_from_map (scrollbar_id
);
3243 gtk_widget_show_all (gtk_widget_get_parent (w
));
3246 /* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */
3249 xg_remove_scroll_bar (f
, scrollbar_id
)
3253 GtkWidget
*w
= xg_get_widget_from_map (scrollbar_id
);
3256 GtkWidget
*wparent
= gtk_widget_get_parent (w
);
3257 gtk_widget_destroy (w
);
3258 gtk_widget_destroy (wparent
);
3259 SET_FRAME_GARBAGED (f
);
3263 /* Update the position of the vertical scroll bar represented by SCROLLBAR_ID
3265 TOP/LEFT are the new pixel positions where the bar shall appear.
3266 WIDTH, HEIGHT is the size in pixels the bar shall have. */
3269 xg_update_scrollbar_pos (f
, scrollbar_id
, top
, left
, width
, height
)
3278 GtkWidget
*wscroll
= xg_get_widget_from_map (scrollbar_id
);
3282 GtkWidget
*wfixed
= f
->output_data
.x
->edit_widget
;
3283 GtkWidget
*wparent
= gtk_widget_get_parent (wscroll
);
3285 /* Move and resize to new values. */
3286 gtk_fixed_move (GTK_FIXED (wfixed
), wparent
, left
, top
);
3287 gtk_widget_set_size_request (wscroll
, width
, height
);
3288 gtk_widget_queue_draw (wparent
);
3289 gdk_window_process_all_updates ();
3290 /* GTK does not redraw until the main loop is entered again, but
3291 if there are no X events pending we will not enter it. So we sync
3292 here to get some events. */
3294 SET_FRAME_GARBAGED (f
);
3295 cancel_mouse_face (f
);
3299 /* Set the thumb size and position of scroll bar BAR. We are currently
3300 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3303 xg_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
3304 struct scroll_bar
*bar
;
3305 int portion
, position
, whole
;
3307 GtkWidget
*wscroll
= xg_get_widget_from_map (bar
->x_window
);
3309 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3311 if (wscroll
&& NILP (bar
->dragging
))
3320 adj
= gtk_range_get_adjustment (GTK_RANGE (wscroll
));
3322 /* We do the same as for MOTIF in xterm.c, assume 30 chars per line
3323 rather than the real portion value. This makes the thumb less likely
3324 to resize and that looks better. */
3325 portion
= WINDOW_TOTAL_LINES (XWINDOW (bar
->window
)) * 30;
3326 /* When the thumb is at the bottom, position == whole.
3327 So we need to increase `whole' to make space for the thumb. */
3334 top
= (gdouble
) position
/ whole
;
3335 shown
= (gdouble
) portion
/ whole
;
3338 size
= shown
* XG_SB_RANGE
;
3339 size
= min (size
, XG_SB_RANGE
);
3340 size
= max (size
, 1);
3342 value
= top
* XG_SB_RANGE
;
3343 value
= min (value
, XG_SB_MAX
- size
);
3344 value
= max (value
, XG_SB_MIN
);
3346 /* Assume all lines are of equal size. */
3347 new_step
= size
/ max (1, FRAME_LINES (f
));
3349 if ((int) adj
->page_size
!= size
3350 || (int) adj
->step_increment
!= new_step
)
3352 adj
->page_size
= size
;
3353 adj
->step_increment
= new_step
;
3354 /* Assume a page increment is about 95% of the page size */
3355 adj
->page_increment
= (int) (0.95*adj
->page_size
);
3359 if (changed
|| (int) gtk_range_get_value (GTK_RANGE (wscroll
)) != value
)
3361 GtkWidget
*wfixed
= f
->output_data
.x
->edit_widget
;
3365 /* gtk_range_set_value invokes the callback. Set
3366 ignore_gtk_scrollbar to make the callback do nothing */
3367 xg_ignore_gtk_scrollbar
= 1;
3369 if ((int) gtk_range_get_value (GTK_RANGE (wscroll
)) != value
)
3370 gtk_range_set_value (GTK_RANGE (wscroll
), (gdouble
)value
);
3372 gtk_adjustment_changed (adj
);
3374 xg_ignore_gtk_scrollbar
= 0;
3382 /***********************************************************************
3384 ***********************************************************************/
3385 /* The key for the data we put in the GtkImage widgets. The data is
3386 the image used by Emacs. We use this to see if we need to update
3387 the GtkImage with a new image. */
3388 #define XG_TOOL_BAR_IMAGE_DATA "emacs-tool-bar-image"
3390 /* The key for storing the latest modifiers so the activate callback can
3392 #define XG_TOOL_BAR_LAST_MODIFIER "emacs-tool-bar-modifier"
3394 /* The key for storing the button widget in its proxy menu item. */
3395 #define XG_TOOL_BAR_PROXY_BUTTON "emacs-tool-bar-proxy-button"
3397 /* The key for the data we put in the GtkImage widgets. The data is
3398 the stock name used by Emacs. We use this to see if we need to update
3399 the GtkImage with a new image. */
3400 #define XG_TOOL_BAR_STOCK_NAME "emacs-tool-bar-stock-name"
3402 /* As above, but this is used for named theme widgets, as opposed to
3404 #define XG_TOOL_BAR_ICON_NAME "emacs-tool-bar-icon-name"
3406 /* Callback function invoked when a tool bar item is pressed.
3407 W is the button widget in the tool bar that got pressed,
3408 CLIENT_DATA is an integer that is the index of the button in the
3409 tool bar. 0 is the first button. */
3412 xg_tool_bar_button_cb (widget
, event
, user_data
)
3414 GdkEventButton
*event
;
3417 /* Casts to avoid warnings when gpointer is 64 bits and int is 32 bits */
3418 gpointer ptr
= (gpointer
) (EMACS_INT
) event
->state
;
3419 g_object_set_data (G_OBJECT (widget
), XG_TOOL_BAR_LAST_MODIFIER
, ptr
);
3424 /* Callback function invoked when a tool bar item is pressed.
3425 W is the button widget in the tool bar that got pressed,
3426 CLIENT_DATA is an integer that is the index of the button in the
3427 tool bar. 0 is the first button. */
3430 xg_tool_bar_callback (w
, client_data
)
3432 gpointer client_data
;
3434 /* The EMACS_INT cast avoids a warning. */
3435 int idx
= (int) (EMACS_INT
) client_data
;
3436 int mod
= (int) (EMACS_INT
) g_object_get_data (G_OBJECT (w
),
3437 XG_TOOL_BAR_LAST_MODIFIER
);
3439 FRAME_PTR f
= (FRAME_PTR
) g_object_get_data (G_OBJECT (w
), XG_FRAME_DATA
);
3440 Lisp_Object key
, frame
;
3441 struct input_event event
;
3444 if (! f
|| ! f
->n_tool_bar_items
|| NILP (f
->tool_bar_items
))
3447 idx
*= TOOL_BAR_ITEM_NSLOTS
;
3449 key
= AREF (f
->tool_bar_items
, idx
+ TOOL_BAR_ITEM_KEY
);
3450 XSETFRAME (frame
, f
);
3452 /* We generate two events here. The first one is to set the prefix
3453 to `(tool_bar)', see keyboard.c. */
3454 event
.kind
= TOOL_BAR_EVENT
;
3455 event
.frame_or_window
= frame
;
3457 kbd_buffer_store_event (&event
);
3459 event
.kind
= TOOL_BAR_EVENT
;
3460 event
.frame_or_window
= frame
;
3462 /* Convert between the modifier bits GDK uses and the modifier bits
3463 Emacs uses. This assumes GDK and X masks are the same, which they are when
3465 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
), mod
);
3466 kbd_buffer_store_event (&event
);
3468 /* Return focus to the frame after we have clicked on a detached
3470 Fx_focus_frame (frame
);
3473 /* Callback function invoked when a tool bar item is pressed in a detached
3474 tool bar or the overflow drop down menu.
3475 We just call xg_tool_bar_callback.
3476 W is the menu item widget that got pressed,
3477 CLIENT_DATA is an integer that is the index of the button in the
3478 tool bar. 0 is the first button. */
3481 xg_tool_bar_proxy_callback (w
, client_data
)
3483 gpointer client_data
;
3485 GtkWidget
*wbutton
= GTK_WIDGET (g_object_get_data (G_OBJECT (w
),
3486 XG_TOOL_BAR_PROXY_BUTTON
));
3487 xg_tool_bar_callback (wbutton
, client_data
);
3492 xg_tool_bar_help_callback
P_ ((GtkWidget
*w
,
3493 GdkEventCrossing
*event
,
3494 gpointer client_data
));
3496 /* This callback is called when a help is to be shown for an item in
3497 the detached tool bar when the detached tool bar it is not expanded. */
3500 xg_tool_bar_proxy_help_callback (w
, event
, client_data
)
3502 GdkEventCrossing
*event
;
3503 gpointer client_data
;
3505 GtkWidget
*wbutton
= GTK_WIDGET (g_object_get_data (G_OBJECT (w
),
3506 XG_TOOL_BAR_PROXY_BUTTON
));
3508 xg_tool_bar_help_callback (wbutton
, event
, client_data
);
3512 /* This callback is called when a tool item should create a proxy item,
3513 such as for the overflow menu. Also called when the tool bar is detached.
3514 If we don't create a proxy menu item, the detached tool bar will be
3518 xg_tool_bar_menu_proxy (toolitem
, user_data
)
3519 GtkToolItem
*toolitem
;
3522 GtkWidget
*weventbox
= gtk_bin_get_child (GTK_BIN (toolitem
));
3523 GtkButton
*wbutton
= GTK_BUTTON (gtk_bin_get_child (GTK_BIN (weventbox
)));
3524 GtkWidget
*wmenuitem
= gtk_image_menu_item_new_with_label ("");
3525 GtkWidget
*wmenuimage
;
3527 if (gtk_button_get_use_stock (wbutton
))
3528 wmenuimage
= gtk_image_new_from_stock (gtk_button_get_label (wbutton
),
3529 GTK_ICON_SIZE_MENU
);
3532 GtkImage
*wimage
= GTK_IMAGE (gtk_bin_get_child (GTK_BIN (wbutton
)));
3533 GtkSettings
*settings
= gtk_widget_get_settings (GTK_WIDGET (wbutton
));
3534 GtkImageType store_type
= gtk_image_get_storage_type (wimage
);
3536 if (store_type
== GTK_IMAGE_STOCK
)
3539 gtk_image_get_stock (wimage
, &stock_id
, NULL
);
3540 wmenuimage
= gtk_image_new_from_stock (stock_id
, GTK_ICON_SIZE_MENU
);
3542 else if (store_type
== GTK_IMAGE_ICON_SET
)
3544 GtkIconSet
*icon_set
;
3545 gtk_image_get_icon_set (wimage
, &icon_set
, NULL
);
3546 wmenuimage
= gtk_image_new_from_icon_set (icon_set
,
3547 GTK_ICON_SIZE_MENU
);
3549 else if (store_type
== GTK_IMAGE_PIXBUF
)
3554 gtk_icon_size_lookup_for_settings (settings
, GTK_ICON_SIZE_MENU
,
3557 GdkPixbuf
*src_pixbuf
, *dest_pixbuf
;
3559 src_pixbuf
= gtk_image_get_pixbuf (wimage
);
3560 dest_pixbuf
= gdk_pixbuf_scale_simple (src_pixbuf
, width
, height
,
3561 GDK_INTERP_BILINEAR
);
3563 wmenuimage
= gtk_image_new_from_pixbuf (dest_pixbuf
);
3567 fprintf (stderr
, "internal error: GTK_IMAGE_PIXBUF failed\n");
3571 else if (store_type
== GTK_IMAGE_ICON_NAME
)
3573 const gchar
*icon_name
;
3574 GtkIconSize icon_size
;
3576 gtk_image_get_icon_name (wimage
, &icon_name
, &icon_size
);
3577 wmenuimage
= gtk_image_new_from_icon_name (icon_name
,
3578 GTK_ICON_SIZE_MENU
);
3582 fprintf (stderr
, "internal error: store_type is %d\n", store_type
);
3587 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (wmenuitem
), wmenuimage
);
3589 g_signal_connect (G_OBJECT (wmenuitem
),
3591 G_CALLBACK (xg_tool_bar_proxy_callback
),
3595 g_object_set_data (G_OBJECT (wmenuitem
), XG_TOOL_BAR_PROXY_BUTTON
,
3596 (gpointer
) wbutton
);
3597 gtk_tool_item_set_proxy_menu_item (toolitem
, "Emacs toolbar item", wmenuitem
);
3598 gtk_widget_set_sensitive (wmenuitem
, GTK_WIDGET_SENSITIVE (wbutton
));
3600 /* Use enter/leave notify to show help. We use the events
3601 rather than the GtkButton specific signals "enter" and
3602 "leave", so we can have only one callback. The event
3603 will tell us what kind of event it is. */
3604 g_signal_connect (G_OBJECT (wmenuitem
),
3605 "enter-notify-event",
3606 G_CALLBACK (xg_tool_bar_proxy_help_callback
),
3608 g_signal_connect (G_OBJECT (wmenuitem
),
3609 "leave-notify-event",
3610 G_CALLBACK (xg_tool_bar_proxy_help_callback
),
3616 /* This callback is called when a tool bar is detached. We must set
3617 the height of the tool bar to zero when this happens so frame sizes
3618 are correctly calculated.
3619 WBOX is the handle box widget that enables detach/attach of the tool bar.
3620 W is the tool bar widget.
3621 CLIENT_DATA is a pointer to the frame the tool bar belongs to. */
3624 xg_tool_bar_detach_callback (wbox
, w
, client_data
)
3627 gpointer client_data
;
3629 FRAME_PTR f
= (FRAME_PTR
) client_data
;
3630 extern int x_gtk_whole_detached_tool_bar
;
3632 g_object_set (G_OBJECT (w
), "show-arrow", !x_gtk_whole_detached_tool_bar
,
3637 FRAME_X_OUTPUT (f
)->toolbar_detached
= 1;
3639 /* When detaching a tool bar, not everything dissapear. There are
3640 a few pixels left that are used to drop the tool bar back into
3642 FRAME_TOOLBAR_HEIGHT (f
) = 4;
3643 xg_height_changed (f
);
3647 /* This callback is called when a tool bar is reattached. We must set
3648 the height of the tool bar when this happens so frame sizes
3649 are correctly calculated.
3650 WBOX is the handle box widget that enables detach/attach of the tool bar.
3651 W is the tool bar widget.
3652 CLIENT_DATA is a pointer to the frame the tool bar belongs to. */
3655 xg_tool_bar_attach_callback (wbox
, w
, client_data
)
3658 gpointer client_data
;
3660 FRAME_PTR f
= (FRAME_PTR
) client_data
;
3661 g_object_set (G_OBJECT (w
), "show-arrow", TRUE
, NULL
);
3667 FRAME_X_OUTPUT (f
)->toolbar_detached
= 0;
3669 gtk_widget_size_request (w
, &req
);
3670 FRAME_TOOLBAR_HEIGHT (f
) = req
.height
;
3671 xg_height_changed (f
);
3675 /* This callback is called when the mouse enters or leaves a tool bar item.
3676 It is used for displaying and hiding the help text.
3677 W is the tool bar item, a button.
3678 EVENT is either an enter event or leave event.
3679 CLIENT_DATA is an integer that is the index of the button in the
3680 tool bar. 0 is the first button.
3682 Returns FALSE to tell GTK to keep processing this event. */
3685 xg_tool_bar_help_callback (w
, event
, client_data
)
3687 GdkEventCrossing
*event
;
3688 gpointer client_data
;
3690 /* The EMACS_INT cast avoids a warning. */
3691 int idx
= (int) (EMACS_INT
) client_data
;
3692 FRAME_PTR f
= (FRAME_PTR
) g_object_get_data (G_OBJECT (w
), XG_FRAME_DATA
);
3693 Lisp_Object help
, frame
;
3695 if (! f
|| ! f
->n_tool_bar_items
|| NILP (f
->tool_bar_items
))
3698 if (event
->type
== GDK_ENTER_NOTIFY
)
3700 idx
*= TOOL_BAR_ITEM_NSLOTS
;
3701 help
= AREF (f
->tool_bar_items
, idx
+ TOOL_BAR_ITEM_HELP
);
3704 help
= AREF (f
->tool_bar_items
, idx
+ TOOL_BAR_ITEM_CAPTION
);
3709 XSETFRAME (frame
, f
);
3710 kbd_buffer_store_help_event (frame
, help
);
3716 /* This callback is called when a tool bar item shall be redrawn.
3717 It modifies the expose event so that the GtkImage widget redraws the
3718 whole image. This to overcome a bug that makes GtkImage draw the image
3719 in the wrong place when it tries to redraw just a part of the image.
3720 W is the GtkImage to be redrawn.
3721 EVENT is the expose event for W.
3722 CLIENT_DATA is unused.
3724 Returns FALSE to tell GTK to keep processing this event. */
3727 xg_tool_bar_item_expose_callback (w
, event
, client_data
)
3729 GdkEventExpose
*event
;
3730 gpointer client_data
;
3734 gdk_drawable_get_size (event
->window
, &width
, &height
);
3736 event
->area
.x
-= width
> event
->area
.width
? width
-event
->area
.width
: 0;
3737 event
->area
.y
-= height
> event
->area
.height
? height
-event
->area
.height
: 0;
3739 event
->area
.x
= max (0, event
->area
.x
);
3740 event
->area
.y
= max (0, event
->area
.y
);
3742 event
->area
.width
= max (width
, event
->area
.width
);
3743 event
->area
.height
= max (height
, event
->area
.height
);
3748 /* Attach a tool bar to frame F. */
3751 xg_pack_tool_bar (f
)
3754 struct x_output
*x
= f
->output_data
.x
;
3755 int vbox_pos
= x
->menubar_widget
? 1 : 0;
3757 x
->handlebox_widget
= gtk_handle_box_new ();
3758 g_signal_connect (G_OBJECT (x
->handlebox_widget
), "child-detached",
3759 G_CALLBACK (xg_tool_bar_detach_callback
), f
);
3760 g_signal_connect (G_OBJECT (x
->handlebox_widget
), "child-attached",
3761 G_CALLBACK (xg_tool_bar_attach_callback
), f
);
3763 gtk_container_add (GTK_CONTAINER (x
->handlebox_widget
),
3766 gtk_box_pack_start (GTK_BOX (x
->vbox_widget
), x
->handlebox_widget
,
3769 gtk_box_reorder_child (GTK_BOX (x
->vbox_widget
), x
->handlebox_widget
,
3771 gtk_widget_show_all (x
->handlebox_widget
);
3774 /* Create a tool bar for frame F. */
3777 xg_create_tool_bar (f
)
3780 struct x_output
*x
= f
->output_data
.x
;
3783 x
->toolbar_widget
= gtk_toolbar_new ();
3784 x
->toolbar_detached
= 0;
3786 gtk_widget_set_name (x
->toolbar_widget
, "emacs-toolbar");
3788 /* We only have icons, so override any user setting. We could
3789 use the caption property of the toolbar item (see update_frame_tool_bar
3790 below), but some of those strings are long, making the toolbar so
3791 long it does not fit on the screen. The GtkToolbar widget makes every
3792 item equal size, so the longest caption determine the size of every
3793 tool bar item. I think the creators of the GtkToolbar widget
3794 counted on 4 or 5 character long strings. */
3795 gtk_toolbar_set_style (GTK_TOOLBAR (x
->toolbar_widget
), GTK_TOOLBAR_ICONS
);
3796 gtk_toolbar_set_orientation (GTK_TOOLBAR (x
->toolbar_widget
),
3797 GTK_ORIENTATION_HORIZONTAL
);
3801 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
3803 /* Find the right-to-left image named by RTL in the tool bar images for F.
3804 Returns IMAGE if RTL is not found. */
3807 find_rtl_image (f
, image
, rtl
)
3813 Lisp_Object file
, rtl_name
;
3814 struct gcpro gcpro1
, gcpro2
;
3815 GCPRO2 (file
, rtl_name
);
3817 rtl_name
= Ffile_name_nondirectory (rtl
);
3819 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
3821 Lisp_Object rtl_image
= PROP (TOOL_BAR_ITEM_IMAGES
);
3822 if (!NILP (file
= file_for_image (rtl_image
)))
3824 file
= call1 (intern ("file-name-sans-extension"),
3825 Ffile_name_nondirectory (file
));
3826 if (EQ (Fequal (file
, rtl_name
), Qt
))
3837 /* Update the tool bar for frame F. Add new buttons and remove old. */
3839 extern Lisp_Object Qx_gtk_map_stock
;
3842 update_frame_tool_bar (f
)
3846 GtkRequisition old_req
, new_req
;
3847 struct x_output
*x
= f
->output_data
.x
;
3848 int hmargin
= 0, vmargin
= 0;
3849 GtkToolbar
*wtoolbar
;
3851 GtkTextDirection dir
;
3852 int pack_tool_bar
= x
->handlebox_widget
== NULL
;
3854 if (! FRAME_GTK_WIDGET (f
))
3859 if (INTEGERP (Vtool_bar_button_margin
)
3860 && XINT (Vtool_bar_button_margin
) > 0)
3862 hmargin
= XFASTINT (Vtool_bar_button_margin
);
3863 vmargin
= XFASTINT (Vtool_bar_button_margin
);
3865 else if (CONSP (Vtool_bar_button_margin
))
3867 if (INTEGERP (XCAR (Vtool_bar_button_margin
))
3868 && XINT (XCAR (Vtool_bar_button_margin
)) > 0)
3869 hmargin
= XFASTINT (XCAR (Vtool_bar_button_margin
));
3871 if (INTEGERP (XCDR (Vtool_bar_button_margin
))
3872 && XINT (XCDR (Vtool_bar_button_margin
)) > 0)
3873 vmargin
= XFASTINT (XCDR (Vtool_bar_button_margin
));
3876 /* The natural size (i.e. when GTK uses 0 as margin) looks best,
3877 so take DEFAULT_TOOL_BAR_BUTTON_MARGIN to mean "default for GTK",
3878 i.e. zero. This means that margins less than
3879 DEFAULT_TOOL_BAR_BUTTON_MARGIN has no effect. */
3880 hmargin
= max (0, hmargin
- DEFAULT_TOOL_BAR_BUTTON_MARGIN
);
3881 vmargin
= max (0, vmargin
- DEFAULT_TOOL_BAR_BUTTON_MARGIN
);
3883 if (! x
->toolbar_widget
)
3884 xg_create_tool_bar (f
);
3886 wtoolbar
= GTK_TOOLBAR (x
->toolbar_widget
);
3887 gtk_widget_size_request (GTK_WIDGET (wtoolbar
), &old_req
);
3888 dir
= gtk_widget_get_direction (x
->toolbar_widget
);
3890 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
3892 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
3893 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
3897 struct image
*img
= NULL
;
3899 Lisp_Object stock
= Qnil
;
3900 GtkStockItem stock_item
;
3901 char *stock_name
= NULL
;
3902 char *icon_name
= NULL
;
3904 GtkWidget
*wbutton
= NULL
;
3905 GtkWidget
*weventbox
;
3906 Lisp_Object specified_file
;
3908 ti
= gtk_toolbar_get_nth_item (GTK_TOOLBAR (x
->toolbar_widget
), i
);
3912 weventbox
= gtk_bin_get_child (GTK_BIN (ti
));
3913 wbutton
= gtk_bin_get_child (GTK_BIN (weventbox
));
3916 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
3918 /* Ignore invalid image specifications. */
3919 if (!valid_image_p (image
))
3921 if (wbutton
) gtk_widget_hide (wbutton
);
3925 specified_file
= file_for_image (image
);
3926 if (!NILP (specified_file
) && !NILP (Ffboundp (Qx_gtk_map_stock
)))
3927 stock
= call1 (Qx_gtk_map_stock
, specified_file
);
3929 if (STRINGP (stock
))
3931 stock_name
= SSDATA (stock
);
3932 if (stock_name
[0] == 'n' && stock_name
[1] == ':')
3934 GdkScreen
*screen
= gtk_widget_get_screen (GTK_WIDGET (wtoolbar
));
3935 GtkIconTheme
*icon_theme
= gtk_icon_theme_get_for_screen (screen
);
3937 icon_name
= stock_name
+ 2;
3941 if (! gtk_icon_theme_has_icon (icon_theme
, icon_name
))
3944 icon_size
= gtk_toolbar_get_icon_size (wtoolbar
);
3946 else if (gtk_stock_lookup (SSDATA (stock
), &stock_item
))
3947 icon_size
= gtk_toolbar_get_icon_size (wtoolbar
);
3955 if (stock_name
== NULL
&& icon_name
== NULL
)
3957 /* No stock image, or stock item not known. Try regular image. */
3959 /* If image is a vector, choose the image according to the
3961 if (dir
== GTK_TEXT_DIR_RTL
3962 && !NILP (rtl
= PROP (TOOL_BAR_ITEM_RTL_IMAGE
))
3965 image
= find_rtl_image (f
, image
, rtl
);
3968 if (VECTORP (image
))
3972 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
3973 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
3976 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
3977 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
3979 xassert (ASIZE (image
) >= idx
);
3980 image
= AREF (image
, idx
);
3985 img_id
= lookup_image (f
, image
);
3986 img
= IMAGE_FROM_ID (f
, img_id
);
3987 prepare_image_for_display (f
, img
);
3989 if (img
->load_failed_p
|| img
->pixmap
== None
)
3992 gtk_widget_hide_all (GTK_WIDGET (ti
));
3995 /* Insert an empty (non-image) button */
3996 weventbox
= gtk_event_box_new ();
3997 wbutton
= gtk_button_new ();
3998 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton
), FALSE
);
3999 gtk_button_set_relief (GTK_BUTTON (wbutton
),
4001 gtk_container_add (GTK_CONTAINER (weventbox
), wbutton
);
4002 ti
= gtk_tool_item_new ();
4003 gtk_container_add (GTK_CONTAINER (ti
), weventbox
);
4004 gtk_toolbar_insert (GTK_TOOLBAR (x
->toolbar_widget
), ti
, -1);
4015 w
= gtk_image_new_from_stock (stock_name
, icon_size
);
4016 g_object_set_data_full (G_OBJECT (w
), XG_TOOL_BAR_STOCK_NAME
,
4017 (gpointer
) xstrdup (stock_name
),
4018 (GDestroyNotify
) xfree
);
4022 w
= gtk_image_new_from_icon_name (icon_name
, icon_size
);
4023 g_object_set_data_full (G_OBJECT (w
), XG_TOOL_BAR_ICON_NAME
,
4024 (gpointer
) xstrdup (icon_name
),
4025 (GDestroyNotify
) xfree
);
4029 w
= xg_get_image_for_pixmap (f
, img
, x
->widget
, NULL
);
4030 /* Save the image so we can see if an update is needed when
4031 this function is called again. */
4032 g_object_set_data (G_OBJECT (w
), XG_TOOL_BAR_IMAGE_DATA
,
4033 (gpointer
)img
->pixmap
);
4036 gtk_misc_set_padding (GTK_MISC (w
), hmargin
, vmargin
);
4037 wbutton
= gtk_button_new ();
4038 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton
), FALSE
);
4039 gtk_button_set_relief (GTK_BUTTON (wbutton
), GTK_RELIEF_NONE
);
4040 gtk_container_add (GTK_CONTAINER (wbutton
), w
);
4041 weventbox
= gtk_event_box_new ();
4042 gtk_container_add (GTK_CONTAINER (weventbox
), wbutton
);
4043 ti
= gtk_tool_item_new ();
4044 gtk_container_add (GTK_CONTAINER (ti
), weventbox
);
4045 gtk_toolbar_insert (GTK_TOOLBAR (x
->toolbar_widget
), ti
, -1);
4048 /* The EMACS_INT cast avoids a warning. */
4049 g_signal_connect (G_OBJECT (ti
), "create-menu-proxy",
4050 G_CALLBACK (xg_tool_bar_menu_proxy
),
4051 (gpointer
) (EMACS_INT
) i
);
4053 g_signal_connect (G_OBJECT (wbutton
), "clicked",
4054 G_CALLBACK (xg_tool_bar_callback
),
4055 (gpointer
) (EMACS_INT
) i
);
4057 gtk_widget_show_all (GTK_WIDGET (ti
));
4060 g_object_set_data (G_OBJECT (weventbox
), XG_FRAME_DATA
, (gpointer
)f
);
4062 /* Catch expose events to overcome an annoying redraw bug, see
4063 comment for xg_tool_bar_item_expose_callback. */
4064 g_signal_connect (G_OBJECT (ti
),
4066 G_CALLBACK (xg_tool_bar_item_expose_callback
),
4069 gtk_widget_set_sensitive (wbutton
, enabled_p
);
4070 gtk_tool_item_set_homogeneous (ti
, FALSE
);
4072 /* Callback to save modifyer mask (Shift/Control, etc). GTK makes
4073 no distinction based on modifiers in the activate callback,
4074 so we have to do it ourselves. */
4075 g_signal_connect (wbutton
, "button-release-event",
4076 G_CALLBACK (xg_tool_bar_button_cb
),
4079 g_object_set_data (G_OBJECT (wbutton
), XG_FRAME_DATA
, (gpointer
)f
);
4081 /* Use enter/leave notify to show help. We use the events
4082 rather than the GtkButton specific signals "enter" and
4083 "leave", so we can have only one callback. The event
4084 will tell us what kind of event it is. */
4085 /* The EMACS_INT cast avoids a warning. */
4086 g_signal_connect (G_OBJECT (weventbox
),
4087 "enter-notify-event",
4088 G_CALLBACK (xg_tool_bar_help_callback
),
4089 (gpointer
) (EMACS_INT
) i
);
4090 g_signal_connect (G_OBJECT (weventbox
),
4091 "leave-notify-event",
4092 G_CALLBACK (xg_tool_bar_help_callback
),
4093 (gpointer
) (EMACS_INT
) i
);
4097 GtkWidget
*wimage
= gtk_bin_get_child (GTK_BIN (wbutton
));
4098 Pixmap old_img
= (Pixmap
)g_object_get_data (G_OBJECT (wimage
),
4099 XG_TOOL_BAR_IMAGE_DATA
);
4100 gpointer old_stock_name
= g_object_get_data (G_OBJECT (wimage
),
4101 XG_TOOL_BAR_STOCK_NAME
);
4102 gpointer old_icon_name
= g_object_get_data (G_OBJECT (wimage
),
4103 XG_TOOL_BAR_ICON_NAME
);
4105 (! old_stock_name
|| strcmp (old_stock_name
, stock_name
) != 0))
4107 gtk_image_set_from_stock (GTK_IMAGE (wimage
),
4108 stock_name
, icon_size
);
4109 g_object_set_data_full (G_OBJECT (wimage
), XG_TOOL_BAR_STOCK_NAME
,
4110 (gpointer
) xstrdup (stock_name
),
4111 (GDestroyNotify
) xfree
);
4112 g_object_set_data (G_OBJECT (wimage
), XG_TOOL_BAR_IMAGE_DATA
,
4114 g_object_set_data (G_OBJECT (wimage
), XG_TOOL_BAR_ICON_NAME
, NULL
);
4116 else if (icon_name
&&
4117 (! old_icon_name
|| strcmp (old_icon_name
, icon_name
) != 0))
4119 gtk_image_set_from_icon_name (GTK_IMAGE (wimage
),
4120 icon_name
, icon_size
);
4121 g_object_set_data_full (G_OBJECT (wimage
), XG_TOOL_BAR_ICON_NAME
,
4122 (gpointer
) xstrdup (icon_name
),
4123 (GDestroyNotify
) xfree
);
4124 g_object_set_data (G_OBJECT (wimage
), XG_TOOL_BAR_IMAGE_DATA
,
4126 g_object_set_data (G_OBJECT (wimage
), XG_TOOL_BAR_STOCK_NAME
,
4129 else if (img
&& old_img
!= img
->pixmap
)
4131 (void) xg_get_image_for_pixmap (f
, img
, x
->widget
, wimage
);
4132 g_object_set_data (G_OBJECT (wimage
), XG_TOOL_BAR_IMAGE_DATA
,
4133 (gpointer
)img
->pixmap
);
4135 g_object_set_data (G_OBJECT (wimage
), XG_TOOL_BAR_STOCK_NAME
,
4137 g_object_set_data (G_OBJECT (wimage
), XG_TOOL_BAR_ICON_NAME
, NULL
);
4140 gtk_misc_set_padding (GTK_MISC (wimage
), hmargin
, vmargin
);
4142 gtk_widget_set_sensitive (wbutton
, enabled_p
);
4143 gtk_widget_show_all (GTK_WIDGET (ti
));
4149 /* Remove buttons not longer needed. We just hide them so they
4150 can be reused later on. */
4153 ti
= gtk_toolbar_get_nth_item (GTK_TOOLBAR (x
->toolbar_widget
), i
++);
4154 if (ti
) gtk_widget_hide_all (GTK_WIDGET (ti
));
4155 } while (ti
!= NULL
);
4158 if (pack_tool_bar
&& f
->n_tool_bar_items
!= 0)
4159 xg_pack_tool_bar (f
);
4162 gtk_widget_size_request (GTK_WIDGET (x
->toolbar_widget
), &new_req
);
4163 if (old_req
.height
!= new_req
.height
4164 && ! FRAME_X_OUTPUT (f
)->toolbar_detached
)
4166 FRAME_TOOLBAR_HEIGHT (f
) = new_req
.height
;
4167 xg_height_changed (f
);
4172 /* Deallocate all resources for the tool bar on frame F.
4173 Remove the tool bar. */
4176 free_frame_tool_bar (f
)
4179 struct x_output
*x
= f
->output_data
.x
;
4181 if (x
->toolbar_widget
)
4183 int is_packed
= x
->handlebox_widget
!= 0;
4185 /* We may have created the toolbar_widget in xg_create_tool_bar, but
4186 not the x->handlebox_widget which is created in xg_pack_tool_bar. */
4188 gtk_container_remove (GTK_CONTAINER (x
->vbox_widget
),
4189 x
->handlebox_widget
);
4191 gtk_widget_destroy (x
->toolbar_widget
);
4193 x
->toolbar_widget
= 0;
4194 x
->handlebox_widget
= 0;
4195 FRAME_TOOLBAR_HEIGHT (f
) = 0;
4196 xg_height_changed (f
);
4204 /***********************************************************************
4206 ***********************************************************************/
4210 GtkBindingSet
*binding_set
;
4213 /* Work around a bug with corrupted data if libXft gets unloaded. This way
4214 we keep it permanently linked in. */
4219 xg_ignore_gtk_scrollbar
= 0;
4220 xg_detached_menus
= 0;
4221 xg_menu_cb_list
.prev
= xg_menu_cb_list
.next
=
4222 xg_menu_item_cb_list
.prev
= xg_menu_item_cb_list
.next
= 0;
4224 id_to_widget
.max_size
= id_to_widget
.used
= 0;
4225 id_to_widget
.widgets
= 0;
4227 /* Remove F10 as a menu accelerator, it does not mix well with Emacs key
4228 bindings. It doesn't seem to be any way to remove properties,
4229 so we set it to VoidSymbol which in X means "no key". */
4230 gtk_settings_set_string_property (gtk_settings_get_default (),
4231 "gtk-menu-bar-accel",
4235 /* Make GTK text input widgets use Emacs style keybindings. This is
4237 gtk_settings_set_string_property (gtk_settings_get_default (),
4238 "gtk-key-theme-name",
4242 /* Make dialogs close on C-g. Since file dialog inherits from
4243 dialog, this works for them also. */
4244 binding_set
= gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_DIALOG
));
4245 gtk_binding_entry_add_signal (binding_set
, GDK_g
, GDK_CONTROL_MASK
,
4248 /* Make menus close on C-g. */
4249 binding_set
= gtk_binding_set_by_class (g_type_class_ref
4250 (GTK_TYPE_MENU_SHELL
));
4251 gtk_binding_entry_add_signal (binding_set
, GDK_g
, GDK_CONTROL_MASK
,
4255 #endif /* USE_GTK */
4257 /* arch-tag: fe7104da-bc1e-4aba-9bd1-f349c528f7e3
4258 (do not change this comment) */