added screen locking support to win32. added support for

resolution changing (only semi-supported on X because that
has no means for resizing screen anyway).  also fixed some
clipboard problems on win32.
This commit is contained in:
crs 2002-05-24 17:54:28 +00:00
parent 34c587e864
commit 5fc87baa0f
19 changed files with 253 additions and 40 deletions

View File

@ -32,7 +32,8 @@ CClient::CClient(const CString& clientName) :
m_output(NULL),
m_screen(NULL),
m_active(false),
m_seqNum(0)
m_seqNum(0),
m_ignoreMove(false)
{
// do nothing
}
@ -106,7 +107,7 @@ void CClient::onClipboardChanged(ClipboardID id)
m_timeClipboard[id] = 0;
// if we're not the active screen then send the clipboard now,
// otherwise we'll until we leave.
// otherwise we'll wait until we leave.
if (!m_active) {
// get clipboard
CClipboard clipboard;
@ -127,6 +128,19 @@ void CClient::onClipboardChanged(ClipboardID id)
}
}
void CClient::onResolutionChanged()
{
log((CLOG_DEBUG "resolution changed"));
CLock lock(&m_mutex);
// start ignoring mouse movement until we get an acknowledgment
m_ignoreMove = true;
// send notification of resolution change
onQueryInfoNoLock();
}
#include "CTCPSocket.h" // FIXME
void CClient::runSession(void*)
{
@ -261,6 +275,9 @@ void CClient::runSession(void*)
else if (memcmp(code, kMsgQInfo, 4) == 0) {
onQueryInfo();
}
else if (memcmp(code, kMsgCInfoAck, 4) == 0) {
onInfoAcknowledgment();
}
else if (memcmp(code, kMsgDClipboard, 4) == 0) {
onSetClipboard();
}
@ -399,10 +416,13 @@ void CClient::onLeave()
// marshall the data
CString data = clipboard.marshall();
// send data
log((CLOG_DEBUG "sending clipboard %d seqnum=%d, size=%d", id, m_seqNum, data.size()));
CProtocolUtil::writef(m_output,
// save and send data if different
if (data != m_dataClipboard[id]) {
log((CLOG_DEBUG "sending clipboard %d seqnum=%d, size=%d", id, m_seqNum, data.size()));
m_dataClipboard[id] = data;
CProtocolUtil::writef(m_output,
kMsgDClipboard, id, m_seqNum, &data);
}
}
}
}
@ -441,13 +461,26 @@ void CClient::onScreenSaver()
void CClient::onQueryInfo()
{
SInt32 w, h;
CLock lock(&m_mutex);
onQueryInfoNoLock();
}
void CClient::onQueryInfoNoLock()
{
SInt32 x, y, w, h;
m_screen->getMousePos(&x, &y);
m_screen->getSize(&w, &h);
SInt32 zoneSize = m_screen->getJumpZoneSize();
log((CLOG_DEBUG1 "sending info size=%d,%d zone=%d", w, h, zoneSize));
log((CLOG_DEBUG1 "sending info size=%d,%d zone=%d pos=%d,%d", w, h, zoneSize, x, y));
CProtocolUtil::writef(m_output, kMsgDInfo, w, h, zoneSize, x, y);
}
void CClient::onInfoAcknowledgment()
{
log((CLOG_DEBUG1 "recv info acknowledgment"));
CLock lock(&m_mutex);
CProtocolUtil::writef(m_output, kMsgDInfo, w, h, zoneSize);
m_ignoreMove = false;
}
void CClient::onSetClipboard()
@ -536,13 +569,17 @@ void CClient::onMouseUp()
void CClient::onMouseMove()
{
bool ignore;
SInt16 x, y;
{
CLock lock(&m_mutex);
CProtocolUtil::readf(m_input, kMsgDMouseMove + 4, &x, &y);
ignore = m_ignoreMove;
}
log((CLOG_DEBUG2 "recv mouse move %d,%d", x, y));
m_screen->mouseMove(x, y);
if (!ignore) {
m_screen->mouseMove(x, y);
}
}
void CClient::onMouseWheel()

View File

