Added support for 4th and 5th (non-mouse-wheel) buttons and

"Internet" keyboard keys.
This commit is contained in:
crs 2003-05-04 21:40:42 +00:00
parent b840c61f6c
commit 0e58bab76c
10 changed files with 401 additions and 132 deletions

View File

@ -57,6 +57,7 @@ AC_PATH_XTRA
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$X_CFLAGS $CPPFLAGS"
AC_CHECK_HEADERS([X11/extensions/XTest.h])
AC_CHECK_HEADERS([X11/XF86keysym.h])
AC_CHECK_LIB(Xinerama, XineramaQueryExtension, AC_CHECK_HEADERS([X11/extensions/Xinerama.h]) [X_LIBS="$X_LIBS -lXinerama"], , [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
CPPFLAGS="$save_CPPFLAGS"

View File

@ -21,16 +21,38 @@
#include "CArchMiscWindows.h"
#include <cstring>
// X button stuff
#if !defined(WM_XBUTTONDOWN)
#define WM_XBUTTONDOWN 0x020B
#define WM_XBUTTONUP 0x020C
#define WM_XBUTTONDBLCLK 0x020D
#define WM_NCXBUTTONDOWN 0x00AB
#define WM_NCXBUTTONUP 0x00AC
#define WM_NCXBUTTONDBLCLK 0x00AD
#define MOUSEEVENTF_XDOWN 0x0100
#define MOUSEEVENTF_XUP 0x0200
#define XBUTTON1 0x0001
#define XBUTTON2 0x0002
#endif
//
// map virtual key id to a name
//
static const char* g_buttonToName[] = {
"button 0",
"Left Button",
"Middle Button",
"Right Button",
"X Button 1",
"X Button 2"
};
static const char* g_vkToName[] = {
"vk 0x00",
"VK_LBUTTON",
"VK_RBUTTON",
"Left Button",
"Right Button",
"VK_CANCEL",
"VK_MBUTTON",
"Middle Button",
"vk 0x05",
"vk 0x06",
"vk 0x07",
@ -192,24 +214,24 @@ static const char* g_vkToName[] = {
"VK_RCONTROL",
"VK_LMENU",
"VK_RMENU",
"vk 0xa6",
"vk 0xa7",
"vk 0xa8",
"vk 0xa9",
"vk 0xaa",
"vk 0xab",
"vk 0xac",
"vk 0xad",
"vk 0xae",
"vk 0xaf",
"vk 0xb0",
"vk 0xb1",
"vk 0xb2",
"vk 0xb3",
"vk 0xb4",
"vk 0xb5",
"vk 0xb6",
"vk 0xb7",
"VK_BROWSER_BACK",
"VK_BROWSER_FORWARD",
"VK_BROWSER_REFRESH",
"VK_BROWSER_STOP",
"VK_BROWSER_SEARCH",
"VK_BROWSER_FAVORITES",
"VK_BROWSER_HOME",
"VK_VOLUME_MUTE",
"VK_VOLUME_DOWN",
"VK_VOLUME_UP",
"VK_MEDIA_NEXT_TRACK",
"VK_MEDIA_PREV_TRACK",
"VK_MEDIA_STOP",
"VK_MEDIA_PLAY_PAUSE",
"VK_LAUNCH_MAIL",
"VK_LAUNCH_MEDIA_SELECT",
"VK_LAUNCH_APP1",
"VK_LAUNCH_APP2",
"vk 0xb8",
"vk 0xb9",
"vk 0xba",
@ -384,24 +406,14 @@ KeyModifierMask
CMSWindowsPrimaryScreen::getToggleMask() const
{
KeyModifierMask mask = 0;
if (!m_lowLevel) {
// get key state from our shadow state
if ((m_keys[VK_CAPITAL] & 0x01) != 0)
mask |= KeyModifierCapsLock;
if ((m_keys[VK_NUMLOCK] & 0x01) != 0)
mask |= KeyModifierNumLock;
if ((m_keys[VK_SCROLL] & 0x01) != 0)
mask |= KeyModifierScrollLock;
}
else {
// get key state from the system when using low level hooks
if ((GetKeyState(VK_CAPITAL) & 0x01) != 0)
mask |= KeyModifierCapsLock;
if ((GetKeyState(VK_NUMLOCK) & 0x01) != 0)
mask |= KeyModifierNumLock;
if ((GetKeyState(VK_SCROLL) & 0x01) != 0)
mask |= KeyModifierScrollLock;
}
// get key state from our shadow state
if ((m_keys[VK_CAPITAL] & 0x01) != 0)
mask |= KeyModifierCapsLock;
if ((m_keys[VK_NUMLOCK] & 0x01) != 0)
mask |= KeyModifierNumLock;
if ((m_keys[VK_SCROLL] & 0x01) != 0)
mask |= KeyModifierScrollLock;
return mask;
}
@ -409,44 +421,17 @@ CMSWindowsPrimaryScreen::getToggleMask() const
bool
CMSWindowsPrimaryScreen::isLockedToScreen() const
{
// virtual key table. the table defines the virtual keys that are
// mapped to something (including mouse buttons, OEM and kanji keys
// but not unassigned or undefined keys).
static const UInt32 s_mappedKeys[] = {
0xfbff331e,
0x03ffffff,
0x3ffffffe,
0xffffffff,
0x000300ff,
0xfc000000,
0xf8000001,
0x7ffffe5f
};
// check each key. if we're capturing events at a low level we
// can query the keyboard state using GetKeyState(). if not we
// resort to using our shadow keyboard state since the system's
// shadow state won't be in sync (because our window is not
// getting keyboard events).
if (!m_lowLevel) {
// use shadow keyboard state in m_keys
for (UInt32 i = 0; i < 256; ++i) {
if ((m_keys[i] & 0x80) != 0) {
LOG((CLOG_DEBUG "locked by \"%s\"", g_vkToName[i]));
return true;
}
// use shadow keyboard state in m_keys and m_buttons
for (UInt32 i = 0; i < sizeof(m_buttons) / sizeof(m_buttons[0]); ++i) {
if ((m_buttons[i] & 0x80) != 0) {
LOG((CLOG_DEBUG "locked by \"%s\"", g_buttonToName[i]));
return true;
}
}
else {
for (UInt32 i = 0; i < 256 / 32; ++i) {
for (UInt32 b = 1, j = 0; j < 32; b <<= 1, ++j) {
if ((s_mappedKeys[i] & b) != 0) {
if (GetKeyState(i * 32 + j) < 0) {
LOG((CLOG_DEBUG "locked by \"%s\"", g_vkToName[i * 32 + j]));
return true;
}
}
}
for (UInt32 i = 0; i < sizeof(m_keys) / sizeof(m_keys[0]); ++i) {
if ((m_keys[i] & 0x80) != 0) {
LOG((CLOG_DEBUG "locked by \"%s\"", g_vkToName[i]));
return true;
}
}
@ -583,16 +568,9 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
return true;
case SYNERGY_MSG_MOUSE_BUTTON: {
static const int s_vkButton[] = {
0, // kButtonNone
VK_LBUTTON, // kButtonLeft, etc.
VK_MBUTTON,
VK_RBUTTON
};
// get which button
bool pressed = false;
const ButtonID button = mapButton(msg->wParam);
const ButtonID button = mapButton(msg->wParam, msg->lParam);
// ignore message if posted prior to last mark change
if (!ignore()) {
@ -600,19 +578,22 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_XBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_XBUTTONDBLCLK:
case WM_NCLBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_NCRBUTTONDOWN:
case WM_NCXBUTTONDOWN:
case WM_NCLBUTTONDBLCLK:
case WM_NCMBUTTONDBLCLK:
case WM_NCRBUTTONDBLCLK:
case WM_NCXBUTTONDBLCLK:
LOG((CLOG_DEBUG1 "event: button press button=%d", button));
if (button != kButtonNone) {
m_receiver->onMouseDown(button);
m_keys[s_vkButton[button]] |= 0x80;
}
pressed = true;
break;
@ -620,13 +601,14 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_XBUTTONUP:
case WM_NCLBUTTONUP:
case WM_NCMBUTTONUP:
case WM_NCRBUTTONUP:
case WM_NCXBUTTONUP:
LOG((CLOG_DEBUG1 "event: button release button=%d", button));
if (button != kButtonNone) {
m_receiver->onMouseUp(button);
m_keys[s_vkButton[button]] &= ~0x80;
}
pressed = false;
break;
@ -634,8 +616,13 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
}
// keep our shadow key state up to date
if (button != kButtonNone) {
updateKey(s_vkButton[button], pressed);
if (button >= kButtonLeft && button <= kButtonExtra0 + 1) {
if (pressed) {
m_buttons[button] |= 0x80;
}
else {
m_buttons[button] &= ~0x80;
}
}
return true;
@ -1139,24 +1126,24 @@ static const KeyID g_virtualKey[][2] =
/* 0xa3 */ kKeyControl_R, kKeyControl_R, // VK_RCONTROL
/* 0xa4 */ kKeyAlt_L, kKeyAlt_L, // VK_LMENU
/* 0xa5 */ kKeyAlt_R, kKeyAlt_R, // VK_RMENU
/* 0xa6 */ kKeyNone, kKeyNone, // unassigned
/* 0xa7 */ kKeyNone, kKeyNone, // unassigned
/* 0xa8 */ kKeyNone, kKeyNone, // unassigned
/* 0xa9 */ kKeyNone, kKeyNone, // unassigned
/* 0xaa */ kKeyNone, kKeyNone, // unassigned
/* 0xab */ kKeyNone, kKeyNone, // unassigned
/* 0xac */ kKeyNone, kKeyNone, // unassigned
/* 0xad */ kKeyNone, kKeyNone, // unassigned
/* 0xae */ kKeyNone, kKeyNone, // unassigned
/* 0xaf */ kKeyNone, kKeyNone, // unassigned
/* 0xb0 */ kKeyNone, kKeyNone, // unassigned
/* 0xb1 */ kKeyNone, kKeyNone, // unassigned
/* 0xb2 */ kKeyNone, kKeyNone, // unassigned
/* 0xb3 */ kKeyNone, kKeyNone, // unassigned
/* 0xb4 */ kKeyNone, kKeyNone, // unassigned
/* 0xb5 */ kKeyNone, kKeyNone, // unassigned
/* 0xb6 */ kKeyNone, kKeyNone, // unassigned
/* 0xb7 */ kKeyNone, kKeyNone, // unassigned
/* 0xa6 */ kKeyNone, kKeyWWWBack, // VK_BROWSER_BACK
/* 0xa7 */ kKeyNone, kKeyWWWForward, // VK_BROWSER_FORWARD
/* 0xa8 */ kKeyNone, kKeyWWWRefresh, // VK_BROWSER_REFRESH
/* 0xa9 */ kKeyNone, kKeyWWWStop, // VK_BROWSER_STOP
/* 0xaa */ kKeyNone, kKeyWWWSearch, // VK_BROWSER_SEARCH
/* 0xab */ kKeyNone, kKeyWWWFavorites, // VK_BROWSER_FAVORITES
/* 0xac */ kKeyNone, kKeyWWWHome, // VK_BROWSER_HOME
/* 0xad */ kKeyNone, kKeyAudioMute, // VK_VOLUME_MUTE
/* 0xae */ kKeyNone, kKeyAudioDown, // VK_VOLUME_DOWN
/* 0xaf */ kKeyNone, kKeyAudioUp, // VK_VOLUME_UP
/* 0xb0 */ kKeyNone, kKeyAudioNext, // VK_MEDIA_NEXT_TRACK
/* 0xb1 */ kKeyNone, kKeyAudioPrev, // VK_MEDIA_PREV_TRACK
/* 0xb2 */ kKeyNone, kKeyAudioStop, // VK_MEDIA_STOP
/* 0xb3 */ kKeyNone, kKeyAudioPlay, // VK_MEDIA_PLAY_PAUSE
/* 0xb4 */ kKeyNone, kKeyAppMail, // VK_LAUNCH_MAIL
/* 0xb5 */ kKeyNone, kKeyAppMedia, // VK_LAUNCH_MEDIA_SELECT
/* 0xb6 */ kKeyNone, kKeyAppUser1, // VK_LAUNCH_APP1
/* 0xb7 */ kKeyNone, kKeyAppUser2, // VK_LAUNCH_APP2
/* 0xb8 */ kKeyNone, kKeyNone, // unassigned
/* 0xb9 */ kKeyNone, kKeyNone, // unassigned
/* 0xba */ kKeyNone, kKeyNone, // OEM specific
@ -1407,9 +1394,9 @@ CMSWindowsPrimaryScreen::mapKey(
}
ButtonID
CMSWindowsPrimaryScreen::mapButton(WPARAM button) const
CMSWindowsPrimaryScreen::mapButton(WPARAM msg, LPARAM button) const
{
switch (button) {
switch (msg) {
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONUP:
@ -1434,6 +1421,21 @@ CMSWindowsPrimaryScreen::mapButton(WPARAM button) const
case WM_NCRBUTTONUP:
return kButtonRight;
case WM_XBUTTONDOWN:
case WM_XBUTTONDBLCLK:
case WM_XBUTTONUP:
case WM_NCXBUTTONDOWN:
case WM_NCXBUTTONDBLCLK:
case WM_NCXBUTTONUP:
switch (button) {
case XBUTTON1:
return kButtonExtra0 + 0;
case XBUTTON2:
return kButtonExtra0 + 1;
}
return kButtonNone;
default:
return kButtonNone;
}
@ -1446,8 +1448,9 @@ CMSWindowsPrimaryScreen::updateKeys()
// up-to-date results. i don't know why that is or why GetKeyState()
// should give different results.
// clear key state
// clear key and button state
memset(m_keys, 0, sizeof(m_keys));
memset(m_buttons, 0, sizeof(m_buttons));
// we only care about the modifier key states. other keys and the
// mouse buttons should be up.

View File

@ -87,7 +87,7 @@ private:
// key and button queries
KeyID mapKey(WPARAM keycode, LPARAM info,
KeyModifierMask* maskOut);
ButtonID mapButton(WPARAM button) const;
ButtonID mapButton(WPARAM msg, LPARAM button) const;
void updateKey(UINT vkCode, bool press);
bool isModifier(UINT vkCode) const;
@ -108,6 +108,9 @@ private:
// map of key state
BYTE m_keys[256];
// map of button state
BYTE m_buttons[1 + kButtonExtra0 + 1];
// last mouse position
SInt32 m_x, m_y;

View File

@ -28,6 +28,42 @@
#define SPI_SETMOUSESPEED 113
#endif
// X button stuff
#if !defined(WM_XBUTTONDOWN)
#define WM_XBUTTONDOWN 0x020B
#define WM_XBUTTONUP 0x020C
#define WM_XBUTTONDBLCLK 0x020D
#define WM_NCXBUTTONDOWN 0x00AB
#define WM_NCXBUTTONUP 0x00AC
#define WM_NCXBUTTONDBLCLK 0x00AD
#define MOUSEEVENTF_XDOWN 0x0100
#define MOUSEEVENTF_XUP 0x0200
#define XBUTTON1 0x0001
#define XBUTTON2 0x0002
#endif
// multimedia keys
#if !defined(VK_BROWSER_BACK)
#define VK_BROWSER_BACK 0xA6
#define VK_BROWSER_FORWARD 0xA7
#define VK_BROWSER_REFRESH 0xA8
#define VK_BROWSER_STOP 0xA9
#define VK_BROWSER_SEARCH 0xAA
#define VK_BROWSER_FAVORITES 0xAB
#define VK_BROWSER_HOME 0xAC
#define VK_VOLUME_MUTE 0xAD
#define VK_VOLUME_DOWN 0xAE
#define VK_VOLUME_UP 0xAF
#define VK_MEDIA_NEXT_TRACK 0xB0
#define VK_MEDIA_PREV_TRACK 0xB1
#define VK_MEDIA_STOP 0xB2
#define VK_MEDIA_PLAY_PAUSE 0xB3
#define VK_LAUNCH_MAIL 0xB4
#define VK_LAUNCH_MEDIA_SELECT 0xB5
#define VK_LAUNCH_APP1 0xB6
#define VK_LAUNCH_APP2 0xB7
#endif
//
// CMSWindowsSecondaryScreen
//
@ -258,11 +294,12 @@ CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
m_screen->syncDesktop();
// map button id to button flag
DWORD flags = mapButton(button, true);
DWORD data;
DWORD flags = mapButton(button, true, &data);
// send event
if (flags != 0) {
mouse_event(flags, 0, 0, 0, 0);
mouse_event(flags, 0, 0, data, 0);
}
}
@ -273,11 +310,12 @@ CMSWindowsSecondaryScreen::mouseUp(ButtonID button)
m_screen->syncDesktop();
// map button id to button flag
DWORD flags = mapButton(button, false);
DWORD data;
DWORD flags = mapButton(button, false, &data);
// send event
if (flags != 0) {
mouse_event(flags, 0, 0, 0, 0);
mouse_event(flags, 0, 0, data, 0);
}
}
@ -606,6 +644,48 @@ CMSWindowsSecondaryScreen::getToggleState() const
// map special KeyID keys to virtual key codes. if the key is an
// extended key then the entry is the virtual key code | 0x100.
// unmapped keys have a 0 entry.
static const UINT g_mapE000[] =
{
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xa0 */ 0, 0, 0, 0,
/* 0xa4 */ 0, 0, VK_BROWSER_BACK|0x100, VK_BROWSER_FORWARD|0x100,
/* 0xa8 */ VK_BROWSER_REFRESH|0x100, VK_BROWSER_STOP|0x100,
/* 0xaa */ VK_BROWSER_SEARCH|0x100, VK_BROWSER_FAVORITES|0x100,
/* 0xac */ VK_BROWSER_HOME|0x100, VK_VOLUME_MUTE|0x100,
/* 0xae */ VK_VOLUME_DOWN|0x100, VK_VOLUME_UP|0x100,
/* 0xb0 */ VK_MEDIA_NEXT_TRACK|0x100, VK_MEDIA_PREV_TRACK|0x100,
/* 0xb2 */ VK_MEDIA_STOP|0x100, VK_MEDIA_PLAY_PAUSE|0x100,
/* 0xb4 */ VK_LAUNCH_MAIL|0x100, VK_LAUNCH_MEDIA_SELECT|0x100,
/* 0xb6 */ VK_LAUNCH_APP1|0x100, VK_LAUNCH_APP2|0x100,
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
};
static const UINT g_mapEE00[] =
{
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
@ -685,8 +765,12 @@ static const UINT g_mapEF00[] =
};
DWORD
CMSWindowsSecondaryScreen::mapButton(ButtonID button, bool press) const
CMSWindowsSecondaryScreen::mapButton(ButtonID button,
bool press, DWORD* inData) const
{
DWORD dummy;
DWORD* data = (inData != NULL) ? inData : &dummy;
// the system will swap the meaning of left/right for us if
// the user has configured a left-handed mouse but we don't
// want it to swap since we want the handedness of the
@ -703,7 +787,8 @@ CMSWindowsSecondaryScreen::mapButton(ButtonID button, bool press) const
}
}
// map button id to button flag
// map button id to button flag and button data
*data = 0;
switch (button) {
case kButtonLeft:
return press ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
@ -714,6 +799,14 @@ CMSWindowsSecondaryScreen::mapButton(ButtonID button, bool press) const
case kButtonRight:
return press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
case kButtonExtra0 + 0:
*data = XBUTTON1;
return press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
case kButtonExtra0 + 1:
*data = XBUTTON2;
return press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
default:
return 0;
}
@ -727,7 +820,10 @@ CMSWindowsSecondaryScreen::mapKey(Keystrokes& keys, UINT& virtualKey,
// check for special keys
if ((id & 0xfffff000) == 0xe000) {
if ((id & 0xff00) == 0xee00) {
if ((id & 0xff00) == 0xe000) {
virtualKey = g_mapE000[id & 0xff];
}
else if ((id & 0xff00) == 0xee00) {
virtualKey = g_mapEE00[id & 0xff];
}
else if ((id & 0xff00) == 0xef00) {

View File

@ -98,7 +98,8 @@ private:
bool isMultimon() const;
// key and button queries and operations
DWORD mapButton(ButtonID button, bool press) const;
DWORD mapButton(ButtonID button,
bool press, DWORD* data) const;
KeyModifierMask mapKey(Keystrokes&, UINT& virtualKey, KeyID,
KeyModifierMask, EKeyAction) const;
void doKeystrokes(const Keystrokes&, SInt32 count);

View File

@ -45,6 +45,20 @@ typedef struct tagMOUSEHOOKSTRUCTWin2000 {
#define SM_MOUSEWHEELPRESENT 75
#endif
// X button stuff
#if !defined(WM_XBUTTONDOWN)
#define WM_XBUTTONDOWN 0x020B
#define WM_XBUTTONUP 0x020C
#define WM_XBUTTONDBLCLK 0x020D
#define WM_NCXBUTTONDOWN 0x00AB
#define WM_NCXBUTTONUP 0x00AC
#define WM_NCXBUTTONDBLCLK 0x00AD
#define MOUSEEVENTF_XDOWN 0x0100
#define MOUSEEVENTF_XUP 0x0200
#define XBUTTON1 0x0001
#define XBUTTON2 0x0002
#endif
//
// globals
@ -152,35 +166,41 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
static
bool
mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 wheel)
mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
{
switch (wParam) {
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_XBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_XBUTTONDBLCLK:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_XBUTTONUP:
case WM_NCLBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_NCRBUTTONDOWN:
case WM_NCXBUTTONDOWN:
case WM_NCLBUTTONDBLCLK:
case WM_NCMBUTTONDBLCLK:
case WM_NCRBUTTONDBLCLK:
case WM_NCXBUTTONDBLCLK:
case WM_NCLBUTTONUP:
case WM_NCMBUTTONUP:
case WM_NCRBUTTONUP:
case WM_NCXBUTTONUP:
// always relay the event. eat it if relaying.
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_BUTTON, wParam, 0);
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_BUTTON, wParam, data);
return g_relay;
case WM_MOUSEWHEEL:
if (g_relay) {
// relay event
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_WHEEL, wheel, 0);
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_WHEEL, data, 0);
}
return g_relay;
@ -276,7 +296,10 @@ mouseHook(int code, WPARAM wParam, LPARAM lParam)
}
}
// handle the message
// handle the message. note that we don't handle X buttons
// here. that's okay because they're only supported on
// win2k and winxp and up and on those platforms we'll get
// get the mouse events through the low level hook.
if (mouseHookHandler(wParam, x, y, w)) {
return 1;
}

View File

@ -699,6 +699,44 @@ CXWindowsPrimaryScreen::mapModifier(unsigned int state) const
return mask;
}
// map "Internet" keys to KeyIDs
static const KeySym g_map1008FF[] =
{
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, kKeyAudioDown, kKeyAudioMute, kKeyAudioUp,
/* 0x14 */ kKeyAudioPlay, kKeyAudioStop, kKeyAudioPrev, kKeyAudioNext,
/* 0x18 */ kKeyWWWHome, kKeyAppMail, 0, kKeyWWWSearch, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, kKeyWWWBack, kKeyWWWForward,
/* 0x28 */ kKeyWWWStop, kKeyWWWRefresh, 0, 0, 0, 0, 0, 0,
/* 0x30 */ kKeyWWWFavorites, 0, kKeyAppMedia, 0, 0, 0, 0, 0,
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x40 */ kKeyAppUser1, kKeyAppUser2, 0, 0, 0, 0, 0, 0,
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
};
KeyID
CXWindowsPrimaryScreen::mapKey(XKeyEvent* event) const
{
@ -727,6 +765,10 @@ CXWindowsPrimaryScreen::mapKey(XKeyEvent* event) const
// MISCELLANY
return static_cast<KeyID>(keysym - 0xff00 + 0xef00);
case 0x1008ff00:
// "Internet" keys
return g_map1008FF[keysym & 0xff];
default: {
// lookup character in table
UInt32 key = CXWindowsUtil::mapKeySymToUCS4(keysym);
@ -743,10 +785,18 @@ CXWindowsPrimaryScreen::mapKey(XKeyEvent* event) const
ButtonID
CXWindowsPrimaryScreen::mapButton(unsigned int button) const
{
// FIXME -- should use button mapping?
// first three buttons map to 1, 2, 3 (kButtonLeft, Middle, Right)
if (button >= 1 && button <= 3) {
return static_cast<ButtonID>(button);
}
// buttons 4 and 5 are ignored here. they're used for the wheel.
// buttons 6, 7, etc and up map to 4, 5, etc.
else if (button >= 6) {
return static_cast<ButtonID>(button - 2);
}
// unknown button
else {
return kButtonNone;
}

View File

@ -34,6 +34,9 @@
# else
# error The XTest extension is required to build synergy
# endif
# if defined(HAVE_X11_XF86KEYSYM_H)
# include <X11/XF86keysym.h>
# endif
#endif
//
@ -263,7 +266,8 @@ void
CXWindowsSecondaryScreen::mouseWheel(SInt32 delta)
{
// choose button depending on rotation direction
const unsigned int xButton = mapButton((delta >= 0) ? 4 : 5);
const unsigned int xButton = mapButton(static_cast<ButtonID>(
(delta >= 0) ? -1 : -2));
if (xButton == 0) {
return;
}
@ -573,17 +577,30 @@ CXWindowsSecondaryScreen::getToggleState() const
unsigned int
CXWindowsSecondaryScreen::mapButton(ButtonID id) const
{
// map button -1 to button 4 (+wheel)
if (id == static_cast<ButtonID>(-1)) {
id = 4;
}
// map button -2 to button 5 (-wheel)
else if (id == static_cast<ButtonID>(-2)) {
id = 5;
}
// map buttons 4, 5, etc. to 6, 7, etc. to make room for buttons
// 4 and 5 used to simulate the mouse wheel.
else if (id >= 4) {
id += 2;
}
// check button is in legal range
if (id < 1 || id > m_buttons.size()) {
// out of range
return 0;
}
else if (m_buttons[id - 1] == 0) {
// button not mapped
return 0;
}
else {
return static_cast<unsigned int>(m_buttons[id - 1]);
}
// map button
return static_cast<unsigned int>(m_buttons[id - 1]);
}
KeyModifierMask
@ -1380,6 +1397,53 @@ CXWindowsSecondaryScreen::isToggleKeysym(KeySym key)
}
}
// map special KeyID keys to KeySyms
#if defined(HAVE_X11_XF86KEYSYM_H)
static const KeySym g_mapE000[] =
{
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xa0 */ 0, 0, 0, 0,
/* 0xa4 */ 0, 0,
/* 0xa6 */ XF86XK_Back, XF86XK_Forward,
/* 0xa8 */ XF86XK_Refresh, XF86XK_Stop,
/* 0xaa */ XF86XK_Search, XF86XK_Favorites,
/* 0xac */ XF86XK_HomePage, XF86XK_AudioMute,
/* 0xae */ XF86XK_AudioLowerVolume, XF86XK_AudioRaiseVolume,
/* 0xb0 */ XF86XK_AudioNext, XF86XK_AudioPrev,
/* 0xb2 */ XF86XK_AudioStop, XF86XK_AudioPlay,
/* 0xb4 */ XF86XK_Mail, XF86XK_AudioMedia,
/* 0xb6 */ XF86XK_Launch0, XF86XK_Launch1,
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
CXWindowsSecondaryScreen::KeyCodeIndex
CXWindowsSecondaryScreen::findKey(KeyID id, KeyModifierMask& mask) const
{
@ -1388,6 +1452,12 @@ CXWindowsSecondaryScreen::findKey(KeyID id, KeyModifierMask& mask) const
if ((id & 0xfffff000) == 0xe000) {
// special character
switch (id & 0x0000ff00) {
#if defined(HAVE_X11_XF86KEYSYM_H)
case 0xe000:
keysym = g_mapE000[id & 0xff];
break;
#endif
case 0xee00:
// ISO 9995 Function and Modifier Keys
if (id == kKeyLeftTab) {

View File

@ -70,8 +70,8 @@ static const KeyModifierID kKeyModifierIDLast = 6;
//! @name Key identifiers
//@{
// all identifiers except kKeyNone are equal to the corresponding
// X11 keysym - 0x1000.
// all identifiers except kKeyNone and those in 0xE000 to 0xE0FF
// inclusive are equal to the corresponding X11 keysym - 0x1000.
// no key
static const KeyID kKeyNone = 0x0000;
@ -211,6 +211,27 @@ static const KeyID kKeyHyper_R = 0xEFEE; /* Right hyper */
// more function and modifier keys
static const KeyID kKeyLeftTab = 0xEE20;
// extended keys
static const KeyID kKeyWWWBack = 0xE0A6;
static const KeyID kKeyWWWForward = 0xE0A7;
static const KeyID kKeyWWWRefresh = 0xE0A8;
static const KeyID kKeyWWWStop = 0xE0A9;
static const KeyID kKeyWWWSearch = 0xE0AA;
static const KeyID kKeyWWWFavorites = 0xE0AB;
static const KeyID kKeyWWWHome = 0xE0AC;
static const KeyID kKeyAudioMute = 0xE0AD;
static const KeyID kKeyAudioDown = 0xE0AE;
static const KeyID kKeyAudioUp = 0xE0AF;
static const KeyID kKeyAudioNext = 0xE0B0;
static const KeyID kKeyAudioPrev = 0xE0B1;
static const KeyID kKeyAudioStop = 0xE0B2;
static const KeyID kKeyAudioPlay = 0xE0B3;
static const KeyID kKeyAppMail = 0xE0B4;
static const KeyID kKeyAppMedia = 0xE0B5;
static const KeyID kKeyAppUser1 = 0xE0B6;
static const KeyID kKeyAppUser2 = 0xE0B7;
//@}
#endif

View File

@ -29,6 +29,7 @@ static const ButtonID kButtonNone = 0;
static const ButtonID kButtonLeft = 1;
static const ButtonID kButtonMiddle = 2;
static const ButtonID kButtonRight = 3;
static const ButtonID kButtonExtra0 = 4;
//@}
#endif