From: David Ponce <david.ponce@wanadoo.fr>
Cc: emacs-devel@gnu.org
Subject: Re: Subject: w32 mouse wheel handling
Date: Fri, 30 May 2003 14:14:51 +0200 [thread overview]
Message-ID: <3ED74B3B.5090900@wanadoo.fr> (raw)
In-Reply-To: <E19LY6G-0007Xn-8g@fencepost.gnu.org>
Hi,
> Like with mouse buttons, it will be possible to handle several wheels:
> wheel-up-1 and wheel-down-1 events are associated to the first wheel,
> wheel-up-2 and wheel-down-2 to the second wheel, etc..
>
> I'd rather not add this complexity unless someone would actually want
> it. Emacs is already very complex; we should avoid adding any
> complexity that isn't really needed.
OK, here is a new patch that introduce only the wheel-up and
wheel-down events.
I updated w32term.c to generate Emacs WHEEL_EVENTs from w32
WM_MOUSEWHEEL events. I let MACOS and X gurus update macterm.c and
xterm.c ;-)
For now, to try the new code with mwheel, you need to customize
`mouse-wheel-down-event' and `mouse-wheel-up-event' to be respectively
wheel-up and wheel-down.
It appears there is a little inconsistency here, because mwheel seems
to assume that wheel events are scroll events. IMO it don't make
sense to generate a wheel-down event when the wheel is rotated up and
a wheel-up event when the wheel is rotated down.
Perhaps `mwheel-scroll' could be changed to handle wheel-up/down
events more consistently? That is scroll up on wheel-down and scroll
down on wheel-up.
Following is the change log and the patch.
Hope it will help.
Sincerely,
David
2003-05-30 David Ponce <david@dponce.com>
* termhooks.h (enum event_kind): Added new WHEEL_EVENT event.
Declare MOUSE_WHEEL_EVENT only if MAC_OSX defined.
* keyboard.c (Qmouse_wheel): Declare only if MAC_OSX defined.
(mouse_wheel_syms, lispy_mouse_wheel_names): Likewise.
(discard_mouse_events): Discard WHEEL_EVENT events too.
(lispy_wheel_names, wheel_syms): New.
(syms_of_keyboard): Init and staticpro `wheel_syms'. Init and
staticpro `Qmouse_wheel' and `mouse_wheel_syms' only if MAC_OSX
defined.
(make_lispy_event): Added WHEEL_EVENT handler.
* w32term.c (construct_mouse_wheel): Construct WHEEL_EVENT.
(w32_read_socket): Map w32 WM_MOUSEWHEEL events to Emacs
WHEEL_EVENT events.
Index: src/keyboard.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/keyboard.c,v
retrieving revision 1.747
diff -c -r1.747 keyboard.c
*** src/keyboard.c 26 May 2003 22:55:45 -0000 1.747
--- src/keyboard.c 30 May 2003 11:43:25 -0000
***************
*** 547,553 ****
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
! #if defined(WINDOWSNT) || defined(MAC_OSX)
Lisp_Object Qmouse_wheel;
#endif
#ifdef WINDOWSNT
--- 547,553 ----
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
! #if defined(MAC_OSX)
Lisp_Object Qmouse_wheel;
#endif
#ifdef WINDOWSNT
***************
*** 3737,3742 ****
--- 3737,3743 ----
sp = kbd_buffer;
if (sp->kind == MOUSE_CLICK_EVENT
+ || sp->kind == WHEEL_EVENT
#ifdef WINDOWSNT
|| sp->kind == W32_SCROLL_BAR_CLICK_EVENT
#endif
***************
*** 4436,4442 ****
static Lisp_Object accent_key_syms;
static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
! #if defined(WINDOWSNT) || defined(MAC_OSX)
static Lisp_Object mouse_wheel_syms;
#endif
static Lisp_Object drag_n_drop_syms;
--- 4437,4444 ----
static Lisp_Object accent_key_syms;
static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
! static Lisp_Object wheel_syms;
! #if defined(MAC_OSX)
static Lisp_Object mouse_wheel_syms;
#endif
static Lisp_Object drag_n_drop_syms;
***************
*** 4892,4898 ****
Lisp_Object Vlispy_mouse_stem;
! #if defined(WINDOWSNT) || defined(MAC_OSX)
/* mouse-wheel events are generated by the wheel on devices such as
the MS Intellimouse. The wheel sits in between the left and right
mouse buttons, and is typically used to scroll or zoom the window
--- 4894,4905 ----
Lisp_Object Vlispy_mouse_stem;
! static char *lispy_wheel_names[] =
! {
! "wheel-up", "wheel-down"
! };
!
! #if defined(MAC_OSX)
/* mouse-wheel events are generated by the wheel on devices such as
the MS Intellimouse. The wheel sits in between the left and right
mouse buttons, and is typically used to scroll or zoom the window
***************
*** 5416,5421 ****
--- 5423,5614 ----
}
}
+ case WHEEL_EVENT:
+ {
+ Lisp_Object position;
+ Lisp_Object window;
+ Lisp_Object head;
+
+ position = Qnil;
+
+ /* Build the position as appropriate for this mouse click. */
+ enum window_part part;
+ struct frame *f = XFRAME (event->frame_or_window);
+ Lisp_Object posn;
+ Lisp_Object string_info = Qnil;
+ int row, column;
+ int wx, wy;
+
+ /* Ignore wheel events that were made on frame that have been
+ deleted. */
+ if (! FRAME_LIVE_P (f))
+ return Qnil;
+
+ /* EVENT->x and EVENT->y are frame-relative pixel
+ coordinates at this place. Under old redisplay, COLUMN
+ and ROW are set to frame relative glyph coordinates
+ which are then used to determine whether this click is
+ in a menu (non-toolkit version). */
+ pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
+ &column, &row, NULL, 1);
+
+ /* Set `window' to the window under frame pixel coordinates
+ event->x/event->y. */
+ window = window_from_coordinates (f, XINT (event->x),
+ XINT (event->y),
+ &part, &wx, &wy, 0);
+
+ if (!WINDOWP (window))
+ {
+ window = event->frame_or_window;
+ posn = Qnil;
+ }
+ else
+ {
+ /* It's a click in window window at frame coordinates
+ event->x/ event->y. */
+ struct window *w = XWINDOW (window);
+
+ /* Set event coordinates to window-relative coordinates
+ for constructing the Lisp event below. */
+ XSETINT (event->x, wx);
+ XSETINT (event->y, wy);
+
+ if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
+ {
+ /* Mode line or header line. Look for a string under
+ the mouse that may have a `local-map' property. */
+ Lisp_Object string;
+ int charpos;
+
+ posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
+ string = mode_line_string (w, wx, wy, part, &charpos);
+ if (STRINGP (string))
+ string_info = Fcons (string, make_number (charpos));
+ }
+ else if (part == ON_VERTICAL_BORDER)
+ posn = Qvertical_line;
+ else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
+ {
+ int charpos;
+ Lisp_Object object = marginal_area_string (w, wx, wy, part,
+ &charpos);
+ posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
+ if (STRINGP (object))
+ string_info = Fcons (object, make_number (charpos));
+ }
+ else
+ {
+ Lisp_Object object;
+ struct display_pos p;
+ buffer_posn_from_coords (w, &wx, &wy, &object, &p);
+ posn = make_number (CHARPOS (p.pos));
+ if (STRINGP (object))
+ string_info
+ = Fcons (object,
+ make_number (CHARPOS (p.string_pos)));
+ }
+ }
+
+ position
+ = Fcons (window,
+ Fcons (posn,
+ Fcons (Fcons (event->x, event->y),
+ Fcons (make_number (event->timestamp),
+ (NILP (string_info)
+ ? Qnil
+ : Fcons (string_info, Qnil))))));
+
+ /* Set double or triple modifiers to indicate the wheel speed. */
+ {
+ /* On window-system frames, use the value of
+ double-click-fuzz as is. On other frames, interpret it
+ as a multiple of 1/8 characters. */
+ struct frame *f;
+ int fuzz;
+ int is_double;
+
+ if (WINDOWP (event->frame_or_window))
+ f = XFRAME (XWINDOW (event->frame_or_window)->frame);
+ else if (FRAMEP (event->frame_or_window))
+ f = XFRAME (event->frame_or_window);
+ else
+ abort ();
+
+ if (FRAME_WINDOW_P (f))
+ fuzz = double_click_fuzz;
+ else
+ fuzz = double_click_fuzz / 8;
+
+ is_double = (last_mouse_button < 0
+ && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
+ && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+ && button_down_time != 0
+ && (EQ (Vdouble_click_time, Qt)
+ || (INTEGERP (Vdouble_click_time)
+ && ((int)(event->timestamp - button_down_time)
+ < XINT (Vdouble_click_time)))));
+ if (is_double)
+ {
+ double_click_count++;
+ event->modifiers |= ((double_click_count > 2)
+ ? triple_modifier
+ : double_modifier);
+ }
+ else
+ {
+ double_click_count = 1;
+ event->modifiers |= click_modifier;
+ }
+
+ button_down_time = event->timestamp;
+ /* Use a negative value to distinguish wheel from mouse button. */
+ last_mouse_button = -1;
+ last_mouse_x = XINT (event->x);
+ last_mouse_y = XINT (event->y);
+ }
+
+ {
+ int symbol_num;
+
+ if (event->modifiers & up_modifier)
+ {
+ /* Emit a wheel-up event. */
+ event->modifiers &= ~up_modifier;
+ symbol_num = 0;
+ }
+ else if (event->modifiers & down_modifier)
+ {
+ /* Emit a wheel-down event. */
+ event->modifiers &= ~down_modifier;
+ symbol_num = 1;
+ }
+ else
+ /* Every wheel event should either have the down_modifier or
+ the up_modifier set. */
+ abort ();
+
+ /* Get the symbol we should use for the wheel event. */
+ head = modify_event_symbol (symbol_num,
+ event->modifiers,
+ Qmouse_click,
+ Qnil,
+ lispy_wheel_names,
+ &wheel_syms,
+ ASIZE (wheel_syms));
+ }
+
+ if (event->modifiers & (double_modifier | triple_modifier))
+ return Fcons (head,
+ Fcons (position,
+ Fcons (make_number (double_click_count),
+ Qnil)));
+ else
+ return Fcons (head,
+ Fcons (position,
+ Qnil));
+ }
+
#ifdef USE_TOOLKIT_SCROLL_BARS
/* We don't have down and up events if using toolkit scroll bars,
***************
*** 10675,10681 ****
staticpro (&Qfunction_key);
Qmouse_click = intern ("mouse-click");
staticpro (&Qmouse_click);
! #if defined(WINDOWSNT) || defined(MAC_OSX)
Qmouse_wheel = intern ("mouse-wheel");
staticpro (&Qmouse_wheel);
#endif
--- 10868,10874 ----
staticpro (&Qfunction_key);
Qmouse_click = intern ("mouse-click");
staticpro (&Qmouse_click);
! #if defined(MAC_OSX)
Qmouse_wheel = intern ("mouse-wheel");
staticpro (&Qmouse_wheel);
#endif
***************
*** 10793,10798 ****
--- 10986,10993 ----
staticpro (&button_down_location);
mouse_syms = Fmake_vector (make_number (1), Qnil);
staticpro (&mouse_syms);
+ wheel_syms = Fmake_vector (make_number (2), Qnil);
+ staticpro (&wheel_syms);
{
int i;
***************
*** 10827,10838 ****
func_key_syms = Qnil;
staticpro (&func_key_syms);
! #if defined(WINDOWSNT) || defined(MAC_OSX)
mouse_wheel_syms = Qnil;
staticpro (&mouse_wheel_syms);
drag_n_drop_syms = Qnil;
staticpro (&drag_n_drop_syms);
- #endif
unread_switch_frame = Qnil;
staticpro (&unread_switch_frame);
--- 11022,11033 ----
func_key_syms = Qnil;
staticpro (&func_key_syms);
! #if defined(MAC_OSX)
mouse_wheel_syms = Qnil;
staticpro (&mouse_wheel_syms);
+ #endif
drag_n_drop_syms = Qnil;
staticpro (&drag_n_drop_syms);
unread_switch_frame = Qnil;
staticpro (&unread_switch_frame);
Index: src/termhooks.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/termhooks.h,v
retrieving revision 1.62
diff -c -r1.62 termhooks.h
*** src/termhooks.h 4 Feb 2003 14:03:13 -0000 1.62
--- src/termhooks.h 30 May 2003 11:43:26 -0000
***************
*** 228,234 ****
which the key was typed.
.timestamp gives a timestamp (in
milliseconds) for the keystroke. */
! TIMER_EVENT, /* A timer fired. */
MOUSE_CLICK_EVENT, /* The button number is in .code; it must
be >= 0 and < NUM_MOUSE_BUTTONS, defined
below.
--- 228,234 ----
which the key was typed.
.timestamp gives a timestamp (in
milliseconds) for the keystroke. */
! TIMER_EVENT, /* A timer fired. */
MOUSE_CLICK_EVENT, /* The button number is in .code; it must
be >= 0 and < NUM_MOUSE_BUTTONS, defined
below.
***************
*** 240,253 ****
the mouse click occurred in.
.timestamp gives a timestamp (in
milliseconds) for the click. */
! #if defined(WINDOWSNT) || defined(MAC_OSX)
! MOUSE_WHEEL_EVENT, /* A mouse-wheel event is generated
! on WINDOWSNT or MAC_OSX by a
! wheel on a mouse (e.g., MS Intellimouse).
! The event contains a delta that corresponds
! to the amount and direction that the wheel
! is rotated. This delta is typically
! used to implement a scroll or zoom.
.code gives the delta.
.modifiers holds the state of the
modifier keys.
--- 240,266 ----
the mouse click occurred in.
.timestamp gives a timestamp (in
milliseconds) for the click. */
! WHEEL_EVENT, /* A wheel event is generated by a
! wheel on a mouse (e.g., MS
! Intellimouse).
! .modifiers holds the rotate
! direction (up or down), and the
! state of the modifier keys.
! .x and .y give the mouse position,
! in characters, within the window.
! .frame_or_window gives the frame
! the wheel event occurred in.
! .timestamp gives a timestamp (in
! milliseconds) for the event. */
! #if defined(MAC_OSX)
! MOUSE_WHEEL_EVENT, /* A mouse-wheel event is generated on
! MAC_OSX by a wheel on a mouse
! (e.g., MS Intellimouse). The event
! contains a delta that corresponds
! to the amount and direction that
! the wheel is rotated. This delta
! is typically used to implement a
! scroll or zoom.
.code gives the delta.
.modifiers holds the state of the
modifier keys.
***************
*** 256,262 ****
.frame_or_window gives the frame
the wheel event occurred in.
.timestamp gives a timestamp (in
! milliseconds) for the wheel event. */
#endif
#ifdef WINDOWSNT
LANGUAGE_CHANGE_EVENT, /* A LANGUAGE_CHANGE_EVENT is generated
--- 269,276 ----
.frame_or_window gives the frame
the wheel event occurred in.
.timestamp gives a timestamp (in
! milliseconds) for the wheel
! event. */
#endif
#ifdef WINDOWSNT
LANGUAGE_CHANGE_EVENT, /* A LANGUAGE_CHANGE_EVENT is generated
***************
*** 308,315 ****
.timestamp gives a timestamp (in
milliseconds) for the click. */
USER_SIGNAL_EVENT, /* A user signal.
! code is a number identifying it,
! index into lispy_user_signals. */
/* Help events. Member `frame_or_window' of the input_event is the
frame on which the event occurred, and member `arg' contains
--- 322,329 ----
.timestamp gives a timestamp (in
milliseconds) for the click. */
USER_SIGNAL_EVENT, /* A user signal.
! code is a number identifying it,
! index into lispy_user_signals. */
/* Help events. Member `frame_or_window' of the input_event is the
frame on which the event occurred, and member `arg' contains
Index: src/w32term.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/w32term.c,v
retrieving revision 1.192
diff -c -r1.192 w32term.c
*** src/w32term.c 27 May 2003 22:34:58 -0000 1.192
--- src/w32term.c 30 May 2003 11:44:01 -0000
***************
*** 2916,2925 ****
struct frame *f;
{
POINT p;
! result->kind = MOUSE_CLICK_EVENT;
! result->code = (GET_WHEEL_DELTA_WPARAM (msg->msg.wParam) < 0) ? 4 : 3;
result->timestamp = msg->msg.time;
! result->modifiers = msg->dwModifiers;
p.x = LOWORD (msg->msg.lParam);
p.y = HIWORD (msg->msg.lParam);
ScreenToClient (msg->msg.hwnd, &p);
--- 2916,2936 ----
struct frame *f;
{
POINT p;
! int delta;
!
! result->kind = WHEEL_EVENT;
! result->code = 0;
result->timestamp = msg->msg.time;
!
! /* A WHEEL_DELTA positive value indicates that the wheel was rotated
! forward, away from the user (up); a negative value indicates that
! the wheel was rotated backward, toward the user (down). */
! delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
!
! /* The up and down modifiers indicate if the wheel was rotated up or
! down based on WHEEL_DELTA value. */
! result->modifiers = (msg->dwModifiers
! | ((delta < 0 ) ? down_modifier : up_modifier));
p.x = LOWORD (msg->msg.lParam);
p.y = HIWORD (msg->msg.lParam);
ScreenToClient (msg->msg.hwnd, &p);
***************
*** 4389,4403 ****
case WM_MOUSEWHEEL:
{
- /* Convert each Windows mouse wheel event in a couple of
- Emacs mouse click down/up events. Scrolling the wheel up
- is associated to mouse button 4 and scrolling the wheel
- down to the mouse button 5. */
- int button;
- int up;
-
- up = msg.dwModifiers & up_modifier;
-
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
--- 4400,4405 ----
***************
*** 4406,4475 ****
if (f)
{
- Lisp_Object window;
- POINT p;
- int x, y;
-
- p.x = LOWORD (msg.msg.lParam);
- p.y = HIWORD (msg.msg.lParam);
- ScreenToClient (msg.msg.hwnd, &p);
- x = XFASTINT (p.x);
- y = XFASTINT (p.y);
-
- window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
-
- /* Ignore mouse wheel events not in a window. */
- if (!WINDOWP(window))
- break;
-
if ((!dpyinfo->w32_focus_frame
|| f == dpyinfo->w32_focus_frame)
&& (numchars >= 1))
{
! if ( !up )
! {
! /* Emit an Emacs mouse down message. */
! msg.dwModifiers |= down_modifier;
! construct_mouse_wheel (bufp, &msg, f);
! bufp++;
! count++;
! numchars--;
!
! /* Push a simulated WM_MOUSEWHEEL up message. */
! msg.dwModifiers &= ~down_modifier;
! msg.dwModifiers |= up_modifier;
! prepend_msg (&msg);
! }
! else
! {
! /* Emit an Emacs mouse up message. */
! construct_mouse_wheel (bufp, &msg, f);
! bufp++;
! count++;
! numchars--;
! }
}
}
!
! button = (GET_WHEEL_DELTA_WPARAM (msg.msg.wParam) < 0)? 4 : 3;
!
! if (up)
! {
! dpyinfo->grabbed &= ~ (1 << button);
! }
! else
! {
! dpyinfo->grabbed |= (1 << button);
! last_mouse_frame = f;
! /* Ignore any mouse motion that happened
! before this event; any subsequent mouse-movement
! Emacs events should reflect only motion after
! the ButtonPress. */
! if (f != 0)
! f->mouse_moved = 0;
!
! last_tool_bar_item = -1;
! }
}
break;
--- 4408,4431 ----
if (f)
{
if ((!dpyinfo->w32_focus_frame
|| f == dpyinfo->w32_focus_frame)
&& (numchars >= 1))
{
! /* Emit an Emacs wheel-up/down event. */
! construct_mouse_wheel (bufp, &msg, f);
! bufp++;
! count++;
! numchars--;
}
+ /* Ignore any mouse motion that happened before this
+ event; any subsequent mouse-movement Emacs events
+ should reflect only motion after the
+ ButtonPress. */
+ f->mouse_moved = 0;
}
! last_mouse_frame = f;
! last_tool_bar_item = -1;
}
break;
next prev parent reply other threads:[~2003-05-30 12:14 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-05-23 14:47 Subject: w32 mouse wheel handling David PONCE
2003-05-25 4:17 ` Michael Welsh Duggan
2003-05-25 8:34 ` David Ponce
2003-05-25 15:19 ` Stefan Monnier
2003-05-25 23:22 ` Kim F. Storm
2003-05-26 5:09 ` Kai Großjohann
2003-05-27 12:44 ` Richard Stallman
2003-05-28 22:18 ` David Ponce
2003-05-29 7:33 ` Jason Rumney
2003-05-30 0:50 ` Richard Stallman
2003-05-30 12:14 ` David Ponce [this message]
2003-05-26 13:30 ` Jason Rumney
2003-05-27 7:21 ` Jason Rumney
-- strict thread matches above, loose matches on Subject: below --
2003-05-27 8:12 David PONCE
2003-05-27 8:29 ` Juanma Barranquero
2003-05-27 8:45 ` Jason Rumney
2003-05-27 8:49 ` Juanma Barranquero
2003-05-27 22:41 ` Richard Stallman
2003-05-28 7:50 ` Oliver Scholz
2003-05-27 14:28 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3ED74B3B.5090900@wanadoo.fr \
--to=david.ponce@wanadoo.fr \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.