Merged primary and secondary screens into one class.
This commit is contained in:
parent
4fea7719f3
commit
47ca409ff9
|
@ -13,7 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CClient.h"
|
#include "CClient.h"
|
||||||
#include "ISecondaryScreenFactory.h"
|
#include "IScreenFactory.h"
|
||||||
#include "ProtocolTypes.h"
|
#include "ProtocolTypes.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
#include "XScreen.h"
|
#include "XScreen.h"
|
||||||
|
@ -35,14 +35,13 @@
|
||||||
#define DAEMON_RUNNING(running_)
|
#define DAEMON_RUNNING(running_)
|
||||||
#if WINDOWS_LIKE
|
#if WINDOWS_LIKE
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CMSWindowsScreen.h"
|
||||||
#include "CMSWindowsSecondaryScreen.h"
|
|
||||||
#include "CArchMiscWindows.h"
|
#include "CArchMiscWindows.h"
|
||||||
#include "CMSWindowsClientTaskBarReceiver.h"
|
#include "CMSWindowsClientTaskBarReceiver.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#undef DAEMON_RUNNING
|
#undef DAEMON_RUNNING
|
||||||
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
|
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
|
||||||
#elif UNIX_LIKE
|
#elif UNIX_LIKE
|
||||||
#include "CXWindowsSecondaryScreen.h"
|
#include "CXWindowsScreen.h"
|
||||||
#include "CXWindowsClientTaskBarReceiver.h"
|
#include "CXWindowsClientTaskBarReceiver.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -88,28 +87,28 @@ CArgs* CArgs::s_instance = NULL;
|
||||||
// platform dependent factories
|
// platform dependent factories
|
||||||
//
|
//
|
||||||
|
|
||||||
//! Factory for creating secondary screens
|
//! Factory for creating screens
|
||||||
/*!
|
/*!
|
||||||
Objects of this type create secondary screens appropriate for the
|
Objects of this type create screens appropriate for the platform.
|
||||||
platform.
|
|
||||||
*/
|
*/
|
||||||
class CSecondaryScreenFactory : public ISecondaryScreenFactory {
|
class CScreenFactory : public IScreenFactory {
|
||||||
public:
|
public:
|
||||||
CSecondaryScreenFactory() { }
|
CScreenFactory() { }
|
||||||
virtual ~CSecondaryScreenFactory() { }
|
virtual ~CScreenFactory() { }
|
||||||
|
|
||||||
// ISecondaryScreenFactory overrides
|
// IScreenFactory overrides
|
||||||
virtual CSecondaryScreen*
|
virtual IPlatformScreen*
|
||||||
create(IScreenReceiver*);
|
create(IScreenReceiver*, IPrimaryScreenReceiver*);
|
||||||
};
|
};
|
||||||
|
|
||||||
CSecondaryScreen*
|
IPlatformScreen*
|
||||||
CSecondaryScreenFactory::create(IScreenReceiver* receiver)
|
CScreenFactory::create(IScreenReceiver* receiver,
|
||||||
|
IPrimaryScreenReceiver* primaryReceiver)
|
||||||
{
|
{
|
||||||
#if WINDOWS_LIKE
|
#if WINDOWS_LIKE
|
||||||
return new CMSWindowsSecondaryScreen(receiver);
|
return new CMSWindowsScreen(receiver, primaryReceiver);
|
||||||
#elif UNIX_LIKE
|
#elif UNIX_LIKE
|
||||||
return new CXWindowsSecondaryScreen(receiver);
|
return new CXWindowsScreen(receiver, primaryReceiver);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +166,7 @@ realMain(void)
|
||||||
// create client
|
// create client
|
||||||
s_client = new CClient(ARG->m_name);
|
s_client = new CClient(ARG->m_name);
|
||||||
s_client->setAddress(ARG->m_serverAddress);
|
s_client->setAddress(ARG->m_serverAddress);
|
||||||
s_client->setScreenFactory(new CSecondaryScreenFactory);
|
s_client->setScreenFactory(new CScreenFactory);
|
||||||
s_client->setSocketFactory(new CTCPSocketFactory);
|
s_client->setSocketFactory(new CTCPSocketFactory);
|
||||||
s_client->setStreamFilterFactory(NULL);
|
s_client->setStreamFilterFactory(NULL);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include "CServer.h"
|
#include "CServer.h"
|
||||||
#include "CConfig.h"
|
#include "CConfig.h"
|
||||||
#include "IPrimaryScreenFactory.h"
|
#include "IScreenFactory.h"
|
||||||
#include "ProtocolTypes.h"
|
#include "ProtocolTypes.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
#include "XScreen.h"
|
#include "XScreen.h"
|
||||||
|
@ -34,14 +34,13 @@
|
||||||
#define DAEMON_RUNNING(running_)
|
#define DAEMON_RUNNING(running_)
|
||||||
#if WINDOWS_LIKE
|
#if WINDOWS_LIKE
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CMSWindowsScreen.h"
|
||||||
#include "CMSWindowsPrimaryScreen.h"
|
|
||||||
#include "CArchMiscWindows.h"
|
#include "CArchMiscWindows.h"
|
||||||
#include "CMSWindowsServerTaskBarReceiver.h"
|
#include "CMSWindowsServerTaskBarReceiver.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#undef DAEMON_RUNNING
|
#undef DAEMON_RUNNING
|
||||||
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
|
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
|
||||||
#elif UNIX_LIKE
|
#elif UNIX_LIKE
|
||||||
#include "CXWindowsPrimaryScreen.h"
|
#include "CXWindowsScreen.h"
|
||||||
#include "CXWindowsServerTaskBarReceiver.h"
|
#include "CXWindowsServerTaskBarReceiver.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -100,29 +99,28 @@ CArgs* CArgs::s_instance = NULL;
|
||||||
// platform dependent factories
|
// platform dependent factories
|
||||||
//
|
//
|
||||||
|
|
||||||
//! Factory for creating primary screens
|
//! Factory for creating screens
|
||||||
/*!
|
/*!
|
||||||
Objects of this type create primary screens appropriate for the
|
Objects of this type create screens appropriate for the platform.
|
||||||
platform.
|
|
||||||
*/
|
*/
|
||||||
class CPrimaryScreenFactory : public IPrimaryScreenFactory {
|
class CScreenFactory : public IScreenFactory {
|
||||||
public:
|
public:
|
||||||
CPrimaryScreenFactory() { }
|
CScreenFactory() { }
|
||||||
virtual ~CPrimaryScreenFactory() { }
|
virtual ~CScreenFactory() { }
|
||||||
|
|
||||||
// IPrimaryScreenFactory overrides
|
// IScreenFactory overrides
|
||||||
virtual CPrimaryScreen*
|
virtual IPlatformScreen*
|
||||||
create(IScreenReceiver*, IPrimaryScreenReceiver*);
|
create(IScreenReceiver*, IPrimaryScreenReceiver*);
|
||||||
};
|
};
|
||||||
|
|
||||||
CPrimaryScreen*
|
IPlatformScreen*
|
||||||
CPrimaryScreenFactory::create(IScreenReceiver* receiver,
|
CScreenFactory::create(IScreenReceiver* receiver,
|
||||||
IPrimaryScreenReceiver* primaryReceiver)
|
IPrimaryScreenReceiver* primaryReceiver)
|
||||||
{
|
{
|
||||||
#if WINDOWS_LIKE
|
#if WINDOWS_LIKE
|
||||||
return new CMSWindowsPrimaryScreen(receiver, primaryReceiver);
|
return new CMSWindowsScreen(receiver, primaryReceiver);
|
||||||
#elif UNIX_LIKE
|
#elif UNIX_LIKE
|
||||||
return new CXWindowsPrimaryScreen(receiver, primaryReceiver);
|
return new CXWindowsScreen(receiver, primaryReceiver);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +199,7 @@ realMain(void)
|
||||||
// create server
|
// create server
|
||||||
s_server = new CServer(ARG->m_name);
|
s_server = new CServer(ARG->m_name);
|
||||||
s_server->setConfig(ARG->m_config);
|
s_server->setConfig(ARG->m_config);
|
||||||
s_server->setScreenFactory(new CPrimaryScreenFactory);
|
s_server->setScreenFactory(new CScreenFactory);
|
||||||
s_server->setSocketFactory(new CTCPSocketFactory);
|
s_server->setSocketFactory(new CTCPSocketFactory);
|
||||||
s_server->setStreamFilterFactory(NULL);
|
s_server->setStreamFilterFactory(NULL);
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ dnl checks for system services
|
||||||
|
|
||||||
|
|
||||||
dnl adjust variables for X11 and pthreads
|
dnl adjust variables for X11 and pthreads
|
||||||
CXXFLAGS="$CXXFLAGS $SYNERGY_CXXFLAGS $X_CFLAGS $PTHREAD_CFLAGS"
|
CXXFLAGS="$CXXFLAGS $SYNERGY_CXXFLAGS $X_CFLAGS $PTHREAD_CFLAGS -D_BSD_SOURCE -D_XOPEN_SOURCE=500"
|
||||||
LIBS="$NANOSLEEP_LIBS $INET_ATON_LIBS $PTHREAD_LIBS $LIBS"
|
LIBS="$NANOSLEEP_LIBS $INET_ATON_LIBS $PTHREAD_LIBS $LIBS"
|
||||||
|
|
||||||
AC_OUTPUT([
|
AC_OUTPUT([
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
# include "CArchDaemonWindows.h"
|
# include "CArchDaemonWindows.h"
|
||||||
# include "CArchFileWindows.h"
|
# include "CArchFileWindows.h"
|
||||||
# include "CArchLogWindows.h"
|
# include "CArchLogWindows.h"
|
||||||
|
# include "CArchMiscWindows.h"
|
||||||
# include "CArchMultithreadWindows.h"
|
# include "CArchMultithreadWindows.h"
|
||||||
# include "CArchNetworkWinsock.h"
|
# include "CArchNetworkWinsock.h"
|
||||||
# include "CArchSleepWindows.h"
|
# include "CArchSleepWindows.h"
|
||||||
|
@ -116,6 +117,10 @@ CArch::CArch(ARCH_ARGS* args)
|
||||||
m_console = new ARCH_CONSOLE;
|
m_console = new ARCH_CONSOLE;
|
||||||
m_daemon = new ARCH_DAEMON;
|
m_daemon = new ARCH_DAEMON;
|
||||||
m_taskbar = new ARCH_TASKBAR(args);
|
m_taskbar = new ARCH_TASKBAR(args);
|
||||||
|
|
||||||
|
#if WINDOWS_LIKE
|
||||||
|
CArchMiscWindows::init();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CArch::~CArch()
|
CArch::~CArch()
|
||||||
|
|
|
@ -29,6 +29,13 @@ CArchConsoleWindows::CArchConsoleWindows() :
|
||||||
s_thread = ARCH->newCurrentThread();
|
s_thread = ARCH->newCurrentThread();
|
||||||
|
|
||||||
m_mutex = ARCH->newMutex();
|
m_mutex = ARCH->newMutex();
|
||||||
|
|
||||||
|
// dummy write to stderr to create locks in stdio from the main
|
||||||
|
// thread. if we open the console from another thread then we
|
||||||
|
// can deadlock in stdio when trying to write from a 3rd thread.
|
||||||
|
// writes to stderr without a console don't go anywhere so the
|
||||||
|
// user won't notice this.
|
||||||
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CArchConsoleWindows::~CArchConsoleWindows()
|
CArchConsoleWindows::~CArchConsoleWindows()
|
||||||
|
|
|
@ -19,16 +19,31 @@
|
||||||
// CArchMiscWindows
|
// CArchMiscWindows
|
||||||
//
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
CArchMiscWindows::init()
|
||||||
|
{
|
||||||
|
isWindows95Family();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CArchMiscWindows::isWindows95Family()
|
CArchMiscWindows::isWindows95Family()
|
||||||
{
|
{
|
||||||
|
static bool init = false;
|
||||||
|
static bool result = false;
|
||||||
|
|
||||||
|
if (!init) {
|
||||||
OSVERSIONINFO version;
|
OSVERSIONINFO version;
|
||||||
version.dwOSVersionInfoSize = sizeof(version);
|
version.dwOSVersionInfoSize = sizeof(version);
|
||||||
if (GetVersionEx(&version) == 0) {
|
if (GetVersionEx(&version) == 0) {
|
||||||
// cannot determine OS; assume windows 95 family
|
// cannot determine OS; assume windows 95 family
|
||||||
return true;
|
result = true;
|
||||||
}
|
}
|
||||||
return (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
else {
|
||||||
|
result = (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
||||||
|
}
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -26,6 +26,9 @@ class CArchMiscWindows {
|
||||||
public:
|
public:
|
||||||
typedef int (*RunFunc)(void);
|
typedef int (*RunFunc)(void);
|
||||||
|
|
||||||
|
//! Initialize
|
||||||
|
static void init();
|
||||||
|
|
||||||
//! Test if windows 95, et al.
|
//! Test if windows 95, et al.
|
||||||
/*!
|
/*!
|
||||||
Returns true iff the platform is win95/98/me.
|
Returns true iff the platform is win95/98/me.
|
||||||
|
|
|
@ -252,14 +252,12 @@ CArchMultithreadPosix::waitCondVar(CArchCond cond,
|
||||||
CArchMutex
|
CArchMutex
|
||||||
CArchMultithreadPosix::newMutex()
|
CArchMultithreadPosix::newMutex()
|
||||||
{
|
{
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
int status = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
assert(status == 0);
|
||||||
CArchMutexImpl* mutex = new CArchMutexImpl;
|
CArchMutexImpl* mutex = new CArchMutexImpl;
|
||||||
int status = pthread_mutex_init(&mutex->m_mutex, NULL);
|
status = pthread_mutex_init(&mutex->m_mutex, &attr);
|
||||||
assert(status == 0);
|
assert(status == 0);
|
||||||
/*
|
|
||||||
status = pthread_mutexattr_settype(&mutex->m_mutex,
|
|
||||||
PTHREAD_MUTEX_RECURSIVE);
|
|
||||||
assert(status == 0);
|
|
||||||
*/
|
|
||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,11 @@ public:
|
||||||
// mutex methods
|
// mutex methods
|
||||||
//
|
//
|
||||||
|
|
||||||
//! Create a non-recursive mutex
|
//! Create a recursive mutex
|
||||||
/*!
|
/*!
|
||||||
Creates a non-recursive mutex. A thread must not lock a
|
Creates a recursive mutex. A thread may lock a recursive mutex
|
||||||
non-recursive mutex when it already holds a lock on that mutex.
|
when it already holds a lock on that mutex. The mutex is an
|
||||||
If it does it will deadlock. The mutex is an opaque data type.
|
opaque data type.
|
||||||
*/
|
*/
|
||||||
virtual CArchMutex newMutex() = 0;
|
virtual CArchMutex newMutex() = 0;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPRIORITYQUEUE_H
|
||||||
|
#define CPRIORITYQUEUE_H
|
||||||
|
|
||||||
|
#include "stdvector.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
//! A priority queue with an iterator
|
||||||
|
/*!
|
||||||
|
This priority queue is the same as a standard priority queue except:
|
||||||
|
it sorts by std::greater, it has a forward iterator through the elements
|
||||||
|
(which can appear in any order), and its contents can be swapped.
|
||||||
|
*/
|
||||||
|
template <class T, class Container = std::vector<T>,
|
||||||
|
class Compare = std::greater<typename Container::value_type> >
|
||||||
|
class CPriorityQueue {
|
||||||
|
public:
|
||||||
|
typedef typename Container::value_type value_type;
|
||||||
|
typedef typename Container::size_type size_type;
|
||||||
|
typedef typename Container::iterator iterator;
|
||||||
|
typedef typename Container::const_iterator const_iterator;
|
||||||
|
typedef Container container_type;
|
||||||
|
|
||||||
|
CPriorityQueue() { }
|
||||||
|
CPriorityQueue(Container& swappedIn) { swap(swappedIn); }
|
||||||
|
~CPriorityQueue() { }
|
||||||
|
|
||||||
|
//! @name manipulators
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Add element
|
||||||
|
void push(const value_type& v)
|
||||||
|
{
|
||||||
|
c.push_back(v);
|
||||||
|
std::push_heap(c.begin(), c.end(), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Remove head element
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
std::pop_heap(c.begin(), c.end(), comp);
|
||||||
|
c.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Get start iterator
|
||||||
|
iterator begin()
|
||||||
|
{
|
||||||
|
return c.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Get end iterator
|
||||||
|
iterator end()
|
||||||
|
{
|
||||||
|
return c.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Swap contents with another priority queue
|
||||||
|
void swap(CPriorityQueue<T, Container, Compare>& q)
|
||||||
|
{
|
||||||
|
c.swap(q.c);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Swap contents with another container
|
||||||
|
void swap(Container& c2)
|
||||||
|
{
|
||||||
|
c.swap(c2);
|
||||||
|
std::make_heap(c.begin(), c.end(), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//@}
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Returns true if there are no elements
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return c.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns the number of elements
|
||||||
|
size_type size() const
|
||||||
|
{
|
||||||
|
return c.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns the head element
|
||||||
|
const value_type& top() const
|
||||||
|
{
|
||||||
|
return c.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Get start iterator
|
||||||
|
const_iterator begin() const
|
||||||
|
{
|
||||||
|
return c.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Get end iterator
|
||||||
|
const_iterator end() const
|
||||||
|
{
|
||||||
|
return c.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Container c;
|
||||||
|
Compare comp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -36,6 +36,7 @@ libbase_a_SOURCES = \
|
||||||
CFunctionJob.h \
|
CFunctionJob.h \
|
||||||
CJobList.h \
|
CJobList.h \
|
||||||
CLog.h \
|
CLog.h \
|
||||||
|
CPriorityQueue.h \
|
||||||
CStopwatch.h \
|
CStopwatch.h \
|
||||||
CString.h \
|
CString.h \
|
||||||
CStringUtil.h \
|
CStringUtil.h \
|
||||||
|
|
|
@ -14,12 +14,13 @@
|
||||||
|
|
||||||
#include "CClient.h"
|
#include "CClient.h"
|
||||||
#include "CServerProxy.h"
|
#include "CServerProxy.h"
|
||||||
#include "ISecondaryScreenFactory.h"
|
#include "CScreen.h"
|
||||||
|
#include "IScreenFactory.h"
|
||||||
#include "CClipboard.h"
|
#include "CClipboard.h"
|
||||||
#include "CInputPacketStream.h"
|
#include "CInputPacketStream.h"
|
||||||
#include "COutputPacketStream.h"
|
#include "COutputPacketStream.h"
|
||||||
#include "CProtocolUtil.h"
|
#include "CProtocolUtil.h"
|
||||||
#include "CSecondaryScreen.h"
|
#include "IPlatformScreen.h"
|
||||||
#include "IServer.h"
|
#include "IServer.h"
|
||||||
#include "ProtocolTypes.h"
|
#include "ProtocolTypes.h"
|
||||||
#include "XScreen.h"
|
#include "XScreen.h"
|
||||||
|
@ -72,7 +73,7 @@ CClient::setAddress(const CNetworkAddress& serverAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClient::setScreenFactory(ISecondaryScreenFactory* adopted)
|
CClient::setScreenFactory(IScreenFactory* adopted)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
delete m_screenFactory;
|
delete m_screenFactory;
|
||||||
|
@ -305,8 +306,9 @@ CClient::enter(SInt32 xAbs, SInt32 yAbs, UInt32, KeyModifierMask mask, bool)
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
m_active = true;
|
m_active = true;
|
||||||
}
|
}
|
||||||
|
m_screen->mouseMove(xAbs, yAbs);
|
||||||
m_screen->enter(xAbs, yAbs, mask);
|
m_screen->enter();
|
||||||
|
m_screen->setToggleState(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -464,7 +466,10 @@ CClient::openSecondaryScreen()
|
||||||
// create screen
|
// create screen
|
||||||
LOG((CLOG_DEBUG1 "creating secondary screen"));
|
LOG((CLOG_DEBUG1 "creating secondary screen"));
|
||||||
if (m_screenFactory != NULL) {
|
if (m_screenFactory != NULL) {
|
||||||
m_screen = m_screenFactory->create(this);
|
IPlatformScreen* platformScreen = m_screenFactory->create(this, NULL);
|
||||||
|
if (platformScreen != NULL) {
|
||||||
|
m_screen = new CScreen(platformScreen, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m_screen == NULL) {
|
if (m_screen == NULL) {
|
||||||
throw XScreenOpenFailure();
|
throw XScreenOpenFailure();
|
||||||
|
@ -634,9 +639,11 @@ CClient::runServer()
|
||||||
m_server = proxy;
|
m_server = proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool enabled = false;
|
||||||
try {
|
try {
|
||||||
// prepare for remote control
|
// enable the screen
|
||||||
m_screen->remoteControl();
|
m_screen->enable();
|
||||||
|
enabled = true;
|
||||||
|
|
||||||
// process messages
|
// process messages
|
||||||
bool rejected = true;
|
bool rejected = true;
|
||||||
|
@ -647,8 +654,8 @@ CClient::runServer()
|
||||||
setStatus(kNotRunning);
|
setStatus(kNotRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare for local control
|
// disable the screen
|
||||||
m_screen->localControl();
|
m_screen->disable();
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
|
@ -661,7 +668,9 @@ CClient::runServer()
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
setStatus(kNotRunning);
|
setStatus(kNotRunning);
|
||||||
m_screen->localControl();
|
if (enabled) {
|
||||||
|
m_screen->disable();
|
||||||
|
}
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
m_rejected = false;
|
m_rejected = false;
|
||||||
m_server = NULL;
|
m_server = NULL;
|
||||||
|
|
|
@ -22,12 +22,12 @@
|
||||||
#include "CMutex.h"
|
#include "CMutex.h"
|
||||||
#include "CJobList.h"
|
#include "CJobList.h"
|
||||||
|
|
||||||
class CSecondaryScreen;
|
class CScreen;
|
||||||
class CServerProxy;
|
class CServerProxy;
|
||||||
class CThread;
|
class CThread;
|
||||||
class IDataSocket;
|
class IDataSocket;
|
||||||
class IScreenReceiver;
|
class IScreenReceiver;
|
||||||
class ISecondaryScreenFactory;
|
class IScreenFactory;
|
||||||
class ISocketFactory;
|
class ISocketFactory;
|
||||||
class IStreamFilterFactory;
|
class IStreamFilterFactory;
|
||||||
|
|
||||||
|
@ -60,13 +60,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void setAddress(const CNetworkAddress& serverAddress);
|
void setAddress(const CNetworkAddress& serverAddress);
|
||||||
|
|
||||||
//! Set secondary screen factory
|
//! Set screen factory
|
||||||
/*!
|
/*!
|
||||||
Sets the factory for creating secondary screens. This must be
|
Sets the factory for creating screens. This must be set before
|
||||||
set before calling open(). This object takes ownership of the
|
calling open(). This object takes ownership of the factory.
|
||||||
factory.
|
|
||||||
*/
|
*/
|
||||||
void setScreenFactory(ISecondaryScreenFactory*);
|
void setScreenFactory(IScreenFactory*);
|
||||||
|
|
||||||
//! Set socket factory
|
//! Set socket factory
|
||||||
/*!
|
/*!
|
||||||
|
@ -184,10 +183,10 @@ private:
|
||||||
private:
|
private:
|
||||||
CMutex m_mutex;
|
CMutex m_mutex;
|
||||||
CString m_name;
|
CString m_name;
|
||||||
CSecondaryScreen* m_screen;
|
CScreen* m_screen;
|
||||||
IScreenReceiver* m_server;
|
IScreenReceiver* m_server;
|
||||||
CNetworkAddress m_serverAddress;
|
CNetworkAddress m_serverAddress;
|
||||||
ISecondaryScreenFactory* m_screenFactory;
|
IScreenFactory* m_screenFactory;
|
||||||
ISocketFactory* m_socketFactory;
|
ISocketFactory* m_socketFactory;
|
||||||
IStreamFilterFactory* m_streamFilterFactory;
|
IStreamFilterFactory* m_streamFilterFactory;
|
||||||
CThread* m_session;
|
CThread* m_session;
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2002 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CMSWindowsDesktop.h"
|
||||||
|
#include "CLog.h"
|
||||||
|
#include "CArchMiscWindows.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// CMSWindowsDesktop
|
||||||
|
//
|
||||||
|
|
||||||
|
HDESK
|
||||||
|
CMSWindowsDesktop::openInputDesktop()
|
||||||
|
{
|
||||||
|
if (CArchMiscWindows::isWindows95Family()) {
|
||||||
|
// there's only one desktop on windows 95 et al.
|
||||||
|
return GetThreadDesktop(GetCurrentThreadId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, TRUE,
|
||||||
|
DESKTOP_CREATEWINDOW |
|
||||||
|
DESKTOP_HOOKCONTROL |
|
||||||
|
GENERIC_WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsDesktop::closeDesktop(HDESK desk)
|
||||||
|
{
|
||||||
|
// on 95/98/me we don't need to close the desktop returned by
|
||||||
|
// openInputDesktop().
|
||||||
|
if (desk != NULL && !CArchMiscWindows::isWindows95Family()) {
|
||||||
|
CloseDesktop(desk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CMSWindowsDesktop::setDesktop(HDESK desk)
|
||||||
|
{
|
||||||
|
// 95/98/me doesn't support multiple desktops so just return
|
||||||
|
// true on those platforms.
|
||||||
|
return (CArchMiscWindows::isWindows95Family() ||
|
||||||
|
SetThreadDesktop(desk) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
CMSWindowsDesktop::getDesktopName(HDESK desk)
|
||||||
|
{
|
||||||
|
if (desk == NULL) {
|
||||||
|
return CString();
|
||||||
|
}
|
||||||
|
else if (CArchMiscWindows::isWindows95Family()) {
|
||||||
|
return "desktop";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DWORD size;
|
||||||
|
GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size);
|
||||||
|
TCHAR* name = (TCHAR*)alloca(size + sizeof(TCHAR));
|
||||||
|
GetUserObjectInformation(desk, UOI_NAME, name, size, &size);
|
||||||
|
CString result(name);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2002 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CMSWINDOWSDESKTOP_H
|
||||||
|
#define CMSWINDOWSDESKTOP_H
|
||||||
|
|
||||||
|
#include "CString.h"
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
//! Encapsulate Microsoft Windows desktop
|
||||||
|
class CMSWindowsDesktop {
|
||||||
|
public:
|
||||||
|
//! Open the input desktop
|
||||||
|
/*!
|
||||||
|
Opens the input desktop. The caller must close the desktop.
|
||||||
|
*/
|
||||||
|
static HDESK openInputDesktop();
|
||||||
|
|
||||||
|
//! Close a desktop
|
||||||
|
/*!
|
||||||
|
Closes the given desktop.
|
||||||
|
*/
|
||||||
|
static void closeDesktop(HDESK);
|
||||||
|
|
||||||
|
//! Change current desktop
|
||||||
|
/*!
|
||||||
|
Changes the calling thread's desktop, return true iff successful.
|
||||||
|
The call will fail if the calling thread has any windows or a hooks
|
||||||
|
on the current desktop.
|
||||||
|
*/
|
||||||
|
static bool setDesktop(HDESK);
|
||||||
|
|
||||||
|
//! Get the desktop's name.
|
||||||
|
/*!
|
||||||
|
Returns the current desktop's name. Returns a constant string
|
||||||
|
on 95/98/Me.
|
||||||
|
*/
|
||||||
|
static CString getDesktopName(HDESK);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CMSWINDOWSKEYMAPPER_H
|
||||||
|
#define CMSWINDOWSKEYMAPPER_H
|
||||||
|
|
||||||
|
#include "IKeyState.h"
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
//! Microsoft Windows key mapper
|
||||||
|
/*!
|
||||||
|
This class maps KeyIDs to keystrokes.
|
||||||
|
*/
|
||||||
|
class CMSWindowsKeyMapper {
|
||||||
|
public:
|
||||||
|
CMSWindowsKeyMapper();
|
||||||
|
~CMSWindowsKeyMapper();
|
||||||
|
|
||||||
|
//! @name manipulators
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Update key mapper
|
||||||
|
/*!
|
||||||
|
Updates the key mapper's internal tables according to the
|
||||||
|
current keyboard mapping and updates \c keyState.
|
||||||
|
*/
|
||||||
|
void update(IKeyState* keyState);
|
||||||
|
|
||||||
|
//! Update shadow key state
|
||||||
|
/*!
|
||||||
|
Updates the shadow keyboard state.
|
||||||
|
*/
|
||||||
|
void updateKey(KeyButton key, bool pressed);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Map key press/repeat to keystrokes
|
||||||
|
/*!
|
||||||
|
Converts a press/repeat of key \c id with the modifiers as given
|
||||||
|
in \c desiredMask into the keystrokes necessary to synthesize
|
||||||
|
that key event. Returns the platform specific code of the key
|
||||||
|
being pressed, or 0 if the key cannot be mapped or \c isAutoRepeat
|
||||||
|
is true and the key does not auto-repeat.
|
||||||
|
*/
|
||||||
|
KeyButton mapKey(IKeyState::Keystrokes&,
|
||||||
|
const IKeyState& keyState, KeyID id,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
//! Map key event to a key
|
||||||
|
/*!
|
||||||
|
Converts a key event into a KeyID and the shadow modifier state
|
||||||
|
to a modifier mask. If \c altgr is non-NULL it's set to true if
|
||||||
|
the key requires AltGr and false otherwise.
|
||||||
|
*/
|
||||||
|
KeyID mapKeyFromEvent(WPARAM vkCode, LPARAM info,
|
||||||
|
KeyModifierMask* maskOut, bool* altgr) const;
|
||||||
|
|
||||||
|
//! Test shadow key state
|
||||||
|
/*!
|
||||||
|
Returns true iff the shadow state indicates the key is pressed.
|
||||||
|
*/
|
||||||
|
bool isPressed(KeyButton key) const;
|
||||||
|
|
||||||
|
//! Map key to a scan code
|
||||||
|
/*!
|
||||||
|
Returns the scan code for \c key and possibly adjusts \c key.
|
||||||
|
*/
|
||||||
|
UINT keyToScanCode(KeyButton* key) const;
|
||||||
|
|
||||||
|
//! Check for extended key
|
||||||
|
/*!
|
||||||
|
Returns true iff \c key is an extended key
|
||||||
|
*/
|
||||||
|
bool isExtendedKey(KeyButton key) const;
|
||||||
|
|
||||||
|
//! Get name of key
|
||||||
|
/*!
|
||||||
|
Return a string describing the given key.
|
||||||
|
*/
|
||||||
|
const char* getKeyName(KeyButton) const;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// convert a language ID to a code page
|
||||||
|
UINT getCodePageFromLangID(LANGID langid) const;
|
||||||
|
|
||||||
|
// map character \c c given keyboard layout \c hkl to the keystrokes
|
||||||
|
// to generate it.
|
||||||
|
KeyButton mapCharacter(IKeyState::Keystrokes& keys,
|
||||||
|
const IKeyState& keyState, char c, HKL hkl,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
// map \c virtualKey to the keystrokes to generate it, along with
|
||||||
|
// keystrokes to update and restore the modifier state.
|
||||||
|
KeyButton mapToKeystrokes(IKeyState::Keystrokes& keys,
|
||||||
|
const IKeyState& keyState, KeyButton virtualKey,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
KeyModifierMask requiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
// get keystrokes to get modifiers in a desired state
|
||||||
|
bool adjustModifiers(IKeyState::Keystrokes& keys,
|
||||||
|
IKeyState::Keystrokes& undo,
|
||||||
|
const IKeyState& keyState,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
KeyModifierMask requiredMask) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class CModifierKeys {
|
||||||
|
public:
|
||||||
|
enum { s_maxKeys = 2 };
|
||||||
|
KeyModifierMask m_mask;
|
||||||
|
KeyButton m_keys[s_maxKeys];
|
||||||
|
};
|
||||||
|
|
||||||
|
BYTE m_keys[256];
|
||||||
|
|
||||||
|
static const CModifierKeys s_modifiers[];
|
||||||
|
static const char* s_vkToName[];
|
||||||
|
static const KeyID s_virtualKey[][2];
|
||||||
|
static const KeyButton s_mapE000[];
|
||||||
|
static const KeyButton s_mapEE00[];
|
||||||
|
static const KeyButton s_mapEF00[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,140 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CMSWINDOWSPRIMARYSCREEN_H
|
|
||||||
#define CMSWINDOWSPRIMARYSCREEN_H
|
|
||||||
|
|
||||||
#include "CPrimaryScreen.h"
|
|
||||||
#include "IMSWindowsScreenEventHandler.h"
|
|
||||||
#include "CSynergyHook.h"
|
|
||||||
#include "MouseTypes.h"
|
|
||||||
#include "CString.h"
|
|
||||||
|
|
||||||
class CMSWindowsScreen;
|
|
||||||
class IScreenReceiver;
|
|
||||||
class IPrimaryScreenReceiver;
|
|
||||||
|
|
||||||
//! Microsoft windows primary screen implementation
|
|
||||||
class CMSWindowsPrimaryScreen :
|
|
||||||
public CPrimaryScreen, public IMSWindowsScreenEventHandler {
|
|
||||||
public:
|
|
||||||
typedef bool (CMSWindowsPrimaryScreen::*HookMethod)(int, WPARAM, LPARAM);
|
|
||||||
|
|
||||||
CMSWindowsPrimaryScreen(IScreenReceiver*, IPrimaryScreenReceiver*);
|
|
||||||
virtual ~CMSWindowsPrimaryScreen();
|
|
||||||
|
|
||||||
// CPrimaryScreen overrides
|
|
||||||
virtual void reconfigure(UInt32 activeSides);
|
|
||||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
|
||||||
virtual void resetOptions();
|
|
||||||
virtual void setOptions(const COptionsList& options);
|
|
||||||
virtual UInt32 addOneShotTimer(double timeout);
|
|
||||||
virtual KeyModifierMask getToggleMask() const;
|
|
||||||
virtual bool isLockedToScreen() const;
|
|
||||||
virtual IScreen* getScreen() const;
|
|
||||||
|
|
||||||
// IMSWindowsScreenEventHandler overrides
|
|
||||||
virtual void onScreensaver(bool activated);
|
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
|
||||||
virtual bool onEvent(CEvent* event);
|
|
||||||
virtual void onOneShotTimerExpired(UInt32 id);
|
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
|
||||||
virtual void postCreateWindow(HWND);
|
|
||||||
virtual void preDestroyWindow(HWND);
|
|
||||||
virtual void onAccessibleDesktop();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// CPrimaryScreen overrides
|
|
||||||
virtual void onPreMainLoop();
|
|
||||||
virtual void onPreOpen();
|
|
||||||
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:
|
|
||||||
void enterNoWarp();
|
|
||||||
|
|
||||||
// warp cursor without discarding queued events
|
|
||||||
void warpCursorNoFlush(SInt32 x, SInt32 y);
|
|
||||||
|
|
||||||
// discard posted messages
|
|
||||||
void nextMark();
|
|
||||||
|
|
||||||
// test if event should be ignored
|
|
||||||
bool ignore() const;
|
|
||||||
|
|
||||||
// key and button queries
|
|
||||||
KeyID mapKey(WPARAM keycode, LPARAM info,
|
|
||||||
KeyModifierMask* maskOut, bool* altgr);
|
|
||||||
ButtonID mapButton(WPARAM msg, LPARAM button) const;
|
|
||||||
void updateKey(UINT vkCode, bool press);
|
|
||||||
bool isModifier(UINT vkCode) const;
|
|
||||||
KeyButton mapKeyToScanCode(UINT vk1, UINT vk2) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
IPrimaryScreenReceiver* m_receiver;
|
|
||||||
CMSWindowsScreen* m_screen;
|
|
||||||
|
|
||||||
// true if windows 95/98/me
|
|
||||||
bool m_is95Family;
|
|
||||||
|
|
||||||
// the main loop's thread id
|
|
||||||
DWORD m_threadID;
|
|
||||||
|
|
||||||
// my window
|
|
||||||
HWND m_window;
|
|
||||||
|
|
||||||
// used to discard queued messages that are no longer needed
|
|
||||||
UInt32 m_mark;
|
|
||||||
UInt32 m_markReceived;
|
|
||||||
|
|
||||||
// map of key state
|
|
||||||
BYTE m_keys[256];
|
|
||||||
|
|
||||||
// map of button state
|
|
||||||
BYTE m_buttons[1 + kButtonExtra0 + 1];
|
|
||||||
|
|
||||||
// last mouse position
|
|
||||||
SInt32 m_x, m_y;
|
|
||||||
|
|
||||||
// position of center pixel of screen
|
|
||||||
SInt32 m_xCenter, m_yCenter;
|
|
||||||
|
|
||||||
// hook library stuff
|
|
||||||
HINSTANCE m_hookLibrary;
|
|
||||||
InitFunc m_init;
|
|
||||||
CleanupFunc m_cleanup;
|
|
||||||
InstallFunc m_install;
|
|
||||||
UninstallFunc m_uninstall;
|
|
||||||
SetSidesFunc m_setSides;
|
|
||||||
SetZoneFunc m_setZone;
|
|
||||||
SetRelayFunc m_setRelay;
|
|
||||||
bool m_lowLevel;
|
|
||||||
|
|
||||||
// stuff for hiding the cursor
|
|
||||||
DWORD m_cursorThread;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,7 +15,8 @@
|
||||||
#ifndef CMSWINDOWSSCREEN_H
|
#ifndef CMSWINDOWSSCREEN_H
|
||||||
#define CMSWINDOWSSCREEN_H
|
#define CMSWINDOWSSCREEN_H
|
||||||
|
|
||||||
#include "IScreen.h"
|
#include "IPlatformScreen.h"
|
||||||
|
#include "CMSWindowsKeyMapper.h"
|
||||||
#include "CSynergyHook.h"
|
#include "CSynergyHook.h"
|
||||||
#include "CMutex.h"
|
#include "CMutex.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
|
@ -23,22 +24,13 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
class CMSWindowsScreenSaver;
|
class CMSWindowsScreenSaver;
|
||||||
class CThread;
|
|
||||||
|
|
||||||
// Microsoft windows event
|
|
||||||
class CEvent {
|
|
||||||
public:
|
|
||||||
MSG m_msg;
|
|
||||||
LRESULT m_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IScreenReceiver;
|
class IScreenReceiver;
|
||||||
class IMSWindowsScreenEventHandler;
|
class IPrimaryScreenReceiver;
|
||||||
|
|
||||||
//! Implementation of IScreen for Microsoft Windows
|
//! Implementation of IPlatformScreen for Microsoft Windows
|
||||||
class CMSWindowsScreen : public IScreen {
|
class CMSWindowsScreen : public IPlatformScreen {
|
||||||
public:
|
public:
|
||||||
CMSWindowsScreen(IScreenReceiver*, IMSWindowsScreenEventHandler*);
|
CMSWindowsScreen(IScreenReceiver*, IPrimaryScreenReceiver*);
|
||||||
virtual ~CMSWindowsScreen();
|
virtual ~CMSWindowsScreen();
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
@ -51,37 +43,10 @@ public:
|
||||||
*/
|
*/
|
||||||
static void init(HINSTANCE);
|
static void init(HINSTANCE);
|
||||||
|
|
||||||
//! Open desktop
|
|
||||||
/*!
|
|
||||||
Open the desktop and create and return the window. Returns NULL
|
|
||||||
on failure.
|
|
||||||
*/
|
|
||||||
HWND openDesktop();
|
|
||||||
|
|
||||||
//! Close desktop
|
|
||||||
/*!
|
|
||||||
Close the window and desktop.
|
|
||||||
*/
|
|
||||||
void closeDesktop();
|
|
||||||
|
|
||||||
//! Install a one-shot timer
|
|
||||||
/*!
|
|
||||||
Installs a one-shot timer for \c timeout seconds and returns the
|
|
||||||
id of the timer (which will be passed to the receiver's
|
|
||||||
\c onTimerExpired()).
|
|
||||||
*/
|
|
||||||
UInt32 addOneShotTimer(double timeout);
|
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
//! Test for multiple monitors
|
|
||||||
/*!
|
|
||||||
Returns true iff the system appears to have multiple monitors.
|
|
||||||
*/
|
|
||||||
bool isMultimon() const;
|
|
||||||
|
|
||||||
//! Get instance
|
//! Get instance
|
||||||
/*!
|
/*!
|
||||||
Returns the application instance handle passed to init().
|
Returns the application instance handle passed to init().
|
||||||
|
@ -90,53 +55,116 @@ public:
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
// IScreen overrides
|
// IPlatformScreen overrides
|
||||||
// note -- this class expects the hook DLL to have been loaded
|
virtual void open(IKeyState*);
|
||||||
// and initialized before open() is called.
|
virtual void close();
|
||||||
void open();
|
virtual void enable();
|
||||||
void mainLoop();
|
virtual void disable();
|
||||||
void exitMainLoop();
|
virtual void mainLoop();
|
||||||
void close();
|
virtual void exitMainLoop();
|
||||||
bool setClipboard(ClipboardID, const IClipboard*);
|
virtual void enter();
|
||||||
void checkClipboards();
|
virtual bool leave();
|
||||||
void openScreensaver(bool notify);
|
virtual bool setClipboard(ClipboardID, const IClipboard*);
|
||||||
void closeScreensaver();
|
virtual void checkClipboards();
|
||||||
void screensaver(bool activate);
|
virtual void openScreensaver(bool notify);
|
||||||
void syncDesktop();
|
virtual void closeScreensaver();
|
||||||
bool getClipboard(ClipboardID, IClipboard*) const;
|
virtual void screensaver(bool activate);
|
||||||
void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
virtual void resetOptions();
|
||||||
void getCursorPos(SInt32&, SInt32&) const;
|
virtual void setOptions(const COptionsList& options);
|
||||||
void getCursorCenter(SInt32&, SInt32&) const;
|
virtual void updateKeys();
|
||||||
|
virtual bool isPrimary() const;
|
||||||
|
virtual bool getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
virtual void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
||||||
|
virtual void getCursorPos(SInt32&, SInt32&) const;
|
||||||
|
|
||||||
|
// IPrimaryScreen overrides
|
||||||
|
virtual void reconfigure(UInt32 activeSides);
|
||||||
|
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||||
|
virtual UInt32 addOneShotTimer(double timeout);
|
||||||
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
virtual bool isAnyMouseButtonDown() const;
|
||||||
|
virtual const char* getKeyName(KeyButton) const;
|
||||||
|
|
||||||
|
// ISecondaryScreen overrides
|
||||||
|
virtual void fakeKeyEvent(KeyButton id, bool press) const;
|
||||||
|
virtual bool fakeCtrlAltDel() const;
|
||||||
|
virtual void fakeMouseButton(ButtonID id, bool press) const;
|
||||||
|
virtual void fakeMouseMove(SInt32 x, SInt32 y) const;
|
||||||
|
virtual void fakeMouseWheel(SInt32 delta) const;
|
||||||
|
virtual KeyButton mapKey(IKeyState::Keystrokes&,
|
||||||
|
const IKeyState& keyState, KeyID id,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// update screen size cache
|
// update screen size cache
|
||||||
void updateScreenShape();
|
void updateScreenShape();
|
||||||
|
|
||||||
// internal pre-dispatch event processing
|
|
||||||
bool onPreDispatch(const CEvent* event);
|
|
||||||
|
|
||||||
// internal (post-dispatch) event processing
|
|
||||||
bool onEvent(CEvent* event);
|
|
||||||
|
|
||||||
// create the transparent cursor
|
|
||||||
void createBlankCursor();
|
|
||||||
|
|
||||||
// switch to the given desktop. this destroys the window and unhooks
|
// switch to the given desktop. this destroys the window and unhooks
|
||||||
// all hooks, switches the desktop, then creates the window and rehooks
|
// 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
|
// all hooks (because you can't switch the thread's desktop if it has
|
||||||
// any windows or hooks).
|
// any windows or hooks).
|
||||||
bool switchDesktop(HDESK desk);
|
bool switchDesktop(HDESK desk);
|
||||||
|
|
||||||
// get the input desktop. caller must CloseDesktop() the result.
|
// make sure we're on the expected desktop
|
||||||
// do not call under windows 95/98/me.
|
void syncDesktop() const;
|
||||||
HDESK openInputDesktop() const;
|
|
||||||
|
|
||||||
// get the desktop's name. do not call under windows 95/98/me.
|
// handle message before it gets dispatched. returns true iff
|
||||||
CString getDesktopName(HDESK) const;
|
// the message should not be dispatched.
|
||||||
|
bool onPreDispatch(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
// returns true iff desk is the current desk. do not call under
|
// handle message before it gets dispatched. returns true iff
|
||||||
// windows 95/98/me.
|
// the message should not be dispatched.
|
||||||
bool isCurrentDesktop(HDESK desk) const;
|
bool onPreDispatchPrimary(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
|
// handle message. returns true iff handled and optionally sets
|
||||||
|
// \c *result (which defaults to 0).
|
||||||
|
bool onEvent(HWND, UINT, WPARAM, LPARAM, LRESULT* result);
|
||||||
|
|
||||||
|
// message handlers
|
||||||
|
bool onMark(UInt32 mark);
|
||||||
|
bool onKey(WPARAM, LPARAM);
|
||||||
|
bool onMouseButton(WPARAM, LPARAM);
|
||||||
|
bool onMouseMove(SInt32 x, SInt32 y);
|
||||||
|
bool onMouseWheel(SInt32 delta);
|
||||||
|
bool onScreensaver(bool activated);
|
||||||
|
bool onTimer(UINT timerID);
|
||||||
|
bool onDisplayChange();
|
||||||
|
bool onClipboardChange();
|
||||||
|
bool onActivate(bool activated);
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
// warp cursor without discarding queued events
|
||||||
|
void warpCursorNoFlush(SInt32 x, SInt32 y);
|
||||||
|
|
||||||
|
// discard posted messages
|
||||||
|
void nextMark();
|
||||||
|
|
||||||
|
// test if event should be ignored
|
||||||
|
bool ignore() const;
|
||||||
|
// XXX
|
||||||
|
|
||||||
|
// create the transparent cursor
|
||||||
|
HCURSOR createBlankCursor() const;
|
||||||
|
|
||||||
|
// show/hide the cursor
|
||||||
|
void showCursor(bool) const;
|
||||||
|
|
||||||
|
// enable/disable special key combinations so we can catch/pass them
|
||||||
|
void enableSpecialKeys(bool) const;
|
||||||
|
|
||||||
|
// map a button ID and action to a mouse event
|
||||||
|
DWORD mapButtonToEvent(ButtonID button,
|
||||||
|
bool press, DWORD* inData) const;
|
||||||
|
|
||||||
|
// map a button event to a button ID
|
||||||
|
ButtonID mapButtonFromEvent(WPARAM msg, LPARAM button) const;
|
||||||
|
|
||||||
|
// return true iff the given virtual key is a modifier
|
||||||
|
bool isModifier(UINT vkCode) const;
|
||||||
|
|
||||||
|
// send ctrl+alt+del hotkey event
|
||||||
|
static void ctrlAltDelThread(void*);
|
||||||
|
|
||||||
// our window proc
|
// our window proc
|
||||||
static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
|
static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
@ -144,53 +172,63 @@ private:
|
||||||
private:
|
private:
|
||||||
static HINSTANCE s_instance;
|
static HINSTANCE s_instance;
|
||||||
|
|
||||||
IScreenReceiver* m_receiver;
|
// true if screen is being used as a primary screen, false otherwise
|
||||||
IMSWindowsScreenEventHandler* m_eventHandler;
|
bool m_isPrimary;
|
||||||
|
|
||||||
ATOM m_class;
|
|
||||||
HICON m_icon;
|
|
||||||
HCURSOR m_cursor;
|
|
||||||
|
|
||||||
// true if windows 95/98/me
|
// true if windows 95/98/me
|
||||||
bool m_is95Family;
|
bool m_is95Family;
|
||||||
|
|
||||||
// our window
|
// receivers
|
||||||
|
IScreenReceiver* m_receiver;
|
||||||
|
IPrimaryScreenReceiver* m_primaryReceiver;
|
||||||
|
|
||||||
|
// true if mouse has entered the screen
|
||||||
|
bool m_isOnScreen;
|
||||||
|
|
||||||
|
// our resources
|
||||||
|
ATOM m_class;
|
||||||
|
HCURSOR m_cursor;
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
|
|
||||||
// screen shape
|
// screen shape stuff
|
||||||
SInt32 m_x, m_y;
|
SInt32 m_x, m_y;
|
||||||
SInt32 m_w, m_h;
|
SInt32 m_w, m_h;
|
||||||
|
SInt32 m_xCenter, m_yCenter;
|
||||||
|
|
||||||
// true if system appears to have multiple monitors
|
// true if system appears to have multiple monitors
|
||||||
bool m_multimon;
|
bool m_multimon;
|
||||||
|
|
||||||
|
// last mouse position
|
||||||
|
SInt32 m_xCursor, m_yCursor;
|
||||||
|
|
||||||
|
// used to discard queued messages that are no longer needed
|
||||||
|
UInt32 m_mark;
|
||||||
|
UInt32 m_markReceived;
|
||||||
|
|
||||||
// the main loop's thread id
|
// the main loop's thread id
|
||||||
DWORD m_threadID;
|
DWORD m_threadID;
|
||||||
|
|
||||||
// the thread id of the last attached thread
|
// the thread id of the last attached thread
|
||||||
DWORD m_lastThreadID;
|
DWORD m_lastThreadID;
|
||||||
|
|
||||||
// clipboard stuff
|
|
||||||
HWND m_nextClipboardWindow;
|
|
||||||
bool m_ownClipboard;
|
|
||||||
|
|
||||||
// the timer used to check for desktop switching
|
// the timer used to check for desktop switching
|
||||||
UINT m_timer;
|
UINT m_timer;
|
||||||
|
|
||||||
// the one shot timer
|
// the one shot timer
|
||||||
UINT m_oneShotTimer;
|
UINT m_oneShotTimer;
|
||||||
|
|
||||||
|
// screen saver stuff
|
||||||
|
CMSWindowsScreenSaver* m_screensaver;
|
||||||
|
bool m_screensaverNotify;
|
||||||
|
|
||||||
|
// clipboard stuff
|
||||||
|
HWND m_nextClipboardWindow;
|
||||||
|
bool m_ownClipboard;
|
||||||
|
|
||||||
// the current desk and it's name
|
// the current desk and it's name
|
||||||
HDESK m_desk;
|
HDESK m_desk;
|
||||||
CString m_deskName;
|
CString m_deskName;
|
||||||
|
|
||||||
// screen saver stuff
|
|
||||||
HINSTANCE m_hookLibrary;
|
|
||||||
InstallScreenSaverFunc m_installScreensaver;
|
|
||||||
UninstallScreenSaverFunc m_uninstallScreensaver;
|
|
||||||
CMSWindowsScreenSaver* m_screensaver;
|
|
||||||
bool m_screensaverNotify;
|
|
||||||
|
|
||||||
// true when the current desktop is inaccessible. while
|
// true when the current desktop is inaccessible. while
|
||||||
// the desktop is inaccessible we won't receive user input
|
// the desktop is inaccessible we won't receive user input
|
||||||
// and we'll lose track of the keyboard state. when the
|
// and we'll lose track of the keyboard state. when the
|
||||||
|
@ -198,6 +236,29 @@ private:
|
||||||
// handler of that.
|
// handler of that.
|
||||||
bool m_inaccessibleDesktop;
|
bool m_inaccessibleDesktop;
|
||||||
|
|
||||||
|
// hook library stuff
|
||||||
|
HINSTANCE m_hookLibrary;
|
||||||
|
InitFunc m_init;
|
||||||
|
CleanupFunc m_cleanup;
|
||||||
|
InstallFunc m_install;
|
||||||
|
UninstallFunc m_uninstall;
|
||||||
|
SetSidesFunc m_setSides;
|
||||||
|
SetZoneFunc m_setZone;
|
||||||
|
SetModeFunc m_setMode;
|
||||||
|
InstallScreenSaverFunc m_installScreensaver;
|
||||||
|
UninstallScreenSaverFunc m_uninstallScreensaver;
|
||||||
|
bool m_lowLevel;
|
||||||
|
|
||||||
|
// keyboard stuff
|
||||||
|
IKeyState* m_keyState;
|
||||||
|
CMSWindowsKeyMapper m_keyMapper;
|
||||||
|
|
||||||
|
// map of button state
|
||||||
|
BYTE m_buttons[1 + kButtonExtra0 + 1];
|
||||||
|
|
||||||
|
// stuff for hiding the cursor
|
||||||
|
DWORD m_cursorThread;
|
||||||
|
|
||||||
static CMSWindowsScreen* s_screen;
|
static CMSWindowsScreen* s_screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,137 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CMSWINDOWSSECONDARYSCREEN_H
|
|
||||||
#define CMSWINDOWSSECONDARYSCREEN_H
|
|
||||||
|
|
||||||
// ensure that we get SendInput()
|
|
||||||
#if _WIN32_WINNT <= 0x400
|
|
||||||
#undef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x401
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "CSecondaryScreen.h"
|
|
||||||
#include "IMSWindowsScreenEventHandler.h"
|
|
||||||
#include "CMutex.h"
|
|
||||||
#include "CString.h"
|
|
||||||
|
|
||||||
class CMSWindowsScreen;
|
|
||||||
class IScreenReceiver;
|
|
||||||
|
|
||||||
//! Microsoft windows secondary screen implementation
|
|
||||||
class CMSWindowsSecondaryScreen :
|
|
||||||
public CSecondaryScreen, public IMSWindowsScreenEventHandler {
|
|
||||||
public:
|
|
||||||
CMSWindowsSecondaryScreen(IScreenReceiver*);
|
|
||||||
virtual ~CMSWindowsSecondaryScreen();
|
|
||||||
|
|
||||||
// CSecondaryScreen overrides
|
|
||||||
virtual IScreen* getScreen() const;
|
|
||||||
|
|
||||||
// IMSWindowsScreenEventHandler overrides
|
|
||||||
virtual void onScreensaver(bool activated);
|
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
|
||||||
virtual bool onEvent(CEvent* event);
|
|
||||||
virtual void onOneShotTimerExpired(UInt32 id);
|
|
||||||
virtual void postCreateWindow(HWND);
|
|
||||||
virtual void preDestroyWindow(HWND);
|
|
||||||
virtual void onAccessibleDesktop();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// CSecondaryScreen overrides
|
|
||||||
virtual void onPreMainLoop();
|
|
||||||
virtual void onPreOpen();
|
|
||||||
virtual void onPreEnter();
|
|
||||||
virtual void onPreLeave();
|
|
||||||
virtual void createWindow();
|
|
||||||
virtual void destroyWindow();
|
|
||||||
virtual void showWindow(SInt32 x, SInt32 y);
|
|
||||||
virtual void hideWindow();
|
|
||||||
virtual void updateKeys(KeyState* sysKeyStates);
|
|
||||||
virtual KeyModifierMask getModifiers() const;
|
|
||||||
|
|
||||||
virtual SysKeyID getUnhanded(SysKeyID) const;
|
|
||||||
virtual SysKeyID getOtherHanded(SysKeyID) const;
|
|
||||||
virtual bool isAutoRepeating(SysKeyID) const;
|
|
||||||
virtual KeyModifierMask getModifierKeyMask(SysKeyID) const;
|
|
||||||
virtual bool isModifierActive(SysKeyID) const;
|
|
||||||
virtual SysKeyID getToggleSysKey(KeyID keyID) const;
|
|
||||||
virtual bool synthesizeCtrlAltDel(EKeyAction);
|
|
||||||
virtual void sync() const;
|
|
||||||
virtual KeyModifierMask
|
|
||||||
mapKey(Keystrokes&, SysKeyID& sysKeyID, KeyID,
|
|
||||||
KeyModifierMask, KeyModifierMask, EKeyAction) const;
|
|
||||||
virtual void fakeKeyEvent(SysKeyID, bool press) const;
|
|
||||||
virtual void fakeMouseButton(ButtonID, bool press) const;
|
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const;
|
|
||||||
virtual void fakeMouseWheel(SInt32 delta) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class CModifierInfo {
|
|
||||||
public:
|
|
||||||
KeyModifierMask m_mask;
|
|
||||||
UINT m_virtualKey;
|
|
||||||
UINT m_virtualKey2;
|
|
||||||
bool m_isToggle;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// returns true iff there appear to be multiple monitors
|
|
||||||
bool isMultimon() const;
|
|
||||||
|
|
||||||
// key and button queries and operations
|
|
||||||
DWORD mapButton(ButtonID button,
|
|
||||||
bool press, DWORD* data) const;
|
|
||||||
UINT mapCharacter(Keystrokes& keys,
|
|
||||||
char c, HKL hkl,
|
|
||||||
KeyModifierMask currentMask,
|
|
||||||
KeyModifierMask desiredMask,
|
|
||||||
EKeyAction action) const;
|
|
||||||
KeyModifierMask mapToKeystrokes(Keystrokes& keys,
|
|
||||||
UINT virtualKey,
|
|
||||||
KeyModifierMask currentMask,
|
|
||||||
KeyModifierMask desiredMask,
|
|
||||||
EKeyAction action) const;
|
|
||||||
const CModifierInfo* getModifierInfo(UINT virtualKey) const;
|
|
||||||
|
|
||||||
KeyState getKeyState(UINT virtualKey) const;
|
|
||||||
UINT virtualKeyToScanCode(UINT& virtualKey) const;
|
|
||||||
bool isExtendedKey(UINT virtualKey) const;
|
|
||||||
|
|
||||||
UINT getCodePageFromLangID(LANGID) const;
|
|
||||||
|
|
||||||
// thread that generates fake ctrl+alt+del
|
|
||||||
static void ctrlAltDelThread(void*);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CMutex m_mutex;
|
|
||||||
CMSWindowsScreen* m_screen;
|
|
||||||
|
|
||||||
// true if windows 95/98/me
|
|
||||||
bool m_is95Family;
|
|
||||||
|
|
||||||
// our window
|
|
||||||
HWND m_window;
|
|
||||||
|
|
||||||
// modifier table
|
|
||||||
static const CModifierInfo s_modifier[];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -82,7 +82,7 @@ static HANDLE g_hookEventLL = NULL;
|
||||||
static HHOOK g_keyboardLL = NULL;
|
static HHOOK g_keyboardLL = NULL;
|
||||||
static HHOOK g_mouseLL = NULL;
|
static HHOOK g_mouseLL = NULL;
|
||||||
static bool g_screenSaver = false;
|
static bool g_screenSaver = false;
|
||||||
static bool g_relay = false;
|
static EHookMode g_mode = kHOOK_WATCH_JUMP_ZONE;
|
||||||
static UInt32 g_zoneSides = 0;
|
static UInt32 g_zoneSides = 0;
|
||||||
static SInt32 g_zoneSize = 0;
|
static SInt32 g_zoneSize = 0;
|
||||||
static SInt32 g_xScreen = 0;
|
static SInt32 g_xScreen = 0;
|
||||||
|
@ -151,7 +151,7 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
// the scroll lock toggle state.
|
// the scroll lock toggle state.
|
||||||
PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, wParam, lParam);
|
PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, wParam, lParam);
|
||||||
|
|
||||||
if (g_relay) {
|
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||||
// let certain keys pass through
|
// let certain keys pass through
|
||||||
switch (wParam) {
|
switch (wParam) {
|
||||||
case VK_CAPITAL:
|
case VK_CAPITAL:
|
||||||
|
@ -202,18 +202,18 @@ mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
|
||||||
case WM_NCXBUTTONUP:
|
case WM_NCXBUTTONUP:
|
||||||
// always relay the event. eat it if relaying.
|
// always relay the event. eat it if relaying.
|
||||||
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_BUTTON, wParam, data);
|
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_BUTTON, wParam, data);
|
||||||
return g_relay;
|
return (g_mode == kHOOK_RELAY_EVENTS);
|
||||||
|
|
||||||
case WM_MOUSEWHEEL:
|
case WM_MOUSEWHEEL:
|
||||||
if (g_relay) {
|
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||||
// relay event
|
// relay event
|
||||||
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_WHEEL, data, 0);
|
PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_WHEEL, data, 0);
|
||||||
}
|
}
|
||||||
return g_relay;
|
return (g_mode == kHOOK_RELAY_EVENTS);
|
||||||
|
|
||||||
case WM_NCMOUSEMOVE:
|
case WM_NCMOUSEMOVE:
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
if (g_relay) {
|
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||||
// we want the cursor to be hidden at all times so we
|
// we want the cursor to be hidden at all times so we
|
||||||
// hide the cursor on whatever window has it. but then
|
// hide the cursor on whatever window has it. but then
|
||||||
// we have to show the cursor whenever we leave that
|
// we have to show the cursor whenever we leave that
|
||||||
|
@ -329,7 +329,7 @@ getMessageHook(int code, WPARAM wParam, LPARAM lParam)
|
||||||
SYNERGY_MSG_SCREEN_SAVER, TRUE, 0);
|
SYNERGY_MSG_SCREEN_SAVER, TRUE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (g_relay) {
|
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||||
MSG* msg = reinterpret_cast<MSG*>(lParam);
|
MSG* msg = reinterpret_cast<MSG*>(lParam);
|
||||||
if (msg->message == g_wmMouseWheel) {
|
if (msg->message == g_wmMouseWheel) {
|
||||||
// post message to our window
|
// post message to our window
|
||||||
|
@ -614,7 +614,7 @@ init(DWORD threadID)
|
||||||
g_threadID = threadID;
|
g_threadID = threadID;
|
||||||
|
|
||||||
// set defaults
|
// set defaults
|
||||||
g_relay = false;
|
g_mode = kHOOK_WATCH_JUMP_ZONE;
|
||||||
g_zoneSides = 0;
|
g_zoneSides = 0;
|
||||||
g_zoneSize = 0;
|
g_zoneSize = 0;
|
||||||
g_xScreen = 0;
|
g_xScreen = 0;
|
||||||
|
@ -827,14 +827,14 @@ setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h, SInt32 jumpZoneSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
setRelay(int enable)
|
setMode(EHookMode mode)
|
||||||
{
|
{
|
||||||
if ((enable != 0) == g_relay) {
|
if (mode == g_mode) {
|
||||||
// no change
|
// no change
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_relay = (enable != 0);
|
g_mode = mode;
|
||||||
if (!g_relay) {
|
if (g_mode != kHOOK_RELAY_EVENTS) {
|
||||||
restoreCursor();
|
restoreCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,11 @@ enum EHookResult {
|
||||||
kHOOK_OKAY_LL
|
kHOOK_OKAY_LL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EHookMode {
|
||||||
|
kHOOK_WATCH_JUMP_ZONE,
|
||||||
|
kHOOK_RELAY_EVENTS
|
||||||
|
};
|
||||||
|
|
||||||
typedef int (*InitFunc)(DWORD targetQueueThreadID);
|
typedef int (*InitFunc)(DWORD targetQueueThreadID);
|
||||||
typedef int (*CleanupFunc)(void);
|
typedef int (*CleanupFunc)(void);
|
||||||
typedef EHookResult (*InstallFunc)(void);
|
typedef EHookResult (*InstallFunc)(void);
|
||||||
|
@ -57,7 +62,7 @@ typedef int (*InstallScreenSaverFunc)(void);
|
||||||
typedef int (*UninstallScreenSaverFunc)(void);
|
typedef int (*UninstallScreenSaverFunc)(void);
|
||||||
typedef void (*SetSidesFunc)(UInt32);
|
typedef void (*SetSidesFunc)(UInt32);
|
||||||
typedef void (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32);
|
typedef void (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32);
|
||||||
typedef void (*SetRelayFunc)(int);
|
typedef void (*SetModeFunc)(int);
|
||||||
|
|
||||||
CSYNERGYHOOK_API int init(DWORD);
|
CSYNERGYHOOK_API int init(DWORD);
|
||||||
CSYNERGYHOOK_API int cleanup(void);
|
CSYNERGYHOOK_API int cleanup(void);
|
||||||
|
@ -68,7 +73,7 @@ CSYNERGYHOOK_API int uninstallScreenSaver(void);
|
||||||
CSYNERGYHOOK_API void setSides(UInt32 sides);
|
CSYNERGYHOOK_API void setSides(UInt32 sides);
|
||||||
CSYNERGYHOOK_API void setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h,
|
CSYNERGYHOOK_API void setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h,
|
||||||
SInt32 jumpZoneSize);
|
SInt32 jumpZoneSize);
|
||||||
CSYNERGYHOOK_API void setRelay(int enable); // relay iff enable != 0
|
CSYNERGYHOOK_API void setMode(EHookMode mode);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,910 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CXWindowsKeyMapper.h"
|
||||||
|
#include "CXWindowsUtil.h"
|
||||||
|
#include "CLog.h"
|
||||||
|
#if defined(X_DISPLAY_MISSING)
|
||||||
|
# error X11 is required to build synergy
|
||||||
|
#else
|
||||||
|
# include <X11/X.h>
|
||||||
|
# include <X11/Xutil.h>
|
||||||
|
# define XK_MISCELLANY
|
||||||
|
# define XK_XKB_KEYS
|
||||||
|
# include <X11/keysymdef.h>
|
||||||
|
# if defined(HAVE_X11_XF86KEYSYM_H)
|
||||||
|
# include <X11/XF86keysym.h>
|
||||||
|
# endif
|
||||||
|
# if !defined(XF86XK_Launch0)
|
||||||
|
# define XF86XK_Launch0 0x1008FF40
|
||||||
|
# endif
|
||||||
|
# if !defined(XF86XK_Launch1)
|
||||||
|
# define XF86XK_Launch1 0x1008FF41
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// map special KeyID keys to KeySyms
|
||||||
|
#if defined(HAVE_X11_XF86KEYSYM_H)
|
||||||
|
static const KeySym g_mapE000[] =
|
||||||
|
{
|
||||||
|
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xa0 */ 0, 0, 0, 0,
|
||||||
|
/* 0xa4 */ 0, 0,
|
||||||
|
/* 0xa6 */ XF86XK_Back, XF86XK_Forward,
|
||||||
|
/* 0xa8 */ XF86XK_Refresh, XF86XK_Stop,
|
||||||
|
/* 0xaa */ XF86XK_Search, XF86XK_Favorites,
|
||||||
|
/* 0xac */ XF86XK_HomePage, XF86XK_AudioMute,
|
||||||
|
/* 0xae */ XF86XK_AudioLowerVolume, XF86XK_AudioRaiseVolume,
|
||||||
|
/* 0xb0 */ XF86XK_AudioNext, XF86XK_AudioPrev,
|
||||||
|
/* 0xb2 */ XF86XK_AudioStop, XF86XK_AudioPlay,
|
||||||
|
/* 0xb4 */ XF86XK_Mail, XF86XK_AudioMedia,
|
||||||
|
/* 0xb6 */ XF86XK_Launch0, XF86XK_Launch1,
|
||||||
|
/* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CXWindowsKeyMapper::CXWindowsKeyMapper()
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
CXWindowsKeyMapper::~CXWindowsKeyMapper()
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CXWindowsKeyMapper::update(Display* display, IKeyState* keyState)
|
||||||
|
{
|
||||||
|
// query which keys are pressed
|
||||||
|
char keys[32];
|
||||||
|
XQueryKeymap(display, keys);
|
||||||
|
|
||||||
|
// query the pointer to get the keyboard state
|
||||||
|
Window root = DefaultRootWindow(display), window;
|
||||||
|
int xRoot, yRoot, xWindow, yWindow;
|
||||||
|
unsigned int state;
|
||||||
|
if (!XQueryPointer(display, root, &root, &window,
|
||||||
|
&xRoot, &yRoot, &xWindow, &yWindow, &state)) {
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update mappings
|
||||||
|
updateKeysymMap(display, keyState);
|
||||||
|
updateModifiers();
|
||||||
|
|
||||||
|
// transfer to our state
|
||||||
|
for (UInt32 i = 0, j = 0; i < 32; j += 8, ++i) {
|
||||||
|
if ((keys[i] & 0x01) != 0)
|
||||||
|
keyState->setKeyDown(j + 0);
|
||||||
|
if ((keys[i] & 0x02) != 0)
|
||||||
|
keyState->setKeyDown(j + 1);
|
||||||
|
if ((keys[i] & 0x04) != 0)
|
||||||
|
keyState->setKeyDown(j + 2);
|
||||||
|
if ((keys[i] & 0x08) != 0)
|
||||||
|
keyState->setKeyDown(j + 3);
|
||||||
|
if ((keys[i] & 0x10) != 0)
|
||||||
|
keyState->setKeyDown(j + 4);
|
||||||
|
if ((keys[i] & 0x20) != 0)
|
||||||
|
keyState->setKeyDown(j + 5);
|
||||||
|
if ((keys[i] & 0x40) != 0)
|
||||||
|
keyState->setKeyDown(j + 6);
|
||||||
|
if ((keys[i] & 0x80) != 0)
|
||||||
|
keyState->setKeyDown(j + 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set toggle modifier states
|
||||||
|
if ((state & LockMask) != 0)
|
||||||
|
keyState->setToggled(KeyModifierCapsLock);
|
||||||
|
if ((state & m_numLockMask) != 0)
|
||||||
|
keyState->setToggled(KeyModifierNumLock);
|
||||||
|
if ((state & m_scrollLockMask) != 0)
|
||||||
|
keyState->setToggled(KeyModifierScrollLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyButton
|
||||||
|
CXWindowsKeyMapper::mapKey(IKeyState::Keystrokes& keys,
|
||||||
|
const IKeyState& keyState, KeyID id,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const
|
||||||
|
{
|
||||||
|
// the system translates key events into characters depending
|
||||||
|
// on the modifier key state at the time of the event. to
|
||||||
|
// generate the right keysym we need to set the modifier key
|
||||||
|
// states appropriately.
|
||||||
|
//
|
||||||
|
// desiredMask is the mask desired by the caller. however, there
|
||||||
|
// may not be a keycode mapping to generate the desired keysym
|
||||||
|
// with that mask. we override the bits in the mask that cannot
|
||||||
|
// be accomodated.
|
||||||
|
|
||||||
|
// convert KeyID to a KeySym
|
||||||
|
KeySym keysym = keyIDToKeySym(id, desiredMask);
|
||||||
|
if (keysym == NoSymbol) {
|
||||||
|
// unknown key
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the mapping for this keysym
|
||||||
|
KeySymIndex keyIndex = m_keysymMap.find(keysym);
|
||||||
|
|
||||||
|
// if the mapping isn't found and keysym is caps lock sensitive
|
||||||
|
// then convert the case of the keysym and try again.
|
||||||
|
if (keyIndex == m_keysymMap.end()) {
|
||||||
|
KeySym lKey, uKey;
|
||||||
|
XConvertCase(keysym, &lKey, &uKey);
|
||||||
|
if (lKey != uKey) {
|
||||||
|
if (lKey == keysym) {
|
||||||
|
keyIndex = m_keysymMap.find(uKey);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
keyIndex = m_keysymMap.find(lKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyIndex != m_keysymMap.end()) {
|
||||||
|
// the keysym is mapped to some keycode. create the keystrokes
|
||||||
|
// for this keysym.
|
||||||
|
return mapToKeystrokes(keys, keyState, keyIndex, isAutoRepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can't find the keysym mapped to any keycode. this doesn't
|
||||||
|
// necessarily mean we can't generate the keysym, though. if the
|
||||||
|
// keysym can be created by combining keysyms then we may still
|
||||||
|
// be okay.
|
||||||
|
CXWindowsUtil::KeySyms decomposition;
|
||||||
|
if (!CXWindowsUtil::decomposeKeySym(keysym, decomposition)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LOG((CLOG_DEBUG2 "decomposed keysym 0x%08x into %d keysyms", keysym, decomposition.size()));
|
||||||
|
|
||||||
|
// map each decomposed keysym to keystrokes. we want the mask
|
||||||
|
// and the keycode from the last keysym (which should be the
|
||||||
|
// only non-dead key). the dead keys are not sensitive to
|
||||||
|
// anything but shift and mode switch.
|
||||||
|
KeyButton keycode = 0;
|
||||||
|
for (CXWindowsUtil::KeySyms::const_iterator i = decomposition.begin();
|
||||||
|
i != decomposition.end(); ++i) {
|
||||||
|
// lookup the key
|
||||||
|
keysym = *i;
|
||||||
|
keyIndex = m_keysymMap.find(keysym);
|
||||||
|
if (keyIndex == m_keysymMap.end()) {
|
||||||
|
// missing a required keysym
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the keysym is mapped to some keycode
|
||||||
|
keycode = mapToKeystrokes(keys, keyState, keyIndex, isAutoRepeat);
|
||||||
|
if (keycode == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyModifierMask
|
||||||
|
CXWindowsKeyMapper::mapModifier(unsigned int state) const
|
||||||
|
{
|
||||||
|
KeyModifierMask mask = 0;
|
||||||
|
if (state & ShiftMask)
|
||||||
|
mask |= KeyModifierShift;
|
||||||
|
if (state & LockMask)
|
||||||
|
mask |= KeyModifierCapsLock;
|
||||||
|
if (state & ControlMask)
|
||||||
|
mask |= KeyModifierControl;
|
||||||
|
if (state & m_altMask)
|
||||||
|
mask |= KeyModifierAlt;
|
||||||
|
if (state & m_metaMask)
|
||||||
|
mask |= KeyModifierMeta;
|
||||||
|
if (state & m_superMask)
|
||||||
|
mask |= KeyModifierSuper;
|
||||||
|
if (state & m_modeSwitchMask)
|
||||||
|
mask |= KeyModifierModeSwitch;
|
||||||
|
if (state & m_numLockMask)
|
||||||
|
mask |= KeyModifierNumLock;
|
||||||
|
if (state & m_scrollLockMask)
|
||||||
|
mask |= KeyModifierScrollLock;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CXWindowsKeyMapper::updateKeysymMap(Display* display, IKeyState* keyState)
|
||||||
|
{
|
||||||
|
// there are up to 4 keysyms per keycode
|
||||||
|
static const unsigned int maxKeysyms = 4;
|
||||||
|
|
||||||
|
// get the number of keycodes
|
||||||
|
int minKeycode, maxKeycode;
|
||||||
|
XDisplayKeycodes(display, &minKeycode, &maxKeycode);
|
||||||
|
const int numKeycodes = maxKeycode - minKeycode + 1;
|
||||||
|
|
||||||
|
// get the keyboard mapping for all keys
|
||||||
|
int keysymsPerKeycode;
|
||||||
|
KeySym* keysyms = XGetKeyboardMapping(display,
|
||||||
|
minKeycode, numKeycodes,
|
||||||
|
&keysymsPerKeycode);
|
||||||
|
|
||||||
|
// we only understand up to maxKeysyms keysyms per keycodes
|
||||||
|
unsigned int numKeysyms = keysymsPerKeycode;
|
||||||
|
if (numKeysyms > maxKeysyms) {
|
||||||
|
numKeysyms = maxKeysyms;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine shift and mode switch sensitivity. a keysym is shift
|
||||||
|
// or mode switch sensitive if its keycode is. a keycode is mode
|
||||||
|
// mode switch sensitive if it has keysyms for indices 2 or 3.
|
||||||
|
// it's shift sensitive if the keysym for index 1 (if any) is
|
||||||
|
// different from the keysym for index 0 and, if the keysym for
|
||||||
|
// for index 3 (if any) is different from the keysym for index 2.
|
||||||
|
// that is, if shift changes the generated keysym for the keycode.
|
||||||
|
std::vector<bool> usesShift(numKeycodes);
|
||||||
|
std::vector<bool> usesModeSwitch(numKeycodes);
|
||||||
|
for (int i = 0; i < numKeycodes; ++i) {
|
||||||
|
// check mode switch first
|
||||||
|
if (numKeysyms > 2 &&
|
||||||
|
keysyms[i * keysymsPerKeycode + 2] != NoSymbol ||
|
||||||
|
keysyms[i * keysymsPerKeycode + 3] != NoSymbol) {
|
||||||
|
usesModeSwitch[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check index 0 with index 1 keysyms
|
||||||
|
if (keysyms[i * keysymsPerKeycode + 0] != NoSymbol &&
|
||||||
|
keysyms[i * keysymsPerKeycode + 1] != NoSymbol &&
|
||||||
|
keysyms[i * keysymsPerKeycode + 1] !=
|
||||||
|
keysyms[i * keysymsPerKeycode + 0]) {
|
||||||
|
usesShift[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (numKeysyms >= 4 &&
|
||||||
|
keysyms[i * keysymsPerKeycode + 2] != NoSymbol &&
|
||||||
|
keysyms[i * keysymsPerKeycode + 3] != NoSymbol &&
|
||||||
|
keysyms[i * keysymsPerKeycode + 3] !=
|
||||||
|
keysyms[i * keysymsPerKeycode + 2]) {
|
||||||
|
usesShift[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get modifier map from server
|
||||||
|
XModifierKeymap* modifiers = XGetModifierMapping(display);
|
||||||
|
int keysPerModifier = modifiers->max_keypermod;
|
||||||
|
|
||||||
|
// clear state
|
||||||
|
m_keysymMap.clear();
|
||||||
|
m_modeSwitchKeysym = NoSymbol;
|
||||||
|
m_altMask = 0;
|
||||||
|
m_metaMask = 0;
|
||||||
|
m_superMask = 0;
|
||||||
|
m_modeSwitchMask = 0;
|
||||||
|
m_numLockMask = 0;
|
||||||
|
m_scrollLockMask = 0;
|
||||||
|
|
||||||
|
// work around for my system, which reports this state bit when
|
||||||
|
// mode switch is down, instead of the appropriate modifier bit.
|
||||||
|
// should have no effect on other systems. -crs 9/02.
|
||||||
|
m_modeSwitchMask |= (1 << 13);
|
||||||
|
|
||||||
|
// for each modifier keycode, get the index 0 keycode and add it to
|
||||||
|
// the keysym map. also collect all keycodes for each modifier.
|
||||||
|
for (unsigned int i = 0; i < 8; ++i) {
|
||||||
|
// no keycodes for this modifier yet
|
||||||
|
bool hasKeycode = false;
|
||||||
|
KeyModifierMask mask = 0;
|
||||||
|
IKeyState::KeyButtons modifierKeys;
|
||||||
|
|
||||||
|
// add each keycode for modifier
|
||||||
|
for (unsigned int j = 0; j < keysPerModifier; ++j) {
|
||||||
|
// get keycode and ignore unset keycodes
|
||||||
|
KeyCode keycode = modifiers->modifiermap[i * keysPerModifier + j];
|
||||||
|
if (keycode == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get keysym and get/create key mapping
|
||||||
|
const int keycodeIndex = keycode - minKeycode;
|
||||||
|
const KeySym keysym = keysyms[keycodeIndex *
|
||||||
|
keysymsPerKeycode + 0];
|
||||||
|
|
||||||
|
// get modifier mask if we haven't yet. this has the side
|
||||||
|
// effect of setting the m_*Mask members.
|
||||||
|
if (mask == 0) {
|
||||||
|
mask = mapToModifierMask(i, keysym);
|
||||||
|
if (mask == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save keycode for modifier
|
||||||
|
modifierKeys.push_back(keycode);
|
||||||
|
|
||||||
|
// skip if we already have a keycode for this index
|
||||||
|
KeyMapping& mapping = m_keysymMap[keysym];
|
||||||
|
if (mapping.m_keycode[0] != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill in keysym info
|
||||||
|
mapping.m_keycode[0] = keycode;
|
||||||
|
mapping.m_shiftSensitive[0] = usesShift[keycodeIndex];
|
||||||
|
mapping.m_modeSwitchSensitive[0] = usesModeSwitch[keycodeIndex];
|
||||||
|
mapping.m_modifierMask = mask;
|
||||||
|
mapping.m_capsLockSensitive = false;
|
||||||
|
mapping.m_numLockSensitive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell keyState about this modifier
|
||||||
|
if (mask != 0 && keyState != NULL) {
|
||||||
|
keyState->addModifier(mask, modifierKeys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a convenient NoSymbol entry (if it doesn't exist yet).
|
||||||
|
// sometimes it's useful to handle NoSymbol like a normal keysym.
|
||||||
|
// remove any entry for NoSymbol. that keysym doesn't count.
|
||||||
|
{
|
||||||
|
KeyMapping& mapping = m_keysymMap[NoSymbol];
|
||||||
|
for (unsigned int i = 0; i < numKeysyms; ++i) {
|
||||||
|
mapping.m_keycode[i] = 0;
|
||||||
|
mapping.m_shiftSensitive[i] = false;
|
||||||
|
mapping.m_modeSwitchSensitive[i] = false;
|
||||||
|
}
|
||||||
|
mapping.m_modifierMask = 0;
|
||||||
|
mapping.m_capsLockSensitive = false;
|
||||||
|
mapping.m_numLockSensitive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add each keysym to the map, unless we've already inserted a key
|
||||||
|
// for that keysym index.
|
||||||
|
for (int i = 0; i < numKeycodes; ++i) {
|
||||||
|
for (unsigned int j = 0; j < numKeysyms; ++j) {
|
||||||
|
// lookup keysym
|
||||||
|
const KeySym keysym = keysyms[i * keysymsPerKeycode + j];
|
||||||
|
if (keysym == NoSymbol) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
KeyMapping& mapping = m_keysymMap[keysym];
|
||||||
|
|
||||||
|
// skip if we already have a keycode for this index
|
||||||
|
if (mapping.m_keycode[j] != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill in keysym info
|
||||||
|
if (mapping.m_keycode[0] == 0) {
|
||||||
|
mapping.m_modifierMask = 0;
|
||||||
|
}
|
||||||
|
mapping.m_keycode[j] = static_cast<KeyCode>(
|
||||||
|
minKeycode + i);
|
||||||
|
mapping.m_shiftSensitive[j] = usesShift[i];
|
||||||
|
mapping.m_modeSwitchSensitive[j] = usesModeSwitch[i];
|
||||||
|
mapping.m_numLockSensitive = isNumLockSensitive(keysym);
|
||||||
|
mapping.m_capsLockSensitive = isCapsLockSensitive(keysym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
XFreeModifiermap(modifiers);
|
||||||
|
XFree(keysyms);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyModifierMask
|
||||||
|
CXWindowsKeyMapper::mapToModifierMask(unsigned int i, KeySym keysym)
|
||||||
|
{
|
||||||
|
// some modifier indices (0,1,2) are dedicated to particular uses,
|
||||||
|
// the rest depend on the keysyms bound.
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return KeyModifierShift;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return KeyModifierCapsLock;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return KeyModifierControl;
|
||||||
|
|
||||||
|
default:
|
||||||
|
switch (keysym) {
|
||||||
|
case XK_Shift_L:
|
||||||
|
case XK_Shift_R:
|
||||||
|
return KeyModifierShift;
|
||||||
|
|
||||||
|
case XK_Control_L:
|
||||||
|
case XK_Control_R:
|
||||||
|
return KeyModifierControl;
|
||||||
|
|
||||||
|
case XK_Alt_L:
|
||||||
|
case XK_Alt_R:
|
||||||
|
m_altMask = (1 << i);
|
||||||
|
return KeyModifierAlt;
|
||||||
|
|
||||||
|
case XK_Meta_L:
|
||||||
|
case XK_Meta_R:
|
||||||
|
m_metaMask = (1 << i);
|
||||||
|
return KeyModifierMeta;
|
||||||
|
|
||||||
|
case XK_Super_L:
|
||||||
|
case XK_Super_R:
|
||||||
|
m_superMask = (1 << i);
|
||||||
|
return KeyModifierSuper;
|
||||||
|
|
||||||
|
case XK_Mode_switch:
|
||||||
|
m_modeSwitchMask = (1 << i);
|
||||||
|
return KeyModifierModeSwitch;
|
||||||
|
|
||||||
|
case XK_Caps_Lock:
|
||||||
|
return KeyModifierCapsLock;
|
||||||
|
|
||||||
|
case XK_Num_Lock:
|
||||||
|
m_numLockMask = (1 << i);
|
||||||
|
return KeyModifierNumLock;
|
||||||
|
|
||||||
|
case XK_Scroll_Lock:
|
||||||
|
m_scrollLockMask = (1 << i);
|
||||||
|
return KeyModifierScrollLock;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CXWindowsKeyMapper::updateModifiers()
|
||||||
|
{
|
||||||
|
struct CModifierBitInfo {
|
||||||
|
public:
|
||||||
|
KeySym CXWindowsKeyMapper::*m_keysym;
|
||||||
|
KeySym m_left;
|
||||||
|
KeySym m_right;
|
||||||
|
};
|
||||||
|
static const CModifierBitInfo s_modifierBitTable[] = {
|
||||||
|
{ &CXWindowsKeyMapper::m_modeSwitchKeysym, XK_Mode_switch, NoSymbol },
|
||||||
|
};
|
||||||
|
|
||||||
|
// choose the keysym to use for some modifiers. if a modifier has
|
||||||
|
// both left and right versions then (arbitrarily) prefer the left.
|
||||||
|
for (size_t i = 0; i < sizeof(s_modifierBitTable) /
|
||||||
|
sizeof(s_modifierBitTable[0]); ++i) {
|
||||||
|
const CModifierBitInfo& info = s_modifierBitTable[i];
|
||||||
|
|
||||||
|
// find available keysym
|
||||||
|
KeySymIndex keyIndex = m_keysymMap.find(info.m_left);
|
||||||
|
if (keyIndex == m_keysymMap.end() && info.m_right != NoSymbol) {
|
||||||
|
keyIndex = m_keysymMap.find(info.m_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save modifier info
|
||||||
|
if (keyIndex != m_keysymMap.end() &&
|
||||||
|
keyIndex->second.m_modifierMask != 0) {
|
||||||
|
this->*(info.m_keysym) = keyIndex->first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there's no mode switch key mapped then remove all keycodes
|
||||||
|
// that depend on it and no keycode can be mode switch sensitive.
|
||||||
|
if (m_modeSwitchKeysym == NoSymbol) {
|
||||||
|
LOG((CLOG_DEBUG2 "no mode switch in keymap"));
|
||||||
|
for (KeySymMap::iterator i = m_keysymMap.begin();
|
||||||
|
i != m_keysymMap.end(); ) {
|
||||||
|
i->second.m_keycode[2] = 0;
|
||||||
|
i->second.m_keycode[3] = 0;
|
||||||
|
i->second.m_modeSwitchSensitive[0] = false;
|
||||||
|
i->second.m_modeSwitchSensitive[1] = false;
|
||||||
|
i->second.m_modeSwitchSensitive[2] = false;
|
||||||
|
i->second.m_modeSwitchSensitive[3] = false;
|
||||||
|
|
||||||
|
// if this keysym no has no keycodes then remove it
|
||||||
|
// except for the NoSymbol keysym mapping.
|
||||||
|
if (i->second.m_keycode[0] == 0 && i->second.m_keycode[1] == 0) {
|
||||||
|
m_keysymMap.erase(i++);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeySym
|
||||||
|
CXWindowsKeyMapper::keyIDToKeySym(KeyID id, KeyModifierMask mask) const
|
||||||
|
{
|
||||||
|
// convert id to keysym
|
||||||
|
KeySym keysym = NoSymbol;
|
||||||
|
if ((id & 0xfffff000) == 0xe000) {
|
||||||
|
// special character
|
||||||
|
switch (id & 0x0000ff00) {
|
||||||
|
#if defined(HAVE_X11_XF86KEYSYM_H)
|
||||||
|
case 0xe000:
|
||||||
|
return g_mapE000[id & 0xff];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 0xee00:
|
||||||
|
// ISO 9995 Function and Modifier Keys
|
||||||
|
if (id == kKeyLeftTab) {
|
||||||
|
keysym = XK_ISO_Left_Tab;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xef00:
|
||||||
|
// MISCELLANY
|
||||||
|
keysym = static_cast<KeySym>(id - 0xef00 + 0xff00);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((id >= 0x0020 && id <= 0x007e) ||
|
||||||
|
(id >= 0x00a0 && id <= 0x00ff)) {
|
||||||
|
// Latin-1 maps directly
|
||||||
|
return static_cast<KeySym>(id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// lookup keysym in table
|
||||||
|
return CXWindowsUtil::mapUCS4ToKeySym(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail if unknown key
|
||||||
|
if (keysym == NoSymbol) {
|
||||||
|
return keysym;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if kKeyTab is requested with shift active then try XK_ISO_Left_Tab
|
||||||
|
// instead. if that doesn't work, we'll fall back to XK_Tab with
|
||||||
|
// shift active. this is to handle primary screens that don't map
|
||||||
|
// XK_ISO_Left_Tab sending events to secondary screens that do.
|
||||||
|
if (keysym == XK_Tab && (mask & KeyModifierShift) != 0) {
|
||||||
|
keysym = XK_ISO_Left_Tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
// some keysyms have emergency backups (particularly the numpad
|
||||||
|
// keys since most laptops don't have a separate numpad and the
|
||||||
|
// numpad overlaying the main keyboard may not have movement
|
||||||
|
// key bindings). figure out the emergency backup.
|
||||||
|
KeySym backupKeysym;
|
||||||
|
switch (keysym) {
|
||||||
|
case XK_KP_Home:
|
||||||
|
backupKeysym = XK_Home;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Left:
|
||||||
|
backupKeysym = XK_Left;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Up:
|
||||||
|
backupKeysym = XK_Up;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Right:
|
||||||
|
backupKeysym = XK_Right;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Down:
|
||||||
|
backupKeysym = XK_Down;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Prior:
|
||||||
|
backupKeysym = XK_Prior;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Next:
|
||||||
|
backupKeysym = XK_Next;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_End:
|
||||||
|
backupKeysym = XK_End;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Insert:
|
||||||
|
backupKeysym = XK_Insert;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_KP_Delete:
|
||||||
|
backupKeysym = XK_Delete;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XK_ISO_Left_Tab:
|
||||||
|
backupKeysym = XK_Tab;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
backupKeysym = keysym;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if the keysym is assigned to any keycode. if not and the
|
||||||
|
// backup keysym is then use the backup keysym.
|
||||||
|
if (backupKeysym != keysym &&
|
||||||
|
m_keysymMap.find(keysym) == m_keysymMap.end() &&
|
||||||
|
m_keysymMap.find(backupKeysym) != m_keysymMap.end()) {
|
||||||
|
keysym = backupKeysym;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keysym;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyButton
|
||||||
|
CXWindowsKeyMapper::mapToKeystrokes(IKeyState::Keystrokes& keys,
|
||||||
|
const IKeyState& keyState,
|
||||||
|
KeySymIndex keyIndex,
|
||||||
|
bool isAutoRepeat) const
|
||||||
|
{
|
||||||
|
// keyIndex must be valid
|
||||||
|
assert(keyIndex != m_keysymMap.end());
|
||||||
|
|
||||||
|
KeyModifierMask currentMask = keyState.getActiveModifiers();
|
||||||
|
|
||||||
|
// get the keysym we're trying to generate and possible keycodes
|
||||||
|
const KeySym keysym = keyIndex->first;
|
||||||
|
const KeyMapping& mapping = keyIndex->second;
|
||||||
|
LOG((CLOG_DEBUG2 "keysym = 0x%08x", keysym));
|
||||||
|
|
||||||
|
// get the best keycode index for the keysym and modifiers. note
|
||||||
|
// that (bestIndex & 1) == 0 if the keycode is a shift modifier
|
||||||
|
// and (bestIndex & 2) == 0 if the keycode is a mode switch
|
||||||
|
// modifier. this is important later because we don't want
|
||||||
|
// adjustModifiers() to adjust a modifier if that's the key we're
|
||||||
|
// mapping.
|
||||||
|
unsigned int bestIndex = findBestKeyIndex(keyIndex, currentMask);
|
||||||
|
|
||||||
|
// get the keycode
|
||||||
|
KeyButton keycode = mapping.m_keycode[bestIndex];
|
||||||
|
|
||||||
|
// flip low bit of bestIndex if shift is inverted. if there's a
|
||||||
|
// keycode for this new index then use it. otherwise use the old
|
||||||
|
// keycode. you'd think we should fail if there isn't a keycode
|
||||||
|
// for the new index but some keymaps only include the upper case
|
||||||
|
// keysyms (notably those on Sun Solaris) so to handle the missing
|
||||||
|
// lower case keysyms we just use the old keycode. note that
|
||||||
|
// isShiftInverted() will always return false for a shift modifier.
|
||||||
|
if (isShiftInverted(keyIndex, currentMask)) {
|
||||||
|
LOG((CLOG_DEBUG2 "shift is inverted"));
|
||||||
|
bestIndex ^= 1;
|
||||||
|
if (mapping.m_keycode[bestIndex] != 0) {
|
||||||
|
keycode = mapping.m_keycode[bestIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG((CLOG_DEBUG2 "bestIndex = %d, keycode = %d", bestIndex, keycode));
|
||||||
|
|
||||||
|
// if this for auto-repeat and this key does not auto-repeat
|
||||||
|
// then return 0.
|
||||||
|
if (isAutoRepeat &&
|
||||||
|
(m_keyControl.auto_repeats[keycode >> 3] &
|
||||||
|
static_cast<char>(1 << (keycode & 7))) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute desired mask. the desired mask is the one that matches
|
||||||
|
// bestIndex, except if the key being synthesized is a shift key
|
||||||
|
// where we desire what we already have or if it's the mode switch
|
||||||
|
// key where we only desire to adjust shift. also, if the keycode
|
||||||
|
// is not sensitive to shift then don't adjust it, otherwise
|
||||||
|
// something like shift+home would become just home. similiarly
|
||||||
|
// for mode switch.
|
||||||
|
KeyModifierMask desiredMask = currentMask;
|
||||||
|
if (keyIndex->second.m_modifierMask != KeyModifierShift) {
|
||||||
|
if (keyIndex->second.m_shiftSensitive[bestIndex]) {
|
||||||
|
if ((bestIndex & 1) != 0) {
|
||||||
|
desiredMask |= KeyModifierShift;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
desiredMask &= ~KeyModifierShift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyIndex->second.m_modifierMask != KeyModifierModeSwitch) {
|
||||||
|
if (keyIndex->second.m_modeSwitchSensitive[bestIndex]) {
|
||||||
|
if ((bestIndex & 2) != 0) {
|
||||||
|
desiredMask |= KeyModifierModeSwitch;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
desiredMask &= ~KeyModifierModeSwitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust the modifiers to match the desired modifiers
|
||||||
|
IKeyState::Keystrokes undo;
|
||||||
|
if (!adjustModifiers(keys, undo, keyState, desiredMask)) {
|
||||||
|
LOG((CLOG_DEBUG2 "failed to adjust modifiers"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the key event
|
||||||
|
IKeyState::Keystroke keystroke;
|
||||||
|
keystroke.m_key = keycode;
|
||||||
|
if (!isAutoRepeat) {
|
||||||
|
keystroke.m_press = true;
|
||||||
|
keystroke.m_repeat = false;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
keystroke.m_press = false;
|
||||||
|
keystroke.m_repeat = true;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
keystroke.m_press = true;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
}
|
||||||
|
|
||||||
|
// put undo keystrokes at end of keystrokes in reverse order
|
||||||
|
while (!undo.empty()) {
|
||||||
|
keys.push_back(undo.back());
|
||||||
|
undo.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
return keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
CXWindowsKeyMapper::findBestKeyIndex(KeySymIndex keyIndex,
|
||||||
|
KeyModifierMask /*currentMask*/) const
|
||||||
|
{
|
||||||
|
// there are up to 4 keycodes per keysym to choose from. the
|
||||||
|
// best choice is the one that requires the fewest adjustments
|
||||||
|
// to the modifier state. for example, the letter A normally
|
||||||
|
// requires shift + a. if shift isn't already down we'd have
|
||||||
|
// to synthesize a shift press before the a press. however,
|
||||||
|
// if A could also be created with some other keycode without
|
||||||
|
// shift then we'd prefer that when shift wasn't down.
|
||||||
|
//
|
||||||
|
// if the action is an auto-repeat then we don't call this
|
||||||
|
// method since we just need to synthesize a key repeat on the
|
||||||
|
// same keycode that we pressed.
|
||||||
|
// XXX -- do this right
|
||||||
|
for (unsigned int i = 0; i < 4; ++i) {
|
||||||
|
if (keyIndex->second.m_keycode[i] != 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(0 && "no keycode found for keysym");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CXWindowsKeyMapper::isShiftInverted(KeySymIndex keyIndex,
|
||||||
|
KeyModifierMask currentMask) const
|
||||||
|
{
|
||||||
|
// each keycode has up to 4 keysym associated with it, one each for:
|
||||||
|
// no modifiers, shift, mode switch, and shift and mode switch. if
|
||||||
|
// a keysym is modified by num lock and num lock is active then you
|
||||||
|
// get the shifted keysym when shift is not down and the unshifted
|
||||||
|
// keysym when it is. that is, num lock inverts the sense of the
|
||||||
|
// shift modifier when active. similarly for caps lock. this
|
||||||
|
// method returns true iff the sense of shift should be inverted
|
||||||
|
// for this key given a modifier state.
|
||||||
|
if (keyIndex->second.m_numLockSensitive) {
|
||||||
|
if ((currentMask & KeyModifierNumLock) != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a keysym is num lock sensitive it is never caps lock
|
||||||
|
// sensitive, thus the else here.
|
||||||
|
else if (keyIndex->second.m_capsLockSensitive) {
|
||||||
|
if ((currentMask & KeyModifierCapsLock) != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CXWindowsKeyMapper::adjustModifiers(IKeyState::Keystrokes& keys,
|
||||||
|
IKeyState::Keystrokes& undo,
|
||||||
|
const IKeyState& keyState,
|
||||||
|
KeyModifierMask desiredMask) const
|
||||||
|
{
|
||||||
|
KeyModifierMask currentMask = keyState.getActiveModifiers();
|
||||||
|
|
||||||
|
// get mode switch set correctly. do this before shift because
|
||||||
|
// mode switch may be sensitive to the shift modifier and will
|
||||||
|
// set/reset it as necessary.
|
||||||
|
const bool wantModeSwitch = ((desiredMask & KeyModifierModeSwitch) != 0);
|
||||||
|
const bool haveModeSwitch = ((currentMask & KeyModifierModeSwitch) != 0);
|
||||||
|
if (wantModeSwitch != haveModeSwitch) {
|
||||||
|
LOG((CLOG_DEBUG2 "fix mode switch"));
|
||||||
|
|
||||||
|
// adjust shift if necessary
|
||||||
|
KeySymIndex modeSwitchIndex = m_keysymMap.find(m_modeSwitchKeysym);
|
||||||
|
assert(modeSwitchIndex != m_keysymMap.end());
|
||||||
|
if (modeSwitchIndex->second.m_shiftSensitive[0]) {
|
||||||
|
const bool wantShift = false;
|
||||||
|
const bool haveShift = ((currentMask & KeyModifierShift) != 0);
|
||||||
|
if (wantShift != haveShift) {
|
||||||
|
// add shift keystrokes
|
||||||
|
LOG((CLOG_DEBUG2 "fix shift for mode switch"));
|
||||||
|
if (!keyState.mapModifier(keys, undo,
|
||||||
|
KeyModifierShift, wantShift)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
currentMask ^= KeyModifierShift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add mode switch keystrokes
|
||||||
|
if (!keyState.mapModifier(keys, undo,
|
||||||
|
KeyModifierModeSwitch, wantModeSwitch)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
currentMask ^= KeyModifierModeSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get shift set correctly
|
||||||
|
const bool wantShift = ((desiredMask & KeyModifierShift) != 0);
|
||||||
|
const bool haveShift = ((currentMask & KeyModifierShift) != 0);
|
||||||
|
if (wantShift != haveShift) {
|
||||||
|
// add shift keystrokes
|
||||||
|
LOG((CLOG_DEBUG2 "fix shift"));
|
||||||
|
if (!keyState.mapModifier(keys, undo, KeyModifierShift, wantShift)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
currentMask ^= KeyModifierShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CXWindowsKeyMapper::isNumLockSensitive(KeySym keysym) const
|
||||||
|
{
|
||||||
|
return (IsKeypadKey(keysym) || IsPrivateKeypadKey(keysym));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CXWindowsKeyMapper::isCapsLockSensitive(KeySym keysym) const
|
||||||
|
{
|
||||||
|
KeySym lKey, uKey;
|
||||||
|
XConvertCase(keysym, &lKey, &uKey);
|
||||||
|
return (lKey != uKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// CXWindowsKeyMapper::KeyMapping
|
||||||
|
//
|
||||||
|
|
||||||
|
CXWindowsKeyMapper::KeyMapping::KeyMapping()
|
||||||
|
{
|
||||||
|
m_keycode[0] = 0;
|
||||||
|
m_keycode[1] = 0;
|
||||||
|
m_keycode[2] = 0;
|
||||||
|
m_keycode[3] = 0;
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CXWINDOWSKEYMAPPER_H
|
||||||
|
#define CXWINDOWSKEYMAPPER_H
|
||||||
|
|
||||||
|
#include "IKeyState.h"
|
||||||
|
#include "stdmap.h"
|
||||||
|
#if defined(X_DISPLAY_MISSING)
|
||||||
|
# error X11 is required to build synergy
|
||||||
|
#else
|
||||||
|
# include <X11/Xlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! X Windows key mapper
|
||||||
|
/*!
|
||||||
|
This class maps KeyIDs to keystrokes.
|
||||||
|
*/
|
||||||
|
class CXWindowsKeyMapper {
|
||||||
|
public:
|
||||||
|
CXWindowsKeyMapper();
|
||||||
|
~CXWindowsKeyMapper();
|
||||||
|
|
||||||
|
//! @name manipulators
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Update key mapper
|
||||||
|
/*!
|
||||||
|
Updates the key mapper's internal tables according to the display's
|
||||||
|
current keyboard mapping and updates \c keyState.
|
||||||
|
*/
|
||||||
|
void update(Display*, IKeyState* keyState);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Map key press/repeat to keystrokes
|
||||||
|
/*!
|
||||||
|
Converts a press/repeat of key \c id with the modifiers as given
|
||||||
|
in \c desiredMask into the keystrokes necessary to synthesize
|
||||||
|
that key event. Returns the platform specific code of the key
|
||||||
|
being pressed, or 0 if the key cannot be mapped or \c isAutoRepeat
|
||||||
|
is true and the key does not auto-repeat.
|
||||||
|
*/
|
||||||
|
KeyButton mapKey(IKeyState::Keystrokes&,
|
||||||
|
const IKeyState& keyState, KeyID id,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
//! Convert X modifier mask to synergy mask
|
||||||
|
/*!
|
||||||
|
Returns the synergy modifier mask corresponding to the given X
|
||||||
|
modifier mask.
|
||||||
|
*/
|
||||||
|
KeyModifierMask mapModifier(unsigned int state) const;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class KeyMapping {
|
||||||
|
public:
|
||||||
|
KeyMapping();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// KeyCode to generate keysym and whether keycode[i] is
|
||||||
|
// sensitive to shift and mode switch.
|
||||||
|
KeyCode m_keycode[4];
|
||||||
|
bool m_shiftSensitive[4];
|
||||||
|
bool m_modeSwitchSensitive[4];
|
||||||
|
|
||||||
|
// the modifier mask of keysym or 0 if not a modifier
|
||||||
|
KeyModifierMask m_modifierMask;
|
||||||
|
|
||||||
|
// whether keysym is sensitive to caps and num lock
|
||||||
|
bool m_numLockSensitive;
|
||||||
|
bool m_capsLockSensitive;
|
||||||
|
};
|
||||||
|
typedef std::map<KeySym, KeyMapping> KeySymMap;
|
||||||
|
typedef KeySymMap::const_iterator KeySymIndex;
|
||||||
|
|
||||||
|
// save the current keyboard mapping and note the currently
|
||||||
|
// pressed keys in \c keyState.
|
||||||
|
void updateKeysymMap(Display* display, IKeyState* keyState);
|
||||||
|
|
||||||
|
// note interesting modifier KeySyms
|
||||||
|
void updateModifiers();
|
||||||
|
|
||||||
|
// map a modifier index and its KeySym to a modifier mask. also
|
||||||
|
// save the modifier mask in one of m_*Mask.
|
||||||
|
KeyModifierMask mapToModifierMask(unsigned int, KeySym);
|
||||||
|
|
||||||
|
// convert a KeyID to a KeySym
|
||||||
|
KeySym keyIDToKeySym(KeyID id, KeyModifierMask mask) const;
|
||||||
|
|
||||||
|
// map a KeySym into the keystrokes to produce it
|
||||||
|
KeyButton mapToKeystrokes(IKeyState::Keystrokes& keys,
|
||||||
|
const IKeyState& keyState,
|
||||||
|
KeySymIndex keyIndex,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
|
// choose the best set of modifiers to generate the KeySym
|
||||||
|
unsigned int findBestKeyIndex(KeySymIndex keyIndex,
|
||||||
|
KeyModifierMask currentMask) const;
|
||||||
|
|
||||||
|
// returns true if the sense of shift is inverted for KeySym
|
||||||
|
bool isShiftInverted(KeySymIndex keyIndex,
|
||||||
|
KeyModifierMask currentMask) const;
|
||||||
|
|
||||||
|
// returns the keystrokes to adjust the modifiers into the desired
|
||||||
|
// state the keystrokes to get back to the current state.
|
||||||
|
bool adjustModifiers(IKeyState::Keystrokes& keys,
|
||||||
|
IKeyState::Keystrokes& undo,
|
||||||
|
const IKeyState& keyState,
|
||||||
|
KeyModifierMask desiredMask) const;
|
||||||
|
|
||||||
|
// returns true if keysym is sensitive to the NumLock state
|
||||||
|
bool isNumLockSensitive(KeySym keysym) const;
|
||||||
|
|
||||||
|
// returns true if keysym is sensitive to the CapsLock state
|
||||||
|
bool isCapsLockSensitive(KeySym keysym) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// keysym to keycode mapping
|
||||||
|
KeySymMap m_keysymMap;
|
||||||
|
|
||||||
|
// the keyboard control state the last time this screen was entered
|
||||||
|
XKeyboardState m_keyControl;
|
||||||
|
|
||||||
|
// modifier keysyms
|
||||||
|
KeySym m_modeSwitchKeysym;
|
||||||
|
|
||||||
|
// modifier masks
|
||||||
|
unsigned int m_altMask;
|
||||||
|
unsigned int m_metaMask;
|
||||||
|
unsigned int m_superMask;
|
||||||
|
unsigned int m_modeSwitchMask;
|
||||||
|
unsigned int m_numLockMask;
|
||||||
|
unsigned int m_scrollLockMask;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CXWINDOWSPRIMARYSCREEN_H
|
|
||||||
#define CXWINDOWSPRIMARYSCREEN_H
|
|
||||||
|
|
||||||
#include "CPrimaryScreen.h"
|
|
||||||
#include "IScreenEventHandler.h"
|
|
||||||
#include "MouseTypes.h"
|
|
||||||
#if defined(X_DISPLAY_MISSING)
|
|
||||||
# error X11 is required to build synergy
|
|
||||||
#else
|
|
||||||
# include <X11/Xlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class CXWindowsScreen;
|
|
||||||
class IScreenReceiver;
|
|
||||||
class IPrimaryScreenReceiver;
|
|
||||||
|
|
||||||
//! X11 primary screen implementation
|
|
||||||
class CXWindowsPrimaryScreen :
|
|
||||||
public CPrimaryScreen, public IScreenEventHandler {
|
|
||||||
public:
|
|
||||||
CXWindowsPrimaryScreen(IScreenReceiver*, IPrimaryScreenReceiver*);
|
|
||||||
virtual ~CXWindowsPrimaryScreen();
|
|
||||||
|
|
||||||
// CPrimaryScreen overrides
|
|
||||||
virtual void reconfigure(UInt32 activeSides);
|
|
||||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
|
||||||
virtual void resetOptions();
|
|
||||||
virtual void setOptions(const COptionsList& options);
|
|
||||||
virtual UInt32 addOneShotTimer(double timeout);
|
|
||||||
virtual KeyModifierMask getToggleMask() const;
|
|
||||||
virtual bool isLockedToScreen() const;
|
|
||||||
virtual IScreen* getScreen() const;
|
|
||||||
|
|
||||||
// IScreenEventHandler overrides
|
|
||||||
virtual void onScreensaver(bool activated);
|
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
|
||||||
virtual bool onEvent(CEvent* event);
|
|
||||||
virtual void onOneShotTimerExpired(UInt32 id);
|
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// CPrimaryScreen overrides
|
|
||||||
virtual void onPreMainLoop();
|
|
||||||
virtual void onPreOpen();
|
|
||||||
virtual void onPostOpen();
|
|
||||||
virtual void onPreClose();
|
|
||||||
virtual void onPreEnter();
|
|
||||||
virtual void onPreLeave();
|
|
||||||
virtual void onEnterScreenSaver();
|
|
||||||
|
|
||||||
virtual void createWindow();
|
|
||||||
virtual void destroyWindow();
|
|
||||||
virtual bool showWindow();
|
|
||||||
virtual void hideWindow();
|
|
||||||
virtual void warpCursorToCenter();
|
|
||||||
|
|
||||||
virtual void updateKeys();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void warpCursorNoFlush(Display*,
|
|
||||||
SInt32 xAbsolute, SInt32 yAbsolute);
|
|
||||||
|
|
||||||
void selectEvents(Display*, Window) const;
|
|
||||||
void doSelectEvents(Display*, Window) const;
|
|
||||||
|
|
||||||
KeyModifierMask mapModifier(unsigned int state) const;
|
|
||||||
KeyID mapKey(XKeyEvent*) const;
|
|
||||||
ButtonID mapButton(unsigned int button) const;
|
|
||||||
|
|
||||||
class CKeyEventInfo {
|
|
||||||
public:
|
|
||||||
int m_event;
|
|
||||||
Window m_window;
|
|
||||||
Time m_time;
|
|
||||||
KeyCode m_keycode;
|
|
||||||
};
|
|
||||||
static Bool findKeyEvent(Display*, XEvent* xevent, XPointer arg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CXWindowsScreen* m_screen;
|
|
||||||
IPrimaryScreenReceiver* m_receiver;
|
|
||||||
|
|
||||||
// our window
|
|
||||||
Window m_window;
|
|
||||||
|
|
||||||
// note toggle keys that toggle on up/down (false) or on
|
|
||||||
// transition (true)
|
|
||||||
bool m_numLockHalfDuplex;
|
|
||||||
bool m_capsLockHalfDuplex;
|
|
||||||
|
|
||||||
// modifier masks
|
|
||||||
unsigned int m_altMask;
|
|
||||||
unsigned int m_metaMask;
|
|
||||||
unsigned int m_superMask;
|
|
||||||
unsigned int m_modeSwitchMask;
|
|
||||||
unsigned int m_numLockMask;
|
|
||||||
unsigned int m_capsLockMask;
|
|
||||||
unsigned int m_scrollLockMask;
|
|
||||||
|
|
||||||
// last mouse position
|
|
||||||
SInt32 m_x, m_y;
|
|
||||||
|
|
||||||
// position of center pixel of screen
|
|
||||||
SInt32 m_xCenter, m_yCenter;
|
|
||||||
|
|
||||||
// input method stuff
|
|
||||||
XIM m_im;
|
|
||||||
XIC m_ic;
|
|
||||||
KeyCode m_lastKeycode;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,40 +15,28 @@
|
||||||
#ifndef CXWINDOWSSCREEN_H
|
#ifndef CXWINDOWSSCREEN_H
|
||||||
#define CXWINDOWSSCREEN_H
|
#define CXWINDOWSSCREEN_H
|
||||||
|
|
||||||
#include "IScreen.h"
|
#include "IPlatformScreen.h"
|
||||||
|
#include "CXWindowsKeyMapper.h"
|
||||||
#include "CMutex.h"
|
#include "CMutex.h"
|
||||||
#include "CStopwatch.h"
|
#include "CStopwatch.h"
|
||||||
|
#include "CPriorityQueue.h"
|
||||||
#include "stdvector.h"
|
#include "stdvector.h"
|
||||||
#if defined(X_DISPLAY_MISSING)
|
#if defined(X_DISPLAY_MISSING)
|
||||||
# error X11 is required to build synergy
|
# error X11 is required to build synergy
|
||||||
#else
|
#else
|
||||||
# include <X11/Xlib.h>
|
# include <X11/Xlib.h>
|
||||||
#endif
|
#endif
|
||||||
#include <algorithm>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
class IJob;
|
|
||||||
class IScreenEventHandler;
|
|
||||||
class IScreenReceiver;
|
|
||||||
class CXWindowsClipboard;
|
class CXWindowsClipboard;
|
||||||
class CXWindowsScreenSaver;
|
class CXWindowsScreenSaver;
|
||||||
|
class IJob;
|
||||||
|
class IScreenReceiver;
|
||||||
|
class IPrimaryScreenReceiver;
|
||||||
|
|
||||||
/*!
|
//! Implementation of IPlatformScreen for X11
|
||||||
\class CEvent
|
class CXWindowsScreen : public IPlatformScreen {
|
||||||
\brief User event data
|
|
||||||
An architecture dependent type holding user event data.
|
|
||||||
*/
|
|
||||||
// X11 event
|
|
||||||
class CEvent {
|
|
||||||
public:
|
public:
|
||||||
XEvent m_event;
|
CXWindowsScreen(IScreenReceiver*, IPrimaryScreenReceiver*);
|
||||||
SInt32 m_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Implementation of IScreen for X11
|
|
||||||
class CXWindowsScreen : public IScreen {
|
|
||||||
public:
|
|
||||||
CXWindowsScreen(IScreenReceiver*, IScreenEventHandler*);
|
|
||||||
virtual ~CXWindowsScreen();
|
virtual ~CXWindowsScreen();
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
@ -56,10 +44,10 @@ public:
|
||||||
|
|
||||||
//! Add timer
|
//! Add timer
|
||||||
/*!
|
/*!
|
||||||
Add a job to invoke every timeout seconds. The job is
|
Add a job to invoke every timeout seconds. The job is called
|
||||||
called with the display locked. If a job timeout expires twice
|
with the display locked. If a job timeout expires twice or
|
||||||
or more before the job can be called then the job is called
|
more before the job can be called then the job is called just
|
||||||
just once. The caller retains ownership of the job.
|
once. The caller retains ownership of the job.
|
||||||
*/
|
*/
|
||||||
void addTimer(IJob*, double timeout);
|
void addTimer(IJob*, double timeout);
|
||||||
|
|
||||||
|
@ -69,64 +57,55 @@ public:
|
||||||
*/
|
*/
|
||||||
void removeTimer(IJob*);
|
void removeTimer(IJob*);
|
||||||
|
|
||||||
//! Install a one-shot timer
|
|
||||||
/*!
|
|
||||||
Installs a one-shot timer for \c timeout seconds and returns the
|
|
||||||
id of the timer (which will be passed to the receiver's
|
|
||||||
\c onTimerExpired()).
|
|
||||||
*/
|
|
||||||
UInt32 addOneShotTimer(double timeout);
|
|
||||||
|
|
||||||
//! Set window
|
|
||||||
/*!
|
|
||||||
Set the window (created by the subclass). This performs some
|
|
||||||
initialization and saves the window in case it's needed later.
|
|
||||||
*/
|
|
||||||
void setWindow(Window);
|
|
||||||
|
|
||||||
//@}
|
|
||||||
//! @name accessors
|
|
||||||
//@{
|
|
||||||
|
|
||||||
//! Get window
|
|
||||||
/*!
|
|
||||||
Returns the root window of the screen.
|
|
||||||
*/
|
|
||||||
Window getRoot() const;
|
|
||||||
|
|
||||||
//! Get transparent cursor
|
|
||||||
/*!
|
|
||||||
Returns a cursor that is transparent everywhere.
|
|
||||||
*/
|
|
||||||
Cursor getBlankCursor() const;
|
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
// IScreen overrides
|
// IPlatformScreen overrides
|
||||||
void open();
|
virtual void open(IKeyState*);
|
||||||
void mainLoop();
|
virtual void close();
|
||||||
void exitMainLoop();
|
virtual void enable();
|
||||||
void close();
|
virtual void disable();
|
||||||
bool setClipboard(ClipboardID, const IClipboard*);
|
virtual void mainLoop();
|
||||||
void checkClipboards();
|
virtual void exitMainLoop();
|
||||||
void openScreensaver(bool notify);
|
virtual void enter();
|
||||||
void closeScreensaver();
|
virtual bool leave();
|
||||||
void screensaver(bool activate);
|
virtual bool setClipboard(ClipboardID, const IClipboard*);
|
||||||
void syncDesktop();
|
virtual void checkClipboards();
|
||||||
bool getClipboard(ClipboardID, IClipboard*) const;
|
virtual void openScreensaver(bool notify);
|
||||||
void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
virtual void closeScreensaver();
|
||||||
void getCursorPos(SInt32&, SInt32&) const;
|
virtual void screensaver(bool activate);
|
||||||
void getCursorCenter(SInt32&, SInt32&) const;
|
virtual void resetOptions();
|
||||||
|
virtual void setOptions(const COptionsList& options);
|
||||||
|
virtual void updateKeys();
|
||||||
|
virtual bool isPrimary() const;
|
||||||
|
virtual bool getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
virtual void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
||||||
|
virtual void getCursorPos(SInt32&, SInt32&) const;
|
||||||
|
|
||||||
|
// IPrimaryScreen overrides
|
||||||
|
virtual void reconfigure(UInt32 activeSides);
|
||||||
|
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||||
|
virtual UInt32 addOneShotTimer(double timeout);
|
||||||
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
virtual bool isAnyMouseButtonDown() const;
|
||||||
|
virtual const char* getKeyName(KeyButton) const;
|
||||||
|
|
||||||
|
// ISecondaryScreen overrides
|
||||||
|
virtual void fakeKeyEvent(KeyButton id, bool press) const;
|
||||||
|
virtual bool fakeCtrlAltDel() const;
|
||||||
|
virtual void fakeMouseButton(ButtonID id, bool press) const;
|
||||||
|
virtual void fakeMouseMove(SInt32 x, SInt32 y) const;
|
||||||
|
virtual void fakeMouseWheel(SInt32 delta) const;
|
||||||
|
virtual KeyButton mapKey(IKeyState::Keystrokes&,
|
||||||
|
const IKeyState& keyState, KeyID id,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// update screen size cache
|
|
||||||
void updateScreenShape();
|
|
||||||
|
|
||||||
// process events before dispatching to receiver
|
// process events before dispatching to receiver
|
||||||
bool onPreDispatch(CEvent* event);
|
void onEvent(XEvent* event);
|
||||||
|
|
||||||
// create the transparent cursor
|
// create the transparent cursor
|
||||||
void createBlankCursor();
|
Cursor createBlankCursor() const;
|
||||||
|
|
||||||
// remove a timer without locking
|
// remove a timer without locking
|
||||||
void removeTimerNoLock(IJob*);
|
void removeTimerNoLock(IJob*);
|
||||||
|
@ -149,78 +128,6 @@ private:
|
||||||
static int ioErrorHandler(Display*);
|
static int ioErrorHandler(Display*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// a priority queue will direct access to the elements
|
|
||||||
template <class T, class Container = std::vector<T>,
|
|
||||||
class Compare = std::greater<typename Container::value_type> >
|
|
||||||
class CPriorityQueue {
|
|
||||||
public:
|
|
||||||
typedef typename Container::value_type value_type;
|
|
||||||
typedef typename Container::size_type size_type;
|
|
||||||
typedef typename Container::iterator iterator;
|
|
||||||
typedef Container container_type;
|
|
||||||
|
|
||||||
CPriorityQueue() { }
|
|
||||||
CPriorityQueue(Container& swappedIn);
|
|
||||||
~CPriorityQueue() { }
|
|
||||||
|
|
||||||
// manipulators
|
|
||||||
|
|
||||||
void push(const value_type& v)
|
|
||||||
{
|
|
||||||
c.push_back(v);
|
|
||||||
std::push_heap(c.begin(), c.end(), comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop()
|
|
||||||
{
|
|
||||||
std::pop_heap(c.begin(), c.end(), comp);
|
|
||||||
c.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator begin()
|
|
||||||
{
|
|
||||||
return c.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator end()
|
|
||||||
{
|
|
||||||
return c.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(CPriorityQueue<T, Container, Compare>& q)
|
|
||||||
{
|
|
||||||
c.swap(q.c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(Container& c2)
|
|
||||||
{
|
|
||||||
c.swap(c2);
|
|
||||||
std::make_heap(c.begin(), c.end(), comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// accessors
|
|
||||||
|
|
||||||
bool empty() const
|
|
||||||
{
|
|
||||||
return c.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_type size() const
|
|
||||||
{
|
|
||||||
return c.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const value_type&
|
|
||||||
top() const
|
|
||||||
{
|
|
||||||
return c.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Container c;
|
|
||||||
Compare comp;
|
|
||||||
};
|
|
||||||
|
|
||||||
// a timer priority queue element
|
// a timer priority queue element
|
||||||
class CTimer {
|
class CTimer {
|
||||||
public:
|
public:
|
||||||
|
@ -252,32 +159,80 @@ private:
|
||||||
double m_time;
|
double m_time;
|
||||||
double m_startTime;
|
double m_startTime;
|
||||||
};
|
};
|
||||||
|
class CKeyEventInfo {
|
||||||
|
public:
|
||||||
|
int m_event;
|
||||||
|
Window m_window;
|
||||||
|
Time m_time;
|
||||||
|
KeyCode m_keycode;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isQuitEvent(XEvent*) const;
|
||||||
|
|
||||||
|
Window createWindow() const;
|
||||||
|
void openIM();
|
||||||
|
|
||||||
|
bool grabMouseAndKeyboard();
|
||||||
|
void onKeyPress(XKeyEvent&);
|
||||||
|
void onKeyRelease(XKeyEvent&);
|
||||||
|
void onMousePress(const XButtonEvent&);
|
||||||
|
void onMouseRelease(const XButtonEvent&);
|
||||||
|
void onMouseMove(const XMotionEvent&);
|
||||||
|
|
||||||
|
void selectEvents(Window) const;
|
||||||
|
void doSelectEvents(Window) const;
|
||||||
|
|
||||||
|
KeyID mapKeyFromX(XKeyEvent*) const;
|
||||||
|
ButtonID mapButtonFromX(const XButtonEvent*) const;
|
||||||
|
unsigned int mapButtonToX(ButtonID id) const;
|
||||||
|
|
||||||
|
void warpCursorNoFlush(SInt32 x, SInt32 y);
|
||||||
|
|
||||||
|
void updateButtons();
|
||||||
|
|
||||||
|
static Bool findKeyEvent(Display*, XEvent* xevent, XPointer arg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class CDisplayLock;
|
|
||||||
|
|
||||||
typedef CPriorityQueue<CTimer> CTimerPriorityQueue;
|
typedef CPriorityQueue<CTimer> CTimerPriorityQueue;
|
||||||
|
|
||||||
|
// true if screen is being used as a primary screen, false otherwise
|
||||||
|
bool m_isPrimary;
|
||||||
|
|
||||||
// X is not thread safe
|
// X is not thread safe
|
||||||
CMutex m_mutex;
|
CMutex m_mutex;
|
||||||
|
|
||||||
Display* m_display;
|
Display* m_display;
|
||||||
Window m_root;
|
Window m_root;
|
||||||
bool m_stop;
|
|
||||||
|
|
||||||
IScreenReceiver* m_receiver;
|
|
||||||
IScreenEventHandler* m_eventHandler;
|
|
||||||
Window m_window;
|
Window m_window;
|
||||||
|
|
||||||
|
IScreenReceiver* m_receiver;
|
||||||
|
IPrimaryScreenReceiver* m_primaryReceiver;
|
||||||
|
|
||||||
|
// true if mouse has entered the screen
|
||||||
|
bool m_isOnScreen;
|
||||||
|
|
||||||
|
// screen shape stuff
|
||||||
SInt32 m_x, m_y;
|
SInt32 m_x, m_y;
|
||||||
SInt32 m_w, m_h;
|
SInt32 m_w, m_h;
|
||||||
SInt32 m_xCenter, m_yCenter;
|
SInt32 m_xCenter, m_yCenter;
|
||||||
|
|
||||||
|
// last mouse position
|
||||||
|
SInt32 m_xCursor, m_yCursor;
|
||||||
|
|
||||||
|
// keyboard stuff
|
||||||
|
IKeyState* m_keyState;
|
||||||
|
CXWindowsKeyMapper m_keyMapper;
|
||||||
|
|
||||||
|
// input method stuff
|
||||||
|
XIM m_im;
|
||||||
|
XIC m_ic;
|
||||||
|
KeyCode m_lastKeycode;
|
||||||
|
|
||||||
// clipboards
|
// clipboards
|
||||||
CXWindowsClipboard* m_clipboard[kClipboardEnd];
|
CXWindowsClipboard* m_clipboard[kClipboardEnd];
|
||||||
|
|
||||||
// the transparent cursor
|
// the quit message
|
||||||
Cursor m_cursor;
|
Atom m_atomQuit;
|
||||||
|
|
||||||
// screen saver stuff
|
// screen saver stuff
|
||||||
CXWindowsScreenSaver* m_screensaver;
|
CXWindowsScreenSaver* m_screensaver;
|
||||||
|
@ -290,22 +245,23 @@ private:
|
||||||
CMutex m_timersMutex;
|
CMutex m_timersMutex;
|
||||||
CTimer* m_oneShotTimer;
|
CTimer* m_oneShotTimer;
|
||||||
|
|
||||||
|
// logical to physical button mapping. m_buttons[i] gives the
|
||||||
|
// physical button for logical button i+1.
|
||||||
|
std::vector<unsigned char> m_buttons;
|
||||||
|
|
||||||
|
// true if global auto-repeat was enabled before we turned it off
|
||||||
|
bool m_autoRepeat;
|
||||||
|
|
||||||
|
// stuff to workaround xtest being xinerama unaware. attempting
|
||||||
|
// to fake a mouse motion under xinerama may behave strangely,
|
||||||
|
// especially if screen 0 is not at 0,0 or if faking a motion on
|
||||||
|
// a screen other than screen 0.
|
||||||
|
bool m_xtestIsXineramaUnaware;
|
||||||
|
bool m_xinerama;
|
||||||
|
|
||||||
// pointer to (singleton) screen. this is only needed by
|
// pointer to (singleton) screen. this is only needed by
|
||||||
// ioErrorHandler().
|
// ioErrorHandler().
|
||||||
static CXWindowsScreen* s_screen;
|
static CXWindowsScreen* s_screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Convenience object to lock/unlock a CXWindowsScreen
|
|
||||||
class CDisplayLock {
|
|
||||||
public:
|
|
||||||
CDisplayLock(const CXWindowsScreen*);
|
|
||||||
~CDisplayLock();
|
|
||||||
|
|
||||||
operator Display*() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const CMutex* m_mutex;
|
|
||||||
Display* m_display;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,195 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CXWINDOWSSECONDARYSCREEN_H
|
|
||||||
#define CXWINDOWSSECONDARYSCREEN_H
|
|
||||||
|
|
||||||
#include "CSecondaryScreen.h"
|
|
||||||
#include "IScreenEventHandler.h"
|
|
||||||
#include "stdmap.h"
|
|
||||||
#include "stdvector.h"
|
|
||||||
#if defined(X_DISPLAY_MISSING)
|
|
||||||
# error X11 is required to build synergy
|
|
||||||
#else
|
|
||||||
# include <X11/Xlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class CXWindowsScreen;
|
|
||||||
class IScreenReceiver;
|
|
||||||
|
|
||||||
//! X11 secondary screen implementation
|
|
||||||
class CXWindowsSecondaryScreen :
|
|
||||||
public CSecondaryScreen, public IScreenEventHandler {
|
|
||||||
public:
|
|
||||||
CXWindowsSecondaryScreen(IScreenReceiver*);
|
|
||||||
virtual ~CXWindowsSecondaryScreen();
|
|
||||||
|
|
||||||
// CSecondaryScreen overrides
|
|
||||||
virtual void resetOptions();
|
|
||||||
virtual void setOptions(const COptionsList& options);
|
|
||||||
virtual IScreen* getScreen() const;
|
|
||||||
|
|
||||||
// IScreenEventHandler overrides
|
|
||||||
virtual void onScreensaver(bool activated);
|
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
|
||||||
virtual bool onEvent(CEvent* event);
|
|
||||||
virtual void onOneShotTimerExpired(UInt32 id);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// CSecondaryScreen overrides
|
|
||||||
virtual void onPreMainLoop();
|
|
||||||
virtual void onPreOpen();
|
|
||||||
virtual void onPostOpen();
|
|
||||||
virtual void onPreClose();
|
|
||||||
virtual void onPreEnter();
|
|
||||||
virtual void onPostEnter();
|
|
||||||
virtual void onPreLeave();
|
|
||||||
virtual void createWindow();
|
|
||||||
virtual void destroyWindow();
|
|
||||||
virtual void showWindow(SInt32 x, SInt32 y);
|
|
||||||
virtual void hideWindow();
|
|
||||||
virtual void updateKeys(KeyState* sysKeyStates);
|
|
||||||
virtual KeyModifierMask getModifiers() const;
|
|
||||||
|
|
||||||
virtual bool isAutoRepeating(SysKeyID) const;
|
|
||||||
virtual KeyModifierMask getModifierKeyMask(SysKeyID) const;
|
|
||||||
virtual bool isModifierActive(SysKeyID) const;
|
|
||||||
virtual SysKeyID getToggleSysKey(KeyID keyID) const;
|
|
||||||
virtual void flush();
|
|
||||||
virtual KeyModifierMask
|
|
||||||
mapKey(Keystrokes&, SysKeyID& sysKeyID, KeyID,
|
|
||||||
KeyModifierMask, KeyModifierMask, EKeyAction) const;
|
|
||||||
virtual void fakeKeyEvent(SysKeyID, bool press) const;
|
|
||||||
virtual void fakeMouseButton(ButtonID, bool press) const;
|
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const;
|
|
||||||
virtual void fakeMouseWheel(SInt32 delta) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef unsigned int ModifierIndex;
|
|
||||||
class KeyMapping {
|
|
||||||
public:
|
|
||||||
KeyMapping();
|
|
||||||
|
|
||||||
public:
|
|
||||||
// KeyCode to generate keysym and whether keycode[i] is
|
|
||||||
// sensitive to shift and mode switch.
|
|
||||||
KeyCode m_keycode[4];
|
|
||||||
bool m_shiftSensitive[4];
|
|
||||||
bool m_modeSwitchSensitive[4];
|
|
||||||
|
|
||||||
// the modifier mask of keysym or 0 if not a modifier
|
|
||||||
KeyModifierMask m_modifierMask;
|
|
||||||
|
|
||||||
// whether keysym is sensitive to caps and num lock
|
|
||||||
bool m_numLockSensitive;
|
|
||||||
bool m_capsLockSensitive;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<KeyCode> KeyCodes;
|
|
||||||
typedef std::map<KeyCode, ModifierIndex> KeyCodeToModifierMap;
|
|
||||||
typedef std::map<KeySym, KeyMapping> KeySymMap;
|
|
||||||
typedef KeySymMap::const_iterator KeySymIndex;
|
|
||||||
typedef std::vector<KeySym> KeySyms;
|
|
||||||
typedef std::map<KeySym, KeySyms> KeySymsMap;
|
|
||||||
|
|
||||||
unsigned int mapButton(ButtonID button) const;
|
|
||||||
|
|
||||||
bool mapToKeystrokes(Keystrokes& keys,
|
|
||||||
SysKeyID& keycode,
|
|
||||||
KeyModifierMask& finalMask,
|
|
||||||
KeySymIndex keyIndex,
|
|
||||||
KeyModifierMask currentMask,
|
|
||||||
EKeyAction action,
|
|
||||||
bool isHalfDuplex) const;
|
|
||||||
bool adjustModifiers(Keystrokes& keys,
|
|
||||||
Keystrokes& undo,
|
|
||||||
KeyModifierMask& inOutMask,
|
|
||||||
KeyModifierMask desiredMask) const;
|
|
||||||
bool adjustModifier(Keystrokes& keys,
|
|
||||||
Keystrokes& undo,
|
|
||||||
KeySym keysym,
|
|
||||||
bool desireActive) const;
|
|
||||||
KeyModifierMask mapToModifierMask(ModifierIndex, KeySym) const;
|
|
||||||
|
|
||||||
unsigned int findBestKeyIndex(KeySymIndex keyIndex,
|
|
||||||
KeyModifierMask currentMask) const;
|
|
||||||
bool isShiftInverted(KeySymIndex keyIndex,
|
|
||||||
KeyModifierMask currentMask) const;
|
|
||||||
|
|
||||||
void doUpdateKeys(Display*);
|
|
||||||
void updateKeysymMap(Display* display);
|
|
||||||
void updateModifiers(Display* display);
|
|
||||||
ModifierIndex keySymToModifierIndex(KeySym) const;
|
|
||||||
static bool isToggleKeysym(KeySym);
|
|
||||||
|
|
||||||
KeySym keyIDToKeySym(KeyID id, KeyModifierMask mask) const;
|
|
||||||
bool adjustForNumLock(KeySym) const;
|
|
||||||
bool adjustForCapsLock(KeySym) const;
|
|
||||||
|
|
||||||
bool decomposeKeySym(KeySym keysym,
|
|
||||||
KeySyms& decomposed) const;
|
|
||||||
static const KeySymsMap& getDecomposedKeySymTable();
|
|
||||||
|
|
||||||
private:
|
|
||||||
CXWindowsScreen* m_screen;
|
|
||||||
Window m_window;
|
|
||||||
|
|
||||||
// logical to physical button mapping. m_buttons[i] gives the
|
|
||||||
// physical button for logical button i+1.
|
|
||||||
std::vector<unsigned char> m_buttons;
|
|
||||||
|
|
||||||
// the modifiers that have keys bound to them
|
|
||||||
KeyModifierMask m_modifierMask;
|
|
||||||
|
|
||||||
// set bits indicate modifiers that toggle (e.g. caps-lock)
|
|
||||||
KeyModifierMask m_toggleModifierMask;
|
|
||||||
|
|
||||||
// keysym to keycode mapping
|
|
||||||
KeySymMap m_keysymMap;
|
|
||||||
|
|
||||||
// modifier index to keycodes
|
|
||||||
KeyCodes m_modifierKeycodes[8];
|
|
||||||
|
|
||||||
// modifier index to modifier mask
|
|
||||||
KeyModifierMask m_modifierIndexToMask[8];
|
|
||||||
|
|
||||||
// keycode to modifier index
|
|
||||||
KeyCodeToModifierMap m_keycodeToModifier;
|
|
||||||
|
|
||||||
// modifier keysyms
|
|
||||||
KeySym m_shiftKeysym;
|
|
||||||
KeySym m_ctrlKeysym;
|
|
||||||
KeySym m_altKeysym;
|
|
||||||
KeySym m_metaKeysym;
|
|
||||||
KeySym m_superKeysym;
|
|
||||||
KeySym m_modeSwitchKeysym;
|
|
||||||
KeySym m_numLockKeysym;
|
|
||||||
KeySym m_capsLockKeysym;
|
|
||||||
KeySym m_scrollLockKeysym;
|
|
||||||
|
|
||||||
// the keyboard control state the last time this screen was entered
|
|
||||||
XKeyboardState m_keyControl;
|
|
||||||
|
|
||||||
// stuff to workaround xtest being xinerama unaware. attempting
|
|
||||||
// to fake a mouse motion under xinerama may behave strangely,
|
|
||||||
// especially if screen 0 is not at 0,0 or if faking a motion on
|
|
||||||
// a screen other than screen 0.
|
|
||||||
bool m_xtestIsXineramaUnaware;
|
|
||||||
bool m_xinerama;
|
|
||||||
|
|
||||||
// a table of keysym decompositions
|
|
||||||
static KeySymsMap s_decomposedKeySyms;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -16,6 +16,14 @@
|
||||||
#include "CThread.h"
|
#include "CThread.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#define XK_XKB_KEYS
|
||||||
|
#define XK_LATIN1
|
||||||
|
#define XK_LATIN2
|
||||||
|
#define XK_LATIN3
|
||||||
|
#define XK_LATIN4
|
||||||
|
#define XK_LATIN8
|
||||||
|
#define XK_LATIN9
|
||||||
|
#include <X11/keysymdef.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This table maps keysym values into the corresponding ISO 10646
|
* This table maps keysym values into the corresponding ISO 10646
|
||||||
|
@ -805,6 +813,218 @@ struct codepair {
|
||||||
{ 0x20ac, 0x20ac } /* EuroSign EURO SIGN */
|
{ 0x20ac, 0x20ac } /* EuroSign EURO SIGN */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const KeySym s_rawDecomposeTable[] = {
|
||||||
|
// non-dead version of dead keys
|
||||||
|
XK_grave, XK_dead_grave, XK_space, 0,
|
||||||
|
XK_acute, XK_dead_acute, XK_space, 0,
|
||||||
|
XK_asciicircum, XK_dead_circumflex, XK_space, 0,
|
||||||
|
XK_asciitilde, XK_dead_tilde, XK_space, 0,
|
||||||
|
XK_cedilla, XK_dead_cedilla, XK_space, 0,
|
||||||
|
XK_ogonek, XK_dead_ogonek, XK_space, 0,
|
||||||
|
XK_caron, XK_dead_caron, XK_space, 0,
|
||||||
|
XK_abovedot, XK_dead_abovedot, XK_space, 0,
|
||||||
|
XK_doubleacute, XK_dead_doubleacute, XK_space, 0,
|
||||||
|
XK_breve, XK_dead_breve, XK_space, 0,
|
||||||
|
XK_macron, XK_dead_macron, XK_space, 0,
|
||||||
|
|
||||||
|
// Latin-1 (ISO 8859-1)
|
||||||
|
XK_Agrave, XK_dead_grave, XK_A, 0,
|
||||||
|
XK_Aacute, XK_dead_acute, XK_A, 0,
|
||||||
|
XK_Acircumflex, XK_dead_circumflex, XK_A, 0,
|
||||||
|
XK_Atilde, XK_dead_tilde, XK_A, 0,
|
||||||
|
XK_Adiaeresis, XK_dead_diaeresis, XK_A, 0,
|
||||||
|
XK_Aring, XK_dead_abovering, XK_A, 0,
|
||||||
|
XK_Ccedilla, XK_dead_cedilla, XK_C, 0,
|
||||||
|
XK_Egrave, XK_dead_grave, XK_E, 0,
|
||||||
|
XK_Eacute, XK_dead_acute, XK_E, 0,
|
||||||
|
XK_Ecircumflex, XK_dead_circumflex, XK_E, 0,
|
||||||
|
XK_Ediaeresis, XK_dead_diaeresis, XK_E, 0,
|
||||||
|
XK_Igrave, XK_dead_grave, XK_I, 0,
|
||||||
|
XK_Iacute, XK_dead_acute, XK_I, 0,
|
||||||
|
XK_Icircumflex, XK_dead_circumflex, XK_I, 0,
|
||||||
|
XK_Idiaeresis, XK_dead_diaeresis, XK_I, 0,
|
||||||
|
XK_Ntilde, XK_dead_tilde, XK_N, 0,
|
||||||
|
XK_Ograve, XK_dead_grave, XK_O, 0,
|
||||||
|
XK_Oacute, XK_dead_acute, XK_O, 0,
|
||||||
|
XK_Ocircumflex, XK_dead_circumflex, XK_O, 0,
|
||||||
|
XK_Otilde, XK_dead_tilde, XK_O, 0,
|
||||||
|
XK_Odiaeresis, XK_dead_diaeresis, XK_O, 0,
|
||||||
|
XK_Ugrave, XK_dead_grave, XK_U, 0,
|
||||||
|
XK_Uacute, XK_dead_acute, XK_U, 0,
|
||||||
|
XK_Ucircumflex, XK_dead_circumflex, XK_U, 0,
|
||||||
|
XK_Udiaeresis, XK_dead_diaeresis, XK_U, 0,
|
||||||
|
XK_Yacute, XK_dead_acute, XK_Y, 0,
|
||||||
|
XK_agrave, XK_dead_grave, XK_a, 0,
|
||||||
|
XK_aacute, XK_dead_acute, XK_a, 0,
|
||||||
|
XK_acircumflex, XK_dead_circumflex, XK_a, 0,
|
||||||
|
XK_atilde, XK_dead_tilde, XK_a, 0,
|
||||||
|
XK_adiaeresis, XK_dead_diaeresis, XK_a, 0,
|
||||||
|
XK_aring, XK_dead_abovering, XK_a, 0,
|
||||||
|
XK_ccedilla, XK_dead_cedilla, XK_c, 0,
|
||||||
|
XK_egrave, XK_dead_grave, XK_e, 0,
|
||||||
|
XK_eacute, XK_dead_acute, XK_e, 0,
|
||||||
|
XK_ecircumflex, XK_dead_circumflex, XK_e, 0,
|
||||||
|
XK_ediaeresis, XK_dead_diaeresis, XK_e, 0,
|
||||||
|
XK_igrave, XK_dead_grave, XK_i, 0,
|
||||||
|
XK_iacute, XK_dead_acute, XK_i, 0,
|
||||||
|
XK_icircumflex, XK_dead_circumflex, XK_i, 0,
|
||||||
|
XK_idiaeresis, XK_dead_diaeresis, XK_i, 0,
|
||||||
|
XK_ntilde, XK_dead_tilde, XK_n, 0,
|
||||||
|
XK_ograve, XK_dead_grave, XK_o, 0,
|
||||||
|
XK_oacute, XK_dead_acute, XK_o, 0,
|
||||||
|
XK_ocircumflex, XK_dead_circumflex, XK_o, 0,
|
||||||
|
XK_otilde, XK_dead_tilde, XK_o, 0,
|
||||||
|
XK_odiaeresis, XK_dead_diaeresis, XK_o, 0,
|
||||||
|
XK_ugrave, XK_dead_grave, XK_u, 0,
|
||||||
|
XK_uacute, XK_dead_acute, XK_u, 0,
|
||||||
|
XK_ucircumflex, XK_dead_circumflex, XK_u, 0,
|
||||||
|
XK_udiaeresis, XK_dead_diaeresis, XK_u, 0,
|
||||||
|
XK_yacute, XK_dead_acute, XK_y, 0,
|
||||||
|
XK_ydiaeresis, XK_dead_diaeresis, XK_y, 0,
|
||||||
|
|
||||||
|
// Latin-2 (ISO 8859-2)
|
||||||
|
XK_Aogonek, XK_dead_ogonek, XK_A, 0,
|
||||||
|
XK_Lcaron, XK_dead_caron, XK_L, 0,
|
||||||
|
XK_Sacute, XK_dead_acute, XK_S, 0,
|
||||||
|
XK_Scaron, XK_dead_caron, XK_S, 0,
|
||||||
|
XK_Scedilla, XK_dead_cedilla, XK_S, 0,
|
||||||
|
XK_Tcaron, XK_dead_caron, XK_T, 0,
|
||||||
|
XK_Zacute, XK_dead_acute, XK_Z, 0,
|
||||||
|
XK_Zcaron, XK_dead_caron, XK_Z, 0,
|
||||||
|
XK_Zabovedot, XK_dead_abovedot, XK_Z, 0,
|
||||||
|
XK_aogonek, XK_dead_ogonek, XK_a, 0,
|
||||||
|
XK_lcaron, XK_dead_caron, XK_l, 0,
|
||||||
|
XK_sacute, XK_dead_acute, XK_s, 0,
|
||||||
|
XK_scaron, XK_dead_caron, XK_s, 0,
|
||||||
|
XK_scedilla, XK_dead_cedilla, XK_s, 0,
|
||||||
|
XK_tcaron, XK_dead_caron, XK_t, 0,
|
||||||
|
XK_zacute, XK_dead_acute, XK_z, 0,
|
||||||
|
XK_zcaron, XK_dead_caron, XK_z, 0,
|
||||||
|
XK_zabovedot, XK_dead_abovedot, XK_z, 0,
|
||||||
|
XK_Racute, XK_dead_acute, XK_R, 0,
|
||||||
|
XK_Abreve, XK_dead_breve, XK_A, 0,
|
||||||
|
XK_Lacute, XK_dead_acute, XK_L, 0,
|
||||||
|
XK_Cacute, XK_dead_acute, XK_C, 0,
|
||||||
|
XK_Ccaron, XK_dead_caron, XK_C, 0,
|
||||||
|
XK_Eogonek, XK_dead_ogonek, XK_E, 0,
|
||||||
|
XK_Ecaron, XK_dead_caron, XK_E, 0,
|
||||||
|
XK_Dcaron, XK_dead_caron, XK_D, 0,
|
||||||
|
XK_Nacute, XK_dead_acute, XK_N, 0,
|
||||||
|
XK_Ncaron, XK_dead_caron, XK_N, 0,
|
||||||
|
XK_Odoubleacute, XK_dead_doubleacute, XK_O, 0,
|
||||||
|
XK_Rcaron, XK_dead_caron, XK_R, 0,
|
||||||
|
XK_Uring, XK_dead_abovering, XK_U, 0,
|
||||||
|
XK_Udoubleacute, XK_dead_doubleacute, XK_U, 0,
|
||||||
|
XK_Tcedilla, XK_dead_cedilla, XK_T, 0,
|
||||||
|
XK_racute, XK_dead_acute, XK_r, 0,
|
||||||
|
XK_abreve, XK_dead_breve, XK_a, 0,
|
||||||
|
XK_lacute, XK_dead_acute, XK_l, 0,
|
||||||
|
XK_cacute, XK_dead_acute, XK_c, 0,
|
||||||
|
XK_ccaron, XK_dead_caron, XK_c, 0,
|
||||||
|
XK_eogonek, XK_dead_ogonek, XK_e, 0,
|
||||||
|
XK_ecaron, XK_dead_caron, XK_e, 0,
|
||||||
|
XK_dcaron, XK_dead_caron, XK_d, 0,
|
||||||
|
XK_nacute, XK_dead_acute, XK_n, 0,
|
||||||
|
XK_ncaron, XK_dead_caron, XK_n, 0,
|
||||||
|
XK_odoubleacute, XK_dead_doubleacute, XK_o, 0,
|
||||||
|
XK_rcaron, XK_dead_caron, XK_r, 0,
|
||||||
|
XK_uring, XK_dead_abovering, XK_u, 0,
|
||||||
|
XK_udoubleacute, XK_dead_doubleacute, XK_u, 0,
|
||||||
|
XK_tcedilla, XK_dead_cedilla, XK_t, 0,
|
||||||
|
|
||||||
|
// Latin-3 (ISO 8859-3)
|
||||||
|
XK_Hcircumflex, XK_dead_circumflex, XK_H, 0,
|
||||||
|
XK_Iabovedot, XK_dead_abovedot, XK_I, 0,
|
||||||
|
XK_Gbreve, XK_dead_breve, XK_G, 0,
|
||||||
|
XK_Jcircumflex, XK_dead_circumflex, XK_J, 0,
|
||||||
|
XK_hcircumflex, XK_dead_circumflex, XK_h, 0,
|
||||||
|
XK_gbreve, XK_dead_breve, XK_g, 0,
|
||||||
|
XK_jcircumflex, XK_dead_circumflex, XK_j, 0,
|
||||||
|
XK_Cabovedot, XK_dead_abovedot, XK_C, 0,
|
||||||
|
XK_Ccircumflex, XK_dead_circumflex, XK_C, 0,
|
||||||
|
XK_Gabovedot, XK_dead_abovedot, XK_G, 0,
|
||||||
|
XK_Gcircumflex, XK_dead_circumflex, XK_G, 0,
|
||||||
|
XK_Ubreve, XK_dead_breve, XK_U, 0,
|
||||||
|
XK_Scircumflex, XK_dead_circumflex, XK_S, 0,
|
||||||
|
XK_cabovedot, XK_dead_abovedot, XK_c, 0,
|
||||||
|
XK_ccircumflex, XK_dead_circumflex, XK_c, 0,
|
||||||
|
XK_gabovedot, XK_dead_abovedot, XK_g, 0,
|
||||||
|
XK_gcircumflex, XK_dead_circumflex, XK_g, 0,
|
||||||
|
XK_ubreve, XK_dead_breve, XK_u, 0,
|
||||||
|
XK_scircumflex, XK_dead_circumflex, XK_s, 0,
|
||||||
|
|
||||||
|
// Latin-4 (ISO 8859-4)
|
||||||
|
XK_scircumflex, XK_dead_circumflex, XK_s, 0,
|
||||||
|
XK_Rcedilla, XK_dead_cedilla, XK_R, 0,
|
||||||
|
XK_Itilde, XK_dead_tilde, XK_I, 0,
|
||||||
|
XK_Lcedilla, XK_dead_cedilla, XK_L, 0,
|
||||||
|
XK_Emacron, XK_dead_macron, XK_E, 0,
|
||||||
|
XK_Gcedilla, XK_dead_cedilla, XK_G, 0,
|
||||||
|
XK_rcedilla, XK_dead_cedilla, XK_r, 0,
|
||||||
|
XK_itilde, XK_dead_tilde, XK_i, 0,
|
||||||
|
XK_lcedilla, XK_dead_cedilla, XK_l, 0,
|
||||||
|
XK_emacron, XK_dead_macron, XK_e, 0,
|
||||||
|
XK_gcedilla, XK_dead_cedilla, XK_g, 0,
|
||||||
|
XK_Amacron, XK_dead_macron, XK_A, 0,
|
||||||
|
XK_Iogonek, XK_dead_ogonek, XK_I, 0,
|
||||||
|
XK_Eabovedot, XK_dead_abovedot, XK_E, 0,
|
||||||
|
XK_Imacron, XK_dead_macron, XK_I, 0,
|
||||||
|
XK_Ncedilla, XK_dead_cedilla, XK_N, 0,
|
||||||
|
XK_Omacron, XK_dead_macron, XK_O, 0,
|
||||||
|
XK_Kcedilla, XK_dead_cedilla, XK_K, 0,
|
||||||
|
XK_Uogonek, XK_dead_ogonek, XK_U, 0,
|
||||||
|
XK_Utilde, XK_dead_tilde, XK_U, 0,
|
||||||
|
XK_Umacron, XK_dead_macron, XK_U, 0,
|
||||||
|
XK_amacron, XK_dead_macron, XK_a, 0,
|
||||||
|
XK_iogonek, XK_dead_ogonek, XK_i, 0,
|
||||||
|
XK_eabovedot, XK_dead_abovedot, XK_e, 0,
|
||||||
|
XK_imacron, XK_dead_macron, XK_i, 0,
|
||||||
|
XK_ncedilla, XK_dead_cedilla, XK_n, 0,
|
||||||
|
XK_omacron, XK_dead_macron, XK_o, 0,
|
||||||
|
XK_kcedilla, XK_dead_cedilla, XK_k, 0,
|
||||||
|
XK_uogonek, XK_dead_ogonek, XK_u, 0,
|
||||||
|
XK_utilde, XK_dead_tilde, XK_u, 0,
|
||||||
|
XK_umacron, XK_dead_macron, XK_u, 0,
|
||||||
|
|
||||||
|
// Latin-8 (ISO 8859-14)
|
||||||
|
#if defined(XK_Babovedot)
|
||||||
|
XK_Babovedot, XK_dead_abovedot, XK_B, 0,
|
||||||
|
XK_babovedot, XK_dead_abovedot, XK_b, 0,
|
||||||
|
XK_Dabovedot, XK_dead_abovedot, XK_D, 0,
|
||||||
|
XK_Wgrave, XK_dead_grave, XK_W, 0,
|
||||||
|
XK_Wacute, XK_dead_acute, XK_W, 0,
|
||||||
|
XK_dabovedot, XK_dead_abovedot, XK_d, 0,
|
||||||
|
XK_Ygrave, XK_dead_grave, XK_Y, 0,
|
||||||
|
XK_Fabovedot, XK_dead_abovedot, XK_F, 0,
|
||||||
|
XK_fabovedot, XK_dead_abovedot, XK_f, 0,
|
||||||
|
XK_Mabovedot, XK_dead_abovedot, XK_M, 0,
|
||||||
|
XK_mabovedot, XK_dead_abovedot, XK_m, 0,
|
||||||
|
XK_Pabovedot, XK_dead_abovedot, XK_P, 0,
|
||||||
|
XK_wgrave, XK_dead_grave, XK_w, 0,
|
||||||
|
XK_pabovedot, XK_dead_abovedot, XK_p, 0,
|
||||||
|
XK_wacute, XK_dead_acute, XK_w, 0,
|
||||||
|
XK_Sabovedot, XK_dead_abovedot, XK_S, 0,
|
||||||
|
XK_ygrave, XK_dead_grave, XK_y, 0,
|
||||||
|
XK_Wdiaeresis, XK_dead_diaeresis, XK_W, 0,
|
||||||
|
XK_wdiaeresis, XK_dead_diaeresis, XK_w, 0,
|
||||||
|
XK_sabovedot, XK_dead_abovedot, XK_s, 0,
|
||||||
|
XK_Wcircumflex, XK_dead_circumflex, XK_W, 0,
|
||||||
|
XK_Tabovedot, XK_dead_abovedot, XK_T, 0,
|
||||||
|
XK_Ycircumflex, XK_dead_circumflex, XK_Y, 0,
|
||||||
|
XK_wcircumflex, XK_dead_circumflex, XK_w, 0,
|
||||||
|
XK_tabovedot, XK_dead_abovedot, XK_t, 0,
|
||||||
|
XK_ycircumflex, XK_dead_circumflex, XK_y, 0,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Latin-9 (ISO 8859-15)
|
||||||
|
#if defined(XK_Ydiaeresis)
|
||||||
|
XK_Ydiaeresis, XK_dead_diaeresis, XK_Y, 0,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// end of table
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CXWindowsUtil
|
// CXWindowsUtil
|
||||||
|
@ -812,6 +1032,7 @@ struct codepair {
|
||||||
|
|
||||||
CXWindowsUtil::CKeySymMap CXWindowsUtil::s_keySymToUCS4;
|
CXWindowsUtil::CKeySymMap CXWindowsUtil::s_keySymToUCS4;
|
||||||
CXWindowsUtil::CUCS4Map CXWindowsUtil::s_UCS4ToKeySym;
|
CXWindowsUtil::CUCS4Map CXWindowsUtil::s_UCS4ToKeySym;
|
||||||
|
CXWindowsUtil::CKeySymsMap CXWindowsUtil::s_decomposedKeySyms;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CXWindowsUtil::getWindowProperty(Display* display, Window window,
|
CXWindowsUtil::getWindowProperty(Display* display, Window window,
|
||||||
|
@ -1008,6 +1229,21 @@ CXWindowsUtil::mapUCS4ToKeySym(UInt32 c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CXWindowsUtil::decomposeKeySym(KeySym keysym, KeySyms& decomposed)
|
||||||
|
{
|
||||||
|
// unfortunately, X11 doesn't appear to have any way of
|
||||||
|
// decomposing a keysym into its component keysyms. we'll
|
||||||
|
// use a lookup table for certain character sets.
|
||||||
|
initKeyMaps();
|
||||||
|
CKeySymsMap::const_iterator i = s_decomposedKeySyms.find(keysym);
|
||||||
|
if (i == s_decomposedKeySyms.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
decomposed = i->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
CXWindowsUtil::propertyNotifyPredicate(Display*, XEvent* xevent, XPointer arg)
|
CXWindowsUtil::propertyNotifyPredicate(Display*, XEvent* xevent, XPointer arg)
|
||||||
{
|
{
|
||||||
|
@ -1031,6 +1267,19 @@ CXWindowsUtil::initKeyMaps()
|
||||||
s_UCS4ToKeySym[s_keymap[i].ucs4] = s_keymap[i].keysym;
|
s_UCS4ToKeySym[s_keymap[i].ucs4] = s_keymap[i].keysym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill decomposed key table if not filled yet
|
||||||
|
if (s_decomposedKeySyms.empty()) {
|
||||||
|
for (const KeySym* scan = s_rawDecomposeTable; *scan != 0; ++scan) {
|
||||||
|
// add an entry for this keysym
|
||||||
|
KeySyms& entry = s_decomposedKeySyms[*scan];
|
||||||
|
|
||||||
|
// add the decomposed keysyms for the keysym
|
||||||
|
while (*++scan != 0) {
|
||||||
|
entry.push_back(*scan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
#include "BasicTypes.h"
|
#include "BasicTypes.h"
|
||||||
#include "stdmap.h"
|
#include "stdmap.h"
|
||||||
|
#include "stdvector.h"
|
||||||
#if defined(X_DISPLAY_MISSING)
|
#if defined(X_DISPLAY_MISSING)
|
||||||
# error X11 is required to build synergy
|
# error X11 is required to build synergy
|
||||||
#else
|
#else
|
||||||
|
@ -27,6 +28,8 @@
|
||||||
//! X11 utility functions
|
//! X11 utility functions
|
||||||
class CXWindowsUtil {
|
class CXWindowsUtil {
|
||||||
public:
|
public:
|
||||||
|
typedef std::vector<KeySym> KeySyms;
|
||||||
|
|
||||||
//! Get property
|
//! Get property
|
||||||
/*!
|
/*!
|
||||||
Gets property \c property on \c window. \b Appends the data to
|
Gets property \c property on \c window. \b Appends the data to
|
||||||
|
@ -70,6 +73,14 @@ public:
|
||||||
*/
|
*/
|
||||||
static KeySym mapUCS4ToKeySym(UInt32);
|
static KeySym mapUCS4ToKeySym(UInt32);
|
||||||
|
|
||||||
|
//! Decompose a KeySym
|
||||||
|
/*!
|
||||||
|
Decomposes \c keysym into its component keysyms. All but the last
|
||||||
|
decomposed KeySym are dead keys. Returns true iff the decomposition
|
||||||
|
was successful.
|
||||||
|
*/
|
||||||
|
static bool decomposeKeySym(KeySym keysym, KeySyms& decomposed);
|
||||||
|
|
||||||
//! X11 error handler
|
//! X11 error handler
|
||||||
/*!
|
/*!
|
||||||
This class sets an X error handler in the c'tor and restores the
|
This class sets an X error handler in the c'tor and restores the
|
||||||
|
@ -133,9 +144,11 @@ private:
|
||||||
private:
|
private:
|
||||||
typedef std::map<KeySym, UInt32> CKeySymMap;
|
typedef std::map<KeySym, UInt32> CKeySymMap;
|
||||||
typedef std::map<UInt32, KeySym> CUCS4Map;
|
typedef std::map<UInt32, KeySym> CUCS4Map;
|
||||||
|
typedef std::map<KeySym, KeySyms> CKeySymsMap;
|
||||||
|
|
||||||
static CKeySymMap s_keySymToUCS4;
|
static CKeySymMap s_keySymToUCS4;
|
||||||
static CUCS4Map s_UCS4ToKeySym;
|
static CUCS4Map s_UCS4ToKeySym;
|
||||||
|
static CKeySymsMap s_decomposedKeySyms;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMSWINDOWSSCREENEVENTHANDLER_H
|
|
||||||
#define IMSWINDOWSSCREENEVENTHANDLER_H
|
|
||||||
|
|
||||||
#include "IScreenEventHandler.h"
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
//! MS Windows screen event handler interface
|
|
||||||
class IMSWindowsScreenEventHandler : public IScreenEventHandler {
|
|
||||||
public:
|
|
||||||
//! @name manipulators
|
|
||||||
//@{
|
|
||||||
|
|
||||||
//! Notify of window creation
|
|
||||||
/*!
|
|
||||||
This is called after the window is created.
|
|
||||||
*/
|
|
||||||
virtual void postCreateWindow(HWND) = 0;
|
|
||||||
|
|
||||||
//! Notify of window destruction
|
|
||||||
/*!
|
|
||||||
This is called before the window is destroyed.
|
|
||||||
*/
|
|
||||||
virtual void preDestroyWindow(HWND) = 0;
|
|
||||||
|
|
||||||
//! Notify of newly accessible desktop
|
|
||||||
/*!
|
|
||||||
This is called when the user switched from an inaccessible desktop
|
|
||||||
to an accessible desktop.
|
|
||||||
*/
|
|
||||||
virtual void onAccessibleDesktop() = 0;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
|
|
||||||
// IScreenEventHandler overrides
|
|
||||||
virtual void onScreensaver(bool activated) = 0;
|
|
||||||
virtual bool onPreDispatch(const CEvent* event) = 0;
|
|
||||||
virtual bool onEvent(CEvent* event) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -23,21 +23,20 @@ EXTRA_DIST = \
|
||||||
CMSWindowsClipboardAnyTextConverter.cpp \
|
CMSWindowsClipboardAnyTextConverter.cpp \
|
||||||
CMSWindowsClipboardTextConverter.cpp \
|
CMSWindowsClipboardTextConverter.cpp \
|
||||||
CMSWindowsClipboardUTF16Converter.cpp \
|
CMSWindowsClipboardUTF16Converter.cpp \
|
||||||
CMSWindowsPrimaryScreen.cpp \
|
CMSWindowsDesktop.cpp \
|
||||||
|
CMSWindowsKeyMapper.cpp \
|
||||||
CMSWindowsScreen.cpp \
|
CMSWindowsScreen.cpp \
|
||||||
CMSWindowsScreenSaver.cpp \
|
CMSWindowsScreenSaver.cpp \
|
||||||
CMSWindowsSecondaryScreen.cpp \
|
|
||||||
CSynergyHook.cpp \
|
CSynergyHook.cpp \
|
||||||
CMSWindowsClipboard.h \
|
CMSWindowsClipboard.h \
|
||||||
CMSWindowsClipboardAnyTextConverter.h \
|
CMSWindowsClipboardAnyTextConverter.h \
|
||||||
CMSWindowsClipboardTextConverter.h \
|
CMSWindowsClipboardTextConverter.h \
|
||||||
CMSWindowsClipboardUTF16Converter.h \
|
CMSWindowsClipboardUTF16Converter.h \
|
||||||
CMSWindowsPrimaryScreen.h \
|
CMSWindowsDesktop.h \
|
||||||
|
CMSWindowsKeyMapper.h \
|
||||||
CMSWindowsScreen.h \
|
CMSWindowsScreen.h \
|
||||||
CMSWindowsScreenSaver.h \
|
CMSWindowsScreenSaver.h \
|
||||||
CMSWindowsSecondaryScreen.h \
|
|
||||||
CSynergyHook.h \
|
CSynergyHook.h \
|
||||||
IMSWindowsScreenEventHandler.h \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
|
@ -50,19 +49,17 @@ libplatform_a_SOURCES = \
|
||||||
CXWindowsClipboardTextConverter.cpp \
|
CXWindowsClipboardTextConverter.cpp \
|
||||||
CXWindowsClipboardUCS2Converter.cpp \
|
CXWindowsClipboardUCS2Converter.cpp \
|
||||||
CXWindowsClipboardUTF8Converter.cpp \
|
CXWindowsClipboardUTF8Converter.cpp \
|
||||||
CXWindowsPrimaryScreen.cpp \
|
CXWindowsKeyMapper.cpp \
|
||||||
CXWindowsScreen.cpp \
|
CXWindowsScreen.cpp \
|
||||||
CXWindowsScreenSaver.cpp \
|
CXWindowsScreenSaver.cpp \
|
||||||
CXWindowsSecondaryScreen.cpp \
|
|
||||||
CXWindowsUtil.cpp \
|
CXWindowsUtil.cpp \
|
||||||
CXWindowsClipboard.h \
|
CXWindowsClipboard.h \
|
||||||
CXWindowsClipboardTextConverter.h \
|
CXWindowsClipboardTextConverter.h \
|
||||||
CXWindowsClipboardUCS2Converter.h \
|
CXWindowsClipboardUCS2Converter.h \
|
||||||
CXWindowsClipboardUTF8Converter.h \
|
CXWindowsClipboardUTF8Converter.h \
|
||||||
CXWindowsPrimaryScreen.h \
|
CXWindowsKeyMapper.h \
|
||||||
CXWindowsScreen.h \
|
CXWindowsScreen.h \
|
||||||
CXWindowsScreenSaver.h \
|
CXWindowsScreenSaver.h \
|
||||||
CXWindowsSecondaryScreen.h \
|
|
||||||
CXWindowsUtil.h \
|
CXWindowsUtil.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
INCLUDES = \
|
INCLUDES = \
|
||||||
|
|
|
@ -103,7 +103,11 @@ SOURCE=.\CMSWindowsClipboardUTF16Converter.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CMSWindowsPrimaryScreen.cpp
|
SOURCE=.\CMSWindowsDesktop.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\CMSWindowsKeyMapper.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
@ -113,10 +117,6 @@ SOURCE=.\CMSWindowsScreen.cpp
|
||||||
|
|
||||||
SOURCE=.\CMSWindowsScreenSaver.cpp
|
SOURCE=.\CMSWindowsScreenSaver.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\CMSWindowsSecondaryScreen.cpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "Header Files"
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
@ -139,7 +139,11 @@ SOURCE=.\CMSWindowsClipboardUTF16Converter.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CMSWindowsPrimaryScreen.h
|
SOURCE=.\CMSWindowsDesktop.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\CMSWindowsKeyMapper.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
@ -149,14 +153,6 @@ SOURCE=.\CMSWindowsScreen.h
|
||||||
|
|
||||||
SOURCE=.\CMSWindowsScreenSaver.h
|
SOURCE=.\CMSWindowsScreenSaver.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\CMSWindowsSecondaryScreen.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\IMSWindowsScreenEventHandler.h
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
# End Group
|
||||||
# End Target
|
# End Target
|
||||||
# End Project
|
# End Project
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CPrimaryClient.h"
|
#include "CPrimaryClient.h"
|
||||||
#include "IPrimaryScreenFactory.h"
|
#include "CScreen.h"
|
||||||
|
#include "IScreenFactory.h"
|
||||||
#include "IServer.h"
|
#include "IServer.h"
|
||||||
#include "XScreen.h"
|
#include "XScreen.h"
|
||||||
#include "XSynergy.h"
|
#include "XSynergy.h"
|
||||||
#include "CPrimaryScreen.h"
|
|
||||||
#include "CClipboard.h"
|
#include "CClipboard.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
// CPrimaryClient
|
// CPrimaryClient
|
||||||
//
|
//
|
||||||
|
|
||||||
CPrimaryClient::CPrimaryClient(IPrimaryScreenFactory* screenFactory,
|
CPrimaryClient::CPrimaryClient(IScreenFactory* screenFactory,
|
||||||
IServer* server,
|
IServer* server,
|
||||||
IPrimaryScreenReceiver* receiver,
|
IPrimaryScreenReceiver* receiver,
|
||||||
const CString& name) :
|
const CString& name) :
|
||||||
|
@ -38,7 +38,11 @@ CPrimaryClient::CPrimaryClient(IPrimaryScreenFactory* screenFactory,
|
||||||
// create screen
|
// create screen
|
||||||
LOG((CLOG_DEBUG1 "creating primary screen"));
|
LOG((CLOG_DEBUG1 "creating primary screen"));
|
||||||
if (screenFactory != NULL) {
|
if (screenFactory != NULL) {
|
||||||
m_screen = screenFactory->create(this, receiver);
|
IPlatformScreen* platformScreen =
|
||||||
|
screenFactory->create(this, receiver);
|
||||||
|
if (platformScreen != NULL) {
|
||||||
|
m_screen = new CScreen(platformScreen, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m_screen == NULL) {
|
if (m_screen == NULL) {
|
||||||
throw XScreenOpenFailure();
|
throw XScreenOpenFailure();
|
||||||
|
@ -86,7 +90,7 @@ CPrimaryClient::isLockedToScreen() const
|
||||||
KeyModifierMask
|
KeyModifierMask
|
||||||
CPrimaryClient::getToggleMask() const
|
CPrimaryClient::getToggleMask() const
|
||||||
{
|
{
|
||||||
return m_screen->getToggleMask();
|
return m_screen->getActiveModifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -149,13 +153,28 @@ CPrimaryClient::close()
|
||||||
m_screen->close();
|
m_screen->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPrimaryClient::enable()
|
||||||
|
{
|
||||||
|
m_screen->enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPrimaryClient::disable()
|
||||||
|
{
|
||||||
|
m_screen->disable();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CPrimaryClient::enter(SInt32 xAbs, SInt32 yAbs,
|
CPrimaryClient::enter(SInt32 xAbs, SInt32 yAbs,
|
||||||
UInt32 seqNum, KeyModifierMask, bool screensaver)
|
UInt32 seqNum, KeyModifierMask, bool screensaver)
|
||||||
{
|
{
|
||||||
// note -- we must not call any server methods except onError().
|
// note -- we must not call any server methods except onError().
|
||||||
m_seqNum = seqNum;
|
m_seqNum = seqNum;
|
||||||
m_screen->enter(xAbs, yAbs, screensaver);
|
if (!screensaver) {
|
||||||
|
m_screen->warpCursor(xAbs, yAbs);
|
||||||
|
}
|
||||||
|
m_screen->enter();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
#include "IScreenReceiver.h"
|
#include "IScreenReceiver.h"
|
||||||
#include "ProtocolTypes.h"
|
#include "ProtocolTypes.h"
|
||||||
|
|
||||||
|
class CScreen;
|
||||||
class IClipboard;
|
class IClipboard;
|
||||||
class CPrimaryScreen;
|
class IScreenFactory;
|
||||||
class IPrimaryScreenFactory;
|
|
||||||
class IPrimaryScreenReceiver;
|
class IPrimaryScreenReceiver;
|
||||||
class IServer;
|
class IServer;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public:
|
||||||
\c factory. Throws XScreenOpenFailure or whatever the factory can
|
\c factory. Throws XScreenOpenFailure or whatever the factory can
|
||||||
throw if the screen cannot be created.
|
throw if the screen cannot be created.
|
||||||
*/
|
*/
|
||||||
CPrimaryClient(IPrimaryScreenFactory* factory, IServer*,
|
CPrimaryClient(IScreenFactory* factory, IServer*,
|
||||||
IPrimaryScreenReceiver*, const CString& name);
|
IPrimaryScreenReceiver*, const CString& name);
|
||||||
~CPrimaryClient();
|
~CPrimaryClient();
|
||||||
|
|
||||||
|
@ -96,6 +96,9 @@ public:
|
||||||
virtual bool onGrabClipboard(ClipboardID);
|
virtual bool onGrabClipboard(ClipboardID);
|
||||||
virtual void onClipboardChanged(ClipboardID, const CString&);
|
virtual void onClipboardChanged(ClipboardID, const CString&);
|
||||||
|
|
||||||
|
// XXX -- these go in IClient
|
||||||
|
virtual void enable();
|
||||||
|
virtual void disable();
|
||||||
// IClient overrides
|
// IClient overrides
|
||||||
virtual void open();
|
virtual void open();
|
||||||
virtual void mainLoop();
|
virtual void mainLoop();
|
||||||
|
@ -127,7 +130,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IServer* m_server;
|
IServer* m_server;
|
||||||
CPrimaryScreen* m_screen;
|
CScreen* m_screen;
|
||||||
CString m_name;
|
CString m_name;
|
||||||
UInt32 m_seqNum;
|
UInt32 m_seqNum;
|
||||||
CClientInfo m_info;
|
CClientInfo m_info;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "CServer.h"
|
#include "CServer.h"
|
||||||
#include "CHTTPServer.h"
|
#include "CHTTPServer.h"
|
||||||
#include "CPrimaryClient.h"
|
#include "CPrimaryClient.h"
|
||||||
#include "IPrimaryScreenFactory.h"
|
#include "IScreenFactory.h"
|
||||||
#include "CInputPacketStream.h"
|
#include "CInputPacketStream.h"
|
||||||
#include "COutputPacketStream.h"
|
#include "COutputPacketStream.h"
|
||||||
#include "CProtocolUtil.h"
|
#include "CProtocolUtil.h"
|
||||||
|
@ -89,6 +89,7 @@ CServer::open()
|
||||||
LOG((CLOG_INFO "opening screen"));
|
LOG((CLOG_INFO "opening screen"));
|
||||||
openPrimaryScreen();
|
openPrimaryScreen();
|
||||||
setStatus(kNotRunning);
|
setStatus(kNotRunning);
|
||||||
|
m_primaryClient->enable();
|
||||||
}
|
}
|
||||||
catch (XScreen& e) {
|
catch (XScreen& e) {
|
||||||
// can't open screen
|
// can't open screen
|
||||||
|
@ -212,6 +213,7 @@ void
|
||||||
CServer::close()
|
CServer::close()
|
||||||
{
|
{
|
||||||
if (m_primaryClient != NULL) {
|
if (m_primaryClient != NULL) {
|
||||||
|
m_primaryClient->disable();
|
||||||
closePrimaryScreen();
|
closePrimaryScreen();
|
||||||
}
|
}
|
||||||
LOG((CLOG_INFO "closed screen"));
|
LOG((CLOG_INFO "closed screen"));
|
||||||
|
@ -280,7 +282,7 @@ CServer::setConfig(const CConfig& config)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServer::setScreenFactory(IPrimaryScreenFactory* adopted)
|
CServer::setScreenFactory(IScreenFactory* adopted)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
delete m_screenFactory;
|
delete m_screenFactory;
|
||||||
|
@ -1601,7 +1603,7 @@ CServer::runClient(void* vsocket)
|
||||||
try {
|
try {
|
||||||
CProtocolUtil::writef(proxy->getOutputStream(), kMsgEBusy);
|
CProtocolUtil::writef(proxy->getOutputStream(), kMsgEBusy);
|
||||||
}
|
}
|
||||||
catch (XSocket&) {
|
catch (XIO&) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
delete proxy;
|
delete proxy;
|
||||||
|
@ -1614,7 +1616,7 @@ CServer::runClient(void* vsocket)
|
||||||
try {
|
try {
|
||||||
CProtocolUtil::writef(proxy->getOutputStream(), kMsgEUnknown);
|
CProtocolUtil::writef(proxy->getOutputStream(), kMsgEUnknown);
|
||||||
}
|
}
|
||||||
catch (XSocket&) {
|
catch (XIO&) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
delete proxy;
|
delete proxy;
|
||||||
|
@ -1646,7 +1648,7 @@ CServer::runClient(void* vsocket)
|
||||||
try {
|
try {
|
||||||
CProtocolUtil::writef(proxy->getOutputStream(), kMsgEBad);
|
CProtocolUtil::writef(proxy->getOutputStream(), kMsgEBad);
|
||||||
}
|
}
|
||||||
catch (XSocket&) {
|
catch (XIO&) {
|
||||||
// ignore. client probably aborted the connection.
|
// ignore. client probably aborted the connection.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1766,7 +1768,7 @@ CServer::handshakeClient(IDataSocket* socket)
|
||||||
CProtocolUtil::writef(output, kMsgEIncompatible,
|
CProtocolUtil::writef(output, kMsgEIncompatible,
|
||||||
kProtocolMajorVersion, kProtocolMinorVersion);
|
kProtocolMajorVersion, kProtocolMinorVersion);
|
||||||
}
|
}
|
||||||
catch (XSocket&) {
|
catch (XIO&) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1776,7 +1778,7 @@ CServer::handshakeClient(IDataSocket* socket)
|
||||||
try {
|
try {
|
||||||
CProtocolUtil::writef(output, kMsgEBad);
|
CProtocolUtil::writef(output, kMsgEBad);
|
||||||
}
|
}
|
||||||
catch (XSocket&) {
|
catch (XIO&) {
|
||||||
// ignore. client probably aborted the connection.
|
// ignore. client probably aborted the connection.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ class CHTTPServer;
|
||||||
class CPrimaryClient;
|
class CPrimaryClient;
|
||||||
class IClient;
|
class IClient;
|
||||||
class IDataSocket;
|
class IDataSocket;
|
||||||
class IPrimaryScreenFactory;
|
class IScreenFactory;
|
||||||
class IServerProtocol;
|
class IServerProtocol;
|
||||||
class ISocketFactory;
|
class ISocketFactory;
|
||||||
class IStreamFilterFactory;
|
class IStreamFilterFactory;
|
||||||
|
@ -102,13 +102,12 @@ public:
|
||||||
*/
|
*/
|
||||||
bool setConfig(const CConfig&);
|
bool setConfig(const CConfig&);
|
||||||
|
|
||||||
//! Set primary screen factory
|
//! Set screen factory
|
||||||
/*!
|
/*!
|
||||||
Sets the factory for creating primary screens. This must be
|
Sets the factory for creating screens. This must be set before
|
||||||
set before calling open(). This object takes ownership of the
|
calling open(). This object takes ownership of the factory.
|
||||||
factory.
|
|
||||||
*/
|
*/
|
||||||
void setScreenFactory(IPrimaryScreenFactory*);
|
void setScreenFactory(IScreenFactory*);
|
||||||
|
|
||||||
//! Set socket factory
|
//! Set socket factory
|
||||||
/*!
|
/*!
|
||||||
|
@ -341,7 +340,7 @@ private:
|
||||||
double m_bindTimeout;
|
double m_bindTimeout;
|
||||||
|
|
||||||
// factories
|
// factories
|
||||||
IPrimaryScreenFactory* m_screenFactory;
|
IScreenFactory* m_screenFactory;
|
||||||
ISocketFactory* m_socketFactory;
|
ISocketFactory* m_socketFactory;
|
||||||
IStreamFilterFactory* m_streamFilterFactory;
|
IStreamFilterFactory* m_streamFilterFactory;
|
||||||
|
|
||||||
|
|
|
@ -1,281 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "CPrimaryScreen.h"
|
|
||||||
#include "IScreen.h"
|
|
||||||
#include "IScreenReceiver.h"
|
|
||||||
#include "ProtocolTypes.h"
|
|
||||||
#include "CLock.h"
|
|
||||||
#include "CThread.h"
|
|
||||||
#include "CLog.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// CPrimaryScreen
|
|
||||||
//
|
|
||||||
|
|
||||||
CPrimaryScreen::CPrimaryScreen(IScreenReceiver* receiver) :
|
|
||||||
m_receiver(receiver),
|
|
||||||
m_active(false)
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
CPrimaryScreen::~CPrimaryScreen()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::mainLoop()
|
|
||||||
{
|
|
||||||
// change our priority
|
|
||||||
CThread::getCurrentThread().setPriority(-14);
|
|
||||||
|
|
||||||
// run event loop
|
|
||||||
try {
|
|
||||||
LOG((CLOG_DEBUG "entering event loop"));
|
|
||||||
onPreMainLoop();
|
|
||||||
getScreen()->mainLoop();
|
|
||||||
onPostMainLoop();
|
|
||||||
LOG((CLOG_DEBUG "exiting event loop"));
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
onPostMainLoop();
|
|
||||||
LOG((CLOG_DEBUG "exiting event loop"));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::exitMainLoop()
|
|
||||||
{
|
|
||||||
getScreen()->exitMainLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::open()
|
|
||||||
{
|
|
||||||
CClientInfo info;
|
|
||||||
try {
|
|
||||||
// subclass hook
|
|
||||||
onPreOpen();
|
|
||||||
|
|
||||||
// open the screen
|
|
||||||
getScreen()->open();
|
|
||||||
|
|
||||||
// create and prepare our window
|
|
||||||
createWindow();
|
|
||||||
|
|
||||||
// collect screen info
|
|
||||||
getScreen()->getShape(info.m_x, info.m_y, info.m_w, info.m_h);
|
|
||||||
getScreen()->getCursorPos(info.m_mx, info.m_my);
|
|
||||||
info.m_zoneSize = getJumpZoneSize();
|
|
||||||
|
|
||||||
// update keyboard state
|
|
||||||
updateKeys();
|
|
||||||
|
|
||||||
// get notified of screen saver activation/deactivation
|
|
||||||
getScreen()->openScreensaver(true);
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPostOpen();
|
|
||||||
|
|
||||||
// reset options
|
|
||||||
resetOptions();
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
close();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// enter the screen
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
enterNoWarp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// send screen info
|
|
||||||
m_receiver->onInfoChanged(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::close()
|
|
||||||
{
|
|
||||||
onPreClose();
|
|
||||||
getScreen()->closeScreensaver();
|
|
||||||
destroyWindow();
|
|
||||||
getScreen()->close();
|
|
||||||
onPostClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreensaver)
|
|
||||||
{
|
|
||||||
LOG((CLOG_INFO "entering primary at %d,%d%s", x, y, forScreensaver ? " for screen saver" : ""));
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
assert(m_active == true);
|
|
||||||
|
|
||||||
if (!forScreensaver) {
|
|
||||||
warpCursor(x, y);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
onEnterScreensaver();
|
|
||||||
}
|
|
||||||
enterNoWarp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::enterNoWarp()
|
|
||||||
{
|
|
||||||
// note -- must be locked on entry
|
|
||||||
|
|
||||||
// not active anymore
|
|
||||||
m_active = false;
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPreEnter();
|
|
||||||
|
|
||||||
// restore active window and hide our window
|
|
||||||
hideWindow();
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPostEnter();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPrimaryScreen::leave()
|
|
||||||
{
|
|
||||||
LOG((CLOG_INFO "leaving primary"));
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
assert(m_active == false);
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPreLeave();
|
|
||||||
|
|
||||||
// show our window
|
|
||||||
if (!showWindow()) {
|
|
||||||
onPostLeave(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get keyboard state as we leave
|
|
||||||
updateKeys();
|
|
||||||
|
|
||||||
// warp mouse to center
|
|
||||||
warpCursorToCenter();
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPostLeave(true);
|
|
||||||
|
|
||||||
// local client now active
|
|
||||||
m_active = true;
|
|
||||||
|
|
||||||
// make sure our idea of clipboard ownership is correct
|
|
||||||
getScreen()->checkClipboards();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::setClipboard(ClipboardID id,
|
|
||||||
const IClipboard* clipboard)
|
|
||||||
{
|
|
||||||
getScreen()->setClipboard(id, clipboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::grabClipboard(ClipboardID id)
|
|
||||||
{
|
|
||||||
getScreen()->setClipboard(id, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPrimaryScreen::isActive() const
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
return m_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::getClipboard(ClipboardID id,
|
|
||||||
IClipboard* clipboard) const
|
|
||||||
{
|
|
||||||
getScreen()->getClipboard(id, clipboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPreMainLoop()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPostMainLoop()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPreOpen()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPostOpen()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPreClose()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPostClose()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPreEnter()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPostEnter()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onEnterScreensaver()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPreLeave()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPrimaryScreen::onPostLeave(bool)
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
|
@ -1,349 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPRIMARYSCREEN_H
|
|
||||||
#define CPRIMARYSCREEN_H
|
|
||||||
|
|
||||||
#include "ClipboardTypes.h"
|
|
||||||
#include "KeyTypes.h"
|
|
||||||
#include "OptionTypes.h"
|
|
||||||
#include "CMutex.h"
|
|
||||||
|
|
||||||
class IClipboard;
|
|
||||||
class IScreen;
|
|
||||||
class IScreenReceiver;
|
|
||||||
|
|
||||||
//! Generic server-side screen
|
|
||||||
/*!
|
|
||||||
This is a platform independent base class for primary screen
|
|
||||||
implementations. A primary screen is a server-side screen.
|
|
||||||
Each platform will derive a class from CPrimaryScreen to handle
|
|
||||||
platform dependent operations.
|
|
||||||
*/
|
|
||||||
class CPrimaryScreen {
|
|
||||||
public:
|
|
||||||
CPrimaryScreen(IScreenReceiver*);
|
|
||||||
virtual ~CPrimaryScreen();
|
|
||||||
|
|
||||||
//! @name manipulators
|
|
||||||
//@{
|
|
||||||
|
|
||||||
//! Open screen
|
|
||||||
/*!
|
|
||||||
Opens the screen. This includes initializing the screen, opening
|
|
||||||
the screen saver, synchronizing keyboard state, and causing events
|
|
||||||
to be reported to an IPrimaryScreenReceiver (set through another
|
|
||||||
interface). Calls close() before returning (rethrowing) if it
|
|
||||||
fails for any reason.
|
|
||||||
*/
|
|
||||||
void open();
|
|
||||||
|
|
||||||
//! Run event loop
|
|
||||||
/*!
|
|
||||||
Run the screen's event loop. This returns when it detects
|
|
||||||
the application should terminate or when exitMainLoop() is called.
|
|
||||||
mainLoop() may only be called between open() and close().
|
|
||||||
*/
|
|
||||||
void mainLoop();
|
|
||||||
|
|
||||||
//! Exit event loop
|
|
||||||
/*!
|
|
||||||
Force mainLoop() to return. This call can return before
|
|
||||||
mainLoop() does (i.e. asynchronously).
|
|
||||||
*/
|
|
||||||
void exitMainLoop();
|
|
||||||
|
|
||||||
//! Close screen
|
|
||||||
/*!
|
|
||||||
Closes the screen. This close the screen saver and the screen.
|
|
||||||
*/
|
|
||||||
void close();
|
|
||||||
|
|
||||||
//! Enter screen
|
|
||||||
/*!
|
|
||||||
Called when the user navigates to the primary screen. Warps
|
|
||||||
the cursor to the absolute coordinates \c x,y and unhides
|
|
||||||
it. If \c forScreensaver is true then we're entering because
|
|
||||||
the screen saver started and the cursor is not warped.
|
|
||||||
*/
|
|
||||||
void enter(SInt32 x, SInt32 y, bool forScreensaver);
|
|
||||||
|
|
||||||
//! Leave screen
|
|
||||||
/*!
|
|
||||||
Called when the user navigates off the primary screen. Returns
|
|
||||||
true iff successful.
|
|
||||||
*/
|
|
||||||
bool leave();
|
|
||||||
|
|
||||||
//! Update configuration
|
|
||||||
/*!
|
|
||||||
This is called when the configuration has changed. \c activeSides
|
|
||||||
is a bitmask of EDirectionMask indicating which sides of the
|
|
||||||
primary screen are linked to clients. Override to handle the
|
|
||||||
possible change in jump zones.
|
|
||||||
*/
|
|
||||||
virtual void reconfigure(UInt32 activeSides) = 0;
|
|
||||||
|
|
||||||
//! Warp cursor
|
|
||||||
/*!
|
|
||||||
Warp the cursor to the absolute coordinates \c x,y. Also
|
|
||||||
discard input events up to and including the warp before
|
|
||||||
returning.
|
|
||||||
*/
|
|
||||||
virtual void warpCursor(SInt32 x, SInt32 y) = 0;
|
|
||||||
|
|
||||||
//! Set clipboard
|
|
||||||
/*!
|
|
||||||
Sets the system's clipboard contents. This is usually called
|
|
||||||
soon after an enter().
|
|
||||||
*/
|
|
||||||
void setClipboard(ClipboardID, const IClipboard*);
|
|
||||||
|
|
||||||
//! Grab clipboard
|
|
||||||
/*!
|
|
||||||
Grabs (i.e. take ownership of) the system clipboard.
|
|
||||||
*/
|
|
||||||
void grabClipboard(ClipboardID);
|
|
||||||
|
|
||||||
//! Notify of options changes
|
|
||||||
/*!
|
|
||||||
Reset all options to their default values.
|
|
||||||
*/
|
|
||||||
virtual void resetOptions() = 0;
|
|
||||||
|
|
||||||
//! Notify of options changes
|
|
||||||
/*!
|
|
||||||
Set options to given values. Ignore unknown options and don't
|
|
||||||
modify our options that aren't given in \c options.
|
|
||||||
*/
|
|
||||||
virtual void setOptions(const COptionsList& options) = 0;
|
|
||||||
|
|
||||||
//! Install a one-shot timer
|
|
||||||
/*!
|
|
||||||
Installs a one-shot timer for \c timeout seconds and returns the
|
|
||||||
id of the timer.
|
|
||||||
*/
|
|
||||||
virtual UInt32 addOneShotTimer(double timeout) = 0;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
//! @name accessors
|
|
||||||
//@{
|
|
||||||
|
|
||||||
//! Test if active
|
|
||||||
/*!
|
|
||||||
Returns true iff the screen is active (i.e. the user has left
|
|
||||||
the screen). Note this is the reverse of a secdonary screen.
|
|
||||||
*/
|
|
||||||
bool isActive() const;
|
|
||||||
|
|
||||||
//! Get clipboard
|
|
||||||
/*!
|
|
||||||
Saves the contents of the system clipboard indicated by \c id.
|
|
||||||
*/
|
|
||||||
void getClipboard(ClipboardID, IClipboard*) const;
|
|
||||||
|
|
||||||
//! Get jump zone size
|
|
||||||
/*!
|
|
||||||
Return the jump zone size, the size of the regions on the edges of
|
|
||||||
the screen that cause the cursor to jump to another screen.
|
|
||||||
*/
|
|
||||||
virtual SInt32 getJumpZoneSize() const = 0;
|
|
||||||
|
|
||||||
//! Get toggle key state
|
|
||||||
/*!
|
|
||||||
Return the primary screen's current toggle modifier key state.
|
|
||||||
The returned mask should have the corresponding bit set for
|
|
||||||
each toggle key that is active. For example, if caps lock is
|
|
||||||
on then the returned mask should have \c KeyModifierCapsLock set.
|
|
||||||
*/
|
|
||||||
virtual KeyModifierMask getToggleMask() const = 0;
|
|
||||||
|
|
||||||
//! Get screen lock state
|
|
||||||
/*!
|
|
||||||
Return true if any key or button is being pressed or if there's
|
|
||||||
any other reason that the user should not be allowed to switch
|
|
||||||
screens. Active toggle keys (including the scroll lock key)
|
|
||||||
should not be counted as reasons to lock to the screen.
|
|
||||||
If this method returns true it should log a message on why at
|
|
||||||
the CLOG_DEBUG level.
|
|
||||||
*/
|
|
||||||
virtual bool isLockedToScreen() const = 0;
|
|
||||||
|
|
||||||
//! Get screen
|
|
||||||
/*!
|
|
||||||
Return the platform dependent screen.
|
|
||||||
*/
|
|
||||||
virtual IScreen* getScreen() const = 0;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! Pre-mainLoop() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to mainLoop(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreMainLoop();
|
|
||||||
|
|
||||||
//! Post-mainLoop() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from mainLoop(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostMainLoop();
|
|
||||||
|
|
||||||
//! Pre-open() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to open(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreOpen();
|
|
||||||
|
|
||||||
//! Post-open() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from open() iff the open was successful. Default
|
|
||||||
does nothing. May throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostOpen();
|
|
||||||
|
|
||||||
//! Pre-close() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to close(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreClose();
|
|
||||||
|
|
||||||
//! Post-close() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from close(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostClose();
|
|
||||||
|
|
||||||
//! Pre-enter() hook
|
|
||||||
/*!
|
|
||||||
Called from enter() after the cursor has been warped or, if
|
|
||||||
\c forScreensaver is true, onEnterScreensaver() was called. Override
|
|
||||||
to perform platform specific operations. Default does nothing. May
|
|
||||||
\b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreEnter();
|
|
||||||
|
|
||||||
//! Post-enter() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from enter(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostEnter();
|
|
||||||
|
|
||||||
//! Pre-enter() for screen saver hook
|
|
||||||
/*!
|
|
||||||
Called on entry to enter() if the \c forScreensaver passed to it was
|
|
||||||
true. Override to perform platform specific operations. Default
|
|
||||||
does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onEnterScreensaver();
|
|
||||||
|
|
||||||
//! Pre-leave() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to leave() after desktop synchronization. Override
|
|
||||||
to perform platform specific operations. Default does nothing. May
|
|
||||||
\b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreLeave();
|
|
||||||
|
|
||||||
//! Post-leave() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from leave(). \c success is the value returned by
|
|
||||||
showWindow(). Override to perform platform specific operations.
|
|
||||||
Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostLeave(bool success);
|
|
||||||
|
|
||||||
//! Create window
|
|
||||||
/*!
|
|
||||||
Called to create the window. This window is generally used to
|
|
||||||
receive events, hide the cursor, and to capture keyboard and mouse
|
|
||||||
input.
|
|
||||||
*/
|
|
||||||
virtual void createWindow() = 0;
|
|
||||||
|
|
||||||
//! Destroy window
|
|
||||||
/*!
|
|
||||||
Called to destroy the window created by createWindow().
|
|
||||||
*/
|
|
||||||
virtual void destroyWindow() = 0;
|
|
||||||
|
|
||||||
//! Show window
|
|
||||||
/*!
|
|
||||||
Called when the user navigates off the primary screen. Hide the
|
|
||||||
cursor and grab exclusive access to the input devices. Every call
|
|
||||||
to showWindow() has a matching call to hideWindow() which preceeds
|
|
||||||
it. Return true iff successful (in particular, iff the input
|
|
||||||
devices were grabbed).
|
|
||||||
|
|
||||||
After a successful showWindow(), user input events and
|
|
||||||
screensaver activation/deactivation should be reported to an
|
|
||||||
IPrimaryScreenReceiver (set through another interface) until
|
|
||||||
hideWindow() is called. Report mouse motion to its
|
|
||||||
onMouseMoveSecondary(). User input should not be delivered to
|
|
||||||
any application except this one.
|
|
||||||
*/
|
|
||||||
virtual bool showWindow() = 0;
|
|
||||||
|
|
||||||
//! Hide window
|
|
||||||
/*!
|
|
||||||
Called when the user navigates back to the primary screen. Show
|
|
||||||
the cursor and ungrab the input devices.
|
|
||||||
|
|
||||||
After hideWindow(), user input events should be delivered normally
|
|
||||||
to other applications. Mouse motion over (at least) the jump zones
|
|
||||||
must be reported to an IPrimaryScreenReceiver's onMouseMovePrimary().
|
|
||||||
*/
|
|
||||||
virtual void hideWindow() = 0;
|
|
||||||
|
|
||||||
//! Warp cursor for relative motion
|
|
||||||
/*!
|
|
||||||
Prepare the cursor to report relative motion. When the user has
|
|
||||||
navigated to another screen, synergy requires the cursor motion
|
|
||||||
deltas, not the absolute coordinates. Typically this is done by
|
|
||||||
warping the cursor to the center of the primary screen and then
|
|
||||||
every time it moves compute the motion and warp back to the
|
|
||||||
center (but without reporting that warp as motion). This is
|
|
||||||
only called after a successful showWindow().
|
|
||||||
*/
|
|
||||||
virtual void warpCursorToCenter() = 0;
|
|
||||||
|
|
||||||
//! Synchronize key state
|
|
||||||
/*!
|
|
||||||
Check the current keyboard state. Normally a screen will save
|
|
||||||
the keyboard state in this method and use this shadow state
|
|
||||||
when handling user input and in methods like isLockedToScreen().
|
|
||||||
*/
|
|
||||||
virtual void updateKeys() = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void enterNoWarp();
|
|
||||||
|
|
||||||
private:
|
|
||||||
CMutex m_mutex;
|
|
||||||
|
|
||||||
// object to notify of changes
|
|
||||||
IScreenReceiver* m_receiver;
|
|
||||||
|
|
||||||
// m_active is true if this screen has been left
|
|
||||||
bool m_active;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2002 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CSECONDARYSCREEN_H
|
||||||
|
#define CSECONDARYSCREEN_H
|
||||||
|
|
||||||
|
#include "IKeyState.h"
|
||||||
|
#include "ClipboardTypes.h"
|
||||||
|
#include "MouseTypes.h"
|
||||||
|
#include "OptionTypes.h"
|
||||||
|
#include "CMutex.h"
|
||||||
|
#include "stdmap.h"
|
||||||
|
|
||||||
|
class IClipboard;
|
||||||
|
class IPlatformScreen;
|
||||||
|
class IScreenReceiver;
|
||||||
|
|
||||||
|
//! Platform independent screen
|
||||||
|
/*!
|
||||||
|
This is a platform independent screen. It can work as either a
|
||||||
|
primary or secondary screen.
|
||||||
|
*/
|
||||||
|
class CScreen : public IKeyState {
|
||||||
|
public:
|
||||||
|
CScreen(IPlatformScreen* platformScreen, IScreenReceiver*);
|
||||||
|
virtual ~CScreen();
|
||||||
|
|
||||||
|
//! @name manipulators
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Open screen
|
||||||
|
/*!
|
||||||
|
Opens the screen.
|
||||||
|
*/
|
||||||
|
void open();
|
||||||
|
|
||||||
|
//! Close screen
|
||||||
|
/*!
|
||||||
|
Closes the screen.
|
||||||
|
*/
|
||||||
|
void close();
|
||||||
|
|
||||||
|
//! Activate screen
|
||||||
|
/*!
|
||||||
|
Activate the screen, preparing it to report system and user events.
|
||||||
|
For a secondary screen it also means disabling the screen saver if
|
||||||
|
synchronizing it and preparing to synthesize events.
|
||||||
|
*/
|
||||||
|
void enable();
|
||||||
|
|
||||||
|
//! Deactivate screen
|
||||||
|
/*!
|
||||||
|
Undoes the operations in activate() and events are no longer
|
||||||
|
reported. It also releases keys that are logically pressed.
|
||||||
|
*/
|
||||||
|
void disable();
|
||||||
|
|
||||||
|
//! Run event loop
|
||||||
|
/*!
|
||||||
|
Run the screen's event loop. This returns when it detects
|
||||||
|
the application should terminate or when exitMainLoop() is called.
|
||||||
|
mainLoop() may only be called between open() and close().
|
||||||
|
*/
|
||||||
|
void mainLoop();
|
||||||
|
|
||||||
|
//! Exit event loop
|
||||||
|
/*!
|
||||||
|
Force mainLoop() to return. This call can return before
|
||||||
|
mainLoop() does (i.e. asynchronously).
|
||||||
|
*/
|
||||||
|
void exitMainLoop();
|
||||||
|
|
||||||
|
//! Enter screen
|
||||||
|
/*!
|
||||||
|
Called when the user navigates to this screen.
|
||||||
|
*/
|
||||||
|
void enter();
|
||||||
|
|
||||||
|
//! Leave screen
|
||||||
|
/*!
|
||||||
|
Called when the user navigates off this screen.
|
||||||
|
*/
|
||||||
|
bool leave();
|
||||||
|
|
||||||
|
//! Update configuration
|
||||||
|
/*!
|
||||||
|
This is called when the configuration has changed. \c activeSides
|
||||||
|
is a bitmask of EDirectionMask indicating which sides of the
|
||||||
|
primary screen are linked to clients.
|
||||||
|
*/
|
||||||
|
void reconfigure(UInt32 activeSides);
|
||||||
|
|
||||||
|
//! Warp cursor
|
||||||
|
/*!
|
||||||
|
Warps the cursor to the absolute coordinates \c x,y. Also
|
||||||
|
discards input events up to and including the warp before
|
||||||
|
returning.
|
||||||
|
*/
|
||||||
|
void warpCursor(SInt32 x, SInt32 y);
|
||||||
|
|
||||||
|
//! Set clipboard
|
||||||
|
/*!
|
||||||
|
Sets the system's clipboard contents. This is usually called
|
||||||
|
soon after an enter().
|
||||||
|
*/
|
||||||
|
void setClipboard(ClipboardID, const IClipboard*);
|
||||||
|
|
||||||
|
//! Grab clipboard
|
||||||
|
/*!
|
||||||
|
Grabs (i.e. take ownership of) the system clipboard.
|
||||||
|
*/
|
||||||
|
void grabClipboard(ClipboardID);
|
||||||
|
|
||||||
|
//! Activate/deactivate screen saver
|
||||||
|
/*!
|
||||||
|
Forcibly activates the screen saver if \c activate is true otherwise
|
||||||
|
forcibly deactivates it.
|
||||||
|
*/
|
||||||
|
void screensaver(bool activate);
|
||||||
|
|
||||||
|
//! Notify of key press
|
||||||
|
/*!
|
||||||
|
Synthesize key events to generate a press of key \c id. If possible
|
||||||
|
match the given modifier mask. The KeyButton identifies the physical
|
||||||
|
key on the server that generated this key down. The client must
|
||||||
|
ensure that a key up or key repeat that uses the same KeyButton will
|
||||||
|
synthesize an up or repeat for the same client key synthesized by
|
||||||
|
keyDown().
|
||||||
|
*/
|
||||||
|
void keyDown(KeyID id, KeyModifierMask, KeyButton);
|
||||||
|
|
||||||
|
//! Notify of key repeat
|
||||||
|
/*!
|
||||||
|
Synthesize key events to generate a press and release of key \c id
|
||||||
|
\c count times. If possible match the given modifier mask.
|
||||||
|
*/
|
||||||
|
void keyRepeat(KeyID id, KeyModifierMask,
|
||||||
|
SInt32 count, KeyButton);
|
||||||
|
|
||||||
|
//! Notify of key release
|
||||||
|
/*!
|
||||||
|
Synthesize key events to generate a release of key \c id. If possible
|
||||||
|
match the given modifier mask.
|
||||||
|
*/
|
||||||
|
void keyUp(KeyID id, KeyModifierMask, KeyButton);
|
||||||
|
|
||||||
|
//! Notify of mouse press
|
||||||
|
/*!
|
||||||
|
Synthesize mouse events to generate a press of mouse button \c id.
|
||||||
|
*/
|
||||||
|
void mouseDown(ButtonID id);
|
||||||
|
|
||||||
|
//! Notify of mouse release
|
||||||
|
/*!
|
||||||
|
Synthesize mouse events to generate a release of mouse button \c id.
|
||||||
|
*/
|
||||||
|
void mouseUp(ButtonID id);
|
||||||
|
|
||||||
|
//! Notify of mouse motion
|
||||||
|
/*!
|
||||||
|
Synthesize mouse events to generate mouse motion to the absolute
|
||||||
|
screen position \c xAbs,yAbs.
|
||||||
|
*/
|
||||||
|
void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||||
|
|
||||||
|
//! Notify of mouse wheel motion
|
||||||
|
/*!
|
||||||
|
Synthesize mouse events to generate mouse wheel motion of \c delta.
|
||||||
|
\c delta is positive for motion away from the user and negative for
|
||||||
|
motion towards the user. Each wheel click should generate a delta
|
||||||
|
of +/-120.
|
||||||
|
*/
|
||||||
|
void mouseWheel(SInt32 delta);
|
||||||
|
|
||||||
|
//! Notify of options changes
|
||||||
|
/*!
|
||||||
|
Resets all options to their default values.
|
||||||
|
*/
|
||||||
|
void resetOptions();
|
||||||
|
|
||||||
|
//! Notify of options changes
|
||||||
|
/*!
|
||||||
|
Set options to given values. Ignores unknown options and doesn't
|
||||||
|
modify options that aren't given in \c options.
|
||||||
|
*/
|
||||||
|
void setOptions(const COptionsList& options);
|
||||||
|
|
||||||
|
//! Install a one-shot timer
|
||||||
|
/*!
|
||||||
|
Installs a one-shot timer for \c timeout seconds and returns the
|
||||||
|
id of the timer.
|
||||||
|
*/
|
||||||
|
UInt32 addOneShotTimer(double timeout);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Test if cursor on screen
|
||||||
|
/*!
|
||||||
|
Returns true iff the cursor is on the screen.
|
||||||
|
*/
|
||||||
|
bool isOnScreen() const;
|
||||||
|
|
||||||
|
//! Get clipboard
|
||||||
|
/*!
|
||||||
|
Saves the contents of the system clipboard indicated by \c id.
|
||||||
|
*/
|
||||||
|
void getClipboard(ClipboardID id, IClipboard*) const;
|
||||||
|
|
||||||
|
//! Get jump zone size
|
||||||
|
/*!
|
||||||
|
Returns the jump zone size, the size of the regions on the edges of
|
||||||
|
the screen that cause the cursor to jump to another screen.
|
||||||
|
*/
|
||||||
|
SInt32 getJumpZoneSize() const;
|
||||||
|
|
||||||
|
//! Get screen lock state
|
||||||
|
/*!
|
||||||
|
Returns true if there's any reason that the user should not be
|
||||||
|
allowed to leave the screen. Active toggle keys (excluding the
|
||||||
|
scroll lock key) are not be counted as reasons to lock to the
|
||||||
|
screen. If this method returns true it logs a message on why at
|
||||||
|
the CLOG_DEBUG level.
|
||||||
|
*/
|
||||||
|
bool isLockedToScreen() const;
|
||||||
|
|
||||||
|
//! Get screen shape
|
||||||
|
/*!
|
||||||
|
Returns the position of the upper-left corner of the screen in \c x
|
||||||
|
and \c y and the size of the screen in \c width and \c height.
|
||||||
|
*/
|
||||||
|
void getShape(SInt32& x, SInt32& y,
|
||||||
|
SInt32& width, SInt32& height) const;
|
||||||
|
|
||||||
|
//! Get cursor position
|
||||||
|
/*!
|
||||||
|
Returns the current position of the cursor in \c x,y.
|
||||||
|
*/
|
||||||
|
void getCursorPos(SInt32& x, SInt32& y) const;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
// IKeyState overrides
|
||||||
|
virtual void updateKeys();
|
||||||
|
virtual void releaseKeys();
|
||||||
|
virtual void setKeyDown(KeyButton key);
|
||||||
|
virtual void setToggled(KeyModifierMask);
|
||||||
|
virtual void addModifier(KeyModifierMask, KeyButtons&);
|
||||||
|
virtual void setToggleState(KeyModifierMask);
|
||||||
|
virtual KeyButton isAnyKeyDown() const;
|
||||||
|
virtual bool isKeyDown(KeyButton) const;
|
||||||
|
virtual bool isToggle(KeyModifierMask) const;
|
||||||
|
virtual bool isHalfDuplex(KeyModifierMask) const;
|
||||||
|
virtual bool isModifierActive(KeyModifierMask) const;
|
||||||
|
virtual KeyModifierMask
|
||||||
|
getActiveModifiers() const;
|
||||||
|
virtual bool mapModifier(Keystrokes& keys, Keystrokes& undo,
|
||||||
|
KeyModifierMask mask, bool desireActive) const;
|
||||||
|
virtual KeyModifierMask
|
||||||
|
getMaskForKey(KeyButton) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void enablePrimary();
|
||||||
|
void enableSecondary();
|
||||||
|
void disablePrimary();
|
||||||
|
void disableSecondary();
|
||||||
|
|
||||||
|
void enterPrimary();
|
||||||
|
void enterSecondary();
|
||||||
|
void leavePrimary();
|
||||||
|
void leaveSecondary();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Get the modifier mask for the current key state
|
||||||
|
KeyModifierMask getModifierMask() const;
|
||||||
|
|
||||||
|
// Send fake keystrokes
|
||||||
|
void doKeystrokes(const Keystrokes&, SInt32 count);
|
||||||
|
|
||||||
|
// Send a fake key event
|
||||||
|
void fakeKeyEvent(KeyButton, bool press, bool repeat) const;
|
||||||
|
|
||||||
|
// Update the shadow state for a key
|
||||||
|
void updateKeyState(KeyButton button,
|
||||||
|
KeyButton key, bool press);
|
||||||
|
|
||||||
|
// Toggle a modifier
|
||||||
|
void toggleKey(KeyModifierMask);
|
||||||
|
|
||||||
|
// Test if a modifier is toggled
|
||||||
|
bool isKeyToggled(KeyButton) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map<KeyButton, KeyButton> ServerKeyMap;
|
||||||
|
typedef std::map<KeyModifierMask, KeyButtons> MaskToKeys;
|
||||||
|
typedef std::map<KeyButton, KeyModifierMask> KeyToMask;
|
||||||
|
|
||||||
|
CMutex m_mutex;
|
||||||
|
|
||||||
|
// our platform dependent screen
|
||||||
|
IPlatformScreen* m_screen;
|
||||||
|
|
||||||
|
// our screen receiver
|
||||||
|
IScreenReceiver* m_receiver;
|
||||||
|
|
||||||
|
// true if screen is being used as a primary screen, false otherwise
|
||||||
|
bool m_isPrimary;
|
||||||
|
|
||||||
|
// true if screen is enabled
|
||||||
|
bool m_enabled;
|
||||||
|
|
||||||
|
// true if the cursor is on this screen
|
||||||
|
bool m_entered;
|
||||||
|
|
||||||
|
// true if screen saver should be synchronized to server
|
||||||
|
bool m_screenSaverSync;
|
||||||
|
|
||||||
|
// note toggle keys that toggles on up/down (false) or on
|
||||||
|
// transition (true)
|
||||||
|
bool m_numLockHalfDuplex;
|
||||||
|
bool m_capsLockHalfDuplex;
|
||||||
|
|
||||||
|
// keyboard state
|
||||||
|
|
||||||
|
// map server key buttons to local system keys
|
||||||
|
ServerKeyMap m_serverKeyMap;
|
||||||
|
|
||||||
|
// system key states as set by us or the user
|
||||||
|
KeyState m_keys[256];
|
||||||
|
|
||||||
|
// system key states as set by us
|
||||||
|
KeyState m_fakeKeys[256];
|
||||||
|
|
||||||
|
// modifier info
|
||||||
|
MaskToKeys m_maskToKeys;
|
||||||
|
KeyToMask m_keyToMask;
|
||||||
|
|
||||||
|
// current active modifiers
|
||||||
|
KeyModifierMask m_mask;
|
||||||
|
|
||||||
|
// the toggle key state when this screen was last entered
|
||||||
|
KeyModifierMask m_toggleKeys;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,781 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "CSecondaryScreen.h"
|
|
||||||
#include "IScreen.h"
|
|
||||||
#include "CLock.h"
|
|
||||||
#include "CThread.h"
|
|
||||||
#include "CLog.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// CSecondaryScreen
|
|
||||||
//
|
|
||||||
|
|
||||||
CSecondaryScreen::CSecondaryScreen() :
|
|
||||||
m_remoteReady(false),
|
|
||||||
m_active(false),
|
|
||||||
m_toggleKeys(0),
|
|
||||||
m_screenSaverSync(true)
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
CSecondaryScreen::~CSecondaryScreen()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::mainLoop()
|
|
||||||
{
|
|
||||||
// change our priority
|
|
||||||
CThread::getCurrentThread().setPriority(-14);
|
|
||||||
|
|
||||||
// run event loop
|
|
||||||
try {
|
|
||||||
LOG((CLOG_DEBUG "entering event loop"));
|
|
||||||
onPreMainLoop();
|
|
||||||
getScreen()->mainLoop();
|
|
||||||
onPostMainLoop();
|
|
||||||
LOG((CLOG_DEBUG "exiting event loop"));
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
onPostMainLoop();
|
|
||||||
LOG((CLOG_DEBUG "exiting event loop"));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::exitMainLoop()
|
|
||||||
{
|
|
||||||
getScreen()->exitMainLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::open()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// subclass hook
|
|
||||||
onPreOpen();
|
|
||||||
|
|
||||||
// open the screen
|
|
||||||
getScreen()->open();
|
|
||||||
|
|
||||||
// create and prepare our window. pretend we're active so
|
|
||||||
// we don't try to show our window until later.
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
assert(m_active == false);
|
|
||||||
m_active = true;
|
|
||||||
}
|
|
||||||
createWindow();
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
m_active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPostOpen();
|
|
||||||
|
|
||||||
// reset options
|
|
||||||
resetOptions();
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
close();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::close()
|
|
||||||
{
|
|
||||||
onPreClose();
|
|
||||||
destroyWindow();
|
|
||||||
getScreen()->close();
|
|
||||||
onPostClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::remoteControl()
|
|
||||||
{
|
|
||||||
// assume primary has all clipboards
|
|
||||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
|
||||||
grabClipboard(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update keyboard state
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
updateKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
// now remote ready. fake being active for call to leave().
|
|
||||||
bool screenSaverSync;
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
m_remoteReady = true;
|
|
||||||
m_active = true;
|
|
||||||
|
|
||||||
// copy screen saver synchronization state
|
|
||||||
screenSaverSync = m_screenSaverSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable the screen saver if synchronization is enabled
|
|
||||||
if (screenSaverSync) {
|
|
||||||
getScreen()->openScreensaver(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// hide the cursor
|
|
||||||
leave();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::localControl()
|
|
||||||
{
|
|
||||||
getScreen()->closeScreensaver();
|
|
||||||
|
|
||||||
// not remote ready anymore
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
m_remoteReady = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::enter(SInt32 x, SInt32 y, KeyModifierMask mask)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
assert(m_active == false);
|
|
||||||
|
|
||||||
LOG((CLOG_INFO "entering screen at %d,%d mask=%04x", x, y, mask));
|
|
||||||
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// now active
|
|
||||||
m_active = true;
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPreEnter();
|
|
||||||
|
|
||||||
// update our keyboard state to reflect the local state
|
|
||||||
updateKeys();
|
|
||||||
|
|
||||||
// toggle modifiers that don't match the desired state and
|
|
||||||
// remember previous toggle key state.
|
|
||||||
m_toggleKeys = m_mask;
|
|
||||||
setToggleState(mask);
|
|
||||||
|
|
||||||
// warp to requested location
|
|
||||||
fakeMouseMove(x, y);
|
|
||||||
|
|
||||||
// show mouse
|
|
||||||
hideWindow();
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPostEnter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::leave()
|
|
||||||
{
|
|
||||||
LOG((CLOG_INFO "leaving screen"));
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
assert(m_active == true);
|
|
||||||
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPreLeave();
|
|
||||||
|
|
||||||
// restore toggle key state
|
|
||||||
setToggleState(m_toggleKeys);
|
|
||||||
|
|
||||||
// hide mouse
|
|
||||||
SInt32 x, y;
|
|
||||||
getScreen()->getCursorCenter(x, y);
|
|
||||||
showWindow(x, y);
|
|
||||||
|
|
||||||
// subclass hook
|
|
||||||
onPostLeave();
|
|
||||||
|
|
||||||
// not active anymore
|
|
||||||
m_active = false;
|
|
||||||
|
|
||||||
// make sure our idea of clipboard ownership is correct
|
|
||||||
getScreen()->checkClipboards();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::setClipboard(ClipboardID id,
|
|
||||||
const IClipboard* clipboard)
|
|
||||||
{
|
|
||||||
getScreen()->setClipboard(id, clipboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::grabClipboard(ClipboardID id)
|
|
||||||
{
|
|
||||||
getScreen()->setClipboard(id, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::screensaver(bool activate)
|
|
||||||
{
|
|
||||||
// get screen saver synchronization flag
|
|
||||||
bool screenSaverSync;
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
screenSaverSync = m_screenSaverSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
// activate/deactivation screen saver iff synchronization enabled
|
|
||||||
if (screenSaverSync) {
|
|
||||||
getScreen()->screensaver(activate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSecondaryScreen::SysKeyID
|
|
||||||
CSecondaryScreen::getUnhanded(SysKeyID) const
|
|
||||||
{
|
|
||||||
// no key represents both left and right sides of any key
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSecondaryScreen::SysKeyID
|
|
||||||
CSecondaryScreen::getOtherHanded(SysKeyID) const
|
|
||||||
{
|
|
||||||
// no key represents both left and right sides of any key
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CSecondaryScreen::synthesizeCtrlAltDel(EKeyAction)
|
|
||||||
{
|
|
||||||
// pass keys through unchanged
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::sync() const
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::flush()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::doKeystrokes(const Keystrokes& keys, SInt32 count)
|
|
||||||
{
|
|
||||||
// do nothing if no keys or no repeats
|
|
||||||
if (count < 1 || keys.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate key events
|
|
||||||
LOG((CLOG_DEBUG2 "keystrokes:"));
|
|
||||||
for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ) {
|
|
||||||
if (k->m_repeat) {
|
|
||||||
// repeat from here up to but not including the next key
|
|
||||||
// with m_repeat == false count times.
|
|
||||||
Keystrokes::const_iterator start = k;
|
|
||||||
for (; count > 0; --count) {
|
|
||||||
// send repeating events
|
|
||||||
for (k = start; k != keys.end() && k->m_repeat; ++k) {
|
|
||||||
LOG((CLOG_DEBUG2 " %d %s repeat", k->m_sysKeyID, k->m_press ? "down" : "up"));
|
|
||||||
fakeKeyEvent(k->m_sysKeyID, k->m_press);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// note -- k is now on the first non-repeat key after the
|
|
||||||
// repeat keys, exactly where we'd like to continue from.
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// send event
|
|
||||||
LOG((CLOG_DEBUG2 " %d %s", k->m_sysKeyID, k->m_press ? "down" : "up"));
|
|
||||||
fakeKeyEvent(k->m_sysKeyID, k->m_press);
|
|
||||||
|
|
||||||
// next key
|
|
||||||
++k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::keyDown(KeyID key,
|
|
||||||
KeyModifierMask mask, KeyButton button)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// check for ctrl+alt+del emulation
|
|
||||||
if (key == kKeyDelete &&
|
|
||||||
(mask & (KeyModifierControl | KeyModifierAlt)) ==
|
|
||||||
(KeyModifierControl | KeyModifierAlt)) {
|
|
||||||
LOG((CLOG_DEBUG "emulating ctrl+alt+del press"));
|
|
||||||
if (synthesizeCtrlAltDel(kPress)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the sequence of keys to simulate key press and the final
|
|
||||||
// modifier state.
|
|
||||||
Keystrokes keys;
|
|
||||||
SysKeyID sysKeyID;
|
|
||||||
m_mask = mapKey(keys, sysKeyID, key, m_mask, mask, kPress);
|
|
||||||
if (keys.empty()) {
|
|
||||||
// do nothing if there are no associated keys (i.e. lookup failed)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sysKeyID &= 0xffu;
|
|
||||||
|
|
||||||
// generate key events
|
|
||||||
doKeystrokes(keys, 1);
|
|
||||||
|
|
||||||
// do not record button down if button or system key is 0 (invalid)
|
|
||||||
if (button != 0 && sysKeyID != 0) {
|
|
||||||
// note that key is now down
|
|
||||||
SysKeyID unhandedSysKeyID = getUnhanded(sysKeyID);
|
|
||||||
m_serverKeyMap[button] = sysKeyID;
|
|
||||||
m_keys[sysKeyID] |= kDown;
|
|
||||||
m_fakeKeys[sysKeyID] |= kDown;
|
|
||||||
if (unhandedSysKeyID != 0) {
|
|
||||||
m_keys[unhandedSysKeyID] |= kDown;
|
|
||||||
m_fakeKeys[unhandedSysKeyID] |= kDown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::keyRepeat(KeyID key,
|
|
||||||
KeyModifierMask mask, SInt32 count, KeyButton button)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// if we haven't seen this button go down then ignore it
|
|
||||||
ServerKeyMap::iterator index = m_serverKeyMap.find(button);
|
|
||||||
if (index == m_serverKeyMap.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the sequence of keys to simulate key repeat and the final
|
|
||||||
// modifier state.
|
|
||||||
Keystrokes keys;
|
|
||||||
SysKeyID sysKeyID;
|
|
||||||
m_mask = mapKey(keys, sysKeyID, key, m_mask, mask, kRepeat);
|
|
||||||
if (keys.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sysKeyID &= 0xffu;
|
|
||||||
|
|
||||||
// if this key shouldn't auto-repeat then ignore
|
|
||||||
if (!isAutoRepeating(sysKeyID)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the keycode for the auto-repeat is not the same as for the
|
|
||||||
// initial press then mark the initial key as released and the new
|
|
||||||
// key as pressed. this can happen when we auto-repeat after a
|
|
||||||
// dead key. for example, a dead accent followed by 'a' will
|
|
||||||
// generate an 'a with accent' followed by a repeating 'a'. the
|
|
||||||
// keycodes for the two keysyms might be different.
|
|
||||||
if (sysKeyID != index->second) {
|
|
||||||
// replace key up with previous key id but leave key down
|
|
||||||
// alone so it uses the new keycode and store that keycode
|
|
||||||
// in the server key map.
|
|
||||||
for (Keystrokes::iterator index2 = keys.begin();
|
|
||||||
index2 != keys.end(); ++index2) {
|
|
||||||
if ((index2->m_sysKeyID & 0xffu) == sysKeyID) {
|
|
||||||
index2->m_sysKeyID = index->second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// note that old key is now up
|
|
||||||
m_keys[index->second] &= ~kDown;
|
|
||||||
m_fakeKeys[index->second] &= ~kDown;
|
|
||||||
|
|
||||||
// map server key to new key
|
|
||||||
index->second = sysKeyID;
|
|
||||||
|
|
||||||
// note that new key is now down
|
|
||||||
m_keys[index->second] |= kDown;
|
|
||||||
m_fakeKeys[index->second] |= kDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate key events
|
|
||||||
doKeystrokes(keys, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask, KeyButton button)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// if we haven't seen this button go down then ignore it
|
|
||||||
ServerKeyMap::iterator index = m_serverKeyMap.find(button);
|
|
||||||
if (index == m_serverKeyMap.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SysKeyID sysKeyID = index->second;
|
|
||||||
|
|
||||||
// check for ctrl+alt+del emulation
|
|
||||||
if (key == kKeyDelete &&
|
|
||||||
(mask & (KeyModifierControl | KeyModifierAlt)) ==
|
|
||||||
(KeyModifierControl | KeyModifierAlt)) {
|
|
||||||
LOG((CLOG_DEBUG "emulating ctrl+alt+del release"));
|
|
||||||
if (synthesizeCtrlAltDel(kRelease)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the sequence of keys to simulate key release
|
|
||||||
Keystrokes keys;
|
|
||||||
Keystroke keystroke;
|
|
||||||
keystroke.m_sysKeyID = sysKeyID;
|
|
||||||
keystroke.m_press = false;
|
|
||||||
keystroke.m_repeat = false;
|
|
||||||
keys.push_back(keystroke);
|
|
||||||
|
|
||||||
// generate key events
|
|
||||||
doKeystrokes(keys, 1);
|
|
||||||
|
|
||||||
// note that key is now up
|
|
||||||
SysKeyID unhandedSysKeyID = getUnhanded(sysKeyID);
|
|
||||||
m_serverKeyMap.erase(index);
|
|
||||||
m_keys[sysKeyID] &= ~kDown;
|
|
||||||
m_fakeKeys[sysKeyID] &= ~kDown;
|
|
||||||
if (unhandedSysKeyID != 0) {
|
|
||||||
SysKeyID otherHandedSysKeyID = getOtherHanded(sysKeyID);
|
|
||||||
if ((m_keys[otherHandedSysKeyID] & kDown) == 0) {
|
|
||||||
m_keys[unhandedSysKeyID] &= ~kDown;
|
|
||||||
m_fakeKeys[unhandedSysKeyID] &= ~kDown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the new modifier state
|
|
||||||
mask = getModifierKeyMask(sysKeyID);
|
|
||||||
if (mask != 0) {
|
|
||||||
// key is a modifier key
|
|
||||||
if ((mask & (KeyModifierCapsLock |
|
|
||||||
KeyModifierNumLock |
|
|
||||||
KeyModifierScrollLock)) != 0) {
|
|
||||||
// modifier is a toggle
|
|
||||||
m_mask ^= mask;
|
|
||||||
}
|
|
||||||
else if (!isModifierActive(sysKeyID)) {
|
|
||||||
// all keys for this modifier are released
|
|
||||||
m_mask &= ~mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::mouseDown(ButtonID button)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
fakeMouseButton(button, true);
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::mouseUp(ButtonID button)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
fakeMouseButton(button, false);
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::mouseMove(SInt32 x, SInt32 y)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
fakeMouseMove(x, y);
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::mouseWheel(SInt32 delta)
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
fakeMouseWheel(delta);
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::setToggleState(KeyModifierMask mask)
|
|
||||||
{
|
|
||||||
// toggle modifiers that don't match the desired state
|
|
||||||
KeyModifierMask different = (m_mask ^ mask);
|
|
||||||
if ((different & KeyModifierCapsLock) != 0) {
|
|
||||||
toggleKey(kKeyCapsLock, KeyModifierCapsLock);
|
|
||||||
}
|
|
||||||
if ((different & KeyModifierNumLock) != 0) {
|
|
||||||
toggleKey(kKeyNumLock, KeyModifierNumLock);
|
|
||||||
}
|
|
||||||
if ((different & KeyModifierScrollLock) != 0) {
|
|
||||||
toggleKey(kKeyScrollLock, KeyModifierScrollLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::resetOptions()
|
|
||||||
{
|
|
||||||
// set screen saver synchronization flag and see if we need to
|
|
||||||
// update the screen saver synchronization. reset other options.
|
|
||||||
bool screenSaverSyncOn;
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
screenSaverSyncOn = (!m_screenSaverSync && m_remoteReady);
|
|
||||||
m_screenSaverSync = true;
|
|
||||||
m_numLockHalfDuplex = false;
|
|
||||||
m_capsLockHalfDuplex = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update screen saver synchronization
|
|
||||||
if (screenSaverSyncOn) {
|
|
||||||
getScreen()->openScreensaver(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::setOptions(const COptionsList& options)
|
|
||||||
{
|
|
||||||
// update options
|
|
||||||
bool updateScreenSaverSync = false;
|
|
||||||
bool oldScreenSaverSync;
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
oldScreenSaverSync = m_screenSaverSync;
|
|
||||||
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
|
||||||
if (options[i] == kOptionScreenSaverSync) {
|
|
||||||
updateScreenSaverSync = true;
|
|
||||||
m_screenSaverSync = (options[i + 1] != 0);
|
|
||||||
LOG((CLOG_DEBUG1 "screen saver synchronization %s", m_screenSaverSync ? "on" : "off"));
|
|
||||||
}
|
|
||||||
else if (options[i] == kOptionHalfDuplexCapsLock) {
|
|
||||||
m_capsLockHalfDuplex = (options[i + 1] != 0);
|
|
||||||
LOG((CLOG_DEBUG1 "half-duplex caps-lock %s", m_capsLockHalfDuplex ? "on" : "off"));
|
|
||||||
}
|
|
||||||
else if (options[i] == kOptionHalfDuplexNumLock) {
|
|
||||||
m_numLockHalfDuplex = (options[i + 1] != 0);
|
|
||||||
LOG((CLOG_DEBUG1 "half-duplex num-lock %s", m_numLockHalfDuplex ? "on" : "off"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!m_remoteReady || oldScreenSaverSync == m_screenSaverSync) {
|
|
||||||
updateScreenSaverSync = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update screen saver synchronization
|
|
||||||
if (updateScreenSaverSync) {
|
|
||||||
if (oldScreenSaverSync) {
|
|
||||||
getScreen()->closeScreensaver();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
getScreen()->openScreensaver(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CSecondaryScreen::isActive() const
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
return m_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::getClipboard(ClipboardID id,
|
|
||||||
IClipboard* clipboard) const
|
|
||||||
{
|
|
||||||
getScreen()->getClipboard(id, clipboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
SInt32
|
|
||||||
CSecondaryScreen::getJumpZoneSize() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
|
||||||
{
|
|
||||||
sync();
|
|
||||||
getScreen()->getShape(x, y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::getCursorPos(SInt32& x, SInt32& y) const
|
|
||||||
{
|
|
||||||
sync();
|
|
||||||
getScreen()->getCursorPos(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPreMainLoop()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPostMainLoop()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPreOpen()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPostOpen()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPreClose()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPostClose()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPreEnter()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPostEnter()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPreLeave()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::onPostLeave()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::updateKeys()
|
|
||||||
{
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// clear key state
|
|
||||||
memset(m_keys, 0, sizeof(m_keys));
|
|
||||||
memset(m_fakeKeys, 0, sizeof(m_fakeKeys));
|
|
||||||
|
|
||||||
// let subclass set m_keys
|
|
||||||
updateKeys(m_keys);
|
|
||||||
|
|
||||||
// get m_mask from subclass
|
|
||||||
m_mask = getModifiers();
|
|
||||||
LOG((CLOG_DEBUG2 "modifiers on update: 0x%04x", m_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::releaseKeys()
|
|
||||||
{
|
|
||||||
CLock lock(&m_mutex);
|
|
||||||
sync();
|
|
||||||
|
|
||||||
// release keys that we've synthesized a press for and only those
|
|
||||||
// keys. we don't want to synthesize a release on a key the user
|
|
||||||
// is still physically pressing.
|
|
||||||
for (UInt32 i = 1; i < 256; ++i) {
|
|
||||||
if ((m_fakeKeys[i] & kDown) != 0) {
|
|
||||||
fakeKeyEvent(i, false);
|
|
||||||
m_keys[i] &= ~kDown;
|
|
||||||
m_fakeKeys[i] &= ~kDown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CSecondaryScreen::toggleKey(KeyID keyID, KeyModifierMask mask)
|
|
||||||
{
|
|
||||||
// get the system key ID for this toggle key ID
|
|
||||||
SysKeyID sysKeyID = getToggleSysKey(keyID);
|
|
||||||
if (sysKeyID == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// toggle the key
|
|
||||||
if (isKeyHalfDuplex(keyID)) {
|
|
||||||
// "half-duplex" toggle
|
|
||||||
fakeKeyEvent(sysKeyID, (m_mask & mask) == 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// normal toggle
|
|
||||||
fakeKeyEvent(sysKeyID, true);
|
|
||||||
fakeKeyEvent(sysKeyID, false);
|
|
||||||
}
|
|
||||||
flush();
|
|
||||||
|
|
||||||
// toggle shadow state
|
|
||||||
m_mask ^= mask;
|
|
||||||
sysKeyID &= 0xffu;
|
|
||||||
m_keys[sysKeyID] ^= kToggled;
|
|
||||||
m_fakeKeys[sysKeyID] ^= kToggled;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CSecondaryScreen::isKeyDown(SysKeyID sysKeyID) const
|
|
||||||
{
|
|
||||||
sysKeyID &= 0xffu;
|
|
||||||
return (sysKeyID != 0 && ((m_keys[sysKeyID] & kDown) != 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CSecondaryScreen::isKeyToggled(SysKeyID sysKeyID) const
|
|
||||||
{
|
|
||||||
sysKeyID &= 0xffu;
|
|
||||||
return (sysKeyID != 0 && ((m_keys[sysKeyID] & kToggled) != 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CSecondaryScreen::isKeyHalfDuplex(KeyID keyID) const
|
|
||||||
{
|
|
||||||
return ((keyID == kKeyCapsLock && m_capsLockHalfDuplex) ||
|
|
||||||
(keyID == kKeyNumLock && m_numLockHalfDuplex));
|
|
||||||
}
|
|
|
@ -1,446 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CSECONDARYSCREEN_H
|
|
||||||
#define CSECONDARYSCREEN_H
|
|
||||||
|
|
||||||
#include "ClipboardTypes.h"
|
|
||||||
#include "KeyTypes.h"
|
|
||||||
#include "MouseTypes.h"
|
|
||||||
#include "OptionTypes.h"
|
|
||||||
#include "CMutex.h"
|
|
||||||
#include "stdmap.h"
|
|
||||||
#include "stdvector.h"
|
|
||||||
|
|
||||||
class IClipboard;
|
|
||||||
class IScreen;
|
|
||||||
|
|
||||||
//! Generic client-side screen
|
|
||||||
/*!
|
|
||||||
This is a platform independent base class for secondary screen
|
|
||||||
implementations. A secondary screen is a client-side screen.
|
|
||||||
Each platform will derive a class from CSecondaryScreen to handle
|
|
||||||
platform dependent operations.
|
|
||||||
*/
|
|
||||||
class CSecondaryScreen {
|
|
||||||
public:
|
|
||||||
CSecondaryScreen();
|
|
||||||
virtual ~CSecondaryScreen();
|
|
||||||
|
|
||||||
//! @name manipulators
|
|
||||||
//@{
|
|
||||||
|
|
||||||
//! Open screen
|
|
||||||
/*!
|
|
||||||
Opens the screen. It also causes events to the reported to an
|
|
||||||
IScreenReceiver (which is set through some other interface).
|
|
||||||
Calls close() before returning (rethrowing) if it fails for any
|
|
||||||
reason.
|
|
||||||
*/
|
|
||||||
void open();
|
|
||||||
|
|
||||||
//! Run event loop
|
|
||||||
/*!
|
|
||||||
Run the screen's event loop. This returns when it detects
|
|
||||||
the application should terminate or when exitMainLoop() is called.
|
|
||||||
mainLoop() may only be called between open() and close().
|
|
||||||
*/
|
|
||||||
void mainLoop();
|
|
||||||
|
|
||||||
//! Exit event loop
|
|
||||||
/*!
|
|
||||||
Force mainLoop() to return. This call can return before
|
|
||||||
mainLoop() does (i.e. asynchronously).
|
|
||||||
*/
|
|
||||||
void exitMainLoop();
|
|
||||||
|
|
||||||
//! Prepare for remote control
|
|
||||||
/*!
|
|
||||||
Prepares the screen for remote control by the server. In
|
|
||||||
particular, it disables the screen saver.
|
|
||||||
*/
|
|
||||||
void remoteControl();
|
|
||||||
|
|
||||||
//! Release from remote control
|
|
||||||
/*!
|
|
||||||
Cleans up the screen from remote control by the server. In
|
|
||||||
particular, it enables the screen saver. It also synthesizes
|
|
||||||
key up events for any keys that are logically down; without
|
|
||||||
this the client will leave its keyboard in the wrong logical
|
|
||||||
state.
|
|
||||||
*/
|
|
||||||
void localControl();
|
|
||||||
|
|
||||||
//! Close screen
|
|
||||||
/*!
|
|
||||||
Closes the screen.
|
|
||||||
*/
|
|
||||||
void close();
|
|
||||||
|
|
||||||
//! Enter screen
|
|
||||||
/*!
|
|
||||||
Called when the user navigates to this secondary screen. Warps
|
|
||||||
the cursor to the absolute coordinates \c x,y and unhides
|
|
||||||
it. Also prepares to synthesize input events.
|
|
||||||
*/
|
|
||||||
void enter(SInt32 x, SInt32 y, KeyModifierMask mask);
|
|
||||||
|
|
||||||
//! Leave screen
|
|
||||||
/*!
|
|
||||||
Called when the user navigates off the secondary screen. Cleans
|
|
||||||
up input event synthesis and hides the cursor.
|
|
||||||
*/
|
|
||||||
void leave();
|
|
||||||
|
|
||||||
//! Set clipboard
|
|
||||||
/*!
|
|
||||||
Sets the system's clipboard contents. This is usually called
|
|
||||||
soon after an enter().
|
|
||||||
*/
|
|
||||||
void setClipboard(ClipboardID, const IClipboard*);
|
|
||||||
|
|
||||||
//! Grab clipboard
|
|
||||||
/*!
|
|
||||||
Grabs (i.e. take ownership of) the system clipboard.
|
|
||||||
*/
|
|
||||||
void grabClipboard(ClipboardID);
|
|
||||||
|
|
||||||
//! Activate/deactivate screen saver
|
|
||||||
/*!
|
|
||||||
Forcibly activates the screen saver if \c activate is true otherwise
|
|
||||||
forcibly deactivates it.
|
|
||||||
*/
|
|
||||||
void screensaver(bool activate);
|
|
||||||
|
|
||||||
//! Notify of key press
|
|
||||||
/*!
|
|
||||||
Synthesize key events to generate a press of key \c id. If possible
|
|
||||||
match the given modifier mask. The KeyButton identifies the physical
|
|
||||||
key on the server that generated this key down. The client must
|
|
||||||
ensure that a key up or key repeat that uses the same KeyButton will
|
|
||||||
synthesize an up or repeat for the same client key synthesized by
|
|
||||||
keyDown().
|
|
||||||
*/
|
|
||||||
void keyDown(KeyID id, KeyModifierMask, KeyButton);
|
|
||||||
|
|
||||||
//! Notify of key repeat
|
|
||||||
/*!
|
|
||||||
Synthesize key events to generate a press and release of key \c id
|
|
||||||
\c count times. If possible match the given modifier mask.
|
|
||||||
*/
|
|
||||||
void keyRepeat(KeyID id, KeyModifierMask,
|
|
||||||
SInt32 count, KeyButton);
|
|
||||||
|
|
||||||
//! Notify of key release
|
|
||||||
/*!
|
|
||||||
Synthesize key events to generate a release of key \c id. If possible
|
|
||||||
match the given modifier mask.
|
|
||||||
*/
|
|
||||||
void keyUp(KeyID id, KeyModifierMask, KeyButton);
|
|
||||||
|
|
||||||
//! Notify of mouse press
|
|
||||||
/*!
|
|
||||||
Synthesize mouse events to generate a press of mouse button \c id.
|
|
||||||
*/
|
|
||||||
void mouseDown(ButtonID id);
|
|
||||||
|
|
||||||
//! Notify of mouse release
|
|
||||||
/*!
|
|
||||||
Synthesize mouse events to generate a release of mouse button \c id.
|
|
||||||
*/
|
|
||||||
void mouseUp(ButtonID id);
|
|
||||||
|
|
||||||
//! Notify of mouse motion
|
|
||||||
/*!
|
|
||||||
Synthesize mouse events to generate mouse motion to the absolute
|
|
||||||
screen position \c xAbs,yAbs.
|
|
||||||
*/
|
|
||||||
void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
|
||||||
|
|
||||||
//! Notify of mouse wheel motion
|
|
||||||
/*!
|
|
||||||
Synthesize mouse events to generate mouse wheel motion of \c delta.
|
|
||||||
\c delta is positive for motion away from the user and negative for
|
|
||||||
motion towards the user. Each wheel click should generate a delta
|
|
||||||
of +/-120.
|
|
||||||
*/
|
|
||||||
void mouseWheel(SInt32 delta);
|
|
||||||
|
|
||||||
//! Notify of options changes
|
|
||||||
/*!
|
|
||||||
Reset all options to their default values. Overrides should call
|
|
||||||
the superclass's method.
|
|
||||||
*/
|
|
||||||
virtual void resetOptions();
|
|
||||||
|
|
||||||
//! Notify of options changes
|
|
||||||
/*!
|
|
||||||
Set options to given values. Ignore unknown options and don't
|
|
||||||
modify our options that aren't given in \c options. Overrides
|
|
||||||
should call the superclass's method.
|
|
||||||
*/
|
|
||||||
virtual void setOptions(const COptionsList& options);
|
|
||||||
|
|
||||||
//@}
|
|
||||||
//! @name accessors
|
|
||||||
//@{
|
|
||||||
|
|
||||||
//! Test if active
|
|
||||||
/*!
|
|
||||||
Returns true iff the screen is active (i.e. the user has entered
|
|
||||||
the screen). Note this is the reverse of a primary screen.
|
|
||||||
*/
|
|
||||||
bool isActive() const;
|
|
||||||
|
|
||||||
//! Get clipboard
|
|
||||||
/*!
|
|
||||||
Saves the contents of the system clipboard indicated by \c id.
|
|
||||||
*/
|
|
||||||
void getClipboard(ClipboardID id, IClipboard*) const;
|
|
||||||
|
|
||||||
//! Get jump zone size
|
|
||||||
/*!
|
|
||||||
Return the jump zone size, the size of the regions on the edges of
|
|
||||||
the screen that cause the cursor to jump to another screen.
|
|
||||||
*/
|
|
||||||
SInt32 getJumpZoneSize() const;
|
|
||||||
|
|
||||||
//! Get screen shape
|
|
||||||
/*!
|
|
||||||
Return the position of the upper-left corner of the screen in \c x and
|
|
||||||
\c y and the size of the screen in \c width and \c height.
|
|
||||||
*/
|
|
||||||
virtual void getShape(SInt32& x, SInt32& y,
|
|
||||||
SInt32& width, SInt32& height) const;
|
|
||||||
|
|
||||||
//! Get cursor position
|
|
||||||
/*!
|
|
||||||
Return the current position of the cursor in \c x,y.
|
|
||||||
*/
|
|
||||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
|
||||||
|
|
||||||
//! Get screen
|
|
||||||
/*!
|
|
||||||
Return the platform dependent screen.
|
|
||||||
*/
|
|
||||||
virtual IScreen* getScreen() const = 0;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef UInt8 KeyState;
|
|
||||||
typedef UInt32 SysKeyID;
|
|
||||||
enum EKeyState { kDown = 0x01, kToggled = 0x80 };
|
|
||||||
enum EKeyAction { kPress, kRelease, kRepeat };
|
|
||||||
class Keystroke {
|
|
||||||
public:
|
|
||||||
SysKeyID m_sysKeyID;
|
|
||||||
bool m_press;
|
|
||||||
bool m_repeat;
|
|
||||||
};
|
|
||||||
typedef std::vector<Keystroke> Keystrokes;
|
|
||||||
typedef std::map<KeyButton, SysKeyID> ServerKeyMap;
|
|
||||||
|
|
||||||
void updateKeys();
|
|
||||||
void releaseKeys();
|
|
||||||
void doKeystrokes(const Keystrokes&, SInt32 count);
|
|
||||||
bool isKeyDown(SysKeyID) const;
|
|
||||||
bool isKeyToggled(SysKeyID) const;
|
|
||||||
bool isKeyHalfDuplex(KeyID) const;
|
|
||||||
|
|
||||||
//! Pre-mainLoop() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to mainLoop(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreMainLoop();
|
|
||||||
|
|
||||||
//! Post-mainLoop() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from mainLoop(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostMainLoop();
|
|
||||||
|
|
||||||
//! Pre-open() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to open(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreOpen();
|
|
||||||
|
|
||||||
//! Post-open() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from open() iff the open was successful. Default
|
|
||||||
does nothing. May throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostOpen();
|
|
||||||
|
|
||||||
//! Pre-close() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to close(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreClose();
|
|
||||||
|
|
||||||
//! Post-close() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from close(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostClose();
|
|
||||||
|
|
||||||
//! Pre-enter() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to enter() after desktop synchronization. Override
|
|
||||||
to perform platform specific operations. Default does nothing. May
|
|
||||||
\b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreEnter();
|
|
||||||
|
|
||||||
//! Post-enter() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from enter(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostEnter();
|
|
||||||
|
|
||||||
//! Pre-leave() hook
|
|
||||||
/*!
|
|
||||||
Called on entry to leave() after desktop synchronization. Override
|
|
||||||
to perform platform specific operations. Default does nothing. May
|
|
||||||
\b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPreLeave();
|
|
||||||
|
|
||||||
//! Post-leave() hook
|
|
||||||
/*!
|
|
||||||
Called on exit from leave(). Override to perform platform specific
|
|
||||||
operations. Default does nothing. May \b not throw.
|
|
||||||
*/
|
|
||||||
virtual void onPostLeave();
|
|
||||||
|
|
||||||
//! Create window
|
|
||||||
/*!
|
|
||||||
Called to create the window. This window is generally used to
|
|
||||||
receive events and hide the cursor.
|
|
||||||
*/
|
|
||||||
virtual void createWindow() = 0;
|
|
||||||
|
|
||||||
//! Destroy window
|
|
||||||
/*!
|
|
||||||
Called to destroy the window created by createWindow().
|
|
||||||
*/
|
|
||||||
virtual void destroyWindow() = 0;
|
|
||||||
|
|
||||||
//! Show window
|
|
||||||
/*!
|
|
||||||
Called when the user navigates off this secondary screen. It needn't
|
|
||||||
actually show the window created by createWindow() but it must move
|
|
||||||
the cursor to x,y, hide it, and clean up event synthesis.
|
|
||||||
*/
|
|
||||||
virtual void showWindow(SInt32 x, SInt32 y) = 0;
|
|
||||||
|
|
||||||
//! Hide window
|
|
||||||
/*!
|
|
||||||
Called when the user navigates to this secondary screen. It should
|
|
||||||
hide the window (if shown), show the cursor, and prepare to synthesize
|
|
||||||
input events.
|
|
||||||
*/
|
|
||||||
virtual void hideWindow() = 0;
|
|
||||||
|
|
||||||
//! Synchronize key state
|
|
||||||
/*!
|
|
||||||
Save the current keyboard state. Normally a screen will save
|
|
||||||
the keyboard state in this method and use this shadow state,
|
|
||||||
available through isKeyDown() and getKeyState(), when
|
|
||||||
synthesizing events.
|
|
||||||
*/
|
|
||||||
virtual void updateKeys(KeyState* sysKeyStates) = 0;
|
|
||||||
|
|
||||||
//! Get modifier key state
|
|
||||||
/*!
|
|
||||||
Return the current keyboard modifier state.
|
|
||||||
*/
|
|
||||||
virtual KeyModifierMask getModifiers() const = 0;
|
|
||||||
|
|
||||||
//! Synchronize toggle key state
|
|
||||||
/*!
|
|
||||||
Toggles modifiers that don't match the given state so that they do.
|
|
||||||
*/
|
|
||||||
void setToggleState(KeyModifierMask);
|
|
||||||
|
|
||||||
virtual SysKeyID getUnhanded(SysKeyID) const;
|
|
||||||
virtual SysKeyID getOtherHanded(SysKeyID) const;
|
|
||||||
virtual bool isAutoRepeating(SysKeyID) const = 0;
|
|
||||||
virtual KeyModifierMask getModifierKeyMask(SysKeyID) const = 0;
|
|
||||||
virtual bool isModifierActive(SysKeyID) const = 0;
|
|
||||||
virtual SysKeyID getToggleSysKey(KeyID keyID) const = 0;
|
|
||||||
virtual bool synthesizeCtrlAltDel(EKeyAction);
|
|
||||||
virtual void sync() const;
|
|
||||||
virtual void flush();
|
|
||||||
|
|
||||||
virtual KeyModifierMask
|
|
||||||
mapKey(Keystrokes&, SysKeyID& sysKeyID, KeyID,
|
|
||||||
KeyModifierMask currentMask,
|
|
||||||
KeyModifierMask desiredMask, EKeyAction) const = 0;
|
|
||||||
virtual void fakeKeyEvent(SysKeyID, bool press) const = 0;
|
|
||||||
virtual void fakeMouseButton(ButtonID, bool press) const = 0;
|
|
||||||
|
|
||||||
//! Warp cursor
|
|
||||||
/*!
|
|
||||||
Warp the cursor to the absolute coordinates \c x,y.
|
|
||||||
*/
|
|
||||||
virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0;
|
|
||||||
|
|
||||||
virtual void fakeMouseWheel(SInt32 delta) const = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void toggleKey(KeyID, KeyModifierMask);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CMutex m_mutex;
|
|
||||||
|
|
||||||
// true if ready for remote control
|
|
||||||
bool m_remoteReady;
|
|
||||||
|
|
||||||
// m_active is true if this screen has been entered
|
|
||||||
bool m_active;
|
|
||||||
|
|
||||||
// true if screen saver should be synchronized to server
|
|
||||||
bool m_screenSaverSync;
|
|
||||||
|
|
||||||
// map server key buttons to local system keys
|
|
||||||
ServerKeyMap m_serverKeyMap;
|
|
||||||
|
|
||||||
// system key states as set by us or the user
|
|
||||||
KeyState m_keys[256];
|
|
||||||
|
|
||||||
// system key states as set by us
|
|
||||||
KeyState m_fakeKeys[256];
|
|
||||||
|
|
||||||
// current active modifiers
|
|
||||||
// XXX -- subclasses still have and use this
|
|
||||||
KeyModifierMask m_mask;
|
|
||||||
|
|
||||||
// the toggle key state when this screen was last entered
|
|
||||||
KeyModifierMask m_toggleKeys;
|
|
||||||
|
|
||||||
// note toggle keys that toggles on up/down (false) or on
|
|
||||||
// transition (true)
|
|
||||||
bool m_numLockHalfDuplex;
|
|
||||||
bool m_capsLockHalfDuplex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IKEYSTATE_H
|
||||||
|
#define IKEYSTATE_H
|
||||||
|
|
||||||
|
#include "IInterface.h"
|
||||||
|
#include "KeyTypes.h"
|
||||||
|
#include "CString.h"
|
||||||
|
#include "stdvector.h"
|
||||||
|
|
||||||
|
class IKeyState : public IInterface {
|
||||||
|
public:
|
||||||
|
class Keystroke {
|
||||||
|
public:
|
||||||
|
KeyButton m_key;
|
||||||
|
bool m_press;
|
||||||
|
bool m_repeat;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Keystroke> Keystrokes;
|
||||||
|
typedef std::vector<KeyButton> KeyButtons;
|
||||||
|
|
||||||
|
//! @name manipulators
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Update the key state
|
||||||
|
/*!
|
||||||
|
Causes the key state to get updated to reflect the physical keyboard
|
||||||
|
state and current keyboard mapping.
|
||||||
|
*/
|
||||||
|
virtual void updateKeys() = 0;
|
||||||
|
|
||||||
|
//! Release fake pressed keys
|
||||||
|
/*!
|
||||||
|
Send fake key events to release keys that aren't physically pressed
|
||||||
|
but are logically pressed.
|
||||||
|
*/
|
||||||
|
virtual void releaseKeys() = 0;
|
||||||
|
|
||||||
|
//! Mark key as being down
|
||||||
|
/*!
|
||||||
|
Sets the state of \c key to down.
|
||||||
|
*/
|
||||||
|
virtual void setKeyDown(KeyButton key) = 0;
|
||||||
|
|
||||||
|
//! Mark modifier as being toggled on
|
||||||
|
/*!
|
||||||
|
Sets the state of the keys for the given (single) modifier to be
|
||||||
|
toggled on.
|
||||||
|
*/
|
||||||
|
virtual void setToggled(KeyModifierMask) = 0;
|
||||||
|
|
||||||
|
//! Add keys for modifier
|
||||||
|
/*!
|
||||||
|
Sets the keys that are mapped to the given (single) modifier. For
|
||||||
|
example, if buttons 5 and 23 were mapped to KeyModifierShift (perhaps
|
||||||
|
as left and right shift keys) then the mask would be KeyModifierShift
|
||||||
|
and \c keys would contain 5 and 23. A modifier with no keys is
|
||||||
|
ignored. All keys must be valid (not zero). \c keys may be modified
|
||||||
|
by the call.
|
||||||
|
*/
|
||||||
|
virtual void addModifier(KeyModifierMask, KeyButtons& keys) = 0;
|
||||||
|
|
||||||
|
//! Set toggle key state
|
||||||
|
/*!
|
||||||
|
Update the local toggle key state to match the given state.
|
||||||
|
*/
|
||||||
|
virtual void setToggleState(KeyModifierMask) = 0;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Test if any key is down
|
||||||
|
/*!
|
||||||
|
If any key is down then returns one of those keys. Otherwise returns 0.
|
||||||
|
*/
|
||||||
|
virtual KeyButton isAnyKeyDown() const = 0;
|
||||||
|
|
||||||
|
//! Test if key is pressed
|
||||||
|
/*!
|
||||||
|
Returns true iff the given key is down. Half-duplex toggles
|
||||||
|
should always return false.
|
||||||
|
*/
|
||||||
|
virtual bool isKeyDown(KeyButton) const = 0;
|
||||||
|
|
||||||
|
//! Test if modifier is a toggle
|
||||||
|
/*!
|
||||||
|
Returns true iff the given (single) modifier is a toggle.
|
||||||
|
*/
|
||||||
|
virtual bool isToggle(KeyModifierMask) const = 0;
|
||||||
|
|
||||||
|
//! Test if modifier is half-duplex
|
||||||
|
/*!
|
||||||
|
Returns true iff the given (single) modifier is a half-duplex
|
||||||
|
toggle key.
|
||||||
|
*/
|
||||||
|
virtual bool isHalfDuplex(KeyModifierMask) const = 0;
|
||||||
|
|
||||||
|
//! Test if modifier is active
|
||||||
|
/*!
|
||||||
|
Returns true iff the given (single) modifier is currently active.
|
||||||
|
*/
|
||||||
|
virtual bool isModifierActive(KeyModifierMask) const = 0;
|
||||||
|
|
||||||
|
//! Get the active modifiers
|
||||||
|
/*!
|
||||||
|
Returns the modifiers that are currently active.
|
||||||
|
*/
|
||||||
|
virtual KeyModifierMask
|
||||||
|
getActiveModifiers() const = 0;
|
||||||
|
|
||||||
|
//! Get key events to change modifier state
|
||||||
|
/*!
|
||||||
|
Retrieves the key events necessary to activate (\c desireActive is true)
|
||||||
|
or deactivate (\c desireActive is false) the modifier given by \c mask
|
||||||
|
by pushing them onto the back of \c keys. \c mask must specify exactly
|
||||||
|
one modifier. \c undo receives the key events necessary to restore the
|
||||||
|
modifier's previous state. They're pushed onto \c undo in the reverse
|
||||||
|
order they should be executed. Returns true if the modifier can be
|
||||||
|
adjusted, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool mapModifier(Keystrokes& keys, Keystrokes& undo,
|
||||||
|
KeyModifierMask mask, bool desireActive) const = 0;
|
||||||
|
|
||||||
|
//! Get modifier mask for key
|
||||||
|
/*!
|
||||||
|
Returns the modifier mask for \c key. If \c key is not a modifier
|
||||||
|
key then returns 0.
|
||||||
|
*/
|
||||||
|
virtual KeyModifierMask
|
||||||
|
getMaskForKey(KeyButton) const = 0;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef UInt8 KeyState;
|
||||||
|
enum EKeyState {
|
||||||
|
kDown = 0x01, //!< Key is down
|
||||||
|
kToggled = 0x80 //!< Key is toggled on
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,21 +12,24 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ISCREEN_H
|
#ifndef IPLATFORMSCREEN_H
|
||||||
#define ISCREEN_H
|
#define IPLATFORMSCREEN_H
|
||||||
|
|
||||||
#include "IInterface.h"
|
#include "IPrimaryScreen.h"
|
||||||
|
#include "ISecondaryScreen.h"
|
||||||
#include "ClipboardTypes.h"
|
#include "ClipboardTypes.h"
|
||||||
|
#include "OptionTypes.h"
|
||||||
|
|
||||||
class IClipboard;
|
class IClipboard;
|
||||||
|
class IKeyState;
|
||||||
|
|
||||||
//! Screen interface
|
//! Screen interface
|
||||||
/*!
|
/*!
|
||||||
This interface defines the methods common to all platform dependent
|
This interface defines the methods common to all platform dependent
|
||||||
screen implementations that are use by both primary and secondary
|
screen implementations that are used by both primary and secondary
|
||||||
screens.
|
screens.
|
||||||
*/
|
*/
|
||||||
class IScreen : public IInterface {
|
class IPlatformScreen : public IPrimaryScreen, public ISecondaryScreen {
|
||||||
public:
|
public:
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
//@{
|
//@{
|
||||||
|
@ -37,7 +40,29 @@ public:
|
||||||
if the screen cannot be opened but retrying later may succeed.
|
if the screen cannot be opened but retrying later may succeed.
|
||||||
Otherwise throw some other XScreenOpenFailure exception.
|
Otherwise throw some other XScreenOpenFailure exception.
|
||||||
*/
|
*/
|
||||||
virtual void open() = 0;
|
virtual void open(IKeyState*) = 0;
|
||||||
|
|
||||||
|
//! Close screen
|
||||||
|
/*!
|
||||||
|
Called to close the screen. close() should quietly ignore calls
|
||||||
|
that don't have a matching successful call to open().
|
||||||
|
*/
|
||||||
|
virtual void close() = 0;
|
||||||
|
|
||||||
|
//! Enable screen
|
||||||
|
/*!
|
||||||
|
Enable the screen, preparing it to report system and user events.
|
||||||
|
For a secondary screen it also means preparing to synthesize events
|
||||||
|
and hiding the cursor.
|
||||||
|
*/
|
||||||
|
virtual void enable() = 0;
|
||||||
|
|
||||||
|
//! Disable screen
|
||||||
|
/*!
|
||||||
|
Undoes the operations in enable() and events should no longer
|
||||||
|
be reported.
|
||||||
|
*/
|
||||||
|
virtual void disable() = 0;
|
||||||
|
|
||||||
//! Run event loop
|
//! Run event loop
|
||||||
/*!
|
/*!
|
||||||
|
@ -54,12 +79,20 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void exitMainLoop() = 0;
|
virtual void exitMainLoop() = 0;
|
||||||
|
|
||||||
//! Close screen
|
//! Enter screen
|
||||||
/*!
|
/*!
|
||||||
Called to close the screen. close() should quietly ignore calls
|
Called when the user navigates to this screen.
|
||||||
that don't have a matching successful call to open().
|
|
||||||
*/
|
*/
|
||||||
virtual void close() = 0;
|
virtual void enter() = 0;
|
||||||
|
|
||||||
|
//! Leave screen
|
||||||
|
/*!
|
||||||
|
Called when the user navigates off the screen. Returns true on
|
||||||
|
success, false on failure. A typical reason for failure is being
|
||||||
|
unable to install the keyboard and mouse snoopers on a primary
|
||||||
|
screen. Secondary screens should not fail.
|
||||||
|
*/
|
||||||
|
virtual bool leave() = 0;
|
||||||
|
|
||||||
//! Set clipboard
|
//! Set clipboard
|
||||||
/*!
|
/*!
|
||||||
|
@ -84,6 +117,7 @@ public:
|
||||||
it's closed. If \c notify is false then the screen saver is
|
it's closed. If \c notify is false then the screen saver is
|
||||||
disabled on open and restored on close.
|
disabled on open and restored on close.
|
||||||
*/
|
*/
|
||||||
|
// XXX -- pass an interface pointer, not a notify flag
|
||||||
virtual void openScreensaver(bool notify) = 0;
|
virtual void openScreensaver(bool notify) = 0;
|
||||||
|
|
||||||
//! Close screen saver
|
//! Close screen saver
|
||||||
|
@ -101,20 +135,35 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void screensaver(bool activate) = 0;
|
virtual void screensaver(bool activate) = 0;
|
||||||
|
|
||||||
//! Attach to desktop
|
//! Notify of options changes
|
||||||
/*!
|
/*!
|
||||||
Called to ensure that this thread is attached to the visible desktop.
|
Reset all options to their default values.
|
||||||
This is mainly intended for microsoft windows which has an artificial
|
|
||||||
distinction between desktops where a thread cannot interact with the
|
|
||||||
visible desktop unless the thread is attached to that desktop. Since
|
|
||||||
it doesn't report when the visible desktop changes we must poll.
|
|
||||||
*/
|
*/
|
||||||
virtual void syncDesktop() = 0;
|
virtual void resetOptions() = 0;
|
||||||
|
|
||||||
|
//! Notify of options changes
|
||||||
|
/*!
|
||||||
|
Set options to given values. Ignore unknown options and don't
|
||||||
|
modify options that aren't given in \c options.
|
||||||
|
*/
|
||||||
|
virtual void setOptions(const COptionsList& options) = 0;
|
||||||
|
|
||||||
|
//! Get keyboard state
|
||||||
|
/*!
|
||||||
|
Put the current keyboard state into the IKeyState passed to \c open().
|
||||||
|
*/
|
||||||
|
virtual void updateKeys() = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
//! Test if is primary screen
|
||||||
|
/*!
|
||||||
|
Return true iff this screen is a primary screen.
|
||||||
|
*/
|
||||||
|
virtual bool isPrimary() const = 0;
|
||||||
|
|
||||||
//! Get clipboard
|
//! Get clipboard
|
||||||
/*!
|
/*!
|
||||||
Save the contents of the clipboard indicated by \c id and return
|
Save the contents of the clipboard indicated by \c id and return
|
||||||
|
@ -136,15 +185,26 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
||||||
|
|
||||||
//! Get cursor center position
|
|
||||||
/*!
|
|
||||||
Return the cursor center position which is where we park the
|
|
||||||
cursor to compute cursor motion deltas and should be far from
|
|
||||||
the edges of the screen, typically the center.
|
|
||||||
*/
|
|
||||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
|
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
// IPrimaryScreen overrides
|
||||||
|
virtual void reconfigure(UInt32 activeSides) = 0;
|
||||||
|
virtual void warpCursor(SInt32 x, SInt32 y) = 0;
|
||||||
|
virtual UInt32 addOneShotTimer(double timeout) = 0;
|
||||||
|
virtual SInt32 getJumpZoneSize() const = 0;
|
||||||
|
virtual bool isAnyMouseButtonDown() const = 0;
|
||||||
|
virtual const char* getKeyName(KeyButton) const = 0;
|
||||||
|
|
||||||
|
// ISecondaryScreen overrides
|
||||||
|
virtual void fakeKeyEvent(KeyButton id, bool press) const = 0;
|
||||||
|
virtual bool fakeCtrlAltDel() const = 0;
|
||||||
|
virtual void fakeMouseButton(ButtonID id, bool press) const = 0;
|
||||||
|
virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0;
|
||||||
|
virtual void fakeMouseWheel(SInt32 delta) const = 0;
|
||||||
|
virtual KeyButton mapKey(IKeyState::Keystrokes&,
|
||||||
|
const IKeyState& keyState, KeyID id,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IPRIMARYSCREEN_H
|
||||||
|
#define IPRIMARYSCREEN_H
|
||||||
|
|
||||||
|
#include "IInterface.h"
|
||||||
|
#include "IKeyState.h"
|
||||||
|
|
||||||
|
//! Primary screen interface
|
||||||
|
/*!
|
||||||
|
This interface defines the methods common to all platform dependent
|
||||||
|
primary screen implementations.
|
||||||
|
*/
|
||||||
|
class IPrimaryScreen : public IInterface {
|
||||||
|
public:
|
||||||
|
// XXX -- may need an interface for sending events
|
||||||
|
//! @name manipulators
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Update configuration
|
||||||
|
/*!
|
||||||
|
This is called when the configuration has changed. \c activeSides
|
||||||
|
is a bitmask of EDirectionMask indicating which sides of the
|
||||||
|
primary screen are linked to clients. Override to handle the
|
||||||
|
possible change in jump zones.
|
||||||
|
*/
|
||||||
|
virtual void reconfigure(UInt32 activeSides) = 0;
|
||||||
|
|
||||||
|
//! Warp cursor
|
||||||
|
/*!
|
||||||
|
Warp the cursor to the absolute coordinates \c x,y. Also
|
||||||
|
discard input events up to and including the warp before
|
||||||
|
returning.
|
||||||
|
*/
|
||||||
|
virtual void warpCursor(SInt32 x, SInt32 y) = 0;
|
||||||
|
|
||||||
|
//! Install a one-shot timer
|
||||||
|
/*!
|
||||||
|
Installs a one-shot timer for \c timeout seconds and returns the
|
||||||
|
id of the timer.
|
||||||
|
*/
|
||||||
|
// XXX -- need to specify the receiver of the event. or we should
|
||||||
|
// pass a job. need a method to remove the timer?
|
||||||
|
virtual UInt32 addOneShotTimer(double timeout) = 0;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Get jump zone size
|
||||||
|
/*!
|
||||||
|
Return the jump zone size, the size of the regions on the edges of
|
||||||
|
the screen that cause the cursor to jump to another screen.
|
||||||
|
*/
|
||||||
|
virtual SInt32 getJumpZoneSize() const = 0;
|
||||||
|
|
||||||
|
//! Test if mouse is pressed
|
||||||
|
/*!
|
||||||
|
Return true if any mouse button is currently pressed.
|
||||||
|
*/
|
||||||
|
virtual bool isAnyMouseButtonDown() const = 0;
|
||||||
|
|
||||||
|
//! Get name of key
|
||||||
|
/*!
|
||||||
|
Return a string describing the given key.
|
||||||
|
*/
|
||||||
|
virtual const char* getKeyName(KeyButton) const = 0;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ISCREENEVENTHANDLER_H
|
|
||||||
#define ISCREENEVENTHANDLER_H
|
|
||||||
|
|
||||||
#include "IInterface.h"
|
|
||||||
|
|
||||||
// the platform screen should define this
|
|
||||||
class CEvent;
|
|
||||||
|
|
||||||
class IScreen;
|
|
||||||
|
|
||||||
//! Screen event handler interface
|
|
||||||
/*!
|
|
||||||
This is the interface through which IScreen sends notification of events.
|
|
||||||
Each platform will derive two types from IScreenEventHandler, one
|
|
||||||
for handling events on the primary screen and one for the
|
|
||||||
secondary screen. The header file with the IScreen subclass for
|
|
||||||
each platform should define the CEvent type, which depends on the
|
|
||||||
type of native events for that platform.
|
|
||||||
*/
|
|
||||||
class IScreenEventHandler : public IInterface {
|
|
||||||
public:
|
|
||||||
//! @name manipulators
|
|
||||||
//@{
|
|
||||||
|
|
||||||
//! Notify of screen saver change
|
|
||||||
/*!
|
|
||||||
Called when the screensaver is activated or deactivated.
|
|
||||||
*/
|
|
||||||
virtual void onScreensaver(bool activated) = 0;
|
|
||||||
|
|
||||||
//! Event filtering
|
|
||||||
/*!
|
|
||||||
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) = 0;
|
|
||||||
|
|
||||||
//! Event handling
|
|
||||||
/*!
|
|
||||||
Called to handle an event. Iff the event was handled return true and
|
|
||||||
store the result, if any, in event->m_result, which defaults to zero.
|
|
||||||
*/
|
|
||||||
virtual bool onEvent(CEvent* event) = 0;
|
|
||||||
|
|
||||||
//! Notify of one-shot timer expiration
|
|
||||||
/*!
|
|
||||||
Called when a one-shot timer expires.
|
|
||||||
*/
|
|
||||||
virtual void onOneShotTimerExpired(UInt32 id) = 0;
|
|
||||||
|
|
||||||
//@}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* synergy -- mouse and keyboard sharing utility
|
* synergy -- mouse and keyboard sharing utility
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
*
|
*
|
||||||
* This package is free software; you can redistribute it and/or
|
* This package is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -12,27 +12,29 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef IPRIMARYSCREENFACTORY_H
|
#ifndef ISCREENFACTORY_H
|
||||||
#define IPRIMARYSCREENFACTORY_H
|
#define ISCREENFACTORY_H
|
||||||
|
|
||||||
#include "IInterface.h"
|
#include "IInterface.h"
|
||||||
|
|
||||||
class CPrimaryScreen;
|
|
||||||
class IPrimaryScreenReceiver;
|
class IPrimaryScreenReceiver;
|
||||||
|
class IPlatformScreen;
|
||||||
class IScreenReceiver;
|
class IScreenReceiver;
|
||||||
|
|
||||||
//! Primary screen factory interface
|
//! Primary screen factory interface
|
||||||
/*!
|
/*!
|
||||||
This interface provides factory methods to create primary screens.
|
This interface provides factory methods to create primary and
|
||||||
|
secondary screens.
|
||||||
*/
|
*/
|
||||||
class IPrimaryScreenFactory : public IInterface {
|
class IScreenFactory : public IInterface {
|
||||||
public:
|
public:
|
||||||
//! Create screen
|
//! Create screen
|
||||||
/*!
|
/*!
|
||||||
Create and return a primary screen. The caller must delete the
|
Create and return a screen. The caller must delete the returned
|
||||||
returned object.
|
object. The screen is a primary screen iff the IPrimaryScreenReceiver
|
||||||
|
is not NULL.
|
||||||
*/
|
*/
|
||||||
virtual CPrimaryScreen*
|
virtual IPlatformScreen*
|
||||||
create(IScreenReceiver*, IPrimaryScreenReceiver*) = 0;
|
create(IScreenReceiver*, IPrimaryScreenReceiver*) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2003 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ISECONDARYSCREEN_H
|
||||||
|
#define ISECONDARYSCREEN_H
|
||||||
|
|
||||||
|
#include "IInterface.h"
|
||||||
|
#include "IKeyState.h"
|
||||||
|
#include "MouseTypes.h"
|
||||||
|
|
||||||
|
//! Secondary screen interface
|
||||||
|
/*!
|
||||||
|
This interface defines the methods common to all platform dependent
|
||||||
|
secondary screen implementations.
|
||||||
|
*/
|
||||||
|
class ISecondaryScreen : public IInterface {
|
||||||
|
public:
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Fake key press/release
|
||||||
|
/*!
|
||||||
|
Synthesize a press or release of key \c id.
|
||||||
|
*/
|
||||||
|
virtual void fakeKeyEvent(KeyButton id, bool press) const = 0;
|
||||||
|
|
||||||
|
//! Fake ctrl+alt+del
|
||||||
|
/*!
|
||||||
|
Synthesize a press of ctrl+alt+del. Return true if processing is
|
||||||
|
complete and false if normal key processing should continue.
|
||||||
|
*/
|
||||||
|
virtual bool fakeCtrlAltDel() const = 0;
|
||||||
|
|
||||||
|
//! Fake mouse press/release
|
||||||
|
/*!
|
||||||
|
Synthesize a press or release of mouse button \c id.
|
||||||
|
*/
|
||||||
|
virtual void fakeMouseButton(ButtonID id, bool press) const = 0;
|
||||||
|
|
||||||
|
//! Fake mouse move
|
||||||
|
/*!
|
||||||
|
Synthesize a mouse move to the absolute coordinates \c x,y.
|
||||||
|
*/
|
||||||
|
virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0;
|
||||||
|
|
||||||
|
//! Fake mouse wheel
|
||||||
|
/*!
|
||||||
|
Synthesize a mouse wheel event of amount \c delta.
|
||||||
|
*/
|
||||||
|
virtual void fakeMouseWheel(SInt32 delta) const = 0;
|
||||||
|
|
||||||
|
//! Map key press/repeat to keystrokes
|
||||||
|
/*!
|
||||||
|
Convert a press/repeat of key \c id with the modifiers as given
|
||||||
|
in \c desiredMask into the keystrokes necessary to synthesize
|
||||||
|
that key event. This may expand into multiple keys due to modifiers
|
||||||
|
that don't match the current modifier state from \c keyState, or to
|
||||||
|
needing to compose a character using dead key, or to other reasons.
|
||||||
|
Return the platform specific code of the key being pressed. If \c id
|
||||||
|
cannot be mapped or if \c isAutoRepeat is true and the key does not
|
||||||
|
auto-repeat then return 0.
|
||||||
|
*/
|
||||||
|
virtual KeyButton mapKey(IKeyState::Keystrokes&,
|
||||||
|
const IKeyState& keyState, KeyID id,
|
||||||
|
KeyModifierMask desiredMask,
|
||||||
|
bool isAutoRepeat) const = 0;
|
||||||
|
|
||||||
|
//@}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* synergy -- mouse and keyboard sharing utility
|
|
||||||
* Copyright (C) 2002 Chris Schoeneman
|
|
||||||
*
|
|
||||||
* This package is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* found in the file COPYING that should have accompanied this file.
|
|
||||||
*
|
|
||||||
* This package is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ISECONDARYSCREENFACTORY_H
|
|
||||||
#define ISECONDARYSCREENFACTORY_H
|
|
||||||
|
|
||||||
#include "IInterface.h"
|
|
||||||
|
|
||||||
class CSecondaryScreen;
|
|
||||||
class IScreenReceiver;
|
|
||||||
|
|
||||||
//! Secondary screen factory interface
|
|
||||||
/*!
|
|
||||||
This interface provides factory methods to create secondary screens.
|
|
||||||
*/
|
|
||||||
class ISecondaryScreenFactory : public IInterface {
|
|
||||||
public:
|
|
||||||
//! Create screen
|
|
||||||
/*!
|
|
||||||
Create and return a secondary screen. The caller must delete the
|
|
||||||
returned object.
|
|
||||||
*/
|
|
||||||
virtual CSecondaryScreen*
|
|
||||||
create(IScreenReceiver*) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -28,27 +28,26 @@ libsynergy_a_SOURCES = \
|
||||||
CClipboard.cpp \
|
CClipboard.cpp \
|
||||||
CInputPacketStream.cpp \
|
CInputPacketStream.cpp \
|
||||||
COutputPacketStream.cpp \
|
COutputPacketStream.cpp \
|
||||||
CPrimaryScreen.cpp \
|
|
||||||
CProtocolUtil.cpp \
|
CProtocolUtil.cpp \
|
||||||
CSecondaryScreen.cpp \
|
CScreen.cpp \
|
||||||
XScreen.cpp \
|
XScreen.cpp \
|
||||||
XSynergy.cpp \
|
XSynergy.cpp \
|
||||||
CClipboard.h \
|
CClipboard.h \
|
||||||
CInputPacketStream.h \
|
CInputPacketStream.h \
|
||||||
COutputPacketStream.h \
|
COutputPacketStream.h \
|
||||||
CPrimaryScreen.h \
|
|
||||||
CProtocolUtil.h \
|
CProtocolUtil.h \
|
||||||
CSecondaryScreen.h \
|
CScreen.h \
|
||||||
ClipboardTypes.h \
|
ClipboardTypes.h \
|
||||||
IClient.h \
|
IClient.h \
|
||||||
IClipboard.h \
|
IClipboard.h \
|
||||||
IPrimaryScreenFactory.h \
|
IKeyState.h \
|
||||||
|
IPlatformScreen.h \
|
||||||
|
IPrimaryScreen.h \
|
||||||
IPrimaryScreenReceiver.h \
|
IPrimaryScreenReceiver.h \
|
||||||
IScreen.h \
|
IScreenFactory.h \
|
||||||
IScreenEventHandler.h \
|
|
||||||
IScreenReceiver.h \
|
IScreenReceiver.h \
|
||||||
IScreenSaver.h \
|
IScreenSaver.h \
|
||||||
ISecondaryScreenFactory.h \
|
ISecondaryScreen.h \
|
||||||
IServer.h \
|
IServer.h \
|
||||||
KeyTypes.h \
|
KeyTypes.h \
|
||||||
MouseTypes.h \
|
MouseTypes.h \
|
||||||
|
|
|
@ -99,15 +99,11 @@ SOURCE=.\COutputPacketStream.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CPrimaryScreen.cpp
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\CProtocolUtil.cpp
|
SOURCE=.\CProtocolUtil.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CSecondaryScreen.cpp
|
SOURCE=.\CScreen.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
@ -139,15 +135,11 @@ SOURCE=.\COutputPacketStream.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CPrimaryScreen.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\CProtocolUtil.h
|
SOURCE=.\CProtocolUtil.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\CSecondaryScreen.h
|
SOURCE=.\CScreen.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
@ -159,7 +151,15 @@ SOURCE=.\IClipboard.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\IPrimaryScreenFactory.h
|
SOURCE=.\IKeyState.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\IPlatformScreen.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\IPrimaryScreen.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
@ -167,11 +167,7 @@ SOURCE=.\IPrimaryScreenReceiver.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\IScreen.h
|
SOURCE=.\IScreenFactory.h
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\IScreenEventHandler.h
|
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
@ -183,7 +179,7 @@ SOURCE=.\IScreenSaver.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\ISecondaryScreenFactory.h
|
SOURCE=.\ISecondaryScreen.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue