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:
crs 2002-12-23 13:55:21 +00:00
parent 72578b8061
commit 3fc1ddf6ce
29 changed files with 557 additions and 19 deletions

View File

@ -356,6 +356,18 @@ CClient::screensaver(bool activate)
m_screen->screensaver(activate); m_screen->screensaver(activate);
} }
void
CClient::resetOptions()
{
m_screen->resetOptions();
}
void
CClient::setOptions(const COptionsList& options)
{
m_screen->setOptions(options);
}
CString CString
CClient::getName() const CClient::getName() const
{ {

View File

@ -130,6 +130,8 @@ public:
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
virtual void mouseWheel(SInt32 delta); virtual void mouseWheel(SInt32 delta);
virtual void screensaver(bool activate); virtual void screensaver(bool activate);
virtual void resetOptions();
virtual void setOptions(const COptionsList& options);
virtual CString getName() const; virtual CString getName() const;
virtual SInt32 getJumpZoneSize() const; virtual SInt32 getJumpZoneSize() const;
virtual void getShape(SInt32& x, SInt32& y, virtual void getShape(SInt32& x, SInt32& y,

View File

@ -214,6 +214,18 @@ CMSWindowsSecondaryScreen::mouseWheel(SInt32 delta)
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, 0); mouse_event(MOUSEEVENTF_WHEEL, 0, 0, delta, 0);
} }
void
CMSWindowsSecondaryScreen::resetOptions()
{
// no options
}
void
CMSWindowsSecondaryScreen::setOptions(const COptionsList& /*options*/)
{
// no options
}
IScreen* IScreen*
CMSWindowsSecondaryScreen::getScreen() const CMSWindowsSecondaryScreen::getScreen() const
{ {

View File

@ -45,6 +45,8 @@ public:
virtual void mouseUp(ButtonID); virtual void mouseUp(ButtonID);
virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute); virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute);
virtual void mouseWheel(SInt32 delta); virtual void mouseWheel(SInt32 delta);
virtual void resetOptions();
virtual void setOptions(const COptionsList& options);
virtual IScreen* getScreen() const; virtual IScreen* getScreen() const;
// IMSWindowsScreenEventHandler overrides // IMSWindowsScreenEventHandler overrides

View File

@ -87,6 +87,9 @@ CSecondaryScreen::open()
// subclass hook // subclass hook
onPostOpen(); onPostOpen();
// reset options
resetOptions();
} }
catch (...) { catch (...) {
close(); close();

View File

@ -18,6 +18,7 @@
#include "ClipboardTypes.h" #include "ClipboardTypes.h"
#include "KeyTypes.h" #include "KeyTypes.h"
#include "MouseTypes.h" #include "MouseTypes.h"
#include "OptionTypes.h"
#include "CMutex.h" #include "CMutex.h"
class IClipboard; class IClipboard;
@ -156,6 +157,19 @@ public:
*/ */
virtual void mouseWheel(SInt32 delta) = 0; 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 //! @name accessors
//@{ //@{

View File

@ -203,6 +203,28 @@ CXWindowsSecondaryScreen::mouseWheel(SInt32 delta)
XSync(display, False); 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* IScreen*
CXWindowsSecondaryScreen::getScreen() const CXWindowsSecondaryScreen::getScreen() const
{ {
@ -262,12 +284,7 @@ CXWindowsSecondaryScreen::onPreOpen()
void void
CXWindowsSecondaryScreen::onPostOpen() CXWindowsSecondaryScreen::onPostOpen()
{ {
// check for peculiarities assert(m_window != None);
// FIXME -- may have to get these from some database
m_numLockHalfDuplex = false;
m_capsLockHalfDuplex = false;
// m_numLockHalfDuplex = true;
// m_capsLockHalfDuplex = true;
} }
void void

View File

@ -43,6 +43,8 @@ public:
virtual void mouseUp(ButtonID); virtual void mouseUp(ButtonID);
virtual void mouseMove(SInt32 x, SInt32 y); virtual void mouseMove(SInt32 x, SInt32 y);
virtual void mouseWheel(SInt32 delta); virtual void mouseWheel(SInt32 delta);
virtual void resetOptions();
virtual void setOptions(const COptionsList& options);
virtual IScreen* getScreen() const; virtual IScreen* getScreen() const;
// IScreenEventHandler overrides // IScreenEventHandler overrides

View File

@ -75,6 +75,8 @@ public:
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0; virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
virtual void mouseWheel(SInt32 delta) = 0; virtual void mouseWheel(SInt32 delta) = 0;
virtual void screensaver(bool activate) = 0; virtual void screensaver(bool activate) = 0;
virtual void resetOptions() = 0;
virtual void setOptions(const COptionsList& options) = 0;
virtual CString getName() const; virtual CString getName() const;
virtual SInt32 getJumpZoneSize() const = 0; virtual SInt32 getJumpZoneSize() const = 0;
virtual void getShape(SInt32& x, SInt32& y, virtual void getShape(SInt32& x, SInt32& y,

View File

@ -252,6 +252,20 @@ CClientProxy1_0::screensaver(bool on)
CProtocolUtil::writef(getOutputStream(), kMsgCScreenSaver, on ? 1 : 0); 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 SInt32
CClientProxy1_0::getJumpZoneSize() const CClientProxy1_0::getJumpZoneSize() const
{ {

View File

@ -46,6 +46,8 @@ public:
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
virtual void mouseWheel(SInt32 delta); virtual void mouseWheel(SInt32 delta);
virtual void screensaver(bool activate); virtual void screensaver(bool activate);
virtual void resetOptions();
virtual void setOptions(const COptionsList& options);
virtual SInt32 getJumpZoneSize() const; virtual SInt32 getJumpZoneSize() const;
virtual void getShape(SInt32& x, SInt32& y, virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const; SInt32& width, SInt32& height) const;

View File

@ -240,6 +240,34 @@ CConfig::setHTTPAddress(const CNetworkAddress& addr)
m_httpAddress = 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 bool
CConfig::isValidScreenName(const CString& name) const CConfig::isValidScreenName(const CString& name) const
{ {
@ -359,6 +387,19 @@ CConfig::getHTTPAddress() const
return m_httpAddress; 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 bool
CConfig::operator==(const CConfig& x) const CConfig::operator==(const CConfig& x) const
{ {
@ -438,6 +479,39 @@ CConfig::readLine(std::istream& s, CString& line)
return false; 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 void
CConfig::readSection(std::istream& s) CConfig::readSection(std::istream& s)
{ {
@ -547,7 +621,7 @@ void
CConfig::readSectionScreens(std::istream& s) CConfig::readSectionScreens(std::istream& s)
{ {
CString line; CString line;
CString name; CString screen;
while (readLine(s, line)) { while (readLine(s, line)) {
// check for end of section // check for end of section
if (line == "end") { if (line == "end") {
@ -557,23 +631,54 @@ CConfig::readSectionScreens(std::istream& s)
// see if it's the next screen // see if it's the next screen
if (line[line.size() - 1] == ':') { if (line[line.size() - 1] == ':') {
// strip : // strip :
name = line.substr(0, line.size() - 1); screen = line.substr(0, line.size() - 1);
// verify validity of screen name // verify validity of screen name
if (!isValidScreenName(name)) { if (!isValidScreenName(screen)) {
throw XConfigRead("invalid screen name"); throw XConfigRead("invalid screen name");
} }
// add the screen to the configuration // add the screen to the configuration
if (!addScreen(name)) { if (!addScreen(screen)) {
throw XConfigRead("duplicate screen name"); throw XConfigRead("duplicate screen name");
} }
} }
else if (name.empty()) { else if (screen.empty()) {
throw XConfigRead("argument before first screen"); throw XConfigRead("argument before first screen");
} }
else { else {
throw XConfigRead("unknown argument"); // 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"); 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(); for (CConfig::const_iterator screen = config.begin();
screen != config.end(); ++screen) { screen != config.end(); ++screen) {
s << "\t" << screen->c_str() << ":" << std::endl; 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; s << "end" << std::endl;

View File

@ -15,6 +15,7 @@
#ifndef CCONFIG_H #ifndef CCONFIG_H
#define CCONFIG_H #define CCONFIG_H
#include "OptionTypes.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "CNetworkAddress.h" #include "CNetworkAddress.h"
#include "XBase.h" #include "XBase.h"
@ -45,10 +46,14 @@ comparing names. Screen names and their aliases share a
namespace and must be unique. namespace and must be unique.
*/ */
class CConfig { class CConfig {
public:
typedef std::map<OptionID, OptionValue> CScreenOptions;
private: private:
class CCell { class CCell {
public: public:
CString m_neighbor[kLastDirection - kFirstDirection + 1]; CString m_neighbor[kLastDirection - kFirstDirection + 1];
CScreenOptions m_options;
}; };
typedef std::map<CString, CCell, CStringUtil::CaselessCmp> CCellMap; typedef std::map<CString, CCell, CStringUtil::CaselessCmp> CCellMap;
typedef std::map<CString, CString, CStringUtil::CaselessCmp> CNameMap; typedef std::map<CString, CString, CStringUtil::CaselessCmp> CNameMap;
@ -175,6 +180,23 @@ public:
*/ */
void setHTTPAddress(const CNetworkAddress&); 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 //! @name accessors
//@{ //@{
@ -227,6 +249,14 @@ public:
//! Get the HTTP server address //! Get the HTTP server address
const CNetworkAddress& getHTTPAddress() const; 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 //! Compare configurations
bool operator==(const CConfig&) const; bool operator==(const CConfig&) const;
//! Compare configurations //! Compare configurations
@ -254,6 +284,9 @@ public:
private: private:
static bool readLine(std::istream&, CString&); 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 readSection(std::istream&);
void readSectionNetwork(std::istream&); void readSectionNetwork(std::istream&);
void readSectionScreens(std::istream&); void readSectionScreens(std::istream&);

View File

@ -99,6 +99,18 @@ CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
m_y = y; m_y = y;
} }
void
CMSWindowsPrimaryScreen::resetOptions()
{
// no options
}
void
CMSWindowsPrimaryScreen::setOptions(const COptionsList& /*options*/)
{
// no options
}
KeyModifierMask KeyModifierMask
CMSWindowsPrimaryScreen::getToggleMask() const CMSWindowsPrimaryScreen::getToggleMask() const
{ {

View File

@ -37,6 +37,8 @@ public:
// CPrimaryScreen overrides // CPrimaryScreen overrides
virtual void reconfigure(UInt32 activeSides); virtual void reconfigure(UInt32 activeSides);
virtual void warpCursor(SInt32 x, SInt32 y); virtual void warpCursor(SInt32 x, SInt32 y);
virtual void resetOptions();
virtual void setOptions(const COptionsList& options);
virtual KeyModifierMask getToggleMask() const; virtual KeyModifierMask getToggleMask() const;
virtual bool isLockedToScreen() const; virtual bool isLockedToScreen() const;
virtual IScreen* getScreen() const; virtual IScreen* getScreen() const;

View File

@ -242,6 +242,18 @@ CPrimaryClient::screensaver(bool)
// ignore // ignore
} }
void
CPrimaryClient::resetOptions()
{
m_screen->resetOptions();
}
void
CPrimaryClient::setOptions(const COptionsList& options)
{
m_screen->setOptions(options);
}
CString CString
CPrimaryClient::getName() const CPrimaryClient::getName() const
{ {

View File

@ -108,6 +108,8 @@ public:
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
virtual void mouseWheel(SInt32 delta); virtual void mouseWheel(SInt32 delta);
virtual void screensaver(bool activate); virtual void screensaver(bool activate);
virtual void resetOptions();
virtual void setOptions(const COptionsList& options);
virtual CString getName() const; virtual CString getName() const;
virtual SInt32 getJumpZoneSize() const; virtual SInt32 getJumpZoneSize() const;
virtual void getShape(SInt32& x, SInt32& y, virtual void getShape(SInt32& x, SInt32& y,

View File

@ -90,6 +90,9 @@ CPrimaryScreen::open()
// subclass hook // subclass hook
onPostOpen(); onPostOpen();
// reset options
resetOptions();
} }
catch (...) { catch (...) {
close(); close();

View File

@ -17,6 +17,7 @@
#include "ClipboardTypes.h" #include "ClipboardTypes.h"
#include "KeyTypes.h" #include "KeyTypes.h"
#include "OptionTypes.h"
#include "CMutex.h" #include "CMutex.h"
class IClipboard; class IClipboard;
@ -115,6 +116,19 @@ public:
*/ */
void grabClipboard(ClipboardID); 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 //! @name accessors
//@{ //@{

View File

@ -20,6 +20,7 @@
#include "COutputPacketStream.h" #include "COutputPacketStream.h"
#include "CProtocolUtil.h" #include "CProtocolUtil.h"
#include "CClientProxy1_0.h" #include "CClientProxy1_0.h"
#include "OptionTypes.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "XScreen.h" #include "XScreen.h"
#include "XSynergy.h" #include "XSynergy.h"
@ -220,6 +221,8 @@ CServer::setConfig(const CConfig& config)
m_primaryClient->reconfigure(getActivePrimarySides()); m_primaryClient->reconfigure(getActivePrimarySides());
} }
// FIXME -- tell all (connected) clients about current options
return true; return true;
} }
@ -830,6 +833,8 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver)
IClient* IClient*
CServer::getNeighbor(IClient* src, EDirection dir) const CServer::getNeighbor(IClient* src, EDirection dir) const
{ {
// note -- must be locked on entry
assert(src != NULL); assert(src != NULL);
CString srcName = src->getName(); CString srcName = src->getName();
@ -863,6 +868,8 @@ IClient*
CServer::getNeighbor(IClient* src, CServer::getNeighbor(IClient* src,
EDirection srcSide, SInt32& x, SInt32& y) const EDirection srcSide, SInt32& x, SInt32& y) const
{ {
// note -- must be locked on entry
assert(src != NULL); assert(src != NULL);
// get the first neighbor // get the first neighbor
@ -1274,6 +1281,9 @@ CServer::runClient(void* vsocket)
CLock lock(&m_mutex); CLock lock(&m_mutex);
m_clientThreads.insert(std::make_pair(proxy->getName(), m_clientThreads.insert(std::make_pair(proxy->getName(),
CThread::getCurrentThread())); CThread::getCurrentThread()));
// send configuration options
sendOptions(proxy);
} }
catch (XDuplicateClient& e) { catch (XDuplicateClient& e) {
// client has duplicate name // 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 void
CServer::openPrimaryScreen() CServer::openPrimaryScreen()
{ {
@ -1605,8 +1641,13 @@ CServer::openPrimaryScreen()
// tell it about the active sides // tell it about the active sides
m_primaryClient->reconfigure(getActivePrimarySides()); m_primaryClient->reconfigure(getActivePrimarySides());
// tell primary client about its options
sendOptions(m_primaryClient);
} }
catch (...) { 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) { if (m_active != NULL) {
removeConnection(primaryName); removeConnection(primaryName);
} }

View File

@ -197,6 +197,9 @@ private:
IClient* getNeighbor(IClient*, EDirection, IClient* getNeighbor(IClient*, EDirection,
SInt32& x, SInt32& y) const; SInt32& x, SInt32& y) const;
// send screen options to \c client
void sendOptions(IClient* client) const;
// open/close the primary screen // open/close the primary screen
void openPrimaryScreen(); void openPrimaryScreen();
void closePrimaryScreen(); void closePrimaryScreen();

View File

@ -79,6 +79,28 @@ CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
m_y = 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 KeyModifierMask
CXWindowsPrimaryScreen::getToggleMask() const CXWindowsPrimaryScreen::getToggleMask() const
{ {
@ -385,16 +407,11 @@ CXWindowsPrimaryScreen::onPreOpen()
void void
CXWindowsPrimaryScreen::onPostOpen() CXWindowsPrimaryScreen::onPostOpen()
{ {
assert(m_window != None);
// get cursor info // get cursor info
m_screen->getCursorPos(m_x, m_y); m_screen->getCursorPos(m_x, m_y);
m_screen->getCursorCenter(m_xCenter, m_yCenter); 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 void

View File

@ -38,6 +38,8 @@ public:
// CPrimaryScreen overrides // CPrimaryScreen overrides
virtual void reconfigure(UInt32 activeSides); virtual void reconfigure(UInt32 activeSides);
virtual void warpCursor(SInt32 x, SInt32 y); virtual void warpCursor(SInt32 x, SInt32 y);
virtual void resetOptions();
virtual void setOptions(const COptionsList& options);
virtual KeyModifierMask getToggleMask() const; virtual KeyModifierMask getToggleMask() const;
virtual bool isLockedToScreen() const; virtual bool isLockedToScreen() const;
virtual IScreen* getScreen() const; virtual IScreen* getScreen() const;

View File

@ -16,6 +16,7 @@
#include "IInputStream.h" #include "IInputStream.h"
#include "IOutputStream.h" #include "IOutputStream.h"
#include "CLog.h" #include "CLog.h"
#include "stdvector.h"
#include <cctype> #include <cctype>
#include <cstring> #include <cstring>
@ -116,6 +117,56 @@ CProtocolUtil::readf(IInputStream* stream, const char* fmt, ...)
break; 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': { case 's': {
assert(len == 0); assert(len == 0);
@ -207,6 +258,24 @@ CProtocolUtil::getLength(const char* fmt, va_list args)
(void)va_arg(args, UInt32); (void)va_arg(args, UInt32);
break; 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': case 's':
assert(len == 0); assert(len == 0);
len = (va_arg(args, CString*))->size() + 4; len = (va_arg(args, CString*))->size() + 4;
@ -281,6 +350,52 @@ CProtocolUtil::writef(void* buffer, const char* fmt, va_list args)
break; 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': { case 's': {
assert(len == 0); assert(len == 0);
const CString* src = va_arg(args, CString*); const CString* src = va_arg(args, CString*);

View File

@ -41,6 +41,9 @@ public:
- \%1i -- converts integer argument to 1 byte integer - \%1i -- converts integer argument to 1 byte integer
- \%2i -- converts integer argument to 2 byte integer in NBO - \%2i -- converts integer argument to 2 byte integer in NBO
- \%4i -- converts integer argument to 4 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 CString* to stream of bytes
- \%S -- converts integer N and const UInt8* to stream of N 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* - \%1i -- reads a 1 byte integer; argument is a SInt32* or UInt32*
- \%2i -- reads an NBO 2 byte integer; arg is 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* - \%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* - \%s -- reads bytes; argument must be a CString*, \b not a char*
*/ */
static void readf(IInputStream*, static void readf(IInputStream*,

View File

@ -19,6 +19,7 @@
#include "ClipboardTypes.h" #include "ClipboardTypes.h"
#include "KeyTypes.h" #include "KeyTypes.h"
#include "MouseTypes.h" #include "MouseTypes.h"
#include "OptionTypes.h"
#include "CString.h" #include "CString.h"
//! Client interface //! Client interface
@ -151,6 +152,19 @@ public:
//! Notify of screen saver change //! Notify of screen saver change
virtual void screensaver(bool activate) = 0; 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 //! @name accessors
//@{ //@{

View File

@ -46,6 +46,7 @@ libsynergy_a_SOURCES = \
IServer.h \ IServer.h \
KeyTypes.h \ KeyTypes.h \
MouseTypes.h \ MouseTypes.h \
OptionTypes.h \
ProtocolTypes.h \ ProtocolTypes.h \
XScreen.h \ XScreen.h \
XSynergy.h \ XSynergy.h \

52
lib/synergy/OptionTypes.h Normal file
View File

@ -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

View File

@ -118,6 +118,10 @@ static const char kMsgCClipboard[] = "CCLP%1i%4i";
// screensaver on primary has started ($1 == 1) or closed ($1 == 0) // screensaver on primary has started ($1 == 1) or closed ($1 == 0)
static const char kMsgCScreenSaver[] = "CSEC%1i"; 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 // resolution change acknowledgment: primary -> secondary
// sent by primary in response to a secondary screen's kMsgDInfo. // sent by primary in response to a secondary screen's kMsgDInfo.
// this is sent for every kMsgDInfo, whether or not the primary // 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. // the new screen area.
static const char kMsgDInfo[] = "DINF%2i%2i%2i%2i%2i%2i%2i"; 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 // query codes