aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2013-10-15 21:38:26 +0300
committerEli Zaretskii2013-10-15 21:38:26 +0300
commit5d64d7704ec60bcc95084173336851c5822f8ca5 (patch)
tree2dd45920773382ec9028571dffe30660c52d30f2
parent454e2fb9b928cb5d0f09db4e4334570419eb56b3 (diff)
downloademacs-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/ChangeLog7
-rw-r--r--src/termhooks.h1
-rw-r--r--src/w32inevt.c212
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 @@
12013-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
12013-10-15 Paul Eggert <eggert@cs.ucla.edu> 82013-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
448static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] = 451static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
449{ 452{
450 0, 2, 1 453 0, 2, 1, 3, 4
451}; 454};
452 455
453static int 456static 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
555static void 585static void