X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/4c9ca1a3ebeea5942a2f9e06160e627eec43a1ed..7f32b80b1110fab9b5010502ebb28e30a757e446:/src/gtkutil.c diff --git a/src/gtkutil.c b/src/gtkutil.c index 065adeb493..b8d37df221 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1,5 +1,5 @@ /* Functions for creating and updating GTK widgets. - Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -199,7 +199,7 @@ malloc_widget_value () } else { - wv = (widget_value *) malloc (sizeof (widget_value)); + wv = (widget_value *) xmalloc (sizeof (widget_value)); malloc_cpt++; } memset (wv, 0, sizeof (widget_value)); @@ -327,6 +327,7 @@ xg_get_image_for_pixmap (f, img, widget, old_widget) look good in all cases. */ Lisp_Object specified_file = Qnil; Lisp_Object tail; + Lisp_Object file; extern Lisp_Object QCfile; for (tail = XCDR (img->spec); @@ -335,23 +336,18 @@ xg_get_image_for_pixmap (f, img, widget, old_widget) if (EQ (XCAR (tail), QCfile)) specified_file = XCAR (XCDR (tail)); - if (STRINGP (specified_file)) - { - Lisp_Object file = Qnil; - struct gcpro gcpro1; - GCPRO1 (file); - - file = x_find_image_file (specified_file); - /* We already loaded the image once before calling this - function, so this should not fail. */ - xassert (STRINGP (file) != 0); + /* We already loaded the image once before calling this + function, so this only fails if the image file has been removed. + In that case, use the pixmap already loaded. */ + if (STRINGP (specified_file) + && STRINGP (file = x_find_image_file (specified_file))) + { if (! old_widget) old_widget = GTK_IMAGE (gtk_image_new_from_file (SSDATA (file))); else gtk_image_set_from_file (old_widget, SSDATA (file)); - UNGCPRO; return GTK_WIDGET (old_widget); } @@ -3242,11 +3238,28 @@ xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) the GtkImage with a new image. */ #define XG_TOOL_BAR_IMAGE_DATA "emacs-tool-bar-image" +/* The key for storing the latest modifiers so the activate callback can + get them. */ +#define XG_TOOL_BAR_LAST_MODIFIER "emacs-tool-bar-modifier" + + /* Callback function invoked when a tool bar item is pressed. W is the button widget in the tool bar that got pressed, CLIENT_DATA is an integer that is the index of the button in the tool bar. 0 is the first button. */ +static gboolean +xg_tool_bar_button_cb (widget, event, user_data) + GtkWidget *widget; + GdkEventButton *event; + gpointer user_data; +{ + g_object_set_data (G_OBJECT (user_data), XG_TOOL_BAR_LAST_MODIFIER, + (gpointer) event->state); + return FALSE; +} + + static void xg_tool_bar_callback (w, client_data) GtkWidget *w; @@ -3254,6 +3267,8 @@ xg_tool_bar_callback (w, client_data) { /* The EMACS_INT cast avoids a warning. */ int idx = (int) (EMACS_INT) client_data; + int mod = (int) g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER); + FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA); Lisp_Object key, frame; struct input_event event; @@ -3274,7 +3289,10 @@ xg_tool_bar_callback (w, client_data) event.kind = TOOL_BAR_EVENT; event.frame_or_window = frame; event.arg = key; - event.modifiers = 0; /* These are not available. */ + /* Convert between the modifier bits GDK uses and the modifier bits + Emacs uses. This assumes GDK an X masks are the same, which they are when + this is written. */ + event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), mod); kbd_buffer_store_event (&event); } @@ -3292,6 +3310,10 @@ xg_tool_bar_detach_callback (wbox, w, client_data) gpointer client_data; { FRAME_PTR f = (FRAME_PTR) client_data; + extern int x_gtk_whole_detached_tool_bar; + + g_object_set (G_OBJECT (w), "show-arrow", !x_gtk_whole_detached_tool_bar, + NULL); if (f) { @@ -3322,6 +3344,7 @@ xg_tool_bar_attach_callback (wbox, w, client_data) gpointer client_data; { FRAME_PTR f = (FRAME_PTR) client_data; + g_object_set (G_OBJECT (w), "show-arrow", TRUE, NULL); if (f) { @@ -3359,9 +3382,7 @@ xg_tool_bar_help_callback (w, event, client_data) Lisp_Object help, frame; if (! GTK_IS_BUTTON (w)) - { - return FALSE; - } + return FALSE; if (! f || ! f->n_tool_bar_items || NILP (f->tool_bar_items)) return FALSE; @@ -3596,54 +3617,63 @@ update_frame_tool_bar (f) if (! wicon) { GtkWidget *w = xg_get_image_for_pixmap (f, img, x->widget, NULL); + GtkToolItem *ti = gtk_tool_button_new (w, ""); gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin); + gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), + ti, + i); /* The EMACS_INT cast avoids a warning. */ - gtk_toolbar_append_item (GTK_TOOLBAR (x->toolbar_widget), - 0, 0, 0, - w, - GTK_SIGNAL_FUNC (xg_tool_bar_callback), - (gpointer) (EMACS_INT) i); + g_signal_connect (GTK_WIDGET (ti), "clicked", + GTK_SIGNAL_FUNC (xg_tool_bar_callback), + (gpointer) (EMACS_INT) i); + + gtk_widget_show (GTK_WIDGET (ti)); + gtk_widget_show (GTK_WIDGET (w)); /* Save the image so we can see if an update is needed when this function is called again. */ g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA, (gpointer)img->pixmap); + g_object_set_data (G_OBJECT (ti), XG_FRAME_DATA, (gpointer)f); + /* Catch expose events to overcome an annoying redraw bug, see comment for xg_tool_bar_item_expose_callback. */ - g_signal_connect (G_OBJECT (w), + g_signal_connect (G_OBJECT (ti), "expose-event", G_CALLBACK (xg_tool_bar_item_expose_callback), 0); - /* We must set sensitive on the button that is the parent - of the GtkImage parent. Go upwards until we find the button. */ + gtk_widget_set_sensitive (GTK_WIDGET (ti), enabled_p); + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (ti), FALSE); + while (! GTK_IS_BUTTON (w)) w = gtk_widget_get_parent (w); - if (w) - { - /* Save the frame in the button so the xg_tool_bar_callback - can get at it. */ - g_object_set_data (G_OBJECT (w), XG_FRAME_DATA, (gpointer)f); - gtk_widget_set_sensitive (w, enabled_p); - - /* Use enter/leave notify to show help. We use the events - rather than the GtkButton specific signals "enter" and - "leave", so we can have only one callback. The event - will tell us what kind of event it is. */ - /* The EMACS_INT cast avoids a warning. */ - g_signal_connect (G_OBJECT (w), - "enter-notify-event", - G_CALLBACK (xg_tool_bar_help_callback), - (gpointer) (EMACS_INT) i); - g_signal_connect (G_OBJECT (w), - "leave-notify-event", - G_CALLBACK (xg_tool_bar_help_callback), - (gpointer) (EMACS_INT) i); - } + /* Callback to save modifyer mask (Shift/Control, etc). GTK makes + no distinction based on modifiers in the activate callback, + so we have to do it ourselves. */ + g_signal_connect (w, "button-release-event", + GTK_SIGNAL_FUNC (xg_tool_bar_button_cb), + ti); + + g_object_set_data (G_OBJECT (w), XG_FRAME_DATA, (gpointer)f); + + /* Use enter/leave notify to show help. We use the events + rather than the GtkButton specific signals "enter" and + "leave", so we can have only one callback. The event + will tell us what kind of event it is. */ + /* The EMACS_INT cast avoids a warning. */ + g_signal_connect (G_OBJECT (w), + "enter-notify-event", + G_CALLBACK (xg_tool_bar_help_callback), + (gpointer) (EMACS_INT) i); + g_signal_connect (G_OBJECT (w), + "leave-notify-event", + G_CALLBACK (xg_tool_bar_help_callback), + (gpointer) (EMACS_INT) i); } else {