From 148c5261bd5375d6601710975160e9910d9fa370 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jan=20Dj=C3=A4rv?= Date: Mon, 22 Mar 2010 15:36:26 +0100 Subject: [PATCH] Fix resize with tabs. --- lisp/Makefile.in | 1 + lisp/native-tabs.el | 31 +++++++++++++++++++ src/gtkutil.c | 72 +++++++++++++++++++++++++++++++++++++++------ src/xterm.h | 6 +++- 4 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 lisp/native-tabs.el diff --git a/lisp/Makefile.in b/lisp/Makefile.in index ddec46405a6..03ef8b3d0d6 100644 --- a/lisp/Makefile.in +++ b/lisp/Makefile.in @@ -992,6 +992,7 @@ ELCFILES = \ $(lisp)/mpc.elc \ $(lisp)/msb.elc \ $(lisp)/mwheel.elc \ + $(lisp)/native-tabs.elc \ $(lisp)/net/ange-ftp.elc \ $(lisp)/net/browse-url.elc \ $(lisp)/net/dbus.elc \ diff --git a/lisp/native-tabs.el b/lisp/native-tabs.el new file mode 100644 index 00000000000..25a59fffeb6 --- /dev/null +++ b/lisp/native-tabs.el @@ -0,0 +1,31 @@ +;; -*- lisp-interaction-mode -*- + +(defun handle-tab-event (event) + "Handle tab-changed-event to change tabs on the frame in EVENT." + (interactive "e") + (let* ((keys (nth 1 event)) + (new-tab (car keys)) + (old-tab (cdr keys)) + (frame (nth 2 event)) + (configs (frame-parameter frame 'tab-config)) + (new-config (assoc new-tab configs)) + (old-config (assoc old-tab configs))) + (if old-config + (setcdr old-config (current-window-configuration)) + (setq configs (append configs + (list (cons old-tab + (current-window-configuration)))))) + (set-frame-parameter frame 'tab-config configs) + (if new-config + (set-window-configuration (cdr new-config))))) + +(if (featurep 'tabs) + (progn + (define-key special-event-map [tab-changed-event] + 'handle-tab-event) + (global-set-key "\C-x70" 'tab-delete) + (global-set-key "\C-x71" 'tab-delete-other) + (global-set-key "\C-x72" 'tab-new) + (global-set-key "\C-x7n" 'tab-next) + (global-set-key "\C-x7p" 'tab-previous))) + diff --git a/src/gtkutil.c b/src/gtkutil.c index 2254978a79e..145a2866be5 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -643,7 +643,8 @@ xg_frame_set_char_size (f, cols, rows) int rows; { int pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows) - + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); + + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f) + + FRAME_TABS_HEIGHT (f); int pixelwidth; if (FRAME_PIXEL_HEIGHT (f) == 0) @@ -759,24 +760,63 @@ xg_pix_to_gcolor (w, pixel, c) #define XG_TAB_KEY "emacs-tab-key" static int xg_tab_nr; +static void +xg_check_show_tabs (FRAME_PTR f, + GtkNotebook *wnote) +{ + gboolean shown = gtk_notebook_get_show_tabs (wnote); + int pages = gtk_notebook_get_n_pages (wnote); + + if ((shown && pages == 1) || (!shown && pages > 1)) + { + gtk_notebook_set_show_tabs (wnote, pages > 1); + GtkRequisition req; + int oldheight = FRAME_TABS_HEIGHT (f); + int row_add = 0; + gtk_widget_size_request (f->output_data.x->notebook_widget, &req); + if (req.height > FRAME_PIXEL_HEIGHT (f)) + FRAME_TABS_HEIGHT (f) = req.height - FRAME_PIXEL_HEIGHT (f); + else + FRAME_TABS_HEIGHT (f) = 0; + x_wm_set_size_hint (f, 0, 0); + + /* Try to minimize resize, when adding the tabs, subtract some text + lines, when removing tabs, add text lines. Some resize will be + made when tab height isn't a multiple of the line height. */ + + if (oldheight > 0 && FRAME_LINE_HEIGHT (f) > 0) + { + row_add = oldheight/FRAME_LINE_HEIGHT (f); + if (row_add * FRAME_LINE_HEIGHT (f) != oldheight) + ++row_add; + } + else if (FRAME_TABS_HEIGHT (f) > 0 && FRAME_LINE_HEIGHT (f) > 0) + { + row_add = -(FRAME_TABS_HEIGHT (f)/FRAME_LINE_HEIGHT (f)); + if (row_add * FRAME_LINE_HEIGHT (f) != FRAME_TABS_HEIGHT (f)) + --row_add; + } + + xg_frame_set_char_size (f, FRAME_COLS (f), FRAME_LINES (f) + row_add); + } +} + /* Callback called when the current tab changes. */ static void -xg_switch_page_cb (GtkNotebook *notebook, +xg_switch_page_cb (GtkNotebook *wnote, GtkNotebookPage *page, guint page_num, gpointer user_data) { BLOCK_INPUT; - GtkWidget *w = gtk_notebook_get_nth_page (notebook, page_num); + GtkWidget *w = gtk_notebook_get_nth_page (wnote, page_num); FRAME_PTR f = (FRAME_PTR) user_data; if (w != FRAME_GTK_WIDGET (f)) { GtkWidget *old = FRAME_GTK_WIDGET (f); GList *children = old ? GTK_FIXED (old)->children : NULL; GSList *todo = NULL, *iter; - struct input_event event; - Lisp_Object frame; char *key = g_object_get_data (G_OBJECT (w), XG_TAB_KEY); if (!w->window) gtk_widget_realize (w); @@ -793,7 +833,7 @@ xg_switch_page_cb (GtkNotebook *notebook, } } - for (iter = todo; iter; iter = iter->next) + for (iter = todo; iter; iter = g_slist_next (iter)) { GtkFixedChild *child = (GtkFixedChild*)iter->data; GtkWidget *wevbox = child->widget; @@ -812,6 +852,9 @@ xg_switch_page_cb (GtkNotebook *notebook, if (old) { char *oldkey = g_object_get_data (G_OBJECT (old), XG_TAB_KEY); + struct input_event event; + Lisp_Object frame; + XSETFRAME (frame, f); EVENT_INIT (event); event.kind = TAB_CHANGED_EVENT; @@ -821,7 +864,7 @@ xg_switch_page_cb (GtkNotebook *notebook, kbd_buffer_store_event (&event); } } - + xg_check_show_tabs (f, wnote); UNBLOCK_INPUT; } @@ -950,6 +993,7 @@ xg_delete_tab (FRAME_PTR f, } gtk_notebook_remove_page (wnote, page_to_remove); } + xg_check_show_tabs (f, wnote); } /* Delete all tabs except the current tab. */ @@ -969,6 +1013,7 @@ xg_delete_all_tabs (FRAME_PTR f) /* Then delete the rest. */ for (i = 0; i < current_page; ++i) gtk_notebook_remove_page (wnote, 0); + xg_check_show_tabs (f, wnote); } /* Make the next tab current. If there are no next tabs, wrap around to 0. */ @@ -1092,9 +1137,17 @@ xg_create_frame_widgets (f) xg_set_geometry (f); f->win_gravity = gtk_window_get_gravity (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); - xg_add_tab (f, NULL); gtk_notebook_popup_enable (GTK_NOTEBOOK (wnote)); gtk_notebook_set_scrollable (GTK_NOTEBOOK (wnote), TRUE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (wnote), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (wnote), 0); + GtkRcStyle *style = gtk_widget_get_modifier_style (wnote); + + /* Must use g_strdup because gtk_widget_modify_style does g_free. */ + style->xthickness = style->ythickness = 0; + gtk_widget_modify_style (wnote, style); + + xg_add_tab (f, NULL); GtkWidget *wfixed = gtk_notebook_get_nth_page (GTK_NOTEBOOK (wnote), 0); /* Must realize the windows so the X window gets created. It is used @@ -1153,7 +1206,8 @@ x_wm_set_size_hint (f, flags, user_position) 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); + + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f) + + FRAME_TABS_HEIGHT (f); check_frame_size (f, &min_rows, &min_cols); diff --git a/src/xterm.h b/src/xterm.h index 846c6df4a11..09be1626c19 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -430,6 +430,7 @@ struct x_output /* Height of tool bar widget, in pixels. Zero if not using an external tool bar. */ int toolbar_height; + int tabs_height; /* The tiled border used when the mouse is out of the frame. */ Pixmap border_tile; @@ -683,6 +684,8 @@ enum #define FRAME_FONTSET(f) ((f)->output_data.x->fontset) #define FRAME_MENUBAR_HEIGHT(f) ((f)->output_data.x->menubar_height) #define FRAME_TOOLBAR_HEIGHT(f) ((f)->output_data.x->toolbar_height) +#define FRAME_TABS_HEIGHT(f) ((f)->output_data.x->tabs_height) + #define FRAME_BASELINE_OFFSET(f) ((f)->output_data.x->baseline_offset) /* This gives the x_display_info structure for the display F is on. */ @@ -711,7 +714,8 @@ enum ((f)->output_data.x->x_pixels_outer_diff) #define FRAME_OUTER_TO_INNER_DIFF_Y(f) \ ((f)->output_data.x->y_pixels_outer_diff \ - + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) + + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f) \ + + FRAME_TABS_HEIGHT (f)) #define FRAME_XIC(f) ((f)->output_data.x->xic) -- 2.39.5