aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gtkutil.c239
1 files changed, 178 insertions, 61 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 7dc451a5d04..9fb011de919 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -298,6 +298,23 @@ xg_get_pixbuf_from_pix_and_mask (gpix, gmask, cmap)
298 return icon_buf; 298 return icon_buf;
299} 299}
300 300
301static Lisp_Object
302file_for_image(image)
303 Lisp_Object image;
304{
305 Lisp_Object specified_file = Qnil;
306 Lisp_Object tail;
307 extern Lisp_Object QCfile;
308
309 for (tail = XCDR (image);
310 NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail));
311 tail = XCDR (XCDR (tail)))
312 if (EQ (XCAR (tail), QCfile))
313 specified_file = XCAR (XCDR (tail));
314
315 return specified_file;
316}
317
301/* For the image defined in IMG, make and return a GtkImage. For displays with 318/* For the image defined in IMG, make and return a GtkImage. For displays with
302 8 planes or less we must make a GdkPixbuf and apply the mask manually. 319 8 planes or less we must make a GdkPixbuf and apply the mask manually.
303 Otherwise the highlightning and dimming the tool bar code in GTK does 320 Otherwise the highlightning and dimming the tool bar code in GTK does
@@ -323,16 +340,8 @@ xg_get_image_for_pixmap (f, img, widget, old_widget)
323 /* If we have a file, let GTK do all the image handling. 340 /* If we have a file, let GTK do all the image handling.
324 This seems to be the only way to make insensitive and activated icons 341 This seems to be the only way to make insensitive and activated icons
325 look good in all cases. */ 342 look good in all cases. */
326 Lisp_Object specified_file = Qnil; 343 Lisp_Object specified_file = file_for_image (img->spec);
327 Lisp_Object tail;
328 Lisp_Object file; 344 Lisp_Object file;
329 extern Lisp_Object QCfile;
330
331 for (tail = XCDR (img->spec);
332 NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail));
333 tail = XCDR (XCDR (tail)))
334 if (EQ (XCAR (tail), QCfile))
335 specified_file = XCAR (XCDR (tail));
336 345
337 /* We already loaded the image once before calling this 346 /* We already loaded the image once before calling this
338 function, so this only fails if the image file has been removed. 347 function, so this only fails if the image file has been removed.
@@ -3332,6 +3341,16 @@ xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
3332/* The key for storing the button widget in its proxy menu item. */ 3341/* The key for storing the button widget in its proxy menu item. */
3333#define XG_TOOL_BAR_PROXY_BUTTON "emacs-tool-bar-proxy-button" 3342#define XG_TOOL_BAR_PROXY_BUTTON "emacs-tool-bar-proxy-button"
3334 3343
3344/* The key for the data we put in the GtkImage widgets. The data is
3345 the stock name used by Emacs. We use this to see if we need to update
3346 the GtkImage with a new image. */
3347#define XG_TOOL_BAR_STOCK_NAME "emacs-tool-bar-stock-name"
3348
3349/* Callback function invoked when a tool bar item is pressed.
3350 W is the button widget in the tool bar that got pressed,
3351 CLIENT_DATA is an integer that is the index of the button in the
3352 tool bar. 0 is the first button. */
3353
3335static gboolean 3354static gboolean
3336xg_tool_bar_button_cb (widget, event, user_data) 3355xg_tool_bar_button_cb (widget, event, user_data)
3337 GtkWidget *widget; 3356 GtkWidget *widget;
@@ -3614,8 +3633,10 @@ xg_tool_bar_item_expose_callback (w, event, client_data)
3614 return FALSE; 3633 return FALSE;
3615} 3634}
3616 3635
3636#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
3637
3617/* This callback is called when a tool bar shall be redrawn. 3638/* This callback is called when a tool bar shall be redrawn.
3618 We need to update the tool bar from here in case the image cache 3639 We need to update the images in case the image cache
3619 has deleted the pixmaps used in the tool bar. 3640 has deleted the pixmaps used in the tool bar.
3620 W is the GtkToolbar to be redrawn. 3641 W is the GtkToolbar to be redrawn.
3621 EVENT is the expose event for W. 3642 EVENT is the expose event for W.
@@ -3629,7 +3650,8 @@ xg_tool_bar_expose_callback (w, event, client_data)
3629 GdkEventExpose *event; 3650 GdkEventExpose *event;
3630 gpointer client_data; 3651 gpointer client_data;
3631{ 3652{
3632 update_frame_tool_bar ((FRAME_PTR) client_data); 3653 FRAME_PTR f = (FRAME_PTR) client_data;
3654 SET_FRAME_GARBAGED (f);
3633 return FALSE; 3655 return FALSE;
3634} 3656}
3635 3657
@@ -3690,6 +3712,40 @@ xg_create_tool_bar (f)
3690 SET_FRAME_GARBAGED (f); 3712 SET_FRAME_GARBAGED (f);
3691} 3713}
3692 3714
3715/* Find the right-to-left image named by RTL in the tool bar images for F.
3716 Returns IMAGE if RTL is not found. */
3717
3718static Lisp_Object
3719find_rtl_image (f, image, rtl)
3720 FRAME_PTR f;
3721 Lisp_Object image;
3722 Lisp_Object rtl;
3723{
3724 int i;
3725 Lisp_Object file, rtl_name;
3726 struct gcpro gcpro1, gcpro2;
3727 GCPRO2 (file, rtl_name);
3728
3729 rtl_name = Ffile_name_nondirectory (rtl);
3730
3731 for (i = 0; i < f->n_tool_bar_items; ++i)
3732 {
3733 Lisp_Object rtl_image = PROP (TOOL_BAR_ITEM_IMAGES);
3734 if (!NILP (file = file_for_image (rtl_image)))
3735 {
3736 file = call1 (intern ("file-name-sans-extension"),
3737 Ffile_name_nondirectory (file));
3738 if (EQ (Fequal (file, rtl_name), Qt))
3739 {
3740 image = rtl_image;
3741 break;
3742 }
3743 }
3744 }
3745
3746 return image;
3747}
3748
3693/* Update the tool bar for frame F. Add new buttons and remove old. */ 3749/* Update the tool bar for frame F. Add new buttons and remove old. */
3694 3750
3695void 3751void
@@ -3700,7 +3756,9 @@ update_frame_tool_bar (f)
3700 GtkRequisition old_req, new_req; 3756 GtkRequisition old_req, new_req;
3701 struct x_output *x = f->output_data.x; 3757 struct x_output *x = f->output_data.x;
3702 int hmargin = 0, vmargin = 0; 3758 int hmargin = 0, vmargin = 0;
3759 GtkToolbar *wtoolbar;
3703 GtkToolItem *ti; 3760 GtkToolItem *ti;
3761 GtkTextDirection dir;
3704 3762
3705 if (! FRAME_GTK_WIDGET (f)) 3763 if (! FRAME_GTK_WIDGET (f))
3706 return; 3764 return;
@@ -3734,20 +3792,27 @@ update_frame_tool_bar (f)
3734 if (! x->toolbar_widget) 3792 if (! x->toolbar_widget)
3735 xg_create_tool_bar (f); 3793 xg_create_tool_bar (f);
3736 3794
3737 gtk_widget_size_request (x->toolbar_widget, &old_req); 3795 wtoolbar = GTK_TOOLBAR (x->toolbar_widget);
3796 gtk_widget_size_request (GTK_WIDGET (wtoolbar), &old_req);
3797 dir = gtk_widget_get_direction (x->toolbar_widget);
3738 3798
3739 for (i = 0; i < f->n_tool_bar_items; ++i) 3799 for (i = 0; i < f->n_tool_bar_items; ++i)
3740 { 3800 {
3741#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
3742 3801
3743 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); 3802 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
3744 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); 3803 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
3745 int idx; 3804 int idx;
3746 int img_id; 3805 int img_id;
3747 struct image *img; 3806 int icon_size = 0;
3807 struct image *img = NULL;
3748 Lisp_Object image; 3808 Lisp_Object image;
3809 Lisp_Object stock;
3810 GtkStockItem stock_item;
3811 char *stock_name = NULL;
3812 Lisp_Object rtl;
3749 GtkWidget *wbutton; 3813 GtkWidget *wbutton;
3750 GtkWidget *weventbox; 3814 GtkWidget *weventbox;
3815 Lisp_Object func = intern ("x-gtk-map-stock");
3751 3816
3752 ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (x->toolbar_widget), i); 3817 ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (x->toolbar_widget), i);
3753 3818
@@ -3757,59 +3822,98 @@ update_frame_tool_bar (f)
3757 wbutton = gtk_bin_get_child (GTK_BIN (weventbox)); 3822 wbutton = gtk_bin_get_child (GTK_BIN (weventbox));
3758 } 3823 }
3759 3824
3760 /* If image is a vector, choose the image according to the
3761 button state. */
3762 image = PROP (TOOL_BAR_ITEM_IMAGES); 3825 image = PROP (TOOL_BAR_ITEM_IMAGES);
3763 if (VECTORP (image))
3764 {
3765 if (enabled_p)
3766 idx = (selected_p
3767 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
3768 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
3769 else
3770 idx = (selected_p
3771 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
3772 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
3773
3774 xassert (ASIZE (image) >= idx);
3775 image = AREF (image, idx);
3776 }
3777 else
3778 idx = -1;
3779 3826
3780 /* Ignore invalid image specifications. */ 3827 /* Ignore invalid image specifications. */
3781 if (!valid_image_p (image)) 3828 if (!valid_image_p (image))
3782 { 3829 {
3783 if (ti) gtk_widget_hide_all (GTK_WIDGET (ti)); 3830 if (wbutton) gtk_widget_hide (wbutton);
3784 continue; 3831 continue;
3785 } 3832 }
3786 3833
3787 img_id = lookup_image (f, image); 3834 if (EQ (Qt, Ffboundp (func)))
3788 img = IMAGE_FROM_ID (f, img_id); 3835 stock = call1 (func, file_for_image (image));
3789 prepare_image_for_display (f, img);
3790 3836
3791 if (img->load_failed_p || img->pixmap == None) 3837 if (! NILP (stock) && STRINGP (stock)
3838 && gtk_stock_lookup (SSDATA (stock), &stock_item))
3839 {
3840 stock_name = SSDATA (stock);
3841 icon_size = gtk_toolbar_get_icon_size (wtoolbar);
3842 }
3843 else
3792 { 3844 {
3793 if (ti) 3845 /* No stock image, or stock item not known. Try regular image. */
3794 gtk_widget_hide_all (GTK_WIDGET (ti)); 3846
3795 else 3847 /* If image is a vector, choose the image according to the
3848 button state. */
3849 if (dir == GTK_TEXT_DIR_RTL
3850 && !NILP (rtl = PROP (TOOL_BAR_ITEM_RTL_IMAGE))
3851 && STRINGP (rtl))
3796 { 3852 {
3797 /* Insert an empty (non-image) button */ 3853 image = find_rtl_image (f, image, rtl);
3798 weventbox = gtk_event_box_new (); 3854 }
3799 wbutton = gtk_button_new (); 3855
3800 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE); 3856 if (VECTORP (image))
3801 gtk_button_set_relief (GTK_BUTTON (wbutton), GTK_RELIEF_NONE); 3857 {
3802 gtk_container_add (GTK_CONTAINER (weventbox), wbutton); 3858 if (enabled_p)
3803 ti = gtk_tool_item_new (); 3859 idx = (selected_p
3804 gtk_container_add (GTK_CONTAINER (ti), weventbox); 3860 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
3805 gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), ti, -1); 3861 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
3862 else
3863 idx = (selected_p
3864 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
3865 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
3866
3867 xassert (ASIZE (image) >= idx);
3868 image = AREF (image, idx);
3869 }
3870 else
3871 idx = -1;
3872
3873 img_id = lookup_image (f, image);
3874 img = IMAGE_FROM_ID (f, img_id);
3875 prepare_image_for_display (f, img);
3876
3877 if (img->load_failed_p || img->pixmap == None)
3878 {
3879 if (ti)
3880 gtk_widget_hide_all (GTK_WIDGET (ti));
3881 else
3882 {
3883 /* Insert an empty (non-image) button */
3884 weventbox = gtk_event_box_new ();
3885 wbutton = gtk_button_new ();
3886 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE);
3887 gtk_button_set_relief (GTK_BUTTON (wbutton),
3888 GTK_RELIEF_NONE);
3889 gtk_container_add (GTK_CONTAINER (weventbox), wbutton);
3890 ti = gtk_tool_item_new ();
3891 gtk_container_add (GTK_CONTAINER (ti), weventbox);
3892 gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), ti, -1);
3893 }
3894 continue;
3806 } 3895 }
3807 continue;
3808 } 3896 }
3809 3897
3810 if (ti == NULL) 3898 if (ti == NULL)
3811 { 3899 {
3812 GtkWidget *w = xg_get_image_for_pixmap (f, img, x->widget, NULL); 3900 GtkWidget *w;
3901 if (stock_name)
3902 {
3903 w = gtk_image_new_from_stock (stock_name, icon_size);
3904 g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_STOCK_NAME,
3905 (gpointer) xstrdup (stock_name),
3906 (GDestroyNotify) xfree);
3907 }
3908 else
3909 {
3910 w = xg_get_image_for_pixmap (f, img, x->widget, NULL);
3911 /* Save the image so we can see if an update is needed when
3912 this function is called again. */
3913 g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA,
3914 (gpointer)img->pixmap);
3915 }
3916
3813 gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin); 3917 gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin);
3814 wbutton = gtk_button_new (); 3918 wbutton = gtk_button_new ();
3815 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE); 3919 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE);
@@ -3833,10 +3937,6 @@ update_frame_tool_bar (f)
3833 3937
3834 gtk_widget_show_all (GTK_WIDGET (ti)); 3938 gtk_widget_show_all (GTK_WIDGET (ti));
3835 3939
3836 /* Save the image so we can see if an update is needed when
3837 this function is called again. */
3838 g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA,
3839 (gpointer)img->pixmap);
3840 3940
3841 g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f); 3941 g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f);
3842 3942
@@ -3878,13 +3978,30 @@ update_frame_tool_bar (f)
3878 GtkWidget *wimage = gtk_bin_get_child (GTK_BIN (wbutton)); 3978 GtkWidget *wimage = gtk_bin_get_child (GTK_BIN (wbutton));
3879 Pixmap old_img = (Pixmap)g_object_get_data (G_OBJECT (wimage), 3979 Pixmap old_img = (Pixmap)g_object_get_data (G_OBJECT (wimage),
3880 XG_TOOL_BAR_IMAGE_DATA); 3980 XG_TOOL_BAR_IMAGE_DATA);
3881 gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin); 3981 gpointer old_stock_name = g_object_get_data (G_OBJECT (wimage),
3982 XG_TOOL_BAR_STOCK_NAME);
3983 if (stock_name &&
3984 (! old_stock_name || strcmp (old_stock_name, stock_name) != 0))
3985 {
3986 gtk_image_set_from_stock (GTK_IMAGE (wimage),
3987 stock_name, icon_size);
3988 g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
3989 (gpointer) xstrdup (stock_name),
3990 (GDestroyNotify) xfree);
3991 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
3992 NULL);
3993 }
3994 else if (img && old_img != img->pixmap)
3995 {
3996 (void) xg_get_image_for_pixmap (f, img, x->widget, wimage);
3997 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
3998 (gpointer)img->pixmap);
3882 3999
3883 if (old_img != img->pixmap) 4000 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
3884 (void) xg_get_image_for_pixmap (f, img, x->widget, wimage); 4001 NULL);
4002 }
3885 4003
3886 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, 4004 gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin);
3887 (gpointer)img->pixmap);
3888 4005
3889 gtk_widget_set_sensitive (wbutton, enabled_p); 4006 gtk_widget_set_sensitive (wbutton, enabled_p);
3890 gtk_widget_show_all (GTK_WIDGET (ti)); 4007 gtk_widget_show_all (GTK_WIDGET (ti));
@@ -3901,7 +4018,7 @@ update_frame_tool_bar (f)
3901 if (ti) gtk_widget_hide_all (GTK_WIDGET (ti)); 4018 if (ti) gtk_widget_hide_all (GTK_WIDGET (ti));
3902 } while (ti != NULL); 4019 } while (ti != NULL);
3903 4020
3904 gtk_widget_size_request (x->toolbar_widget, &new_req); 4021 gtk_widget_size_request (GTK_WIDGET (wtoolbar), &new_req);
3905 if (old_req.height != new_req.height 4022 if (old_req.height != new_req.height
3906 && ! FRAME_X_OUTPUT (f)->toolbar_detached) 4023 && ! FRAME_X_OUTPUT (f)->toolbar_detached)
3907 { 4024 {