Added support for per-screen options in the configuration file
and sending those options to the appropriate client screens. Currently, two options are supported: halfDuplexCapsLock and halfDuplexNumLock mark the caps lock and num lock keys, respectively, as being half-duplex.
This commit is contained in:
parent
72578b8061
commit
3fc1ddf6ce
|
@ -356,6 +356,18 @@ CClient::screensaver(bool activate)
|
|||
m_screen->screensaver(activate);
|
||||
}
|
||||
|
||||
void
|
||||
CClient::resetOptions()
|
||||
{
|
||||
m_screen->resetOptions();
|
||||
}
|
||||
|
||||
void
|
||||
CClient::setOptions(const COptionsList& options)
|
||||
{
|
||||
m_screen->setOptions(options);
|
||||
}
|
||||
|
||||
CString
|
||||
CClient::getName() const
|
||||
{
|
||||
|
|
|
@ -130,6 +130,8 @@ public:
|
|||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
virtual CString getName() const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
|
|
|
@ -214,6 +214,18 @@ CMSWindowsSecondaryScreen::mouseWheel(SInt32 delta)
|
|||
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, 0);
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsSecondaryScreen::resetOptions()
|
||||
{
|
||||
// no options
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsSecondaryScreen::setOptions(const COptionsList& /*options*/)
|
||||
{
|
||||
// no options
|
||||
}
|
||||
|
||||
IScreen*
|
||||
CMSWindowsSecondaryScreen::getScreen() const
|
||||
{
|
||||
|
|
|
@ -45,6 +45,8 @@ public:
|
|||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
virtual IScreen* getScreen() const;
|
||||
|
||||
// IMSWindowsScreenEventHandler overrides
|
||||
|
|
|
@ -87,6 +87,9 @@ CSecondaryScreen::open()
|
|||
|
||||
// subclass hook
|
||||
onPostOpen();
|
||||
|
||||
// reset options
|
||||
resetOptions();
|
||||
}
|
||||
catch (...) {
|
||||
close();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "ClipboardTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "MouseTypes.h"
|
||||
#include "OptionTypes.h"
|
||||
#include "CMutex.h"
|
||||
|
||||
class IClipboard;
|
||||
|
@ -156,6 +157,19 @@ public:
|
|||
*/
|
||||
virtual void mouseWheel(SInt32 delta) = 0;
|
||||
|
||||
//! 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;
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
|
|
@ -203,6 +203,28 @@ CXWindowsSecondaryScreen::mouseWheel(SInt32 delta)
|
|||
XSync(display, False);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::resetOptions()
|
||||
{
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::setOptions(const COptionsList& options)
|
||||
{
|
||||
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IScreen*
|
||||
CXWindowsSecondaryScreen::getScreen() const
|
||||
{
|
||||
|
@ -262,12 +284,7 @@ CXWindowsSecondaryScreen::onPreOpen()
|
|||
void
|
||||
CXWindowsSecondaryScreen::onPostOpen()
|
||||
{
|
||||
// check for peculiarities
|
||||
// FIXME -- may have to get these from some database
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_numLockHalfDuplex = true;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
assert(m_window != None);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 x, SInt32 y);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
virtual IScreen* getScreen() const;
|
||||
|
||||
// IScreenEventHandler overrides
|
||||
|
|
|
@ -75,6 +75,8 @@ public:
|
|||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
|
||||
virtual void mouseWheel(SInt32 delta) = 0;
|
||||
virtual void screensaver(bool activate) = 0;
|
||||
virtual void resetOptions() = 0;
|
||||
virtual void setOptions(const COptionsList& options) = 0;
|
||||
virtual CString getName() const;
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
|
|
|
@ -252,6 +252,20 @@ CClientProxy1_0::screensaver(bool on)
|
|||
CProtocolUtil::writef(getOutputStream(), kMsgCScreenSaver, on ? 1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::resetOptions()
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send reset options to \"%s\"", getName().c_str()));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCResetOptions);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::setOptions(const COptionsList& options)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send set options to \"%s\" size=%d", getName().c_str(), options.size()));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDSetOptions, &options);
|
||||
}
|
||||
|
||||
SInt32
|
||||
CClientProxy1_0::getJumpZoneSize() const
|
||||
{
|
||||
|
|
|
@ -46,6 +46,8 @@ public:
|
|||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
|
|
|
@ -240,6 +240,34 @@ CConfig::setHTTPAddress(const CNetworkAddress& addr)
|
|||
m_httpAddress = addr;
|
||||
}
|
||||
|
||||
bool
|
||||
CConfig::addOption(const CString& name, UInt32 option, SInt32 value)
|
||||
{
|
||||
// find cell
|
||||
CCellMap::iterator index = m_map.find(name);
|
||||
if (index == m_map.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add option
|
||||
index->second.m_options.insert(std::make_pair(option, value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CConfig::removeOption(const CString& name, UInt32 option)
|
||||
{
|
||||
// find cell
|
||||
CCellMap::iterator index = m_map.find(name);
|
||||
if (index == m_map.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove option
|
||||
index->second.m_options.erase(option);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CConfig::isValidScreenName(const CString& name) const
|
||||
{
|
||||
|
@ -359,6 +387,19 @@ CConfig::getHTTPAddress() const
|
|||
return m_httpAddress;
|
||||
}
|
||||
|
||||
const CConfig::CScreenOptions*
|
||||
CConfig::getOptions(const CString& name) const
|
||||
{
|
||||
// find cell
|
||||
CCellMap::const_iterator index = m_map.find(name);
|
||||
if (index == m_map.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// return options
|
||||
return &index->second.m_options;
|
||||
}
|
||||
|
||||
bool
|
||||
CConfig::operator==(const CConfig& x) const
|
||||
{
|
||||
|
@ -438,6 +479,39 @@ CConfig::readLine(std::istream& s, CString& line)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CConfig::parseBoolean(const CString& arg)
|
||||
{
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "true"))
|
||||
return true;
|
||||
if (CStringUtil::CaselessCmp::equal(arg, "false"))
|
||||
return false;
|
||||
throw XConfigRead("invalid argument");
|
||||
}
|
||||
|
||||
const char*
|
||||
CConfig::getOptionName(OptionID id)
|
||||
{
|
||||
if (id == kOptionHalfDuplexCapsLock) {
|
||||
return "halfDuplexCapsLock";
|
||||
}
|
||||
if (id == kOptionHalfDuplexNumLock) {
|
||||
return "halfDuplexNumLock";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char*
|
||||
CConfig::getOptionValue(OptionID id, OptionValue value)
|
||||
{
|
||||
if (id == kOptionHalfDuplexCapsLock ||
|
||||
id == kOptionHalfDuplexNumLock) {
|
||||
return (value != 0) ? "true" : "false";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
CConfig::readSection(std::istream& s)
|
||||
{
|
||||
|
@ -547,7 +621,7 @@ void
|
|||
CConfig::readSectionScreens(std::istream& s)
|
||||
{
|
||||
CString line;
|
||||
CString name;
|
||||
CString screen;
|
||||
while (readLine(s, line)) {
|
||||
// check for end of section
|
||||
if (line == "end") {
|
||||
|
@ -557,25 +631,56 @@ CConfig::readSectionScreens(std::istream& s)
|
|||
// see if it's the next screen
|
||||
if (line[line.size() - 1] == ':') {
|
||||
// strip :
|
||||
name = line.substr(0, line.size() - 1);
|
||||
screen = line.substr(0, line.size() - 1);
|
||||
|
||||
// verify validity of screen name
|
||||
if (!isValidScreenName(name)) {
|
||||
if (!isValidScreenName(screen)) {
|
||||
throw XConfigRead("invalid screen name");
|
||||
}
|
||||
|
||||
// add the screen to the configuration
|
||||
if (!addScreen(name)) {
|
||||
if (!addScreen(screen)) {
|
||||
throw XConfigRead("duplicate screen name");
|
||||
}
|
||||
}
|
||||
else if (name.empty()) {
|
||||
else if (screen.empty()) {
|
||||
throw XConfigRead("argument before first screen");
|
||||
}
|
||||
else {
|
||||
// parse argument: `<name>=<value>'
|
||||
CString::size_type i = line.find_first_of(" \t=");
|
||||
if (i == 0) {
|
||||
throw XConfigRead("missing argument name");
|
||||
}
|
||||
if (i == CString::npos) {
|
||||
throw XConfigRead("missing = in argument");
|
||||
}
|
||||
CString name = line.substr(0, i);
|
||||
i = line.find_first_not_of(" \t", i);
|
||||
if (i == CString::npos || line[i] != '=') {
|
||||
throw XConfigRead("missing = in argument");
|
||||
}
|
||||
i = line.find_first_not_of(" \t", i + 1);
|
||||
CString value;
|
||||
if (i != CString::npos) {
|
||||
value = line.substr(i);
|
||||
}
|
||||
|
||||
// handle argument
|
||||
if (name == "halfDuplexCapsLock") {
|
||||
addOption(screen, kOptionHalfDuplexCapsLock,
|
||||
parseBoolean(value));
|
||||
}
|
||||
else if (name == "halfDuplexNumLock") {
|
||||
addOption(screen, kOptionHalfDuplexNumLock,
|
||||
parseBoolean(value));
|
||||
}
|
||||
else {
|
||||
// unknown argument
|
||||
throw XConfigRead("unknown argument");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw XConfigRead("unexpected end of screens section");
|
||||
}
|
||||
|
||||
|
@ -740,6 +845,19 @@ operator<<(std::ostream& s, const CConfig& config)
|
|||
for (CConfig::const_iterator screen = config.begin();
|
||||
screen != config.end(); ++screen) {
|
||||
s << "\t" << screen->c_str() << ":" << std::endl;
|
||||
const CConfig::CScreenOptions* options = config.getOptions(*screen);
|
||||
if (options != NULL && options->size() > 0) {
|
||||
for (CConfig::CScreenOptions::const_iterator
|
||||
option = options->begin();
|
||||
option != options->end(); ++option) {
|
||||
const char* name = CConfig::getOptionName(option->first);
|
||||
const char* value = CConfig::getOptionValue(option->first,
|
||||
option->second);
|
||||
if (name != NULL && value != NULL) {
|
||||
s << "\t\t" << name << " = " << value << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s << "end" << std::endl;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef CCONFIG_H
|
||||
#define CCONFIG_H
|
||||
|
||||
#include "OptionTypes.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "CNetworkAddress.h"
|
||||
#include "XBase.h"
|
||||
|
@ -45,10 +46,14 @@ comparing names. Screen names and their aliases share a
|
|||
namespace and must be unique.
|
||||
*/
|
||||
class CConfig {
|
||||
public:
|
||||
typedef std::map<OptionID, OptionValue> CScreenOptions;
|
||||
|
||||
private:
|
||||
class CCell {
|
||||
public:
|
||||
CString m_neighbor[kLastDirection - kFirstDirection + 1];
|
||||
CScreenOptions m_options;
|
||||
};
|
||||
typedef std::map<CString, CCell, CStringUtil::CaselessCmp> CCellMap;
|
||||
typedef std::map<CString, CString, CStringUtil::CaselessCmp> CNameMap;
|
||||
|
@ -175,6 +180,23 @@ public:
|
|||
*/
|
||||
void setHTTPAddress(const CNetworkAddress&);
|
||||
|
||||
//! Add a screen option
|
||||
/*!
|
||||
Adds an option and its value to the named screen. Replaces the
|
||||
existing option's value if there is one. Returns true iff \c name
|
||||
is a known screen.
|
||||
*/
|
||||
bool addOption(const CString& name,
|
||||
UInt32 option, SInt32 value);
|
||||
|
||||
//! Remove a screen option
|
||||
/*!
|
||||
Removes an option and its value from the named screen. Does
|
||||
nothing if the option doesn't exist on the screen. Returns true
|
||||
iff \c name is a known screen.
|
||||
*/
|
||||
bool removeOption(const CString& name, UInt32 option);
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
@ -227,6 +249,14 @@ public:
|
|||
//! Get the HTTP server address
|
||||
const CNetworkAddress& getHTTPAddress() const;
|
||||
|
||||
//! Get the screen options
|
||||
/*!
|
||||
Returns all the added options for the named screen. Returns NULL
|
||||
if the screen is unknown and an empty collection if there are no
|
||||
options.
|
||||
*/
|
||||
const CScreenOptions* getOptions(const CString& name) const;
|
||||
|
||||
//! Compare configurations
|
||||
bool operator==(const CConfig&) const;
|
||||
//! Compare configurations
|
||||
|
@ -254,6 +284,9 @@ public:
|
|||
|
||||
private:
|
||||
static bool readLine(std::istream&, CString&);
|
||||
static bool parseBoolean(const CString&);
|
||||
static const char* getOptionName(OptionID);
|
||||
static const char* getOptionValue(OptionID, OptionValue);
|
||||
void readSection(std::istream&);
|
||||
void readSectionNetwork(std::istream&);
|
||||
void readSectionScreens(std::istream&);
|
||||
|
|
|
@ -99,6 +99,18 @@ CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
|||
m_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsPrimaryScreen::resetOptions()
|
||||
{
|
||||
// no options
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsPrimaryScreen::setOptions(const COptionsList& /*options*/)
|
||||
{
|
||||
// no options
|
||||
}
|
||||
|
||||
KeyModifierMask
|
||||
CMSWindowsPrimaryScreen::getToggleMask() const
|
||||
{
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
// CPrimaryScreen overrides
|
||||
virtual void reconfigure(UInt32 activeSides);
|
||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
virtual KeyModifierMask getToggleMask() const;
|
||||
virtual bool isLockedToScreen() const;
|
||||
virtual IScreen* getScreen() const;
|
||||
|
|
|
@ -242,6 +242,18 @@ CPrimaryClient::screensaver(bool)
|
|||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::resetOptions()
|
||||
{
|
||||
m_screen->resetOptions();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::setOptions(const COptionsList& options)
|
||||
{
|
||||
m_screen->setOptions(options);
|
||||
}
|
||||
|
||||
CString
|
||||
CPrimaryClient::getName() const
|
||||
{
|
||||
|
|
|
@ -108,6 +108,8 @@ public:
|
|||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
virtual CString getName() const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
|
|
|
@ -90,6 +90,9 @@ CPrimaryScreen::open()
|
|||
|
||||
// subclass hook
|
||||
onPostOpen();
|
||||
|
||||
// reset options
|
||||
resetOptions();
|
||||
}
|
||||
catch (...) {
|
||||
close();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "ClipboardTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "OptionTypes.h"
|
||||
#include "CMutex.h"
|
||||
|
||||
class IClipboard;
|
||||
|
@ -115,6 +116,19 @@ public:
|
|||
*/
|
||||
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;
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "COutputPacketStream.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "CClientProxy1_0.h"
|
||||
#include "OptionTypes.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "XScreen.h"
|
||||
#include "XSynergy.h"
|
||||
|
@ -220,6 +221,8 @@ CServer::setConfig(const CConfig& config)
|
|||
m_primaryClient->reconfigure(getActivePrimarySides());
|
||||
}
|
||||
|
||||
// FIXME -- tell all (connected) clients about current options
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -830,6 +833,8 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver)
|
|||
IClient*
|
||||
CServer::getNeighbor(IClient* src, EDirection dir) const
|
||||
{
|
||||
// note -- must be locked on entry
|
||||
|
||||
assert(src != NULL);
|
||||
|
||||
CString srcName = src->getName();
|
||||
|
@ -863,6 +868,8 @@ IClient*
|
|||
CServer::getNeighbor(IClient* src,
|
||||
EDirection srcSide, SInt32& x, SInt32& y) const
|
||||
{
|
||||
// note -- must be locked on entry
|
||||
|
||||
assert(src != NULL);
|
||||
|
||||
// get the first neighbor
|
||||
|
@ -1274,6 +1281,9 @@ CServer::runClient(void* vsocket)
|
|||
CLock lock(&m_mutex);
|
||||
m_clientThreads.insert(std::make_pair(proxy->getName(),
|
||||
CThread::getCurrentThread()));
|
||||
|
||||
// send configuration options
|
||||
sendOptions(proxy);
|
||||
}
|
||||
catch (XDuplicateClient& e) {
|
||||
// client has duplicate name
|
||||
|
@ -1564,6 +1574,32 @@ CServer::processHTTPRequest(void* vsocket)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServer::sendOptions(IClient* client) const
|
||||
{
|
||||
// note -- must be locked on entry
|
||||
|
||||
// look up options for client. we're done if there aren't any.
|
||||
const CConfig::CScreenOptions* options =
|
||||
m_config.getOptions(client->getName());
|
||||
if (options == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// convert options to a more convenient form for sending
|
||||
COptionsList optionsList;
|
||||
optionsList.reserve(2 * options->size());
|
||||
for (CConfig::CScreenOptions::const_iterator index = options->begin();
|
||||
index != options->end(); ++index) {
|
||||
optionsList.push_back(index->first);
|
||||
optionsList.push_back(static_cast<UInt32>(index->second));
|
||||
}
|
||||
|
||||
// send the options
|
||||
client->resetOptions();
|
||||
client->setOptions(optionsList);
|
||||
}
|
||||
|
||||
void
|
||||
CServer::openPrimaryScreen()
|
||||
{
|
||||
|
@ -1605,8 +1641,13 @@ CServer::openPrimaryScreen()
|
|||
|
||||
// tell it about the active sides
|
||||
m_primaryClient->reconfigure(getActivePrimarySides());
|
||||
|
||||
// tell primary client about its options
|
||||
sendOptions(m_primaryClient);
|
||||
}
|
||||
catch (...) {
|
||||
// if m_active is NULL then we haven't added the connection
|
||||
// for the primary client so we don't try to remove it.
|
||||
if (m_active != NULL) {
|
||||
removeConnection(primaryName);
|
||||
}
|
||||
|
|
|
@ -197,6 +197,9 @@ private:
|
|||
IClient* getNeighbor(IClient*, EDirection,
|
||||
SInt32& x, SInt32& y) const;
|
||||
|
||||
// send screen options to \c client
|
||||
void sendOptions(IClient* client) const;
|
||||
|
||||
// open/close the primary screen
|
||||
void openPrimaryScreen();
|
||||
void closePrimaryScreen();
|
||||
|
|
|
@ -79,6 +79,28 @@ CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
|||
m_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::resetOptions()
|
||||
{
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::setOptions(const COptionsList& options)
|
||||
{
|
||||
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyModifierMask
|
||||
CXWindowsPrimaryScreen::getToggleMask() const
|
||||
{
|
||||
|
@ -385,16 +407,11 @@ CXWindowsPrimaryScreen::onPreOpen()
|
|||
void
|
||||
CXWindowsPrimaryScreen::onPostOpen()
|
||||
{
|
||||
assert(m_window != None);
|
||||
|
||||
// get cursor info
|
||||
m_screen->getCursorPos(m_x, m_y);
|
||||
m_screen->getCursorCenter(m_xCenter, m_yCenter);
|
||||
|
||||
// check for peculiarities
|
||||
// FIXME -- may have to get these from some database
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_numLockHalfDuplex = true;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -38,6 +38,8 @@ public:
|
|||
// CPrimaryScreen overrides
|
||||
virtual void reconfigure(UInt32 activeSides);
|
||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
virtual KeyModifierMask getToggleMask() const;
|
||||
virtual bool isLockedToScreen() const;
|
||||
virtual IScreen* getScreen() const;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "IInputStream.h"
|
||||
#include "IOutputStream.h"
|
||||
#include "CLog.h"
|
||||
#include "stdvector.h"
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
|
||||
|
@ -116,6 +117,56 @@ CProtocolUtil::readf(IInputStream* stream, const char* fmt, ...)
|
|||
break;
|
||||
}
|
||||
|
||||
case 'I': {
|
||||
// check for valid length
|
||||
assert(len == 1 || len == 2 || len == 4);
|
||||
|
||||
// read the vector length
|
||||
UInt8 buffer[4];
|
||||
read(stream, buffer, 4);
|
||||
UInt32 len = (static_cast<UInt32>(buffer[0]) << 24) |
|
||||
(static_cast<UInt32>(buffer[1]) << 16) |
|
||||
(static_cast<UInt32>(buffer[2]) << 8) |
|
||||
static_cast<UInt32>(buffer[3]);
|
||||
|
||||
// convert it
|
||||
void* v = va_arg(args, void*);
|
||||
switch (len) {
|
||||
case 1:
|
||||
// 1 byte integer
|
||||
for (UInt32 i = 0; i < len; ++i) {
|
||||
reinterpret_cast<std::vector<UInt8>*>(v)->push_back(
|
||||
buffer[0]);
|
||||
LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast<std::vector<UInt8>*>(v)->back(), reinterpret_cast<std::vector<UInt8>*>(v)->back()));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// 2 byte integer
|
||||
for (UInt32 i = 0; i < len; ++i) {
|
||||
reinterpret_cast<std::vector<UInt16>*>(v)->push_back(
|
||||
static_cast<UInt16>(
|
||||
(static_cast<UInt16>(buffer[0]) << 8) |
|
||||
static_cast<UInt16>(buffer[1])));
|
||||
LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast<std::vector<UInt16>*>(v)->back(), reinterpret_cast<std::vector<UInt16>*>(v)->back()));
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// 4 byte integer
|
||||
for (UInt32 i = 0; i < len; ++i) {
|
||||
reinterpret_cast<std::vector<UInt32>*>(v)->push_back(
|
||||
(static_cast<UInt32>(buffer[0]) << 24) |
|
||||
(static_cast<UInt32>(buffer[1]) << 16) |
|
||||
(static_cast<UInt32>(buffer[2]) << 8) |
|
||||
static_cast<UInt32>(buffer[3]));
|
||||
LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast<std::vector<UInt32>*>(v)->back(), reinterpret_cast<std::vector<UInt32>*>(v)->back()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
assert(len == 0);
|
||||
|
||||
|
@ -207,6 +258,24 @@ CProtocolUtil::getLength(const char* fmt, va_list args)
|
|||
(void)va_arg(args, UInt32);
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
assert(len == 1 || len == 2 || len == 4);
|
||||
switch (len) {
|
||||
case 1:
|
||||
len = (va_arg(args, std::vector<UInt8>*))->size() + 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
len = 2 * (va_arg(args, std::vector<UInt8>*))->size() + 4;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
len = 4 * (va_arg(args, std::vector<UInt8>*))->size() + 4;
|
||||
break;
|
||||
}
|
||||
(void)va_arg(args, void*);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
assert(len == 0);
|
||||
len = (va_arg(args, CString*))->size() + 4;
|
||||
|
@ -281,6 +350,52 @@ CProtocolUtil::writef(void* buffer, const char* fmt, va_list args)
|
|||
break;
|
||||
}
|
||||
|
||||
case 'I': {
|
||||
const UInt32 v = va_arg(args, UInt32);
|
||||
switch (len) {
|
||||
case 1: {
|
||||
// 1 byte integers
|
||||
const std::vector<UInt8>* list =
|
||||
va_arg(args, const std::vector<UInt8>*);
|
||||
for (UInt32 i = 0, n = list->size(); i < n; ++i) {
|
||||
*dst++ = (*list)[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
// 2 byte integers
|
||||
const std::vector<UInt16>* list =
|
||||
va_arg(args, const std::vector<UInt16>*);
|
||||
for (UInt32 i = 0, n = list->size(); i < n; ++i) {
|
||||
const UInt16 v = (*list)[i];
|
||||
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
|
||||
*dst++ = static_cast<UInt8>( v & 0xff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4: {
|
||||
// 4 byte integers
|
||||
const std::vector<UInt32>* list =
|
||||
va_arg(args, const std::vector<UInt32>*);
|
||||
for (UInt32 i = 0, n = list->size(); i < n; ++i) {
|
||||
const UInt32 v = (*list)[i];
|
||||
*dst++ = static_cast<UInt8>((v >> 24) & 0xff);
|
||||
*dst++ = static_cast<UInt8>((v >> 16) & 0xff);
|
||||
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
|
||||
*dst++ = static_cast<UInt8>( v & 0xff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0 && "invalid integer vector format length");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
assert(len == 0);
|
||||
const CString* src = va_arg(args, CString*);
|
||||
|
|
|
@ -41,6 +41,9 @@ public:
|
|||
- \%1i -- converts integer argument to 1 byte integer
|
||||
- \%2i -- converts integer argument to 2 byte integer in NBO
|
||||
- \%4i -- converts integer argument to 4 byte integer in NBO
|
||||
- \%1I -- converts std::vector<UInt8>* to 1 byte integers
|
||||
- \%2I -- converts std::vector<UInt16>* to 2 byte integers in NBO
|
||||
- \%4I -- converts std::vector<UInt32>* to 4 byte integers in NBO
|
||||
- \%s -- converts CString* to stream of bytes
|
||||
- \%S -- converts integer N and const UInt8* to stream of N bytes
|
||||
*/
|
||||
|
@ -57,6 +60,9 @@ public:
|
|||
- \%1i -- reads a 1 byte integer; argument is a SInt32* or UInt32*
|
||||
- \%2i -- reads an NBO 2 byte integer; arg is SInt32* or UInt32*
|
||||
- \%4i -- reads an NBO 4 byte integer; arg is SInt32* or UInt32*
|
||||
- \%1I -- reads 1 byte integers; arg is std::vector<UInt8>*
|
||||
- \%2I -- reads NBO 2 byte integers; arg is std::vector<UInt16>*
|
||||
- \%4I -- reads NBO 4 byte integers; arg is std::vector<UInt32>*
|
||||
- \%s -- reads bytes; argument must be a CString*, \b not a char*
|
||||
*/
|
||||
static void readf(IInputStream*,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "ClipboardTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "MouseTypes.h"
|
||||
#include "OptionTypes.h"
|
||||
#include "CString.h"
|
||||
|
||||
//! Client interface
|
||||
|
@ -151,6 +152,19 @@ public:
|
|||
//! Notify of screen saver change
|
||||
virtual void screensaver(bool activate) = 0;
|
||||
|
||||
//! 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;
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
|
|
@ -46,6 +46,7 @@ libsynergy_a_SOURCES = \
|
|||
IServer.h \
|
||||
KeyTypes.h \
|
||||
MouseTypes.h \
|
||||
OptionTypes.h \
|
||||
ProtocolTypes.h \
|
||||
XScreen.h \
|
||||
XSynergy.h \
|
||||
|
|
|
@ -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 OPTIONTYPES_H
|
||||
#define OPTIONTYPES_H
|
||||
|
||||
#include "BasicTypes.h"
|
||||
#include "stdvector.h"
|
||||
|
||||
//! Option ID
|
||||
/*!
|
||||
Type to hold an option identifier.
|
||||
*/
|
||||
typedef UInt32 OptionID;
|
||||
|
||||
//! Option Value
|
||||
/*!
|
||||
Type to hold an option value.
|
||||
*/
|
||||
typedef SInt32 OptionValue;
|
||||
|
||||
// for now, options are just pairs of integers
|
||||
typedef std::vector<UInt32> COptionsList;
|
||||
|
||||
// macro for packing 4 character strings into 4 byte integers
|
||||
#define OPTION_CODE(_s) \
|
||||
(static_cast<UInt32>(static_cast<unsigned char>(_s[0]) << 24) | \
|
||||
static_cast<UInt32>(static_cast<unsigned char>(_s[1]) << 16) | \
|
||||
static_cast<UInt32>(static_cast<unsigned char>(_s[2]) << 8) | \
|
||||
static_cast<UInt32>(static_cast<unsigned char>(_s[3]) ))
|
||||
|
||||
//! @name Option identifiers
|
||||
//@{
|
||||
static const OptionID kOptionHalfDuplexCapsLock = OPTION_CODE("HDCL");
|
||||
static const OptionID kOptionHalfDuplexNumLock = OPTION_CODE("HDNL");
|
||||
static const OptionID kOptionHalfDuplexScrollLock = OPTION_CODE("HDSL");
|
||||
//@}
|
||||
|
||||
#undef OPTION_CODE
|
||||
|
||||
#endif
|
|
@ -118,6 +118,10 @@ static const char kMsgCClipboard[] = "CCLP%1i%4i";
|
|||
// screensaver on primary has started ($1 == 1) or closed ($1 == 0)
|
||||
static const char kMsgCScreenSaver[] = "CSEC%1i";
|
||||
|
||||
// reset options: primary -> secondary
|
||||
// client should reset all of its options to their defaults.
|
||||
static const char kMsgCResetOptions[] = "CROP";
|
||||
|
||||
// resolution change acknowledgment: primary -> secondary
|
||||
// sent by primary in response to a secondary screen's kMsgDInfo.
|
||||
// this is sent for every kMsgDInfo, whether or not the primary
|
||||
|
@ -181,6 +185,11 @@ static const char kMsgDClipboard[] = "DCLP%1i%4i%s";
|
|||
// the new screen area.
|
||||
static const char kMsgDInfo[] = "DINF%2i%2i%2i%2i%2i%2i%2i";
|
||||
|
||||
// set options: primary -> secondary
|
||||
// client should set the given option/value pairs. $1 = option/value
|
||||
// pairs.
|
||||
static const char kMsgDSetOptions[] = "DSOP%4I";
|
||||
|
||||
|
||||
//
|
||||
// query codes
|
||||
|
|
Loading…
Reference in New Issue