emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master ad76020 1/2: Support mouse clicks on tab bar on TTY


From: Eli Zaretskii
Subject: [Emacs-diffs] master ad76020 1/2: Support mouse clicks on tab bar on TTY frames
Date: Sun, 6 Oct 2019 12:55:10 -0400 (EDT)

branch: master
commit ad76020af8498d148984daf4de545d5d610d0589
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    Support mouse clicks on tab bar on TTY frames
    
    This for now doesn't work on GPM.
    * src/xdisp.c (display_tab_bar): Make the loop over tab-bar
    items more efficient.
    (tab_bar_item_info, tool_bar_item_info): Correct data type for
    CHARPOS.
    (tty_get_tab_bar_item, tty_handle_tab_bar_click): New functions.
    (note_mouse_highlight): Handle help-echo of tab-bar tabs on
    TTY frames.
    * src/w32inevt.c (do_mouse_event): Call
    tty_handle_tab_bar_click to process mouse clicks on the tab bar.
    * src/termchar.h (tty_handle_tab_bar_click): Add prototype.
    * src/w32console.c (w32con_set_terminal_modes): Disable Quick
    Edit mode on entry, to make sure mouse events get reported to
    us.
---
 src/termchar.h   |   4 ++
 src/w32console.c |   9 +++-
 src/w32inevt.c   |  25 +++++++----
 src/xdisp.c      | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 146 insertions(+), 17 deletions(-)

diff --git a/src/termchar.h b/src/termchar.h
index 796453d..11c964b 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -231,4 +231,8 @@ extern struct tty_display_info *tty_list;
 
 #define CURTTY() FRAME_TTY (SELECTED_FRAME())
 
+struct input_event;
+extern bool tty_handle_tab_bar_click (struct frame *, int, int, bool,
+                                     struct input_event *);
+
 #endif /* EMACS_TERMCHAR_H */
diff --git a/src/w32console.c b/src/w32console.c
index 8575c93..c50bb67 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -503,7 +503,14 @@ w32con_set_terminal_modes (struct terminal *t)
 
   SetConsoleActiveScreenBuffer (cur_screen);
 
-  SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
+  /* If Quick Edit is enabled for the console, it will get in the way
+     of receiving mouse events, so we disable it.  But leave the
+     Insert Mode as it was set by the user.  */
+  DWORD new_console_mode
+    = ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | ENABLE_EXTENDED_FLAGS;
+  if ((prev_console_mode & ENABLE_INSERT_MODE) != 0)
+    new_console_mode |= ENABLE_INSERT_MODE;
+  SetConsoleMode (keyboard_handle, new_console_mode);
 
   /* Initialize input mode: interrupt_input off, no flow control, allow
      8 bit character input, standard quit char.  */
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 0a1321c..1a901d4 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -559,8 +559,6 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
       if (event->dwButtonState == button_state)
        return 0;
 
-      emacs_ev->kind = MOUSE_CLICK_EVENT;
-
       /* Find out what button has changed state since the last button
         event.  */
       but_change = button_state ^ event->dwButtonState;
@@ -576,15 +574,24 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
          }
 
       button_state = event->dwButtonState;
-      emacs_ev->modifiers =
-       w32_kbd_mods_to_emacs (event->dwControlKeyState, 0)
-       | ((event->dwButtonState & mask) ? down_modifier : up_modifier);
+      emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 
0);
+      emacs_ev->timestamp = GetTickCount ();
+
+      int x = event->dwMousePosition.X;
+      int y = event->dwMousePosition.Y;
+      struct frame *f = get_frame ();
+      if (tty_handle_tab_bar_click (f, x, y, (button_state & mask) != 0,
+                                   emacs_ev))
+       return 0;       /* tty_handle_tab_bar_click adds the event to queue */
 
-      XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
-      XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
-      XSETFRAME (emacs_ev->frame_or_window, get_frame ());
+      emacs_ev->modifiers |= ((button_state & mask)
+                             ? down_modifier : up_modifier);
+
+      emacs_ev->kind = MOUSE_CLICK_EVENT;
+      XSETFASTINT (emacs_ev->x, x);
+      XSETFASTINT (emacs_ev->y, y);
+      XSETFRAME (emacs_ev->frame_or_window, f);
       emacs_ev->arg = Qnil;
-      emacs_ev->timestamp = GetTickCount ();
 
       return 1;
     }
diff --git a/src/xdisp.c b/src/xdisp.c
index f5dedc2..8aa38c8 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12746,12 +12746,12 @@ display_tab_bar (struct window *w)
 
   /* Display all items of the tab bar.  */
   items = it.f->tab_bar_items;
