Commit ad76020a authored by Eli Zaretskii's avatar Eli Zaretskii

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.
parent 9d829b8b
......@@ -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 */
......@@ -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. */
......
......@@ -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;
}
......
......@@ -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. */
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