diff options
| author | Eli Zaretskii | 2012-05-26 15:14:56 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2012-05-26 15:14:56 +0300 |
| commit | 53a63be64de2c4a28ffcd275398255976a380fee (patch) | |
| tree | 8d131c07086847e5756ac31e140908bae1ccbb1d | |
| parent | 4cfd81f6c9755fb87eaf9f529c2bcbb0a30edfcf (diff) | |
| parent | c4aeb92ab4ffdc943f330c9cce22d65eaba743af (diff) | |
| download | emacs-53a63be64de2c4a28ffcd275398255976a380fee.tar.gz emacs-53a63be64de2c4a28ffcd275398255976a380fee.zip | |
Extend mouse support on W32 text-mode console.
src/xdisp.c (draw_row_with_mouse_face): Call
tty_draw_row_with_mouse_face for WINDOWSNT as well.
src/w32console.c: Include window.h.
(w32con_write_glyphs_with_face, tty_draw_row_with_mouse_face): New
functions.
(initialize_w32_display): Initialize mouse-highlight data.
src/w32inevt.c: Include termchar.h and window.h.
(do_mouse_event): Support mouse-autoselect-window. When the mouse
moves, call note_mouse_highlight. If help_echo changed, call
gen_help_event to produce help-echo message in the echo area.
Call clear_mouse_face if mouse_face_hidden is set in the mouse
highlight info.
etc/NEWS: Describe the changes.
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | src/ChangeLog | 18 | ||||
| -rw-r--r-- | src/w32console.c | 89 | ||||
| -rw-r--r-- | src/w32inevt.c | 59 | ||||
| -rw-r--r-- | src/xdisp.c | 2 |
5 files changed, 167 insertions, 5 deletions
| @@ -313,6 +313,10 @@ by the underlying C implementation. | |||
| 313 | *** --without-libxml2 omits support for libxml2, even if its presence | 313 | *** --without-libxml2 omits support for libxml2, even if its presence |
| 314 | is detected. | 314 | is detected. |
| 315 | 315 | ||
| 316 | ** When invoked with the -nw switch to run on the Windows text-mode terminal, | ||
| 317 | Emacs now supports mouse highlight, help-echo (in the echo area), and | ||
| 318 | mouse-autoselect-window. | ||
| 319 | |||
| 316 | 320 | ||
| 317 | * Installation Changes in Emacs 24.1 | 321 | * Installation Changes in Emacs 24.1 |
| 318 | 322 | ||
diff --git a/src/ChangeLog b/src/ChangeLog index 2981e754c8a..c71ea45dded 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2012-05-26 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | Extend mouse support on W32 text-mode console. | ||
| 4 | * xdisp.c (draw_row_with_mouse_face): Call | ||
| 5 | tty_draw_row_with_mouse_face for WINDOWSNT as well. | ||
| 6 | |||
| 7 | * w32console.c: Include window.h. | ||
| 8 | (w32con_write_glyphs_with_face, tty_draw_row_with_mouse_face): New | ||
| 9 | functions. | ||
| 10 | (initialize_w32_display): Initialize mouse-highlight data. | ||
| 11 | |||
| 12 | * w32inevt.c: Include termchar.h and window.h. | ||
| 13 | (do_mouse_event): Support mouse-autoselect-window. When the mouse | ||
| 14 | moves, call note_mouse_highlight. If help_echo changed, call | ||
| 15 | gen_help_event to produce help-echo message in the echo area. | ||
| 16 | Call clear_mouse_face if mouse_face_hidden is set in the mouse | ||
| 17 | highlight info. | ||
| 18 | |||
| 1 | 2012-05-26 Paul Eggert <eggert@cs.ucla.edu> | 19 | 2012-05-26 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 20 | ||
| 3 | * lread.c (read1): Simplify slightly to avoid an overflow warning | 21 | * lread.c (read1): Simplify slightly to avoid an overflow warning |
diff --git a/src/w32console.c b/src/w32console.c index e8b0f621b4f..22f329e239d 100644 --- a/src/w32console.c +++ b/src/w32console.c | |||
| @@ -33,6 +33,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 33 | #include "coding.h" | 33 | #include "coding.h" |
| 34 | #include "disptab.h" | 34 | #include "disptab.h" |
| 35 | #include "frame.h" | 35 | #include "frame.h" |
| 36 | #include "window.h" | ||
| 36 | #include "termhooks.h" | 37 | #include "termhooks.h" |
| 37 | #include "termchar.h" | 38 | #include "termchar.h" |
| 38 | #include "dispextern.h" | 39 | #include "dispextern.h" |
| @@ -339,6 +340,84 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string, | |||
| 339 | } | 340 | } |
| 340 | } | 341 | } |
| 341 | 342 | ||
| 343 | /* Used for mouse highlight. */ | ||
| 344 | static void | ||
| 345 | w32con_write_glyphs_with_face (struct frame *f, register int x, register int y, | ||
| 346 | register struct glyph *string, register int len, | ||
| 347 | register int face_id) | ||
| 348 | { | ||
| 349 | unsigned char *conversion_buffer; | ||
| 350 | struct coding_system *coding; | ||
| 351 | |||
| 352 | if (len <= 0) | ||
| 353 | return; | ||
| 354 | |||
| 355 | /* If terminal_coding does any conversion, use it, otherwise use | ||
| 356 | safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here | ||
| 357 | because it always return 1 if the member src_multibyte is 1. */ | ||
| 358 | coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK | ||
| 359 | ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding); | ||
| 360 | /* We are going to write the entire block of glyphs in one go, as | ||
| 361 | they all have the same face. So this _is_ the last block. */ | ||
| 362 | coding->mode |= CODING_MODE_LAST_BLOCK; | ||
| 363 | |||
| 364 | conversion_buffer = encode_terminal_code (string, len, coding); | ||
| 365 | if (coding->produced > 0) | ||
| 366 | { | ||
| 367 | DWORD filled, written; | ||
| 368 | /* Compute the character attributes corresponding to the face. */ | ||
| 369 | DWORD char_attr = w32_face_attributes (f, face_id); | ||
| 370 | COORD start_coords; | ||
| 371 | |||
| 372 | start_coords.X = x; | ||
| 373 | start_coords.Y = y; | ||
| 374 | /* Set the attribute for these characters. */ | ||
| 375 | if (!FillConsoleOutputAttribute (cur_screen, char_attr, | ||
| 376 | coding->produced, start_coords, | ||
| 377 | &filled)) | ||
| 378 | DebPrint (("Failed writing console attributes: %d\n", GetLastError ())); | ||
| 379 | else | ||
| 380 | { | ||
| 381 | /* Write the characters. */ | ||
| 382 | if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer, | ||
| 383 | filled, start_coords, &written)) | ||
| 384 | DebPrint (("Failed writing console characters: %d\n", | ||
| 385 | GetLastError ())); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | /* Implementation of draw_row_with_mouse_face for W32 console. */ | ||
| 391 | void | ||
| 392 | tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, | ||
| 393 | int start_hpos, int end_hpos, | ||
| 394 | enum draw_glyphs_face draw) | ||
| 395 | { | ||
| 396 | int nglyphs = end_hpos - start_hpos; | ||
| 397 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | ||
| 398 | struct tty_display_info *tty = FRAME_TTY (f); | ||
| 399 | int face_id = tty->mouse_highlight.mouse_face_face_id; | ||
| 400 | int pos_x, pos_y; | ||
| 401 | |||
| 402 | if (end_hpos >= row->used[TEXT_AREA]) | ||
| 403 | nglyphs = row->used[TEXT_AREA] - start_hpos; | ||
| 404 | |||
| 405 | pos_y = row->y + WINDOW_TOP_EDGE_Y (w); | ||
| 406 | pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); | ||
| 407 | |||
| 408 | if (draw == DRAW_MOUSE_FACE) | ||
| 409 | w32con_write_glyphs_with_face (f, pos_x, pos_y, | ||
| 410 | row->glyphs[TEXT_AREA] + start_hpos, | ||
| 411 | nglyphs, face_id); | ||
| 412 | else if (draw == DRAW_NORMAL_TEXT) | ||
| 413 | { | ||
| 414 | COORD save_coords = cursor_coords; | ||
| 415 | |||
| 416 | w32con_move_cursor (f, pos_y, pos_x); | ||
| 417 | write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); | ||
| 418 | w32con_move_cursor (f, save_coords.Y, save_coords.X); | ||
| 419 | } | ||
| 420 | } | ||
| 342 | 421 | ||
| 343 | static void | 422 | static void |
| 344 | w32con_delete_glyphs (struct frame *f, int n) | 423 | w32con_delete_glyphs (struct frame *f, int n) |
| @@ -570,6 +649,7 @@ void | |||
| 570 | initialize_w32_display (struct terminal *term) | 649 | initialize_w32_display (struct terminal *term) |
| 571 | { | 650 | { |
| 572 | CONSOLE_SCREEN_BUFFER_INFO info; | 651 | CONSOLE_SCREEN_BUFFER_INFO info; |
| 652 | Mouse_HLInfo *hlinfo; | ||
| 573 | 653 | ||
| 574 | term->rif = 0; /* No window based redisplay on the console. */ | 654 | term->rif = 0; /* No window based redisplay on the console. */ |
| 575 | term->cursor_to_hook = w32con_move_cursor; | 655 | term->cursor_to_hook = w32con_move_cursor; |
| @@ -600,6 +680,15 @@ initialize_w32_display (struct terminal *term) | |||
| 600 | term->judge_scroll_bars_hook = 0; | 680 | term->judge_scroll_bars_hook = 0; |
| 601 | term->frame_up_to_date_hook = 0; | 681 | term->frame_up_to_date_hook = 0; |
| 602 | 682 | ||
| 683 | /* Initialize the mouse-highlight data. */ | ||
| 684 | hlinfo = &term->display_info.tty->mouse_highlight; | ||
| 685 | hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; | ||
| 686 | hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; | ||
| 687 | hlinfo->mouse_face_face_id = DEFAULT_FACE_ID; | ||
| 688 | hlinfo->mouse_face_mouse_frame = NULL; | ||
| 689 | hlinfo->mouse_face_window = Qnil; | ||
| 690 | hlinfo->mouse_face_hidden = 0; | ||
| 691 | |||
| 603 | /* Initialize interrupt_handle. */ | 692 | /* Initialize interrupt_handle. */ |
| 604 | init_crit (); | 693 | init_crit (); |
| 605 | 694 | ||
diff --git a/src/w32inevt.c b/src/w32inevt.c index e7a8bf629d6..a85fdbbe435 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c | |||
| @@ -35,8 +35,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 35 | #include "keyboard.h" | 35 | #include "keyboard.h" |
| 36 | #include "frame.h" | 36 | #include "frame.h" |
| 37 | #include "dispextern.h" | 37 | #include "dispextern.h" |
| 38 | #include "window.h" | ||
| 38 | #include "blockinput.h" | 39 | #include "blockinput.h" |
| 39 | #include "termhooks.h" | 40 | #include "termhooks.h" |
| 41 | #include "termchar.h" | ||
| 40 | #include "w32heap.h" | 42 | #include "w32heap.h" |
| 41 | #include "w32term.h" | 43 | #include "w32term.h" |
| 42 | 44 | ||
| @@ -566,7 +568,7 @@ w32_console_mouse_position (FRAME_PTR *f, | |||
| 566 | static void | 568 | static void |
| 567 | mouse_moved_to (int x, int y) | 569 | mouse_moved_to (int x, int y) |
| 568 | { | 570 | { |
| 569 | /* If we're in the same place, ignore it */ | 571 | /* If we're in the same place, ignore it. */ |
| 570 | if (x != movement_pos.X || y != movement_pos.Y) | 572 | if (x != movement_pos.X || y != movement_pos.Y) |
| 571 | { | 573 | { |
| 572 | SELECTED_FRAME ()->mouse_moved = 1; | 574 | SELECTED_FRAME ()->mouse_moved = 1; |
| @@ -599,14 +601,63 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, | |||
| 599 | struct input_event *emacs_ev) | 601 | struct input_event *emacs_ev) |
| 600 | { | 602 | { |
| 601 | static DWORD button_state = 0; | 603 | static DWORD button_state = 0; |
| 604 | static Lisp_Object last_mouse_window; | ||
| 602 | DWORD but_change, mask; | 605 | DWORD but_change, mask; |
| 603 | int i; | 606 | int i; |
| 604 | 607 | ||
| 605 | if (event->dwEventFlags == MOUSE_MOVED) | 608 | if (event->dwEventFlags == MOUSE_MOVED) |
| 606 | { | 609 | { |
| 607 | /* For movement events we just note that the mouse has moved | 610 | FRAME_PTR f = SELECTED_FRAME (); |
| 608 | so that emacs will generate drag events. */ | 611 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 609 | mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y); | 612 | int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y; |
| 613 | |||
| 614 | mouse_moved_to (mx, my); | ||
| 615 | |||
| 616 | if (f->mouse_moved) | ||
| 617 | { | ||
| 618 | if (hlinfo->mouse_face_hidden) | ||
| 619 | { | ||
| 620 | hlinfo->mouse_face_hidden = 0; | ||
| 621 | clear_mouse_face (hlinfo); | ||
| 622 | } | ||
| 623 | |||
| 624 | /* Generate SELECT_WINDOW_EVENTs when needed. */ | ||
| 625 | if (!NILP (Vmouse_autoselect_window)) | ||
| 626 | { | ||
| 627 | Lisp_Object mouse_window = window_from_coordinates (f, mx, my, | ||
| 628 | 0, 0); | ||
| 629 | /* A window will be selected only when it is not | ||
| 630 | selected now, and the last mouse movement event was | ||
| 631 | not in it. A minibuffer window will be selected iff | ||
| 632 | it is active. */ | ||
| 633 | if (WINDOWP (mouse_window) | ||
| 634 | && !EQ (mouse_window, last_mouse_window) | ||
| 635 | && !EQ (mouse_window, selected_window)) | ||
| 636 | { | ||
| 637 | struct input_event event; | ||
| 638 | |||
| 639 | EVENT_INIT (event); | ||
| 640 | event.kind = SELECT_WINDOW_EVENT; | ||
| 641 | event.frame_or_window = mouse_window; | ||
| 642 | event.arg = Qnil; | ||
| 643 | event.timestamp = movement_time; | ||
| 644 | kbd_buffer_store_event (&event); | ||
| 645 | } | ||
| 646 | last_mouse_window = mouse_window; | ||
| 647 | } | ||
| 648 | else | ||
| 649 | last_mouse_window = Qnil; | ||
| 650 | |||
| 651 | previous_help_echo_string = help_echo_string; | ||
| 652 | help_echo_string = help_echo_object = help_echo_window = Qnil; | ||
| 653 | help_echo_pos = -1; | ||
| 654 | note_mouse_highlight (f, mx, my); | ||
| 655 | /* If the contents of the global variable help_echo has | ||
| 656 | changed (inside note_mouse_highlight), generate a HELP_EVENT. */ | ||
| 657 | if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) | ||
| 658 | gen_help_event (help_echo_string, selected_frame, help_echo_window, | ||
| 659 | help_echo_object, help_echo_pos); | ||
| 660 | } | ||
| 610 | return 0; | 661 | return 0; |
| 611 | } | 662 | } |
| 612 | 663 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index 0a25eab1cbc..794355af153 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -25832,7 +25832,7 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, | |||
| 25832 | return; | 25832 | return; |
| 25833 | } | 25833 | } |
| 25834 | #endif | 25834 | #endif |
| 25835 | #if defined (HAVE_GPM) || defined (MSDOS) | 25835 | #if defined (HAVE_GPM) || defined (MSDOS) || defined (WINDOWSNT) |
| 25836 | tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw); | 25836 | tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw); |
| 25837 | #endif | 25837 | #endif |
| 25838 | } | 25838 | } |