added support for mouse wheel on win32.

This commit is contained in:
crs 2002-05-23 18:35:08 +00:00
parent 24f5b66cf3
commit e277e6e74a
3 changed files with 170 additions and 27 deletions

View File

@ -406,6 +406,14 @@ bool CMSWindowsPrimaryScreen::onPreTranslate(MSG* msg)
} }
return true; return true;
case SYNERGY_MSG_MOUSE_WHEEL:
// ignore if not at current mark
if (m_mark == m_markReceived) {
log((CLOG_ERR "event: button wheel delta=%d %d", msg->wParam, msg->lParam));
m_server->onMouseWheel(msg->wParam);
}
return true;
case SYNERGY_MSG_MOUSE_MOVE: case SYNERGY_MSG_MOUSE_MOVE:
// ignore if not at current mark // ignore if not at current mark
if (m_mark == m_markReceived) { if (m_mark == m_markReceived) {

View File

@ -1,6 +1,29 @@
#include "CSynergyHook.h" #include "CSynergyHook.h"
#include "CScreenMap.h" #include "CScreenMap.h"
#include <assert.h> #include <assert.h>
#include <zmouse.h>
//
// extra mouse wheel stuff
//
enum EWheelSupport {
kWheelNone,
kWheelOld,
kWheelWin2000,
kWheelModern
};
// declare extended mouse hook struct. useable on win2k
typedef struct tagMOUSEHOOKSTRUCTWin2000 {
MOUSEHOOKSTRUCT mhs;
DWORD mouseData;
} MOUSEHOOKSTRUCTWin2000;
#if !defined(SM_MOUSEWHEELPRESENT)
#define SM_MOUSEWHEELPRESENT 75
#endif
// //
// globals // globals
@ -12,10 +35,13 @@
static HINSTANCE g_hinstance = NULL; static HINSTANCE g_hinstance = NULL;
static DWORD g_process = NULL; static DWORD g_process = NULL;
static EWheelSupport g_wheelSupport = kWheelNone;
static UINT g_wmMouseWheel = 0;
static HWND g_hwnd = NULL; static HWND g_hwnd = NULL;
static HHOOK g_keyboard = NULL; static HHOOK g_keyboard = NULL;
static HHOOK g_mouse = NULL; static HHOOK g_mouse = NULL;
static HHOOK g_cbt = NULL; static HHOOK g_cbt = NULL;
static HHOOK g_getMessage = NULL;
static bool g_relay = false; static bool g_relay = false;
static SInt32 g_zoneSize = 0; static SInt32 g_zoneSize = 0;
static UInt32 g_zoneSides = 0; static UInt32 g_zoneSides = 0;
@ -24,6 +50,8 @@ static SInt32 g_hScreen = 0;
static HCURSOR g_cursor = NULL; static HCURSOR g_cursor = NULL;
static DWORD g_cursorThread = 0; static DWORD g_cursorThread = 0;
static int foo = 0;
#pragma data_seg() #pragma data_seg()
// //
@ -58,30 +86,32 @@ static LRESULT CALLBACK keyboardHook(int code, WPARAM wParam, LPARAM lParam)
{ {
if (code >= 0) { if (code >= 0) {
if (g_relay) { if (g_relay) {
if (code == HC_ACTION) {
// forward message to our window // forward message to our window
PostMessage(g_hwnd, SYNERGY_MSG_KEY, wParam, lParam); PostMessage(g_hwnd, SYNERGY_MSG_KEY, wParam, lParam);
/* XXX -- this doesn't seem to work/help with lost key events
// if the active window isn't our window then make it // if the active window isn't our window then make it
// active. // active.
const bool wrongFocus = (GetActiveWindow() != g_hwnd); const bool wrongFocus = (GetActiveWindow() != g_hwnd);
if (wrongFocus) { if (wrongFocus) {
SetForegroundWindow(g_hwnd); SetForegroundWindow(g_hwnd);
} }
*/
// let non-system keyboard messages through to our window. // let certain keys pass through
// this allows DefWindowProc() to do normal processing. switch (wParam) {
// for most keys that means do nothing. for toggle keys case VK_CAPITAL:
// it means updating the thread's toggle state. discard case VK_NUMLOCK:
// system messages (i.e. keys pressed when alt is down) to case VK_SCROLL:
// prevent unexpected or undesired processing. also // pass event
// discard messages if not destined for our window break;
if (wrongFocus || (lParam & 0x20000000lu) != 0) {
default:
// discard event
return 1; return 1;
} }
} }
} }
}
return CallNextHookEx(g_keyboard, code, wParam, lParam); return CallNextHookEx(g_keyboard, code, wParam, lParam);
} }
@ -100,6 +130,33 @@ static LRESULT CALLBACK mouseHook(int code, WPARAM wParam, LPARAM lParam)
PostMessage(g_hwnd, SYNERGY_MSG_MOUSE_BUTTON, wParam, 0); PostMessage(g_hwnd, SYNERGY_MSG_MOUSE_BUTTON, wParam, 0);
return 1; return 1;
case WM_MOUSEWHEEL: {
// win2k and other systems supporting WM_MOUSEWHEEL in
// the mouse hook are gratuitously different (and poorly
// documented).
switch (g_wheelSupport) {
case kWheelModern: {
const MOUSEHOOKSTRUCT* info =
(const MOUSEHOOKSTRUCT*)lParam;
PostMessage(g_hwnd, SYNERGY_MSG_MOUSE_WHEEL,
static_cast<short>(LOWORD(info->dwExtraInfo)), 0);
break;
}
case kWheelWin2000: {
const MOUSEHOOKSTRUCTWin2000* info =
(const MOUSEHOOKSTRUCTWin2000*)lParam;
PostMessage(g_hwnd, SYNERGY_MSG_MOUSE_WHEEL,
static_cast<short>(HIWORD(info->mouseData)), 0);
break;
}
default:
break;
}
return 1;
}
case WM_MOUSEMOVE: { case WM_MOUSEMOVE: {
const MOUSEHOOKSTRUCT* info = (const MOUSEHOOKSTRUCT*)lParam; const MOUSEHOOKSTRUCT* info = (const MOUSEHOOKSTRUCT*)lParam;
SInt32 x = (SInt32)info->pt.x; SInt32 x = (SInt32)info->pt.x;
@ -174,6 +231,66 @@ static LRESULT CALLBACK cbtHook(int code, WPARAM wParam, LPARAM lParam)
return CallNextHookEx(g_cbt, code, wParam, lParam); return CallNextHookEx(g_cbt, code, wParam, lParam);
} }
static LRESULT CALLBACK getMessageHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code >= 0) {
if (g_relay) {
MSG* msg = reinterpret_cast<MSG*>(lParam);
if (msg->message == g_wmMouseWheel) {
// post message to our window
PostMessage(g_hwnd, SYNERGY_MSG_MOUSE_WHEEL, msg->wParam, 0);
// zero out the delta in the message so it's (hopefully)
// ignored
msg->wParam = 0;
}
}
}
return CallNextHookEx(g_getMessage, code, wParam, lParam);
}
static EWheelSupport GetWheelSupport()
{
// get operating system
OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof(info);
if (!GetVersionEx(&info)) {
return kWheelNone;
}
// see if modern wheel is present
if (GetSystemMetrics(SM_MOUSEWHEELPRESENT)) {
// note if running on win2k
if (info.dwPlatformId == VER_PLATFORM_WIN32_NT &&
info.dwMajorVersion == 5 &&
info.dwMinorVersion == 0) {
return kWheelWin2000;
}
return kWheelModern;
}
// not modern. see if we've got old-style support.
UINT wheelSupportMsg = RegisterWindowMessage(MSH_WHEELSUPPORT);
HWND wheelSupportWindow = FindWindow(MSH_WHEELMODULE_CLASS,
MSH_WHEELMODULE_TITLE);
if (wheelSupportWindow != NULL && wheelSupportMsg != 0) {
if (SendMessage(wheelSupportWindow, wheelSupportMsg, 0, 0) != 0) {
g_wmMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
if (g_wmMouseWheel != 0) {
return kWheelOld;
}
}
}
// assume modern. we don't do anything special in this case
// except respond to WM_MOUSEWHEEL messages. GetSystemMetrics()
// can apparently return FALSE even if a mouse wheel is present
// though i'm not sure exactly when it does that (but WinME does
// for my logitech usb trackball).
return kWheelModern;
}
// //
// external functions // external functions
@ -206,6 +323,7 @@ int install(HWND hwnd)
assert(g_keyboard == NULL); assert(g_keyboard == NULL);
assert(g_mouse == NULL); assert(g_mouse == NULL);
assert(g_cbt == NULL); assert(g_cbt == NULL);
assert(g_wheelSupport != kWheelOld || g_getMessage == NULL);
// save window // save window
g_hwnd = hwnd; g_hwnd = hwnd;
@ -219,6 +337,9 @@ int install(HWND hwnd)
g_cursor = NULL; g_cursor = NULL;
g_cursorThread = 0; g_cursorThread = 0;
// check for mouse wheel support
g_wheelSupport = GetWheelSupport();
// install keyboard hook // install keyboard hook
g_keyboard = SetWindowsHookEx(WH_KEYBOARD, g_keyboard = SetWindowsHookEx(WH_KEYBOARD,
&keyboardHook, &keyboardHook,
@ -257,6 +378,15 @@ int install(HWND hwnd)
return 0; return 0;
} }
// install GetMessage hook
if (g_wheelSupport == kWheelOld) {
g_getMessage = SetWindowsHookEx(WH_GETMESSAGE,
&getMessageHook,
g_hinstance,
0);
// ignore failure; we just won't get mouse wheel messages
}
return 1; return 1;
} }
@ -270,9 +400,13 @@ int uninstall(void)
UnhookWindowsHookEx(g_keyboard); UnhookWindowsHookEx(g_keyboard);
UnhookWindowsHookEx(g_mouse); UnhookWindowsHookEx(g_mouse);
UnhookWindowsHookEx(g_cbt); UnhookWindowsHookEx(g_cbt);
if (g_getMessage != NULL) {
UnhookWindowsHookEx(g_getMessage);
}
g_keyboard = NULL; g_keyboard = NULL;
g_mouse = NULL; g_mouse = NULL;
g_cbt = NULL; g_cbt = NULL;
g_getMessage = NULL;
g_hwnd = NULL; g_hwnd = NULL;
// show the cursor // show the cursor

View File

@ -18,6 +18,7 @@
#define SYNERGY_MSG_KEY WM_APP + 0x0012 // vk code; key data #define SYNERGY_MSG_KEY WM_APP + 0x0012 // vk code; key data
#define SYNERGY_MSG_MOUSE_BUTTON WM_APP + 0x0013 // button msg; <unused> #define SYNERGY_MSG_MOUSE_BUTTON WM_APP + 0x0013 // button msg; <unused>
#define SYNERGY_MSG_MOUSE_MOVE WM_APP + 0x0014 // x; y #define SYNERGY_MSG_MOUSE_MOVE WM_APP + 0x0014 // x; y
#define SYNERGY_MSG_MOUSE_WHEEL WM_APP + 0x0015 // delta; <unused>
typedef int (*InstallFunc)(HWND); typedef int (*InstallFunc)(HWND);
typedef int (*UninstallFunc)(void); typedef int (*UninstallFunc)(void);