/* Functions for creating and updating GTK widgets.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef HAVE_GTK_MULTIDISPLAY
-/* Gtk does not work well without any display open. Emacs may close
- all its displays. In that case, keep a display around just for
- the purpose of having one. */
+/* Keep track of the default display, or NULL if there is none. Emacs
+ may close all its displays. */
static GdkDisplay *gdpy_def;
-
/* Return the GdkDisplay that corresponds to the X display DPY. */
static GdkDisplay *
GdkDisplay *gdpy;
gdpy = gdk_display_open (display_name);
- *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL;
+ if (!gdpy_def && gdpy)
+ {
+ gdpy_def = gdpy;
+ gdk_display_manager_set_default_display (gdk_display_manager_get (),
+ gdpy);
+ }
+ *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL;
return gdpy != NULL;
#else /* not HAVE_GTK_MULTIDISPLAY */
#ifdef HAVE_GTK_MULTIDISPLAY
GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy);
- /* If this is the default display, we must change it before calling
- dispose, otherwise it will crash on some Gtk+ versions. */
+ /* If this is the default display, try to change it before closing.
+ If there is no other display to use, gdpy_def is set to NULL, and
+ the next call to xg_display_open resets the default display. */
if (gdk_display_get_default () == gdpy)
{
struct x_display_info *dpyinfo;
- Display *new_dpy = 0;
- GdkDisplay *gdpy_new;
+ GdkDisplay *gdpy_new = NULL;
/* Find another display. */
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
if (dpyinfo->display != dpy)
{
- new_dpy = dpyinfo->display;
+ gdpy_new = gdk_x11_lookup_xdisplay (dpyinfo->display);
+ gdk_display_manager_set_default_display (gdk_display_manager_get (),
+ gdpy_new);
break;
}
-
- if (new_dpy)
- gdpy_new = gdk_x11_lookup_xdisplay (new_dpy);
- else
- {
- if (!gdpy_def)
- gdpy_def = gdk_display_open (gdk_display_get_name (gdpy));
- gdpy_new = gdpy_def;
- }
-
- gdk_display_manager_set_default_display (gdk_display_manager_get (),
- gdpy_new);
+ gdpy_def = gdpy_new;
}
- /* GTK 2.2-2.8 has a bug that makes gdk_display_close crash (bug
- http://bugzilla.gnome.org/show_bug.cgi?id=85715). This way
- we can continue running, but there will be memory leaks. */
-
#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 10
+ /* GTK 2.2-2.8 has a bug that makes gdk_display_close crash (bug
+ http://bugzilla.gnome.org/show_bug.cgi?id=85715). This way we
+ can continue running, but there will be memory leaks. */
g_object_run_dispose (G_OBJECT (gdpy));
#else
/* This seems to be fixed in GTK 2.10. */
{
/* When the number of already allocated cells is too big,
We free it. */
- free (wv);
+ xfree (wv);
malloc_cpt--;
}
else
if (!g_utf8_validate (str, -1, NULL))
utf8_str = g_locale_to_utf8 (str, -1, 0, 0, 0);
- if (!utf8_str)
+ if (!utf8_str)
{
/* Probably some control characters in str. Escape them. */
size_t nr_bad = 0;
error = NULL;
}
- if (error)
+ if (error)
{
g_error_free (error);
error = NULL;
error = NULL;
}
- if (cp)
+ if (cp)
{
strcat (utf8_str, cp);
g_free (cp);
}
- if (error)
+ if (error)
{
g_error_free (error);
error = NULL;
FRAME_PIXEL_WIDTH (f) = pixelwidth;
FRAME_PIXEL_HEIGHT (f) = pixelheight;
- if (rows != FRAME_LINES (f) || columns != FRAME_COLS (f)
- || (f->new_text_lines != 0 && f->new_text_lines != rows)
- || (f->new_text_cols != 0 && f->new_text_cols != columns))
- {
- change_frame_size (f, rows, columns, 0, 1, 0);
- SET_FRAME_GARBAGED (f);
- cancel_mouse_face (f);
- }
+ change_frame_size (f, rows, columns, 0, 1, 0);
+ SET_FRAME_GARBAGED (f);
+ cancel_mouse_face (f);
}
}
long flags;
int user_position;
{
- if (FRAME_GTK_OUTER_WIDGET (f))
- {
- /* Must use GTK routines here, otherwise GTK resets the size hints
- to its own defaults. */
- GdkGeometry size_hints;
- gint hint_flags = 0;
- int base_width, base_height;
- int min_rows = 0, min_cols = 0;
- int win_gravity = f->win_gravity;
-
- if (flags)
- {
- memset (&size_hints, 0, sizeof (size_hints));
- f->output_data.x->size_hints = size_hints;
- f->output_data.x->hint_flags = hint_flags;
- }
- else
- flags = f->size_hint_flags;
-
- size_hints = f->output_data.x->size_hints;
- hint_flags = f->output_data.x->hint_flags;
-
- hint_flags |= GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE;
- size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
- size_hints.height_inc = FRAME_LINE_HEIGHT (f);
-
- hint_flags |= GDK_HINT_BASE_SIZE;
- base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
- base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0)
- + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
-
- check_frame_size (f, &min_rows, &min_cols);
-
- size_hints.base_width = base_width;
- size_hints.base_height = base_height;
- size_hints.min_width = base_width + min_cols * size_hints.width_inc;
- size_hints.min_height = base_height + min_rows * size_hints.height_inc;
-
-
- /* These currently have a one to one mapping with the X values, but I
- don't think we should rely on that. */
- hint_flags |= GDK_HINT_WIN_GRAVITY;
- size_hints.win_gravity = 0;
- if (win_gravity == NorthWestGravity)
- size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST;
- else if (win_gravity == NorthGravity)
- size_hints.win_gravity = GDK_GRAVITY_NORTH;
- else if (win_gravity == NorthEastGravity)
- size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST;
- else if (win_gravity == WestGravity)
- size_hints.win_gravity = GDK_GRAVITY_WEST;
- else if (win_gravity == CenterGravity)
- size_hints.win_gravity = GDK_GRAVITY_CENTER;
- else if (win_gravity == EastGravity)
- size_hints.win_gravity = GDK_GRAVITY_EAST;
- else if (win_gravity == SouthWestGravity)
- size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST;
- else if (win_gravity == SouthGravity)
- size_hints.win_gravity = GDK_GRAVITY_SOUTH;
- else if (win_gravity == SouthEastGravity)
- size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST;
- else if (win_gravity == StaticGravity)
- size_hints.win_gravity = GDK_GRAVITY_STATIC;
-
- if (flags & PPosition) hint_flags |= GDK_HINT_POS;
- if (flags & USPosition) hint_flags |= GDK_HINT_USER_POS;
- if (flags & USSize) hint_flags |= GDK_HINT_USER_SIZE;
-
- if (user_position)
- {
- hint_flags &= ~GDK_HINT_POS;
- hint_flags |= GDK_HINT_USER_POS;
- }
+ /* Don't set size hints during initialization; that apparently leads
+ to a race condition. See the thread at
+ http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */
+ if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f))
+ return;
- if (hint_flags != f->output_data.x->hint_flags
- || memcmp (&size_hints,
- &f->output_data.x->size_hints,
- sizeof (size_hints)) != 0)
- {
- BLOCK_INPUT;
+ /* Must use GTK routines here, otherwise GTK resets the size hints
+ to its own defaults. */
+ GdkGeometry size_hints;
+ gint hint_flags = 0;
+ int base_width, base_height;
+ int min_rows = 0, min_cols = 0;
+ int win_gravity = f->win_gravity;
- gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- NULL,
- &size_hints,
- hint_flags);
+ if (flags)
+ {
+ memset (&size_hints, 0, sizeof (size_hints));
+ f->output_data.x->size_hints = size_hints;
+ f->output_data.x->hint_flags = hint_flags;
+ }
+ else
+ flags = f->size_hint_flags;
- f->output_data.x->size_hints = size_hints;
- f->output_data.x->hint_flags = hint_flags;
- UNBLOCK_INPUT;
- }
- }
+ size_hints = f->output_data.x->size_hints;
+ hint_flags = f->output_data.x->hint_flags;
+
+ hint_flags |= GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE;
+ size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
+ size_hints.height_inc = FRAME_LINE_HEIGHT (f);
+
+ hint_flags |= GDK_HINT_BASE_SIZE;
+ base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
+ base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0)
+ + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
+
+ check_frame_size (f, &min_rows, &min_cols);
+
+ size_hints.base_width = base_width;
+ size_hints.base_height = base_height;
+ size_hints.min_width = base_width + min_cols * size_hints.width_inc;
+ size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+
+ /* These currently have a one to one mapping with the X values, but I
+ don't think we should rely on that. */
+ hint_flags |= GDK_HINT_WIN_GRAVITY;
+ size_hints.win_gravity = 0;
+ if (win_gravity == NorthWestGravity)
+ size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST;
+ else if (win_gravity == NorthGravity)
+ size_hints.win_gravity = GDK_GRAVITY_NORTH;
+ else if (win_gravity == NorthEastGravity)
+ size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST;
+ else if (win_gravity == WestGravity)
+ size_hints.win_gravity = GDK_GRAVITY_WEST;
+ else if (win_gravity == CenterGravity)
+ size_hints.win_gravity = GDK_GRAVITY_CENTER;
+ else if (win_gravity == EastGravity)
+ size_hints.win_gravity = GDK_GRAVITY_EAST;
+ else if (win_gravity == SouthWestGravity)
+ size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST;
+ else if (win_gravity == SouthGravity)
+ size_hints.win_gravity = GDK_GRAVITY_SOUTH;
+ else if (win_gravity == SouthEastGravity)
+ size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST;
+ else if (win_gravity == StaticGravity)
+ size_hints.win_gravity = GDK_GRAVITY_STATIC;
+
+ if (flags & PPosition) hint_flags |= GDK_HINT_POS;
+ if (flags & USPosition) hint_flags |= GDK_HINT_USER_POS;
+ if (flags & USSize) hint_flags |= GDK_HINT_USER_SIZE;
+
+ if (user_position)
+ {
+ hint_flags &= ~GDK_HINT_POS;
+ hint_flags |= GDK_HINT_USER_POS;
+ }
+
+ if (hint_flags != f->output_data.x->hint_flags
+ || memcmp (&size_hints,
+ &f->output_data.x->size_hints,
+ sizeof (size_hints)) != 0)
+ {
+ BLOCK_INPUT;
+ gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+ NULL, &size_hints, hint_flags);
+ f->output_data.x->size_hints = size_hints;
+ f->output_data.x->hint_flags = hint_flags;
+ UNBLOCK_INPUT;
+ }
}
/* Change background color of a frame.
wbox = gtk_vbox_new (FALSE, 0);
gtk_widget_show (wbox);
wtoggle = gtk_check_button_new_with_label ("Show hidden files.");
-
- if (x_gtk_show_hidden_files)
+
+ if (x_gtk_show_hidden_files)
{
g_object_set (G_OBJECT (filewin), "show-hidden", TRUE, NULL);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle), TRUE);
strcat (message, "\nIf you don't like this file selector, use the "
"corresponding\nkey binding or customize "
"use-file-dialog to turn it off.");
-
+
wmessage = gtk_label_new (message);
gtk_widget_show (wmessage);
}
an absolute name starting with /. */
if (default_filename[0] != '/')
file = Fexpand_file_name (file, Qnil);
-
+
utf8_filename = SSDATA (ENCODE_UTF_8 (file));
if (! NILP (Ffile_directory_p (file)))
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filewin),
/* Update the menu item W so it corresponds to VAL.
SELECT_CB is the callback to use when a menu item is selected.
HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
- CL_DATA is the data to set in the widget for menu invokation. */
+ CL_DATA is the data to set in the widget for menu invocation. */
static void
xg_update_menu_item (val, w, select_cb, highlight_cb, cl_data)
}
/* Callback for button press/release events. Used to start timer so that
- the scroll bar repetition timer in GTK gets handeled.
+ the scroll bar repetition timer in GTK gets handled.
Also, sets bar->dragging to Qnil when dragging (button release) is done.
WIDGET is the scroll bar widget the event is for (not used).
EVENT contains the event.
to `(tool_bar)', see keyboard.c. */
event.kind = TOOL_BAR_EVENT;
event.frame_or_window = frame;
- event.arg = frame;
- kbd_buffer_store_event (&event);
-
- event.kind = TOOL_BAR_EVENT;
+ event.arg = frame;
+ kbd_buffer_store_event (&event);
+
+ event.kind = TOOL_BAR_EVENT;
event.frame_or_window = frame;
event.arg = key;
/* 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
+ Emacs uses. This assumes GDK and 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);
+
+ /* Return focus to the frame after we have clicked on a detached
+ tool bar button. */
+ Fx_focus_frame (frame);
}
/* Callback function invoked when a tool bar item is pressed in a detached
GtkWidget *wbutton = GTK_WIDGET (g_object_get_data (G_OBJECT (w),
XG_TOOL_BAR_PROXY_BUTTON));
xg_tool_bar_callback (wbutton, client_data);
+ FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (wbutton),
+ XG_FRAME_DATA);
}
/* This callback is called when a tool item should create a proxy item,
GtkWidget *wmenuitem = gtk_image_menu_item_new ();
GtkWidget *wmenuimage;
- if (gtk_button_get_use_stock (wbutton))
+ if (gtk_button_get_use_stock (wbutton))
wmenuimage = gtk_image_new_from_stock (gtk_button_get_label (wbutton),
GTK_ICON_SIZE_MENU);
else
else if (store_type == GTK_IMAGE_PIXBUF)
{
gint width, height;
-
+
if (settings &&
gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
&width, &height))
abort ();
}
}
- else if (store_type == GTK_IMAGE_ICON_NAME)
+ else if (store_type == GTK_IMAGE_ICON_NAME)
{
const gchar *icon_name;
GtkIconSize icon_size;
g_signal_connect (G_OBJECT (wmenuitem),
"activate",
- GTK_SIGNAL_FUNC (xg_tool_bar_proxy_callback),
+ G_CALLBACK (xg_tool_bar_proxy_callback),
user_data);
g_object_set_data (G_OBJECT (wmenuitem), XG_TOOL_BAR_PROXY_BUTTON,
for (i = 0; i < f->n_tool_bar_items; ++i)
{
Lisp_Object rtl_image = PROP (TOOL_BAR_ITEM_IMAGES);
- if (!NILP (file = file_for_image (rtl_image)))
+ if (!NILP (file = file_for_image (rtl_image)))
{
file = call1 (intern ("file-name-sans-extension"),
Ffile_name_nondirectory (file));
int icon_size = 0;
struct image *img = NULL;
Lisp_Object image;
- Lisp_Object stock;
+ Lisp_Object stock = Qnil;
GtkStockItem stock_item;
char *stock_name = NULL;
char *icon_name = NULL;
}
else if (gtk_stock_lookup (SSDATA (stock), &stock_item))
icon_size = gtk_toolbar_get_icon_size (wtoolbar);
- else
+ else
{
stock = Qnil;
stock_name = NULL;
img_id = lookup_image (f, image);
img = IMAGE_FROM_ID (f, img_id);
prepare_image_for_display (f, img);
-
+
if (img->load_failed_p || img->pixmap == None)
{
if (ti)
(gpointer) xstrdup (stock_name),
(GDestroyNotify) xfree);
}
- else if (icon_name)
+ else if (icon_name)
{
w = gtk_image_new_from_icon_name (icon_name, icon_size);
g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_ICON_NAME,
/* The EMACS_INT cast avoids a warning. */
g_signal_connect (G_OBJECT (ti), "create-menu-proxy",
- GTK_SIGNAL_FUNC (xg_tool_bar_menu_proxy),
+ G_CALLBACK (xg_tool_bar_menu_proxy),
(gpointer) (EMACS_INT) i);
g_signal_connect (G_OBJECT (wbutton), "clicked",
- GTK_SIGNAL_FUNC (xg_tool_bar_callback),
+ G_CALLBACK (xg_tool_bar_callback),
(gpointer) (EMACS_INT) i);
gtk_widget_show_all (GTK_WIDGET (ti));
gtk_widget_set_sensitive (wbutton, enabled_p);
gtk_tool_item_set_homogeneous (ti, FALSE);
-
+
/* 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 (wbutton, "button-release-event",
- GTK_SIGNAL_FUNC (xg_tool_bar_button_cb),
+ G_CALLBACK (xg_tool_bar_button_cb),
NULL);
g_object_set_data (G_OBJECT (wbutton), XG_FRAME_DATA, (gpointer)f);
/* Make dialogs close on C-g. Since file dialog inherits from
dialog, this works for them also. */
- binding_set = gtk_binding_set_by_class (gtk_type_class (GTK_TYPE_DIALOG));
+ binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_DIALOG));
gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK,
"close", 0);
/* Make menus close on C-g. */
- binding_set = gtk_binding_set_by_class (gtk_type_class (GTK_TYPE_MENU_SHELL));
+ binding_set = gtk_binding_set_by_class (g_type_class_ref
+ (GTK_TYPE_MENU_SHELL));
gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK,
"cancel", 0);
}