aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog13
-rw-r--r--src/gtkutil.c289
2 files changed, 240 insertions, 62 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index de94c9fb0a1..ecd83610758 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
12007-09-02 Jan Dj,Ad(Brv <jan.h.d@swipnet.se>
2
3 * keyboard.c: Qrtl is new.
4 (parse_tool_bar_item): Handle :rtl keyword.
5 (syms_of_keyboard): Intern :rtl keyword.
6
7 * dispextern.h (enum tool_bar_item_idx): Add TOOL_BAR_ITEM_RTL_IMAGE.
8
9 * gtkutil.c: (file_for_image, find_rtl_image): New functions.
10 (xg_get_image_for_pixmap): Use file_for_image
11 (update_frame_tool_bar): If direction is RTL, use RTL image if
12 defined. Use Gtk stock images or named theme icons if defined.
13
12007-08-29 Martin Rudalics <rudalics@gmx.at> 142007-08-29 Martin Rudalics <rudalics@gmx.at>
2 15
3 * keyboard.h (struct kboard): New elt Vlast_repeatable_command. 16 * keyboard.h (struct kboard): New elt Vlast_repeatable_command.
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 5ca8c8885b6..36873f23e6d 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.
@@ -865,7 +874,7 @@ xg_create_frame_widgets (f)
865 874
866 /* Since GTK clears its window by filling with the background color, 875 /* Since GTK clears its window by filling with the background color,
867 we must keep X and GTK background in sync. */ 876 we must keep X and GTK background in sync. */
868 xg_pix_to_gcolor (wfixed, f->output_data.x->background_pixel, &bg); 877 xg_pix_to_gcolor (wfixed, FRAME_BACKGROUND_PIXEL (f), &bg);
869 gtk_widget_modify_bg (wfixed, GTK_STATE_NORMAL, &bg); 878 gtk_widget_modify_bg (wfixed, GTK_STATE_NORMAL, &bg);
870 879
871 /* Also, do not let any background pixmap to be set, this looks very 880 /* Also, do not let any background pixmap to be set, this looks very
@@ -2034,7 +2043,7 @@ xg_create_one_menuitem (item, f, select_cb, highlight_cb, cl_data, group)
2034 return w; 2043 return w;
2035} 2044}
2036 2045
2037/* Callback called when keyboard traversal (started by menu-bar-open) ends. 2046/* Callback called when keyboard traversal (started by x-menu-bar-open) ends.
2038 WMENU is the menu for which traversal has been done. DATA points to the 2047 WMENU is the menu for which traversal has been done. DATA points to the
2039 frame for WMENU. We must release grabs, some bad interaction between GTK 2048 frame for WMENU. We must release grabs, some bad interaction between GTK
2040 and Emacs makes the menus keep the grabs. */ 2049 and Emacs makes the menus keep the grabs. */
@@ -3332,6 +3341,20 @@ 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/* As above, but this is used for named theme widgets, as opposed to
3350 stock items. */
3351#define XG_TOOL_BAR_ICON_NAME "emacs-tool-bar-icon-name"
3352
3353/* Callback function invoked when a tool bar item is pressed.
3354 W is the button widget in the tool bar that got pressed,
3355 CLIENT_DATA is an integer that is the index of the button in the
3356 tool bar. 0 is the first button. */
3357
3335static gboolean 3358static gboolean
3336xg_tool_bar_button_cb (widget, event, user_data) 3359xg_tool_bar_button_cb (widget, event, user_data)
3337 GtkWidget *widget; 3360 GtkWidget *widget;
@@ -3614,6 +3637,8 @@ xg_tool_bar_item_expose_callback (w, event, client_data)
3614 return FALSE; 3637 return FALSE;
3615} 3638}
3616 3639
3640#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
3641
3617/* This callback is called when a tool bar shall be redrawn. 3642/* This callback is called when a tool bar shall be redrawn.
3618 We need to update the images in case the image cache 3643 We need to update the images in case the image cache
3619 has deleted the pixmaps used in the tool bar. 3644 has deleted the pixmaps used in the tool bar.
@@ -3691,6 +3716,40 @@ xg_create_tool_bar (f)
3691 SET_FRAME_GARBAGED (f); 3716 SET_FRAME_GARBAGED (f);
3692} 3717}
3693 3718
3719/* Find the right-to-left image named by RTL in the tool bar images for F.
3720 Returns IMAGE if RTL is not found. */
3721
3722static Lisp_Object
3723find_rtl_image (f, image, rtl)
3724 FRAME_PTR f;
3725 Lisp_Object image;
3726 Lisp_Object rtl;
3727{
3728 int i;
3729 Lisp_Object file, rtl_name;
3730 struct gcpro gcpro1, gcpro2;
3731 GCPRO2 (file, rtl_name);
3732
3733 rtl_name = Ffile_name_nondirectory (rtl);
3734
3735 for (i = 0; i < f->n_tool_bar_items; ++i)
3736 {
3737 Lisp_Object rtl_image = PROP (TOOL_BAR_ITEM_IMAGES);
3738 if (!NILP (file = file_for_image (rtl_image)))
3739 {
3740 file = call1 (intern ("file-name-sans-extension"),
3741 Ffile_name_nondirectory (file));
3742 if (EQ (Fequal (file, rtl_name), Qt))
3743 {
3744 image = rtl_image;
3745 break;
3746 }
3747 }
3748 }
3749
3750 return image;
3751}
3752
3694/* Update the tool bar for frame F. Add new buttons and remove old. */ 3753/* Update the tool bar for frame F. Add new buttons and remove old. */
3695 3754
3696void 3755void
@@ -3701,7 +3760,9 @@ update_frame_tool_bar (f)
3701 GtkRequisition old_req, new_req; 3760 GtkRequisition old_req, new_req;
3702 struct x_output *x = f->output_data.x; 3761 struct x_output *x = f->output_data.x;
3703 int hmargin = 0, vmargin = 0; 3762 int hmargin = 0, vmargin = 0;
3763 GtkToolbar *wtoolbar;
3704 GtkToolItem *ti; 3764 GtkToolItem *ti;
3765 GtkTextDirection dir;
3705 3766
3706 if (! FRAME_GTK_WIDGET (f)) 3767 if (! FRAME_GTK_WIDGET (f))
3707 return; 3768 return;
@@ -3735,20 +3796,28 @@ update_frame_tool_bar (f)
3735 if (! x->toolbar_widget) 3796 if (! x->toolbar_widget)
3736 xg_create_tool_bar (f); 3797 xg_create_tool_bar (f);
3737 3798
3738 gtk_widget_size_request (x->toolbar_widget, &old_req); 3799 wtoolbar = GTK_TOOLBAR (x->toolbar_widget);
3800 gtk_widget_size_request (GTK_WIDGET (wtoolbar), &old_req);
3801 dir = gtk_widget_get_direction (x->toolbar_widget);
3739 3802
3740 for (i = 0; i < f->n_tool_bar_items; ++i) 3803 for (i = 0; i < f->n_tool_bar_items; ++i)
3741 { 3804 {
3742#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
3743 3805
3744 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); 3806 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
3745 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); 3807 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
3746 int idx; 3808 int idx;
3747 int img_id; 3809 int img_id;
3748 struct image *img; 3810 int icon_size = 0;
3811 struct image *img = NULL;
3749 Lisp_Object image; 3812 Lisp_Object image;
3750 GtkWidget *wbutton; 3813 Lisp_Object stock;
3814 GtkStockItem stock_item;
3815 char *stock_name = NULL;
3816 char *icon_name = NULL;
3817 Lisp_Object rtl;
3818 GtkWidget *wbutton = NULL;
3751 GtkWidget *weventbox; 3819 GtkWidget *weventbox;
3820 Lisp_Object func = intern ("x-gtk-map-stock");
3752 3821
3753 ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (x->toolbar_widget), i); 3822 ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (x->toolbar_widget), i);
3754 3823
@@ -3758,59 +3827,125 @@ update_frame_tool_bar (f)
3758 wbutton = gtk_bin_get_child (GTK_BIN (weventbox)); 3827 wbutton = gtk_bin_get_child (GTK_BIN (weventbox));
3759 } 3828 }
3760 3829
3761 /* If image is a vector, choose the image according to the
3762 button state. */
3763 image = PROP (TOOL_BAR_ITEM_IMAGES); 3830 image = PROP (TOOL_BAR_ITEM_IMAGES);
3764 if (VECTORP (image))
3765 {
3766 if (enabled_p)
3767 idx = (selected_p
3768 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
3769 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
3770 else
3771 idx = (selected_p
3772 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
3773 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
3774
3775 xassert (ASIZE (image) >= idx);
3776 image = AREF (image, idx);
3777 }
3778 else
3779 idx = -1;
3780 3831
3781 /* Ignore invalid image specifications. */ 3832 /* Ignore invalid image specifications. */
3782 if (!valid_image_p (image)) 3833 if (!valid_image_p (image))
3783 { 3834 {
3784 if (ti) gtk_widget_hide_all (GTK_WIDGET (ti)); 3835 if (wbutton) gtk_widget_hide (wbutton);
3785 continue; 3836 continue;
3786 } 3837 }
3787 3838
3788 img_id = lookup_image (f, image); 3839 if (EQ (Qt, Ffboundp (func)))
3789 img = IMAGE_FROM_ID (f, img_id); 3840 stock = call1 (func, file_for_image (image));
3790 prepare_image_for_display (f, img);
3791 3841
3792 if (img->load_failed_p || img->pixmap == None) 3842 if (! NILP (stock) && STRINGP (stock))
3793 { 3843 {
3794 if (ti) 3844 stock_name = SSDATA (stock);
3795 gtk_widget_hide_all (GTK_WIDGET (ti)); 3845 if (stock_name[0] == 'n' && stock_name[1] == ':')
3796 else
3797 { 3846 {
3798 /* Insert an empty (non-image) button */ 3847 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (wtoolbar));
3799 weventbox = gtk_event_box_new (); 3848 GtkIconTheme *icon_theme = gtk_icon_theme_get_for_screen (screen);
3800 wbutton = gtk_button_new (); 3849
3801 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE); 3850 icon_name = stock_name + 2;
3802 gtk_button_set_relief (GTK_BUTTON (wbutton), GTK_RELIEF_NONE); 3851 stock_name = NULL;
3803 gtk_container_add (GTK_CONTAINER (weventbox), wbutton); 3852 stock = Qnil;
3804 ti = gtk_tool_item_new (); 3853
3805 gtk_container_add (GTK_CONTAINER (ti), weventbox); 3854 if (! gtk_icon_theme_has_icon (icon_theme, icon_name))
3806 gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), ti, -1); 3855 icon_name = NULL;
3856 else
3857 icon_size = gtk_toolbar_get_icon_size (wtoolbar);
3858 }
3859 else if (gtk_stock_lookup (SSDATA (stock), &stock_item))
3860 icon_size = gtk_toolbar_get_icon_size (wtoolbar);
3861 else
3862 {
3863 stock = Qnil;
3864 stock_name = NULL;
3865 }
3866 }
3867
3868 if (stock_name == NULL && icon_name == NULL)
3869 {
3870 /* No stock image, or stock item not known. Try regular image. */
3871
3872 /* If image is a vector, choose the image according to the
3873 button state. */
3874 if (dir == GTK_TEXT_DIR_RTL
3875 && !NILP (rtl = PROP (TOOL_BAR_ITEM_RTL_IMAGE))
3876 && STRINGP (rtl))
3877 {
3878 image = find_rtl_image (f, image, rtl);
3879 }
3880
3881 if (VECTORP (image))
3882 {
3883 if (enabled_p)
3884 idx = (selected_p
3885 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
3886 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
3887 else
3888 idx = (selected_p
3889 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
3890 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
3891
3892 xassert (ASIZE (image) >= idx);
3893 image = AREF (image, idx);
3894 }
3895 else
3896 idx = -1;
3897
3898 img_id = lookup_image (f, image);
3899 img = IMAGE_FROM_ID (f, img_id);
3900 prepare_image_for_display (f, img);
3901
3902 if (img->load_failed_p || img->pixmap == None)
3903 {
3904 if (ti)
3905 gtk_widget_hide_all (GTK_WIDGET (ti));
3906 else
3907 {
3908 /* Insert an empty (non-image) button */
3909 weventbox = gtk_event_box_new ();
3910 wbutton = gtk_button_new ();
3911 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE);
3912 gtk_button_set_relief (GTK_BUTTON (wbutton),
3913 GTK_RELIEF_NONE);
3914 gtk_container_add (GTK_CONTAINER (weventbox), wbutton);
3915 ti = gtk_tool_item_new ();
3916 gtk_container_add (GTK_CONTAINER (ti), weventbox);
3917 gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), ti, -1);
3918 }
3919 continue;
3807 } 3920 }
3808 continue;
3809 } 3921 }
3810 3922
3811 if (ti == NULL) 3923 if (ti == NULL)
3812 { 3924 {
3813 GtkWidget *w = xg_get_image_for_pixmap (f, img, x->widget, NULL); 3925 GtkWidget *w;
3926 if (stock_name)
3927 {
3928 w = gtk_image_new_from_stock (stock_name, icon_size);
3929 g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_STOCK_NAME,
3930 (gpointer) xstrdup (stock_name),
3931 (GDestroyNotify) xfree);
3932 }
3933 else if (icon_name)
3934 {
3935 w = gtk_image_new_from_icon_name (icon_name, icon_size);
3936 g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_ICON_NAME,
3937 (gpointer) xstrdup (icon_name),
3938 (GDestroyNotify) xfree);
3939 }
3940 else
3941 {
3942 w = xg_get_image_for_pixmap (f, img, x->widget, NULL);
3943 /* Save the image so we can see if an update is needed when
3944 this function is called again. */
3945 g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA,
3946 (gpointer)img->pixmap);
3947 }
3948
3814 gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin); 3949 gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin);
3815 wbutton = gtk_button_new (); 3950 wbutton = gtk_button_new ();
3816 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE); 3951 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE);
@@ -3834,10 +3969,6 @@ update_frame_tool_bar (f)
3834 3969
3835 gtk_widget_show_all (GTK_WIDGET (ti)); 3970 gtk_widget_show_all (GTK_WIDGET (ti));
3836 3971
3837 /* Save the image so we can see if an update is needed when
3838 this function is called again. */
3839 g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA,
3840 (gpointer)img->pixmap);
3841 3972
3842 g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f); 3973 g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f);
3843 3974
@@ -3879,13 +4010,47 @@ update_frame_tool_bar (f)
3879 GtkWidget *wimage = gtk_bin_get_child (GTK_BIN (wbutton)); 4010 GtkWidget *wimage = gtk_bin_get_child (GTK_BIN (wbutton));
3880 Pixmap old_img = (Pixmap)g_object_get_data (G_OBJECT (wimage), 4011 Pixmap old_img = (Pixmap)g_object_get_data (G_OBJECT (wimage),
3881 XG_TOOL_BAR_IMAGE_DATA); 4012 XG_TOOL_BAR_IMAGE_DATA);
3882 gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin); 4013 gpointer old_stock_name = g_object_get_data (G_OBJECT (wimage),
4014 XG_TOOL_BAR_STOCK_NAME);
4015 gpointer old_icon_name = g_object_get_data (G_OBJECT (wimage),
4016 XG_TOOL_BAR_ICON_NAME);
4017 if (stock_name &&
4018 (! old_stock_name || strcmp (old_stock_name, stock_name) != 0))
4019 {
4020 gtk_image_set_from_stock (GTK_IMAGE (wimage),
4021 stock_name, icon_size);
4022 g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
4023 (gpointer) xstrdup (stock_name),
4024 (GDestroyNotify) xfree);
4025 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
4026 NULL);
4027 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME, NULL);
4028 }
4029 else if (icon_name &&
4030 (! old_icon_name || strcmp (old_icon_name, icon_name) != 0))
4031 {
4032 gtk_image_set_from_icon_name (GTK_IMAGE (wimage),
4033 icon_name, icon_size);
4034 g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME,
4035 (gpointer) xstrdup (icon_name),
4036 (GDestroyNotify) xfree);
4037 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
4038 NULL);
4039 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
4040 NULL);
4041 }
4042 else if (img && old_img != img->pixmap)
4043 {
4044 (void) xg_get_image_for_pixmap (f, img, x->widget, wimage);
4045 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
4046 (gpointer)img->pixmap);
3883 4047
3884 if (old_img != img->pixmap) 4048 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
3885 (void) xg_get_image_for_pixmap (f, img, x->widget, wimage); 4049 NULL);
4050 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME, NULL);
4051 }
3886 4052
3887 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, 4053 gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin);
3888 (gpointer)img->pixmap);
3889 4054
3890 gtk_widget_set_sensitive (wbutton, enabled_p); 4055 gtk_widget_set_sensitive (wbutton, enabled_p);
3891 gtk_widget_show_all (GTK_WIDGET (ti)); 4056 gtk_widget_show_all (GTK_WIDGET (ti));
@@ -3902,7 +4067,7 @@ update_frame_tool_bar (f)
3902 if (ti) gtk_widget_hide_all (GTK_WIDGET (ti)); 4067 if (ti) gtk_widget_hide_all (GTK_WIDGET (ti));
3903 } while (ti != NULL); 4068 } while (ti != NULL);
3904 4069
3905 gtk_widget_size_request (x->toolbar_widget, &new_req); 4070 gtk_widget_size_request (GTK_WIDGET (wtoolbar), &new_req);
3906 if (old_req.height != new_req.height 4071 if (old_req.height != new_req.height
3907 && ! FRAME_X_OUTPUT (f)->toolbar_detached) 4072 && ! FRAME_X_OUTPUT (f)->toolbar_detached)
3908 { 4073 {