@ -23,6 +23,7 @@ public:
// handle events on client's screen
void onClipboardChanged(ClipboardID);
void onResolutionChanged();
// accessors
@ -40,6 +41,8 @@ private:
void onGrabClipboard();
void onScreenSaver();
void onQueryInfo();
void onQueryInfoNoLock();
void onInfoAcknowledgment();
void onSetClipboard();
void onKeyDown();
void onKeyRepeat();
@ -61,8 +64,10 @@ private:
const CNetworkAddress* m_serverAddress;
bool m_active;
UInt32 m_seqNum;
bool m_ignoreMove;
bool m_ownClipboard[kClipboardEnd];
IClipboard::Time m_timeClipboard[kClipboardEnd];
CString m_dataClipboard[kClipboardEnd];
};
#endif

View File

@ -315,6 +315,23 @@ void CMSWindowsSecondaryScreen::grabClipboard(ClipboardID id)
}
}
void CMSWindowsSecondaryScreen::getMousePos(
SInt32* x, SInt32* y) const
{
assert(x != NULL);
assert(y != NULL);
POINT pos;
if (GetCursorPos(&pos)) {
*x = pos.x;
*y = pos.y;
}
else {
*x = 0;
*y = 0;
}
}
void CMSWindowsSecondaryScreen::getSize(
SInt32* width, SInt32* height) const
{
@ -420,6 +437,12 @@ LRESULT CMSWindowsSecondaryScreen::onEvent(
else
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
return 0;
case WM_DISPLAYCHANGE:
// screen resolution has changed
updateScreenSize();
m_client->onResolutionChanged();
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);

View File

@ -28,6 +28,7 @@ public:
virtual void mouseWheel(SInt32 delta);
virtual void setClipboard(ClipboardID, const IClipboard*);
virtual void grabClipboard(ClipboardID);
virtual void getMousePos(SInt32* x, SInt32* y) const;
virtual void getSize(SInt32* width, SInt32* height) const;
virtual SInt32 getJumpZoneSize() const;
virtual void getClipboard(ClipboardID, IClipboard*) const;

View File

@ -323,6 +323,19 @@ void CXWindowsSecondaryScreen::grabClipboard(ClipboardID id)
setDisplayClipboard(id, NULL, m_window, getCurrentTime(m_window));
}
void CXWindowsSecondaryScreen::getMousePos(
SInt32* x, SInt32* y) const
{
CDisplayLock display(this);
int xTmp, yTmp, dummy;
unsigned int dummyMask;
Window dummyWindow;
XQueryPointer(display, getRoot(), &dummyWindow, &dummyWindow,
&xTmp, &yTmp, &dummy, &dummy, &dummyMask);
*x = xTmp;
*y = yTmp;
}
void CXWindowsSecondaryScreen::getSize(
SInt32* width, SInt32* height) const
{

View File

@ -27,6 +27,7 @@ public:
virtual void mouseWheel(SInt32 delta);
virtual void setClipboard(ClipboardID, const IClipboard*);
virtual void grabClipboard(ClipboardID);
virtual void getMousePos(SInt32* x, SInt32* y) const;
virtual void getSize(SInt32* width, SInt32* height) const;
virtual SInt32 getJumpZoneSize() const;
virtual void getClipboard(ClipboardID, IClipboard*) const;

View File

@ -61,6 +61,11 @@ void CMSWindowsPrimaryScreen::open(CServer* server)
// get keyboard state
updateKeys();
// send screen info
SInt32 w, h;
getScreenSize(&w, &h);
m_server->setInfo(w, h, getJumpZoneSize(), 0, 0);
// enter the screen
doEnter();
}
@ -246,18 +251,35 @@ void CMSWindowsPrimaryScreen::getClipboard(
KeyModifierMask CMSWindowsPrimaryScreen::getToggleMask() const
{
KeyModifierMask mask = 0;
if ((m_keys[VK_CAPITAL] & 0x01) != 0)
if ((GetKeyState(VK_CAPITAL) & 0x01) != 0)
mask |= KeyModifierCapsLock;
if ((m_keys[VK_NUMLOCK] & 0x01) != 0)
if ((GetKeyState(VK_NUMLOCK) & 0x01) != 0)
mask |= KeyModifierNumLock;
if ((m_keys[VK_SCROLL] & 0x01) != 0)
if ((GetKeyState(VK_SCROLL) & 0x01) != 0)
mask |= KeyModifierScrollLock;
return mask;
}
bool CMSWindowsPrimaryScreen::isLockedToScreen() const
{
// FIXME
// check buttons
if (GetAsyncKeyState(VK_LBUTTON) < 0 ||
GetAsyncKeyState(VK_MBUTTON) < 0 ||
GetAsyncKeyState(VK_RBUTTON) < 0) {
return true;
}
// check keys
BYTE keys[256];
if (GetKeyboardState(keys)) {
for (unsigned int i = 0; i < sizeof(keys); ++i) {
if ((keys[i] & 0x80) != 0) {
return true;
}
}
}
// not locked
return false;
}
@ -433,13 +455,17 @@ bool CMSWindowsPrimaryScreen::onPreTranslate(MSG* msg)
// get mouse deltas
x -= m_xCenter;
y -= m_yCenter;
log((CLOG_DEBUG2 "event: active move %d,%d", x, y));
// warp mouse back to center
warpCursor(m_xCenter, m_yCenter);
// ignore if the mouse didn't move
if (x != 0 && y != 0) {
log((CLOG_DEBUG2 "event: active move %d,%d", x, y));
// send motion
m_server->onMouseMoveSecondary(x, y);
// warp mouse back to center
warpCursor(m_xCenter, m_yCenter);
// send motion
m_server->onMouseMoveSecondary(x, y);
}
}
}
return true;
@ -485,6 +511,36 @@ LRESULT CMSWindowsPrimaryScreen::onEvent(
else
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
return 0;
case WM_DISPLAYCHANGE: {
// screen resolution has changed
SInt32 w, h;
updateScreenSize();
getScreenSize(&w, &h);
// recompute center pixel of screen
m_xCenter = w >> 1;
m_yCenter = h >> 1;
// warp mouse to center if active
if (m_active) {
warpCursor(m_xCenter, m_yCenter);
}
// tell hook about resize if not active
else {
SetZoneFunc setZone = (SetZoneFunc)GetProcAddress(
m_hookLibrary, "setZone");
setZone(m_server->getActivePrimarySides(), w, h, getJumpZoneSize());
}
// send new screen info
POINT pos;
GetCursorPos(&pos);
m_server->setInfo(w, h, getJumpZoneSize(), pos.x, pos.y);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);

View File

@ -132,8 +132,16 @@ UInt32 CServer::getActivePrimarySides() const
return sides;
}
void CServer::setInfo(
SInt32 w, SInt32 h, SInt32 zoneSize,
SInt32 x, SInt32 y)
{
setInfo(m_primaryInfo->m_name, w, h, zoneSize, x, y);
}
void CServer::setInfo(const CString& client,
SInt32 w, SInt32 h, SInt32 zoneSize)
SInt32 w, SInt32 h, SInt32 zoneSize,
SInt32 x, SInt32 y)
{
assert(!client.empty());
assert(w > 0);
@ -151,12 +159,29 @@ void CServer::setInfo(const CString& client,
// update client info
CScreenInfo* info = index->second;
if (info == m_active) {
// FIXME -- ensure mouse is still on screen. warp it if necessary.
// update the remote mouse coordinates
m_x = x;
m_y = y;
}
info->m_width = w;
info->m_height = h;
info->m_zoneSize = zoneSize;
log((CLOG_NOTE "client \"%s\" size=%dx%d zone=%d", client.c_str(), w, h, zoneSize));
log((CLOG_NOTE "client \"%s\" size=%dx%d zone=%d pos=%d,%d", client.c_str(), w, h, zoneSize, x, y));
// send acknowledgement (if client isn't the primary)
if (info->m_protocol != NULL) {
info->m_protocol->sendInfoAcknowledgment();
}
// handle resolution change to primary screen
else {
if (info == m_active) {
onMouseMovePrimary(x, y);
}
else {
onMouseMoveSecondary(0, 0);
}
}
}
void CServer::grabClipboard(ClipboardID id)
@ -1011,6 +1036,10 @@ void CServer::openPrimaryScreen()
// reset sequence number
m_seqNum = 0;
// add connection
m_active = addConnection(CString("primary"/* FIXME */), NULL);
m_primaryInfo = m_active;
// open screen
log((CLOG_DEBUG1 "creating primary screen"));
#if defined(CONFIG_PLATFORM_WIN32)
@ -1021,16 +1050,6 @@ void CServer::openPrimaryScreen()
log((CLOG_DEBUG1 "opening primary screen"));
m_primary->open(this);
// add connection
m_active = addConnection(CString("primary"/* FIXME */), NULL);
m_primaryInfo = m_active;
// update info
m_primary->getSize(&m_active->m_width, &m_active->m_height);
m_active->m_zoneSize = m_primary->getJumpZoneSize();
log((CLOG_NOTE "server size=%dx%d zone=%d", m_active->m_width, m_active->m_height, m_active->m_zoneSize));
// FIXME -- need way for primary screen to call us back
// set the clipboard owner to the primary screen and then get the
// current clipboard data.
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {

View File

@ -46,9 +46,16 @@ public:
void onMouseWheel(SInt32 delta);
void grabClipboard(ClipboardID);
// handle updates from primary
void setInfo(SInt32 wScreen, SInt32 hScreen,
SInt32 zoneSize,
SInt32 xMouse, SInt32 yMouse);
// handle messages from clients
void setInfo(const CString& clientName,
SInt32 w, SInt32 h, SInt32 zoneSize);
SInt32 wScreen, SInt32 hScreen,
SInt32 zoneSize,
SInt32 xMouse, SInt32 yMouse);
void grabClipboard(ClipboardID,
UInt32 seqNum, const CString& clientName);
void setClipboard(ClipboardID,
@ -187,6 +194,7 @@ private:
// the sequence number of enter messages
UInt32 m_seqNum;
// current mouse position (in absolute secondary screen coordinates)
SInt32 m_x, m_y;
CScreenMap m_screenMap;

View File

@ -37,6 +37,7 @@ public:
virtual void sendClipboard(ClipboardID, const CString&) = 0;
virtual void sendGrabClipboard(ClipboardID) = 0;
virtual void sendScreenSaver(bool on) = 0;
virtual void sendInfoAcknowledgment() = 0;
virtual void sendKeyDown(KeyID, KeyModifierMask) = 0;
virtual void sendKeyRepeat(KeyID, KeyModifierMask, SInt32 count) = 0;
virtual void sendKeyUp(KeyID, KeyModifierMask) = 0;

View File

@ -124,6 +124,12 @@ void CServerProtocol1_0::sendScreenSaver(bool on)
CProtocolUtil::writef(getOutputStream(), kMsgCScreenSaver, on ? 1 : 0);
}
void CServerProtocol1_0::sendInfoAcknowledgment()
{
log((CLOG_DEBUG1 "send info ack to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCInfoAck);
}
void CServerProtocol1_0::sendKeyDown(
KeyID key, KeyModifierMask mask)
{
@ -176,17 +182,21 @@ void CServerProtocol1_0::sendMouseWheel(
void CServerProtocol1_0::recvInfo()
{
// parse the message
SInt16 w, h, zoneInfo;
CProtocolUtil::readf(getInputStream(), kMsgDInfo + 4, &w, &h, &zoneInfo);
log((CLOG_DEBUG "received client \"%s\" info size=%dx%d, zone=%d", getClient().c_str(), w, h, zoneInfo));
SInt16 x, y, w, h, zoneInfo;
CProtocolUtil::readf(getInputStream(), kMsgDInfo + 4,
&w, &h, &zoneInfo, &x, &y);
log((CLOG_DEBUG "received client \"%s\" info size=%dx%d, zone=%d, pos=%d,%d", getClient().c_str(), w, h, zoneInfo, x, y));
// validate
if (w <= 0 || h <= 0 || zoneInfo < 0) {
throw XBadClient();
}
if (x < 0 || y < 0 || x >= w || y >= h) {
throw XBadClient();
}
// tell server of change
getServer()->setInfo(getClient(), w, h, zoneInfo);
getServer()->setInfo(getClient(), w, h, zoneInfo, x, y);
}
void CServerProtocol1_0::recvClipboard()

View File

@ -22,6 +22,7 @@ public:
virtual void sendClipboard(ClipboardID, const CString&);
virtual void sendGrabClipboard(ClipboardID);
virtual void sendScreenSaver(bool on);
virtual void sendInfoAcknowledgment();
virtual void sendKeyDown(KeyID, KeyModifierMask);
virtual void sendKeyRepeat(KeyID, KeyModifierMask, SInt32 count);
virtual void sendKeyUp(KeyID, KeyModifierMask);

View File

@ -268,6 +268,11 @@ void CXWindowsPrimaryScreen::open(CServer* server)
CDisplayLock display(this);
updateModifierMap(display);
}
// send screen info
SInt32 w, h;
getScreenSize(&w, &h);
m_server->setInfo(w, h, getJumpZoneSize(), 0, 0);
}
void CXWindowsPrimaryScreen::close()

View File

@ -135,6 +135,13 @@ ATOM CMSWindowsScreen::getClass() const
return m_class;
}
void CMSWindowsScreen::updateScreenSize()
{
m_w = GetSystemMetrics(SM_CXSCREEN);
m_h = GetSystemMetrics(SM_CYSCREEN);
log((CLOG_INFO "display resize: %dx%d", m_w, m_h));
}
void CMSWindowsScreen::getScreenSize(
SInt32* w, SInt32* h) const
{

View File

@ -40,6 +40,9 @@ protected:
static HINSTANCE getInstance();
ATOM getClass() const;
// update screen size cache
void updateScreenSize();
// get the size of the screen
void getScreenSize(SInt32* w, SInt32* h) const;

View File

@ -28,7 +28,11 @@ public:
// can't be detected then this object should disable the system's
// screen saver timer and should start the screen saver after
// idling for an appropriate time.
virtual void open(CServer*) = 0;
//
// open() must call server->setInfo() to notify the server of the
// primary screen's resolution and jump zone size. the mouse
// position is ignored and may be 0,0.
virtual void open(CServer* server) = 0;
// close the screen. should restore the screen saver timer if it
// was disabled.

View File

@ -66,6 +66,9 @@ public:
// accessors
// get the position of the mouse on the screen
virtual void getMousePos(SInt32* x, SInt32* y) const = 0;
// get the size of the screen
virtual void getSize(SInt32* width, SInt32* height) const = 0;

View File

@ -30,6 +30,7 @@ public:
virtual void sendClipboard(ClipboardID, const CString&) = 0;
virtual void sendGrabClipboard(ClipboardID) = 0;
virtual void sendScreenSaver(bool on) = 0;
virtual void sendInfoAcknowledgment() = 0;
virtual void sendKeyDown(KeyID, KeyModifierMask) = 0;
virtual void sendKeyRepeat(KeyID, KeyModifierMask, SInt32 count) = 0;
virtual void sendKeyUp(KeyID, KeyModifierMask) = 0;

View File

@ -50,6 +50,12 @@ static const char kMsgCClipboard[] = "CCLP%1i%4i";
// screensaver on primary has started ($1 == 1) or closed ($1 == 0)
static const char kMsgCScreenSaver[] = "CSEC%1i";
// resolution change acknowledgment: primary -> secondary
// sent by primary in response to a secondary screen's kMsgDInfo.
// this is sent for every kMsgDInfo, whether or not the primary
// had sent a kMsgQInfo.
static const char kMsgCInfoAck[] = "CIAK";
//
// data codes
@ -80,7 +86,8 @@ static const char kMsgDMouseUp[] = "DMUP%1i";
static const char kMsgDMouseMove[] = "DMMV%2i%2i";
// mouse button pressed: primary -> secondary
// $1 = delta
// $1 = delta. the delta should be +120 for one tick forward (away
// from the user) and -120 for one tick backward (toward the user).
static const char kMsgDMouseWheel[] = "DMWM%2i";
// clipboard data: primary <-> secondary
@ -92,8 +99,16 @@ static const char kMsgDClipboard[] = "DCLP%1i%4i%s";
// client data: secondary -> primary
// $1 = seconary screen width in pixels, $2 = screen height, $3 =
// size of warp zone.
static const char kMsgDInfo[] = "DINF%2i%2i%2i";
// size of warp zone. $4 and $5 are the x,y position of the mouse
// on the secondary screen.
//
// the secondary screen must send this message in response to the
// kMsgQInfo message. it must also send this message when the
// screen's resolution changes. in this case, the secondary screen
// should ignore any kMsgDMouseMove messages until it receives a
// kMsgCInfoAck in order to prevent attempts to move the mouse off
// the new screen area.
static const char kMsgDInfo[] = "DINF%2i%2i%2i%2i%2i";
//