-  for (i = 0; i < it.f->n_tab_bar_items; ++i)
+  int j;
+  for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
     {
-      Lisp_Object string;
+      Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
 
       /* Stop at nil string.  */
-      string = AREF (items, i * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_CAPTION);
       if (NILP (string))
        break;
 
@@ -13180,7 +13180,7 @@ tab_bar_item_info (struct frame *f, struct glyph *glyph,
                   int *prop_idx, bool *close_p)
 {
   Lisp_Object prop;
-  int charpos;
+  ptrdiff_t charpos;
 
   /* This function can be called asynchronously, which means we must
      exclude any possibility that Fget_text_property signals an
@@ -13256,7 +13256,7 @@ get_tab_bar_item (struct frame *f, int x, int y, struct 
glyph **glyph,
 
 void
 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
-                      int modifiers)
+                     int modifiers)
 {
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
   struct window *w = XWINDOW (f->tab_bar_window);
@@ -13420,6 +13420,96 @@ note_tab_bar_highlight (struct frame *f, int x, int y)
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
+/* Find the tab-bar item at X coordinate and return its information.  */
+static Lisp_Object
+tty_get_tab_bar_item (struct frame *f, int x, int *idx, ptrdiff_t *end)
+{
+  ptrdiff_t clen = 0;
+  Lisp_Object caption;
+
+  int i, j;
+  for (i = 0, j = 0; i < f->n_tab_bar_items; i++, j += TAB_BAR_ITEM_NSLOTS)
+    {
+      caption = AREF (f->tab_bar_items, j + TAB_BAR_ITEM_CAPTION);
+      if (NILP (caption))
+       return Qnil;
+      clen += SCHARS (caption);
+      if (x < clen)
+       break;
+    }
+  if (i < f->n_tab_bar_items)
+    {
+      *idx = i;
+      *end = clen;
+      return caption;
+    }
+  else
+    return Qnil;
+}
+
+/* Handle a mouse click at X/Y on the tab bar of TTY frame F.  If the
+   click was on the tab bar and was handled, populate the EVENT
+   structure, store it in keyboard queue, and return true; otherwise
+   return false.  MODIFIERS are event modifiers for generating the tab
+   release event.  */
+bool
+tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
+                         struct input_event *event)
+{
+  /* Did they click on the tab bar?  */
+  if (y < FRAME_MENU_BAR_LINES (f)
+      || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
+    return false;
+
+  /* Find the tab-bar item where the X,Y coordinates belong.  */
+  int prop_idx;
+  ptrdiff_t clen;
+  Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &clen);
+
+  if (NILP (caption))
+    return false;
+
+  if (NILP (AREF (f->tab_bar_items,
+                 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
+    return false;
+
+  if (down_p)
+    f->last_tab_bar_item = prop_idx;
+  else
+    {
+      /* Generate a TAB_BAR_EVENT event.  */
+      Lisp_Object frame;
+      Lisp_Object key = AREF (f->tab_bar_items,
+                             prop_idx * TAB_BAR_ITEM_NSLOTS
+                             + TAB_BAR_ITEM_KEY);
+      /* Kludge alert: we assume the last two characters of a tab
+        label are " x", and treat clicks on those 2 characters as a
+        Close Tab command.  */
+      eassert (STRINGP (caption));
+      int lastc = SSDATA (caption)[SCHARS (caption) - 1];
+      bool close_p = false;
+      if ((x == clen - 1 || (clen > 1 && x == clen - 2)) && lastc == 'x')
+       close_p = true;
+
+      event->code = 0;
+      XSETFRAME (frame, f);
+      event->kind = TAB_BAR_EVENT;
+      event->frame_or_window = frame;
+      event->arg = frame;
+      kbd_buffer_store_event (event);
+
+      event->kind = TAB_BAR_EVENT;
+      event->frame_or_window = frame;
+      event->arg = key;
+      if (close_p)
+       event->modifiers |= ctrl_modifier;
+      kbd_buffer_store_event (event);
+      f->last_tab_bar_item = -1;
+    }
+
+  return true;
+}
+
 
 
 /***********************************************************************
@@ -14065,7 +14155,7 @@ static bool
 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
 {
   Lisp_Object prop;
-  int charpos;
+  ptrdiff_t charpos;
 
   /* This function can be called asynchronously, which means we must
      exclude any possibility that Fget_text_property signals an
@@ -32711,9 +32801,30 @@ note_mouse_highlight (struct frame *f, int x, int y)
          && part != ON_TAB_LINE))
     clear_mouse_face (hlinfo);
 
-  /* Reset help_echo_string. It will get recomputed below.  */
+  /* Reset help_echo_string.  It will get recomputed below.  */
   help_echo_string = Qnil;
 
+  /* Handle tab-bar highlight on mouse-capable TTY frames.  */
+  if (!FRAME_WINDOW_P (f)
+      && (y >= FRAME_MENU_BAR_LINES (f)
+         && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
+    {
+      int prop_idx;
+      ptrdiff_t ignore;
+      Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
+
+      if (!NILP (caption))
+       {
+         help_echo_object = help_echo_window = Qnil;
+         help_echo_pos = -1;
+         help_echo_string = AREF (f->tab_bar_items,
+                                  prop_idx * TAB_BAR_ITEM_NSLOTS
+                                  + TAB_BAR_ITEM_HELP);
+         if (NILP (help_echo_string))
+           help_echo_string = caption;
+       }
+    }
+
 #ifdef HAVE_WINDOW_SYSTEM
   /* If the cursor is on the internal border of FRAME and FRAME's
      internal border is draggable, provide some visual feedback.  */



reply via email to

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