Commit a365251d authored by Juri Linkov's avatar Juri Linkov

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.
parent c2ab5e8c
Pipeline #3037 failed with stage
in 6 minutes
......@@ -49,7 +49,8 @@
(defface tab-bar
'((default
:box (:line-width 1 :style released-button)
:foreground "black")
:foreground "black"
:background "white")
(((type x w32 ns) (class color))
:background "grey75")
(((type x) (class mono))
......@@ -97,7 +98,27 @@
(global-set-key [(control shift iso-lefttab)] 'tab-bar-switch-to-prev-tab)
(global-set-key [(control tab)] 'tab-bar-switch-to-next-tab)))
;;;###autoload
(defun tab-bar-mouse (event)
"Text-mode emulation of switching tabs on the tab-bar.
This command is used when you click the mouse in the tab-bar
on a console which has no window system but does have a mouse."
(interactive "e")
(let* ((x-position (car (posn-x-y (event-start event))))
(keymap (lookup-key (cons 'keymap (nreverse (current-active-maps))) [tab-bar]))
(column 0))
(when x-position
(unless (catch 'done
(map-keymap
(lambda (_key binding)
(when (eq (car-safe binding) 'menu-item)
(when (> (+ column (length (nth 1 binding))) x-position)
(call-interactively (nth 2 binding))
(throw 'done t))
(setq column (+ column (length (nth 1 binding)) 1))))
keymap))
;; Clicking anywhere outside existing tabs will add a new tab
(tab-bar-add-tab)))))
;; Used in the Show/Hide menu, to have the toggle reflect the current frame.
(defun toggle-tab-bar-mode-from-frame (&optional arg)
"Toggle tab bar on or off, based on the status of the current frame.
......@@ -152,7 +173,7 @@ Return its existing value or a new value."
"Generate an actual keymap from `tab-bar-map', without caching."
(let ((i 0))
(append
'(keymap)
'(keymap (mouse-1 . tab-bar-mouse))
(mapcan
(lambda (tab)
(setq i (1+ i))
......
......@@ -253,7 +253,13 @@ which is the \"1006\" extension implemented in Xterm >= 277."
(top (nth 1 ltrb))
(posn (if w
(posn-at-x-y (- x left) (- y top) w t)
(append (list nil 'menu-bar)
(append (list nil (if (and tab-bar-mode
(or (not menu-bar-mode)
;; The tab-bar is on the
;; second row below menu-bar
(eq (cdr (nth 6 (posn-at-x-y x y))) 1)))
'tab-bar
'menu-bar))
(nthcdr 2 (posn-at-x-y x y)))))
(event (list type posn)))
(setcar (nthcdr 3 posn) timestamp)
......
......@@ -233,6 +233,35 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
0, 1, 0, 0);
}
}
static void
set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
int nlines;
int olines = FRAME_TAB_BAR_LINES (f);
/* Right now, tab bars don't work properly in minibuf-only frames;
most of the commands try to apply themselves to the minibuffer
frame itself, and get an error because you can't switch buffers
in or split the minibuffer window. */
if (FRAME_MINIBUF_ONLY_P (f))
return;
if (TYPE_RANGED_FIXNUMP (int, value))
nlines = XFIXNUM (value);
else
nlines = 0;
if (nlines != olines)
{
windows_or_buffers_changed = 14;
FRAME_TAB_BAR_LINES (f) = nlines;
FRAME_TAB_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
change_frame_size (f, FRAME_COLS (f),
FRAME_LINES (f) + olines - nlines,
0, 1, 0, 0);
}
}
Lisp_Object Vframe_list;
......@@ -382,6 +411,7 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) && NILP (horizontal))
{
int min_height = (FRAME_MENU_BAR_LINES (f)
+ FRAME_TAB_BAR_LINES (f)
+ FRAME_WANTS_MODELINE_P (f)
+ 2); /* one text line and one echo-area line */
if (retval < min_height)
......@@ -1099,6 +1129,9 @@ make_initial_frame (void)
/* The default value of menu-bar-mode is t. */
set_menu_bar_lines (f, make_fixnum (1), Qnil);
/* The default value of tab-bar-mode is nil. */
set_tab_bar_lines (f, make_fixnum (0), Qnil);
/* Allocate glyph matrices. */
adjust_frame_glyphs (f);
......@@ -3086,6 +3119,8 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
{
if (EQ (prop, Qmenu_bar_lines))
set_menu_bar_lines (f, val, make_fixnum (FRAME_MENU_BAR_LINES (f)));
else if (EQ (prop, Qtab_bar_lines))
set_tab_bar_lines (f, val, make_fixnum (FRAME_TAB_BAR_LINES (f)));
else if (EQ (prop, Qname))
set_term_frame_name (f, val);
}
......@@ -3181,6 +3216,8 @@ If FRAME is omitted or nil, return information on the currently selected frame.
Lisp_Object lines;
XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
store_in_alist (&alist, Qmenu_bar_lines, lines);
XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f));
store_in_alist (&alist, Qtab_bar_lines, lines);
}
return alist;
......
......@@ -989,6 +989,7 @@ static int underlying_face_id (struct it *);
#ifdef HAVE_WINDOW_SYSTEM
static void display_tab_bar (struct window *);
static void update_tab_bar (struct frame *, bool);
static void update_tool_bar (struct frame *, bool);
static void gui_draw_bottom_divider (struct window *w);
......@@ -12550,8 +12551,9 @@ fast_set_selected_frame (Lisp_Object frame)
static void
update_tab_bar (struct frame *f, bool save_match_data)
{
bool do_update = (WINDOWP (f->tab_bar_window)
&& WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0);
bool do_update = ((FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window))
? (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
: (FRAME_TAB_BAR_LINES (f) > 0));
if (do_update)
{
......@@ -13029,6 +13031,110 @@ redisplay_tab_bar (struct frame *f)
return false;
}
/* Redisplay the tab bar in the frame for window W.
The tab bar of X frames that don't have X toolkit support is
displayed in a special window W->frame->tab_bar_window.
The tab bar of terminal frames is treated specially as far as
glyph matrices are concerned. Tab bar lines are not part of
windows, so the update is done directly on the frame matrix rows
for the tab bar. */
static void
display_tab_bar (struct window *w)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct it it;
Lisp_Object items;
int i;
bool has_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
/* Don't do all this for graphical frames. */
#ifdef HAVE_NTGUI
if (FRAME_W32_P (f))
return;
#endif
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
if (FRAME_X_P (f))
return;
#endif
#ifdef HAVE_NS
if (FRAME_NS_P (f))
return;
#endif /* HAVE_NS */
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
eassert (!FRAME_WINDOW_P (f));
init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (has_menu_p ? 1 : 0), TAB_BAR_FACE_ID);
it.first_visible_x = 0;
it.last_visible_x = FRAME_PIXEL_WIDTH (f);
#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
if (FRAME_WINDOW_P (f))
{
/* Tab bar lines are displayed in the desired matrix of the
dummy window tab_bar_window. */
struct window *tab_w;
tab_w = XWINDOW (f->tab_bar_window);
init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows + (has_menu_p ? 1 : 0),
TAB_BAR_FACE_ID);
it.first_visible_x = 0;
it.last_visible_x = FRAME_PIXEL_WIDTH (f);
}
else
#endif /* not USE_X_TOOLKIT and not USE_GTK */
{
/* This is a TTY frame, i.e. character hpos/vpos are used as
pixel x/y. */
init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (has_menu_p ? 1 : 0),
TAB_BAR_FACE_ID);
it.first_visible_x = 0;
it.last_visible_x = FRAME_COLS (f);
}
/* FIXME: This should be controlled by a user option. See the
comments in redisplay_tool_bar and display_mode_line about
this. */
it.paragraph_embedding = L2R;
/* Clear all rows of the tab bar. */
for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
{
struct glyph_row *row = it.glyph_row + i;
clear_glyph_row (row);
row->enabled_p = true;
row->full_width_p = true;
row->reversed_p = false;
}
/* Display all items of the tab bar. */
items = it.f->tab_bar_items;
for (i = 0; i < ASIZE (items); i += 11)
{
Lisp_Object string;
/* Stop at nil string. */
string = AREF (items, i + 3);
if (NILP (string))
break;
/* string = build_string ("Test 4"); */
/* Display the item, pad with one space. */
if (it.current_x < it.last_visible_x)
display_string (NULL, string, Qnil, 0, 0, &it,
SCHARS (string) + 1, 0, 0, -1);
}
/* Fill out the line with spaces. */
if (it.current_x < it.last_visible_x)
display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
/* Compute the total height of the lines. */
compute_line_metrics (&it);
}
/* Get information about the tab-bar item which is displayed in GLYPH
on frame F. Return in *PROP_IDX the index where tab-bar item
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)
ignore_mouse_drag_p = true;
#endif
}
else
{
if ((FRAME_TAB_BAR_LINES (f) > 0))
display_tab_bar (w);
}
gui_consider_frame_title (w->frame);
#endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment