2002-08-02 23:57:46 +04:00
|
|
|
/*
|
|
|
|
* synergy -- mouse and keyboard sharing utility
|
|
|
|
* Copyright (C) 2002 Chris Schoeneman
|
|
|
|
*
|
|
|
|
* This package is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* found in the file COPYING that should have accompanied this file.
|
|
|
|
*
|
|
|
|
* This package is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
2001-11-19 03:33:36 +03:00
|
|
|
#include "CMSWindowsPrimaryScreen.h"
|
2002-07-15 19:01:36 +04:00
|
|
|
#include "CMSWindowsScreen.h"
|
2002-07-11 17:13:37 +04:00
|
|
|
#include "IPrimaryScreenReceiver.h"
|
2002-06-09 01:48:00 +04:00
|
|
|
#include "XScreen.h"
|
2002-06-11 02:06:45 +04:00
|
|
|
#include "CLog.h"
|
2003-01-18 17:36:19 +03:00
|
|
|
#include "CArch.h"
|
2003-01-05 01:01:32 +03:00
|
|
|
#include "CArchMiscWindows.h"
|
2002-06-11 02:06:45 +04:00
|
|
|
#include <cstring>
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2003-05-05 01:40:42 +04:00
|
|
|
// 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
|
|
|
|
|
2003-03-18 01:32:01 +03:00
|
|
|
//
|
|
|
|
// map virtual key id to a name
|
|
|
|
//
|
|
|
|
|
2003-05-05 01:40:42 +04:00
|
|
|
static const char* g_buttonToName[] = {
|
|
|
|
"button 0",
|
|
|
|
"Left Button",
|
|
|
|
"Middle Button",
|
|
|
|
"Right Button",
|
|
|
|
"X Button 1",
|
|
|
|
"X Button 2"
|
|
|
|
};
|
2003-03-18 01:32:01 +03:00
|
|
|
static const char* g_vkToName[] = {
|
|
|
|
"vk 0x00",
|
2003-05-05 01:40:42 +04:00
|
|
|
"Left Button",
|
|
|
|
"Right Button",
|
2003-03-18 01:32:01 +03:00
|
|
|
"VK_CANCEL",
|
2003-05-05 01:40:42 +04:00
|
|
|
"Middle Button",
|
2003-03-18 01:32:01 +03:00
|
|
|
"vk 0x05",
|
|
|
|
"vk 0x06",
|
|
|
|
"vk 0x07",
|
|
|
|
"VK_BACK",
|
|
|
|
"VK_TAB",
|
|
|
|
"vk 0x0a",
|
|
|
|
"vk 0x0b",
|
|
|
|
"VK_CLEAR",
|
|
|
|
"VK_RETURN",
|
|
|
|
"vk 0x0e",
|
|
|
|
"vk 0x0f",
|
|
|
|
"VK_SHIFT",
|
|
|
|
"VK_CONTROL",
|
|
|
|
"VK_MENU",
|
|
|
|
"VK_PAUSE",
|
|
|
|
"VK_CAPITAL",
|
|
|
|
"VK_KANA",
|
|
|
|
"vk 0x16",
|
|
|
|
"VK_JUNJA",
|
|
|
|
"VK_FINAL",
|
|
|
|
"VK_KANJI",
|
|
|
|
"vk 0x1a",
|
|
|
|
"VK_ESCAPE",
|
|
|
|
"VK_CONVERT",
|
|
|
|
"VK_NONCONVERT",
|
|
|
|
"VK_ACCEPT",
|
|
|
|
"VK_MODECHANGE",
|
|
|
|
"VK_SPACE",
|
|
|
|
"VK_PRIOR",
|
|
|
|
"VK_NEXT",
|
|
|
|
"VK_END",
|
|
|
|
"VK_HOME",
|
|
|
|
"VK_LEFT",
|
|
|
|
"VK_UP",
|
|
|
|
"VK_RIGHT",
|
|
|
|
"VK_DOWN",
|
|
|
|
"VK_SELECT",
|
|
|
|
"VK_PRINT",
|
|
|
|
"VK_EXECUTE",
|
|
|
|
"VK_SNAPSHOT",
|
|
|
|
"VK_INSERT",
|
|
|
|
"VK_DELETE",
|
|
|
|
"VK_HELP",
|
|
|
|
"VK_0",
|
|
|
|
"VK_1",
|
|
|
|
"VK_2",
|
|
|
|
"VK_3",
|
|
|
|
"VK_4",
|
|
|
|
"VK_5",
|
|
|
|
"VK_6",
|
|
|
|
"VK_7",
|
|
|
|
"VK_8",
|
|
|
|
"VK_9",
|
|
|
|
"vk 0x3a",
|
|
|
|
"vk 0x3b",
|
|
|
|
"vk 0x3c",
|
|
|
|
"vk 0x3d",
|
|
|
|
"vk 0x3e",
|
|
|
|
"vk 0x3f",
|
|
|
|
"vk 0x40",
|
|
|
|
"VK_A",
|
|
|
|
"VK_B",
|
|
|
|
"VK_C",
|
|
|
|
"VK_D",
|
|
|
|
"VK_E",
|
|
|
|
"VK_F",
|
|
|
|
"VK_G",
|
|
|
|
"VK_H",
|
|
|
|
"VK_I",
|
|
|
|
"VK_J",
|
|
|
|
"VK_K",
|
|
|
|
"VK_L",
|
|
|
|
"VK_M",
|
|
|
|
"VK_N",
|
|
|
|
"VK_O",
|
|
|
|
"VK_P",
|
|
|
|
"VK_Q",
|
|
|
|
"VK_R",
|
|
|
|
"VK_S",
|
|
|
|
"VK_T",
|
|
|
|
"VK_U",
|
|
|
|
"VK_V",
|
|
|
|
"VK_W",
|
|
|
|
"VK_X",
|
|
|
|
"VK_Y",
|
|
|
|
"VK_Z",
|
|
|
|
"VK_LWIN",
|
|
|
|
"VK_RWIN",
|
|
|
|
"VK_APPS",
|
|
|
|
"vk 0x5e",
|
|
|
|
"vk 0x5f",
|
|
|
|
"VK_NUMPAD0",
|
|
|
|
"VK_NUMPAD1",
|
|
|
|
"VK_NUMPAD2",
|
|
|
|
"VK_NUMPAD3",
|
|
|
|
"VK_NUMPAD4",
|
|
|
|
"VK_NUMPAD5",
|
|
|
|
"VK_NUMPAD6",
|
|
|
|
"VK_NUMPAD7",
|
|
|
|
"VK_NUMPAD8",
|
|
|
|
"VK_NUMPAD9",
|
|
|
|
"VK_MULTIPLY",
|
|
|
|
"VK_ADD",
|
|
|
|
"VK_SEPARATOR",
|
|
|
|
"VK_SUBTRACT",
|
|
|
|
"VK_DECIMAL",
|
|
|
|
"VK_DIVIDE",
|
|
|
|
"VK_F1",
|
|
|
|
"VK_F2",
|
|
|
|
"VK_F3",
|
|
|
|
"VK_F4",
|
|
|
|
"VK_F5",
|
|
|
|
"VK_F6",
|
|
|
|
"VK_F7",
|
|
|
|
"VK_F8",
|
|
|
|
"VK_F9",
|
|
|
|
"VK_F10",
|
|
|
|
"VK_F11",
|
|
|
|
"VK_F12",
|
|
|
|
"VK_F13",
|
|
|
|
"VK_F14",
|
|
|
|
"VK_F15",
|
|
|
|
"VK_F16",
|
|
|
|
"VK_F17",
|
|
|
|
"VK_F18",
|
|
|
|
"VK_F19",
|
|
|
|
"VK_F20",
|
|
|
|
"VK_F21",
|
|
|
|
"VK_F22",
|
|
|
|
"VK_F23",
|
|
|
|
"VK_F24",
|
|
|
|
"vk 0x88",
|
|
|
|
"vk 0x89",
|
|
|
|
"vk 0x8a",
|
|
|
|
"vk 0x8b",
|
|
|
|
"vk 0x8c",
|
|
|
|
"vk 0x8d",
|
|
|
|
"vk 0x8e",
|
|
|
|
"vk 0x8f",
|
|
|
|
"VK_NUMLOCK",
|
|
|
|
"VK_SCROLL",
|
|
|
|
"vk 0x92",
|
|
|
|
"vk 0x93",
|
|
|
|
"vk 0x94",
|
|
|
|
"vk 0x95",
|
|
|
|
"vk 0x96",
|
|
|
|
"vk 0x97",
|
|
|
|
"vk 0x98",
|
|
|
|
"vk 0x99",
|
|
|
|
"vk 0x9a",
|
|
|
|
"vk 0x9b",
|
|
|
|
"vk 0x9c",
|
|
|
|
"vk 0x9d",
|
|
|
|
"vk 0x9e",
|
|
|
|
"vk 0x9f",
|
|
|
|
"VK_LSHIFT",
|
|
|
|
"VK_RSHIFT",
|
|
|
|
"VK_LCONTROL",
|
|
|
|
"VK_RCONTROL",
|
|
|
|
"VK_LMENU",
|
|
|
|
"VK_RMENU",
|
2003-05-05 01:40:42 +04:00
|
|
|
"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",
|
2003-03-18 01:32:01 +03:00
|
|
|
"vk 0xb8",
|
|
|
|
"vk 0xb9",
|
|
|
|
"vk 0xba",
|
|
|
|
"vk 0xbb",
|
|
|
|
"vk 0xbc",
|
|
|
|
"vk 0xbd",
|
|
|
|
"vk 0xbe",
|
|
|
|
"vk 0xbf",
|
|
|
|
"vk 0xc0",
|
|
|
|
"vk 0xc1",
|
|
|
|
"vk 0xc2",
|
|
|
|
"vk 0xc3",
|
|
|
|
"vk 0xc4",
|
|
|
|
"vk 0xc5",
|
|
|
|
"vk 0xc6",
|
|
|
|
"vk 0xc7",
|
|
|
|
"vk 0xc8",
|
|
|
|
"vk 0xc9",
|
|
|
|
"vk 0xca",
|
|
|
|
"vk 0xcb",
|
|
|
|
"vk 0xcc",
|
|
|
|
"vk 0xcd",
|
|
|
|
"vk 0xce",
|
|
|
|
"vk 0xcf",
|
|
|
|
"vk 0xd0",
|
|
|
|
"vk 0xd1",
|
|
|
|
"vk 0xd2",
|
|
|
|
"vk 0xd3",
|
|
|
|
"vk 0xd4",
|
|
|
|
"vk 0xd5",
|
|
|
|
"vk 0xd6",
|
|
|
|
"vk 0xd7",
|
|
|
|
"vk 0xd8",
|
|
|
|
"vk 0xd9",
|
|
|
|
"vk 0xda",
|
|
|
|
"vk 0xdb",
|
|
|
|
"vk 0xdc",
|
|
|
|
"vk 0xdd",
|
|
|
|
"vk 0xde",
|
|
|
|
"vk 0xdf",
|
|
|
|
"vk 0xe0",
|
|
|
|
"vk 0xe1",
|
|
|
|
"vk 0xe2",
|
|
|
|
"vk 0xe3",
|
|
|
|
"vk 0xe4",
|
|
|
|
"VK_PROCESSKEY",
|
|
|
|
"vk 0xe6",
|
|
|
|
"vk 0xe7",
|
|
|
|
"vk 0xe8",
|
|
|
|
"vk 0xe9",
|
|
|
|
"vk 0xea",
|
|
|
|
"vk 0xeb",
|
|
|
|
"vk 0xec",
|
|
|
|
"vk 0xed",
|
|
|
|
"vk 0xee",
|
|
|
|
"vk 0xef",
|
|
|
|
"vk 0xf0",
|
|
|
|
"vk 0xf1",
|
|
|
|
"vk 0xf2",
|
|
|
|
"vk 0xf3",
|
|
|
|
"vk 0xf4",
|
|
|
|
"vk 0xf5",
|
|
|
|
"VK_ATTN",
|
|
|
|
"VK_CRSEL",
|
|
|
|
"VK_EXSEL",
|
|
|
|
"VK_EREOF",
|
|
|
|
"VK_PLAY",
|
|
|
|
"VK_ZOOM",
|
|
|
|
"VK_NONAME",
|
|
|
|
"VK_PA1",
|
|
|
|
"VK_OEM_CLEAR",
|
|
|
|
"vk 0xff"
|
|
|
|
};
|
|
|
|
|
2001-11-19 03:33:36 +03:00
|
|
|
//
|
|
|
|
// CMSWindowsPrimaryScreen
|
|
|
|
//
|
|
|
|
|
2002-07-11 17:13:37 +04:00
|
|
|
CMSWindowsPrimaryScreen::CMSWindowsPrimaryScreen(
|
|
|
|
IScreenReceiver* receiver,
|
|
|
|
IPrimaryScreenReceiver* primaryReceiver) :
|
2002-07-15 19:01:36 +04:00
|
|
|
CPrimaryScreen(receiver),
|
|
|
|
m_receiver(primaryReceiver),
|
2003-01-05 01:01:32 +03:00
|
|
|
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
2002-06-11 02:06:45 +04:00
|
|
|
m_threadID(0),
|
|
|
|
m_mark(0),
|
2003-05-03 16:54:22 +04:00
|
|
|
m_markReceived(0),
|
2003-05-18 00:58:27 +04:00
|
|
|
m_lowLevel(false),
|
|
|
|
m_cursorThread(0)
|
2001-11-19 03:33:36 +03:00
|
|
|
{
|
2002-07-15 19:01:36 +04:00
|
|
|
assert(m_receiver != NULL);
|
2002-07-11 17:13:37 +04:00
|
|
|
|
2002-06-09 01:48:00 +04:00
|
|
|
// load the hook library
|
|
|
|
m_hookLibrary = LoadLibrary("synrgyhk");
|
|
|
|
if (m_hookLibrary == NULL) {
|
2002-12-26 01:56:09 +03:00
|
|
|
LOG((CLOG_ERR "Failed to load hook library; synrgyhk.dll is missing"));
|
2002-06-09 01:48:00 +04:00
|
|
|
throw XScreenOpenFailure();
|
|
|
|
}
|
2002-07-11 17:13:37 +04:00
|
|
|
m_setSides = (SetSidesFunc)GetProcAddress(m_hookLibrary, "setSides");
|
2002-06-09 01:48:00 +04:00
|
|
|
m_setZone = (SetZoneFunc)GetProcAddress(m_hookLibrary, "setZone");
|
|
|
|
m_setRelay = (SetRelayFunc)GetProcAddress(m_hookLibrary, "setRelay");
|
|
|
|
m_install = (InstallFunc)GetProcAddress(m_hookLibrary, "install");
|
|
|
|
m_uninstall = (UninstallFunc)GetProcAddress(m_hookLibrary, "uninstall");
|
2002-06-24 01:53:31 +04:00
|
|
|
m_init = (InitFunc)GetProcAddress(m_hookLibrary, "init");
|
|
|
|
m_cleanup = (CleanupFunc)GetProcAddress(m_hookLibrary, "cleanup");
|
2002-07-11 17:13:37 +04:00
|
|
|
if (m_setSides == NULL ||
|
|
|
|
m_setZone == NULL ||
|
2002-06-09 01:48:00 +04:00
|
|
|
m_setRelay == NULL ||
|
|
|
|
m_install == NULL ||
|
2002-06-24 01:53:31 +04:00
|
|
|
m_uninstall == NULL ||
|
|
|
|
m_init == NULL ||
|
|
|
|
m_cleanup == NULL) {
|
2002-12-26 01:56:09 +03:00
|
|
|
LOG((CLOG_ERR "Invalid hook library; use a newer synrgyhk.dll"));
|
2002-06-09 01:48:00 +04:00
|
|
|
FreeLibrary(m_hookLibrary);
|
|
|
|
throw XScreenOpenFailure();
|
2002-06-01 23:26:11 +04:00
|
|
|
}
|
2002-06-09 01:48:00 +04:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
// create screen
|
|
|
|
m_screen = new CMSWindowsScreen(receiver, this);
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
CMSWindowsPrimaryScreen::~CMSWindowsPrimaryScreen()
|
|
|
|
{
|
2002-06-09 01:48:00 +04:00
|
|
|
assert(m_hookLibrary != NULL);
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
delete m_screen;
|
2002-06-09 01:48:00 +04:00
|
|
|
FreeLibrary(m_hookLibrary);
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
void
|
2002-07-11 17:13:37 +04:00
|
|
|
CMSWindowsPrimaryScreen::reconfigure(UInt32 activeSides)
|
2002-06-01 23:26:11 +04:00
|
|
|
{
|
2002-07-11 17:13:37 +04:00
|
|
|
m_setSides(activeSides);
|
2002-06-01 23:26:11 +04:00
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
void
|
2002-06-17 17:31:21 +04:00
|
|
|
CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
2001-11-19 03:33:36 +03:00
|
|
|
{
|
2002-07-17 21:27:41 +04:00
|
|
|
// warp mouse
|
|
|
|
warpCursorNoFlush(x, y);
|
|
|
|
|
|
|
|
// remove all input events before and including warp
|
|
|
|
MSG msg;
|
|
|
|
while (PeekMessage(&msg, NULL, SYNERGY_MSG_INPUT_FIRST,
|
|
|
|
SYNERGY_MSG_INPUT_LAST, PM_REMOVE)) {
|
|
|
|
// do nothing
|
|
|
|
}
|
2002-06-20 00:24:35 +04:00
|
|
|
|
|
|
|
// save position as last position
|
|
|
|
m_x = x;
|
|
|
|
m_y = y;
|
|
|
|
}
|
|
|
|
|
2002-12-23 16:55:21 +03:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::resetOptions()
|
|
|
|
{
|
|
|
|
// no options
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::setOptions(const COptionsList& /*options*/)
|
|
|
|
{
|
|
|
|
// no options
|
|
|
|
}
|
|
|
|
|
2003-03-13 01:34:07 +03:00
|
|
|
UInt32
|
|
|
|
CMSWindowsPrimaryScreen::addOneShotTimer(double timeout)
|
|
|
|
{
|
|
|
|
return m_screen->addOneShotTimer(timeout);
|
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
KeyModifierMask
|
|
|
|
CMSWindowsPrimaryScreen::getToggleMask() const
|
2002-04-30 21:48:11 +04:00
|
|
|
{
|
2002-05-22 21:01:17 +04:00
|
|
|
KeyModifierMask mask = 0;
|
2003-05-05 01:40:42 +04:00
|
|
|
|
|
|
|
// 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;
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
|
2002-04-30 21:48:11 +04:00
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
bool
|
|
|
|
CMSWindowsPrimaryScreen::isLockedToScreen() const
|
2002-05-24 18:37:12 +04:00
|
|
|
{
|
2003-05-05 01:40:42 +04:00
|
|
|
// 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;
|
2002-05-24 21:54:28 +04:00
|
|
|
}
|
|
|
|
}
|
2003-05-05 01:40:42 +04:00
|
|
|
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;
|
2002-07-01 17:00:12 +04:00
|
|
|
}
|
|
|
|
}
|
2002-05-24 21:54:28 +04:00
|
|
|
|
|
|
|
// not locked
|
2002-05-24 18:37:12 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
IScreen*
|
|
|
|
CMSWindowsPrimaryScreen::getScreen() const
|
|
|
|
{
|
|
|
|
return m_screen;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onScreensaver(bool activated)
|
|
|
|
{
|
|
|
|
m_receiver->onScreensaver(activated);
|
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
bool
|
2002-07-15 19:01:36 +04:00
|
|
|
CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
|
2001-11-19 03:33:36 +03:00
|
|
|
{
|
2002-07-13 00:41:23 +04:00
|
|
|
assert(event != NULL);
|
|
|
|
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
const MSG* msg = &event->m_msg;
|
|
|
|
|
|
|
|
// check if windows key is up but we think it's down. if so then
|
|
|
|
// synthesize a key release for it. we have to do this because
|
|
|
|
// if the user presses and releases a windows key without pressing
|
|
|
|
// any other key when its down then windows will eat the key
|
|
|
|
// release. if we don't detect that an synthesize the release
|
|
|
|
// then the user will be locked to the screen and the client won't
|
|
|
|
// take the usual windows key release action (which on windows is
|
|
|
|
// to show the start menu).
|
|
|
|
//
|
|
|
|
// we can use GetKeyState() to check the state of the windows keys
|
|
|
|
// because, event though the key release is not reported to us,
|
|
|
|
// the event is processed and the keyboard state updated by the
|
|
|
|
// system. since the key could go up at any time we'll check the
|
|
|
|
// state on every event. only check on windows 95 family since
|
|
|
|
// NT family reports the key release as usual. obviously we skip
|
|
|
|
// this if the event is for the windows key itself.
|
|
|
|
if (m_is95Family) {
|
|
|
|
if ((m_keys[VK_LWIN] & 0x80) != 0 &&
|
|
|
|
(GetAsyncKeyState(VK_LWIN) & 0x8000) == 0 &&
|
|
|
|
!(msg->message == SYNERGY_MSG_KEY && msg->wParam == VK_LWIN)) {
|
|
|
|
// compute appropriate parameters for fake event
|
|
|
|
WPARAM wParam = VK_LWIN;
|
|
|
|
LPARAM lParam = 0xc1000000;
|
|
|
|
lParam |= (0x00ff0000 & (MapVirtualKey(wParam, 0) << 24));
|
|
|
|
|
|
|
|
// process as if it were a key up
|
|
|
|
KeyModifierMask mask;
|
2003-04-27 21:01:14 +04:00
|
|
|
KeyButton button = static_cast<KeyButton>(
|
|
|
|
(lParam & 0x00ff0000u) >> 16);
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
const KeyID key = mapKey(wParam, lParam, &mask);
|
2003-04-27 21:01:14 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: fake key release key=%d mask=0x%04x button=0x%04x", key, mask, button));
|
|
|
|
m_receiver->onKeyUp(key, mask, button);
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
updateKey(wParam, false);
|
|
|
|
}
|
|
|
|
if ((m_keys[VK_RWIN] & 0x80) != 0 &&
|
|
|
|
(GetAsyncKeyState(VK_RWIN) & 0x8000) == 0 &&
|
|
|
|
!(msg->message == SYNERGY_MSG_KEY && msg->wParam == VK_RWIN)) {
|
|
|
|
// compute appropriate parameters for fake event
|
|
|
|
WPARAM wParam = VK_RWIN;
|
|
|
|
LPARAM lParam = 0xc1000000;
|
|
|
|
lParam |= (0x00ff0000 & (MapVirtualKey(wParam, 0) << 24));
|
|
|
|
|
|
|
|
// process as if it were a key up
|
|
|
|
KeyModifierMask mask;
|
2003-04-27 21:01:14 +04:00
|
|
|
KeyButton button = static_cast<KeyButton>(
|
|
|
|
(lParam & 0x00ff0000u) >> 16);
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
const KeyID key = mapKey(wParam, lParam, &mask);
|
2003-04-27 21:01:14 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: fake key release key=%d mask=0x%04x button=0x%04x", key, mask, button));
|
|
|
|
m_receiver->onKeyUp(key, mask, button);
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
updateKey(wParam, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-19 03:33:36 +03:00
|
|
|
// handle event
|
|
|
|
switch (msg->message) {
|
2002-04-29 18:40:01 +04:00
|
|
|
case SYNERGY_MSG_MARK:
|
2001-11-19 03:33:36 +03:00
|
|
|
m_markReceived = msg->wParam;
|
|
|
|
return true;
|
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
case SYNERGY_MSG_KEY:
|
2002-06-09 01:48:00 +04:00
|
|
|
// ignore message if posted prior to last mark change
|
2002-07-17 21:27:41 +04:00
|
|
|
if (!ignore()) {
|
2003-06-09 02:12:12 +04:00
|
|
|
WPARAM wParam = msg->wParam;
|
|
|
|
LPARAM lParam = msg->lParam;
|
|
|
|
|
|
|
|
// check for ctrl+alt+del emulation
|
|
|
|
if ((wParam == VK_PAUSE || wParam == VK_CANCEL) &&
|
|
|
|
(m_keys[VK_CONTROL] & 0x80) != 0 &&
|
|
|
|
(m_keys[VK_MENU] & 0x80) != 0) {
|
|
|
|
LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
|
|
|
|
wParam = VK_DELETE;
|
|
|
|
lParam &= 0xffff0000;
|
|
|
|
lParam |= 0x00000001;
|
|
|
|
}
|
|
|
|
|
|
|
|
// process key normally
|
2001-11-25 21:32:41 +03:00
|
|
|
KeyModifierMask mask;
|
2003-06-09 02:12:12 +04:00
|
|
|
const KeyID key = mapKey(wParam, lParam, &mask);
|
2003-04-27 21:01:14 +04:00
|
|
|
KeyButton button = static_cast<KeyButton>(
|
2003-06-09 02:12:12 +04:00
|
|
|
(lParam & 0x00ff0000u) >> 16);
|
2003-04-27 21:01:14 +04:00
|
|
|
if (key != kKeyNone && key != kKeyMultiKey) {
|
2003-06-09 02:12:12 +04:00
|
|
|
if ((lParam & 0x80000000) == 0) {
|
2001-11-25 21:32:41 +03:00
|
|
|
// key press
|
2003-06-09 02:12:12 +04:00
|
|
|
const bool wasDown = ((lParam & 0x40000000) != 0);
|
|
|
|
const SInt32 repeat = (SInt32)(lParam & 0xffff);
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
if (repeat >= 2 || wasDown) {
|
2003-04-27 21:01:14 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: key repeat key=%d mask=0x%04x count=%d button=0x%04x", key, mask, repeat, button));
|
|
|
|
m_receiver->onKeyRepeat(key, mask, repeat, button);
|
2001-11-25 21:32:41 +03:00
|
|
|
}
|
|
|
|
else {
|
2003-04-27 21:01:14 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: key press key=%d mask=0x%04x button=0x%04x", key, mask, button));
|
|
|
|
m_receiver->onKeyDown(key, mask, button);
|
2001-11-25 21:32:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
// key release. if the key isn't down according to
|
|
|
|
// our table then we never got the key press event
|
|
|
|
// for it. if it's not a modifier key then we'll
|
|
|
|
// synthesize the press first. only do this on
|
|
|
|
// the windows 95 family, which eats certain special
|
|
|
|
// keys like alt+tab, ctrl+esc, etc.
|
|
|
|
if (m_is95Family && !isModifier(msg->wParam) &&
|
|
|
|
(m_keys[msg->wParam] & 0x80) == 0) {
|
2003-04-27 21:01:14 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: fake key press key=%d mask=0x%04x button=0x%04x", key, mask, button));
|
|
|
|
m_receiver->onKeyDown(key, mask, button);
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
updateKey(msg->wParam, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// do key up
|
2003-04-27 21:01:14 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: key release key=%d mask=0x%04x button=0x%04x", key, mask, button));
|
|
|
|
m_receiver->onKeyUp(key, mask, button);
|
2001-11-25 21:32:41 +03:00
|
|
|
}
|
|
|
|
}
|
2002-05-22 21:01:17 +04:00
|
|
|
else {
|
2002-10-16 01:29:44 +04:00
|
|
|
LOG((CLOG_DEBUG2 "event: cannot map key wParam=%d lParam=0x%08x", msg->wParam, msg->lParam));
|
2002-05-22 21:01:17 +04:00
|
|
|
}
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
2003-05-03 16:54:22 +04:00
|
|
|
|
|
|
|
// keep our shadow key state up to date
|
|
|
|
updateKey(msg->wParam, ((msg->lParam & 0x80000000) == 0));
|
|
|
|
|
2001-11-19 03:33:36 +03:00
|
|
|
return true;
|
|
|
|
|
2003-05-03 16:54:22 +04:00
|
|
|
case SYNERGY_MSG_MOUSE_BUTTON: {
|
|
|
|
// get which button
|
|
|
|
bool pressed = false;
|
2003-05-05 01:40:42 +04:00
|
|
|
const ButtonID button = mapButton(msg->wParam, msg->lParam);
|
2003-05-03 16:54:22 +04:00
|
|
|
|
2002-06-09 01:48:00 +04:00
|
|
|
// ignore message if posted prior to last mark change
|
2002-07-17 21:27:41 +04:00
|
|
|
if (!ignore()) {
|
2001-11-19 03:33:36 +03:00
|
|
|
switch (msg->wParam) {
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_RBUTTONDOWN:
|
2003-05-05 01:40:42 +04:00
|
|
|
case WM_XBUTTONDOWN:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_LBUTTONDBLCLK:
|
|
|
|
case WM_MBUTTONDBLCLK:
|
|
|
|
case WM_RBUTTONDBLCLK:
|
2003-05-05 01:40:42 +04:00
|
|
|
case WM_XBUTTONDBLCLK:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_NCLBUTTONDOWN:
|
|
|
|
case WM_NCMBUTTONDOWN:
|
|
|
|
case WM_NCRBUTTONDOWN:
|
2003-05-05 01:40:42 +04:00
|
|
|
case WM_NCXBUTTONDOWN:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_NCLBUTTONDBLCLK:
|
|
|
|
case WM_NCMBUTTONDBLCLK:
|
|
|
|
case WM_NCRBUTTONDBLCLK:
|
2003-05-05 01:40:42 +04:00
|
|
|
case WM_NCXBUTTONDBLCLK:
|
2002-10-16 01:29:44 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: button press button=%d", button));
|
2001-11-19 03:33:36 +03:00
|
|
|
if (button != kButtonNone) {
|
2002-07-15 19:01:36 +04:00
|
|
|
m_receiver->onMouseDown(button);
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
2003-05-03 16:54:22 +04:00
|
|
|
pressed = true;
|
2001-11-19 03:33:36 +03:00
|
|
|
break;
|
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_LBUTTONUP:
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
case WM_RBUTTONUP:
|
2003-05-05 01:40:42 +04:00
|
|
|
case WM_XBUTTONUP:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_NCLBUTTONUP:
|
|
|
|
case WM_NCMBUTTONUP:
|
|
|
|
case WM_NCRBUTTONUP:
|
2003-05-05 01:40:42 +04:00
|
|
|
case WM_NCXBUTTONUP:
|
2002-10-16 01:29:44 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: button release button=%d", button));
|
2001-11-19 03:33:36 +03:00
|
|
|
if (button != kButtonNone) {
|
2002-07-15 19:01:36 +04:00
|
|
|
m_receiver->onMouseUp(button);
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
2003-05-03 16:54:22 +04:00
|
|
|
pressed = false;
|
2001-11-19 03:33:36 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-05-03 16:54:22 +04:00
|
|
|
|
|
|
|
// keep our shadow key state up to date
|
2003-05-05 01:40:42 +04:00
|
|
|
if (button >= kButtonLeft && button <= kButtonExtra0 + 1) {
|
|
|
|
if (pressed) {
|
|
|
|
m_buttons[button] |= 0x80;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_buttons[button] &= ~0x80;
|
|
|
|
}
|
2003-05-03 16:54:22 +04:00
|
|
|
}
|
|
|
|
|
2001-11-19 03:33:36 +03:00
|
|
|
return true;
|
2003-05-03 16:54:22 +04:00
|
|
|
}
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2002-05-23 22:35:08 +04:00
|
|
|
case SYNERGY_MSG_MOUSE_WHEEL:
|
2002-06-09 01:48:00 +04:00
|
|
|
// ignore message if posted prior to last mark change
|
2002-07-17 21:27:41 +04:00
|
|
|
if (!ignore()) {
|
2002-10-16 01:29:44 +04:00
|
|
|
LOG((CLOG_DEBUG1 "event: button wheel delta=%d %d", msg->wParam, msg->lParam));
|
2002-07-15 19:01:36 +04:00
|
|
|
m_receiver->onMouseWheel(msg->wParam);
|
2002-05-23 22:35:08 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
2002-07-17 21:27:41 +04:00
|
|
|
case SYNERGY_MSG_PRE_WARP:
|
|
|
|
{
|
|
|
|
// save position to compute delta of next motion
|
|
|
|
m_x = static_cast<SInt32>(msg->wParam);
|
|
|
|
m_y = static_cast<SInt32>(msg->lParam);
|
|
|
|
|
|
|
|
// we warped the mouse. discard events until we find the
|
|
|
|
// matching post warp event. see warpCursorNoFlush() for
|
|
|
|
// where the events are sent. we discard the matching
|
|
|
|
// post warp event and can be sure we've skipped the warp
|
|
|
|
// event.
|
|
|
|
MSG msg;
|
|
|
|
do {
|
|
|
|
GetMessage(&msg, NULL, SYNERGY_MSG_MOUSE_MOVE,
|
|
|
|
SYNERGY_MSG_POST_WARP);
|
|
|
|
} while (msg.message != SYNERGY_MSG_POST_WARP);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SYNERGY_MSG_POST_WARP:
|
2002-10-16 01:29:44 +04:00
|
|
|
LOG((CLOG_WARN "unmatched post warp"));
|
2002-07-17 21:27:41 +04:00
|
|
|
return true;
|
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
case SYNERGY_MSG_MOUSE_MOVE:
|
2002-06-09 01:48:00 +04:00
|
|
|
// ignore message if posted prior to last mark change
|
2002-07-17 21:27:41 +04:00
|
|
|
if (!ignore()) {
|
|
|
|
// compute motion delta (relative to the last known
|
|
|
|
// mouse position)
|
|
|
|
SInt32 x = static_cast<SInt32>(msg->wParam) - m_x;
|
|
|
|
SInt32 y = static_cast<SInt32>(msg->lParam) - m_y;
|
|
|
|
|
|
|
|
// save position to compute delta of next motion
|
|
|
|
m_x = static_cast<SInt32>(msg->wParam);
|
|
|
|
m_y = static_cast<SInt32>(msg->lParam);
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
if (!isActive()) {
|
2002-07-17 21:27:41 +04:00
|
|
|
// motion on primary screen
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
if (x != 0 || y != 0) {
|
|
|
|
m_receiver->onMouseMovePrimary(m_x, m_y);
|
|
|
|
}
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
|
|
|
else {
|
2002-07-17 21:27:41 +04:00
|
|
|
// motion on secondary screen. warp mouse back to
|
|
|
|
// center.
|
|
|
|
if (x != 0 || y != 0) {
|
|
|
|
// back to center
|
|
|
|
warpCursorNoFlush(m_xCenter, m_yCenter);
|
|
|
|
|
2003-02-16 22:53:56 +03:00
|
|
|
// examine the motion. if it's about the distance
|
|
|
|
// from the center of the screen to an edge then
|
|
|
|
// it's probably a bogus motion that we want to
|
|
|
|
// ignore (see warpCursorNoFlush() for a further
|
|
|
|
// description).
|
|
|
|
static SInt32 bogusZoneSize = 10;
|
|
|
|
SInt32 x0, y0, w0, h0;
|
|
|
|
m_screen->getShape(x0, y0, w0, h0);
|
|
|
|
if (-x + bogusZoneSize > m_xCenter - x0 ||
|
|
|
|
x + bogusZoneSize > x0 + w0 - m_xCenter ||
|
|
|
|
-y + bogusZoneSize > m_yCenter - y0 ||
|
|
|
|
y + bogusZoneSize > y0 + h0 - m_yCenter) {
|
|
|
|
LOG((CLOG_DEBUG "dropped bogus motion %+d,%+d", x, y));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// send motion
|
|
|
|
m_receiver->onMouseMoveSecondary(x, y);
|
|
|
|
}
|
2002-06-09 01:48:00 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2001-11-25 21:32:41 +03:00
|
|
|
}
|
|
|
|
|
2002-07-13 00:41:23 +04:00
|
|
|
bool
|
|
|
|
CMSWindowsPrimaryScreen::onEvent(CEvent* event)
|
2001-11-25 21:32:41 +03:00
|
|
|
{
|
2002-07-13 00:41:23 +04:00
|
|
|
assert(event != NULL);
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
const MSG& msg = event->m_msg;
|
2002-07-13 00:41:23 +04:00
|
|
|
switch (msg.message) {
|
2002-07-15 19:01:36 +04:00
|
|
|
case WM_DISPLAYCHANGE:
|
|
|
|
// recompute center pixel of primary screen
|
|
|
|
m_screen->getCursorCenter(m_xCenter, m_yCenter);
|
2002-06-09 01:48:00 +04:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
// warp mouse to center if active
|
|
|
|
if (isActive()) {
|
|
|
|
warpCursorToCenter();
|
2002-06-09 01:48:00 +04:00
|
|
|
}
|
2002-06-01 23:26:11 +04:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
// tell hook about resize if not active
|
|
|
|
else {
|
|
|
|
SInt32 x, y, w, h;
|
|
|
|
m_screen->getShape(x, y, w, h);
|
|
|
|
m_setZone(x, y, w, h, getJumpZoneSize());
|
|
|
|
}
|
2002-07-13 00:41:23 +04:00
|
|
|
return true;
|
2002-07-15 19:01:36 +04:00
|
|
|
}
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
return false;
|
|
|
|
}
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2003-03-13 01:34:07 +03:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onOneShotTimerExpired(UInt32 id)
|
|
|
|
{
|
|
|
|
m_receiver->onOneShotTimerExpired(id);
|
|
|
|
}
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
SInt32
|
|
|
|
CMSWindowsPrimaryScreen::getJumpZoneSize() const
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
void
|
2003-05-03 16:54:22 +04:00
|
|
|
CMSWindowsPrimaryScreen::postCreateWindow(HWND)
|
2002-07-15 19:01:36 +04:00
|
|
|
{
|
|
|
|
// install hooks
|
2003-05-03 16:54:22 +04:00
|
|
|
switch (m_install()) {
|
|
|
|
case kHOOK_FAILED:
|
|
|
|
// FIXME -- can't install hook so we won't work; report error
|
|
|
|
m_lowLevel = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kHOOK_OKAY:
|
|
|
|
m_lowLevel = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kHOOK_OKAY_LL:
|
|
|
|
m_lowLevel = true;
|
|
|
|
break;
|
2002-07-15 19:01:36 +04:00
|
|
|
}
|
2003-05-03 16:54:22 +04:00
|
|
|
|
|
|
|
if (!isActive()) {
|
2002-07-15 19:01:36 +04:00
|
|
|
// watch jump zones
|
|
|
|
m_setRelay(false);
|
2002-05-24 21:54:28 +04:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
// all messages prior to now are invalid
|
|
|
|
nextMark();
|
|
|
|
}
|
|
|
|
}
|
2002-05-24 21:54:28 +04:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::preDestroyWindow(HWND)
|
|
|
|
{
|
|
|
|
// uninstall hooks
|
|
|
|
m_uninstall();
|
2002-07-13 00:41:23 +04:00
|
|
|
}
|
|
|
|
|
2003-05-18 00:58:27 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onAccessibleDesktop()
|
|
|
|
{
|
|
|
|
// get the current keyboard state
|
|
|
|
updateKeys();
|
|
|
|
}
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
void
|
2002-07-30 19:17:44 +04:00
|
|
|
CMSWindowsPrimaryScreen::onPreMainLoop()
|
2002-07-13 00:41:23 +04:00
|
|
|
{
|
2002-07-30 19:17:44 +04:00
|
|
|
// must call mainLoop() from same thread as open()
|
2002-07-15 19:01:36 +04:00
|
|
|
assert(m_threadID == GetCurrentThreadId());
|
2002-07-13 00:41:23 +04:00
|
|
|
}
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onPreOpen()
|
2002-07-13 00:41:23 +04:00
|
|
|
{
|
2002-07-15 19:01:36 +04:00
|
|
|
// initialize hook library
|
|
|
|
m_threadID = GetCurrentThreadId();
|
2002-07-18 21:03:10 +04:00
|
|
|
if (m_init(m_threadID) == 0) {
|
2002-12-26 01:56:09 +03:00
|
|
|
LOG((CLOG_ERR "Cannot initialize hook library; is synergy already running?"));
|
2002-07-18 21:03:10 +04:00
|
|
|
throw XScreenOpenFailure();
|
|
|
|
}
|
2002-07-13 00:41:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-07-15 19:01:36 +04:00
|
|
|
CMSWindowsPrimaryScreen::onPostOpen()
|
2002-07-13 00:41:23 +04:00
|
|
|
{
|
2002-07-15 19:01:36 +04:00
|
|
|
// get cursor info
|
|
|
|
m_screen->getCursorPos(m_x, m_y);
|
|
|
|
m_screen->getCursorCenter(m_xCenter, m_yCenter);
|
|
|
|
|
|
|
|
// set jump zones
|
2002-07-13 00:41:23 +04:00
|
|
|
SInt32 x, y, w, h;
|
2002-07-15 19:01:36 +04:00
|
|
|
m_screen->getShape(x, y, w, h);
|
|
|
|
m_setZone(x, y, w, h, getJumpZoneSize());
|
|
|
|
|
|
|
|
// initialize marks
|
|
|
|
m_mark = 0;
|
|
|
|
m_markReceived = 0;
|
|
|
|
nextMark();
|
2002-06-09 01:48:00 +04:00
|
|
|
}
|
2002-05-24 21:54:28 +04:00
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
void
|
2002-07-15 19:01:36 +04:00
|
|
|
CMSWindowsPrimaryScreen::onPostClose()
|
2002-06-09 01:48:00 +04:00
|
|
|
{
|
2002-07-15 19:01:36 +04:00
|
|
|
m_cleanup();
|
|
|
|
m_threadID = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onPreEnter()
|
|
|
|
{
|
2003-05-18 00:58:27 +04:00
|
|
|
// show cursor if we hid it
|
|
|
|
if (m_cursorThread != 0) {
|
|
|
|
if (m_threadID != m_cursorThread) {
|
|
|
|
AttachThreadInput(m_threadID, m_cursorThread, TRUE);
|
|
|
|
}
|
|
|
|
ShowCursor(TRUE);
|
|
|
|
if (m_threadID != m_cursorThread) {
|
|
|
|
AttachThreadInput(m_threadID, m_cursorThread, FALSE);
|
|
|
|
}
|
|
|
|
m_cursorThread = 0;
|
|
|
|
}
|
|
|
|
|
2002-06-09 01:48:00 +04:00
|
|
|
// enable ctrl+alt+del, alt+tab, etc
|
|
|
|
if (m_is95Family) {
|
|
|
|
DWORD dummy = 0;
|
|
|
|
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, FALSE, &dummy, 0);
|
|
|
|
}
|
|
|
|
|
2002-07-11 17:13:37 +04:00
|
|
|
// watch jump zones
|
|
|
|
m_setRelay(false);
|
2002-07-15 19:01:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onPostEnter()
|
|
|
|
{
|
|
|
|
// all messages prior to now are invalid
|
|
|
|
nextMark();
|
|
|
|
}
|
2002-06-09 01:48:00 +04:00
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onPreLeave()
|
|
|
|
{
|
2002-06-09 01:48:00 +04:00
|
|
|
// all messages prior to now are invalid
|
|
|
|
nextMark();
|
|
|
|
}
|
|
|
|
|
2002-07-15 19:01:36 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::onPostLeave(bool success)
|
|
|
|
{
|
|
|
|
if (success) {
|
|
|
|
// relay all mouse and keyboard events
|
|
|
|
m_setRelay(true);
|
|
|
|
|
|
|
|
// disable ctrl+alt+del, alt+tab, etc
|
|
|
|
if (m_is95Family) {
|
|
|
|
DWORD dummy = 0;
|
|
|
|
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0);
|
|
|
|
}
|
2003-05-18 00:58:27 +04:00
|
|
|
|
|
|
|
// hide the cursor if using low level hooks
|
|
|
|
if (m_lowLevel) {
|
|
|
|
HWND hwnd = GetForegroundWindow();
|
|
|
|
m_cursorThread = GetWindowThreadProcessId(hwnd, NULL);
|
|
|
|
if (m_threadID != m_cursorThread) {
|
|
|
|
AttachThreadInput(m_threadID, m_cursorThread, TRUE);
|
|
|
|
}
|
|
|
|
ShowCursor(FALSE);
|
|
|
|
if (m_threadID != m_cursorThread) {
|
|
|
|
AttachThreadInput(m_threadID, m_cursorThread, FALSE);
|
|
|
|
}
|
|
|
|
}
|
2002-07-15 19:01:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::createWindow()
|
|
|
|
{
|
|
|
|
// open the desktop and the window
|
2003-05-18 00:58:27 +04:00
|
|
|
m_window = m_screen->openDesktop();
|
|
|
|
if (m_window == NULL) {
|
2002-07-15 19:01:36 +04:00
|
|
|
throw XScreenOpenFailure();
|
|
|
|
}
|
2003-05-18 00:58:27 +04:00
|
|
|
|
|
|
|
// we don't ever want our window to activate
|
|
|
|
EnableWindow(m_window, FALSE);
|
2002-07-15 19:01:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::destroyWindow()
|
|
|
|
{
|
|
|
|
// close the desktop and the window
|
|
|
|
m_screen->closeDesktop();
|
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
bool
|
2002-07-11 22:58:49 +04:00
|
|
|
CMSWindowsPrimaryScreen::showWindow()
|
2002-06-09 01:48:00 +04:00
|
|
|
{
|
2003-05-18 00:58:27 +04:00
|
|
|
// we don't need a window to capture input but we need a window
|
|
|
|
// to hide the cursor when using low-level hooks. do not try to
|
|
|
|
// take the activation; we want the currently active window to
|
|
|
|
// stay active.
|
|
|
|
if (m_lowLevel) {
|
|
|
|
SetWindowPos(m_window, HWND_TOPMOST, m_xCenter, m_yCenter, 1, 1,
|
|
|
|
SWP_NOACTIVATE);
|
|
|
|
ShowWindow(m_window, SW_SHOWNA);
|
|
|
|
}
|
2002-06-09 01:48:00 +04:00
|
|
|
return true;
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
|
|
|
|
2002-07-11 22:58:49 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::hideWindow()
|
|
|
|
{
|
2003-05-18 00:58:27 +04:00
|
|
|
// hide our window
|
|
|
|
if (m_lowLevel) {
|
|
|
|
ShowWindow(m_window, SW_HIDE);
|
|
|
|
}
|
2002-07-11 22:58:49 +04:00
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
void
|
2002-07-15 19:01:36 +04:00
|
|
|
CMSWindowsPrimaryScreen::warpCursorToCenter()
|
2002-06-09 01:48:00 +04:00
|
|
|
{
|
2002-07-17 21:27:41 +04:00
|
|
|
warpCursor(m_xCenter, m_yCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
|
|
|
|
{
|
|
|
|
// send an event that we can recognize before the mouse warp
|
|
|
|
PostThreadMessage(m_threadID, SYNERGY_MSG_PRE_WARP, x, y);
|
|
|
|
|
|
|
|
// warp mouse. hopefully this inserts a mouse motion event
|
|
|
|
// between the previous message and the following message.
|
|
|
|
SetCursorPos(x, y);
|
|
|
|
|
2003-01-18 17:36:19 +03:00
|
|
|
// yield the CPU. there's a race condition when warping:
|
|
|
|
// a hardware mouse event occurs
|
|
|
|
// the mouse hook is not called because that process doesn't have the CPU
|
|
|
|
// we send PRE_WARP, SetCursorPos(), send POST_WARP
|
|
|
|
// we process all of those events and update m_x, m_y
|
|
|
|
// we finish our time slice
|
|
|
|
// the hook is called
|
|
|
|
// the hook sends us a mouse event from the pre-warp position
|
|
|
|
// we get the CPU
|
|
|
|
// we compute a bogus warp
|
|
|
|
// we need the hook to process all mouse events that occur
|
|
|
|
// before we warp before we do the warp but i'm not sure how
|
|
|
|
// to guarantee that. yielding the CPU here may reduce the
|
2003-02-16 22:53:56 +03:00
|
|
|
// chance of undesired behavior. we'll also check for very
|
|
|
|
// large motions that look suspiciously like about half width
|
|
|
|
// or height of the screen.
|
2003-01-18 17:36:19 +03:00
|
|
|
ARCH->sleep(0.0);
|
|
|
|
|
2002-07-17 21:27:41 +04:00
|
|
|
// send an event that we can recognize after the mouse warp
|
|
|
|
PostThreadMessage(m_threadID, SYNERGY_MSG_POST_WARP, 0, 0);
|
2002-06-09 01:48:00 +04:00
|
|
|
}
|
|
|
|
|
2002-07-13 00:41:23 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::nextMark()
|
2002-06-09 01:48:00 +04:00
|
|
|
{
|
2002-07-13 00:41:23 +04:00
|
|
|
// next mark
|
|
|
|
++m_mark;
|
|
|
|
|
|
|
|
// mark point in message queue where the mark was changed
|
|
|
|
PostThreadMessage(m_threadID, SYNERGY_MSG_MARK, m_mark, 0);
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
|
|
|
|
2002-07-17 21:27:41 +04:00
|
|
|
bool
|
|
|
|
CMSWindowsPrimaryScreen::ignore() const
|
|
|
|
{
|
|
|
|
return (m_mark != m_markReceived);
|
|
|
|
}
|
|
|
|
|
2002-09-02 21:30:04 +04:00
|
|
|
// map virtual keys to synergy key enumeration. use extended keyboard
|
|
|
|
// bit to distinguish some keys.
|
|
|
|
static const KeyID g_virtualKey[][2] =
|
2001-11-19 03:33:36 +03:00
|
|
|
{
|
2002-09-02 21:30:04 +04:00
|
|
|
/* 0x00 */ kKeyNone, kKeyNone, // reserved
|
|
|
|
/* 0x01 */ kKeyNone, kKeyNone, // VK_LBUTTON
|
|
|
|
/* 0x02 */ kKeyNone, kKeyNone, // VK_RBUTTON
|
|
|
|
/* 0x03 */ kKeyNone, kKeyBreak, // VK_CANCEL
|
|
|
|
/* 0x04 */ kKeyNone, kKeyNone, // VK_MBUTTON
|
|
|
|
/* 0x05 */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x06 */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x07 */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x08 */ kKeyBackSpace, kKeyNone, // VK_BACK
|
|
|
|
/* 0x09 */ kKeyTab, kKeyNone, // VK_TAB
|
|
|
|
/* 0x0a */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x0b */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x0c */ kKeyClear, kKeyClear, // VK_CLEAR
|
|
|
|
/* 0x0d */ kKeyReturn, kKeyKP_Enter, // VK_RETURN
|
|
|
|
/* 0x0e */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x0f */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x10 */ kKeyShift_L, kKeyShift_R, // VK_SHIFT
|
|
|
|
/* 0x11 */ kKeyControl_L, kKeyControl_R, // VK_CONTROL
|
|
|
|
/* 0x12 */ kKeyAlt_L, kKeyAlt_R, // VK_MENU
|
|
|
|
/* 0x13 */ kKeyPause, kKeyNone, // VK_PAUSE
|
|
|
|
/* 0x14 */ kKeyCapsLock, kKeyNone, // VK_CAPITAL
|
|
|
|
/* 0x15 */ kKeyNone, kKeyNone, // VK_KANA
|
|
|
|
/* 0x16 */ kKeyNone, kKeyNone, // VK_HANGUL
|
|
|
|
/* 0x17 */ kKeyNone, kKeyNone, // VK_JUNJA
|
|
|
|
/* 0x18 */ kKeyNone, kKeyNone, // VK_FINAL
|
|
|
|
/* 0x19 */ kKeyNone, kKeyNone, // VK_KANJI
|
|
|
|
/* 0x1a */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x1b */ kKeyEscape, kKeyNone, // VK_ESCAPE
|
|
|
|
/* 0x1c */ kKeyNone, kKeyNone, // VK_CONVERT
|
|
|
|
/* 0x1d */ kKeyNone, kKeyNone, // VK_NONCONVERT
|
|
|
|
/* 0x1e */ kKeyNone, kKeyNone, // VK_ACCEPT
|
|
|
|
/* 0x1f */ kKeyNone, kKeyNone, // VK_MODECHANGE
|
|
|
|
/* 0x20 */ 0x0020, kKeyNone, // VK_SPACE
|
|
|
|
/* 0x21 */ kKeyKP_PageUp, kKeyPageUp, // VK_PRIOR
|
|
|
|
/* 0x22 */ kKeyKP_PageDown, kKeyPageDown, // VK_NEXT
|
|
|
|
/* 0x23 */ kKeyKP_End, kKeyEnd, // VK_END
|
|
|
|
/* 0x24 */ kKeyKP_Home, kKeyHome, // VK_HOME
|
|
|
|
/* 0x25 */ kKeyKP_Left, kKeyLeft, // VK_LEFT
|
|
|
|
/* 0x26 */ kKeyKP_Up, kKeyUp, // VK_UP
|
|
|
|
/* 0x27 */ kKeyKP_Right, kKeyRight, // VK_RIGHT
|
|
|
|
/* 0x28 */ kKeyKP_Down, kKeyDown, // VK_DOWN
|
|
|
|
/* 0x29 */ kKeySelect, kKeySelect, // VK_SELECT
|
|
|
|
/* 0x2a */ kKeyNone, kKeyNone, // VK_PRINT
|
|
|
|
/* 0x2b */ kKeyExecute, kKeyExecute, // VK_EXECUTE
|
|
|
|
/* 0x2c */ kKeyPrint, kKeyPrint, // VK_SNAPSHOT
|
|
|
|
/* 0x2d */ kKeyKP_Insert, kKeyInsert, // VK_INSERT
|
|
|
|
/* 0x2e */ kKeyKP_Delete, kKeyDelete, // VK_DELETE
|
|
|
|
/* 0x2f */ kKeyHelp, kKeyHelp, // VK_HELP
|
|
|
|
/* 0x30 */ kKeyNone, kKeyNone, // VK_0
|
|
|
|
/* 0x31 */ kKeyNone, kKeyNone, // VK_1
|
|
|
|
/* 0x32 */ kKeyNone, kKeyNone, // VK_2
|
|
|
|
/* 0x33 */ kKeyNone, kKeyNone, // VK_3
|
|
|
|
/* 0x34 */ kKeyNone, kKeyNone, // VK_4
|
|
|
|
/* 0x35 */ kKeyNone, kKeyNone, // VK_5
|
|
|
|
/* 0x36 */ kKeyNone, kKeyNone, // VK_6
|
|
|
|
/* 0x37 */ kKeyNone, kKeyNone, // VK_7
|
|
|
|
/* 0x38 */ kKeyNone, kKeyNone, // VK_8
|
|
|
|
/* 0x39 */ kKeyNone, kKeyNone, // VK_9
|
|
|
|
/* 0x3a */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x3b */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x3c */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x3d */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x3e */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x3f */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x40 */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x41 */ kKeyNone, kKeyNone, // VK_A
|
|
|
|
/* 0x42 */ kKeyNone, kKeyNone, // VK_B
|
|
|
|
/* 0x43 */ kKeyNone, kKeyNone, // VK_C
|
|
|
|
/* 0x44 */ kKeyNone, kKeyNone, // VK_D
|
|
|
|
/* 0x45 */ kKeyNone, kKeyNone, // VK_E
|
|
|
|
/* 0x46 */ kKeyNone, kKeyNone, // VK_F
|
|
|
|
/* 0x47 */ kKeyNone, kKeyNone, // VK_G
|
|
|
|
/* 0x48 */ kKeyNone, kKeyNone, // VK_H
|
|
|
|
/* 0x49 */ kKeyNone, kKeyNone, // VK_I
|
|
|
|
/* 0x4a */ kKeyNone, kKeyNone, // VK_J
|
|
|
|
/* 0x4b */ kKeyNone, kKeyNone, // VK_K
|
|
|
|
/* 0x4c */ kKeyNone, kKeyNone, // VK_L
|
|
|
|
/* 0x4d */ kKeyNone, kKeyNone, // VK_M
|
|
|
|
/* 0x4e */ kKeyNone, kKeyNone, // VK_N
|
|
|
|
/* 0x4f */ kKeyNone, kKeyNone, // VK_O
|
|
|
|
/* 0x50 */ kKeyNone, kKeyNone, // VK_P
|
|
|
|
/* 0x51 */ kKeyNone, kKeyNone, // VK_Q
|
|
|
|
/* 0x52 */ kKeyNone, kKeyNone, // VK_R
|
|
|
|
/* 0x53 */ kKeyNone, kKeyNone, // VK_S
|
|
|
|
/* 0x54 */ kKeyNone, kKeyNone, // VK_T
|
|
|
|
/* 0x55 */ kKeyNone, kKeyNone, // VK_U
|
|
|
|
/* 0x56 */ kKeyNone, kKeyNone, // VK_V
|
|
|
|
/* 0x57 */ kKeyNone, kKeyNone, // VK_W
|
|
|
|
/* 0x58 */ kKeyNone, kKeyNone, // VK_X
|
|
|
|
/* 0x59 */ kKeyNone, kKeyNone, // VK_Y
|
|
|
|
/* 0x5a */ kKeyNone, kKeyNone, // VK_Z
|
2002-09-14 16:07:02 +04:00
|
|
|
/* 0x5b */ kKeyNone, kKeySuper_L, // VK_LWIN
|
|
|
|
/* 0x5c */ kKeyNone, kKeySuper_R, // VK_RWIN
|
2002-09-02 21:30:04 +04:00
|
|
|
/* 0x5d */ kKeyMenu, kKeyMenu, // VK_APPS
|
|
|
|
/* 0x5e */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x5f */ kKeyNone, kKeyNone, // undefined
|
|
|
|
/* 0x60 */ kKeyKP_0, kKeyNone, // VK_NUMPAD0
|
|
|
|
/* 0x61 */ kKeyKP_1, kKeyNone, // VK_NUMPAD1
|
|
|
|
/* 0x62 */ kKeyKP_2, kKeyNone, // VK_NUMPAD2
|
|
|
|
/* 0x63 */ kKeyKP_3, kKeyNone, // VK_NUMPAD3
|
|
|
|
/* 0x64 */ kKeyKP_4, kKeyNone, // VK_NUMPAD4
|
|
|
|
/* 0x65 */ kKeyKP_5, kKeyNone, // VK_NUMPAD5
|
|
|
|
/* 0x66 */ kKeyKP_6, kKeyNone, // VK_NUMPAD6
|
|
|
|
/* 0x67 */ kKeyKP_7, kKeyNone, // VK_NUMPAD7
|
|
|
|
/* 0x68 */ kKeyKP_8, kKeyNone, // VK_NUMPAD8
|
|
|
|
/* 0x69 */ kKeyKP_9, kKeyNone, // VK_NUMPAD9
|
|
|
|
/* 0x6a */ kKeyKP_Multiply, kKeyNone, // VK_MULTIPLY
|
|
|
|
/* 0x6b */ kKeyKP_Add, kKeyNone, // VK_ADD
|
|
|
|
/* 0x6c */ kKeyKP_Separator,kKeyKP_Separator,// VK_SEPARATOR
|
|
|
|
/* 0x6d */ kKeyKP_Subtract, kKeyNone, // VK_SUBTRACT
|
|
|
|
/* 0x6e */ kKeyKP_Decimal, kKeyNone, // VK_DECIMAL
|
|
|
|
/* 0x6f */ kKeyNone, kKeyKP_Divide, // VK_DIVIDE
|
|
|
|
/* 0x70 */ kKeyF1, kKeyNone, // VK_F1
|
|
|
|
/* 0x71 */ kKeyF2, kKeyNone, // VK_F2
|
|
|
|
/* 0x72 */ kKeyF3, kKeyNone, // VK_F3
|
|
|
|
/* 0x73 */ kKeyF4, kKeyNone, // VK_F4
|
|
|
|
/* 0x74 */ kKeyF5, kKeyNone, // VK_F5
|
|
|
|
/* 0x75 */ kKeyF6, kKeyNone, // VK_F6
|
|
|
|
/* 0x76 */ kKeyF7, kKeyNone, // VK_F7
|
|
|
|
/* 0x77 */ kKeyF8, kKeyNone, // VK_F8
|
|
|
|
/* 0x78 */ kKeyF9, kKeyNone, // VK_F9
|
|
|
|
/* 0x79 */ kKeyF10, kKeyNone, // VK_F10
|
|
|
|
/* 0x7a */ kKeyF11, kKeyNone, // VK_F11
|
|
|
|
/* 0x7b */ kKeyF12, kKeyNone, // VK_F12
|
|
|
|
/* 0x7c */ kKeyF13, kKeyF13, // VK_F13
|
|
|
|
/* 0x7d */ kKeyF14, kKeyF14, // VK_F14
|
|
|
|
/* 0x7e */ kKeyF15, kKeyF15, // VK_F15
|
|
|
|
/* 0x7f */ kKeyF16, kKeyF16, // VK_F16
|
|
|
|
/* 0x80 */ kKeyF17, kKeyF17, // VK_F17
|
|
|
|
/* 0x81 */ kKeyF18, kKeyF18, // VK_F18
|
|
|
|
/* 0x82 */ kKeyF19, kKeyF19, // VK_F19
|
|
|
|
/* 0x83 */ kKeyF20, kKeyF20, // VK_F20
|
|
|
|
/* 0x84 */ kKeyF21, kKeyF21, // VK_F21
|
|
|
|
/* 0x85 */ kKeyF22, kKeyF22, // VK_F22
|
|
|
|
/* 0x86 */ kKeyF23, kKeyF23, // VK_F23
|
|
|
|
/* 0x87 */ kKeyF24, kKeyF24, // VK_F24
|
|
|
|
/* 0x88 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x89 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x8a */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x8b */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x8c */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x8d */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x8e */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x8f */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x90 */ kKeyNumLock, kKeyNumLock, // VK_NUMLOCK
|
|
|
|
/* 0x91 */ kKeyScrollLock, kKeyNone, // VK_SCROLL
|
|
|
|
/* 0x92 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x93 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x94 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x95 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x96 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x97 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x98 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x99 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x9a */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x9b */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x9c */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x9d */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x9e */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0x9f */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xa0 */ kKeyShift_L, kKeyShift_L, // VK_LSHIFT
|
|
|
|
/* 0xa1 */ kKeyShift_R, kKeyShift_R, // VK_RSHIFT
|
|
|
|
/* 0xa2 */ kKeyControl_L, kKeyControl_L, // VK_LCONTROL
|
|
|
|
/* 0xa3 */ kKeyControl_R, kKeyControl_R, // VK_RCONTROL
|
|
|
|
/* 0xa4 */ kKeyAlt_L, kKeyAlt_L, // VK_LMENU
|
|
|
|
/* 0xa5 */ kKeyAlt_R, kKeyAlt_R, // VK_RMENU
|
2003-05-05 01:40:42 +04:00
|
|
|
/* 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
|
2002-09-02 21:30:04 +04:00
|
|
|
/* 0xb8 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xb9 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xba */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xbb */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xbc */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xbd */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xbe */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xbf */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xc0 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xc1 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc2 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc3 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc4 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc5 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc6 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc7 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc8 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xc9 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xca */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xcb */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xcc */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xcd */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xce */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xcf */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd0 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd1 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd2 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd3 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd4 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd5 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd6 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd7 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd8 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xd9 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xda */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xdb */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xdc */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xdd */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xde */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xdf */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xe0 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xe1 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xe2 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xe3 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xe4 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xe5 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xe6 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xe7 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xe8 */ kKeyNone, kKeyNone, // unassigned
|
|
|
|
/* 0xe9 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xea */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xeb */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xec */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xed */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xee */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xef */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xf0 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xf1 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xf2 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xf3 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xf4 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xf5 */ kKeyNone, kKeyNone, // OEM specific
|
|
|
|
/* 0xf6 */ kKeyNone, kKeyNone, // VK_ATTN
|
|
|
|
/* 0xf7 */ kKeyNone, kKeyNone, // VK_CRSEL
|
|
|
|
/* 0xf8 */ kKeyNone, kKeyNone, // VK_EXSEL
|
|
|
|
/* 0xf9 */ kKeyNone, kKeyNone, // VK_EREOF
|
|
|
|
/* 0xfa */ kKeyNone, kKeyNone, // VK_PLAY
|
|
|
|
/* 0xfb */ kKeyNone, kKeyNone, // VK_ZOOM
|
|
|
|
/* 0xfc */ kKeyNone, kKeyNone, // reserved
|
|
|
|
/* 0xfd */ kKeyNone, kKeyNone, // VK_PA1
|
|
|
|
/* 0xfe */ kKeyNone, kKeyNone, // VK_OEM_CLEAR
|
|
|
|
/* 0xff */ kKeyNone, kKeyNone // reserved
|
2001-11-25 21:32:41 +03:00
|
|
|
};
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
KeyID
|
|
|
|
CMSWindowsPrimaryScreen::mapKey(
|
|
|
|
WPARAM vkCode,
|
|
|
|
LPARAM info,
|
|
|
|
KeyModifierMask* maskOut)
|
2001-11-19 03:33:36 +03:00
|
|
|
{
|
2002-04-30 20:23:03 +04:00
|
|
|
// note: known microsoft bugs
|
|
|
|
// Q72583 -- MapVirtualKey() maps keypad keys incorrectly
|
|
|
|
// 95,98: num pad vk code -> invalid scan code
|
|
|
|
// 95,98,NT4: num pad scan code -> bad vk code except
|
|
|
|
// SEPARATOR, MULTIPLY, SUBTRACT, ADD
|
|
|
|
|
2001-11-25 21:32:41 +03:00
|
|
|
assert(maskOut != NULL);
|
|
|
|
|
|
|
|
// map modifier key
|
2001-11-19 03:33:36 +03:00
|
|
|
KeyModifierMask mask = 0;
|
2002-04-30 20:23:03 +04:00
|
|
|
if (((m_keys[VK_LSHIFT] |
|
|
|
|
m_keys[VK_RSHIFT] |
|
2002-06-11 02:06:45 +04:00
|
|
|
m_keys[VK_SHIFT]) & 0x80) != 0) {
|
2001-11-19 03:33:36 +03:00
|
|
|
mask |= KeyModifierShift;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
if (((m_keys[VK_LCONTROL] |
|
|
|
|
m_keys[VK_RCONTROL] |
|
2002-06-11 02:06:45 +04:00
|
|
|
m_keys[VK_CONTROL]) & 0x80) != 0) {
|
2001-11-19 03:33:36 +03:00
|
|
|
mask |= KeyModifierControl;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
2002-12-15 23:00:52 +03:00
|
|
|
if ((m_keys[VK_RMENU] & 0x80) != 0) {
|
|
|
|
// right alt => AltGr on windows
|
|
|
|
mask |= KeyModifierModeSwitch;
|
|
|
|
}
|
|
|
|
else if (((m_keys[VK_LMENU] |
|
|
|
|
m_keys[VK_MENU]) & 0x80) != 0) {
|
2001-11-19 03:33:36 +03:00
|
|
|
mask |= KeyModifierAlt;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
if (((m_keys[VK_LWIN] |
|
2002-06-11 02:06:45 +04:00
|
|
|
m_keys[VK_RWIN]) & 0x80) != 0) {
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
mask |= KeyModifierSuper;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
|
|
|
if ((m_keys[VK_CAPITAL] & 0x01) != 0) {
|
2002-04-30 20:23:03 +04:00
|
|
|
mask |= KeyModifierCapsLock;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
|
|
|
if ((m_keys[VK_NUMLOCK] & 0x01) != 0) {
|
2002-04-30 20:23:03 +04:00
|
|
|
mask |= KeyModifierNumLock;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
|
|
|
if ((m_keys[VK_SCROLL] & 0x01) != 0) {
|
2001-11-19 03:33:36 +03:00
|
|
|
mask |= KeyModifierScrollLock;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
2002-12-15 23:00:52 +03:00
|
|
|
// ctrl+alt => AltGr on windows
|
|
|
|
/* don't convert ctrl+alt to mode switch. if we do that then we can
|
|
|
|
* never send ctrl+alt+[key] from windows to some platform that
|
|
|
|
* doesn't treat ctrl+alt as mode switch (i.e. all other platforms).
|
|
|
|
* instead, let windows clients automatically treat ctrl+alt as
|
|
|
|
* AltGr and let other clients use ctrl+alt as is. the right alt
|
|
|
|
* key serves as a mode switch key.
|
2002-09-02 21:30:04 +04:00
|
|
|
if ((mask & (KeyModifierControl | KeyModifierAlt)) ==
|
|
|
|
(KeyModifierControl | KeyModifierAlt)) {
|
|
|
|
mask |= KeyModifierModeSwitch;
|
|
|
|
mask &= ~(KeyModifierControl | KeyModifierAlt);
|
|
|
|
}
|
2002-12-15 23:00:52 +03:00
|
|
|
*/
|
2001-11-25 21:32:41 +03:00
|
|
|
*maskOut = mask;
|
2002-10-16 01:29:44 +04:00
|
|
|
LOG((CLOG_DEBUG2 "key in vk=%d info=0x%08x mask=0x%04x", vkCode, info, mask));
|
2001-11-19 03:33:36 +03:00
|
|
|
|
2002-09-02 21:30:04 +04:00
|
|
|
// get the scan code and the extended keyboard flag
|
|
|
|
UINT scanCode = static_cast<UINT>((info & 0x00ff0000u) >> 16);
|
|
|
|
int extended = ((info & 0x01000000) == 0) ? 0 : 1;
|
2002-10-16 01:29:44 +04:00
|
|
|
LOG((CLOG_DEBUG1 "key vk=%d ext=%d scan=%d", vkCode, extended, scanCode));
|
2002-04-30 20:23:03 +04:00
|
|
|
|
|
|
|
// handle some keys via table lookup
|
2002-09-02 21:30:04 +04:00
|
|
|
KeyID id = g_virtualKey[vkCode][extended];
|
2001-11-25 21:32:41 +03:00
|
|
|
if (id != kKeyNone) {
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2002-09-02 21:30:04 +04:00
|
|
|
// save the control state then clear it. ToAscii() maps ctrl+letter
|
|
|
|
// to the corresponding control code and ctrl+backspace to delete.
|
|
|
|
// we don't want that translation so we clear the control modifier
|
|
|
|
// state. however, if we want to simulate AltGr (which is ctrl+alt)
|
|
|
|
// then we must not clear it.
|
|
|
|
BYTE lControl = m_keys[VK_LCONTROL];
|
|
|
|
BYTE rControl = m_keys[VK_RCONTROL];
|
|
|
|
BYTE control = m_keys[VK_CONTROL];
|
2003-04-27 21:01:14 +04:00
|
|
|
BYTE lMenu = m_keys[VK_LMENU];
|
|
|
|
BYTE menu = m_keys[VK_MENU];
|
2002-09-02 21:30:04 +04:00
|
|
|
if ((mask & KeyModifierModeSwitch) == 0) {
|
|
|
|
m_keys[VK_LCONTROL] = 0;
|
|
|
|
m_keys[VK_RCONTROL] = 0;
|
|
|
|
m_keys[VK_CONTROL] = 0;
|
|
|
|
}
|
2003-04-27 21:01:14 +04:00
|
|
|
else {
|
|
|
|
m_keys[VK_LCONTROL] = 0x80;
|
|
|
|
m_keys[VK_CONTROL] = 0x80;
|
|
|
|
m_keys[VK_LMENU] = 0x80;
|
|
|
|
m_keys[VK_MENU] = 0x80;
|
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
|
|
|
|
// convert to ascii
|
|
|
|
WORD ascii;
|
|
|
|
int result = ToAscii(vkCode, scanCode, m_keys, &ascii, 0);
|
|
|
|
|
|
|
|
// restore control state
|
|
|
|
m_keys[VK_LCONTROL] = lControl;
|
|
|
|
m_keys[VK_RCONTROL] = rControl;
|
|
|
|
m_keys[VK_CONTROL] = control;
|
2003-04-27 21:01:14 +04:00
|
|
|
m_keys[VK_LMENU] = lMenu;
|
|
|
|
m_keys[VK_MENU] = menu;
|
2002-04-30 20:23:03 +04:00
|
|
|
|
2003-04-27 21:01:14 +04:00
|
|
|
// if result is less than zero then it was a dead key. leave it
|
|
|
|
// there.
|
2002-04-30 20:23:03 +04:00
|
|
|
if (result < 0) {
|
2002-07-23 22:59:15 +04:00
|
|
|
return kKeyMultiKey;
|
2002-04-30 20:23:03 +04:00
|
|
|
}
|
2001-11-25 21:32:41 +03:00
|
|
|
|
2002-04-30 20:23:03 +04:00
|
|
|
// if result is 1 then the key was succesfully converted
|
|
|
|
else if (result == 1) {
|
2003-04-27 21:01:14 +04:00
|
|
|
if (ascii >= 0x80) {
|
|
|
|
// character is not really ASCII. instead it's some
|
|
|
|
// character in the current ANSI code page. try to
|
|
|
|
// convert that to a Unicode character. if we fail
|
|
|
|
// then use the single byte character as is.
|
|
|
|
char src = static_cast<char>(ascii & 0xff);
|
|
|
|
wchar_t unicode;
|
|
|
|
if (MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED,
|
|
|
|
&src, 1, &unicode, 1) > 0) {
|
|
|
|
return static_cast<KeyID>(unicode);
|
|
|
|
}
|
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
return static_cast<KeyID>(ascii & 0x00ff);
|
2001-11-25 21:32:41 +03:00
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
|
|
|
|
// if result is 2 then a previous dead key could not be composed.
|
|
|
|
else if (result == 2) {
|
2003-04-27 21:01:14 +04:00
|
|
|
// if the two characters are the same and this is a key release
|
|
|
|
// then this event is the dead key being released. we put the
|
|
|
|
// dead key back in that case, otherwise we discard both key
|
|
|
|
// events because we can't compose the character. alternatively
|
|
|
|
// we could generate key events for both keys.
|
|
|
|
if (((ascii & 0xff00) >> 8) != (ascii & 0x00ff) ||
|
|
|
|
(info & 0x80000000) == 0) {
|
|
|
|
// cannot compose key
|
|
|
|
return kKeyNone;
|
|
|
|
}
|
|
|
|
|
2002-04-30 20:23:03 +04:00
|
|
|
// get the scan code of the dead key and the shift state
|
|
|
|
// required to generate it.
|
2002-05-22 21:01:17 +04:00
|
|
|
vkCode = VkKeyScan(static_cast<TCHAR>(ascii & 0x00ff));
|
2002-04-30 20:23:03 +04:00
|
|
|
|
|
|
|
// set shift state required to generate key
|
|
|
|
BYTE keys[256];
|
|
|
|
memset(keys, 0, sizeof(keys));
|
2002-06-11 02:06:45 +04:00
|
|
|
if (vkCode & 0x0100) {
|
2002-07-17 21:27:41 +04:00
|
|
|
keys[VK_SHIFT] = 0x80;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
2002-07-17 21:27:41 +04:00
|
|
|
if (vkCode & 0x0200) {
|
2002-04-30 20:23:03 +04:00
|
|
|
keys[VK_CONTROL] = 0x80;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
2002-07-17 21:27:41 +04:00
|
|
|
if (vkCode & 0x0400) {
|
|
|
|
keys[VK_MENU] = 0x80;
|
2002-06-11 02:06:45 +04:00
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
|
|
|
|
// strip shift state off of virtual key code
|
|
|
|
vkCode &= 0x00ff;
|
|
|
|
|
|
|
|
// get the scan code for the key
|
|
|
|
scanCode = MapVirtualKey(vkCode, 0);
|
|
|
|
|
|
|
|
// put it back
|
|
|
|
ToAscii(vkCode, scanCode, keys, &ascii, 0);
|
2002-07-23 22:59:15 +04:00
|
|
|
return kKeyMultiKey;
|
2001-11-25 21:32:41 +03:00
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
|
|
|
|
// cannot convert key
|
|
|
|
return kKeyNone;
|
2001-11-19 03:33:36 +03:00
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
ButtonID
|
2003-05-05 01:40:42 +04:00
|
|
|
CMSWindowsPrimaryScreen::mapButton(WPARAM msg, LPARAM button) const
|
2001-11-19 03:33:36 +03:00
|
|
|
{
|
2003-05-05 01:40:42 +04:00
|
|
|
switch (msg) {
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_LBUTTONDOWN:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_LBUTTONDBLCLK:
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_LBUTTONUP:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_NCLBUTTONDOWN:
|
|
|
|
case WM_NCLBUTTONDBLCLK:
|
|
|
|
case WM_NCLBUTTONUP:
|
2001-11-19 03:33:36 +03:00
|
|
|
return kButtonLeft;
|
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_MBUTTONDOWN:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_MBUTTONDBLCLK:
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_MBUTTONUP:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_NCMBUTTONDOWN:
|
|
|
|
case WM_NCMBUTTONDBLCLK:
|
|
|
|
case WM_NCMBUTTONUP:
|
2001-11-19 03:33:36 +03:00
|
|
|
return kButtonMiddle;
|
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_RBUTTONDOWN:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_RBUTTONDBLCLK:
|
2002-04-29 18:40:01 +04:00
|
|
|
case WM_RBUTTONUP:
|
2003-05-03 16:54:22 +04:00
|
|
|
case WM_NCRBUTTONDOWN:
|
|
|
|
case WM_NCRBUTTONDBLCLK:
|
|
|
|
case WM_NCRBUTTONUP:
|
2001-11-19 03:33:36 +03:00
|
|
|
return kButtonRight;
|
|
|
|
|
2003-05-05 01:40:42 +04:00
|
|
|
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;
|
|
|
|
|
2002-04-29 18:40:01 +04:00
|
|
|
default:
|
2001-11-19 03:33:36 +03:00
|
|
|
return kButtonNone;
|
|
|
|
}
|
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
void
|
|
|
|
CMSWindowsPrimaryScreen::updateKeys()
|
2002-04-30 20:23:03 +04:00
|
|
|
{
|
2002-05-22 21:01:17 +04:00
|
|
|
// not using GetKeyboardState() because that doesn't seem to give
|
|
|
|
// up-to-date results. i don't know why that is or why GetKeyState()
|
|
|
|
// should give different results.
|
|
|
|
|
2003-05-05 01:40:42 +04:00
|
|
|
// clear key and button state
|
2002-04-30 20:23:03 +04:00
|
|
|
memset(m_keys, 0, sizeof(m_keys));
|
2003-05-05 01:40:42 +04:00
|
|
|
memset(m_buttons, 0, sizeof(m_buttons));
|
2002-04-30 20:23:03 +04:00
|
|
|
|
2002-07-01 19:05:49 +04:00
|
|
|
// we only care about the modifier key states. other keys and the
|
|
|
|
// mouse buttons should be up.
|
2003-05-26 13:46:52 +04:00
|
|
|
// sometimes these seem to be out of date so, to avoid getting
|
|
|
|
// locked to a screen unexpectedly, just assume the non-toggle
|
|
|
|
// modifier keys are up.
|
|
|
|
/*
|
2002-09-02 21:30:04 +04:00
|
|
|
m_keys[VK_LSHIFT] = static_cast<BYTE>(GetKeyState(VK_LSHIFT) & 0x80);
|
|
|
|
m_keys[VK_RSHIFT] = static_cast<BYTE>(GetKeyState(VK_RSHIFT) & 0x80);
|
|
|
|
m_keys[VK_SHIFT] = static_cast<BYTE>(GetKeyState(VK_SHIFT) & 0x80);
|
|
|
|
m_keys[VK_LCONTROL] = static_cast<BYTE>(GetKeyState(VK_LCONTROL) & 0x80);
|
|
|
|
m_keys[VK_RCONTROL] = static_cast<BYTE>(GetKeyState(VK_RCONTROL) & 0x80);
|
|
|
|
m_keys[VK_CONTROL] = static_cast<BYTE>(GetKeyState(VK_CONTROL) & 0x80);
|
|
|
|
m_keys[VK_LMENU] = static_cast<BYTE>(GetKeyState(VK_LMENU) & 0x80);
|
|
|
|
m_keys[VK_RMENU] = static_cast<BYTE>(GetKeyState(VK_RMENU) & 0x80);
|
|
|
|
m_keys[VK_MENU] = static_cast<BYTE>(GetKeyState(VK_MENU) & 0x80);
|
|
|
|
m_keys[VK_LWIN] = static_cast<BYTE>(GetKeyState(VK_LWIN) & 0x80);
|
|
|
|
m_keys[VK_RWIN] = static_cast<BYTE>(GetKeyState(VK_RWIN) & 0x80);
|
|
|
|
m_keys[VK_APPS] = static_cast<BYTE>(GetKeyState(VK_APPS) & 0x80);
|
2003-05-26 13:46:52 +04:00
|
|
|
*/
|
2002-05-22 21:01:17 +04:00
|
|
|
m_keys[VK_CAPITAL] = static_cast<BYTE>(GetKeyState(VK_CAPITAL));
|
|
|
|
m_keys[VK_NUMLOCK] = static_cast<BYTE>(GetKeyState(VK_NUMLOCK));
|
|
|
|
m_keys[VK_SCROLL] = static_cast<BYTE>(GetKeyState(VK_SCROLL));
|
2002-04-30 20:23:03 +04:00
|
|
|
}
|
|
|
|
|
2002-06-11 02:06:45 +04:00
|
|
|
void
|
2002-06-17 17:31:21 +04:00
|
|
|
CMSWindowsPrimaryScreen::updateKey(UINT vkCode, bool press)
|
2002-04-30 20:23:03 +04:00
|
|
|
{
|
|
|
|
if (press) {
|
|
|
|
switch (vkCode) {
|
2003-05-26 13:46:52 +04:00
|
|
|
case 0:
|
|
|
|
case VK_LBUTTON:
|
|
|
|
case VK_MBUTTON:
|
|
|
|
case VK_RBUTTON:
|
|
|
|
// ignore bogus key
|
|
|
|
break;
|
|
|
|
|
2002-04-30 20:23:03 +04:00
|
|
|
case VK_LSHIFT:
|
|
|
|
case VK_RSHIFT:
|
|
|
|
case VK_SHIFT:
|
|
|
|
m_keys[vkCode] |= 0x80;
|
|
|
|
m_keys[VK_SHIFT] |= 0x80;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LCONTROL:
|
|
|
|
case VK_RCONTROL:
|
|
|
|
case VK_CONTROL:
|
|
|
|
m_keys[vkCode] |= 0x80;
|
|
|
|
m_keys[VK_CONTROL] |= 0x80;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LMENU:
|
|
|
|
case VK_RMENU:
|
|
|
|
case VK_MENU:
|
|
|
|
m_keys[vkCode] |= 0x80;
|
|
|
|
m_keys[VK_MENU] |= 0x80;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_CAPITAL:
|
|
|
|
case VK_NUMLOCK:
|
|
|
|
case VK_SCROLL:
|
|
|
|
// toggle keys
|
|
|
|
m_keys[vkCode] |= 0x80;
|
|
|
|
break;
|
2002-07-01 17:00:12 +04:00
|
|
|
|
|
|
|
default:
|
|
|
|
case VK_LWIN:
|
|
|
|
case VK_RWIN:
|
|
|
|
case VK_APPS:
|
|
|
|
m_keys[vkCode] |= 0x80;
|
|
|
|
break;
|
2002-04-30 20:23:03 +04:00
|
|
|
}
|
2003-05-26 13:46:52 +04:00
|
|
|
|
|
|
|
// special case: we detect ctrl+alt+del being pressed on some
|
|
|
|
// systems but we don't detect the release of those keys. so
|
|
|
|
// if ctrl, alt, and del are down then mark them up.
|
|
|
|
if ((m_keys[VK_CONTROL] & 0x80) != 0 &&
|
|
|
|
(m_keys[VK_MENU] & 0x80) != 0 &&
|
|
|
|
(m_keys[VK_DELETE] & 0x80) != 0) {
|
|
|
|
m_keys[VK_LCONTROL] &= ~0x80;
|
|
|
|
m_keys[VK_RCONTROL] &= ~0x80;
|
|
|
|
m_keys[VK_CONTROL] &= ~0x80;
|
|
|
|
m_keys[VK_LMENU] &= ~0x80;
|
|
|
|
m_keys[VK_RMENU] &= ~0x80;
|
|
|
|
m_keys[VK_MENU] &= ~0x80;
|
|
|
|
m_keys[VK_DELETE] &= ~0x80;
|
|
|
|
}
|
2002-04-30 20:23:03 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch (vkCode) {
|
2003-05-26 13:46:52 +04:00
|
|
|
case 0:
|
|
|
|
case VK_LBUTTON:
|
|
|
|
case VK_MBUTTON:
|
|
|
|
case VK_RBUTTON:
|
|
|
|
// ignore bogus key
|
|
|
|
break;
|
|
|
|
|
2002-04-30 20:23:03 +04:00
|
|
|
case VK_LSHIFT:
|
|
|
|
case VK_RSHIFT:
|
|
|
|
case VK_SHIFT:
|
|
|
|
m_keys[vkCode] &= ~0x80;
|
|
|
|
if (((m_keys[VK_LSHIFT] | m_keys[VK_RSHIFT]) & 0x80) == 0) {
|
|
|
|
m_keys[VK_SHIFT] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LCONTROL:
|
|
|
|
case VK_RCONTROL:
|
|
|
|
case VK_CONTROL:
|
|
|
|
m_keys[vkCode] &= ~0x80;
|
|
|
|
if (((m_keys[VK_LCONTROL] | m_keys[VK_RCONTROL]) & 0x80) == 0) {
|
|
|
|
m_keys[VK_CONTROL] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_LMENU:
|
|
|
|
case VK_RMENU:
|
|
|
|
case VK_MENU:
|
|
|
|
m_keys[vkCode] &= ~0x80;
|
|
|
|
if (((m_keys[VK_LMENU] | m_keys[VK_RMENU]) & 0x80) == 0) {
|
|
|
|
m_keys[VK_MENU] &= ~0x80;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_CAPITAL:
|
|
|
|
case VK_NUMLOCK:
|
|
|
|
case VK_SCROLL:
|
|
|
|
// toggle keys
|
2002-07-01 17:00:12 +04:00
|
|
|
m_keys[vkCode] &= ~0x80;
|
|
|
|
m_keys[vkCode] ^= 0x01;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
case VK_LWIN:
|
|
|
|
case VK_RWIN:
|
|
|
|
case VK_APPS:
|
|
|
|
m_keys[vkCode] &= ~0x80;
|
2002-04-30 20:23:03 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Fixed several win32 bugs. First, synergy wasn't forwarding mouse
events to other hook functions, which broke some tools like objectbar.
Second, windows key processing was fixed. Previously pressing and
release the key would only send a press event, locking the user onto
the client window; also, the win32 server treated as a Meta modifier
instead of a Super modifier, which broke any use of it as any kind of
modifier key. Third, added hacks to support several key combinations
on windows 95/98/me that are treated specially by windows, including
Alt+Tab, Alt+Shift+Tab, Alt+Esc, Alt+Shift+Esc, Ctrl+Esc, and any
combination using the windows key like Win+E and Win+F but not
Ctrl+Alt+Del. Fourth, scroll lock only locking to the client (which
only happened when using a synergy server on windows) has been fixed;
unfortunately the solution causes a lot of screen redraws for some
reason. Finally, there's been a fix to clipboard handling that may
or may not fix a problem where the clipboard would stop transferring
between systems after a little while. I can't be sure if it fixes
the problem because I can't reproduce the problem.
2003-04-13 18:59:53 +04:00
|
|
|
|
|
|
|
bool
|
|
|
|
CMSWindowsPrimaryScreen::isModifier(UINT vkCode) const
|
|
|
|
|
|
|
|
{
|
|
|
|
switch (vkCode) {
|
|
|
|
case VK_LSHIFT:
|
|
|
|
case VK_RSHIFT:
|
|
|
|
case VK_SHIFT:
|
|
|
|
case VK_LCONTROL:
|
|
|
|
case VK_RCONTROL:
|
|
|
|
case VK_CONTROL:
|
|
|
|
case VK_LMENU:
|
|
|
|
case VK_RMENU:
|
|
|
|
case VK_MENU:
|
|
|
|
case VK_CAPITAL:
|
|
|
|
case VK_NUMLOCK:
|
|
|
|
case VK_SCROLL:
|
|
|
|
case VK_LWIN:
|
|
|
|
case VK_RWIN:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|