diff options
| author | Juri Linkov | 2019-09-03 22:55:13 +0300 |
|---|---|---|
| committer | Juri Linkov | 2019-09-03 22:55:13 +0300 |
| commit | a365251d01f553a329b6ade5b8a9dd93099caf41 (patch) | |
| tree | 7bfad7f767f2871726df1a80122f467da159186d /src | |
| parent | c2ab5e8cf3654e3e13083fb2203502d5d5f49dc6 (diff) | |
| download | emacs-a365251d01f553a329b6ade5b8a9dd93099caf41.tar.gz emacs-a365251d01f553a329b6ade5b8a9dd93099caf41.zip | |
Text-mode display of the tab-bar and emulation of clicking on a tty.
* lisp/tab-bar.el (tab-bar-mouse): New command bound to mouse-1 on [tab-bar].
* lisp/xt-mouse.el (xterm-mouse-event): Use `tab-bar' when clicking
on the tab-bar that is on the second row below menu-bar.
* src/frame.c (set_tab_bar_lines): New function.
(frame_windows_min_size): Add FRAME_TAB_BAR_LINES.
(make_initial_frame): Call set_tab_bar_lines.
(store_frame_param): Call set_tab_bar_lines for Qtab_bar_lines prop.
(Fframe_parameters): Call store_in_alist for Qtab_bar_lines.
* src/xdisp.c (display_tab_bar): New function.
(redisplay_window): Call display_tab_bar when `FRAME_WINDOW_P (f)'
is NULL on a tty.
Diffstat (limited to 'src')
| -rw-r--r-- | src/frame.c | 37 | ||||
| -rw-r--r-- | src/xdisp.c | 116 |
2 files changed, 151 insertions, 2 deletions
diff --git a/src/frame.c b/src/frame.c index 43bd5c2b8c8..ae0b60a58d5 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -233,6 +233,35 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) | |||
| 233 | 0, 1, 0, 0); | 233 | 0, 1, 0, 0); |
| 234 | } | 234 | } |
| 235 | } | 235 | } |
| 236 | |||
| 237 | static void | ||
| 238 | set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) | ||
| 239 | { | ||
| 240 | int nlines; | ||
| 241 | int olines = FRAME_TAB_BAR_LINES (f); | ||
| 242 | |||
| 243 | /* Right now, tab bars don't work properly in minibuf-only frames; | ||
| 244 | most of the commands try to apply themselves to the minibuffer | ||
| 245 | frame itself, and get an error because you can't switch buffers | ||
| 246 | in or split the minibuffer window. */ | ||
| 247 | if (FRAME_MINIBUF_ONLY_P (f)) | ||
| 248 | return; | ||
| 249 | |||
| 250 | if (TYPE_RANGED_FIXNUMP (int, value)) | ||
| 251 | nlines = XFIXNUM (value); | ||
| 252 | else | ||
| 253 | nlines = 0; | ||
| 254 | |||
| 255 | if (nlines != olines) | ||
| 256 | { | ||
| 257 | windows_or_buffers_changed = 14; | ||
| 258 | FRAME_TAB_BAR_LINES (f) = nlines; | ||
| 259 | FRAME_TAB_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); | ||
| 260 | change_frame_size (f, FRAME_COLS (f), | ||
| 261 | FRAME_LINES (f) + olines - nlines, | ||
| 262 | 0, 1, 0, 0); | ||
| 263 | } | ||
| 264 | } | ||
| 236 | 265 | ||
| 237 | Lisp_Object Vframe_list; | 266 | Lisp_Object Vframe_list; |
| 238 | 267 | ||
| @@ -382,6 +411,7 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, | |||
| 382 | if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal)) | 411 | if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal)) |
| 383 | { | 412 | { |
| 384 | int min_height = (FRAME_MENU_BAR_LINES (f) | 413 | int min_height = (FRAME_MENU_BAR_LINES (f) |
| 414 | + FRAME_TAB_BAR_LINES (f) | ||
| 385 | + FRAME_WANTS_MODELINE_P (f) | 415 | + FRAME_WANTS_MODELINE_P (f) |
| 386 | + 2); /* one text line and one echo-area line */ | 416 | + 2); /* one text line and one echo-area line */ |
| 387 | if (retval < min_height) | 417 | if (retval < min_height) |
| @@ -1099,6 +1129,9 @@ make_initial_frame (void) | |||
| 1099 | /* The default value of menu-bar-mode is t. */ | 1129 | /* The default value of menu-bar-mode is t. */ |
| 1100 | set_menu_bar_lines (f, make_fixnum (1), Qnil); | 1130 | set_menu_bar_lines (f, make_fixnum (1), Qnil); |
| 1101 | 1131 | ||
| 1132 | /* The default value of tab-bar-mode is nil. */ | ||
| 1133 | set_tab_bar_lines (f, make_fixnum (0), Qnil); | ||
| 1134 | |||
| 1102 | /* Allocate glyph matrices. */ | 1135 | /* Allocate glyph matrices. */ |
| 1103 | adjust_frame_glyphs (f); | 1136 | adjust_frame_glyphs (f); |
| 1104 | 1137 | ||
| @@ -3086,6 +3119,8 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) | |||
| 3086 | { | 3119 | { |
| 3087 | if (EQ (prop, Qmenu_bar_lines)) | 3120 | if (EQ (prop, Qmenu_bar_lines)) |
| 3088 | set_menu_bar_lines (f, val, make_fixnum (FRAME_MENU_BAR_LINES (f))); | 3121 | set_menu_bar_lines (f, val, make_fixnum (FRAME_MENU_BAR_LINES (f))); |
| 3122 | else if (EQ (prop, Qtab_bar_lines)) | ||
| 3123 | set_tab_bar_lines (f, val, make_fixnum (FRAME_TAB_BAR_LINES (f))); | ||
| 3089 | else if (EQ (prop, Qname)) | 3124 | else if (EQ (prop, Qname)) |
| 3090 | set_term_frame_name (f, val); | 3125 | set_term_frame_name (f, val); |
| 3091 | } | 3126 | } |
| @@ -3181,6 +3216,8 @@ If FRAME is omitted or nil, return information on the currently selected frame. | |||
| 3181 | Lisp_Object lines; | 3216 | Lisp_Object lines; |
| 3182 | XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f)); | 3217 | XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f)); |
| 3183 | store_in_alist (&alist, Qmenu_bar_lines, lines); | 3218 | store_in_alist (&alist, Qmenu_bar_lines, lines); |
| 3219 | XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f)); | ||
| 3220 | store_in_alist (&alist, Qtab_bar_lines, lines); | ||
| 3184 | } | 3221 | } |
| 3185 | 3222 | ||
| 3186 | return alist; | 3223 | return alist; |
diff --git a/src/xdisp.c b/src/xdisp.c index e61d8f7feac..09a243f5ae0 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -989,6 +989,7 @@ static int underlying_face_id (struct it *); | |||
| 989 | 989 | ||
| 990 | #ifdef HAVE_WINDOW_SYSTEM | 990 | #ifdef HAVE_WINDOW_SYSTEM |
| 991 | 991 | ||
| 992 | static void display_tab_bar (struct window *); | ||
| 992 | static void update_tab_bar (struct frame *, bool); | 993 | static void update_tab_bar (struct frame *, bool); |
| 993 | static void update_tool_bar (struct frame *, bool); | 994 | static void update_tool_bar (struct frame *, bool); |
| 994 | static void gui_draw_bottom_divider (struct window *w); | 995 | static void gui_draw_bottom_divider (struct window *w); |
| @@ -12550,8 +12551,9 @@ fast_set_selected_frame (Lisp_Object frame) | |||
| 12550 | static void | 12551 | static void |
| 12551 | update_tab_bar (struct frame *f, bool save_match_data) | 12552 | update_tab_bar (struct frame *f, bool save_match_data) |
| 12552 | { | 12553 | { |
| 12553 | bool do_update = (WINDOWP (f->tab_bar_window) | 12554 | bool do_update = ((FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) |
| 12554 | && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0); | 12555 | ? (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0) |
| 12556 | : (FRAME_TAB_BAR_LINES (f) > 0)); | ||
| 12555 | 12557 | ||
| 12556 | if (do_update) | 12558 | if (do_update) |
| 12557 | { | 12559 | { |
| @@ -13029,6 +13031,110 @@ redisplay_tab_bar (struct frame *f) | |||
| 13029 | return false; | 13031 | return false; |
| 13030 | } | 13032 | } |
| 13031 | 13033 | ||
| 13034 | /* Redisplay the tab bar in the frame for window W. | ||
| 13035 | |||
| 13036 | The tab bar of X frames that don't have X toolkit support is | ||
| 13037 | displayed in a special window W->frame->tab_bar_window. | ||
| 13038 | |||
| 13039 | The tab bar of terminal frames is treated specially as far as | ||
| 13040 | glyph matrices are concerned. Tab bar lines are not part of | ||
| 13041 | windows, so the update is done directly on the frame matrix rows | ||
| 13042 | for the tab bar. */ | ||
| 13043 | |||
| 13044 | static void | ||
| 13045 | display_tab_bar (struct window *w) | ||
| 13046 | { | ||
| 13047 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 13048 | struct it it; | ||
| 13049 | Lisp_Object items; | ||
| 13050 | int i; | ||
| 13051 | bool has_menu_p = FRAME_MENU_BAR_LINES (f) > 0; | ||
| 13052 | |||
| 13053 | /* Don't do all this for graphical frames. */ | ||
| 13054 | #ifdef HAVE_NTGUI | ||
| 13055 | if (FRAME_W32_P (f)) | ||
| 13056 | return; | ||
| 13057 | #endif | ||
| 13058 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) | ||
| 13059 | if (FRAME_X_P (f)) | ||
| 13060 | return; | ||
| 13061 | #endif | ||
| 13062 | |||
| 13063 | #ifdef HAVE_NS | ||
| 13064 | if (FRAME_NS_P (f)) | ||
| 13065 | return; | ||
| 13066 | #endif /* HAVE_NS */ | ||
| 13067 | |||
| 13068 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) | ||
| 13069 | eassert (!FRAME_WINDOW_P (f)); | ||
| 13070 | init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (has_menu_p ? 1 : 0), TAB_BAR_FACE_ID); | ||
| 13071 | it.first_visible_x = 0; | ||
| 13072 | it.last_visible_x = FRAME_PIXEL_WIDTH (f); | ||
| 13073 | #elif defined (HAVE_X_WINDOWS) /* X without toolkit. */ | ||
| 13074 | if (FRAME_WINDOW_P (f)) | ||
| 13075 | { | ||
| 13076 | /* Tab bar lines are displayed in the desired matrix of the | ||
| 13077 | dummy window tab_bar_window. */ | ||
| 13078 | struct window *tab_w; | ||
| 13079 | tab_w = XWINDOW (f->tab_bar_window); | ||
| 13080 | init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows + (has_menu_p ? 1 : 0), | ||
| 13081 | TAB_BAR_FACE_ID); | ||
| 13082 | it.first_visible_x = 0; | ||
| 13083 | it.last_visible_x = FRAME_PIXEL_WIDTH (f); | ||
| 13084 | } | ||
| 13085 | else | ||
| 13086 | #endif /* not USE_X_TOOLKIT and not USE_GTK */ | ||
| 13087 | { | ||
| 13088 | /* This is a TTY frame, i.e. character hpos/vpos are used as | ||
| 13089 | pixel x/y. */ | ||
| 13090 | init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (has_menu_p ? 1 : 0), | ||
| 13091 | TAB_BAR_FACE_ID); | ||
| 13092 | it.first_visible_x = 0; | ||
| 13093 | it.last_visible_x = FRAME_COLS (f); | ||
| 13094 | } | ||
| 13095 | |||
| 13096 | /* FIXME: This should be controlled by a user option. See the | ||
| 13097 | comments in redisplay_tool_bar and display_mode_line about | ||
| 13098 | this. */ | ||
| 13099 | it.paragraph_embedding = L2R; | ||
| 13100 | |||
| 13101 | /* Clear all rows of the tab bar. */ | ||
| 13102 | for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i) | ||
| 13103 | { | ||
| 13104 | struct glyph_row *row = it.glyph_row + i; | ||
| 13105 | clear_glyph_row (row); | ||
| 13106 | row->enabled_p = true; | ||
| 13107 | row->full_width_p = true; | ||
| 13108 | row->reversed_p = false; | ||
| 13109 | } | ||
| 13110 | |||
| 13111 | /* Display all items of the tab bar. */ | ||
| 13112 | items = it.f->tab_bar_items; | ||
| 13113 | for (i = 0; i < ASIZE (items); i += 11) | ||
| 13114 | { | ||
| 13115 | Lisp_Object string; | ||
| 13116 | |||
| 13117 | /* Stop at nil string. */ | ||
| 13118 | string = AREF (items, i + 3); | ||
| 13119 | if (NILP (string)) | ||
| 13120 | break; | ||
| 13121 | |||
| 13122 | /* string = build_string ("Test 4"); */ | ||
| 13123 | |||
| 13124 | /* Display the item, pad with one space. */ | ||
| 13125 | if (it.current_x < it.last_visible_x) | ||
| 13126 | display_string (NULL, string, Qnil, 0, 0, &it, | ||
| 13127 | SCHARS (string) + 1, 0, 0, -1); | ||
| 13128 | } | ||
| 13129 | |||
| 13130 | /* Fill out the line with spaces. */ | ||
| 13131 | if (it.current_x < it.last_visible_x) | ||
| 13132 | display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1); | ||
| 13133 | |||
| 13134 | /* Compute the total height of the lines. */ | ||
| 13135 | compute_line_metrics (&it); | ||
| 13136 | } | ||
| 13137 | |||
| 13032 | /* Get information about the tab-bar item which is displayed in GLYPH | 13138 | /* Get information about the tab-bar item which is displayed in GLYPH |
| 13033 | on frame F. Return in *PROP_IDX the index where tab-bar item | 13139 | on frame F. Return in *PROP_IDX the index where tab-bar item |
| 13034 | properties start in F->tab_bar_items. Value is false if | 13140 | properties start in F->tab_bar_items. Value is false if |
| @@ -18631,6 +18737,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 18631 | ignore_mouse_drag_p = true; | 18737 | ignore_mouse_drag_p = true; |
| 18632 | #endif | 18738 | #endif |
| 18633 | } | 18739 | } |
| 18740 | else | ||
| 18741 | { | ||
| 18742 | if ((FRAME_TAB_BAR_LINES (f) > 0)) | ||
| 18743 | display_tab_bar (w); | ||
| 18744 | } | ||
| 18745 | |||
| 18634 | gui_consider_frame_title (w->frame); | 18746 | gui_consider_frame_title (w->frame); |
| 18635 | #endif | 18747 | #endif |
| 18636 | } | 18748 | } |