After searching around a bit I couldn't find any support for mouse wheels in the Win32 VNC viewer, so I decided to implement it myself.
My solution is a bit of a hack but it does work when connecting from a Win32 client to an X server. It is not compatible with the Win32 server. The attached patch translates wheel movements into buttons 4 and 5, this is compatible with the way most X applications seem to want the wheel to work. See http://koala.ilog.fr/colas/mouse-wheel-scroll/ for ways to persuade various applications to work with the wheel. -- Mike Crowe <[EMAIL PROTECTED]> diff -w -u -p --recursive -N vnc_winsrc/vncviewer/ClientConnection.cpp vnc_winsrc.mac/vncviewer/ClientConnection.cpp --- vnc_winsrc/vncviewer/ClientConnection.cpp Mon Mar 19 14:58:32 2001 +++ vnc_winsrc.mac/vncviewer/ClientConnection.cpp Sun Apr 21 17:57:52 2002 @@ -862,6 +862,8 @@ LRESULT CALLBACK ClientConnection::WndPr case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: case WM_MOUSEMOVE: { if (!_this->m_running) return 0; @@ -877,6 +879,9 @@ LRESULT CALLBACK ClientConnection::WndPr return 0; } + case WM_MOUSEWHEEL: + _this->ProcessWheelEvent(LOWORD(lParam), HIWORD(lParam), wParam); + break; case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: @@ -1263,6 +1268,42 @@ LRESULT CALLBACK ClientConnection::WndPr #pragma warning(default : 4101) +void +ClientConnection::ProcessWheelEvent(int x, int y, WPARAM wParam) +{ + static int wheel_value = 0; + int wheel_delta = GET_WHEEL_DELTA_WPARAM(wParam); + if (wheel_delta) + { + int standard_button_mask = BuildMouseButtonFlags(wParam); + + wheel_value += wheel_delta; + while (abs(wheel_value) >= WHEEL_DELTA) + { + int button_mask; + if (wheel_value > 0) + { + button_mask = standard_button_mask | rfbButton4Mask; + wheel_value -= WHEEL_DELTA; + } + else + { + button_mask = standard_button_mask | rfbButton5Mask; + wheel_value += WHEEL_DELTA; + } + + // Press the button + SendPointerEvent((x + m_hScrollPos) * m_opts.m_scale_den / +m_opts.m_scale_num, + (y + m_vScrollPos) * m_opts.m_scale_den / m_opts.m_scale_num, +button_mask); + + // And release it. + SendPointerEvent((x + m_hScrollPos) * m_opts.m_scale_den / +m_opts.m_scale_num, + (y + m_vScrollPos) * m_opts.m_scale_den / m_opts.m_scale_num, +standard_button_mask); + } + } +} + + // ProcessPointerEvent handles the delicate case of emulating 3 buttons // on a two button mouse, then passes events off to SubProcessPointerEvent. void @@ -1376,23 +1417,35 @@ ClientConnection::ProcessPointerEvent(in } } -// SubProcessPointerEvent takes windows positions and flags and converts -// them into VNC ones. - -inline void -ClientConnection::SubProcessPointerEvent(int x, int y, DWORD keyflags) +inline int +ClientConnection::BuildMouseButtonFlags(DWORD keyflags) const { int mask; - if (m_opts.m_SwapMouse) { - mask = ( ((keyflags & MK_LBUTTON) ? rfbButton1Mask : 0) | + if (m_opts.m_SwapMouse) + { + mask = (((keyflags & MK_LBUTTON) ? rfbButton2Mask : 0) | ((keyflags & MK_MBUTTON) ? rfbButton3Mask : 0) | - ((keyflags & MK_RBUTTON) ? rfbButton2Mask : 0) ); + ((keyflags & MK_RBUTTON) ? rfbButton1Mask : 0) | + ((keyflags & MK_XBUTTON1) ? rfbButton6Mask : 0) | + ((keyflags & MK_XBUTTON2) ? rfbButton7Mask : 0)); } else { mask = ( ((keyflags & MK_LBUTTON) ? rfbButton1Mask : 0) | ((keyflags & MK_MBUTTON) ? rfbButton2Mask : 0) | - ((keyflags & MK_RBUTTON) ? rfbButton3Mask : 0) ); + ((keyflags & MK_RBUTTON) ? rfbButton3Mask : 0) | + ((keyflags & MK_XBUTTON1) ? rfbButton6Mask : 0) | + ((keyflags & MK_XBUTTON2) ? rfbButton7Mask : 0)); } + return mask; +} + +// SubProcessPointerEvent takes windows positions and flags and converts +// them into VNC ones. + +inline void +ClientConnection::SubProcessPointerEvent(int x, int y, DWORD keyflags) +{ + int mask = BuildMouseButtonFlags(keyflags); try { SendPointerEvent((x + m_hScrollPos) * m_opts.m_scale_den / m_opts.m_scale_num, diff -w -u -p --recursive -N vnc_winsrc/vncviewer/ClientConnection.h vnc_winsrc.mac/vncviewer/ClientConnection.h --- vnc_winsrc/vncviewer/ClientConnection.h Mon Mar 19 14:58:32 2001 +++ vnc_winsrc.mac/vncviewer/ClientConnection.h Sun Apr 21 17:44:40 2002 @@ -91,6 +91,7 @@ private: void SubProcessPointerEvent(int x, int y, DWORD keyflags); void SendPointerEvent(int x, int y, int buttonMask); void ProcessKeyEvent(int virtkey, DWORD keyData); + void ProcessWheelEvent(int x, int y, WPARAM wparam); void SendKeyEvent(CARD32 key, bool down); void ReadScreenUpdate(); @@ -134,6 +135,8 @@ private: void ReadExact(char *buf, int bytes); void ReadString(char *buf, int length); void WriteExact(char *buf, int bytes); + + int BuildMouseButtonFlags(DWORD keyflags) const; // This is what controls the thread void * run_undetached(void* arg); diff -w -u -p --recursive -N vnc_winsrc/vncviewer/rfbproto.h vnc_winsrc.mac/vncviewer/rfbproto.h --- vnc_winsrc/vncviewer/rfbproto.h Mon Mar 19 14:58:36 2001 +++ vnc_winsrc.mac/vncviewer/rfbproto.h Sun Apr 21 17:12:00 2002 @@ -678,6 +678,10 @@ typedef struct { #define rfbButton1Mask 1 #define rfbButton2Mask 2 #define rfbButton3Mask 4 +#define rfbButton4Mask 8 +#define rfbButton5Mask 16 +#define rfbButton6Mask 32 +#define rfbButton7Mask 64 #define sz_rfbPointerEventMsg 6 diff -w -u -p --recursive -N vnc_winsrc/vncviewer/stdhdrs.h vnc_winsrc.mac/vncviewer/stdhdrs.h --- vnc_winsrc/vncviewer/stdhdrs.h Mon Mar 19 14:58:36 2001 +++ vnc_winsrc.mac/vncviewer/stdhdrs.h Sun Apr 21 17:55:06 2002 @@ -24,6 +24,7 @@ #define VC_EXTRALEAN +#define _WIN32_WINNT 0x0500 #include <winsock2.h> #include <stdio.h> #include <process.h> --------------------------------------------------------------------- To unsubscribe, mail [EMAIL PROTECTED] with the line: 'unsubscribe vnc-list' in the message BODY See also: http://www.uk.research.att.com/vnc/intouch.html ---------------------------------------------------------------------