diff options
| author | Eli Zaretskii | 2013-10-15 21:38:26 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2013-10-15 21:38:26 +0300 |
| commit | 5d64d7704ec60bcc95084173336851c5822f8ca5 (patch) | |
| tree | 2dd45920773382ec9028571dffe30660c52d30f2 | |
| parent | 454e2fb9b928cb5d0f09db4e4334570419eb56b3 (diff) | |
| download | emacs-5d64d7704ec60bcc95084173336851c5822f8ca5.tar.gz emacs-5d64d7704ec60bcc95084173336851c5822f8ca5.zip | |
Support mouse wheel on MS-Windows text-mode console.
src/w32inevt.c (do_mouse_event): Support mouse wheel and all the 5
standard mouse buttons.
src/termhooks.h (struct input_event): Remove incorrect commentary.
| -rw-r--r-- | src/ChangeLog | 7 | ||||
| -rw-r--r-- | src/termhooks.h | 1 | ||||
| -rw-r--r-- | src/w32inevt.c | 212 |
3 files changed, 128 insertions, 92 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b951c37a646..ece16c869c0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | 2013-10-15 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * w32inevt.c (do_mouse_event): Support mouse wheel and all the 5 | ||
| 4 | standard mouse buttons. | ||
| 5 | |||
| 6 | * termhooks.h (struct input_event): Remove incorrect commentary. | ||
| 7 | |||
| 1 | 2013-10-15 Paul Eggert <eggert@cs.ucla.edu> | 8 | 2013-10-15 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 9 | ||
| 3 | Disallow bool vector operations on mixed-length operands. | 10 | Disallow bool vector operations on mixed-length operands. |
diff --git a/src/termhooks.h b/src/termhooks.h index 52f30b4bf98..a3977f5336e 100644 --- a/src/termhooks.h +++ b/src/termhooks.h | |||
| @@ -243,7 +243,6 @@ struct input_event | |||
| 243 | For a mouse event, this is the button number. | 243 | For a mouse event, this is the button number. |
| 244 | For a HELP_EVENT, this is the position within the object | 244 | For a HELP_EVENT, this is the position within the object |
| 245 | (stored in ARG below) where the help was found. */ | 245 | (stored in ARG below) where the help was found. */ |
| 246 | /* In WindowsNT, for a mouse wheel event, this is the delta. */ | ||
| 247 | ptrdiff_t code; | 246 | ptrdiff_t code; |
| 248 | enum scroll_bar_part part; | 247 | enum scroll_bar_part part; |
| 249 | 248 | ||
diff --git a/src/w32inevt.c b/src/w32inevt.c index 3c41bec6bb5..c5d3fa3ad7d 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c | |||
| @@ -30,6 +30,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 30 | #ifndef MOUSE_MOVED | 30 | #ifndef MOUSE_MOVED |
| 31 | #define MOUSE_MOVED 1 | 31 | #define MOUSE_MOVED 1 |
| 32 | #endif | 32 | #endif |
| 33 | #ifndef MOUSE_HWHEELED | ||
| 34 | #define MOUSE_HWHEELED 8 | ||
| 35 | #endif | ||
| 33 | 36 | ||
| 34 | #include "lisp.h" | 37 | #include "lisp.h" |
| 35 | #include "keyboard.h" | 38 | #include "keyboard.h" |
| @@ -438,16 +441,16 @@ mouse_moved_to (int x, int y) | |||
| 438 | next - Leftmost+1 | 441 | next - Leftmost+1 |
| 439 | next - Leftmost+2... | 442 | next - Leftmost+2... |
| 440 | 443 | ||
| 441 | Assume emacs likes three button mice, so | 444 | For the 3 standard buttons, we have: |
| 442 | Left == 0 | 445 | Left == 0 |
| 443 | Middle == 1 | 446 | Middle == 1 |
| 444 | Right == 2 | 447 | Right == 2 |
| 445 | Others increase from there. */ | 448 | Others increase from there. */ |
| 446 | 449 | ||
| 447 | #define NUM_TRANSLATED_MOUSE_BUTTONS 3 | 450 | #define NUM_TRANSLATED_MOUSE_BUTTONS 5 |
| 448 | static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] = | 451 | static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] = |
| 449 | { | 452 | { |
| 450 | 0, 2, 1 | 453 | 0, 2, 1, 3, 4 |
| 451 | }; | 454 | }; |
| 452 | 455 | ||
| 453 | static int | 456 | static int |
| @@ -456,100 +459,127 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, | |||
| 456 | { | 459 | { |
| 457 | static DWORD button_state = 0; | 460 | static DWORD button_state = 0; |
| 458 | static Lisp_Object last_mouse_window; | 461 | static Lisp_Object last_mouse_window; |
| 459 | DWORD but_change, mask; | 462 | DWORD but_change, mask, flags = event->dwEventFlags; |
| 460 | int i; | 463 | int i; |
| 461 | 464 | ||
| 462 | if (event->dwEventFlags == MOUSE_MOVED) | 465 | switch (flags) |
| 463 | { | 466 | { |
| 464 | struct frame *f = SELECTED_FRAME (); | 467 | case MOUSE_MOVED: |
| 465 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); | ||
| 466 | int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y; | ||
| 467 | |||
| 468 | mouse_moved_to (mx, my); | ||
| 469 | |||
| 470 | if (f->mouse_moved) | ||
| 471 | { | ||
| 472 | if (hlinfo->mouse_face_hidden) | ||
| 473 | { | ||
| 474 | hlinfo->mouse_face_hidden = 0; | ||
| 475 | clear_mouse_face (hlinfo); | ||
| 476 | } | ||
| 477 | |||
| 478 | /* Generate SELECT_WINDOW_EVENTs when needed. */ | ||
| 479 | if (!NILP (Vmouse_autoselect_window)) | ||
| 480 | { | ||
| 481 | Lisp_Object mouse_window = window_from_coordinates (f, mx, my, | ||
| 482 | 0, 0); | ||
| 483 | /* A window will be selected only when it is not | ||
| 484 | selected now, and the last mouse movement event was | ||
| 485 | not in it. A minibuffer window will be selected iff | ||
| 486 | it is active. */ | ||
| 487 | if (WINDOWP (mouse_window) | ||
| 488 | && !EQ (mouse_window, last_mouse_window) | ||
| 489 | && !EQ (mouse_window, selected_window)) | ||
| 490 | { | ||
| 491 | struct input_event event; | ||
| 492 | |||
| 493 | EVENT_INIT (event); | ||
| 494 | event.kind = SELECT_WINDOW_EVENT; | ||
| 495 | event.frame_or_window = mouse_window; | ||
| 496 | event.arg = Qnil; | ||
| 497 | event.timestamp = movement_time; | ||
| 498 | kbd_buffer_store_event (&event); | ||
| 499 | } | ||
| 500 | last_mouse_window = mouse_window; | ||
| 501 | } | ||
| 502 | else | ||
| 503 | last_mouse_window = Qnil; | ||
| 504 | |||
| 505 | previous_help_echo_string = help_echo_string; | ||
| 506 | help_echo_string = help_echo_object = help_echo_window = Qnil; | ||
| 507 | help_echo_pos = -1; | ||
| 508 | note_mouse_highlight (f, mx, my); | ||
| 509 | /* If the contents of the global variable help_echo has | ||
| 510 | changed (inside note_mouse_highlight), generate a HELP_EVENT. */ | ||
| 511 | if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) | ||
| 512 | gen_help_event (help_echo_string, selected_frame, help_echo_window, | ||
| 513 | help_echo_object, help_echo_pos); | ||
| 514 | } | ||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | /* It looks like the console code sends us a mouse event with | ||
| 519 | dwButtonState == 0 when a window is activated. Ignore this case. */ | ||
| 520 | if (event->dwButtonState == button_state) | ||
| 521 | return 0; | ||
| 522 | |||
| 523 | emacs_ev->kind = MOUSE_CLICK_EVENT; | ||
| 524 | |||
| 525 | /* Find out what button has changed state since the last button event. */ | ||
| 526 | but_change = button_state ^ event->dwButtonState; | ||
| 527 | mask = 1; | ||
| 528 | for (i = 0; mask; i++, mask <<= 1) | ||
| 529 | if (but_change & mask) | ||
| 530 | { | 468 | { |
| 531 | if (i < NUM_TRANSLATED_MOUSE_BUTTONS) | 469 | struct frame *f = get_frame (); |
| 532 | emacs_ev->code = emacs_button_translation[i]; | 470 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 533 | else | 471 | int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y; |
| 534 | emacs_ev->code = i; | 472 | |
| 535 | break; | 473 | mouse_moved_to (mx, my); |
| 474 | |||
| 475 | if (f->mouse_moved) | ||
| 476 | { | ||
| 477 | if (hlinfo->mouse_face_hidden) | ||
| 478 | { | ||
| 479 | hlinfo->mouse_face_hidden = 0; | ||
| 480 | clear_mouse_face (hlinfo); | ||
| 481 | } | ||
| 482 | |||
| 483 | /* Generate SELECT_WINDOW_EVENTs when needed. */ | ||
| 484 | if (!NILP (Vmouse_autoselect_window)) | ||
| 485 | { | ||
| 486 | Lisp_Object mouse_window = window_from_coordinates (f, mx, my, | ||
| 487 | 0, 0); | ||
| 488 | /* A window will be selected only when it is not | ||
| 489 | selected now, and the last mouse movement event was | ||
| 490 | not in it. A minibuffer window will be selected iff | ||
| 491 | it is active. */ | ||
| 492 | if (WINDOWP (mouse_window) | ||
| 493 | && !EQ (mouse_window, last_mouse_window) | ||
| 494 | && !EQ (mouse_window, selected_window)) | ||
| 495 | { | ||
| 496 | struct input_event event; | ||
| 497 | |||
| 498 | EVENT_INIT (event); | ||
| 499 | event.kind = SELECT_WINDOW_EVENT; | ||
| 500 | event.frame_or_window = mouse_window; | ||
| 501 | event.arg = Qnil; | ||
| 502 | event.timestamp = movement_time; | ||
| 503 | kbd_buffer_store_event (&event); | ||
| 504 | } | ||
| 505 | last_mouse_window = mouse_window; | ||
| 506 | } | ||
| 507 | else | ||
| 508 | last_mouse_window = Qnil; | ||
| 509 | |||
| 510 | previous_help_echo_string = help_echo_string; | ||
| 511 | help_echo_string = help_echo_object = help_echo_window = Qnil; | ||
| 512 | help_echo_pos = -1; | ||
| 513 | note_mouse_highlight (f, mx, my); | ||
| 514 | /* If the contents of the global variable help_echo has | ||
| 515 | changed (inside note_mouse_highlight), generate a HELP_EVENT. */ | ||
| 516 | if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) | ||
| 517 | gen_help_event (help_echo_string, selected_frame, | ||
| 518 | help_echo_window, help_echo_object, | ||
| 519 | help_echo_pos); | ||
| 520 | } | ||
| 521 | /* We alread called kbd_buffer_store_event, so indicate the | ||
| 522 | the caller it shouldn't. */ | ||
| 523 | return 0; | ||
| 536 | } | 524 | } |
| 525 | case MOUSE_WHEELED: | ||
| 526 | case MOUSE_HWHEELED: | ||
| 527 | { | ||
| 528 | struct frame *f = get_frame (); | ||
| 529 | int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y; | ||
| 530 | bool down_p = (event->dwButtonState & 0x10000000) != 0; | ||
| 531 | |||
| 532 | emacs_ev->kind = | ||
| 533 | flags == MOUSE_HWHEELED ? HORIZ_WHEEL_EVENT : WHEEL_EVENT; | ||
| 534 | emacs_ev->code = 0; | ||
| 535 | emacs_ev->modifiers = down_p ? down_modifier : up_modifier; | ||
| 536 | emacs_ev->modifiers |= | ||
| 537 | w32_kbd_mods_to_emacs (event->dwControlKeyState, 0); | ||
| 538 | XSETINT (emacs_ev->x, mx); | ||
| 539 | XSETINT (emacs_ev->y, my); | ||
| 540 | XSETFRAME (emacs_ev->frame_or_window, f); | ||
| 541 | emacs_ev->arg = Qnil; | ||
| 542 | emacs_ev->timestamp = GetTickCount (); | ||
| 543 | return 1; | ||
| 544 | } | ||
| 545 | case DOUBLE_CLICK: | ||
| 546 | default: /* mouse pressed or released */ | ||
| 547 | /* It looks like the console code sends us a button-release | ||
| 548 | mouse event with dwButtonState == 0 when a window is | ||
| 549 | activated and when the mouse is first clicked. Ignore this | ||
| 550 | case. */ | ||
| 551 | if (event->dwButtonState == button_state) | ||
| 552 | return 0; | ||
| 537 | 553 | ||
| 538 | button_state = event->dwButtonState; | 554 | emacs_ev->kind = MOUSE_CLICK_EVENT; |
| 539 | emacs_ev->timestamp = GetTickCount (); | 555 | |
| 540 | emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) | | 556 | /* Find out what button has changed state since the last button |
| 541 | ((event->dwButtonState & mask) ? down_modifier : up_modifier); | 557 | event. */ |
| 542 | 558 | but_change = button_state ^ event->dwButtonState; | |
| 543 | XSETFASTINT (emacs_ev->x, event->dwMousePosition.X); | 559 | mask = 1; |
| 544 | XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y); | 560 | for (i = 0; mask; i++, mask <<= 1) |
| 545 | /* for Mule 2.2 (Based on Emacs 19.28 */ | 561 | if (but_change & mask) |
| 546 | #ifdef MULE | 562 | { |
| 547 | XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ()); | 563 | if (i < NUM_TRANSLATED_MOUSE_BUTTONS) |
| 548 | #else | 564 | emacs_ev->code = emacs_button_translation[i]; |
| 549 | XSETFRAME (emacs_ev->frame_or_window, get_frame ()); | 565 | else |
| 550 | #endif | 566 | emacs_ev->code = i; |
| 551 | 567 | break; | |
| 552 | return 1; | 568 | } |
| 569 | |||
| 570 | button_state = event->dwButtonState; | ||
| 571 | emacs_ev->modifiers = | ||
| 572 | w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) | ||
| 573 | | ((event->dwButtonState & mask) ? down_modifier : up_modifier); | ||
| 574 | |||
| 575 | XSETFASTINT (emacs_ev->x, event->dwMousePosition.X); | ||
| 576 | XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y); | ||
| 577 | XSETFRAME (emacs_ev->frame_or_window, get_frame ()); | ||
| 578 | emacs_ev->arg = Qnil; | ||
| 579 | emacs_ev->timestamp = GetTickCount (); | ||
| 580 | |||
| 581 | return 1; | ||
| 582 | } | ||
| 553 | } | 583 | } |
| 554 | 584 | ||
| 555 | static void | 585 | static void |