checkpoint. refactored win32 code. had to edit and rename some
files so this is only a checkpoint.
This commit is contained in:
parent
f48a5fe387
commit
4b46862026
|
@ -1,12 +1,8 @@
|
||||||
#include "CMSWindowsSecondaryScreen.h"
|
#include "CMSWindowsSecondaryScreen.h"
|
||||||
#include "IScreenReceiver.h"
|
#include "CMSWindowsScreen.h"
|
||||||
#include "CClipboard.h"
|
|
||||||
#include "CMSWindowsClipboard.h"
|
|
||||||
#include "CMSWindowsScreenSaver.h"
|
|
||||||
#include "CPlatform.h"
|
#include "CPlatform.h"
|
||||||
#include "XScreen.h"
|
#include "XScreen.h"
|
||||||
#include "CLock.h"
|
#include "CLock.h"
|
||||||
#include "CThread.h"
|
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
|
@ -24,155 +20,18 @@
|
||||||
|
|
||||||
CMSWindowsSecondaryScreen::CMSWindowsSecondaryScreen(
|
CMSWindowsSecondaryScreen::CMSWindowsSecondaryScreen(
|
||||||
IScreenReceiver* receiver) :
|
IScreenReceiver* receiver) :
|
||||||
m_receiver(receiver),
|
m_is95Family(CPlatform::isWindows95Family()),
|
||||||
m_threadID(0),
|
|
||||||
m_lastThreadID(0),
|
|
||||||
m_desk(NULL),
|
|
||||||
m_deskName(),
|
|
||||||
m_window(NULL),
|
m_window(NULL),
|
||||||
m_active(false),
|
m_mask(0)
|
||||||
m_nextClipboardWindow(NULL)
|
|
||||||
{
|
{
|
||||||
assert(m_receiver != NULL);
|
m_screen = new CMSWindowsScreen(receiver, this);
|
||||||
|
|
||||||
m_is95Family = CPlatform::isWindows95Family();
|
|
||||||
|
|
||||||
// make sure this thread has a message queue
|
|
||||||
MSG dummy;
|
|
||||||
PeekMessage(&dummy, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CMSWindowsSecondaryScreen::~CMSWindowsSecondaryScreen()
|
CMSWindowsSecondaryScreen::~CMSWindowsSecondaryScreen()
|
||||||
{
|
{
|
||||||
assert(m_window == NULL);
|
assert(m_window == NULL);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
delete m_screen;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -182,8 +41,7 @@ CMSWindowsSecondaryScreen::keyDown(KeyID key, KeyModifierMask mask)
|
||||||
UINT virtualKey;
|
UINT virtualKey;
|
||||||
|
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_window != NULL);
|
m_screen->syncDesktop();
|
||||||
syncDesktop();
|
|
||||||
|
|
||||||
// get the sequence of keys to simulate key press and the final
|
// get the sequence of keys to simulate key press and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
|
@ -223,8 +81,7 @@ CMSWindowsSecondaryScreen::keyRepeat(KeyID key,
|
||||||
UINT virtualKey;
|
UINT virtualKey;
|
||||||
|
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_window != NULL);
|
m_screen->syncDesktop();
|
||||||
syncDesktop();
|
|
||||||
|
|
||||||
// get the sequence of keys to simulate key repeat and the final
|
// get the sequence of keys to simulate key repeat and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
|
@ -244,8 +101,7 @@ CMSWindowsSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask)
|
||||||
UINT virtualKey;
|
UINT virtualKey;
|
||||||
|
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_window != NULL);
|
m_screen->syncDesktop();
|
||||||
syncDesktop();
|
|
||||||
|
|
||||||
// get the sequence of keys to simulate key release and the final
|
// get the sequence of keys to simulate key release and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
|
@ -302,8 +158,7 @@ void
|
||||||
CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
|
CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_window != NULL);
|
m_screen->syncDesktop();
|
||||||
syncDesktop();
|
|
||||||
|
|
||||||
// map button id to button flag
|
// map button id to button flag
|
||||||
DWORD flags = mapButton(button, true);
|
DWORD flags = mapButton(button, true);
|
||||||
|
@ -318,8 +173,7 @@ void
|
||||||
CMSWindowsSecondaryScreen::mouseUp(ButtonID button)
|
CMSWindowsSecondaryScreen::mouseUp(ButtonID button)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_window != NULL);
|
m_screen->syncDesktop();
|
||||||
syncDesktop();
|
|
||||||
|
|
||||||
// map button id to button flag
|
// map button id to button flag
|
||||||
DWORD flags = mapButton(button, false);
|
DWORD flags = mapButton(button, false);
|
||||||
|
@ -334,8 +188,7 @@ void
|
||||||
CMSWindowsSecondaryScreen::mouseMove(SInt32 x, SInt32 y)
|
CMSWindowsSecondaryScreen::mouseMove(SInt32 x, SInt32 y)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_window != NULL);
|
m_screen->syncDesktop();
|
||||||
syncDesktop();
|
|
||||||
warpCursor(x, y);
|
warpCursor(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,61 +196,50 @@ void
|
||||||
CMSWindowsSecondaryScreen::mouseWheel(SInt32 delta)
|
CMSWindowsSecondaryScreen::mouseWheel(SInt32 delta)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_window != NULL);
|
m_screen->syncDesktop();
|
||||||
syncDesktop();
|
|
||||||
|
|
||||||
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, 0);
|
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
IScreen*
|
||||||
CMSWindowsSecondaryScreen::setClipboard(ClipboardID /*id*/,
|
CMSWindowsSecondaryScreen::getScreen() const
|
||||||
const IClipboard* src)
|
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
return m_screen;
|
||||||
assert(m_window != NULL);
|
|
||||||
|
|
||||||
CMSWindowsClipboard dst(m_window);
|
|
||||||
CClipboard::copy(&dst, src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsSecondaryScreen::grabClipboard(ClipboardID /*id*/)
|
CMSWindowsSecondaryScreen::onError()
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
// ignore
|
||||||
assert(m_window != NULL);
|
|
||||||
|
|
||||||
CMSWindowsClipboard clipboard(m_window);
|
|
||||||
if (clipboard.open(0)) {
|
|
||||||
clipboard.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsSecondaryScreen::screenSaver(bool activate)
|
CMSWindowsSecondaryScreen::onScreensaver(bool)
|
||||||
{
|
{
|
||||||
if (activate) {
|
// ignore
|
||||||
getScreenSaver()->activate();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
getScreenSaver()->deactivate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
CMSWindowsSecondaryScreen::getMousePos(SInt32& x, SInt32& y) const
|
CMSWindowsSecondaryScreen::onPreDispatch(const CEvent*)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
return false;
|
||||||
assert(m_window != NULL);
|
|
||||||
syncDesktop();
|
|
||||||
|
|
||||||
getCursorPos(x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
CMSWindowsSecondaryScreen::getShape(
|
CMSWindowsSecondaryScreen::onEvent(CEvent* event)
|
||||||
SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
|
||||||
{
|
{
|
||||||
getScreenShape(x, y, w, h);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SInt32
|
SInt32
|
||||||
|
@ -407,153 +249,63 @@ CMSWindowsSecondaryScreen::getJumpZoneSize() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsSecondaryScreen::getClipboard(ClipboardID /*id*/,
|
CMSWindowsSecondaryScreen::postCreateWindow(HWND window)
|
||||||
IClipboard* dst) const
|
{
|
||||||
|
m_window = window;
|
||||||
|
if (!isActive()) {
|
||||||
|
showWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsSecondaryScreen::preDestroyWindow(HWND)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsSecondaryScreen::onPreRun()
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
|
||||||
assert(m_window != NULL);
|
assert(m_window != NULL);
|
||||||
|
|
||||||
CMSWindowsClipboard src(m_window);
|
|
||||||
CClipboard::copy(dst, &src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
CMSWindowsSecondaryScreen::onPreDispatch(const CEvent* event)
|
CMSWindowsSecondaryScreen::onPreOpen()
|
||||||
{
|
{
|
||||||
assert(event != NULL);
|
assert(m_window == NULL);
|
||||||
|
|
||||||
// forward to superclass
|
|
||||||
if (CMSWindowsScreen::onPreDispatch(event)) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle event
|
void
|
||||||
const MSG* msg = &event->m_msg;
|
CMSWindowsSecondaryScreen::onPreEnter()
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CMSWindowsSecondaryScreen::onEvent(CEvent* event)
|
|
||||||
{
|
{
|
||||||
assert(event != NULL);
|
assert(m_window != 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
|
void
|
||||||
// we're now the owner, in which case it's because we took
|
CMSWindowsSecondaryScreen::onPreLeave()
|
||||||
// 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.
|
assert(m_window != NULL);
|
||||||
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;
|
void
|
||||||
}
|
CMSWindowsSecondaryScreen::createWindow()
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CString
|
|
||||||
CMSWindowsSecondaryScreen::getCurrentDesktopName() const
|
|
||||||
{
|
{
|
||||||
return m_deskName;
|
// 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
|
void
|
||||||
|
@ -580,9 +332,9 @@ CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||||
{
|
{
|
||||||
// move the mouse directly to target position on NT family or if
|
// move the mouse directly to target position on NT family or if
|
||||||
// not using multiple monitors.
|
// not using multiple monitors.
|
||||||
if (!m_multimon || !m_is95Family) {
|
if (m_screen->isMultimon() || !m_is95Family) {
|
||||||
SInt32 x0, y0, w, h;
|
SInt32 x0, y0, w, h;
|
||||||
getScreenShape(x0, y0, w, h);
|
m_screen->getShape(x0, y0, w, h);
|
||||||
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
||||||
(DWORD)((65535.99 * (x - x0)) / (w - 1)),
|
(DWORD)((65535.99 * (x - x0)) / (w - 1)),
|
||||||
(DWORD)((65535.99 * (y - y0)) / (h - 1)),
|
(DWORD)((65535.99 * (y - y0)) / (h - 1)),
|
||||||
|
@ -653,259 +405,70 @@ CMSWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsSecondaryScreen::checkClipboard()
|
CMSWindowsSecondaryScreen::updateKeys()
|
||||||
{
|
{
|
||||||
// if we think we own the clipboard but we don't then somebody
|
// clear key state
|
||||||
// grabbed the clipboard on this screen without us knowing.
|
memset(m_keys, 0, sizeof(m_keys));
|
||||||
// tell the server that this screen grabbed the clipboard.
|
|
||||||
//
|
// we only care about the modifier key states
|
||||||
// this works around bugs in the clipboard viewer chain.
|
m_keys[VK_LSHIFT] = static_cast<BYTE>(GetKeyState(VK_LSHIFT));
|
||||||
// sometimes NT will simply never send WM_DRAWCLIPBOARD
|
m_keys[VK_RSHIFT] = static_cast<BYTE>(GetKeyState(VK_RSHIFT));
|
||||||
// messages for no apparent reason and rebooting fixes the
|
m_keys[VK_SHIFT] = static_cast<BYTE>(GetKeyState(VK_SHIFT));
|
||||||
// problem. since we don't want a broken clipboard until the
|
m_keys[VK_LCONTROL] = static_cast<BYTE>(GetKeyState(VK_LCONTROL));
|
||||||
// next reboot we do this double check. clipboard ownership
|
m_keys[VK_RCONTROL] = static_cast<BYTE>(GetKeyState(VK_RCONTROL));
|
||||||
// won't be reflected on other screens until we leave but at
|
m_keys[VK_CONTROL] = static_cast<BYTE>(GetKeyState(VK_CONTROL));
|
||||||
// least the clipboard itself will work.
|
m_keys[VK_LMENU] = static_cast<BYTE>(GetKeyState(VK_LMENU));
|
||||||
HWND clipboardOwner = GetClipboardOwner();
|
m_keys[VK_RMENU] = static_cast<BYTE>(GetKeyState(VK_RMENU));
|
||||||
if (m_clipboardOwner != clipboardOwner) {
|
m_keys[VK_MENU] = static_cast<BYTE>(GetKeyState(VK_MENU));
|
||||||
try {
|
m_keys[VK_LWIN] = static_cast<BYTE>(GetKeyState(VK_LWIN));
|
||||||
m_clipboardOwner = clipboardOwner;
|
m_keys[VK_RWIN] = static_cast<BYTE>(GetKeyState(VK_RWIN));
|
||||||
if (m_clipboardOwner != m_window && m_clipboardOwner != NULL) {
|
m_keys[VK_APPS] = static_cast<BYTE>(GetKeyState(VK_APPS));
|
||||||
m_receiver->onGrabClipboard(kClipboardClipboard);
|
m_keys[VK_CAPITAL] = static_cast<BYTE>(GetKeyState(VK_CAPITAL));
|
||||||
m_receiver->onGrabClipboard(kClipboardSelection);
|
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;
|
||||||
}
|
}
|
||||||
catch (XBadClient&) {
|
if ((m_keys[VK_LMENU] & 0x80) != 0 || (m_keys[VK_RMENU] & 0x80) != 0) {
|
||||||
// ignore
|
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
|
void
|
||||||
CMSWindowsPrimaryScreen::createWindow()
|
CMSWindowsSecondaryScreen::setToggleState(KeyModifierMask mask)
|
||||||
{
|
{
|
||||||
// save thread id
|
// toggle modifiers that don't match the desired state
|
||||||
m_threadID = GetCurrentThreadId();
|
if ((mask & KeyModifierCapsLock) != (m_mask & KeyModifierCapsLock)) {
|
||||||
|
toggleKey(VK_CAPITAL, KeyModifierCapsLock);
|
||||||
// note if using multiple monitors
|
|
||||||
m_multimon = isMultimon();
|
|
||||||
|
|
||||||
// get the input desktop and switch to it
|
|
||||||
if (m_is95Family) {
|
|
||||||
if (!openDesktop()) {
|
|
||||||
throw XScreenOpenFailure();
|
|
||||||
}
|
}
|
||||||
|
if ((mask & KeyModifierNumLock) != (m_mask & KeyModifierNumLock)) {
|
||||||
|
toggleKey(VK_NUMLOCK | 0x100, KeyModifierNumLock);
|
||||||
}
|
}
|
||||||
else {
|
if ((mask & KeyModifierScrollLock) != (m_mask & KeyModifierScrollLock)) {
|
||||||
if (!switchDesktop(openInputDesktop())) {
|
toggleKey(VK_SCROLL, KeyModifierScrollLock);
|
||||||
throw XScreenOpenFailure();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
// 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
|
// 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
|
// code | 0x100. keys that map to normal characters have a 0 entry
|
||||||
|
@ -1768,7 +1331,7 @@ CMSWindowsSecondaryScreen::releaseKeys()
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
|
|
||||||
syncDesktop();
|
m_screen->syncDesktop();
|
||||||
|
|
||||||
// release left/right modifier keys first. if the platform doesn't
|
// release left/right modifier keys first. if the platform doesn't
|
||||||
// support them then they won't be set and the non-side-distinuishing
|
// 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
|
void
|
||||||
CMSWindowsSecondaryScreen::toggleKey(UINT virtualKey, KeyModifierMask mask)
|
CMSWindowsSecondaryScreen::toggleKey(UINT virtualKey, KeyModifierMask mask)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,28 +7,22 @@
|
||||||
#define _WIN32_WINNT 0x401
|
#define _WIN32_WINNT 0x401
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CSecondaryScreen.h"
|
||||||
#include "ISecondaryScreen.h"
|
#include "IMSWindowsScreenEventHandler.h"
|
||||||
#include "CMutex.h"
|
#include "CMutex.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
#include "stdvector.h"
|
#include "stdvector.h"
|
||||||
|
|
||||||
|
class CMSWindowsScreen;
|
||||||
class IScreenReceiver;
|
class IScreenReceiver;
|
||||||
|
|
||||||
class CMSWindowsSecondaryScreen : public CMSWindowsScreen,
|
class CMSWindowsSecondaryScreen :
|
||||||
public ISecondaryScreen {
|
public CSecondaryScreen, public IMSWindowsScreenEventHandler {
|
||||||
public:
|
public:
|
||||||
CMSWindowsSecondaryScreen(IScreenReceiver*);
|
CMSWindowsSecondaryScreen(IScreenReceiver*);
|
||||||
virtual ~CMSWindowsSecondaryScreen();
|
virtual ~CMSWindowsSecondaryScreen();
|
||||||
|
|
||||||
// ISecondaryScreen overrides
|
// CSecondaryScreen overrides
|
||||||
virtual void run();
|
|
||||||
virtual void stop();
|
|
||||||
virtual void open();
|
|
||||||
virtual void close();
|
|
||||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
|
||||||
KeyModifierMask mask);
|
|
||||||
virtual void leave();
|
|
||||||
virtual void keyDown(KeyID, KeyModifierMask);
|
virtual void keyDown(KeyID, KeyModifierMask);
|
||||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||||
virtual void keyUp(KeyID, KeyModifierMask);
|
virtual void keyUp(KeyID, KeyModifierMask);
|
||||||
|
@ -36,19 +30,30 @@ public:
|
||||||
virtual void mouseUp(ButtonID);
|
virtual void mouseUp(ButtonID);
|
||||||
virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute);
|
virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute);
|
||||||
virtual void mouseWheel(SInt32 delta);
|
virtual void mouseWheel(SInt32 delta);
|
||||||
virtual void setClipboard(ClipboardID, const IClipboard*);
|
virtual IScreen* getScreen() const;
|
||||||
virtual void grabClipboard(ClipboardID);
|
|
||||||
virtual void screenSaver(bool activate);
|
|
||||||
virtual void getMousePos(SInt32& x, SInt32& y) const;
|
|
||||||
virtual void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
|
||||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
|
||||||
|
|
||||||
protected:
|
// IMSWindowsScreenEventHandler overrides
|
||||||
// CMSWindowsScreen overrides
|
virtual void onError();
|
||||||
|
virtual void onScreensaver(bool activated);
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
virtual bool onPreDispatch(const CEvent* event);
|
||||||
virtual bool onEvent(CEvent* event);
|
virtual bool onEvent(CEvent* event);
|
||||||
virtual CString getCurrentDesktopName() const;
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
virtual void postCreateWindow(HWND);
|
||||||
|
virtual void preDestroyWindow(HWND);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// CSecondaryScreen overrides
|
||||||
|
virtual void onPreRun();
|
||||||
|
virtual void onPreOpen();
|
||||||
|
virtual void onPreEnter();
|
||||||
|
virtual void onPreLeave();
|
||||||
|
virtual void createWindow();
|
||||||
|
virtual void destroyWindow();
|
||||||
|
virtual void showWindow();
|
||||||
|
virtual void hideWindow();
|
||||||
|
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||||
|
virtual void updateKeys();
|
||||||
|
virtual void setToggleState(KeyModifierMask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum EKeyAction { kPress, kRelease, kRepeat };
|
enum EKeyAction { kPress, kRelease, kRepeat };
|
||||||
|
@ -60,26 +65,6 @@ private:
|
||||||
};
|
};
|
||||||
typedef std::vector<Keystroke> Keystrokes;
|
typedef std::vector<Keystroke> Keystrokes;
|
||||||
|
|
||||||
void showWindow();
|
|
||||||
void hideWindow();
|
|
||||||
|
|
||||||
// warp the mouse to the specified position
|
|
||||||
void warpCursor(SInt32 x, SInt32 y);
|
|
||||||
|
|
||||||
// check clipboard ownership and, if necessary, tell the receiver
|
|
||||||
// of a grab.
|
|
||||||
void checkClipboard();
|
|
||||||
|
|
||||||
// create/destroy window
|
|
||||||
// also attach to desktop; this destroys and recreates the window
|
|
||||||
// as necessary.
|
|
||||||
void createWindow();
|
|
||||||
void destroyWindow();
|
|
||||||
|
|
||||||
// start/stop watch for screen saver changes
|
|
||||||
void installScreenSaver();
|
|
||||||
void uninstallScreenSaver();
|
|
||||||
|
|
||||||
// open/close desktop (for windows 95/98/me)
|
// open/close desktop (for windows 95/98/me)
|
||||||
bool openDesktop();
|
bool openDesktop();
|
||||||
void closeDesktop();
|
void closeDesktop();
|
||||||
|
@ -87,9 +72,6 @@ private:
|
||||||
// make desk the thread desktop (for windows NT/2000/XP)
|
// make desk the thread desktop (for windows NT/2000/XP)
|
||||||
bool switchDesktop(HDESK desk);
|
bool switchDesktop(HDESK desk);
|
||||||
|
|
||||||
// get calling thread to use the input desktop
|
|
||||||
void syncDesktop() const;
|
|
||||||
|
|
||||||
// returns true iff there appear to be multiple monitors
|
// returns true iff there appear to be multiple monitors
|
||||||
bool isMultimon() const;
|
bool isMultimon() const;
|
||||||
|
|
||||||
|
@ -100,8 +82,6 @@ private:
|
||||||
void doKeystrokes(const Keystrokes&, SInt32 count);
|
void doKeystrokes(const Keystrokes&, SInt32 count);
|
||||||
|
|
||||||
void releaseKeys();
|
void releaseKeys();
|
||||||
void updateKeys();
|
|
||||||
void updateModifiers();
|
|
||||||
void toggleKey(UINT virtualKey, KeyModifierMask mask);
|
void toggleKey(UINT virtualKey, KeyModifierMask mask);
|
||||||
UINT virtualKeyToScanCode(UINT& virtualKey);
|
UINT virtualKeyToScanCode(UINT& virtualKey);
|
||||||
bool isExtendedKey(UINT virtualKey);
|
bool isExtendedKey(UINT virtualKey);
|
||||||
|
@ -109,37 +89,14 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CMutex m_mutex;
|
CMutex m_mutex;
|
||||||
IScreenReceiver* m_receiver;
|
CMSWindowsScreen* m_screen;
|
||||||
|
|
||||||
// true if windows 95/98/me
|
// true if windows 95/98/me
|
||||||
bool m_is95Family;
|
bool m_is95Family;
|
||||||
|
|
||||||
// true if system appears to have multiple monitors
|
// our window
|
||||||
bool m_multimon;
|
|
||||||
|
|
||||||
// the main loop's thread id
|
|
||||||
DWORD m_threadID;
|
|
||||||
|
|
||||||
// the timer used to check for desktop switching
|
|
||||||
UINT m_timer;
|
|
||||||
|
|
||||||
// the thread id of the last attached thread
|
|
||||||
mutable DWORD m_lastThreadID;
|
|
||||||
|
|
||||||
// the current desk and it's name
|
|
||||||
HDESK m_desk;
|
|
||||||
CString m_deskName;
|
|
||||||
|
|
||||||
// our window (for getting clipboard changes)
|
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
|
|
||||||
// m_active is true if this screen has been entered
|
|
||||||
bool m_active;
|
|
||||||
|
|
||||||
// clipboard stuff
|
|
||||||
HWND m_nextClipboardWindow;
|
|
||||||
HWND m_clipboardOwner;
|
|
||||||
|
|
||||||
// virtual key states
|
// virtual key states
|
||||||
BYTE m_keys[256];
|
BYTE m_keys[256];
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ CSecondaryScreen::open()
|
||||||
updateKeys();
|
updateKeys();
|
||||||
|
|
||||||
// disable the screen saver
|
// disable the screen saver
|
||||||
getScreen()->openScreenSaver(false);
|
getScreen()->openScreensaver(false);
|
||||||
|
|
||||||
// subclass hook
|
// subclass hook
|
||||||
onPostOpen();
|
onPostOpen();
|
||||||
|
@ -93,7 +93,7 @@ void
|
||||||
CSecondaryScreen::close()
|
CSecondaryScreen::close()
|
||||||
{
|
{
|
||||||
onPreClose();
|
onPreClose();
|
||||||
getScreen()->closeScreenSaver();
|
getScreen()->closeScreensaver();
|
||||||
destroyWindow();
|
destroyWindow();
|
||||||
getScreen()->close();
|
getScreen()->close();
|
||||||
onPostClose();
|
onPostClose();
|
||||||
|
@ -182,12 +182,6 @@ CSecondaryScreen::getClipboard(ClipboardID id,
|
||||||
getScreen()->getClipboard(id, clipboard);
|
getScreen()->getClipboard(id, clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
SInt32
|
|
||||||
CSecondaryScreen::getJumpZoneSize() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CSecondaryScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
CSecondaryScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,8 +78,8 @@ public:
|
||||||
void getClipboard(ClipboardID, IClipboard*) const;
|
void getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
|
||||||
// returns the size of the zone on the edges of the screen that
|
// returns the size of the zone on the edges of the screen that
|
||||||
// causes the cursor to jump to another screen. default returns 0.
|
// causes the cursor to jump to another screen.
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const = 0;
|
||||||
|
|
||||||
// get the shape (position of upper-left corner and size) of the
|
// get the shape (position of upper-left corner and size) of the
|
||||||
// screen
|
// screen
|
||||||
|
|
|
@ -145,12 +145,6 @@ CXWindowsSecondaryScreen::getScreen() const
|
||||||
return m_screen;
|
return m_screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CXWindowsSecondaryScreen::onScreensaver(bool)
|
|
||||||
{
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsSecondaryScreen::onError()
|
CXWindowsSecondaryScreen::onError()
|
||||||
{
|
{
|
||||||
|
@ -158,6 +152,12 @@ CXWindowsSecondaryScreen::onError()
|
||||||
// FIXME -- forward this? to whom?
|
// FIXME -- forward this? to whom?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CXWindowsSecondaryScreen::onScreensaver(bool)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CXWindowsSecondaryScreen::onPreDispatch(const CEvent*)
|
CXWindowsSecondaryScreen::onPreDispatch(const CEvent*)
|
||||||
{
|
{
|
||||||
|
@ -184,6 +184,12 @@ CXWindowsSecondaryScreen::onEvent(CEvent* event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SInt32
|
||||||
|
CXWindowsSecondaryScreen::getJumpZoneSize() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsSecondaryScreen::onPreRun()
|
CXWindowsSecondaryScreen::onPreRun()
|
||||||
{
|
{
|
||||||
|
@ -260,7 +266,7 @@ CXWindowsSecondaryScreen::createWindow()
|
||||||
XTestGrabControl(display, True);
|
XTestGrabControl(display, True);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell our superclass about the window
|
// tell generic screen about the window
|
||||||
m_screen->setWindow(m_window);
|
m_screen->setWindow(m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,15 +281,19 @@ CXWindowsSecondaryScreen::destroyWindow()
|
||||||
// no longer impervious to server grabs
|
// no longer impervious to server grabs
|
||||||
XTestGrabControl(display, False);
|
XTestGrabControl(display, False);
|
||||||
|
|
||||||
// destroy window
|
|
||||||
if (m_window != None) {
|
|
||||||
XDestroyWindow(display, m_window);
|
|
||||||
m_window = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update
|
// update
|
||||||
XSync(display, False);
|
XSync(display, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// destroy window
|
||||||
|
if (m_window != None) {
|
||||||
|
m_screen->setWindow(None);
|
||||||
|
CDisplayLock display(m_screen);
|
||||||
|
if (display != NULL) {
|
||||||
|
XDestroyWindow(display, m_window);
|
||||||
|
}
|
||||||
|
m_window = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
virtual void onScreensaver(bool activated);
|
virtual void onScreensaver(bool activated);
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
virtual bool onPreDispatch(const CEvent* event);
|
||||||
virtual bool onEvent(CEvent* event);
|
virtual bool onEvent(CEvent* event);
|
||||||
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CSecondaryScreen overrides
|
// CSecondaryScreen overrides
|
||||||
|
|
|
@ -110,6 +110,10 @@ SOURCE=.\CMSWindowsSecondaryScreen.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\CSecondaryScreen.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CServerProxy.cpp
|
SOURCE=.\CServerProxy.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
|
@ -126,11 +130,11 @@ SOURCE=.\CMSWindowsSecondaryScreen.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CServerProxy.h
|
SOURCE=.\CSecondaryScreen.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\ISecondaryScreen.h
|
SOURCE=.\CServerProxy.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CMSWindowsScreen.h"
|
||||||
|
#include "CMSWindowsClipboard.h"
|
||||||
#include "CMSWindowsScreenSaver.h"
|
#include "CMSWindowsScreenSaver.h"
|
||||||
|
#include "CClipboard.h"
|
||||||
|
#include "IMSWindowsScreenEventHandler.h"
|
||||||
|
#include "IScreenReceiver.h"
|
||||||
|
#include "XSynergy.h"
|
||||||
#include "CThread.h"
|
#include "CThread.h"
|
||||||
#include "CLock.h"
|
#include "CLock.h"
|
||||||
#include "TMethodJob.h"
|
#include "TMethodJob.h"
|
||||||
|
@ -8,7 +13,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
//
|
//
|
||||||
// add backwards compatible multihead support (suppress bogus warning)
|
// add backwards compatible multihead support (and suppress bogus warning)
|
||||||
//
|
//
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable: 4706) // assignment within conditional
|
#pragma warning(disable: 4706) // assignment within conditional
|
||||||
|
@ -23,21 +28,46 @@
|
||||||
HINSTANCE CMSWindowsScreen::s_instance = NULL;
|
HINSTANCE CMSWindowsScreen::s_instance = NULL;
|
||||||
CMSWindowsScreen* CMSWindowsScreen::s_screen = NULL;
|
CMSWindowsScreen* CMSWindowsScreen::s_screen = NULL;
|
||||||
|
|
||||||
CMSWindowsScreen::CMSWindowsScreen() :
|
CMSWindowsScreen::CMSWindowsScreen(IScreenReceiver* receiver,
|
||||||
m_class(0),
|
IMSWindowsScreenEventHandler* eventHandler) :
|
||||||
|
m_receiver(receiver),
|
||||||
|
m_eventHandler(eventHandler),
|
||||||
|
m_class(NULL),
|
||||||
|
m_icon(NULL),
|
||||||
m_cursor(NULL),
|
m_cursor(NULL),
|
||||||
|
m_window(NULL),
|
||||||
m_x(0), m_y(0),
|
m_x(0), m_y(0),
|
||||||
m_w(0), m_h(0),
|
m_w(0), m_h(0),
|
||||||
m_thread(0),
|
m_multimon(false),
|
||||||
m_screenSaver(NULL)
|
m_threadID(0),
|
||||||
|
m_lastThreadID(0),
|
||||||
|
m_nextClipboardWindow(NULL),
|
||||||
|
m_clipboardOwner(NULL),
|
||||||
|
m_timer(0),
|
||||||
|
m_desk(NULL),
|
||||||
|
m_deskName(),
|
||||||
|
m_hookLibrary(NULL),
|
||||||
|
m_installScreensaver(NULL),
|
||||||
|
m_uninstallScreensaver(NULL),
|
||||||
|
m_screensaver(NULL),
|
||||||
|
m_screensaverNotify(false)
|
||||||
{
|
{
|
||||||
assert(s_screen == NULL);
|
assert(s_screen == NULL);
|
||||||
|
assert(m_receiver != NULL);
|
||||||
|
assert(m_eventHandler != NULL);
|
||||||
|
|
||||||
s_screen = this;
|
s_screen = this;
|
||||||
|
|
||||||
|
// make sure this thread has a message queue
|
||||||
|
MSG dummy;
|
||||||
|
PeekMessage(&dummy, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMSWindowsScreen::~CMSWindowsScreen()
|
CMSWindowsScreen::~CMSWindowsScreen()
|
||||||
{
|
{
|
||||||
|
assert(s_screen != NULL);
|
||||||
assert(m_class == 0);
|
assert(m_class == 0);
|
||||||
|
|
||||||
s_screen = NULL;
|
s_screen = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +77,110 @@ CMSWindowsScreen::init(HINSTANCE instance)
|
||||||
s_instance = instance;
|
s_instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWND
|
||||||
|
CMSWindowsScreen::openDesktop()
|
||||||
|
{
|
||||||
|
// save thread id
|
||||||
|
m_threadID = GetCurrentThreadId();
|
||||||
|
|
||||||
|
// get the input desktop and switch to it
|
||||||
|
if (!switchDesktop(openInputDesktop())) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsScreen::closeDesktop()
|
||||||
|
{
|
||||||
|
// remove timer
|
||||||
|
if (m_timer != 0) {
|
||||||
|
KillTimer(NULL, m_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// disconnect from desktop
|
||||||
|
switchDesktop(NULL);
|
||||||
|
|
||||||
|
// clear thread id
|
||||||
|
m_threadID = 0;
|
||||||
|
|
||||||
|
assert(m_window == NULL);
|
||||||
|
assert(m_desk == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMSWindowsScreen::isMultimon() const
|
||||||
|
{
|
||||||
|
return m_multimon;
|
||||||
|
}
|
||||||
|
|
||||||
|
HINSTANCE
|
||||||
|
CMSWindowsScreen::getInstance()
|
||||||
|
{
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsScreen::open()
|
||||||
|
{
|
||||||
|
assert(s_instance != NULL);
|
||||||
|
assert(m_class == 0);
|
||||||
|
|
||||||
|
log((CLOG_DEBUG "opening display"));
|
||||||
|
|
||||||
|
// create the transparent cursor
|
||||||
|
createBlankCursor();
|
||||||
|
|
||||||
|
// register a window class
|
||||||
|
WNDCLASSEX classInfo;
|
||||||
|
classInfo.cbSize = sizeof(classInfo);
|
||||||
|
classInfo.style = CS_DBLCLKS | CS_NOCLOSE;
|
||||||
|
classInfo.lpfnWndProc = &CMSWindowsScreen::wndProc;
|
||||||
|
classInfo.cbClsExtra = 0;
|
||||||
|
classInfo.cbWndExtra = 0;
|
||||||
|
classInfo.hInstance = s_instance;
|
||||||
|
classInfo.hIcon = NULL;
|
||||||
|
classInfo.hCursor = m_cursor;
|
||||||
|
classInfo.hbrBackground = NULL;
|
||||||
|
classInfo.lpszMenuName = NULL;
|
||||||
|
classInfo.lpszClassName = "Synergy";
|
||||||
|
classInfo.hIconSm = NULL;
|
||||||
|
m_class = RegisterClassEx(&classInfo);
|
||||||
|
|
||||||
|
// get screen shape
|
||||||
|
updateScreenShape();
|
||||||
|
|
||||||
|
// initialize the screen saver
|
||||||
|
m_screensaver = new CMSWindowsScreenSaver();
|
||||||
|
|
||||||
|
// load the hook library and get the screen saver functions
|
||||||
|
m_hookLibrary = LoadLibrary("synrgyhk");
|
||||||
|
if (m_hookLibrary != NULL) {
|
||||||
|
m_installScreensaver = (InstallScreenSaverFunc)GetProcAddress(
|
||||||
|
m_hookLibrary, "installScreenSaver");
|
||||||
|
m_uninstallScreensaver = (UninstallScreenSaverFunc)GetProcAddress(
|
||||||
|
m_hookLibrary, "uninstallScreenSaver");
|
||||||
|
if (m_installScreensaver == NULL || m_uninstallScreensaver == NULL) {
|
||||||
|
// disable if either install or uninstall is unavailable
|
||||||
|
m_installScreensaver = NULL;
|
||||||
|
m_uninstallScreensaver = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::mainLoop()
|
CMSWindowsScreen::mainLoop()
|
||||||
{
|
{
|
||||||
// save thread id for posting quit message
|
// must call mainLoop() from same thread as openDesktop()
|
||||||
m_thread = GetCurrentThreadId();
|
assert(m_threadID == GetCurrentThreadId());
|
||||||
|
|
||||||
// event loop
|
// event loop
|
||||||
CEvent event;
|
CEvent event;
|
||||||
|
@ -77,55 +206,25 @@ CMSWindowsScreen::mainLoop()
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::exitMainLoop()
|
CMSWindowsScreen::exitMainLoop()
|
||||||
{
|
{
|
||||||
PostThreadMessage(m_thread, WM_QUIT, 0, 0);
|
PostThreadMessage(m_threadID, WM_QUIT, 0, 0);
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CMSWindowsScreen::onPreDispatch(const CEvent*)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::openDisplay()
|
CMSWindowsScreen::close()
|
||||||
{
|
{
|
||||||
assert(s_instance != NULL);
|
assert(s_instance != NULL);
|
||||||
assert(m_class == 0);
|
|
||||||
|
|
||||||
// create the transparent cursor
|
// done with hook library
|
||||||
createBlankCursor();
|
if (m_hookLibrary != NULL) {
|
||||||
|
FreeLibrary(m_hookLibrary);
|
||||||
// register a window class
|
m_installScreensaver = NULL;
|
||||||
WNDCLASSEX classInfo;
|
m_uninstallScreensaver = NULL;
|
||||||
classInfo.cbSize = sizeof(classInfo);
|
m_hookLibrary = NULL;
|
||||||
classInfo.style = CS_DBLCLKS | CS_NOCLOSE;
|
|
||||||
classInfo.lpfnWndProc = &CMSWindowsScreen::wndProc;
|
|
||||||
classInfo.cbClsExtra = 0;
|
|
||||||
classInfo.cbWndExtra = 0;
|
|
||||||
classInfo.hInstance = s_instance;
|
|
||||||
classInfo.hIcon = NULL;
|
|
||||||
classInfo.hCursor = m_cursor;
|
|
||||||
classInfo.hbrBackground = NULL;
|
|
||||||
classInfo.lpszMenuName = NULL;
|
|
||||||
classInfo.lpszClassName = "Synergy";
|
|
||||||
classInfo.hIconSm = NULL;
|
|
||||||
m_class = RegisterClassEx(&classInfo);
|
|
||||||
|
|
||||||
// get screen shape
|
|
||||||
updateScreenShape();
|
|
||||||
|
|
||||||
// initialize the screen saver
|
|
||||||
m_screenSaver = new CMSWindowsScreenSaver();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsScreen::closeDisplay()
|
|
||||||
{
|
|
||||||
assert(s_instance != NULL);
|
|
||||||
|
|
||||||
// done with screen saver
|
// done with screen saver
|
||||||
delete m_screenSaver;
|
delete m_screensaver;
|
||||||
m_screenSaver = NULL;
|
m_screensaver = NULL;
|
||||||
|
|
||||||
// unregister the window class
|
// unregister the window class
|
||||||
if (m_class != 0) {
|
if (m_class != 0) {
|
||||||
|
@ -142,30 +241,130 @@ CMSWindowsScreen::closeDisplay()
|
||||||
log((CLOG_DEBUG "closed display"));
|
log((CLOG_DEBUG "closed display"));
|
||||||
}
|
}
|
||||||
|
|
||||||
HINSTANCE
|
bool
|
||||||
CMSWindowsScreen::getInstance()
|
CMSWindowsScreen::setClipboard(ClipboardID, const IClipboard* src)
|
||||||
{
|
{
|
||||||
return s_instance;
|
CMSWindowsClipboard dst(m_window);
|
||||||
|
if (src != NULL) {
|
||||||
|
// save clipboard data
|
||||||
|
return CClipboard::copy(&dst, src);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// assert clipboard ownership
|
||||||
|
if (!dst.open(0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dst.empty();
|
||||||
|
dst.close();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ATOM
|
|
||||||
CMSWindowsScreen::getClass() const
|
|
||||||
{
|
|
||||||
return m_class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::updateScreenShape()
|
CMSWindowsScreen::checkClipboards()
|
||||||
{
|
{
|
||||||
m_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
// if we think we own the clipboard but we don't then somebody
|
||||||
m_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
// grabbed the clipboard on this screen without us knowing.
|
||||||
m_w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
// tell the server that this screen grabbed the clipboard.
|
||||||
m_h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
//
|
||||||
log((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h));
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsScreen::getScreenShape(SInt32& x, SInt32& y,
|
CMSWindowsScreen::openScreensaver(bool notify)
|
||||||
|
{
|
||||||
|
assert(m_screensaver != NULL);
|
||||||
|
|
||||||
|
m_screensaverNotify = notify;
|
||||||
|
if (m_screensaverNotify) {
|
||||||
|
if (m_installScreensaver != NULL) {
|
||||||
|
m_installScreensaver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_screensaver->disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsScreen::closeScreensaver()
|
||||||
|
{
|
||||||
|
if (m_screensaver != NULL) {
|
||||||
|
if (m_screensaverNotify) {
|
||||||
|
if (m_uninstallScreensaver != NULL) {
|
||||||
|
m_uninstallScreensaver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_screensaver->enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_screensaverNotify = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsScreen::screensaver(bool activate)
|
||||||
|
{
|
||||||
|
assert(m_screensaver != NULL);
|
||||||
|
if (activate) {
|
||||||
|
m_screensaver->activate();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_screensaver->deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsScreen::syncDesktop()
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
CMSWindowsScreen::getClipboard(ClipboardID, IClipboard* dst) const
|
||||||
|
{
|
||||||
|
CMSWindowsClipboard src(m_window);
|
||||||
|
CClipboard::copy(dst, &src);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsScreen::getShape(SInt32& x, SInt32& y,
|
||||||
SInt32& w, SInt32& h) const
|
SInt32& w, SInt32& h) const
|
||||||
{
|
{
|
||||||
assert(m_class != 0);
|
assert(m_class != 0);
|
||||||
|
@ -196,10 +395,153 @@ CMSWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const
|
||||||
y = GetSystemMetrics(SM_CYSCREEN) >> 1;
|
y = GetSystemMetrics(SM_CYSCREEN) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
HCURSOR
|
void
|
||||||
CMSWindowsScreen::getBlankCursor() const
|
CMSWindowsScreen::updateScreenShape()
|
||||||
{
|
{
|
||||||
return m_cursor;
|
// get shape
|
||||||
|
m_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||||
|
m_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||||
|
m_w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||||
|
m_h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||||
|
log((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h));
|
||||||
|
|
||||||
|
// check for multiple monitors
|
||||||
|
m_multimon = (m_w != GetSystemMetrics(SM_CXSCREEN) ||
|
||||||
|
m_h != GetSystemMetrics(SM_CYSCREEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMSWindowsScreen::onPreDispatch(const CEvent* event)
|
||||||
|
{
|
||||||
|
// handle event
|
||||||
|
const MSG* msg = &event->m_msg;
|
||||||
|
switch (msg->message) {
|
||||||
|
case SYNERGY_MSG_SCREEN_SAVER:
|
||||||
|
if (msg->wParam != 0) {
|
||||||
|
if (m_screensaver->checkStarted(msg->message, FALSE, 0)) {
|
||||||
|
m_eventHandler->onScreensaver(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_eventHandler->onScreensaver(false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case WM_TIMER:
|
||||||
|
// if current desktop is not the input desktop then switch to it.
|
||||||
|
// windows 95 doesn't support multiple desktops so don't bother
|
||||||
|
// to check under it.
|
||||||
|
if (!m_is95Family) {
|
||||||
|
HDESK desk = openInputDesktop();
|
||||||
|
if (desk != NULL) {
|
||||||
|
if (isCurrentDesktop(desk)) {
|
||||||
|
CloseDesktop(desk);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switchDesktop(desk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_eventHandler->onPreDispatch(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMSWindowsScreen::onEvent(CEvent* event)
|
||||||
|
{
|
||||||
|
assert(event != NULL);
|
||||||
|
|
||||||
|
const MSG& msg = event->m_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) {
|
||||||
|
exitMainLoop();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_PAINT:
|
||||||
|
ValidateRect(msg.hwnd, NULL);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
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;
|
||||||
|
getShape(xOld, yOld, wOld, hOld);
|
||||||
|
|
||||||
|
// update shape
|
||||||
|
updateScreenShape();
|
||||||
|
|
||||||
|
// collect new screen info
|
||||||
|
CClientInfo info;
|
||||||
|
getShape(info.m_x, info.m_y, info.m_w, info.m_h);
|
||||||
|
getCursorPos(info.m_mx, info.m_my);
|
||||||
|
info.m_zoneSize = m_eventHandler->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) {
|
||||||
|
// forward event
|
||||||
|
m_eventHandler->onEvent(event);
|
||||||
|
|
||||||
|
// send new screen info
|
||||||
|
m_receiver->onInfoChanged(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_eventHandler->onEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -217,14 +559,122 @@ CMSWindowsScreen::createBlankCursor()
|
||||||
delete[] cursorAND;
|
delete[] cursorAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMSWindowsScreen::switchDesktop(HDESK desk)
|
||||||
|
{
|
||||||
|
// did we own the clipboard?
|
||||||
|
bool ownClipboard = (m_clipboardOwner == m_window && m_window != NULL);
|
||||||
|
|
||||||
|
// destroy old window
|
||||||
|
if (m_window != NULL) {
|
||||||
|
// first remove clipboard snooper
|
||||||
|
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
||||||
|
m_nextClipboardWindow = NULL;
|
||||||
|
|
||||||
|
// we no longer own the clipboard
|
||||||
|
if (ownClipboard) {
|
||||||
|
m_clipboardOwner = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let client clean up before we destroy the window
|
||||||
|
m_eventHandler->preDestroyWindow(m_window);
|
||||||
|
|
||||||
|
// now destroy window
|
||||||
|
DestroyWindow(m_window);
|
||||||
|
m_window = NULL;
|
||||||
|
|
||||||
|
// done with desk
|
||||||
|
if (!m_is95Family) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// uninstall screen saver hooks
|
||||||
|
if (m_screensaverNotify) {
|
||||||
|
if (m_uninstallScreensaver != NULL) {
|
||||||
|
m_uninstallScreensaver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()));
|
||||||
|
if (!m_is95Family) {
|
||||||
|
CloseDesktop(desk);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the window
|
||||||
|
m_window = CreateWindowEx(WS_EX_TOPMOST |
|
||||||
|
WS_EX_TRANSPARENT |
|
||||||
|
WS_EX_TOOLWINDOW,
|
||||||
|
(LPCTSTR)m_class,
|
||||||
|
"Synergy",
|
||||||
|
WS_POPUP,
|
||||||
|
0, 0, 1, 1,
|
||||||
|
NULL, NULL,
|
||||||
|
getInstance(),
|
||||||
|
NULL);
|
||||||
|
if (m_window == NULL) {
|
||||||
|
log((CLOG_ERR "failed to create window: %d", GetLastError()));
|
||||||
|
if (!m_is95Family) {
|
||||||
|
CloseDesktop(desk);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reinstall screen saver hooks
|
||||||
|
if (m_screensaverNotify) {
|
||||||
|
if (m_installScreensaver != NULL) {
|
||||||
|
m_installScreensaver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// install our clipboard snooper
|
||||||
|
m_nextClipboardWindow = SetClipboardViewer(m_window);
|
||||||
|
|
||||||
|
// reassert clipboard ownership
|
||||||
|
if (ownClipboard) {
|
||||||
|
// FIXME -- take clipboard ownership, but we should also set
|
||||||
|
// the clipboard data.
|
||||||
|
}
|
||||||
|
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()));
|
||||||
|
|
||||||
|
// let client prepare the window
|
||||||
|
m_eventHandler->postCreateWindow(m_window);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
HDESK
|
HDESK
|
||||||
CMSWindowsScreen::openInputDesktop() const
|
CMSWindowsScreen::openInputDesktop() const
|
||||||
{
|
{
|
||||||
|
if (m_is95Family) {
|
||||||
|
// there's only one desktop on windows 95 et al.
|
||||||
|
return GetThreadDesktop(GetCurrentThreadId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
return OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, TRUE,
|
return OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, TRUE,
|
||||||
DESKTOP_CREATEWINDOW |
|
DESKTOP_CREATEWINDOW |
|
||||||
DESKTOP_HOOKCONTROL |
|
DESKTOP_HOOKCONTROL |
|
||||||
GENERIC_WRITE);
|
GENERIC_WRITE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CString
|
CString
|
||||||
CMSWindowsScreen::getDesktopName(HDESK desk) const
|
CMSWindowsScreen::getDesktopName(HDESK desk) const
|
||||||
|
@ -232,6 +682,9 @@ CMSWindowsScreen::getDesktopName(HDESK desk) const
|
||||||
if (desk == NULL) {
|
if (desk == NULL) {
|
||||||
return CString();
|
return CString();
|
||||||
}
|
}
|
||||||
|
else if (m_is95Family) {
|
||||||
|
return "desktop";
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
DWORD size;
|
DWORD size;
|
||||||
GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size);
|
GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size);
|
||||||
|
@ -246,14 +699,7 @@ CMSWindowsScreen::getDesktopName(HDESK desk) const
|
||||||
bool
|
bool
|
||||||
CMSWindowsScreen::isCurrentDesktop(HDESK desk) const
|
CMSWindowsScreen::isCurrentDesktop(HDESK desk) const
|
||||||
{
|
{
|
||||||
return CStringUtil::CaselessCmp::equal(getDesktopName(desk),
|
return CStringUtil::CaselessCmp::equal(getDesktopName(desk), m_deskName);
|
||||||
getCurrentDesktopName());
|
|
||||||
}
|
|
||||||
|
|
||||||
CMSWindowsScreenSaver*
|
|
||||||
CMSWindowsScreen::getScreenSaver() const
|
|
||||||
{
|
|
||||||
return m_screenSaver;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK
|
LRESULT CALLBACK
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef CMSWINDOWSSCREEN_H
|
#ifndef CMSWINDOWSSCREEN_H
|
||||||
#define CMSWINDOWSSCREEN_H
|
#define CMSWINDOWSSCREEN_H
|
||||||
|
|
||||||
#include "IClipboard.h"
|
#include "IScreen.h"
|
||||||
|
#include "CSynergyHook.h"
|
||||||
#include "CMutex.h"
|
#include "CMutex.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
@ -16,52 +17,69 @@ public:
|
||||||
LRESULT m_result;
|
LRESULT m_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CMSWindowsScreen {
|
class IScreenReceiver;
|
||||||
|
class IMSWindowsScreenEventHandler;
|
||||||
|
|
||||||
|
class CMSWindowsScreen : public IScreen {
|
||||||
public:
|
public:
|
||||||
CMSWindowsScreen();
|
CMSWindowsScreen(IScreenReceiver*, IMSWindowsScreenEventHandler*);
|
||||||
virtual ~CMSWindowsScreen();
|
virtual ~CMSWindowsScreen();
|
||||||
|
|
||||||
// manipulators
|
// manipulators
|
||||||
|
|
||||||
static void init(HINSTANCE);
|
static void init(HINSTANCE);
|
||||||
|
|
||||||
|
// open the desktop and create and return the window. returns NULL
|
||||||
|
// on failure.
|
||||||
|
HWND openDesktop();
|
||||||
|
|
||||||
|
// close the window and desktop
|
||||||
|
void closeDesktop();
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
|
|
||||||
|
// returns true iff the system appears to have multiple monitors
|
||||||
|
bool isMultimon() const;
|
||||||
|
|
||||||
// get the application instance handle
|
// get the application instance handle
|
||||||
static HINSTANCE getInstance();
|
static HINSTANCE getInstance();
|
||||||
|
|
||||||
protected:
|
// IScreen overrides
|
||||||
// runs an event loop and returns when exitMainLoop() is called
|
// note -- this class expects the hook DLL to have been loaded
|
||||||
|
// and initialized before open() is called.
|
||||||
|
void open();
|
||||||
void mainLoop();
|
void mainLoop();
|
||||||
|
|
||||||
// force mainLoop() to return
|
|
||||||
void exitMainLoop();
|
void exitMainLoop();
|
||||||
|
void close();
|
||||||
|
bool setClipboard(ClipboardID, const IClipboard*);
|
||||||
|
void checkClipboards();
|
||||||
|
void openScreensaver(bool notify);
|
||||||
|
void closeScreensaver();
|
||||||
|
void screensaver(bool activate);
|
||||||
|
void syncDesktop();
|
||||||
|
bool getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
||||||
|
void getCursorPos(SInt32&, SInt32&) const;
|
||||||
|
void getCursorCenter(SInt32&, SInt32&) const;
|
||||||
|
|
||||||
// open the X display. calls onOpenDisplay() after opening the display,
|
private:
|
||||||
// getting the screen, its size, and root window. then it starts the
|
|
||||||
// event thread.
|
|
||||||
void openDisplay();
|
|
||||||
|
|
||||||
// destroy the window and close the display. calls onCloseDisplay()
|
|
||||||
// after the event thread has been shut down but before the display
|
|
||||||
// is closed.
|
|
||||||
void closeDisplay();
|
|
||||||
|
|
||||||
// get the registered window class atom
|
|
||||||
ATOM getClass() const;
|
|
||||||
|
|
||||||
// update screen size cache
|
// update screen size cache
|
||||||
void updateScreenShape();
|
void updateScreenShape();
|
||||||
|
|
||||||
// get the size of the screen
|
// internal pre-dispatch event processing
|
||||||
void getScreenShape(SInt32& x, SInt32& y,
|
bool onPreDispatch(const CEvent* event);
|
||||||
SInt32& width, SInt32& height) const;
|
|
||||||
|
|
||||||
// get the current cursor position
|
// internal (post-dispatch) event processing
|
||||||
void getCursorPos(SInt32& x, SInt32& y) const;
|
bool onEvent(CEvent* event);
|
||||||
|
|
||||||
// get the cursor center position
|
// create the transparent cursor
|
||||||
void getCursorCenter(SInt32& x, SInt32& y) const;
|
void createBlankCursor();
|
||||||
|
|
||||||
|
// switch to the given desktop. this destroys the window and unhooks
|
||||||
|
// all hooks, switches the desktop, then creates the window and rehooks
|
||||||
|
// all hooks (because you can't switch the thread's desktop if it has
|
||||||
|
// any windows or hooks).
|
||||||
|
bool switchDesktop(HDESK desk);
|
||||||
|
|
||||||
// get the input desktop. caller must CloseDesktop() the result.
|
// get the input desktop. caller must CloseDesktop() the result.
|
||||||
// do not call under windows 95/98/me.
|
// do not call under windows 95/98/me.
|
||||||
|
@ -74,38 +92,56 @@ protected:
|
||||||
// windows 95/98/me.
|
// windows 95/98/me.
|
||||||
bool isCurrentDesktop(HDESK desk) const;
|
bool isCurrentDesktop(HDESK desk) const;
|
||||||
|
|
||||||
// get the screen saver object
|
|
||||||
CMSWindowsScreenSaver*
|
|
||||||
getScreenSaver() const;
|
|
||||||
|
|
||||||
// called for each event before event translation and dispatch. return
|
|
||||||
// true to skip translation and dispatch. subclasses should call the
|
|
||||||
// superclass's version first and return true if it returns true.
|
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
|
||||||
|
|
||||||
// called by mainLoop(). iff the event was handled return true and
|
|
||||||
// store the result, if any, in m_result, which defaults to zero.
|
|
||||||
virtual bool onEvent(CEvent* event) = 0;
|
|
||||||
|
|
||||||
// called by isCurrentDesktop() to get the current desktop name
|
|
||||||
virtual CString getCurrentDesktopName() const = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// create the transparent cursor
|
|
||||||
void createBlankCursor();
|
|
||||||
|
|
||||||
// our window proc
|
// our window proc
|
||||||
static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
|
static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static HINSTANCE s_instance;
|
static HINSTANCE s_instance;
|
||||||
|
|
||||||
|
IScreenReceiver* m_receiver;
|
||||||
|
IMSWindowsScreenEventHandler* m_eventHandler;
|
||||||
|
|
||||||
ATOM m_class;
|
ATOM m_class;
|
||||||
HICON m_icon;
|
HICON m_icon;
|
||||||
HCURSOR m_cursor;
|
HCURSOR m_cursor;
|
||||||
|
|
||||||
|
// true if windows 95/98/me
|
||||||
|
bool m_is95Family;
|
||||||
|
|
||||||
|
// our window
|
||||||
|
HWND m_window;
|
||||||
|
|
||||||
|
// screen shape
|
||||||
SInt32 m_x, m_y;
|
SInt32 m_x, m_y;
|
||||||
SInt32 m_w, m_h;
|
SInt32 m_w, m_h;
|
||||||
DWORD m_thread;
|
|
||||||
CMSWindowsScreenSaver* m_screenSaver;
|
// true if system appears to have multiple monitors
|
||||||
|
bool m_multimon;
|
||||||
|
|
||||||
|
// the main loop's thread id
|
||||||
|
DWORD m_threadID;
|
||||||
|
|
||||||
|
// the thread id of the last attached thread
|
||||||
|
DWORD m_lastThreadID;
|
||||||
|
|
||||||
|
// clipboard stuff
|
||||||
|
HWND m_nextClipboardWindow;
|
||||||
|
HWND m_clipboardOwner;
|
||||||
|
|
||||||
|
// the timer used to check for desktop switching
|
||||||
|
UINT m_timer;
|
||||||
|
|
||||||
|
// the current desk and it's name
|
||||||
|
HDESK m_desk;
|
||||||
|
CString m_deskName;
|
||||||
|
|
||||||
|
// screen saver stuff
|
||||||
|
HINSTANCE m_hookLibrary;
|
||||||
|
InstallScreenSaverFunc m_installScreensaver;
|
||||||
|
UninstallScreenSaverFunc m_uninstallScreensaver;
|
||||||
|
CMSWindowsScreenSaver* m_screensaver;
|
||||||
|
bool m_screensaverNotify;
|
||||||
|
|
||||||
static CMSWindowsScreen* s_screen;
|
static CMSWindowsScreen* s_screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
#include "CThread.h"
|
#include "CThread.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include "IJob.h"
|
#include "IJob.h"
|
||||||
//#include "CString.h"
|
|
||||||
//#include <cstdlib>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#if defined(X_DISPLAY_MISSING)
|
#if defined(X_DISPLAY_MISSING)
|
||||||
# error X11 is required to build synergy
|
# error X11 is required to build synergy
|
||||||
|
@ -310,7 +308,7 @@ CXWindowsScreen::checkClipboards()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsScreen::openScreenSaver(bool notify)
|
CXWindowsScreen::openScreensaver(bool notify)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
assert(m_screensaver != NULL);
|
assert(m_screensaver != NULL);
|
||||||
|
@ -325,7 +323,7 @@ CXWindowsScreen::openScreenSaver(bool notify)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsScreen::closeScreenSaver()
|
CXWindowsScreen::closeScreensaver()
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
if (m_screensaver != NULL) {
|
if (m_screensaver != NULL) {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#define CXWINDOWSSCREEN_H
|
#define CXWINDOWSSCREEN_H
|
||||||
|
|
||||||
#include "IScreen.h"
|
#include "IScreen.h"
|
||||||
#include "ClipboardTypes.h"
|
|
||||||
#include "CMutex.h"
|
#include "CMutex.h"
|
||||||
#include "CStopwatch.h"
|
#include "CStopwatch.h"
|
||||||
#include "stdvector.h"
|
#include "stdvector.h"
|
||||||
|
@ -59,8 +58,8 @@ public:
|
||||||
void close();
|
void close();
|
||||||
bool setClipboard(ClipboardID, const IClipboard*);
|
bool setClipboard(ClipboardID, const IClipboard*);
|
||||||
void checkClipboards();
|
void checkClipboards();
|
||||||
void openScreenSaver(bool notify);
|
void openScreensaver(bool notify);
|
||||||
void closeScreenSaver();
|
void closeScreensaver();
|
||||||
void screensaver(bool activate);
|
void screensaver(bool activate);
|
||||||
void syncDesktop();
|
void syncDesktop();
|
||||||
bool getClipboard(ClipboardID, IClipboard*) const;
|
bool getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef IMSWINDOWSSCREENEVENTHANDLER_H
|
||||||
|
#define IMSWINDOWSSCREENEVENTHANDLER_H
|
||||||
|
|
||||||
|
#include "IScreenEventHandler.h"
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
class IMSWindowsScreenEventHandler : public IScreenEventHandler {
|
||||||
|
public:
|
||||||
|
// manipulators
|
||||||
|
|
||||||
|
// called after the window is created
|
||||||
|
virtual void postCreateWindow(HWND) = 0;
|
||||||
|
|
||||||
|
// called before the window is destroyed
|
||||||
|
virtual void preDestroyWindow(HWND) = 0;
|
||||||
|
|
||||||
|
// IScreenEventHandler overrides
|
||||||
|
virtual void onError() = 0;
|
||||||
|
virtual void onScreensaver(bool activated) = 0;
|
||||||
|
virtual bool onPreDispatch(const CEvent* event) = 0;
|
||||||
|
virtual bool onEvent(CEvent* event) = 0;
|
||||||
|
virtual SInt32 getJumpZoneSize() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -127,6 +127,10 @@ SOURCE=.\CWin32Platform.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\IMSWindowsScreenEventHandler.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\IPlatform.h
|
SOURCE=.\IPlatform.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
|
|
|
@ -624,22 +624,22 @@ operator<<(std::ostream& s, const CConfig& config)
|
||||||
screen != config.end(); ++screen) {
|
screen != config.end(); ++screen) {
|
||||||
s << "\t" << screen->c_str() << ":" << std::endl;
|
s << "\t" << screen->c_str() << ":" << std::endl;
|
||||||
|
|
||||||
neighbor = config.getNeighbor(*screen, CConfig::kLeft);
|
neighbor = config.getNeighbor(*screen, kLeft);
|
||||||
if (!neighbor.empty()) {
|
if (!neighbor.empty()) {
|
||||||
s << "\t\tleft=" << neighbor.c_str() << std::endl;
|
s << "\t\tleft=" << neighbor.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor = config.getNeighbor(*screen, CConfig::kRight);
|
neighbor = config.getNeighbor(*screen, kRight);
|
||||||
if (!neighbor.empty()) {
|
if (!neighbor.empty()) {
|
||||||
s << "\t\tright=" << neighbor.c_str() << std::endl;
|
s << "\t\tright=" << neighbor.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor = config.getNeighbor(*screen, CConfig::kTop);
|
neighbor = config.getNeighbor(*screen, kTop);
|
||||||
if (!neighbor.empty()) {
|
if (!neighbor.empty()) {
|
||||||
s << "\t\tup=" << neighbor.c_str() << std::endl;
|
s << "\t\tup=" << neighbor.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor = config.getNeighbor(*screen, CConfig::kBottom);
|
neighbor = config.getNeighbor(*screen, kBottom);
|
||||||
if (!neighbor.empty()) {
|
if (!neighbor.empty()) {
|
||||||
s << "\t\tdown=" << neighbor.c_str() << std::endl;
|
s << "\t\tdown=" << neighbor.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef CCONFIG_H
|
#ifndef CCONFIG_H
|
||||||
#define CCONFIG_H
|
#define CCONFIG_H
|
||||||
|
|
||||||
|
#include "ProtocolTypes.h"
|
||||||
#include "CNetworkAddress.h"
|
#include "CNetworkAddress.h"
|
||||||
#include "XBase.h"
|
#include "XBase.h"
|
||||||
#include "stdmap.h"
|
#include "stdmap.h"
|
||||||
|
@ -20,11 +21,6 @@ struct iterator_traits<CConfig> {
|
||||||
};
|
};
|
||||||
|
|
||||||
class CConfig {
|
class CConfig {
|
||||||
public:
|
|
||||||
enum EDirection { kLeft, kRight, kTop, kBottom,
|
|
||||||
kFirstDirection = kLeft, kLastDirection = kBottom };
|
|
||||||
enum EDirectionMask { kLeftMask = 1, kRightMask = 2,
|
|
||||||
kTopMask = 4, kBottomMask = 8 };
|
|
||||||
private:
|
private:
|
||||||
class CCell {
|
class CCell {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -649,7 +649,7 @@ CHTTPServer::CScreenArray::convertFrom(const CConfig& config)
|
||||||
// insert the screen's neighbors
|
// insert the screen's neighbors
|
||||||
// FIXME -- handle edge wrapping
|
// FIXME -- handle edge wrapping
|
||||||
CString neighbor;
|
CString neighbor;
|
||||||
neighbor = config.getNeighbor(name, CConfig::kLeft);
|
neighbor = config.getNeighbor(name, kLeft);
|
||||||
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
||||||
// insert left neighbor, adding a column if necessary
|
// insert left neighbor, adding a column if necessary
|
||||||
if (x == 0 || get(x - 1, y) != neighbor) {
|
if (x == 0 || get(x - 1, y) != neighbor) {
|
||||||
|
@ -659,7 +659,7 @@ CHTTPServer::CScreenArray::convertFrom(const CConfig& config)
|
||||||
}
|
}
|
||||||
screenStack.push_back(neighbor);
|
screenStack.push_back(neighbor);
|
||||||
}
|
}
|
||||||
neighbor = config.getNeighbor(name, CConfig::kRight);
|
neighbor = config.getNeighbor(name, kRight);
|
||||||
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
||||||
// insert right neighbor, adding a column if necessary
|
// insert right neighbor, adding a column if necessary
|
||||||
if (x == m_w - 1 || get(x + 1, y) != neighbor) {
|
if (x == m_w - 1 || get(x + 1, y) != neighbor) {
|
||||||
|
@ -668,7 +668,7 @@ CHTTPServer::CScreenArray::convertFrom(const CConfig& config)
|
||||||
}
|
}
|
||||||
screenStack.push_back(neighbor);
|
screenStack.push_back(neighbor);
|
||||||
}
|
}
|
||||||
neighbor = config.getNeighbor(name, CConfig::kTop);
|
neighbor = config.getNeighbor(name, kTop);
|
||||||
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
||||||
// insert top neighbor, adding a row if necessary
|
// insert top neighbor, adding a row if necessary
|
||||||
if (y == 0 || get(x, y - 1) != neighbor) {
|
if (y == 0 || get(x, y - 1) != neighbor) {
|
||||||
|
@ -678,7 +678,7 @@ CHTTPServer::CScreenArray::convertFrom(const CConfig& config)
|
||||||
}
|
}
|
||||||
screenStack.push_back(neighbor);
|
screenStack.push_back(neighbor);
|
||||||
}
|
}
|
||||||
neighbor = config.getNeighbor(name, CConfig::kBottom);
|
neighbor = config.getNeighbor(name, kBottom);
|
||||||
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
if (!neighbor.empty() && doneSet.count(neighbor) == 0) {
|
||||||
// insert bottom neighbor, adding a row if necessary
|
// insert bottom neighbor, adding a row if necessary
|
||||||
if (y == m_h - 1 || get(x, y + 1) != neighbor) {
|
if (y == m_h - 1 || get(x, y + 1) != neighbor) {
|
||||||
|
@ -699,25 +699,25 @@ CHTTPServer::CScreenArray::convertFrom(const CConfig& config)
|
||||||
}
|
}
|
||||||
|
|
||||||
CString neighbor;
|
CString neighbor;
|
||||||
neighbor = config.getNeighbor(name, CConfig::kLeft);
|
neighbor = config.getNeighbor(name, kLeft);
|
||||||
if ((x == 0 && !neighbor.empty()) ||
|
if ((x == 0 && !neighbor.empty()) ||
|
||||||
(x > 0 && get(x - 1, y) != neighbor)) {
|
(x > 0 && get(x - 1, y) != neighbor)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor = config.getNeighbor(name, CConfig::kRight);
|
neighbor = config.getNeighbor(name, kRight);
|
||||||
if ((x == m_w - 1 && !neighbor.empty()) ||
|
if ((x == m_w - 1 && !neighbor.empty()) ||
|
||||||
(x < m_w - 1 && get(x + 1, y) != neighbor)) {
|
(x < m_w - 1 && get(x + 1, y) != neighbor)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor = config.getNeighbor(name, CConfig::kTop);
|
neighbor = config.getNeighbor(name, kTop);
|
||||||
if ((y == 0 && !neighbor.empty()) ||
|
if ((y == 0 && !neighbor.empty()) ||
|
||||||
(y > 0 && get(x, y - 1) != neighbor)) {
|
(y > 0 && get(x, y - 1) != neighbor)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor = config.getNeighbor(name, CConfig::kBottom);
|
neighbor = config.getNeighbor(name, kBottom);
|
||||||
if ((y == m_h - 1 && !neighbor.empty()) ||
|
if ((y == m_h - 1 && !neighbor.empty()) ||
|
||||||
(y < m_h - 1 && get(x, y + 1) != neighbor)) {
|
(y < m_h - 1 && get(x, y + 1) != neighbor)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -764,24 +764,16 @@ CHTTPServer::CScreenArray::convertTo(CConfig& config) const
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (x > x0 && isSet(x - 1, y)) {
|
if (x > x0 && isSet(x - 1, y)) {
|
||||||
config.connect(get(x, y),
|
config.connect(get(x, y), kLeft, get(x - 1, y));
|
||||||
CConfig::kLeft,
|
|
||||||
get(x - 1, y));
|
|
||||||
}
|
}
|
||||||
if (x < x1 && isSet(x + 1, y)) {
|
if (x < x1 && isSet(x + 1, y)) {
|
||||||
config.connect(get(x, y),
|
config.connect(get(x, y), kRight, get(x + 1, y));
|
||||||
CConfig::kRight,
|
|
||||||
get(x + 1, y));
|
|
||||||
}
|
}
|
||||||
if (y > y0 && isSet(x, y - 1)) {
|
if (y > y0 && isSet(x, y - 1)) {
|
||||||
config.connect(get(x, y),
|
config.connect(get(x, y), kTop, get(x, y - 1));
|
||||||
CConfig::kTop,
|
|
||||||
get(x, y - 1));
|
|
||||||
}
|
}
|
||||||
if (y < y1 && isSet(x, y + 1)) {
|
if (y < y1 && isSet(x, y + 1)) {
|
||||||
config.connect(get(x, y),
|
config.connect(get(x, y), kBottom, get(x, y + 1));
|
||||||
CConfig::kBottom,
|
|
||||||
get(x, y + 1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
#include "CMSWindowsPrimaryScreen.h"
|
#include "CMSWindowsPrimaryScreen.h"
|
||||||
#include "IScreenReceiver.h"
|
#include "CMSWindowsScreen.h"
|
||||||
#include "IPrimaryScreenReceiver.h"
|
#include "IPrimaryScreenReceiver.h"
|
||||||
#include "CMSWindowsClipboard.h"
|
|
||||||
#include "CMSWindowsScreenSaver.h"
|
|
||||||
#include "CPlatform.h"
|
#include "CPlatform.h"
|
||||||
#include "CClipboard.h"
|
|
||||||
#include "ProtocolTypes.h"
|
|
||||||
#include "XScreen.h"
|
#include "XScreen.h"
|
||||||
#include "XSynergy.h"
|
|
||||||
#include "CThread.h"
|
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -19,21 +13,16 @@
|
||||||
CMSWindowsPrimaryScreen::CMSWindowsPrimaryScreen(
|
CMSWindowsPrimaryScreen::CMSWindowsPrimaryScreen(
|
||||||
IScreenReceiver* receiver,
|
IScreenReceiver* receiver,
|
||||||
IPrimaryScreenReceiver* primaryReceiver) :
|
IPrimaryScreenReceiver* primaryReceiver) :
|
||||||
m_receiver(receiver),
|
CPrimaryScreen(receiver),
|
||||||
m_primaryReceiver(primaryReceiver),
|
m_receiver(primaryReceiver),
|
||||||
|
m_is95Family(CPlatform::isWindows95Family()),
|
||||||
m_threadID(0),
|
m_threadID(0),
|
||||||
m_timer(0),
|
|
||||||
m_desk(NULL),
|
|
||||||
m_deskName(),
|
|
||||||
m_window(NULL),
|
m_window(NULL),
|
||||||
m_active(false),
|
|
||||||
m_mark(0),
|
m_mark(0),
|
||||||
m_markReceived(0),
|
m_markReceived(0),
|
||||||
m_nextClipboardWindow(NULL),
|
m_mouseMoveIgnore(0)
|
||||||
m_clipboardOwner(NULL)
|
|
||||||
{
|
{
|
||||||
assert(m_receiver != NULL);
|
assert(m_receiver != NULL);
|
||||||
assert(m_primaryReceiver != NULL);
|
|
||||||
|
|
||||||
// load the hook library
|
// load the hook library
|
||||||
m_hookLibrary = LoadLibrary("synrgyhk");
|
m_hookLibrary = LoadLibrary("synrgyhk");
|
||||||
|
@ -60,22 +49,8 @@ CMSWindowsPrimaryScreen::CMSWindowsPrimaryScreen(
|
||||||
throw XScreenOpenFailure();
|
throw XScreenOpenFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the screen saver functions
|
// create screen
|
||||||
m_installScreenSaver = (InstallScreenSaverFunc)GetProcAddress(
|
m_screen = new CMSWindowsScreen(receiver, this);
|
||||||
m_hookLibrary, "installScreenSaver");
|
|
||||||
m_uninstallScreenSaver = (UninstallScreenSaverFunc)GetProcAddress(
|
|
||||||
m_hookLibrary, "uninstallScreenSaver");
|
|
||||||
if (m_installScreenSaver == NULL || m_uninstallScreenSaver == NULL) {
|
|
||||||
// disable uninstall if install is unavailable
|
|
||||||
m_uninstallScreenSaver = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// detect operating system
|
|
||||||
m_is95Family = CPlatform::isWindows95Family();
|
|
||||||
|
|
||||||
// make sure this thread has a message queue
|
|
||||||
MSG dummy;
|
|
||||||
PeekMessage(&dummy, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CMSWindowsPrimaryScreen::~CMSWindowsPrimaryScreen()
|
CMSWindowsPrimaryScreen::~CMSWindowsPrimaryScreen()
|
||||||
|
@ -83,169 +58,10 @@ CMSWindowsPrimaryScreen::~CMSWindowsPrimaryScreen()
|
||||||
assert(m_hookLibrary != NULL);
|
assert(m_hookLibrary != NULL);
|
||||||
assert(m_window == NULL);
|
assert(m_window == NULL);
|
||||||
|
|
||||||
// done with hook library
|
delete m_screen;
|
||||||
FreeLibrary(m_hookLibrary);
|
FreeLibrary(m_hookLibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::run()
|
|
||||||
{
|
|
||||||
// must call run() from same thread as open()
|
|
||||||
assert(m_threadID == GetCurrentThreadId());
|
|
||||||
|
|
||||||
// change our priority
|
|
||||||
CThread::getCurrentThread().setPriority(-3);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
CMSWindowsPrimaryScreen::stop()
|
|
||||||
{
|
|
||||||
exitMainLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::open()
|
|
||||||
{
|
|
||||||
assert(m_window == NULL);
|
|
||||||
|
|
||||||
CClientInfo info;
|
|
||||||
try {
|
|
||||||
// initialize hook library
|
|
||||||
m_threadID = GetCurrentThreadId();
|
|
||||||
m_init(m_threadID);
|
|
||||||
|
|
||||||
// open the display
|
|
||||||
openDisplay();
|
|
||||||
|
|
||||||
// create and prepare our window
|
|
||||||
createWindow();
|
|
||||||
|
|
||||||
// set jump zones
|
|
||||||
m_setZone(info.m_x, info.m_y, info.m_w, info.m_h, info.m_zoneSize);
|
|
||||||
|
|
||||||
// initialize marks
|
|
||||||
m_mark = 0;
|
|
||||||
m_markReceived = 0;
|
|
||||||
nextMark();
|
|
||||||
|
|
||||||
// collect screen 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();
|
|
||||||
|
|
||||||
// save mouse position
|
|
||||||
m_x = info.m_mx;
|
|
||||||
m_y = info.m_my;
|
|
||||||
|
|
||||||
// compute center pixel of primary screen
|
|
||||||
getCursorCenter(m_xCenter, m_yCenter);
|
|
||||||
|
|
||||||
// get keyboard state
|
|
||||||
updateKeys();
|
|
||||||
|
|
||||||
// get notified of screen saver activation/deactivation
|
|
||||||
installScreenSaver();
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
close();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// enter the screen
|
|
||||||
enterNoWarp();
|
|
||||||
|
|
||||||
// send screen info
|
|
||||||
m_receiver->onInfoChanged(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::close()
|
|
||||||
{
|
|
||||||
uninstallScreenSaver();
|
|
||||||
destroyWindow();
|
|
||||||
closeDisplay();
|
|
||||||
m_cleanup();
|
|
||||||
m_threadID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver)
|
|
||||||
{
|
|
||||||
log((CLOG_INFO "entering primary at %d,%d%s", x, y, forScreenSaver ? " for screen saver" : ""));
|
|
||||||
assert(m_active == true);
|
|
||||||
assert(m_window != NULL);
|
|
||||||
|
|
||||||
// enter the screen
|
|
||||||
enterNoWarp();
|
|
||||||
|
|
||||||
// warp to requested location
|
|
||||||
if (!forScreenSaver) {
|
|
||||||
warpCursor(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CMSWindowsPrimaryScreen::leave()
|
|
||||||
{
|
|
||||||
log((CLOG_INFO "leaving primary"));
|
|
||||||
assert(m_active == false);
|
|
||||||
assert(m_window != NULL);
|
|
||||||
|
|
||||||
// all messages prior to now are invalid
|
|
||||||
nextMark();
|
|
||||||
|
|
||||||
// show our window
|
|
||||||
if (!showWindow()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// relay all mouse and keyboard events
|
|
||||||
m_setRelay(true);
|
|
||||||
|
|
||||||
// get state of keys as we leave
|
|
||||||
updateKeys();
|
|
||||||
|
|
||||||
// warp mouse to center of screen
|
|
||||||
warpCursorToCenter();
|
|
||||||
|
|
||||||
// ignore this many mouse motion events (not including the already
|
|
||||||
// queued events). on (at least) the win2k login desktop, one
|
|
||||||
// motion event is reported using a position from before the above
|
|
||||||
// warpCursor(). i don't know why it does that and other desktops
|
|
||||||
// don't have the same problem. anyway, simply ignoring that event
|
|
||||||
// works around it.
|
|
||||||
// FIXME -- is this true now that we're using mouse_event?
|
|
||||||
m_mouseMoveIgnore = 1;
|
|
||||||
|
|
||||||
// disable ctrl+alt+del, alt+tab, etc
|
|
||||||
if (m_is95Family) {
|
|
||||||
DWORD dummy = 0;
|
|
||||||
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// discard messages until after the warp
|
|
||||||
nextMark();
|
|
||||||
|
|
||||||
// local client now active
|
|
||||||
m_active = true;
|
|
||||||
|
|
||||||
// make sure our idea of clipboard ownership is correct
|
|
||||||
checkClipboard();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsPrimaryScreen::reconfigure(UInt32 activeSides)
|
CMSWindowsPrimaryScreen::reconfigure(UInt32 activeSides)
|
||||||
{
|
{
|
||||||
|
@ -264,41 +80,6 @@ CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||||
m_y = y;
|
m_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::setClipboard(ClipboardID /*id*/,
|
|
||||||
const IClipboard* src)
|
|
||||||
{
|
|
||||||
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
|
|
||||||
assert(m_window != NULL);
|
|
||||||
|
|
||||||
CMSWindowsClipboard dst(m_window);
|
|
||||||
CClipboard::copy(&dst, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::grabClipboard(ClipboardID /*id*/)
|
|
||||||
{
|
|
||||||
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
|
|
||||||
assert(m_window != NULL);
|
|
||||||
|
|
||||||
CMSWindowsClipboard clipboard(m_window);
|
|
||||||
if (clipboard.open(0)) {
|
|
||||||
// FIXME -- don't we need to empty it?
|
|
||||||
clipboard.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::getClipboard(ClipboardID /*id*/,
|
|
||||||
IClipboard* dst) const
|
|
||||||
{
|
|
||||||
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
|
|
||||||
assert(m_window != NULL);
|
|
||||||
|
|
||||||
CMSWindowsClipboard src(m_window);
|
|
||||||
CClipboard::copy(dst, &src);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyModifierMask
|
KeyModifierMask
|
||||||
CMSWindowsPrimaryScreen::getToggleMask() const
|
CMSWindowsPrimaryScreen::getToggleMask() const
|
||||||
{
|
{
|
||||||
|
@ -334,7 +115,7 @@ CMSWindowsPrimaryScreen::isLockedToScreen() const
|
||||||
// that have been pulled off the queue. in general, we won't get
|
// that have been pulled off the queue. in general, we won't get
|
||||||
// these key messages because they're not for our window. if any
|
// these key messages because they're not for our window. if any
|
||||||
// key (or mouse button) is down then we're locked to the screen.
|
// key (or mouse button) is down then we're locked to the screen.
|
||||||
if (m_active) {
|
if (isActive()) {
|
||||||
// use shadow keyboard state in m_keys
|
// use shadow keyboard state in m_keys
|
||||||
for (UInt32 i = 0; i < 256; ++i) {
|
for (UInt32 i = 0; i < 256; ++i) {
|
||||||
if ((m_keys[i] & 0x80) != 0) {
|
if ((m_keys[i] & 0x80) != 0) {
|
||||||
|
@ -358,16 +139,29 @@ CMSWindowsPrimaryScreen::isLockedToScreen() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IScreen*
|
||||||
|
CMSWindowsPrimaryScreen::getScreen() const
|
||||||
|
{
|
||||||
|
return m_screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onError()
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onScreensaver(bool activated)
|
||||||
|
{
|
||||||
|
m_receiver->onScreensaver(activated);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
|
||||||
{
|
{
|
||||||
assert(event != NULL);
|
assert(event != NULL);
|
||||||
|
|
||||||
// forward to superclass
|
|
||||||
if (CMSWindowsScreen::onPreTranslate(event)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle event
|
// handle event
|
||||||
const MSG* msg = &event->m_msg;
|
const MSG* msg = &event->m_msg;
|
||||||
switch (msg->message) {
|
switch (msg->message) {
|
||||||
|
@ -386,11 +180,11 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
const SInt32 repeat = (SInt32)(msg->lParam & 0xffff);
|
const SInt32 repeat = (SInt32)(msg->lParam & 0xffff);
|
||||||
if (repeat >= 2) {
|
if (repeat >= 2) {
|
||||||
log((CLOG_DEBUG1 "event: key repeat key=%d mask=0x%04x count=%d", key, mask, repeat));
|
log((CLOG_DEBUG1 "event: key repeat key=%d mask=0x%04x count=%d", key, mask, repeat));
|
||||||
m_primaryReceiver->onKeyRepeat(key, mask, repeat);
|
m_receiver->onKeyRepeat(key, mask, repeat);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log((CLOG_DEBUG1 "event: key press key=%d mask=0x%04x", key, mask));
|
log((CLOG_DEBUG1 "event: key press key=%d mask=0x%04x", key, mask));
|
||||||
m_primaryReceiver->onKeyDown(key, mask);
|
m_receiver->onKeyDown(key, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update key state
|
// update key state
|
||||||
|
@ -399,7 +193,7 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
else {
|
else {
|
||||||
// key release
|
// key release
|
||||||
log((CLOG_DEBUG1 "event: key release key=%d mask=0x%04x", key, mask));
|
log((CLOG_DEBUG1 "event: key release key=%d mask=0x%04x", key, mask));
|
||||||
m_primaryReceiver->onKeyUp(key, mask);
|
m_receiver->onKeyUp(key, mask);
|
||||||
|
|
||||||
// update key state
|
// update key state
|
||||||
updateKey(msg->wParam, false);
|
updateKey(msg->wParam, false);
|
||||||
|
@ -428,7 +222,7 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
log((CLOG_DEBUG1 "event: button press button=%d", button));
|
log((CLOG_DEBUG1 "event: button press button=%d", button));
|
||||||
if (button != kButtonNone) {
|
if (button != kButtonNone) {
|
||||||
m_primaryReceiver->onMouseDown(button);
|
m_receiver->onMouseDown(button);
|
||||||
m_keys[s_vkButton[button]] |= 0x80;
|
m_keys[s_vkButton[button]] |= 0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -438,7 +232,7 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
case WM_RBUTTONUP:
|
case WM_RBUTTONUP:
|
||||||
log((CLOG_DEBUG1 "event: button release button=%d", button));
|
log((CLOG_DEBUG1 "event: button release button=%d", button));
|
||||||
if (button != kButtonNone) {
|
if (button != kButtonNone) {
|
||||||
m_primaryReceiver->onMouseUp(button);
|
m_receiver->onMouseUp(button);
|
||||||
m_keys[s_vkButton[button]] &= ~0x80;
|
m_keys[s_vkButton[button]] &= ~0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -450,7 +244,7 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
// ignore message if posted prior to last mark change
|
// ignore message if posted prior to last mark change
|
||||||
if (m_markReceived == m_mark) {
|
if (m_markReceived == m_mark) {
|
||||||
log((CLOG_ERR "event: button wheel delta=%d %d", msg->wParam, msg->lParam));
|
log((CLOG_ERR "event: button wheel delta=%d %d", msg->wParam, msg->lParam));
|
||||||
m_primaryReceiver->onMouseWheel(msg->wParam);
|
m_receiver->onMouseWheel(msg->wParam);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -459,8 +253,8 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
if (m_markReceived == m_mark) {
|
if (m_markReceived == m_mark) {
|
||||||
SInt32 x = static_cast<SInt32>(msg->wParam);
|
SInt32 x = static_cast<SInt32>(msg->wParam);
|
||||||
SInt32 y = static_cast<SInt32>(msg->lParam);
|
SInt32 y = static_cast<SInt32>(msg->lParam);
|
||||||
if (!m_active) {
|
if (!isActive()) {
|
||||||
m_primaryReceiver->onMouseMovePrimary(x, y);
|
m_receiver->onMouseMovePrimary(x, y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// compute motion delta. this is relative to the
|
// compute motion delta. this is relative to the
|
||||||
|
@ -480,7 +274,7 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
warpCursorToCenter();
|
warpCursorToCenter();
|
||||||
|
|
||||||
// send motion
|
// send motion
|
||||||
m_primaryReceiver->onMouseMoveSecondary(x, y);
|
m_receiver->onMouseMoveSecondary(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -495,32 +289,6 @@ CMSWindowsPrimaryScreen::onPreTranslate(const CEvent* event)
|
||||||
m_x = static_cast<SInt32>(msg->wParam);
|
m_x = static_cast<SInt32>(msg->wParam);
|
||||||
m_y = static_cast<SInt32>(msg->lParam);
|
m_y = static_cast<SInt32>(msg->lParam);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case SYNERGY_MSG_SCREEN_SAVER:
|
|
||||||
if (msg->wParam != 0) {
|
|
||||||
if (getScreenSaver()->checkStarted(msg->message, FALSE, 0)) {
|
|
||||||
m_primaryReceiver->onScreenSaver(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_primaryReceiver->onScreenSaver(false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
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;
|
return false;
|
||||||
|
@ -531,111 +299,29 @@ CMSWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||||
{
|
{
|
||||||
assert(event != NULL);
|
assert(event != NULL);
|
||||||
|
|
||||||
const MSG& msg = event->msg;
|
const MSG& msg = event->m_msg;
|
||||||
switch (msg.message) {
|
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_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 server that somebody changed the clipboard.
|
|
||||||
// skip that if we're the new owner.
|
|
||||||
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:
|
case WM_DISPLAYCHANGE:
|
||||||
{
|
|
||||||
// screen resolution may have changed. get old shape.
|
|
||||||
SInt32 xOld, yOld, wOld, hOld;
|
|
||||||
getScreenShape(xOld, yOld, wOld, hOld);
|
|
||||||
|
|
||||||
// update shape
|
|
||||||
updateScreenShape();
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
// recompute center pixel of primary screen
|
// recompute center pixel of primary screen
|
||||||
getCursorCenter(m_xCenter, m_yCenter);
|
m_screen->getCursorCenter(m_xCenter, m_yCenter);
|
||||||
|
|
||||||
// warp mouse to center if active
|
// warp mouse to center if active
|
||||||
if (m_active) {
|
if (isActive()) {
|
||||||
warpCursorToCenter();
|
warpCursorToCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell hook about resize if not active
|
// tell hook about resize if not active
|
||||||
else {
|
else {
|
||||||
m_setZone(info.m_x, info.m_y,
|
SInt32 x, y, w, h;
|
||||||
info.m_w, info.m_h, info.m_zoneSize);
|
m_screen->getShape(x, y, w, h);
|
||||||
|
m_setZone(x, y, w, h, getJumpZoneSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
// send new screen info
|
|
||||||
m_receiver->onInfoChanged(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString
|
|
||||||
CMSWindowsPrimaryScreen::getCurrentDesktopName() const
|
|
||||||
{
|
|
||||||
return m_deskName;
|
|
||||||
}
|
|
||||||
|
|
||||||
SInt32
|
SInt32
|
||||||
CMSWindowsPrimaryScreen::getJumpZoneSize() const
|
CMSWindowsPrimaryScreen::getJumpZoneSize() const
|
||||||
{
|
{
|
||||||
|
@ -643,25 +329,96 @@ CMSWindowsPrimaryScreen::getJumpZoneSize() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsPrimaryScreen::warpCursorToCenter()
|
CMSWindowsPrimaryScreen::postCreateWindow(HWND window)
|
||||||
{
|
{
|
||||||
// warp to center. the extra info tells the hook DLL to send
|
// save window
|
||||||
// SYNERGY_MSG_POST_WARP instead of SYNERGY_MSG_MOUSE_MOVE.
|
m_window = window;
|
||||||
|
|
||||||
|
// install hooks
|
||||||
|
m_install();
|
||||||
|
|
||||||
|
// resize window
|
||||||
|
// note -- we use a fullscreen window to grab input. it should
|
||||||
|
// be possible to use a 1x1 window but i've run into problems
|
||||||
|
// with losing keyboard input (focus?) in that case.
|
||||||
|
// unfortunately, hiding the full screen window (when entering
|
||||||
|
// the screen) causes all other windows to redraw.
|
||||||
SInt32 x, y, w, h;
|
SInt32 x, y, w, h;
|
||||||
getScreenShape(x, y, w, h);
|
m_screen->getShape(x, y, w, h);
|
||||||
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
|
MoveWindow(m_window, x, y, w, h, FALSE);
|
||||||
(DWORD)((65535.99 * (m_xCenter - x)) / (w - 1)),
|
|
||||||
(DWORD)((65535.99 * (m_yCenter - y)) / (h - 1)),
|
if (isActive()) {
|
||||||
0,
|
// hide the cursor
|
||||||
0x12345678);
|
showWindow();
|
||||||
// FIXME -- ignore mouse until we get warp notification?
|
}
|
||||||
|
else {
|
||||||
|
// watch jump zones
|
||||||
|
m_setRelay(false);
|
||||||
|
|
||||||
|
// all messages prior to now are invalid
|
||||||
|
nextMark();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsPrimaryScreen::enterNoWarp()
|
CMSWindowsPrimaryScreen::preDestroyWindow(HWND)
|
||||||
{
|
{
|
||||||
// not active anymore
|
// hide the window if it's visible
|
||||||
m_active = false;
|
if (isActive()) {
|
||||||
|
hideWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// uninstall hooks
|
||||||
|
m_uninstall();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onPreRun()
|
||||||
|
{
|
||||||
|
// must call run() from same thread as open()
|
||||||
|
assert(m_threadID == GetCurrentThreadId());
|
||||||
|
assert(m_window != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onPreOpen()
|
||||||
|
{
|
||||||
|
assert(m_window == NULL);
|
||||||
|
|
||||||
|
// initialize hook library
|
||||||
|
m_threadID = GetCurrentThreadId();
|
||||||
|
m_init(m_threadID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onPostOpen()
|
||||||
|
{
|
||||||
|
// get cursor info
|
||||||
|
m_screen->getCursorPos(m_x, m_y);
|
||||||
|
m_screen->getCursorCenter(m_xCenter, m_yCenter);
|
||||||
|
|
||||||
|
// set jump zones
|
||||||
|
SInt32 x, y, w, h;
|
||||||
|
m_screen->getShape(x, y, w, h);
|
||||||
|
m_setZone(x, y, w, h, getJumpZoneSize());
|
||||||
|
|
||||||
|
// initialize marks
|
||||||
|
m_mark = 0;
|
||||||
|
m_markReceived = 0;
|
||||||
|
nextMark();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onPostClose()
|
||||||
|
{
|
||||||
|
m_cleanup();
|
||||||
|
m_threadID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onPreEnter()
|
||||||
|
{
|
||||||
|
assert(m_window != NULL);
|
||||||
|
|
||||||
// reset motion ignore count
|
// reset motion ignore count
|
||||||
m_mouseMoveIgnore = 0;
|
m_mouseMoveIgnore = 0;
|
||||||
|
@ -674,14 +431,78 @@ CMSWindowsPrimaryScreen::enterNoWarp()
|
||||||
|
|
||||||
// watch jump zones
|
// watch jump zones
|
||||||
m_setRelay(false);
|
m_setRelay(false);
|
||||||
|
}
|
||||||
|
|
||||||
// restore active window and hide our window
|
void
|
||||||
hideWindow();
|
CMSWindowsPrimaryScreen::onPostEnter()
|
||||||
|
{
|
||||||
|
// all messages prior to now are invalid
|
||||||
|
nextMark();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onPreLeave()
|
||||||
|
{
|
||||||
|
assert(m_window != NULL);
|
||||||
|
|
||||||
// all messages prior to now are invalid
|
// all messages prior to now are invalid
|
||||||
nextMark();
|
nextMark();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::onPostLeave(bool success)
|
||||||
|
{
|
||||||
|
if (success) {
|
||||||
|
// relay all mouse and keyboard events
|
||||||
|
m_setRelay(true);
|
||||||
|
|
||||||
|
// ignore this many mouse motion events (not including the already
|
||||||
|
// queued events). on (at least) the win2k login desktop, one
|
||||||
|
// motion event is reported using a position from before the above
|
||||||
|
// warpCursor(). i don't know why it does that and other desktops
|
||||||
|
// don't have the same problem. anyway, simply ignoring that event
|
||||||
|
// works around it.
|
||||||
|
// FIXME -- is this true now that we're using mouse_event?
|
||||||
|
m_mouseMoveIgnore = 1;
|
||||||
|
|
||||||
|
// disable ctrl+alt+del, alt+tab, etc
|
||||||
|
if (m_is95Family) {
|
||||||
|
DWORD dummy = 0;
|
||||||
|
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// discard messages until after the warp
|
||||||
|
nextMark();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::createWindow()
|
||||||
|
{
|
||||||
|
// open the desktop and the window
|
||||||
|
m_window = m_screen->openDesktop();
|
||||||
|
if (m_window == NULL) {
|
||||||
|
throw XScreenOpenFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
// note -- we use a fullscreen window to grab input. it should
|
||||||
|
// be possible to use a 1x1 window but i've run into problems
|
||||||
|
// with losing keyboard input (focus?) in that case.
|
||||||
|
// unfortunately, hiding the full screen window (when entering
|
||||||
|
// the scren causes all other windows to redraw).
|
||||||
|
SInt32 x, y, w, h;
|
||||||
|
m_screen->getShape(x, y, w, h);
|
||||||
|
MoveWindow(m_window, x, y, w, h, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsPrimaryScreen::destroyWindow()
|
||||||
|
{
|
||||||
|
// close the desktop and the window
|
||||||
|
m_screen->closeDesktop();
|
||||||
|
m_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CMSWindowsPrimaryScreen::showWindow()
|
CMSWindowsPrimaryScreen::showWindow()
|
||||||
{
|
{
|
||||||
|
@ -733,262 +554,18 @@ CMSWindowsPrimaryScreen::hideWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CMSWindowsPrimaryScreen::checkClipboard()
|
CMSWindowsPrimaryScreen::warpCursorToCenter()
|
||||||
{
|
{
|
||||||
// if we think we own the clipboard but we don't then somebody
|
// warp to center. the extra info tells the hook DLL to send
|
||||||
// grabbed the clipboard on this screen without us knowing.
|
// SYNERGY_MSG_POST_WARP instead of SYNERGY_MSG_MOUSE_MOVE.
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::createWindow()
|
|
||||||
{
|
|
||||||
// get the input desktop and switch to it
|
|
||||||
if (m_is95Family) {
|
|
||||||
if (!openDesktop()) {
|
|
||||||
throw XScreenOpenFailure();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!switchDesktop(openInputDesktop())) {
|
|
||||||
throw XScreenOpenFailure();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// poll input desktop to see if it changes (preTranslateMessage()
|
|
||||||
// handles WM_TIMER)
|
|
||||||
m_timer = 0;
|
|
||||||
if (!m_is95Family) {
|
|
||||||
m_timer = SetTimer(NULL, 0, 200, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::destroyWindow()
|
|
||||||
{
|
|
||||||
// remove timer
|
|
||||||
if (m_timer != 0) {
|
|
||||||
KillTimer(NULL, m_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// disconnect from desktop
|
|
||||||
if (m_is95Family) {
|
|
||||||
closeDesktop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switchDesktop(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(m_window == NULL);
|
|
||||||
assert(m_desk == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::installScreenSaver()
|
|
||||||
{
|
|
||||||
// install the screen saver hook
|
|
||||||
if (m_installScreenSaver != NULL) {
|
|
||||||
m_installScreenSaver();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::uninstallScreenSaver()
|
|
||||||
{
|
|
||||||
// uninstall the screen saver hook
|
|
||||||
if (m_uninstallScreenSaver != NULL) {
|
|
||||||
m_uninstallScreenSaver();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CMSWindowsPrimaryScreen::openDesktop()
|
|
||||||
{
|
|
||||||
// install hooks
|
|
||||||
m_install();
|
|
||||||
|
|
||||||
// note -- we use a fullscreen window to grab input. it should
|
|
||||||
// be possible to use a 1x1 window but i've run into problems
|
|
||||||
// with losing keyboard input (focus?) in that case.
|
|
||||||
// unfortunately, hiding the full screen window (when entering
|
|
||||||
// the scren causes all other windows to redraw).
|
|
||||||
SInt32 x, y, w, h;
|
SInt32 x, y, w, h;
|
||||||
getScreenShape(x, y, w, h);
|
m_screen->getShape(x, y, w, h);
|
||||||
|
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
|
||||||
// create the window
|
(DWORD)((65535.99 * (m_xCenter - x)) / (w - 1)),
|
||||||
m_window = CreateWindowEx(WS_EX_TOPMOST |
|
(DWORD)((65535.99 * (m_yCenter - y)) / (h - 1)),
|
||||||
WS_EX_TRANSPARENT |
|
0,
|
||||||
WS_EX_TOOLWINDOW,
|
0x12345678);
|
||||||
(LPCTSTR)getClass(),
|
// FIXME -- ignore mouse until we get warp notification?
|
||||||
"Synergy",
|
|
||||||
WS_POPUP,
|
|
||||||
x, y, w, h, NULL, NULL,
|
|
||||||
getInstance(),
|
|
||||||
NULL);
|
|
||||||
if (m_window == NULL) {
|
|
||||||
log((CLOG_ERR "failed to create window: %d", GetLastError()));
|
|
||||||
m_uninstall();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// install our clipboard snooper
|
|
||||||
m_nextClipboardWindow = SetClipboardViewer(m_window);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CMSWindowsPrimaryScreen::closeDesktop()
|
|
||||||
{
|
|
||||||
// destroy old window
|
|
||||||
if (m_window != NULL) {
|
|
||||||
// restore active window and hide ours
|
|
||||||
if (m_active) {
|
|
||||||
hideWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
// first remove clipboard snooper
|
|
||||||
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
|
||||||
m_nextClipboardWindow = NULL;
|
|
||||||
|
|
||||||
// we no longer own the clipboard
|
|
||||||
if (m_clipboardOwner == m_window) {
|
|
||||||
m_clipboardOwner = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now destroy window
|
|
||||||
DestroyWindow(m_window);
|
|
||||||
m_window = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unhook
|
|
||||||
m_uninstall();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CMSWindowsPrimaryScreen::switchDesktop(HDESK desk)
|
|
||||||
{
|
|
||||||
// did we own the clipboard?
|
|
||||||
bool ownClipboard = (m_clipboardOwner == m_window);
|
|
||||||
|
|
||||||
// destroy old window
|
|
||||||
if (m_window != NULL) {
|
|
||||||
// restore active window and hide ours
|
|
||||||
if (m_active) {
|
|
||||||
hideWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
// first remove clipboard snooper
|
|
||||||
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
|
||||||
m_nextClipboardWindow = NULL;
|
|
||||||
|
|
||||||
// we no longer own the clipboard
|
|
||||||
if (ownClipboard) {
|
|
||||||
m_clipboardOwner = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now destroy window
|
|
||||||
DestroyWindow(m_window);
|
|
||||||
m_window = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unhook
|
|
||||||
if (m_desk != NULL) {
|
|
||||||
m_uninstall();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// install hooks
|
|
||||||
m_install();
|
|
||||||
|
|
||||||
// note -- we use a fullscreen window to grab input. it should
|
|
||||||
// be possible to use a 1x1 window but i've run into problems
|
|
||||||
// with losing keyboard input (focus?) in that case.
|
|
||||||
// unfortunately, hiding the full screen window (when entering
|
|
||||||
// the scren causes all other windows to redraw).
|
|
||||||
SInt32 x, y, w, h;
|
|
||||||
getScreenShape(x, y, w, h);
|
|
||||||
|
|
||||||
// create the window
|
|
||||||
m_window = CreateWindowEx(WS_EX_TOPMOST |
|
|
||||||
WS_EX_TRANSPARENT |
|
|
||||||
WS_EX_TOOLWINDOW,
|
|
||||||
(LPCTSTR)getClass(),
|
|
||||||
"Synergy",
|
|
||||||
WS_POPUP,
|
|
||||||
x, y, w, h, NULL, NULL,
|
|
||||||
getInstance(),
|
|
||||||
NULL);
|
|
||||||
if (m_window == NULL) {
|
|
||||||
log((CLOG_ERR "failed to create window: %d", GetLastError()));
|
|
||||||
m_uninstall();
|
|
||||||
CloseDesktop(desk);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// install our clipboard snooper
|
|
||||||
m_nextClipboardWindow = SetClipboardViewer(m_window);
|
|
||||||
|
|
||||||
// reassert clipboard ownership
|
|
||||||
if (ownClipboard) {
|
|
||||||
// FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
// save new desktop
|
|
||||||
m_desk = desk;
|
|
||||||
m_deskName = getDesktopName(m_desk);
|
|
||||||
log((CLOG_INFO "switched to desktop %s", m_deskName.c_str()));
|
|
||||||
|
|
||||||
// get active window and show ours
|
|
||||||
if (m_active) {
|
|
||||||
showWindow();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// watch jump zones
|
|
||||||
m_setRelay(false);
|
|
||||||
|
|
||||||
// all messages prior to now are invalid
|
|
||||||
nextMark();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1,74 +1,61 @@
|
||||||
#ifndef CMSWINDOWSPRIMARYSCREEN_H
|
#ifndef CMSWINDOWSPRIMARYSCREEN_H
|
||||||
#define CMSWINDOWSPRIMARYSCREEN_H
|
#define CMSWINDOWSPRIMARYSCREEN_H
|
||||||
|
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CPrimaryScreen.h"
|
||||||
#include "IPrimaryScreen.h"
|
#include "IMSWindowsScreenEventHandler.h"
|
||||||
#include "CSynergyHook.h"
|
#include "CSynergyHook.h"
|
||||||
#include "MouseTypes.h"
|
#include "MouseTypes.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
|
|
||||||
|
class CMSWindowsScreen;
|
||||||
class IScreenReceiver;
|
class IScreenReceiver;
|
||||||
class IPrimaryScreenReceiver;
|
class IPrimaryScreenReceiver;
|
||||||
|
|
||||||
class CMSWindowsPrimaryScreen : public CMSWindowsScreen, public IPrimaryScreen {
|
class CMSWindowsPrimaryScreen :
|
||||||
|
public CPrimaryScreen, public IMSWindowsScreenEventHandler {
|
||||||
public:
|
public:
|
||||||
typedef bool (CMSWindowsPrimaryScreen::*HookMethod)(int, WPARAM, LPARAM);
|
typedef bool (CMSWindowsPrimaryScreen::*HookMethod)(int, WPARAM, LPARAM);
|
||||||
|
|
||||||
CMSWindowsPrimaryScreen(IScreenReceiver*, IPrimaryScreenReceiver*);
|
CMSWindowsPrimaryScreen(IScreenReceiver*, IPrimaryScreenReceiver*);
|
||||||
virtual ~CMSWindowsPrimaryScreen();
|
virtual ~CMSWindowsPrimaryScreen();
|
||||||
|
|
||||||
// IPrimaryScreen overrides
|
// CPrimaryScreen overrides
|
||||||
virtual void run();
|
|
||||||
virtual void stop();
|
|
||||||
virtual void open();
|
|
||||||
virtual void close();
|
|
||||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute, bool);
|
|
||||||
virtual bool leave();
|
|
||||||
virtual void reconfigure(UInt32 activeSides);
|
virtual void reconfigure(UInt32 activeSides);
|
||||||
virtual void warpCursor(SInt32 xAbsolute, SInt32 yAbsolute);
|
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||||
virtual void setClipboard(ClipboardID, const IClipboard*);
|
|
||||||
virtual void grabClipboard(ClipboardID);
|
|
||||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
|
||||||
virtual KeyModifierMask getToggleMask() const;
|
virtual KeyModifierMask getToggleMask() const;
|
||||||
virtual bool isLockedToScreen() const;
|
virtual bool isLockedToScreen() const;
|
||||||
|
virtual IScreen* getScreen() const;
|
||||||
|
|
||||||
|
// IMSWindowsScreenEventHandler overrides
|
||||||
|
virtual void onError();
|
||||||
|
virtual void onScreensaver(bool activated);
|
||||||
|
virtual bool onPreDispatch(const CEvent* event);
|
||||||
|
virtual bool onEvent(CEvent* event);
|
||||||
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
virtual void postCreateWindow(HWND);
|
||||||
|
virtual void preDestroyWindow(HWND);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CMSWindowsScreen overrides
|
// CPrimaryScreen overrides
|
||||||
virtual bool onPreTranslate(const CEvent* event);
|
virtual void onPreRun();
|
||||||
virtual bool onEvent(CEvent* event);
|
virtual void onPreOpen();
|
||||||
virtual CString getCurrentDesktopName() const;
|
virtual void onPostOpen();
|
||||||
|
virtual void onPostClose();
|
||||||
|
virtual void onPreEnter();
|
||||||
|
virtual void onPostEnter();
|
||||||
|
virtual void onPreLeave();
|
||||||
|
virtual void onPostLeave(bool);
|
||||||
|
|
||||||
|
virtual void createWindow();
|
||||||
|
virtual void destroyWindow();
|
||||||
|
virtual bool showWindow();
|
||||||
|
virtual void hideWindow();
|
||||||
|
virtual void warpCursorToCenter();
|
||||||
|
|
||||||
|
virtual void updateKeys();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SInt32 getJumpZoneSize() const;
|
|
||||||
|
|
||||||
// warp mouse to center of primary display (used when computing
|
|
||||||
// motion deltas while mouse is on secondary screen).
|
|
||||||
void warpCursorToCenter();
|
|
||||||
|
|
||||||
void enterNoWarp();
|
void enterNoWarp();
|
||||||
bool showWindow();
|
|
||||||
void hideWindow();
|
|
||||||
|
|
||||||
// check clipboard ownership and, if necessary, tell the receiver
|
|
||||||
// of a grab.
|
|
||||||
void checkClipboard();
|
|
||||||
|
|
||||||
// create/destroy window
|
|
||||||
// also attach to desktop; this destroys and recreates the window
|
|
||||||
// as necessary.
|
|
||||||
void createWindow();
|
|
||||||
void destroyWindow();
|
|
||||||
|
|
||||||
// start/stop watch for screen saver changes
|
|
||||||
void installScreenSaver();
|
|
||||||
void uninstallScreenSaver();
|
|
||||||
|
|
||||||
// open/close desktop (for windows 95/98/me)
|
|
||||||
bool openDesktop();
|
|
||||||
void closeDesktop();
|
|
||||||
|
|
||||||
// make desk the thread desktop (for windows NT/2000/XP)
|
|
||||||
bool switchDesktop(HDESK desk);
|
|
||||||
|
|
||||||
// discard posted messages
|
// discard posted messages
|
||||||
void nextMark();
|
void nextMark();
|
||||||
|
@ -77,12 +64,11 @@ private:
|
||||||
KeyID mapKey(WPARAM keycode, LPARAM info,
|
KeyID mapKey(WPARAM keycode, LPARAM info,
|
||||||
KeyModifierMask* maskOut);
|
KeyModifierMask* maskOut);
|
||||||
ButtonID mapButton(WPARAM button) const;
|
ButtonID mapButton(WPARAM button) const;
|
||||||
void updateKeys();
|
|
||||||
void updateKey(UINT vkCode, bool press);
|
void updateKey(UINT vkCode, bool press);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IScreenReceiver* m_receiver;
|
IPrimaryScreenReceiver* m_receiver;
|
||||||
IPrimaryScreenReceiver* m_primaryReceiver;
|
CMSWindowsScreen* m_screen;
|
||||||
|
|
||||||
// true if windows 95/98/me
|
// true if windows 95/98/me
|
||||||
bool m_is95Family;
|
bool m_is95Family;
|
||||||
|
@ -90,27 +76,13 @@ private:
|
||||||
// the main loop's thread id
|
// the main loop's thread id
|
||||||
DWORD m_threadID;
|
DWORD m_threadID;
|
||||||
|
|
||||||
// the timer used to check for desktop switching
|
// our window
|
||||||
UINT m_timer;
|
|
||||||
|
|
||||||
// the current desk and it's name
|
|
||||||
HDESK m_desk;
|
|
||||||
CString m_deskName;
|
|
||||||
|
|
||||||
// our window (for getting clipboard changes)
|
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
|
|
||||||
// m_active is true the hooks are relaying events
|
|
||||||
bool m_active;
|
|
||||||
|
|
||||||
// used to discard queued messages that are no longer needed
|
// used to discard queued messages that are no longer needed
|
||||||
UInt32 m_mark;
|
UInt32 m_mark;
|
||||||
UInt32 m_markReceived;
|
UInt32 m_markReceived;
|
||||||
|
|
||||||
// clipboard stuff
|
|
||||||
HWND m_nextClipboardWindow;
|
|
||||||
HWND m_clipboardOwner;
|
|
||||||
|
|
||||||
// map of key state
|
// map of key state
|
||||||
BYTE m_keys[256];
|
BYTE m_keys[256];
|
||||||
|
|
||||||
|
@ -132,8 +104,6 @@ private:
|
||||||
SetSidesFunc m_setSides;
|
SetSidesFunc m_setSides;
|
||||||
SetZoneFunc m_setZone;
|
SetZoneFunc m_setZone;
|
||||||
SetRelayFunc m_setRelay;
|
SetRelayFunc m_setRelay;
|
||||||
InstallScreenSaverFunc m_installScreenSaver;
|
|
||||||
UninstallScreenSaverFunc m_uninstallScreenSaver;
|
|
||||||
|
|
||||||
// stuff for restoring active window
|
// stuff for restoring active window
|
||||||
HWND m_lastForegroundWindow;
|
HWND m_lastForegroundWindow;
|
||||||
|
|
|
@ -73,7 +73,7 @@ CPrimaryScreen::open()
|
||||||
updateKeys();
|
updateKeys();
|
||||||
|
|
||||||
// get notified of screen saver activation/deactivation
|
// get notified of screen saver activation/deactivation
|
||||||
getScreen()->openScreenSaver(true);
|
getScreen()->openScreensaver(true);
|
||||||
|
|
||||||
// subclass hook
|
// subclass hook
|
||||||
onPostOpen();
|
onPostOpen();
|
||||||
|
@ -94,7 +94,7 @@ void
|
||||||
CPrimaryScreen::close()
|
CPrimaryScreen::close()
|
||||||
{
|
{
|
||||||
onPreClose();
|
onPreClose();
|
||||||
getScreen()->closeScreenSaver();
|
getScreen()->closeScreensaver();
|
||||||
destroyWindow();
|
destroyWindow();
|
||||||
getScreen()->close();
|
getScreen()->close();
|
||||||
onPostClose();
|
onPostClose();
|
||||||
|
@ -197,12 +197,6 @@ CPrimaryScreen::getClipboard(ClipboardID id,
|
||||||
getScreen()->getClipboard(id, clipboard);
|
getScreen()->getClipboard(id, clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
SInt32
|
|
||||||
CPrimaryScreen::getJumpZoneSize() const
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CPrimaryScreen::onPreRun()
|
CPrimaryScreen::onPreRun()
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,8 +42,8 @@ public:
|
||||||
bool leave();
|
bool leave();
|
||||||
|
|
||||||
// called when the configuration has changed. activeSides is a
|
// called when the configuration has changed. activeSides is a
|
||||||
// bitmask of CConfig::EDirectionMask indicating which sides of
|
// bitmask of EDirectionMask indicating which sides of the
|
||||||
// the primary screen are linked to clients.
|
// primary screen are linked to clients.
|
||||||
virtual void reconfigure(UInt32 activeSides) = 0;
|
virtual void reconfigure(UInt32 activeSides) = 0;
|
||||||
|
|
||||||
// warp the cursor to the given absolute coordinates
|
// warp the cursor to the given absolute coordinates
|
||||||
|
@ -66,8 +66,8 @@ public:
|
||||||
void getClipboard(ClipboardID, IClipboard*) const;
|
void getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
|
||||||
// returns the size of the zone on the edges of the screen that
|
// returns the size of the zone on the edges of the screen that
|
||||||
// causes the cursor to jump to another screen. default returns 1.
|
// causes the cursor to jump to another screen.
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const = 0;
|
||||||
|
|
||||||
// get the primary screen's current toggle modifier key state.
|
// get the primary screen's current toggle modifier key state.
|
||||||
// the returned mask should have the corresponding bit set for
|
// the returned mask should have the corresponding bit set for
|
||||||
|
|
|
@ -197,21 +197,17 @@ CServer::getActivePrimarySides() const
|
||||||
{
|
{
|
||||||
// note -- m_mutex must be locked on entry
|
// note -- m_mutex must be locked on entry
|
||||||
UInt32 sides = 0;
|
UInt32 sides = 0;
|
||||||
if (!m_config.getNeighbor(getPrimaryScreenName(),
|
if (!m_config.getNeighbor(getPrimaryScreenName(), kLeft).empty()) {
|
||||||
CConfig::kLeft).empty()) {
|
sides |= kLeftMask;
|
||||||
sides |= CConfig::kLeftMask;
|
|
||||||
}
|
}
|
||||||
if (!m_config.getNeighbor(getPrimaryScreenName(),
|
if (!m_config.getNeighbor(getPrimaryScreenName(), kRight).empty()) {
|
||||||
CConfig::kRight).empty()) {
|
sides |= kRightMask;
|
||||||
sides |= CConfig::kRightMask;
|
|
||||||
}
|
}
|
||||||
if (!m_config.getNeighbor(getPrimaryScreenName(),
|
if (!m_config.getNeighbor(getPrimaryScreenName(), kTop).empty()) {
|
||||||
CConfig::kTop).empty()) {
|
sides |= kTopMask;
|
||||||
sides |= CConfig::kTopMask;
|
|
||||||
}
|
}
|
||||||
if (!m_config.getNeighbor(getPrimaryScreenName(),
|
if (!m_config.getNeighbor(getPrimaryScreenName(), kBottom).empty()) {
|
||||||
CConfig::kBottom).empty()) {
|
sides |= kBottomMask;
|
||||||
sides |= CConfig::kBottomMask;
|
|
||||||
}
|
}
|
||||||
return sides;
|
return sides;
|
||||||
}
|
}
|
||||||
|
@ -505,25 +501,25 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y)
|
||||||
SInt32 zoneSize = m_active->getJumpZoneSize();
|
SInt32 zoneSize = m_active->getJumpZoneSize();
|
||||||
|
|
||||||
// see if we should change screens
|
// see if we should change screens
|
||||||
CConfig::EDirection dir;
|
EDirection dir;
|
||||||
if (x < ax + zoneSize) {
|
if (x < ax + zoneSize) {
|
||||||
x -= zoneSize;
|
x -= zoneSize;
|
||||||
dir = CConfig::kLeft;
|
dir = kLeft;
|
||||||
log((CLOG_DEBUG1 "switch to left"));
|
log((CLOG_DEBUG1 "switch to left"));
|
||||||
}
|
}
|
||||||
else if (x >= ax + aw - zoneSize) {
|
else if (x >= ax + aw - zoneSize) {
|
||||||
x += zoneSize;
|
x += zoneSize;
|
||||||
dir = CConfig::kRight;
|
dir = kRight;
|
||||||
log((CLOG_DEBUG1 "switch to right"));
|
log((CLOG_DEBUG1 "switch to right"));
|
||||||
}
|
}
|
||||||
else if (y < ay + zoneSize) {
|
else if (y < ay + zoneSize) {
|
||||||
y -= zoneSize;
|
y -= zoneSize;
|
||||||
dir = CConfig::kTop;
|
dir = kTop;
|
||||||
log((CLOG_DEBUG1 "switch to top"));
|
log((CLOG_DEBUG1 "switch to top"));
|
||||||
}
|
}
|
||||||
else if (y >= ay + ah - zoneSize) {
|
else if (y >= ay + ah - zoneSize) {
|
||||||
y += zoneSize;
|
y += zoneSize;
|
||||||
dir = CConfig::kBottom;
|
dir = kBottom;
|
||||||
log((CLOG_DEBUG1 "switch to bottom"));
|
log((CLOG_DEBUG1 "switch to bottom"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -584,24 +580,24 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy)
|
||||||
IClient* newScreen = NULL;
|
IClient* newScreen = NULL;
|
||||||
if (!isLockedToScreenNoLock()) {
|
if (!isLockedToScreenNoLock()) {
|
||||||
// find direction of neighbor
|
// find direction of neighbor
|
||||||
CConfig::EDirection dir;
|
EDirection dir;
|
||||||
if (m_x < ax) {
|
if (m_x < ax) {
|
||||||
dir = CConfig::kLeft;
|
dir = kLeft;
|
||||||
}
|
}
|
||||||
else if (m_x > ax + aw - 1) {
|
else if (m_x > ax + aw - 1) {
|
||||||
dir = CConfig::kRight;
|
dir = kRight;
|
||||||
}
|
}
|
||||||
else if (m_y < ay) {
|
else if (m_y < ay) {
|
||||||
dir = CConfig::kTop;
|
dir = kTop;
|
||||||
}
|
}
|
||||||
else if (m_y > ay + ah - 1) {
|
else if (m_y > ay + ah - 1) {
|
||||||
dir = CConfig::kBottom;
|
dir = kBottom;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
newScreen = m_active;
|
newScreen = m_active;
|
||||||
|
|
||||||
// keep compiler quiet about unset variable
|
// keep compiler quiet about unset variable
|
||||||
dir = CConfig::kLeft;
|
dir = kLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get neighbor if we should switch
|
// get neighbor if we should switch
|
||||||
|
@ -760,7 +756,7 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver)
|
||||||
}
|
}
|
||||||
|
|
||||||
IClient*
|
IClient*
|
||||||
CServer::getNeighbor(IClient* src, CConfig::EDirection dir) const
|
CServer::getNeighbor(IClient* src, EDirection dir) const
|
||||||
{
|
{
|
||||||
assert(src != NULL);
|
assert(src != NULL);
|
||||||
|
|
||||||
|
@ -793,7 +789,7 @@ CServer::getNeighbor(IClient* src, CConfig::EDirection dir) const
|
||||||
|
|
||||||
IClient*
|
IClient*
|
||||||
CServer::getNeighbor(IClient* src,
|
CServer::getNeighbor(IClient* src,
|
||||||
CConfig::EDirection srcSide, SInt32& x, SInt32& y) const
|
EDirection srcSide, SInt32& x, SInt32& y) const
|
||||||
{
|
{
|
||||||
assert(src != NULL);
|
assert(src != NULL);
|
||||||
|
|
||||||
|
@ -816,7 +812,7 @@ CServer::getNeighbor(IClient* src,
|
||||||
// actual to canonical position on entry to and from canonical to
|
// actual to canonical position on entry to and from canonical to
|
||||||
// actual on exit from the search.
|
// actual on exit from the search.
|
||||||
switch (srcSide) {
|
switch (srcSide) {
|
||||||
case CConfig::kLeft:
|
case kLeft:
|
||||||
x -= dx;
|
x -= dx;
|
||||||
while (dst != NULL && dst != lastGoodScreen) {
|
while (dst != NULL && dst != lastGoodScreen) {
|
||||||
lastGoodScreen = dst;
|
lastGoodScreen = dst;
|
||||||
|
@ -832,7 +828,7 @@ CServer::getNeighbor(IClient* src,
|
||||||
x += dx;
|
x += dx;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CConfig::kRight:
|
case kRight:
|
||||||
x -= dx;
|
x -= dx;
|
||||||
while (dst != NULL) {
|
while (dst != NULL) {
|
||||||
x -= dw;
|
x -= dw;
|
||||||
|
@ -848,7 +844,7 @@ CServer::getNeighbor(IClient* src,
|
||||||
x += dx;
|
x += dx;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CConfig::kTop:
|
case kTop:
|
||||||
y -= dy;
|
y -= dy;
|
||||||
while (dst != NULL) {
|
while (dst != NULL) {
|
||||||
lastGoodScreen = dst;
|
lastGoodScreen = dst;
|
||||||
|
@ -864,7 +860,7 @@ CServer::getNeighbor(IClient* src,
|
||||||
y += dy;
|
y += dy;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CConfig::kBottom:
|
case kBottom:
|
||||||
y -= dy;
|
y -= dy;
|
||||||
while (dst != NULL) {
|
while (dst != NULL) {
|
||||||
y -= dh;
|
y -= dh;
|
||||||
|
@ -892,26 +888,26 @@ CServer::getNeighbor(IClient* src,
|
||||||
if (dst == m_primaryClient) {
|
if (dst == m_primaryClient) {
|
||||||
const CString dstName(dst->getName());
|
const CString dstName(dst->getName());
|
||||||
switch (srcSide) {
|
switch (srcSide) {
|
||||||
case CConfig::kLeft:
|
case kLeft:
|
||||||
if (!m_config.getNeighbor(dstName, CConfig::kRight).empty() &&
|
if (!m_config.getNeighbor(dstName, kRight).empty() &&
|
||||||
x > dx + dw - 1 - dst->getJumpZoneSize())
|
x > dx + dw - 1 - dst->getJumpZoneSize())
|
||||||
x = dx + dw - 1 - dst->getJumpZoneSize();
|
x = dx + dw - 1 - dst->getJumpZoneSize();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CConfig::kRight:
|
case kRight:
|
||||||
if (!m_config.getNeighbor(dstName, CConfig::kLeft).empty() &&
|
if (!m_config.getNeighbor(dstName, kLeft).empty() &&
|
||||||
x < dx + dst->getJumpZoneSize())
|
x < dx + dst->getJumpZoneSize())
|
||||||
x = dx + dst->getJumpZoneSize();
|
x = dx + dst->getJumpZoneSize();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CConfig::kTop:
|
case kTop:
|
||||||
if (!m_config.getNeighbor(dstName, CConfig::kBottom).empty() &&
|
if (!m_config.getNeighbor(dstName, kBottom).empty() &&
|
||||||
y > dy + dh - 1 - dst->getJumpZoneSize())
|
y > dy + dh - 1 - dst->getJumpZoneSize())
|
||||||
y = dy + dh - 1 - dst->getJumpZoneSize();
|
y = dy + dh - 1 - dst->getJumpZoneSize();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CConfig::kBottom:
|
case kBottom:
|
||||||
if (!m_config.getNeighbor(dstName, CConfig::kTop).empty() &&
|
if (!m_config.getNeighbor(dstName, kTop).empty() &&
|
||||||
y < dy + dst->getJumpZoneSize())
|
y < dy + dst->getJumpZoneSize())
|
||||||
y = dy + dst->getJumpZoneSize();
|
y = dy + dst->getJumpZoneSize();
|
||||||
break;
|
break;
|
||||||
|
@ -925,8 +921,8 @@ CServer::getNeighbor(IClient* src,
|
||||||
// should be set 120 pixels from the top (again 20% from the
|
// should be set 120 pixels from the top (again 20% from the
|
||||||
// top).
|
// top).
|
||||||
switch (srcSide) {
|
switch (srcSide) {
|
||||||
case CConfig::kLeft:
|
case kLeft:
|
||||||
case CConfig::kRight:
|
case kRight:
|
||||||
y -= sy;
|
y -= sy;
|
||||||
if (y < 0) {
|
if (y < 0) {
|
||||||
y = 0;
|
y = 0;
|
||||||
|
@ -941,8 +937,8 @@ CServer::getNeighbor(IClient* src,
|
||||||
y += dy;
|
y += dy;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CConfig::kTop:
|
case kTop:
|
||||||
case CConfig::kBottom:
|
case kBottom:
|
||||||
x -= sx;
|
x -= sx;
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
|
@ -96,15 +96,14 @@ private:
|
||||||
SInt32 x, SInt32 y, bool forScreenSaver);
|
SInt32 x, SInt32 y, bool forScreenSaver);
|
||||||
|
|
||||||
// lookup neighboring screen
|
// lookup neighboring screen
|
||||||
IClient* getNeighbor(IClient*, CConfig::EDirection) const;
|
IClient* getNeighbor(IClient*, EDirection) const;
|
||||||
|
|
||||||
// lookup neighboring screen. given a position relative to the
|
// lookup neighboring screen. given a position relative to the
|
||||||
// source screen, find the screen we should move onto and where.
|
// source screen, find the screen we should move onto and where.
|
||||||
// if the position is sufficiently far from the source then we
|
// if the position is sufficiently far from the source then we
|
||||||
// cross multiple screens. if there is no suitable screen then
|
// cross multiple screens. if there is no suitable screen then
|
||||||
// return NULL and x,y are not modified.
|
// return NULL and x,y are not modified.
|
||||||
IClient* getNeighbor(IClient*,
|
IClient* getNeighbor(IClient*, EDirection,
|
||||||
CConfig::EDirection,
|
|
||||||
SInt32& x, SInt32& y) const;
|
SInt32& x, SInt32& y) const;
|
||||||
|
|
||||||
// open/close the primary screen
|
// open/close the primary screen
|
||||||
|
|
|
@ -331,6 +331,12 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SInt32
|
||||||
|
CXWindowsPrimaryScreen::getJumpZoneSize() const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsPrimaryScreen::onPreRun()
|
CXWindowsPrimaryScreen::onPreRun()
|
||||||
{
|
{
|
||||||
|
@ -419,7 +425,7 @@ CXWindowsPrimaryScreen::createWindow()
|
||||||
selectEvents(display, m_screen->getRoot());
|
selectEvents(display, m_screen->getRoot());
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell our superclass about the window
|
// tell generic screen about the window
|
||||||
m_screen->setWindow(m_window);
|
m_screen->setWindow(m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
virtual void onScreensaver(bool activated);
|
virtual void onScreensaver(bool activated);
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
virtual bool onPreDispatch(const CEvent* event);
|
||||||
virtual bool onEvent(CEvent* event);
|
virtual bool onEvent(CEvent* event);
|
||||||
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CPrimaryScreen overrides
|
// CPrimaryScreen overrides
|
||||||
|
|
|
@ -118,6 +118,10 @@ SOURCE=.\CPrimaryClient.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\CPrimaryScreen.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CServer.cpp
|
SOURCE=.\CServer.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -158,11 +162,11 @@ SOURCE=.\CPrimaryClient.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CServer.h
|
SOURCE=.\CPrimaryScreen.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\IPrimaryScreen.h
|
SOURCE=.\CServer.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ public:
|
||||||
// will call IScreenEventHandler's onScreenSaver() when the screensaver
|
// will call IScreenEventHandler's onScreenSaver() when the screensaver
|
||||||
// activates or deactivates until close. if notify is false then
|
// activates or deactivates until close. if notify is false then
|
||||||
// the screen saver is disabled on open and restored on close.
|
// the screen saver is disabled on open and restored on close.
|
||||||
virtual void openScreenSaver(bool notify) = 0;
|
virtual void openScreensaver(bool notify) = 0;
|
||||||
virtual void closeScreenSaver() = 0;
|
virtual void closeScreensaver() = 0;
|
||||||
|
|
||||||
// activate or deactivate the screen saver
|
// activate or deactivate the screen saver
|
||||||
virtual void screensaver(bool activate) = 0;
|
virtual void screensaver(bool activate) = 0;
|
||||||
|
|
|
@ -34,6 +34,11 @@ public:
|
||||||
// called by mainLoop(). iff the event was handled return true and
|
// called by mainLoop(). iff the event was handled return true and
|
||||||
// store the result, if any, in m_result, which defaults to zero.
|
// store the result, if any, in m_result, which defaults to zero.
|
||||||
virtual bool onEvent(CEvent* event) = 0;
|
virtual bool onEvent(CEvent* event) = 0;
|
||||||
|
|
||||||
|
// accessors
|
||||||
|
|
||||||
|
// called to get the jump zone size
|
||||||
|
virtual SInt32 getJumpZoneSize() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,6 +16,23 @@ static const double kHeartRate = 2.0;
|
||||||
// time without a heartbeat that we call death
|
// time without a heartbeat that we call death
|
||||||
static const double kHeartDeath = 3.0 * kHeartRate;
|
static const double kHeartDeath = 3.0 * kHeartRate;
|
||||||
|
|
||||||
|
// direction constants
|
||||||
|
enum EDirection {
|
||||||
|
kLeft,
|
||||||
|
kRight,
|
||||||
|
kTop,
|
||||||
|
kBottom,
|
||||||
|
kFirstDirection = kLeft,
|
||||||
|
kLastDirection = kBottom
|
||||||
|
};
|
||||||
|
enum EDirectionMask {
|
||||||
|
kLeftMask = 1 << kLeft,
|
||||||
|
kRightMask = 1 << kRight,
|
||||||
|
kTopMask = 1 << kTop,
|
||||||
|
kBottomMask = 1 << kBottom
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// message codes (trailing NUL is not part of code). in comments, $n
|
// message codes (trailing NUL is not part of code). in comments, $n
|
||||||
// refers to the n'th argument (counting from one). message codes are
|
// refers to the n'th argument (counting from one). message codes are
|
||||||
|
|
|
@ -155,6 +155,14 @@ SOURCE=.\IPrimaryScreenReceiver.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\IScreen.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\IScreenEventHandler.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\IScreenReceiver.h
|
SOURCE=.\IScreenReceiver.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
Loading…
Reference in New Issue