diff options
| author | Eli Zaretskii | 2019-10-06 19:53:18 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2019-10-06 19:53:18 +0300 |
| commit | ad76020af8498d148984daf4de545d5d610d0589 (patch) | |
| tree | 1f748991403fdb1f7f1f92f449dc38e5ddcceff7 | |
| parent | 9d829b8be5b86668d5165b9d0c0cdc392b558dd3 (diff) | |
| download | emacs-ad76020af8498d148984daf4de545d5d610d0589.tar.gz emacs-ad76020af8498d148984daf4de545d5d610d0589.zip | |
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.
| -rw-r--r-- | src/termchar.h | 4 | ||||
| -rw-r--r-- | src/w32console.c | 9 | ||||
| -rw-r--r-- | src/w32inevt.c | 25 | ||||
| -rw-r--r-- | src/xdisp.c | 125 |
4 files changed, 146 insertions, 17 deletions
diff --git a/src/termchar.h b/src/termchar.h index 796453d3cca..11c964b2b6d 100644 --- a/src/termchar.h +++ b/src/termchar.h | |||
| @@ -231,4 +231,8 @@ extern struct tty_display_info *tty_list; | |||
| 231 | 231 | ||
| 232 | #define CURTTY() FRAME_TTY (SELECTED_FRAME()) | 232 | #define CURTTY() FRAME_TTY (SELECTED_FRAME()) |
| 233 | 233 | ||
| 234 | struct input_event; | ||
| 235 | extern bool tty_handle_tab_bar_click (struct frame *, int, int, bool, | ||
| 236 | struct input_event *); | ||
| 237 | |||
| 234 | #endif /* EMACS_TERMCHAR_H */ | 238 | #endif /* EMACS_TERMCHAR_H */ |
diff --git a/src/w32console.c b/src/w32console.c index 8575c930a85..c50bb67cd2c 100644 --- a/src/w32console.c +++ b/src/w32console.c | |||
| @@ -503,7 +503,14 @@ w32con_set_terminal_modes (struct terminal *t) | |||
| 503 | 503 | ||
| 504 | SetConsoleActiveScreenBuffer (cur_screen); | 504 | SetConsoleActiveScreenBuffer (cur_screen); |
| 505 | 505 | ||
| 506 | SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT); | 506 | /* If Quick Edit is enabled for the console, it will get in the way |
| 507 | of receiving mouse events, so we disable it. But leave the | ||
| 508 | Insert Mode as it was set by the user. */ | ||
| 509 | DWORD new_console_mode | ||
| 510 | = ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | ENABLE_EXTENDED_FLAGS; | ||
| 511 | if ((prev_console_mode & ENABLE_INSERT_MODE) != 0) | ||
| 512 | new_console_mode |= ENABLE_INSERT_MODE; | ||
| 513 | SetConsoleMode (keyboard_handle, new_console_mode); | ||
| 507 | 514 | ||
| 508 | /* Initialize input mode: interrupt_input off, no flow control, allow | 515 | /* Initialize input mode: interrupt_input off, no flow control, allow |
| 509 | 8 bit character input, standard quit char. */ | 516 | 8 bit character input, standard quit char. */ |
diff --git a/src/w32inevt.c b/src/w32inevt.c index 0a1321c6d89..1a901d4e0aa 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c | |||
| @@ -559,8 +559,6 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, | |||
| 559 | if (event->dwButtonState == button_state) | 559 | if (event->dwButtonState == button_state) |
| 560 | return 0; | 560 | return 0; |
| 561 | 561 | ||
| 562 | emacs_ev->kind = MOUSE_CLICK_EVENT; | ||
| 563 | |||
| 564 | /* Find out what button has changed state since the last button | 562 | /* Find out what button has changed state since the last button |
| 565 | event. */ | 563 | event. */ |
| 566 | but_change = button_state ^ event->dwButtonState; | 564 | but_change = button_state ^ event->dwButtonState; |
| @@ -576,15 +574,24 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, | |||
| 576 | } | 574 | } |
| 577 | 575 | ||
| 578 | button_state = event->dwButtonState; | 576 | button_state = event->dwButtonState; |
| 579 | emacs_ev->modifiers = | 577 | emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0); |
| 580 | w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) | 578 | emacs_ev->timestamp = GetTickCount (); |
| 581 | | ((event->dwButtonState & mask) ? down_modifier : up_modifier); | 579 | |
| 580 | int x = event->dwMousePosition.X; | ||
| 581 | int y = event->dwMousePosition.Y; | ||
| 582 | struct frame *f = get_frame (); | ||
| 583 | if (tty_handle_tab_bar_click (f, x, y, (button_state & mask) != 0, | ||
| 584 | emacs_ev)) | ||
| 585 | return 0; /* tty_handle_tab_bar_click adds the event to queue */ | ||
| 582 | 586 | ||
| 583 | XSETFASTINT (emacs_ev->x, event->dwMousePosition.X); | 587 | emacs_ev->modifiers |= ((button_state & mask) |
| 584 | XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y); | 588 | ? down_modifier : up_modifier); |
| 585 | XSETFRAME (emacs_ev->frame_or_window, get_frame ()); | 589 | |
| 590 | emacs_ev->kind = MOUSE_CLICK_EVENT; | ||
| 591 | XSETFASTINT (emacs_ev->x, x); | ||
| 592 | XSETFASTINT (emacs_ev->y, y); | ||
| 593 | XSETFRAME (emacs_ev->frame_or_window, f); | ||
| 586 | emacs_ev->arg = Qnil; | 594 | emacs_ev->arg = Qnil; |
| 587 | emacs_ev->timestamp = GetTickCount (); | ||
| 588 | 595 | ||
| 589 | return 1; | 596 | return 1; |
| 590 | } | 597 | } |
diff --git a/src/xdisp.c b/src/xdisp.c index f5dedc218e2..8aa38c8034c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -12746,12 +12746,12 @@ display_tab_bar (struct window *w) | |||
| 12746 | 12746 | ||
| 12747 | /* Display all items of the tab bar. */ | 12747 | /* Display all items of the tab bar. */ |
| 12748 | items = it.f->tab_bar_items; | 12748 | items = it.f->tab_bar_items; |
| 12749 | for (i = 0; i < it.f->n_tab_bar_items; ++i) | 12749 | int j; |
| 12750 | for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS) | ||
| 12750 | { | 12751 | { |
| 12751 | Lisp_Object string; | 12752 | Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION); |
| 12752 | 12753 | ||
| 12753 | /* Stop at nil string. */ | 12754 | /* Stop at nil string. */ |
| 12754 | string = AREF (items, i * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_CAPTION); | ||
| 12755 | if (NILP (string)) | 12755 | if (NILP (string)) |
| 12756 | break; | 12756 | break; |
| 12757 | 12757 | ||
| @@ -13180,7 +13180,7 @@ tab_bar_item_info (struct frame *f, struct glyph *glyph, | |||
| 13180 | int *prop_idx, bool *close_p) | 13180 | int *prop_idx, bool *close_p) |
| 13181 | { | 13181 | { |
| 13182 | Lisp_Object prop; | 13182 | Lisp_Object prop; |
| 13183 | int charpos; | 13183 | ptrdiff_t charpos; |
| 13184 | 13184 | ||
| 13185 | /* This function can be called asynchronously, which means we must | 13185 | /* This function can be called asynchronously, which means we must |
| 13186 | exclude any possibility that Fget_text_property signals an | 13186 | 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, | |||
| 13256 | 13256 | ||
| 13257 | void | 13257 | void |
| 13258 | handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, | 13258 | handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, |
| 13259 | int modifiers) | 13259 | int modifiers) |
| 13260 | { | 13260 | { |
| 13261 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); | 13261 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 13262 | struct window *w = XWINDOW (f->tab_bar_window); | 13262 | struct window *w = XWINDOW (f->tab_bar_window); |
| @@ -13420,6 +13420,96 @@ note_tab_bar_highlight (struct frame *f, int x, int y) | |||
| 13420 | 13420 | ||
| 13421 | #endif /* HAVE_WINDOW_SYSTEM */ | 13421 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 13422 | 13422 | ||
| 13423 | /* Find the tab-bar item at X coordinate and return its information. */ | ||
| 13424 | static Lisp_Object | ||
| 13425 | tty_get_tab_bar_item (struct frame *f, int x, int *idx, ptrdiff_t *end) | ||
| 13426 | { | ||
| 13427 | ptrdiff_t clen = 0; | ||
| 13428 | Lisp_Object caption; | ||
| 13429 | |||
| 13430 | int i, j; | ||
| 13431 | for (i = 0, j = 0; i < f->n_tab_bar_items; i++, j += TAB_BAR_ITEM_NSLOTS) | ||
| 13432 | { | ||
| 13433 | caption = AREF (f->tab_bar_items, j + TAB_BAR_ITEM_CAPTION); | ||
| 13434 | if (NILP (caption)) | ||
| 13435 | return Qnil; | ||
| 13436 | clen += SCHARS (caption); | ||
| 13437 | if (x < clen) | ||
| 13438 | break; | ||
| 13439 | } | ||
| 13440 | if (i < f->n_tab_bar_items) | ||
| 13441 | { | ||
| 13442 | *idx = i; | ||
| 13443 | *end = clen; | ||
| 13444 | return caption; | ||
| 13445 | } | ||
| 13446 | else | ||
| 13447 | return Qnil; | ||
| 13448 | } | ||
| 13449 | |||
| 13450 | /* Handle a mouse click at X/Y on the tab bar of TTY frame F. If the | ||
| 13451 | click was on the tab bar and was handled, populate the EVENT | ||
| 13452 | structure, store it in keyboard queue, and return true; otherwise | ||
| 13453 | return false. MODIFIERS are event modifiers for generating the tab | ||
| 13454 | release event. */ | ||
| 13455 | bool | ||
| 13456 | tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, | ||
| 13457 | struct input_event *event) | ||
| 13458 | { | ||
| 13459 | /* Did they click on the tab bar? */ | ||
| 13460 | if (y < FRAME_MENU_BAR_LINES (f) | ||
| 13461 | || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)) | ||
| 13462 | return false; | ||
| 13463 | |||
| 13464 | /* Find the tab-bar item where the X,Y coordinates belong. */ | ||
| 13465 | int prop_idx; | ||
| 13466 | ptrdiff_t clen; | ||
| 13467 | Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &clen); | ||
| 13468 | |||
| 13469 | if (NILP (caption)) | ||
| 13470 | return false; | ||
| 13471 | |||
| 13472 | if (NILP (AREF (f->tab_bar_items, | ||
| 13473 | prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P))) | ||
| 13474 | return false; | ||
| 13475 | |||
| 13476 | if (down_p) | ||
| 13477 | f->last_tab_bar_item = prop_idx; | ||
| 13478 | else | ||
| 13479 | { | ||
| 13480 | /* Generate a TAB_BAR_EVENT event. */ | ||
| 13481 | Lisp_Object frame; | ||
| 13482 | Lisp_Object key = AREF (f->tab_bar_items, | ||
| 13483 | prop_idx * TAB_BAR_ITEM_NSLOTS | ||
| 13484 | + TAB_BAR_ITEM_KEY); | ||
| 13485 | /* Kludge alert: we assume the last two characters of a tab | ||
| 13486 | label are " x", and treat clicks on those 2 characters as a | ||
| 13487 | Close Tab command. */ | ||
| 13488 | eassert (STRINGP (caption)); | ||
| 13489 | int lastc = SSDATA (caption)[SCHARS (caption) - 1]; | ||
| 13490 | bool close_p = false; | ||
| 13491 | if ((x == clen - 1 || (clen > 1 && x == clen - 2)) && lastc == 'x') | ||
| 13492 | close_p = true; | ||
| 13493 | |||
| 13494 | event->code = 0; | ||
| 13495 | XSETFRAME (frame, f); | ||
| 13496 | event->kind = TAB_BAR_EVENT; | ||
| 13497 | event->frame_or_window = frame; | ||
| 13498 | event->arg = frame; | ||
| 13499 | kbd_buffer_store_event (event); | ||
| 13500 | |||
| 13501 | event->kind = TAB_BAR_EVENT; | ||
| 13502 | event->frame_or_window = frame; | ||
| 13503 | event->arg = key; | ||
| 13504 | if (close_p) | ||
| 13505 | event->modifiers |= ctrl_modifier; | ||
| 13506 | kbd_buffer_store_event (event); | ||
| 13507 | f->last_tab_bar_item = -1; | ||
| 13508 | } | ||
| 13509 | |||
| 13510 | return true; | ||
| 13511 | } | ||
| 13512 | |||
| 13423 | 13513 | ||
| 13424 | 13514 | ||
| 13425 | /*********************************************************************** | 13515 | /*********************************************************************** |
| @@ -14065,7 +14155,7 @@ static bool | |||
| 14065 | tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx) | 14155 | tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx) |
| 14066 | { | 14156 | { |
| 14067 | Lisp_Object prop; | 14157 | Lisp_Object prop; |
| 14068 | int charpos; | 14158 | ptrdiff_t charpos; |
| 14069 | 14159 | ||
| 14070 | /* This function can be called asynchronously, which means we must | 14160 | /* This function can be called asynchronously, which means we must |
| 14071 | exclude any possibility that Fget_text_property signals an | 14161 | exclude any possibility that Fget_text_property signals an |
| @@ -32711,9 +32801,30 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 32711 | && part != ON_TAB_LINE)) | 32801 | && part != ON_TAB_LINE)) |
| 32712 | clear_mouse_face (hlinfo); | 32802 | clear_mouse_face (hlinfo); |
| 32713 | 32803 | ||
| 32714 | /* Reset help_echo_string. It will get recomputed below. */ | 32804 | /* Reset help_echo_string. It will get recomputed below. */ |
| 32715 | help_echo_string = Qnil; | 32805 | help_echo_string = Qnil; |
| 32716 | 32806 | ||
| 32807 | /* Handle tab-bar highlight on mouse-capable TTY frames. */ | ||
| 32808 | if (!FRAME_WINDOW_P (f) | ||
| 32809 | && (y >= FRAME_MENU_BAR_LINES (f) | ||
| 32810 | && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))) | ||
| 32811 | { | ||
| 32812 | int prop_idx; | ||
| 32813 | ptrdiff_t ignore; | ||
| 32814 | Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore); | ||
| 32815 | |||
| 32816 | if (!NILP (caption)) | ||
| 32817 | { | ||
| 32818 | help_echo_object = help_echo_window = Qnil; | ||
| 32819 | help_echo_pos = -1; | ||
| 32820 | help_echo_string = AREF (f->tab_bar_items, | ||
| 32821 | prop_idx * TAB_BAR_ITEM_NSLOTS | ||
| 32822 | + TAB_BAR_ITEM_HELP); | ||
| 32823 | if (NILP (help_echo_string)) | ||
| 32824 | help_echo_string = caption; | ||
| 32825 | } | ||
| 32826 | } | ||
| 32827 | |||
| 32717 | #ifdef HAVE_WINDOW_SYSTEM | 32828 | #ifdef HAVE_WINDOW_SYSTEM |
| 32718 | /* If the cursor is on the internal border of FRAME and FRAME's | 32829 | /* If the cursor is on the internal border of FRAME and FRAME's |
| 32719 | internal border is draggable, provide some visual feedback. */ | 32830 | internal border is draggable, provide some visual feedback. */ |