emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] feature/tabs a365251: Text-mode display of the tab-bar and


From: Juri Linkov
Subject: [Emacs-diffs] feature/tabs a365251: Text-mode display of the tab-bar and emulation of clicking on a tty.
Date: Tue, 3 Sep 2019 15:56:50 -0400 (EDT)

branch: feature/tabs
commit a365251d01f553a329b6ade5b8a9dd93099caf41
Author: Juri Linkov <address@hidden>
Commit: Juri Linkov <address@hidden>

    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.
---
 lisp/tab-bar.el  |  27 +++++++++++--
 lisp/xt-mouse.el |   8 +++-
 src/frame.c      |  37 ++++++++++++++++++
 src/xdisp.c      | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 182 insertions(+), 6 deletions(-)

diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 1819d44..f596bdb 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -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))
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
index b53174b..5464da2 100644
--- a/lisp/xt-mouse.el
+++ b/lisp/xt-mouse.el
@@ -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)
diff --git a/src/frame.c b/src/frame.c
index 43bd5c2..ae0b60a 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)
                         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;
diff --git a/src/xdisp.c b/src/xdisp.c
index e61d8f7..09a243f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -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
     }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]