comparison src/gtkutil.c @ 91015:b83d0dadb2a7

Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 857-865) - Update from CVS - Merge from emacs--rel--22 - Update from CVS: lisp/emacs-lisp/avl-tree.el: New file. - Remove RCS keywords * emacs--rel--22 (patch 97-100) - Update from CVS - Merge from gnus--rel--5.10 * gnus--rel--5.10 (patch 246-247) - Update from CVS Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-252
author Miles Bader <miles@gnu.org>
date Wed, 29 Aug 2007 05:03:40 +0000
parents 424b655804ca 3a5f0fb127ce
children bdb3fe0ba9fa
comparison
equal deleted inserted replaced
91014:2392e6a45952 91015:b83d0dadb2a7
296 } 296 }
297 297
298 return icon_buf; 298 return icon_buf;
299 } 299 }
300 300
301 static Lisp_Object
302 file_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
304 will look bad. For display with more than 8 planes we just use the 321 will look bad. For display with more than 8 planes we just use the
305 pixmap and mask directly. For monochrome displays, GTK doesn't seem 322 pixmap and mask directly. For monochrome displays, GTK doesn't seem
321 GdkDisplay *gdpy; 338 GdkDisplay *gdpy;
322 339
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.
339 In that case, use the pixmap already loaded. */ 348 In that case, use the pixmap already loaded. */
340 349
3329 get them. */ 3338 get them. */
3330 #define XG_TOOL_BAR_LAST_MODIFIER "emacs-tool-bar-modifier" 3339 #define XG_TOOL_BAR_LAST_MODIFIER "emacs-tool-bar-modifier"
3331 3340
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"
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. */
3334 3353
3335 static gboolean 3354 static gboolean
3336 xg_tool_bar_button_cb (widget, event, user_data) 3355 xg_tool_bar_button_cb (widget, event, user_data)
3337 GtkWidget *widget; 3356 GtkWidget *widget;
3338 GdkEventButton *event; 3357 GdkEventButton *event;
3612 event->area.height = max (height, event->area.height); 3631 event->area.height = max (height, event->area.height);
3613 3632
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.
3622 CLIENT_DATA is pointing to the frame for this tool bar. 3643 CLIENT_DATA is pointing to the frame for this tool bar.
3623 3644
3627 xg_tool_bar_expose_callback (w, event, client_data) 3648 xg_tool_bar_expose_callback (w, event, client_data)
3628 GtkWidget *w; 3649 GtkWidget *w;
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
3636 /* Create a tool bar for frame F. */ 3658 /* Create a tool bar for frame F. */
3637 3659
3688 xg_resize_outer_widget (f, FRAME_COLS (f), FRAME_LINES (f)); 3710 xg_resize_outer_widget (f, FRAME_COLS (f), FRAME_LINES (f));
3689 3711
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
3718 static Lisp_Object
3719 find_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
3695 void 3751 void
3696 update_frame_tool_bar (f) 3752 update_frame_tool_bar (f)
3697 FRAME_PTR f; 3753 FRAME_PTR f;
3698 { 3754 {
3699 int i; 3755 int i;
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;
3707 3765
3708 BLOCK_INPUT; 3766 BLOCK_INPUT;
3732 vmargin = max (0, vmargin - DEFAULT_TOOL_BAR_BUTTON_MARGIN); 3790 vmargin = max (0, vmargin - DEFAULT_TOOL_BAR_BUTTON_MARGIN);
3733 3791
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
3754 if (ti) 3819 if (ti)
3755 { 3820 {
3756 weventbox = gtk_bin_get_child (GTK_BIN (ti)); 3821 weventbox = gtk_bin_get_child (GTK_BIN (ti));
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); 3836
3790 3837 if (! NILP (stock) && STRINGP (stock)
3791 if (img->load_failed_p || img->pixmap == None) 3838 && gtk_stock_lookup (SSDATA (stock), &stock_item))
3792 { 3839 {
3793 if (ti) 3840 stock_name = SSDATA (stock);
3794 gtk_widget_hide_all (GTK_WIDGET (ti)); 3841 icon_size = gtk_toolbar_get_icon_size (wtoolbar);
3795 else 3842 }
3843 else
3844 {
3845 /* No stock image, or stock item not known. Try regular image. */
3846
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 ();
3799 wbutton = gtk_button_new ();
3800 gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE);
3801 gtk_button_set_relief (GTK_BUTTON (wbutton), GTK_RELIEF_NONE);
3802 gtk_container_add (GTK_CONTAINER (weventbox), wbutton);
3803 ti = gtk_tool_item_new ();
3804 gtk_container_add (GTK_CONTAINER (ti), weventbox);
3805 gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), ti, -1);
3806 } 3854 }
3807 continue; 3855
3856 if (VECTORP (image))
3857 {
3858 if (enabled_p)
3859 idx = (selected_p
3860 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
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;
3895 }
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);
3816 gtk_button_set_relief (GTK_BUTTON (wbutton), GTK_RELIEF_NONE); 3920 gtk_button_set_relief (GTK_BUTTON (wbutton), GTK_RELIEF_NONE);
3817 gtk_container_add (GTK_CONTAINER (wbutton), w); 3921 gtk_container_add (GTK_CONTAINER (wbutton), w);
3831 GTK_SIGNAL_FUNC (xg_tool_bar_callback), 3935 GTK_SIGNAL_FUNC (xg_tool_bar_callback),
3832 (gpointer) (EMACS_INT) i); 3936 (gpointer) (EMACS_INT) i);
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
3843 /* Catch expose events to overcome an annoying redraw bug, see 3943 /* Catch expose events to overcome an annoying redraw bug, see
3844 comment for xg_tool_bar_item_expose_callback. */ 3944 comment for xg_tool_bar_item_expose_callback. */
3876 else 3976 else
3877 { 3977 {
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);
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);
3999
4000 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME,
4001 NULL);
4002 }
4003
3881 gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin); 4004 gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin);
3882
3883 if (old_img != img->pixmap)
3884 (void) xg_get_image_for_pixmap (f, img, x->widget, wimage);
3885
3886 g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
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));
3891 } 4008 }
3892 4009
3899 { 4016 {
3900 ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (x->toolbar_widget), i++); 4017 ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (x->toolbar_widget), i++);
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 {
3908 FRAME_TOOLBAR_HEIGHT (f) = new_req.height; 4025 FRAME_TOOLBAR_HEIGHT (f) = new_req.height;
3909 xg_resize_outer_widget (f, FRAME_COLS (f), FRAME_LINES (f)); 4026 xg_resize_outer_widget (f, FRAME_COLS (f), FRAME_LINES (f));