From owner-ntemacs-users@cs.washington.edu Wed Jun 4 19:34:55 1997 X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] [nil "" " 4" "June" "1997" "22:03:53" "-0400" "Michael Welsh Duggan" "md5i@schenley.com" nil "365" "Re: Microsoft IntelliMouse wheel support" "^From:" nil nil "6" nil nil nil nil] nil) Received: from joker.cs.washington.edu (joker.cs.washington.edu [128.95.1.42]) by june.cs.washington.edu (8.8.5+CS/7.2ju) with SMTP id TAA04460 for ; Wed, 4 Jun 1997 19:34:55 -0700 Received: from trout.cs.washington.edu (trout.cs.washington.edu [128.95.1.178]) by joker.cs.washington.edu (8.6.12/7.2ws+) with ESMTP id TAA42869 for ; Wed, 4 Jun 1997 19:34:53 -0700 Received: (majordom@localhost) by trout.cs.washington.edu (8.8.5+CS/7.2ws+) id TAA28481 for ntemacs-users-outgoing; Wed, 4 Jun 1997 19:04:06 -0700 (PDT) Received: from june.cs.washington.edu (june.cs.washington.edu [128.95.1.4]) by trout.cs.washington.edu (8.8.5+CS/7.2ws+) with ESMTP id TAA28477 for ; Wed, 4 Jun 1997 19:04:02 -0700 (PDT) Received: from gate.usaor.net (gate.usaor.net [204.157.146.1]) by june.cs.washington.edu (8.8.5+CS/7.2ju) with ESMTP id TAA03104 for ; Wed, 4 Jun 1997 19:04:01 -0700 Received: from maru.schenley.com (maru.schenley.com [206.62.188.70]) by gate.usaor.net (8.8.5/8.8.5) with SMTP id WAA18335 for ; Wed, 4 Jun 1997 22:03:56 -0400 (EDT) Received: by maru.schenley.com from localhost (router,SLMAILNT V2.2); Wed, 04 Jun 1997 22:03:55 EDT Received: by maru.schenley.com from maru.schenley.com (127.0.0.1::mail daemon; unverified,SLMAILNT V2.2); Wed, 04 Jun 1997 22:03:54 EDT References: In-Reply-To: "Michael Welsh Duggan"'s message of 03 Jun 1997 13:59:24 -0400 Message-ID: Lines: 365 X-Mailer: Gnus v5.4.33/Emacs 19.34 Precedence: bulk From: "Michael Welsh Duggan" Sender: owner-ntemacs-users@cs.washington.edu To: ntemacs-users@cs.washington.edu Subject: Re: Microsoft IntelliMouse wheel support Date: 04 Jun 1997 22:03:53 -0400 Chris Szurgot writes: > On Mon, 2 Jun 1997, Robert Brodersen wrote: > > > I just got a new IntelliMouse, and I must say I love using the mouse > > wheel to scroll my windows around! Unfortunately, Emacs doesn't pay > > attention to this cool new feature. Does anybody know if there is a > > patch version which supports the wheel? If not, it would be great if it > > would show up in one of the upcoming releases! > > > > Glad I'm not the only one who likes the Wheel. ;-) I have a hard time > living without one (I've one at home, but haven't yet convinced my boss of > the necessity. ;-) ) I did manage to hack Emacs enough to recognize the > wheel (on NT), but can't seem to wrap my skull around the obtuse event > handling code. It'll probably happen once a GOOD programmer gets a hold of > one. Well, I couldn't pass up the challenge. (Does this make me a GOOD programmer? :-]) I borrowed my collegue's machine and wheelie-mouse and whipped this up. Here follows a patch which implements mousewheel support. Now mousewheel events create an event like the following: (EVENT-TYPE (WINDOW BUFFER-POS (X . Y) TIMESTAMP) DELTA) The form is the same as Click Events, with the following exceptions: EVENT-TYPE is the symbol mouse-wheel with any number of modifiers (e.g: M-S-mouse-wheel). BUFFER-POS will never be a scroll bar. (Sorry.) DELTA is the zDelta value returned by a WM_MOUSEWHEEL event. In general, this means a -120 for forward and 120 for backward. Microsoft claims that multiples of 120 are also possible for very fast wheelers. Microsoft also claims that future wheels might have a higher reolution than 120, so code appropriately (try adding up the deltas till some value has been crossed). Example events: (mouse-wheel (# 1 (192 . 195) -14397175) 120) (mouse-wheel (# mode-line (288 . 255) -14394722) 120) (mouse-wheel (# nil (650 . 353) -14392238) 120) (C-M-mouse-wheel (# mode-line (64 . 255) -13294644) -120) (C-M-S-mouse-wheel (# mode-line (64 . 255) -13291394) -120) Here is some very naive sample code for scrolling windows: (defun mouse-wheel-handler (event) (interactive "e") (condition-case nil (if (< (car (cdr (cdr event))) 0) (scroll-up 3) (scroll-down 3)) (error nil))) (global-set-key [mouse-wheel] 'mouse-wheel-handler) Clicking the mouse wheel is (obviously) a mouse-2 event. This code has _not_ been thoroughly tested. These patches are relative to the 19.34.2 source. *** old\ChangeLog Wed Jun 04 21:09:26 1997 --- ChangeLog Wed Jun 04 21:11:51 1997 *************** *** 1,3 **** --- 1,25 ---- + Wed Jun 04 20:42:37 1997 Michael Welsh Duggan + + * w32term.h (WM_MOUSEWHEEL): Define if not already defined. + Necessary for pre VC5.0 distribution. + + * w32term.c (construct_mouse_wheel): New function. Constructs an + input event from a WM_MOUSEWHEEL message. + (w32_read_socket): Handle WM_MOUSEWHEEL. + + * w32fns.c (win32_wnd_proc): Capture and handle WM_MOUSEWHEEL + events. + + * termhooks.h (event_kind) [WINDOWSNT]: New event type: mouse_wheel. + + * keyboard.c (Qmouse_wheel) [WINDOWSNT]: New variable. + (eat_mouse_events) [WINDOWSNT]: Eat mouse-wheel events as well. + (mouse_wheel_syms) [WINDOWSNT]: New variable. + (lispy_mouse_wheel_names) [WINDOWSNT]: New variable. + (make_lispy_event) [WINDOWSNT]: Make mouse-wheel events. + (syms_of_keyboard) [WINDOWSNT]: Define Qmouse_wheel and + mouse_wheel_syms. + Wed Aug 21 03:51:42 1996 Richard Stallman * Version 19.34 released. *** old\w32term.h Wed Jun 04 21:09:51 1997 --- w32term.h Wed Jun 04 21:13:05 1997 *************** *** 577,582 **** --- 577,587 ---- extern XFontStruct *win32_load_font (); extern void win32_unload_font (); + /* Define for earlier versions of Visual C */ + #ifndef WM_MOUSEWHEEL + #define WM_MOUSEWHEEL (0x020A) + #endif /* WM_MOUSEWHEEL */ + #define WM_EMACS_START (WM_USER + 1) #define WM_EMACS_KILL (WM_EMACS_START + 0x00) #define WM_EMACS_CREATEWINDOW (WM_EMACS_START + 0x01) *** old\w32term.c Wed Jun 04 21:09:51 1997 --- w32term.c Wed Jun 04 21:15:24 1997 *************** *** 1294,1299 **** --- 1294,1318 ---- } } + static void + construct_mouse_wheel (result, msg, f) + struct input_event *result; + Win32Msg *msg; + struct frame *f; + { + POINT p; + result->kind = mouse_wheel; + result->code = (short) HIWORD (msg->msg.wParam); + 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); + XSETINT (result->x, p.x); + XSETINT (result->y, p.y); + XSETFRAME (result->frame_or_window, f); + } + /* Function to report a mouse movement to the mainstream Emacs code. The input handler calls this. *************** *** 2723,2728 **** --- 2742,2769 ---- } } + break; + case WM_MOUSEWHEEL: + { + if (dpyinfo->grabbed && last_mouse_frame + && FRAME_LIVE_P (last_mouse_frame)) + f = last_mouse_frame; + else + f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + + if (f) + { + if ((!dpyinfo->win32_focus_frame + || f == dpyinfo->win32_focus_frame) + && (numchars >= 1)) + { + construct_mouse_wheel (bufp, &msg, f); + bufp++; + count++; + numchars--; + } + } + } break; case WM_VSCROLL: { *** old\w32fns.c Wed Jun 04 21:09:50 1997 --- w32fns.c Wed Jun 04 21:16:11 1997 *************** *** 3244,3249 **** --- 3244,3254 ---- return 0; + case WM_MOUSEWHEEL: + wmsg.dwModifiers = win32_get_modifiers (); + my_post_msg (&wmsg, hwnd, msg, wParam, lParam); + return 0; + case WM_TIMER: /* Flush out saved messages if necessary. */ if (wParam == mouse_button_timer) *** old\termhooks.h Wed Jun 04 21:09:45 1997 --- termhooks.h Wed Jun 04 21:17:17 1997 *************** *** 234,239 **** --- 234,250 ---- the mouse click occurred in. .timestamp gives a timestamp (in milliseconds) for the click. */ + #ifdef WINDOWSNT + mouse_wheel, /* .code gives the delta. + .modifiers holds 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 wheel event. */ + #endif scroll_bar_click, /* .code gives the number of the mouse button that was clicked. .modifiers holds the state of the modifier *************** *** 284,289 **** --- 295,301 ---- /* For an ascii_keystroke, this is the character. For a non_ascii_keystroke, this is the keysym code. For a mouse event, this is the button number. */ + /* In WindowsNT, for a mouse wheel event, this is the delta. */ int code; enum scroll_bar_part part; *** old\keyboard.c Wed Jun 04 21:09:36 1997 --- keyboard.c Wed Jun 04 21:59:52 1997 *************** *** 440,445 **** --- 440,448 ---- Lisp_Object Qfunction_key; Lisp_Object Qmouse_click; Lisp_Object Qtimer_event; + #ifdef WINDOWSNT + Lisp_Object Qmouse_wheel; + #endif /* Lisp_Object Qmouse_movement; - also an event header */ /* Properties of event headers. */ *************** *** 3189,3194 **** --- 3192,3200 ---- static Lisp_Object accent_key_syms; static Lisp_Object func_key_syms; static Lisp_Object mouse_syms; + #ifdef WINDOWSNT + static Lisp_Object mouse_wheel_syms; + #endif /* This is a list of keysym codes for special "accent" characters. It parallels lispy_accent_keys. */ *************** *** 3550,3555 **** --- 3556,3568 ---- "mouse-1", "mouse-2", "mouse-3", "mouse-4", "mouse-5" }; + #ifdef WINDOWSNT + static char *lispy_mouse_wheel_names[] = + { + "mouse-wheel" + }; + #endif /* WINDOWSNT */ + /* Scroll bar parts. */ Lisp_Object Qabove_handle, Qhandle, Qbelow_handle; Lisp_Object Qup, Qdown; *************** *** 3960,3965 **** --- 3973,4039 ---- Qnil)); } } + case mouse_wheel: + { + int part; + FRAME_PTR f = XFRAME (event->frame_or_window); + Lisp_Object window; + Lisp_Object posn; + int row, column; + + /* Ignore mouse events that were made on frame that + have been deleted. */ + if (! FRAME_LIVE_P (f)) + return Qnil; + pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), + &column, &row, NULL, 1); + window = window_from_coordinates (f, column, row, &part); + + if (!WINDOWP (window)) + { + window = event->frame_or_window; + posn = Qnil; + } + else + { + int pixcolumn, pixrow; + column -= XINT (XWINDOW (window)->left); + row -= XINT (XWINDOW (window)->top); + glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow); + XSETINT (event->x, pixcolumn); + XSETINT (event->y, pixrow); + + if (part == 1) + posn = Qmode_line; + else if (part == 2) + posn = Qvertical_line; + else + XSETINT (posn, + buffer_posn_from_coords (XWINDOW (window), + column, row)); + } + + { + Lisp_Object head, position; + + position + = Fcons (window, + Fcons (posn, + Fcons (Fcons (event->x, event->y), + Fcons (make_number (event->timestamp), + Qnil)))); + + head = modify_event_symbol (0, event->modifiers, + Qmouse_wheel, Qnil, + lispy_mouse_wheel_names, + &mouse_wheel_syms, 1); + return Fcons (head, + Fcons (position, + Fcons (make_number (event->code), + Qnil))); + + } + } #endif #endif /* HAVE_MOUSE */ *************** *** 7804,7809 **** --- 7878,7887 ---- staticpro (&Qmouse_click); Qtimer_event = intern ("timer-event"); staticpro (&Qtimer_event); + #ifdef WINDOWSNT + Qmouse_wheel = intern ("mouse-wheel"); + staticpro (&Qmouse_wheel); + #endif Qmenu_enable = intern ("menu-enable"); staticpro (&Qmenu_enable); *************** *** 7895,7900 **** --- 7973,7983 ---- mouse_syms = Qnil; staticpro (&mouse_syms); + + #ifdef WINDOWSNT + mouse_wheel_syms = Qnil; + staticpro (&mouse_wheel_syms); + #endif unread_switch_frame = Qnil; staticpro (&unread_switch_frame); -- Michael Duggan (md5i@schenley.com)