diff options
Diffstat (limited to 'src/gtkutil.c')
| -rw-r--r-- | src/gtkutil.c | 248 |
1 files changed, 184 insertions, 64 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c index 3fb05ba1348..b31eb2d21f2 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)) @@ -640,7 +643,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 +681,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 +738,7 @@ int xg_create_frame_widgets (FRAME_PTR f) { GtkWidget *wtop; - GtkWidget *wvbox; + GtkWidget *wvbox, *whbox; GtkWidget *wfixed; GdkColor bg; GtkRcStyle *style; @@ -749,12 +754,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 +782,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); @@ -889,7 +898,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); @@ -2828,7 +2837,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 +2860,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; } } @@ -3548,13 +3557,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 +3592,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 +3681,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); - - 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); + int into_hbox = EQ (pos, Qleft) || EQ (pos, Qright); - 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) @@ -3875,6 +3922,50 @@ 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; + + 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; + } + + return 0; +} + /* Update the tool bar for frame F. Add new buttons and remove old. */ @@ -3884,7 +3975,6 @@ 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; @@ -3925,7 +4015,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) @@ -4143,18 +4232,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; } @@ -4172,21 +4259,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; +} + /*********************************************************************** |
