checkpoint. refactored win32 code. had to edit and rename some

files so this is only a checkpoint.
This commit is contained in:
crs
2002-07-15 15:01:36 +00:00
parent f48a5fe387
commit 4b46862026
33 changed files with 1210 additions and 1661 deletions

View File

@@ -1,12 +1,8 @@
#include "CMSWindowsSecondaryScreen.h"
#include "IScreenReceiver.h"
#include "CClipboard.h"
#include "CMSWindowsClipboard.h"
#include "CMSWindowsScreenSaver.h"
#include "CMSWindowsScreen.h"
#include "CPlatform.h"
#include "XScreen.h"
#include "CLock.h"
#include "CThread.h"
#include "CLog.h"
#include <cctype>
@@ -24,155 +20,18 @@
CMSWindowsSecondaryScreen::CMSWindowsSecondaryScreen(
IScreenReceiver* receiver) :
m_receiver(receiver),
m_threadID(0),
m_lastThreadID(0),
m_desk(NULL),
m_deskName(),
m_is95Family(CPlatform::isWindows95Family()),
m_window(NULL),
m_active(false),
m_nextClipboardWindow(NULL)
m_mask(0)
{
assert(m_receiver != NULL);
m_is95Family = CPlatform::isWindows95Family();
// make sure this thread has a message queue
MSG dummy;
PeekMessage(&dummy, NULL, WM_USER, WM_USER, PM_NOREMOVE);
m_screen = new CMSWindowsScreen(receiver, this);
}
CMSWindowsSecondaryScreen::~CMSWindowsSecondaryScreen()
{
assert(m_window == NULL);
}
void
CMSWindowsSecondaryScreen::run()
{
assert(m_window != NULL);
// must call run() from same thread as open()
assert(m_threadID == GetCurrentThreadId());
// change our priority
CThread::getCurrentThread().setPriority(-7);
// run event loop
try {
log((CLOG_INFO "entering event loop"));
mainLoop();
log((CLOG_INFO "exiting event loop"));
}
catch (...) {
log((CLOG_INFO "exiting event loop"));
throw;
}
}
void
CMSWindowsSecondaryScreen::stop()
{
exitMainLoop();
}
void
CMSWindowsSecondaryScreen::open()
{
assert(m_window == NULL);
try {
// open the display
openDisplay();
// create and prepare our window
createWindow();
// initialize the clipboards; assume primary has all clipboards
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
grabClipboard(id);
}
// get keyboard state
updateKeys();
updateModifiers();
// disable the screen saver
installScreenSaver();
}
catch (...) {
close();
throw;
}
// hide the cursor
m_active = true;
leave();
}
void
CMSWindowsSecondaryScreen::close()
{
uninstallScreenSaver();
destroyWindow();
closeDisplay();
}
void
CMSWindowsSecondaryScreen::enter(SInt32 x, SInt32 y, KeyModifierMask mask)
{
CLock lock(&m_mutex);
assert(m_window != NULL);
assert(m_active == false);
log((CLOG_INFO "entering screen at %d,%d mask=%04x", x, y, mask));
syncDesktop();
// now active
m_active = true;
// update our keyboard state to reflect the local state
updateKeys();
updateModifiers();
// toggle modifiers that don't match the desired state
if ((mask & KeyModifierCapsLock) != (m_mask & KeyModifierCapsLock)) {
toggleKey(VK_CAPITAL, KeyModifierCapsLock);
}
if ((mask & KeyModifierNumLock) != (m_mask & KeyModifierNumLock)) {
toggleKey(VK_NUMLOCK | 0x100, KeyModifierNumLock);
}
if ((mask & KeyModifierScrollLock) != (m_mask & KeyModifierScrollLock)) {
toggleKey(VK_SCROLL, KeyModifierScrollLock);
}
// warp to requested location
warpCursor(x, y);
// show mouse
hideWindow();
}
void
CMSWindowsSecondaryScreen::leave()
{
CLock lock(&m_mutex);
assert(m_window != NULL);
assert(m_active == true);
log((CLOG_INFO "leaving screen"));
syncDesktop();
// hide mouse
showWindow();
// not active anymore
m_active = false;
// make sure our idea of clipboard ownership is correct
checkClipboard();
delete m_screen;
}
void
@@ -182,8 +41,7 @@ CMSWindowsSecondaryScreen::keyDown(KeyID key, KeyModifierMask mask)
UINT virtualKey;
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
m_screen->syncDesktop();
// get the sequence of keys to simulate key press and the final
// modifier state.
@@ -223,8 +81,7 @@ CMSWindowsSecondaryScreen::keyRepeat(KeyID key,
UINT virtualKey;
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
m_screen->syncDesktop();
// get the sequence of keys to simulate key repeat and the final
// modifier state.
@@ -244,8 +101,7 @@ CMSWindowsSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask)
UINT virtualKey;
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
m_screen->syncDesktop();
// get the sequence of keys to simulate key release and the final
// modifier state.
@@ -302,8 +158,7 @@ void
CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
{
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
m_screen->syncDesktop();
// map button id to button flag
DWORD flags = mapButton(button, true);
@@ -318,8 +173,7 @@ void
CMSWindowsSecondaryScreen::mouseUp(ButtonID button)
{
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
m_screen->syncDesktop();
// map button id to button flag
DWORD flags = mapButton(button, false);
@@ -334,8 +188,7 @@ void
CMSWindowsSecondaryScreen::mouseMove(SInt32 x, SInt32 y)
{
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
m_screen->syncDesktop();
warpCursor(x, y);
}
@@ -343,61 +196,50 @@ void
CMSWindowsSecondaryScreen::mouseWheel(SInt32 delta)
{
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
m_screen->syncDesktop();
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, 0);
}
void
CMSWindowsSecondaryScreen::setClipboard(ClipboardID /*id*/,
const IClipboard* src)
IScreen*
CMSWindowsSecondaryScreen::getScreen() const
{
CLock lock(&m_mutex);
assert(m_window != NULL);
CMSWindowsClipboard dst(m_window);
CClipboard::copy(&dst, src);
return m_screen;
}
void
CMSWindowsSecondaryScreen::grabClipboard(ClipboardID /*id*/)
CMSWindowsSecondaryScreen::onError()
{
CLock lock(&m_mutex);
assert(m_window != NULL);
// ignore
}
CMSWindowsClipboard clipboard(m_window);
if (clipboard.open(0)) {
clipboard.close();
void
CMSWindowsSecondaryScreen::onScreensaver(bool)
{
// ignore
}
bool
CMSWindowsSecondaryScreen::onPreDispatch(const CEvent*)
{
return false;
}
bool
CMSWindowsSecondaryScreen::onEvent(CEvent* event)
{
assert(event != NULL);
const MSG& msg = event->m_msg;
switch (msg.message) {
case WM_ACTIVATEAPP:
if (msg.wParam == FALSE) {
// some other app activated. hide the hider window.
ShowWindow(m_window, SW_HIDE);
}
break;
}
}
void
CMSWindowsSecondaryScreen::screenSaver(bool activate)
{
if (activate) {
getScreenSaver()->activate();
}
else {
getScreenSaver()->deactivate();
}
}
void
CMSWindowsSecondaryScreen::getMousePos(SInt32& x, SInt32& y) const
{
CLock lock(&m_mutex);
assert(m_window != NULL);
syncDesktop();
getCursorPos(x, y);
}
void
CMSWindowsSecondaryScreen::getShape(
SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
{
getScreenShape(x, y, w, h);
return false;
}
SInt32
@@ -407,153 +249,63 @@ CMSWindowsSecondaryScreen::getJumpZoneSize() const
}
void
CMSWindowsSecondaryScreen::getClipboard(ClipboardID /*id*/,
IClipboard* dst) const
CMSWindowsSecondaryScreen::postCreateWindow(HWND window)
{
m_window = window;
if (!isActive()) {
showWindow();
}
}
void
CMSWindowsSecondaryScreen::preDestroyWindow(HWND)
{
// do nothing
}
void
CMSWindowsSecondaryScreen::onPreRun()
{
CLock lock(&m_mutex);
assert(m_window != NULL);
CMSWindowsClipboard src(m_window);
CClipboard::copy(dst, &src);
}
bool
CMSWindowsSecondaryScreen::onPreDispatch(const CEvent* event)
void
CMSWindowsSecondaryScreen::onPreOpen()
{
assert(event != NULL);
// forward to superclass
if (CMSWindowsScreen::onPreDispatch(event)) {
return true;
}
// handle event
const MSG* msg = &event->m_msg;
switch (msg->message) {
case WM_TIMER:
// if current desktop is not the input desktop then switch to it
if (!m_is95Family) {
HDESK desk = openInputDesktop();
if (desk != NULL) {
if (isCurrentDesktop(desk)) {
CloseDesktop(desk);
}
else {
switchDesktop(desk);
}
}
}
return true;
}
return false;
assert(m_window == NULL);
}
bool
CMSWindowsSecondaryScreen::onEvent(CEvent* event)
void
CMSWindowsSecondaryScreen::onPreEnter()
{
assert(event != NULL);
const MSG& msg = event->msg;
switch (msg.message) {
case WM_QUERYENDSESSION:
if (m_is95Family) {
event->m_result = TRUE;
return true;
}
break;
case WM_ENDSESSION:
if (m_is95Family) {
if (msg.wParam == TRUE && msg.lParam == 0) {
stop();
}
return true;
}
break;
case WM_PAINT:
ValidateRect(msg.hwnd, NULL);
return true;
case WM_ACTIVATEAPP:
if (msg.wParam == FALSE) {
// some other app activated. hide the hider window.
ShowWindow(m_window, SW_HIDE);
}
break;
case WM_DRAWCLIPBOARD:
log((CLOG_DEBUG "clipboard was taken"));
// first pass it on
if (m_nextClipboardWindow != NULL) {
SendMessage(m_nextClipboardWindow,
msg.message, msg.wParam, msg.lParam);
}
// now notify client that somebody changed the clipboard (unless
// we're now the owner, in which case it's because we took
// ownership, or now it's owned by nobody, which will happen if
// we owned it and switched desktops because we destroy our
// window to do that).
try {
m_clipboardOwner = GetClipboardOwner();
if (m_clipboardOwner != m_window && m_clipboardOwner != NULL) {
m_receiver->onGrabClipboard(kClipboardClipboard);
m_receiver->onGrabClipboard(kClipboardSelection);
}
}
catch (XBadClient&) {
// ignore. this can happen if we receive this event
// before we've fully started up.
}
return true;
case WM_CHANGECBCHAIN:
if (m_nextClipboardWindow == (HWND)msg.wParam) {
m_nextClipboardWindow = (HWND)msg.lParam;
}
else if (m_nextClipboardWindow != NULL) {
SendMessage(m_nextClipboardWindow,
msg.message, msg.wParam, msg.lParam);
}
return true;
case WM_DISPLAYCHANGE:
{
// screen resolution may have changed. get old shape.
SInt32 xOld, yOld, wOld, hOld;
getScreenShape(xOld, yOld, wOld, hOld);
// update shape
updateScreenShape();
m_multimon = isMultimon();
// collect new screen info
CClientInfo info;
getScreenShape(info.m_x, info.m_y, info.m_w, info.m_h);
getCursorPos(info.m_mx, info.m_my);
info.m_zoneSize = getJumpZoneSize();
// do nothing if resolution hasn't changed
if (info.m_x != xOld || info.m_y != yOld ||
info.m_w != wOld || info.m_h != hOld) {
// send new screen info
m_receiver->onInfoChanged(info);
}
return true;
}
}
return false;
assert(m_window != NULL);
}
CString
CMSWindowsSecondaryScreen::getCurrentDesktopName() const
void
CMSWindowsSecondaryScreen::onPreLeave()
{
return m_deskName;
assert(m_window != NULL);
}
void
CMSWindowsSecondaryScreen::createWindow()
{
// open the desktop and the window
m_window = m_screen->openDesktop();
if (m_window == NULL) {
throw XScreenOpenFailure();
}
}
void
CMSWindowsSecondaryScreen::destroyWindow()
{
// release keys that are logically pressed
releaseKeys();
// close the desktop and the window
m_screen->closeDesktop();
m_window = NULL;
}
void
@@ -580,9 +332,9 @@ CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
{
// move the mouse directly to target position on NT family or if
// not using multiple monitors.
if (!m_multimon || !m_is95Family) {
if (m_screen->isMultimon() || !m_is95Family) {
SInt32 x0, y0, w, h;
getScreenShape(x0, y0, w, h);
m_screen->getShape(x0, y0, w, h);
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
(DWORD)((65535.99 * (x - x0)) / (w - 1)),
(DWORD)((65535.99 * (y - y0)) / (h - 1)),
@@ -653,259 +405,70 @@ CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
}
void
CMSWindowsSecondaryScreen::checkClipboard()
CMSWindowsSecondaryScreen::updateKeys()
{
// if we think we own the clipboard but we don't then somebody
// grabbed the clipboard on this screen without us knowing.
// tell the server that this screen grabbed the clipboard.
//
// this works around bugs in the clipboard viewer chain.
// sometimes NT will simply never send WM_DRAWCLIPBOARD
// messages for no apparent reason and rebooting fixes the
// problem. since we don't want a broken clipboard until the
// next reboot we do this double check. clipboard ownership
// won't be reflected on other screens until we leave but at
// least the clipboard itself will work.
HWND clipboardOwner = GetClipboardOwner();
if (m_clipboardOwner != clipboardOwner) {
try {
m_clipboardOwner = clipboardOwner;
if (m_clipboardOwner != m_window && m_clipboardOwner != NULL) {
m_receiver->onGrabClipboard(kClipboardClipboard);
m_receiver->onGrabClipboard(kClipboardSelection);
}
}
catch (XBadClient&) {
// ignore
}
// clear key state
memset(m_keys, 0, sizeof(m_keys));
// we only care about the modifier key states
m_keys[VK_LSHIFT] = static_cast<BYTE>(GetKeyState(VK_LSHIFT));
m_keys[VK_RSHIFT] = static_cast<BYTE>(GetKeyState(VK_RSHIFT));
m_keys[VK_SHIFT] = static_cast<BYTE>(GetKeyState(VK_SHIFT));
m_keys[VK_LCONTROL] = static_cast<BYTE>(GetKeyState(VK_LCONTROL));
m_keys[VK_RCONTROL] = static_cast<BYTE>(GetKeyState(VK_RCONTROL));
m_keys[VK_CONTROL] = static_cast<BYTE>(GetKeyState(VK_CONTROL));
m_keys[VK_LMENU] = static_cast<BYTE>(GetKeyState(VK_LMENU));
m_keys[VK_RMENU] = static_cast<BYTE>(GetKeyState(VK_RMENU));
m_keys[VK_MENU] = static_cast<BYTE>(GetKeyState(VK_MENU));
m_keys[VK_LWIN] = static_cast<BYTE>(GetKeyState(VK_LWIN));
m_keys[VK_RWIN] = static_cast<BYTE>(GetKeyState(VK_RWIN));
m_keys[VK_APPS] = static_cast<BYTE>(GetKeyState(VK_APPS));
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));
// update active modifier mask
m_mask = 0;
if ((m_keys[VK_LSHIFT] & 0x80) != 0 || (m_keys[VK_RSHIFT] & 0x80) != 0) {
m_mask |= KeyModifierShift;
}
if ((m_keys[VK_LCONTROL] & 0x80) != 0 ||
(m_keys[VK_RCONTROL] & 0x80) != 0) {
m_mask |= KeyModifierControl;
}
if ((m_keys[VK_LMENU] & 0x80) != 0 || (m_keys[VK_RMENU] & 0x80) != 0) {
m_mask |= KeyModifierAlt;
}
if ((m_keys[VK_LWIN] & 0x80) != 0 || (m_keys[VK_RWIN] & 0x80) != 0) {
m_mask |= KeyModifierMeta;
}
if ((m_keys[VK_CAPITAL] & 0x01) != 0) {
m_mask |= KeyModifierCapsLock;
}
if ((m_keys[VK_NUMLOCK] & 0x01) != 0) {
m_mask |= KeyModifierNumLock;
}
if ((m_keys[VK_SCROLL] & 0x01) != 0) {
m_mask |= KeyModifierScrollLock;
}
log((CLOG_DEBUG2 "modifiers on update: 0x%04x", m_mask));
}
void
CMSWindowsPrimaryScreen::createWindow()
CMSWindowsSecondaryScreen::setToggleState(KeyModifierMask mask)
{
// save thread id
m_threadID = GetCurrentThreadId();
// note if using multiple monitors
m_multimon = isMultimon();
// get the input desktop and switch to it
if (m_is95Family) {
if (!openDesktop()) {
throw XScreenOpenFailure();
}
// toggle modifiers that don't match the desired state
if ((mask & KeyModifierCapsLock) != (m_mask & KeyModifierCapsLock)) {
toggleKey(VK_CAPITAL, KeyModifierCapsLock);
}
else {
if (!switchDesktop(openInputDesktop())) {
throw XScreenOpenFailure();
}
if ((mask & KeyModifierNumLock) != (m_mask & KeyModifierNumLock)) {
toggleKey(VK_NUMLOCK | 0x100, KeyModifierNumLock);
}
// poll input desktop to see if it changes (onPreDispatch()
// handles WM_TIMER)
m_timer = 0;
if (!m_is95Family) {
m_timer = SetTimer(NULL, 0, 200, NULL);
if ((mask & KeyModifierScrollLock) != (m_mask & KeyModifierScrollLock)) {
toggleKey(VK_SCROLL, KeyModifierScrollLock);
}
}
void
CMSWindowsPrimaryScreen::destroyWindow()
{
// remove timer
if (m_timer != 0) {
KillTimer(NULL, m_timer);
}
// release keys that are logically pressed
releaseKeys();
// disconnect from desktop
if (m_is95Family) {
closeDesktop();
}
else {
switchDesktop(NULL);
}
// clear thread id
m_threadID = 0;
assert(m_window == NULL);
assert(m_desk == NULL);
}
void
CMSWindowsSecondaryScreen::installScreenSaver()
{
getScreenSaver()->disable();
}
void
CMSWindowsSecondaryScreen::uninstallScreenSaver()
{
getScreenSaver()->enable();
}
bool
CMSWindowsSecondaryScreen::openDesktop()
{
CLock lock(&m_mutex);
// initialize clipboard owner to current owner. we don't want
// to take ownership of the clipboard just by starting up.
m_clipboardOwner = GetClipboardOwner();
// create the cursor hiding window. this window is used to hide the
// cursor when it's not on the screen. the window is hidden as soon
// as the cursor enters the screen or the display's real cursor is
// moved.
m_window = CreateWindowEx(WS_EX_TOPMOST |
WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
(LPCTSTR)getClass(), "Synergy",
WS_POPUP,
0, 0, 1, 1, NULL, NULL,
getInstance(),
NULL);
// install our clipboard snooper
m_nextClipboardWindow = SetClipboardViewer(m_window);
return true;
}
void
CMSWindowsSecondaryScreen::closeDesktop()
{
CLock lock(&m_mutex);
if (m_window != NULL) {
// remove clipboard snooper
ChangeClipboardChain(m_window, m_nextClipboardWindow);
m_nextClipboardWindow = NULL;
// destroy window
DestroyWindow(m_window);
m_window = NULL;
}
}
bool
CMSWindowsSecondaryScreen::switchDesktop(HDESK desk)
{
CLock lock(&m_mutex);
bool ownClipboard = false;
if (m_window != NULL) {
// note if we own the clipboard
ownClipboard = (m_clipboardOwner == m_window);
// remove clipboard snooper
ChangeClipboardChain(m_window, m_nextClipboardWindow);
m_nextClipboardWindow = NULL;
// destroy window
DestroyWindow(m_window);
m_window = NULL;
}
// done with desktop
if (m_desk != NULL) {
CloseDesktop(m_desk);
m_desk = NULL;
m_deskName = "";
}
// if no new desktop then we're done
if (desk == NULL) {
log((CLOG_INFO "disconnecting desktop"));
return true;
}
// set the desktop. can only do this when there are no windows
// and hooks on the current desktop owned by this thread.
if (SetThreadDesktop(desk) == 0) {
log((CLOG_ERR "failed to set desktop: %d", GetLastError()));
CloseDesktop(desk);
return false;
}
// initialize clipboard owner to current owner. we don't want
// to take ownership of the clipboard just by starting up.
m_clipboardOwner = GetClipboardOwner();
// create the cursor hiding window. this window is used to hide the
// cursor when it's not on the screen. the window is hidden as soon
// as the cursor enters the screen or the display's real cursor is
// moved.
m_window = CreateWindowEx(WS_EX_TOPMOST |
WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
(LPCTSTR)getClass(), "Synergy",
WS_POPUP,
0, 0, 1, 1, NULL, NULL,
getInstance(),
NULL);
if (m_window == NULL) {
log((CLOG_ERR "failed to create window: %d", GetLastError()));
CloseDesktop(desk);
return false;
}
// install our clipboard snooper
m_nextClipboardWindow = SetClipboardViewer(m_window);
// if we owned the desktop then set the clipboard owner
if (ownClipboard) {
m_clipboardOwner = GetClipboardOwner();
}
// save new desktop
m_desk = desk;
m_deskName = getDesktopName(m_desk);
log((CLOG_INFO "switched to desktop %s", m_deskName.c_str()));
// get desktop up to date
if (!m_active) {
showWindow();
}
return true;
}
void
CMSWindowsSecondaryScreen::syncDesktop() const
{
// note -- mutex must be locked on entry
// change calling thread's desktop
if (!m_is95Family) {
if (SetThreadDesktop(m_desk) == 0) {
log((CLOG_WARN "failed to set desktop: %d", GetLastError()));
}
}
// attach input queues if not already attached. this has a habit
// of sucking up more and more CPU each time it's called (even if
// the threads are already attached). since we only expect one
// thread to call this more than once we can save just the last
// the attached thread.
DWORD threadID = GetCurrentThreadId();
if (threadID != m_lastThreadID && threadID != m_threadID) {
m_lastThreadID = threadID;
AttachThreadInput(threadID, m_threadID, TRUE);
}
}
bool
CMSWindowsSecondaryScreen::isMultimon() const
{
SInt32 x0, y0, w, h;
getScreenShape(x0, y0, w, h);
return (w != GetSystemMetrics(SM_CXSCREEN) ||
h != GetSystemMetrics(SM_CYSCREEN));
}
// these tables map KeyID (a X windows KeySym) to virtual key codes.
// if the key is an extended key then the entry is the virtual key
// code | 0x100. keys that map to normal characters have a 0 entry
@@ -1768,7 +1331,7 @@ CMSWindowsSecondaryScreen::releaseKeys()
{
CLock lock(&m_mutex);
syncDesktop();
m_screen->syncDesktop();
// release left/right modifier keys first. if the platform doesn't
// support them then they won't be set and the non-side-distinuishing
@@ -1814,60 +1377,6 @@ CMSWindowsSecondaryScreen::releaseKeys()
}
}
void
CMSWindowsSecondaryScreen::updateKeys()
{
// clear key state
memset(m_keys, 0, sizeof(m_keys));
// we only care about the modifier key states
m_keys[VK_LSHIFT] = static_cast<BYTE>(GetKeyState(VK_LSHIFT));
m_keys[VK_RSHIFT] = static_cast<BYTE>(GetKeyState(VK_RSHIFT));
m_keys[VK_SHIFT] = static_cast<BYTE>(GetKeyState(VK_SHIFT));
m_keys[VK_LCONTROL] = static_cast<BYTE>(GetKeyState(VK_LCONTROL));
m_keys[VK_RCONTROL] = static_cast<BYTE>(GetKeyState(VK_RCONTROL));
m_keys[VK_CONTROL] = static_cast<BYTE>(GetKeyState(VK_CONTROL));
m_keys[VK_LMENU] = static_cast<BYTE>(GetKeyState(VK_LMENU));
m_keys[VK_RMENU] = static_cast<BYTE>(GetKeyState(VK_RMENU));
m_keys[VK_MENU] = static_cast<BYTE>(GetKeyState(VK_MENU));
m_keys[VK_LWIN] = static_cast<BYTE>(GetKeyState(VK_LWIN));
m_keys[VK_RWIN] = static_cast<BYTE>(GetKeyState(VK_RWIN));
m_keys[VK_APPS] = static_cast<BYTE>(GetKeyState(VK_APPS));
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));
}
void
CMSWindowsSecondaryScreen::updateModifiers()
{
// update active modifier mask
m_mask = 0;
if ((m_keys[VK_LSHIFT] & 0x80) != 0 || (m_keys[VK_RSHIFT] & 0x80) != 0) {
m_mask |= KeyModifierShift;
}
if ((m_keys[VK_LCONTROL] & 0x80) != 0 ||
(m_keys[VK_RCONTROL] & 0x80) != 0) {
m_mask |= KeyModifierControl;
}
if ((m_keys[VK_LMENU] & 0x80) != 0 || (m_keys[VK_RMENU] & 0x80) != 0) {
m_mask |= KeyModifierAlt;
}
if ((m_keys[VK_LWIN] & 0x80) != 0 || (m_keys[VK_RWIN] & 0x80) != 0) {
m_mask |= KeyModifierMeta;
}
if ((m_keys[VK_CAPITAL] & 0x01) != 0) {
m_mask |= KeyModifierCapsLock;
}
if ((m_keys[VK_NUMLOCK] & 0x01) != 0) {
m_mask |= KeyModifierNumLock;
}
if ((m_keys[VK_SCROLL] & 0x01) != 0) {
m_mask |= KeyModifierScrollLock;
}
log((CLOG_DEBUG2 "modifiers on update: 0x%04x", m_mask));
}
void
CMSWindowsSecondaryScreen::toggleKey(UINT virtualKey, KeyModifierMask mask)
{