summaryrefslogtreecommitdiff
path: root/src/gtkutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkutil.c')
-rw-r--r--src/gtkutil.c502
1 files changed, 410 insertions, 92 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c
index b1bb2e32324..b1591b79f9c 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -44,6 +44,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define FRAME_TOTAL_PIXEL_HEIGHT(f) \
(FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
+#define FRAME_TOTAL_PIXEL_WIDTH(f) \
+ (FRAME_PIXEL_WIDTH (f) + FRAME_TOOLBAR_WIDTH (f))
+
/* Avoid "differ in sign" warnings */
#define SSDATA(x) ((char *) SDATA (x))
@@ -288,7 +291,6 @@ file_for_image (Lisp_Object image)
{
Lisp_Object specified_file = Qnil;
Lisp_Object tail;
- extern Lisp_Object QCfile;
for (tail = XCDR (image);
NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail));
@@ -505,6 +507,172 @@ get_utf8_string (char *str)
/***********************************************************************
+ Tooltips
+ ***********************************************************************/
+/* Gtk+ calls this callback when the parent of our tooltip dummy changes.
+ We use that to pop down the tooltip. This happens if Gtk+ for some
+ reason wants to change or hide the tooltip. */
+
+#ifdef USE_GTK_TOOLTIP
+
+static void
+hierarchy_ch_cb (GtkWidget *widget,
+ GtkWidget *previous_toplevel,
+ gpointer user_data)
+{
+ FRAME_PTR f = (FRAME_PTR) user_data;
+ struct x_output *x = f->output_data.x;
+ GtkWidget *top = gtk_widget_get_toplevel (x->ttip_lbl);
+
+ if (! top || ! GTK_IS_WINDOW (top))
+ gtk_widget_hide (previous_toplevel);
+}
+
+/* Callback called when Gtk+ thinks a tooltip should be displayed.
+ We use it to get the tooltip window and the tooltip widget so
+ we can manipulate the ourselves.
+
+ Return FALSE ensures that the tooltip is not shown. */
+
+static gboolean
+qttip_cb (GtkWidget *widget,
+ gint xpos,
+ gint ypos,
+ gboolean keyboard_mode,
+ GtkTooltip *tooltip,
+ gpointer user_data)
+{
+ FRAME_PTR f = (FRAME_PTR) user_data;
+ struct x_output *x = f->output_data.x;
+ if (x->ttip_widget == NULL)
+ {
+ g_object_set (G_OBJECT (widget), "has-tooltip", FALSE, NULL);
+ x->ttip_widget = tooltip;
+ g_object_ref (G_OBJECT (tooltip));
+ x->ttip_lbl = gtk_label_new ("");
+ g_object_ref (G_OBJECT (x->ttip_lbl));
+ gtk_tooltip_set_custom (tooltip, x->ttip_lbl);
+ x->ttip_window = GTK_WINDOW (gtk_widget_get_toplevel (x->ttip_lbl));
+ /* Realize so we can safely get screen later on. */
+ gtk_widget_realize (GTK_WIDGET (x->ttip_window));
+ gtk_widget_realize (x->ttip_lbl);
+
+ g_signal_connect (x->ttip_lbl, "hierarchy-changed",
+ G_CALLBACK (hierarchy_ch_cb), f);
+ }
+ return FALSE;
+}
+
+#endif /* USE_GTK_TOOLTIP */
+
+/* Prepare a tooltip to be shown, i.e. calculate WIDTH and HEIGHT.
+ Return zero if no system tooltip available, non-zero otherwise. */
+
+int
+xg_prepare_tooltip (FRAME_PTR f,
+ Lisp_Object string,
+ int *width,
+ int *height)
+{
+#ifndef USE_GTK_TOOLTIP
+ return 0;
+#else
+ struct x_output *x = f->output_data.x;
+ GtkWidget *widget;
+ GdkWindow *gwin;
+ GdkScreen *screen;
+ GtkSettings *settings;
+ gboolean tt_enabled = TRUE;
+ GtkRequisition req;
+ Lisp_Object encoded_string;
+
+ if (!x->ttip_lbl) return 0;
+
+ BLOCK_INPUT;
+ encoded_string = ENCODE_UTF_8 (string);
+ widget = GTK_WIDGET (x->ttip_lbl);
+ gwin = gtk_widget_get_window (GTK_WIDGET (x->ttip_window));
+ screen = gdk_drawable_get_screen (gwin);
+ settings = gtk_settings_get_for_screen (screen);
+ g_object_get (settings, "gtk-enable-tooltips", &tt_enabled, NULL);
+ if (tt_enabled)
+ {
+ g_object_set (settings, "gtk-enable-tooltips", FALSE, NULL);
+ /* Record that we disabled it so it can be enabled again. */
+ g_object_set_data (G_OBJECT (x->ttip_window), "restore-tt",
+ (gpointer)f);
+ }
+
+ /* Prevent Gtk+ from hiding tooltip on mouse move and such. */
+ g_object_set_data (G_OBJECT
+ (gtk_widget_get_display (GTK_WIDGET (x->ttip_window))),
+ "gdk-display-current-tooltip", NULL);
+
+ /* Put out dummy widget in so we can get callbacks for unrealize and
+ hierarchy-changed. */
+ gtk_tooltip_set_custom (x->ttip_widget, widget);
+
+ gtk_tooltip_set_text (x->ttip_widget, SDATA (encoded_string));
+ gtk_widget_size_request (GTK_WIDGET (x->ttip_window), &req);
+ if (width) *width = req.width;
+ if (height) *height = req.height;
+
+ UNBLOCK_INPUT;
+
+ return 1;
+#endif /* USE_GTK_TOOLTIP */
+}
+
+/* Show the tooltip at ROOT_X and ROOT_Y.
+ xg_prepare_tooltip must have been called before this function. */
+
+void
+xg_show_tooltip (FRAME_PTR f, int root_x, int root_y)
+{
+#ifdef USE_GTK_TOOLTIP
+ struct x_output *x = f->output_data.x;
+ if (x->ttip_window)
+ {
+ BLOCK_INPUT;
+ gtk_window_move (x->ttip_window, root_x, root_y);
+ gtk_widget_show_all (GTK_WIDGET (x->ttip_window));
+ UNBLOCK_INPUT;
+ }
+#endif
+}
+
+/* Hide tooltip if shown. Do nothing if not shown.
+ Return non-zero if tip was hidden, non-ero if not (i.e. not using
+ system tooltips). */
+
+int
+xg_hide_tooltip (FRAME_PTR f)
+{
+ int ret = 0;
+#ifdef USE_GTK_TOOLTIP
+ if (f->output_data.x->ttip_window)
+ {
+ GtkWindow *win = f->output_data.x->ttip_window;
+ BLOCK_INPUT;
+ gtk_widget_hide (GTK_WIDGET (win));
+
+ if (g_object_get_data (G_OBJECT (win), "restore-tt"))
+ {
+ GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win));
+ GdkScreen *screen = gdk_drawable_get_screen (gwin);
+ GtkSettings *settings = gtk_settings_get_for_screen (screen);
+ g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
+ }
+ UNBLOCK_INPUT;
+
+ ret = 1;
+ }
+#endif
+ return ret;
+}
+
+
+/***********************************************************************
General functions for creating widgets, resizing, events, e.t.c.
***********************************************************************/
@@ -640,7 +808,8 @@ xg_frame_set_char_size (FRAME_PTR f, int cols, int rows)
/* FRAME_TEXT_COLS_TO_PIXEL_WIDTH uses scroll_bar_actual_width, so call it
after calculating that value. */
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
+ pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
+ + FRAME_TOOLBAR_WIDTH (f);
/* Do this before resize, as we don't know yet if we will be resized. */
@@ -677,14 +846,15 @@ xg_frame_set_char_size (FRAME_PTR f, int cols, int rows)
}
}
-/* Handle height changes (i.e. add/remove menu/toolbar).
+/* Handle height/width changes (i.e. add/remove/move menu/toolbar).
The policy is to keep the number of editable lines. */
static void
-xg_height_changed (FRAME_PTR f)
+xg_height_or_width_changed (FRAME_PTR f)
{
gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- FRAME_PIXEL_WIDTH (f), FRAME_TOTAL_PIXEL_HEIGHT (f));
+ FRAME_TOTAL_PIXEL_WIDTH (f),
+ FRAME_TOTAL_PIXEL_HEIGHT (f));
f->output_data.x->hint_flags = 0;
x_wm_set_size_hint (f, 0, 0);
}
@@ -733,7 +903,7 @@ int
xg_create_frame_widgets (FRAME_PTR f)
{
GtkWidget *wtop;
- GtkWidget *wvbox;
+ GtkWidget *wvbox, *whbox;
GtkWidget *wfixed;
GdkColor bg;
GtkRcStyle *style;
@@ -749,12 +919,14 @@ xg_create_frame_widgets (FRAME_PTR f)
xg_set_screen (wtop, f);
wvbox = gtk_vbox_new (FALSE, 0);
+ whbox = gtk_hbox_new (FALSE, 0);
wfixed = gtk_fixed_new (); /* Must have this to place scroll bars */
- if (! wtop || ! wvbox || ! wfixed)
+ if (! wtop || ! wvbox || ! whbox || ! wfixed)
{
if (wtop) gtk_widget_destroy (wtop);
if (wvbox) gtk_widget_destroy (wvbox);
+ if (whbox) gtk_widget_destroy (whbox);
if (wfixed) gtk_widget_destroy (wfixed);
UNBLOCK_INPUT;
@@ -775,11 +947,13 @@ xg_create_frame_widgets (FRAME_PTR f)
FRAME_GTK_OUTER_WIDGET (f) = wtop;
FRAME_GTK_WIDGET (f) = wfixed;
f->output_data.x->vbox_widget = wvbox;
+ f->output_data.x->hbox_widget = whbox;
gtk_widget_set_has_window (wfixed, TRUE);
gtk_container_add (GTK_CONTAINER (wtop), wvbox);
- gtk_box_pack_end (GTK_BOX (wvbox), wfixed, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (wvbox), whbox, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (whbox), wfixed, TRUE, TRUE, 0);
if (FRAME_EXTERNAL_TOOL_BAR (f))
update_frame_tool_bar (f);
@@ -838,17 +1012,38 @@ xg_create_frame_widgets (FRAME_PTR f)
style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("<none>");
gtk_widget_modify_style (wfixed, style);
- /* GTK does not set any border, and they look bad with GTK. */
- /* That they look bad is no excuse for imposing this here. --Stef
- It should be done by providing the proper default in Fx_create_Frame.
- f->border_width = 0;
- f->internal_border_width = 0; */
+#ifdef USE_GTK_TOOLTIP
+ /* Steal a tool tip window we can move ourselves. */
+ f->output_data.x->ttip_widget = 0;
+ f->output_data.x->ttip_lbl = 0;
+ f->output_data.x->ttip_window = 0;
+ gtk_widget_set_tooltip_text (wtop, "Dummy text");
+ g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
+#endif
UNBLOCK_INPUT;
return 1;
}
+void
+xg_free_frame_widgets (FRAME_PTR f)
+{
+ if (FRAME_GTK_OUTER_WIDGET (f))
+ {
+ struct x_output *x = f->output_data.x;
+ gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
+ FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
+ FRAME_GTK_OUTER_WIDGET (f) = 0;
+#ifdef USE_GTK_TOOLTIP
+ if (x->ttip_lbl)
+ gtk_widget_destroy (x->ttip_lbl);
+ if (x->ttip_widget)
+ g_object_unref (G_OBJECT (x->ttip_widget));
+#endif
+ }
+}
+
/* Set the normal size hints for the window manager, for frame F.
FLAGS is the flags word to use--or 0 meaning preserve the flags
that the window now has.
@@ -889,7 +1084,7 @@ x_wm_set_size_hint (FRAME_PTR f, long int flags, int user_position)
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_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0) + FRAME_TOOLBAR_WIDTH (f);
base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0)
+ FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
@@ -988,10 +1183,10 @@ xg_set_frame_icon (FRAME_PTR f, Pixmap icon_pixmap, Pixmap icon_mask)
/* Return the dialog title to use for a dialog of type KEY.
This is the encoding used by lwlib. We use the same for GTK. */
-static char *
+static const char *
get_dialog_title (char key)
{
- char *title = "";
+ const char *title = "";
switch (key) {
case 'E': case 'e':
@@ -1048,7 +1243,7 @@ create_dialog (widget_value *wv,
GCallback select_cb,
GCallback deactivate_cb)
{
- char *title = get_dialog_title (wv->name[0]);
+ const char *title = get_dialog_title (wv->name[0]);
int total_buttons = wv->name[1] - '0';
int right_buttons = wv->name[4] - '0';
int left_buttons;
@@ -1566,7 +1761,7 @@ xg_get_file_name (FRAME_PTR f,
DEFAULT_NAME, if non-zero, is the default font name. */
char *
-xg_get_font_name (FRAME_PTR f, char *default_name)
+xg_get_font_name (FRAME_PTR f, const char *default_name)
{
GtkWidget *w;
char *fontname = NULL;
@@ -1776,7 +1971,7 @@ menu_destroy_callback (GtkWidget *w, gpointer client_data)
Returns the GtkHBox. */
static GtkWidget *
-make_widget_for_menu_item (char *utf8_label, char *utf8_key)
+make_widget_for_menu_item (const char *utf8_label, const char *utf8_key)
{
GtkWidget *wlbl;
GtkWidget *wkey;
@@ -1814,8 +2009,8 @@ make_widget_for_menu_item (char *utf8_label, char *utf8_key)
but the MacOS X version doesn't either, so I guess that is OK. */
static GtkWidget *
-make_menu_item (char *utf8_label,
- char *utf8_key,
+make_menu_item (const char *utf8_label,
+ const char *utf8_key,
widget_value *item,
GSList **group)
{
@@ -2043,7 +2238,7 @@ create_menus (widget_value *data,
int add_tearoff_p,
GtkWidget *topmenu,
xg_menu_cb_data *cl_data,
- char *name)
+ const char *name)
{
widget_value *item;
GtkWidget *wmenu = topmenu;
@@ -2175,7 +2370,7 @@ create_menus (widget_value *data,
Returns the widget created. */
GtkWidget *
-xg_create_widget (char *type, char *name, FRAME_PTR f, widget_value *val,
+xg_create_widget (const char *type, const char *name, FRAME_PTR f, widget_value *val,
GCallback select_cb, GCallback deactivate_cb,
GCallback highlight_cb)
{
@@ -2828,7 +3023,7 @@ xg_update_frame_menubar (FRAME_PTR f)
gtk_widget_show_all (x->menubar_widget);
gtk_widget_size_request (x->menubar_widget, &req);
FRAME_MENUBAR_HEIGHT (f) = req.height;
- xg_height_changed (f);
+ xg_height_or_width_changed (f);
UNBLOCK_INPUT;
return 1;
@@ -2851,7 +3046,7 @@ free_frame_menubar (FRAME_PTR f)
the container. */
x->menubar_widget = 0;
FRAME_MENUBAR_HEIGHT (f) = 0;
- xg_height_changed (f);
+ xg_height_or_width_changed (f);
UNBLOCK_INPUT;
}
}
@@ -3038,7 +3233,7 @@ xg_create_scroll_bar (FRAME_PTR f,
struct scroll_bar *bar,
GCallback scroll_callback,
GCallback end_callback,
- char *scroll_bar_name)
+ const char *scroll_bar_name)
{
GtkWidget *wscroll;
GtkWidget *webox;
@@ -3548,13 +3743,21 @@ xg_tool_bar_detach_callback (GtkHandleBox *wbox,
if (f)
{
+ GtkRequisition req, req2;
FRAME_X_OUTPUT (f)->toolbar_detached = 1;
-
- /* When detaching a tool bar, not everything dissapear. There are
- a few pixels left that are used to drop the tool bar back into
- place. */
- FRAME_TOOLBAR_HEIGHT (f) = 4;
- xg_height_changed (f);
+ gtk_widget_size_request (GTK_WIDGET (wbox), &req);
+ gtk_widget_size_request (w, &req2);
+ req.width -= req2.width;
+ req.height -= req2.height;
+ if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
+ FRAME_TOOLBAR_TOP_HEIGHT (f) = req.height;
+ else if (FRAME_TOOLBAR_BOTTOM_HEIGHT (f) != 0)
+ FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = req.height;
+ else if (FRAME_TOOLBAR_RIGHT_WIDTH (f) != 0)
+ FRAME_TOOLBAR_RIGHT_WIDTH (f) = req.width;
+ else if (FRAME_TOOLBAR_LEFT_WIDTH (f) != 0)
+ FRAME_TOOLBAR_LEFT_WIDTH (f) = req.width;
+ xg_height_or_width_changed (f);
}
}
@@ -3575,13 +3778,21 @@ xg_tool_bar_attach_callback (GtkHandleBox *wbox,
if (f)
{
- GtkRequisition req;
-
+ GtkRequisition req, req2;
FRAME_X_OUTPUT (f)->toolbar_detached = 0;
-
- gtk_widget_size_request (w, &req);
- FRAME_TOOLBAR_HEIGHT (f) = req.height;
- xg_height_changed (f);
+ gtk_widget_size_request (GTK_WIDGET (wbox), &req);
+ gtk_widget_size_request (w, &req2);
+ req.width += req2.width;
+ req.height += req2.height;
+ if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
+ FRAME_TOOLBAR_TOP_HEIGHT (f) = req.height;
+ else if (FRAME_TOOLBAR_BOTTOM_HEIGHT (f) != 0)
+ FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = req.height;
+ else if (FRAME_TOOLBAR_RIGHT_WIDTH (f) != 0)
+ FRAME_TOOLBAR_RIGHT_WIDTH (f) = req.width;
+ else if (FRAME_TOOLBAR_LEFT_WIDTH (f) != 0)
+ FRAME_TOOLBAR_LEFT_WIDTH (f) = req.width;
+ xg_height_or_width_changed (f);
}
}
@@ -3656,41 +3867,63 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
return FALSE;
}
+#ifdef HAVE_GTK_ORIENTABLE_SET_ORIENTATION
+#define toolbar_set_orientation(w, o) \
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (w), o)
+#else
+#define toolbar_set_orientation(w, o) \
+ gtk_toolbar_set_orientation (GTK_TOOLBAR (w), o)
+#endif
+
/* Attach a tool bar to frame F. */
static void
-xg_pack_tool_bar (FRAME_PTR f)
+xg_pack_tool_bar (FRAME_PTR f, Lisp_Object pos)
{
struct x_output *x = f->output_data.x;
- int vbox_pos = x->menubar_widget ? 1 : 0;
-
- x->handlebox_widget = gtk_handle_box_new ();
- g_signal_connect (G_OBJECT (x->handlebox_widget), "child-detached",
- G_CALLBACK (xg_tool_bar_detach_callback), f);
- g_signal_connect (G_OBJECT (x->handlebox_widget), "child-attached",
- G_CALLBACK (xg_tool_bar_attach_callback), f);
+ int into_hbox = EQ (pos, Qleft) || EQ (pos, Qright);
- gtk_container_add (GTK_CONTAINER (x->handlebox_widget),
- x->toolbar_widget);
-
- gtk_box_pack_start (GTK_BOX (x->vbox_widget), x->handlebox_widget,
- FALSE, FALSE, 0);
-
- gtk_box_reorder_child (GTK_BOX (x->vbox_widget), x->handlebox_widget,
- vbox_pos);
+ toolbar_set_orientation (x->toolbar_widget,
+ into_hbox
+ ? GTK_ORIENTATION_VERTICAL
+ : GTK_ORIENTATION_HORIZONTAL);
+ if (!x->handlebox_widget)
+ {
+ x->handlebox_widget = gtk_handle_box_new ();
+ g_signal_connect (G_OBJECT (x->handlebox_widget), "child-detached",
+ G_CALLBACK (xg_tool_bar_detach_callback), f);
+ g_signal_connect (G_OBJECT (x->handlebox_widget), "child-attached",
+ G_CALLBACK (xg_tool_bar_attach_callback), f);
+ gtk_container_add (GTK_CONTAINER (x->handlebox_widget),
+ x->toolbar_widget);
+ }
- gtk_widget_show (x->toolbar_widget);
- gtk_widget_show (x->handlebox_widget);
+ if (into_hbox)
+ {
+ gtk_box_pack_start (GTK_BOX (x->hbox_widget), x->handlebox_widget,
+ FALSE, FALSE, 0);
+
+ if (EQ (pos, Qleft))
+ gtk_box_reorder_child (GTK_BOX (x->hbox_widget),
+ x->handlebox_widget,
+ 0);
+ x->toolbar_in_hbox = 1;
+ }
+ else
+ {
+ int vbox_pos = x->menubar_widget ? 1 : 0;
+ gtk_box_pack_start (GTK_BOX (x->vbox_widget), x->handlebox_widget,
+ FALSE, FALSE, 0);
+
+ if (EQ (pos, Qtop))
+ gtk_box_reorder_child (GTK_BOX (x->vbox_widget),
+ x->handlebox_widget,
+ vbox_pos);
+ x->toolbar_in_hbox = 0;
+ }
}
/* Create a tool bar for frame F. */
-#ifdef HAVE_GTK_ORIENTABLE_SET_ORIENTATION
-#define toolbar_set_orientation(w, o) \
- gtk_orientable_set_orientation (GTK_ORIENTABLE (w), o)
-#else
-#define toolbar_set_orientation(w, o) \
- gtk_toolbar_set_orientation (GTK_TOOLBAR (w), o)
-#endif
static void
xg_create_tool_bar (FRAME_PTR f)
@@ -3703,8 +3936,7 @@ xg_create_tool_bar (FRAME_PTR f)
gtk_widget_set_name (x->toolbar_widget, "emacs-toolbar");
gtk_toolbar_set_style (GTK_TOOLBAR (x->toolbar_widget), GTK_TOOLBAR_ICONS);
- toolbar_set_orientation (x->toolbar_widget,
- GTK_ORIENTATION_HORIZONTAL);
+ toolbar_set_orientation (x->toolbar_widget, GTK_ORIENTATION_HORIZONTAL);
}
@@ -3745,19 +3977,27 @@ static GtkToolItem *
xg_make_tool_item (FRAME_PTR f,
GtkWidget *wimage,
GtkWidget **wbutton,
- char *label,
+ const char *label,
int i)
{
GtkToolItem *ti = gtk_tool_item_new ();
- GtkWidget *vb = EQ (Vtool_bar_style, Qboth_horiz)
+ Lisp_Object style = Ftool_bar_get_system_style ();
+ int both_horiz = EQ (style, Qboth_horiz);
+ int text_image = EQ (style, Qtext_image_horiz);
+
+ GtkWidget *vb = both_horiz || text_image
? gtk_hbox_new (FALSE, 0) : gtk_vbox_new (FALSE, 0);
GtkWidget *wb = gtk_button_new ();
GtkWidget *weventbox = gtk_event_box_new ();
- if (wimage)
+ if (wimage && ! text_image)
gtk_box_pack_start (GTK_BOX (vb), wimage, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vb), gtk_label_new (label), TRUE, TRUE, 0);
+
+ if (wimage && text_image)
+ gtk_box_pack_start (GTK_BOX (vb), wimage, TRUE, TRUE, 0);
+
gtk_button_set_focus_on_click (GTK_BUTTON (wb), FALSE);
gtk_button_set_relief (GTK_BUTTON (wb), GTK_RELIEF_NONE);
gtk_container_add (GTK_CONTAINER (wb), vb);
@@ -3819,11 +4059,12 @@ static void
xg_show_toolbar_item (GtkToolItem *ti)
{
Lisp_Object style = Ftool_bar_get_system_style ();
+ int both_horiz = EQ (style, Qboth_horiz);
+ int text_image = EQ (style, Qtext_image_horiz);
- int show_label = EQ (style, Qboth)
- || EQ (style, Qboth_horiz) || EQ (style, Qtext);
+ int horiz = both_horiz || text_image;
+ int show_label = ! EQ (style, Qimage);
int show_image = ! EQ (style, Qtext);
- int horiz = EQ (style, Qboth_horiz);
GtkWidget *weventbox = gtk_bin_get_child (GTK_BIN (ti));
GtkWidget *wbutton = gtk_bin_get_child (GTK_BIN (weventbox));
@@ -3836,15 +4077,21 @@ xg_show_toolbar_item (GtkToolItem *ti)
new_box = gtk_hbox_new (FALSE, 0);
else if (GTK_IS_HBOX (vb) && !horiz && show_label && show_image)
new_box = gtk_vbox_new (FALSE, 0);
- if (new_box)
+
+ if (!new_box && horiz)
+ gtk_box_reorder_child (GTK_BOX (vb), wlbl, text_image ? 0 : 1);
+ else if (new_box)
{
g_object_ref (G_OBJECT (wimage));
g_object_ref (G_OBJECT (wlbl));
gtk_container_remove (GTK_CONTAINER (vb), wimage);
gtk_container_remove (GTK_CONTAINER (vb), wlbl);
gtk_widget_destroy (GTK_WIDGET (vb));
- gtk_box_pack_start (GTK_BOX (new_box), wimage, TRUE, TRUE, 0);
+ if (! text_image)
+ gtk_box_pack_start (GTK_BOX (new_box), wimage, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (new_box), wlbl, TRUE, TRUE, 0);
+ if (text_image)
+ gtk_box_pack_start (GTK_BOX (new_box), wimage, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (wbutton), new_box);
g_object_unref (G_OBJECT (wimage));
g_object_unref (G_OBJECT (wlbl));
@@ -3861,16 +4108,57 @@ xg_show_toolbar_item (GtkToolItem *ti)
gtk_widget_show (GTK_WIDGET (ti));
}
+static int
+xg_update_tool_bar_sizes (FRAME_PTR f)
+{
+ struct x_output *x = f->output_data.x;
+ GtkRequisition req;
+ int nl = 0, nr = 0, nt = 0, nb = 0;
-/* Update the tool bar for frame F. Add new buttons and remove old. */
+ gtk_widget_size_request (GTK_WIDGET (x->handlebox_widget), &req);
+ if (x->toolbar_in_hbox)
+ {
+ int pos;
+ gtk_container_child_get (GTK_CONTAINER (x->hbox_widget),
+ x->handlebox_widget,
+ "position", &pos, NULL);
+ if (pos == 0) nl = req.width;
+ else nr = req.width;
+ }
+ else
+ {
+ int pos;
+ gtk_container_child_get (GTK_CONTAINER (x->vbox_widget),
+ x->handlebox_widget,
+ "position", &pos, NULL);
+ if (pos == 0 || (pos == 1 && x->menubar_widget)) nt = req.height;
+ else nb = req.height;
+ }
+
+ if (nl != FRAME_TOOLBAR_LEFT_WIDTH (f)
+ || nr != FRAME_TOOLBAR_RIGHT_WIDTH (f)
+ || nt != FRAME_TOOLBAR_TOP_HEIGHT (f)
+ || nb != FRAME_TOOLBAR_BOTTOM_HEIGHT (f))
+ {
+ FRAME_TOOLBAR_RIGHT_WIDTH (f) = FRAME_TOOLBAR_LEFT_WIDTH (f)
+ = FRAME_TOOLBAR_TOP_HEIGHT (f) = FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = 0;
+ FRAME_TOOLBAR_LEFT_WIDTH (f) = nl;
+ FRAME_TOOLBAR_RIGHT_WIDTH (f) = nr;
+ FRAME_TOOLBAR_TOP_HEIGHT (f) = nt;
+ FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = nb;
+ return 1;
+ }
-extern Lisp_Object Qx_gtk_map_stock;
+ return 0;
+}
+
+
+/* Update the tool bar for frame F. Add new buttons and remove old. */
void
update_frame_tool_bar (FRAME_PTR f)
{
int i;
- GtkRequisition old_req, new_req;
struct x_output *x = f->output_data.x;
int hmargin = 0, vmargin = 0;
GtkToolbar *wtoolbar;
@@ -3911,7 +4199,6 @@ update_frame_tool_bar (FRAME_PTR f)
xg_create_tool_bar (f);
wtoolbar = GTK_TOOLBAR (x->toolbar_widget);
- gtk_widget_size_request (GTK_WIDGET (wtoolbar), &old_req);
dir = gtk_widget_get_direction (GTK_WIDGET (wtoolbar));
for (i = 0; i < f->n_tool_bar_items; ++i)
@@ -4129,18 +4416,16 @@ update_frame_tool_bar (FRAME_PTR f)
if (ti) gtk_widget_hide_all (GTK_WIDGET (ti));
} while (ti != NULL);
- new_req.height = 0;
- if (pack_tool_bar && f->n_tool_bar_items != 0)
- xg_pack_tool_bar (f);
-
-
- gtk_widget_size_request (GTK_WIDGET (wtoolbar), &new_req);
- if (old_req.height != new_req.height
- && ! FRAME_X_OUTPUT (f)->toolbar_detached)
+ if (f->n_tool_bar_items != 0)
{
- FRAME_TOOLBAR_HEIGHT (f) = new_req.height;
- xg_height_changed (f);
+ if (pack_tool_bar)
+ xg_pack_tool_bar (f, f->tool_bar_position);
+ gtk_widget_show (x->toolbar_widget);
+ gtk_widget_show (x->handlebox_widget);
+ if (xg_update_tool_bar_sizes (f))
+ xg_height_or_width_changed (f);
}
+
UNBLOCK_INPUT;
}
@@ -4158,21 +4443,54 @@ free_frame_tool_bar (FRAME_PTR f)
BLOCK_INPUT;
/* We may have created the toolbar_widget in xg_create_tool_bar, but
not the x->handlebox_widget which is created in xg_pack_tool_bar. */
- if (is_packed)
- gtk_container_remove (GTK_CONTAINER (x->vbox_widget),
- x->handlebox_widget);
+ if (is_packed)
+ {
+ if (x->toolbar_in_hbox)
+ gtk_container_remove (GTK_CONTAINER (x->hbox_widget),
+ x->handlebox_widget);
+ else
+ gtk_container_remove (GTK_CONTAINER (x->vbox_widget),
+ x->handlebox_widget);
+ }
else
gtk_widget_destroy (x->toolbar_widget);
x->toolbar_widget = 0;
x->handlebox_widget = 0;
- FRAME_TOOLBAR_HEIGHT (f) = 0;
- xg_height_changed (f);
+ FRAME_TOOLBAR_TOP_HEIGHT (f) = FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = 0;
+ FRAME_TOOLBAR_LEFT_WIDTH (f) = FRAME_TOOLBAR_RIGHT_WIDTH (f) = 0;
+
+ xg_height_or_width_changed (f);
UNBLOCK_INPUT;
}
}
+int
+xg_change_toolbar_position (FRAME_PTR f, Lisp_Object pos)
+{
+ struct x_output *x = f->output_data.x;
+
+ if (! x->toolbar_widget || ! x->handlebox_widget)
+ return 1;
+
+ BLOCK_INPUT;
+ g_object_ref (x->handlebox_widget);
+ if (x->toolbar_in_hbox)
+ gtk_container_remove (GTK_CONTAINER (x->hbox_widget),
+ x->handlebox_widget);
+ else
+ gtk_container_remove (GTK_CONTAINER (x->vbox_widget),
+ x->handlebox_widget);
+ xg_pack_tool_bar (f, pos);
+ g_object_unref (x->handlebox_widget);
+ if (xg_update_tool_bar_sizes (f))
+ xg_height_or_width_changed (f);
+
+ UNBLOCK_INPUT;
+ return 1;
+}
+
/***********************************************************************