Initial commit of the synergy trunk sources from sf.net

This commit is contained in:
Sorin Sbarnea
2009-02-27 11:54:59 +00:00
commit 958fa80d1d
429 changed files with 96848 additions and 0 deletions

27
cmd/Makefile.am Normal file
View File

@@ -0,0 +1,27 @@
# 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.
## Process this file with automake to produce Makefile.in
NULL =
SUBDIRS = \
launcher \
synergyc \
synergys \
$(NULL)
EXTRA_DIST = \
$(NULL)
MAINTAINERCLEANFILES = \
Makefile.in \
$(NULL)

427
cmd/launcher/CAddScreen.cpp Normal file
View File

@@ -0,0 +1,427 @@
/*
* 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 "CConfig.h"
#include "KeyTypes.h"
#include "OptionTypes.h"
#include "ProtocolTypes.h"
#include "CStringUtil.h"
#include "CArch.h"
#include "CAddScreen.h"
#include "LaunchUtil.h"
#include "resource.h"
struct CModifierInfo {
public:
int m_ctrlID;
const char* m_name;
KeyModifierID m_modifierID;
OptionID m_optionID;
};
static const CModifierInfo s_modifiers[] = {
{ IDC_ADD_MOD_SHIFT, "Shift",
kKeyModifierIDShift, kOptionModifierMapForShift },
{ IDC_ADD_MOD_CTRL, "Ctrl",
kKeyModifierIDControl, kOptionModifierMapForControl },
{ IDC_ADD_MOD_ALT, "Alt",
kKeyModifierIDAlt, kOptionModifierMapForAlt },
{ IDC_ADD_MOD_META, "Meta",
kKeyModifierIDMeta, kOptionModifierMapForMeta },
{ IDC_ADD_MOD_SUPER, "Super",
kKeyModifierIDSuper, kOptionModifierMapForSuper }
};
static const KeyModifierID baseModifier = kKeyModifierIDShift;
//
// CAddScreen
//
CAddScreen* CAddScreen::s_singleton = NULL;
CAddScreen::CAddScreen(HWND parent, CConfig* config, const CString& name) :
m_parent(parent),
m_config(config),
m_name(name)
{
assert(s_singleton == NULL);
s_singleton = this;
}
CAddScreen::~CAddScreen()
{
s_singleton = NULL;
}
bool
CAddScreen::doModal()
{
// do dialog
return (DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADD),
m_parent, (DLGPROC)dlgProc, (LPARAM)this) != 0);
}
CString
CAddScreen::getName() const
{
return m_name;
}
void
CAddScreen::init(HWND hwnd)
{
// set title
CString title;
if (m_name.empty()) {
title = getString(IDS_ADD_SCREEN);
}
else {
title = CStringUtil::format(
getString(IDS_EDIT_SCREEN).c_str(),
m_name.c_str());
}
SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)title.c_str());
// fill in screen name
HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_name.c_str());
// fill in aliases
CString aliases;
for (CConfig::all_const_iterator index = m_config->beginAll();
index != m_config->endAll(); ++index) {
if (CStringUtil::CaselessCmp::equal(index->second, m_name) &&
!CStringUtil::CaselessCmp::equal(index->second, index->first)) {
if (!aliases.empty()) {
aliases += "\r\n";
}
aliases += index->first;
}
}
child = getItem(hwnd, IDC_ADD_ALIASES_EDIT);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)aliases.c_str());
// set options
CConfig::CScreenOptions options;
getOptions(options);
CConfig::CScreenOptions::const_iterator index;
child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
index = options.find(kOptionHalfDuplexCapsLock);
setItemChecked(child, (index != options.end() && index->second != 0));
child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
index = options.find(kOptionHalfDuplexNumLock);
setItemChecked(child, (index != options.end() && index->second != 0));
child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK);
index = options.find(kOptionHalfDuplexScrollLock);
setItemChecked(child, (index != options.end() && index->second != 0));
// modifier options
for (UInt32 i = 0; i < sizeof(s_modifiers) /
sizeof(s_modifiers[0]); ++i) {
child = getItem(hwnd, s_modifiers[i].m_ctrlID);
// fill in options
for (UInt32 j = 0; j < sizeof(s_modifiers) /
sizeof(s_modifiers[0]); ++j) {
SendMessage(child, CB_ADDSTRING, 0,
(LPARAM)s_modifiers[j].m_name);
}
// choose current value
index = options.find(s_modifiers[i].m_optionID);
KeyModifierID id = s_modifiers[i].m_modifierID;
if (index != options.end()) {
id = index->second;
}
SendMessage(child, CB_SETCURSEL, id - baseModifier, 0);
}
// dead corners
UInt32 corners = 0;
index = options.find(kOptionScreenSwitchCorners);
if (index != options.end()) {
corners = index->second;
}
child = getItem(hwnd, IDC_ADD_DC_TOP_LEFT);
setItemChecked(child, (corners & kTopLeftMask) != 0);
child = getItem(hwnd, IDC_ADD_DC_TOP_RIGHT);
setItemChecked(child, (corners & kTopRightMask) != 0);
child = getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT);
setItemChecked(child, (corners & kBottomLeftMask) != 0);
child = getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT);
setItemChecked(child, (corners & kBottomRightMask) != 0);
index = options.find(kOptionScreenSwitchCornerSize);
SInt32 size = 0;
if (index != options.end()) {
size = index->second;
}
char buffer[20];
sprintf(buffer, "%d", size);
child = getItem(hwnd, IDC_ADD_DC_SIZE);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer);
}
bool
CAddScreen::save(HWND hwnd)
{
// get the old aliases and options
CStringList oldAliases;
getAliases(oldAliases);
CConfig::CScreenOptions options;
getOptions(options);
// extract name and aliases
CString newName;
HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT);
newName = getWindowText(child);
CStringList newAliases;
child = getItem(hwnd, IDC_ADD_ALIASES_EDIT);
tokenize(newAliases, getWindowText(child));
// name must be valid
if (!m_config->isValidScreenName(newName)) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SCREEN_NAME).c_str(),
newName.c_str()));
return false;
}
// aliases must be valid
for (CStringList::const_iterator index = newAliases.begin();
index != newAliases.end(); ++index) {
if (!m_config->isValidScreenName(*index)) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SCREEN_NAME).c_str(),
index->c_str()));
return false;
}
}
// new name may not be in the new alias list
if (isNameInList(newAliases, newName)) {
showError(hwnd, CStringUtil::format(
getString(IDS_SCREEN_NAME_IS_ALIAS).c_str(),
newName.c_str()));
return false;
}
// name must not exist in config but allow same name. also
// allow name if it exists in the old alias list but not the
// new one.
if (m_config->isScreen(newName) &&
!CStringUtil::CaselessCmp::equal(newName, m_name) &&
!isNameInList(oldAliases, newName)) {
showError(hwnd, CStringUtil::format(
getString(IDS_DUPLICATE_SCREEN_NAME).c_str(),
newName.c_str()));
return false;
}
// aliases must not exist in config but allow same aliases and
// allow an alias to be the old name.
for (CStringList::const_iterator index = newAliases.begin();
index != newAliases.end(); ++index) {
if (m_config->isScreen(*index) &&
!CStringUtil::CaselessCmp::equal(*index, m_name) &&
!isNameInList(oldAliases, *index)) {
showError(hwnd, CStringUtil::format(
getString(IDS_DUPLICATE_SCREEN_NAME).c_str(),
index->c_str()));
return false;
}
}
// dead corner size must be non-negative
child = getItem(hwnd, IDC_ADD_DC_SIZE);
CString valueString = getWindowText(child);
int cornerSize = atoi(valueString.c_str());
if (cornerSize < 0) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_CORNER_SIZE).c_str(),
valueString.c_str()));
SetFocus(child);
return false;
}
// collect options
child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
if (isItemChecked(child)) {
options[kOptionHalfDuplexCapsLock] = 1;
}
else {
options.erase(kOptionHalfDuplexCapsLock);
}
child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
if (isItemChecked(child)) {
options[kOptionHalfDuplexNumLock] = 1;
}
else {
options.erase(kOptionHalfDuplexNumLock);
}
child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK);
if (isItemChecked(child)) {
options[kOptionHalfDuplexScrollLock] = 1;
}
else {
options.erase(kOptionHalfDuplexScrollLock);
}
// save modifier options
for (UInt32 i = 0; i < sizeof(s_modifiers) /
sizeof(s_modifiers[0]); ++i) {
child = getItem(hwnd, s_modifiers[i].m_ctrlID);
KeyModifierID id = static_cast<KeyModifierID>(
SendMessage(child, CB_GETCURSEL, 0, 0) +
baseModifier);
if (id != s_modifiers[i].m_modifierID) {
options[s_modifiers[i].m_optionID] = id;
}
else {
options.erase(s_modifiers[i].m_optionID);
}
}
// save dead corner options
UInt32 corners = 0;
if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_LEFT))) {
corners |= kTopLeftMask;
}
if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_RIGHT))) {
corners |= kTopRightMask;
}
if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT))) {
corners |= kBottomLeftMask;
}
if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT))) {
corners |= kBottomRightMask;
}
options[kOptionScreenSwitchCorners] = corners;
options[kOptionScreenSwitchCornerSize] = cornerSize;
// save new data to config
if (m_name.empty()) {
// added screen
m_config->addScreen(newName);
}
else {
// edited screen
m_config->removeAliases(m_name);
m_config->removeOptions(m_name);
m_config->renameScreen(m_name, newName);
}
m_name = newName;
for (CStringList::const_iterator index = newAliases.begin();
index != newAliases.end(); ++index) {
m_config->addAlias(m_name, *index);
}
for (CConfig::CScreenOptions::const_iterator
index = options.begin();
index != options.end(); ++index) {
m_config->addOption(m_name, index->first, index->second);
}
return true;
}
BOOL
CAddScreen::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
{
switch (message) {
case WM_INITDIALOG:
init(hwnd);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (save(hwnd)) {
EndDialog(hwnd, 1);
}
return TRUE;
case IDCANCEL:
EndDialog(hwnd, 0);
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
BOOL CALLBACK
CAddScreen::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
}
void
CAddScreen::getAliases(CStringList& aliases) const
{
for (CConfig::all_const_iterator index = m_config->beginAll();
index != m_config->endAll(); ++index) {
if (CStringUtil::CaselessCmp::equal(index->second, m_name) &&
!CStringUtil::CaselessCmp::equal(index->second, index->first)) {
aliases.push_back(index->first);
}
}
}
void
CAddScreen::getOptions(CConfig::CScreenOptions& optionsOut) const
{
const CConfig::CScreenOptions* options = m_config->getOptions(m_name);
if (options == NULL) {
optionsOut = CConfig::CScreenOptions();
}
else {
optionsOut = *options;
}
}
void
CAddScreen::tokenize(CStringList& tokens, const CString& src)
{
// find first non-whitespace
CString::size_type x = src.find_first_not_of(" \t\r\n");
if (x == CString::npos) {
return;
}
// find next whitespace
do {
CString::size_type y = src.find_first_of(" \t\r\n", x);
if (y == CString::npos) {
y = src.size();
}
tokens.push_back(src.substr(x, y - x));
x = src.find_first_not_of(" \t\r\n", y);
} while (x != CString::npos);
}
bool
CAddScreen::isNameInList(const CStringList& names, const CString& name)
{
for (CStringList::const_iterator index = names.begin();
index != names.end(); ++index) {
if (CStringUtil::CaselessCmp::equal(name, *index)) {
return true;
}
}
return false;
}

74
cmd/launcher/CAddScreen.h Normal file
View File

@@ -0,0 +1,74 @@
/*
* 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 CADDSCREEN_H
#define CADDSCREEN_H
#include "CString.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
class CConfig;
//! Add screen dialog for Microsoft Windows launcher
class CAddScreen {
public:
CAddScreen(HWND parent, CConfig*, const CString& name);
~CAddScreen();
//! @name manipulators
//@{
//! Run dialog
/*!
Display and handle the dialog until closed by the user. Return
\c true if the user accepted the changes, false otherwise.
*/
bool doModal();
//@}
//! @name accessors
//@{
CString getName() const;
//@}
private:
typedef std::vector<CString> CStringList;
void getAliases(CStringList&) const;
void getOptions(CConfig::CScreenOptions&) const;
static void tokenize(CStringList& tokens, const CString& src);
static bool isNameInList(const CStringList& tokens,
const CString& src);
void init(HWND hwnd);
bool save(HWND hwnd);
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
private:
static CAddScreen* s_singleton;
HWND m_parent;
CConfig* m_config;
CString m_name;
};
#endif

View File

@@ -0,0 +1,269 @@
/*
* 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 "CConfig.h"
#include "ProtocolTypes.h"
#include "CStringUtil.h"
#include "CArch.h"
#include "CArchMiscWindows.h"
#include "CAdvancedOptions.h"
#include "LaunchUtil.h"
#include "XArch.h"
#include "resource.h"
//
// CAdvancedOptions
//
CAdvancedOptions* CAdvancedOptions::s_singleton = NULL;
CAdvancedOptions::CAdvancedOptions(HWND parent, CConfig* config) :
m_parent(parent),
m_config(config),
m_isClient(false),
m_screenName(ARCH->getHostName()),
m_port(kDefaultPort),
m_interface()
{
assert(s_singleton == NULL);
s_singleton = this;
init();
}
CAdvancedOptions::~CAdvancedOptions()
{
s_singleton = NULL;
}
void
CAdvancedOptions::doModal(bool isClient)
{
// save state
m_isClient = isClient;
// do dialog
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADVANCED_OPTIONS),
m_parent, (DLGPROC)dlgProc, (LPARAM)this);
}
CString
CAdvancedOptions::getScreenName() const
{
return m_screenName;
}
int
CAdvancedOptions::getPort() const
{
return m_port;
}
CString
CAdvancedOptions::getInterface() const
{
return m_interface;
}
CString
CAdvancedOptions::getCommandLine(bool isClient, const CString& serverName) const
{
CString cmdLine;
// screen name
if (!m_screenName.empty()) {
cmdLine += " --name ";
cmdLine += m_screenName;
}
// port
char portString[20];
sprintf(portString, "%d", m_port);
if (isClient) {
cmdLine += " ";
cmdLine += serverName;
cmdLine += ":";
cmdLine += portString;
}
else {
cmdLine += " --address ";
if (!m_interface.empty()) {
cmdLine += m_interface;
}
cmdLine += ":";
cmdLine += portString;
}
return cmdLine;
}
void
CAdvancedOptions::init()
{
// get values from registry
HKEY key = CArchMiscWindows::openKey(HKEY_CURRENT_USER, getSettingsPath());
if (key != NULL) {
DWORD newPort = CArchMiscWindows::readValueInt(key, "port");
CString newName = CArchMiscWindows::readValueString(key, "name");
CString newInterface =
CArchMiscWindows::readValueString(key, "interface");
if (newPort != 0) {
m_port = static_cast<int>(newPort);
}
if (!newName.empty()) {
m_screenName = newName;
}
if (!newInterface.empty()) {
m_interface = newInterface;
}
CArchMiscWindows::closeKey(key);
}
}
void
CAdvancedOptions::doInit(HWND hwnd)
{
// set values in GUI
HWND child;
char buffer[20];
sprintf(buffer, "%d", m_port);
child = getItem(hwnd, IDC_ADVANCED_PORT_EDIT);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer);
child = getItem(hwnd, IDC_ADVANCED_NAME_EDIT);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_screenName.c_str());
child = getItem(hwnd, IDC_ADVANCED_INTERFACE_EDIT);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_interface.c_str());
}
bool
CAdvancedOptions::save(HWND hwnd)
{
SetCursor(LoadCursor(NULL, IDC_WAIT));
HWND child = getItem(hwnd, IDC_ADVANCED_NAME_EDIT);
CString name = getWindowText(child);
if (!m_config->isValidScreenName(name)) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SCREEN_NAME).c_str(),
name.c_str()));
SetFocus(child);
return false;
}
if (!m_isClient && !m_config->isScreen(name)) {
showError(hwnd, CStringUtil::format(
getString(IDS_UNKNOWN_SCREEN_NAME).c_str(),
name.c_str()));
SetFocus(child);
return false;
}
child = getItem(hwnd, IDC_ADVANCED_INTERFACE_EDIT);
CString iface = getWindowText(child);
if (!m_isClient) {
try {
if (!iface.empty()) {
ARCH->nameToAddr(iface);
}
}
catch (XArchNetworkName& e) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_INTERFACE_NAME).c_str(),
iface.c_str(), e.what().c_str()));
SetFocus(child);
return false;
}
}
// get and verify port
child = getItem(hwnd, IDC_ADVANCED_PORT_EDIT);
CString portString = getWindowText(child);
int port = atoi(portString.c_str());
if (port < 1 || port > 65535) {
CString defaultPortString = CStringUtil::print("%d", kDefaultPort);
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_PORT).c_str(),
portString.c_str(),
defaultPortString.c_str()));
SetFocus(child);
return false;
}
// save state
m_screenName = name;
m_port = port;
m_interface = iface;
// save values to registry
HKEY key = CArchMiscWindows::addKey(HKEY_CURRENT_USER, getSettingsPath());
if (key != NULL) {
CArchMiscWindows::setValue(key, "port", m_port);
CArchMiscWindows::setValue(key, "name", m_screenName);
CArchMiscWindows::setValue(key, "interface", m_interface);
CArchMiscWindows::closeKey(key);
}
return true;
}
void
CAdvancedOptions::setDefaults(HWND hwnd)
{
// restore defaults
m_screenName = ARCH->getHostName();
m_port = kDefaultPort;
m_interface = "";
// update GUI
doInit(hwnd);
}
BOOL
CAdvancedOptions::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
{
switch (message) {
case WM_INITDIALOG:
doInit(hwnd);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (save(hwnd)) {
EndDialog(hwnd, 0);
}
return TRUE;
case IDCANCEL:
EndDialog(hwnd, 0);
return TRUE;
case IDC_ADVANCED_DEFAULTS:
setDefaults(hwnd);
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
BOOL CALLBACK
CAdvancedOptions::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
}

View File

@@ -0,0 +1,80 @@
/*
* 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 CADVANCEDOPTIONS_H
#define CADVANCEDOPTIONS_H
#include "CString.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
class CConfig;
//! Advanced options dialog for Microsoft Windows launcher
class CAdvancedOptions {
public:
CAdvancedOptions(HWND parent, CConfig*);
~CAdvancedOptions();
//! @name manipulators
//@{
//! Run dialog
/*!
Display and handle the dialog until closed by the user.
*/
void doModal(bool isClient);
//@}
//! @name accessors
//@{
//! Get the screen name
CString getScreenName() const;
//! Get the port
int getPort() const;
//! Get the interface
CString getInterface() const;
//! Convert options to command line string
CString getCommandLine(bool isClient,
const CString& serverName) const;
//@}
private:
void init();
void doInit(HWND hwnd);
bool save(HWND hwnd);
void setDefaults(HWND hwnd);
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
private:
static CAdvancedOptions* s_singleton;
HWND m_parent;
CConfig* m_config;
bool m_isClient;
CString m_screenName;
int m_port;
CString m_interface;
};
#endif

361
cmd/launcher/CAutoStart.cpp Normal file
View File

@@ -0,0 +1,361 @@
/*
* 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 "CLog.h"
#include "ILogOutputter.h"
#include "CArch.h"
#include "CStringUtil.h"
#include "XArch.h"
#include "CAutoStart.h"
#include "LaunchUtil.h"
#include "resource.h"
static const char* CLIENT_DAEMON_NAME = "Synergy Client";
static const char* SERVER_DAEMON_NAME = "Synergy Server";
static const char* CLIENT_DAEMON_INFO = "Uses a shared mouse and keyboard.";
static const char* SERVER_DAEMON_INFO = "Shares this system's mouse and keyboard with others.";
//
// CAutoStartOutputter
//
// This class detects a message above a certain level and saves it
//
class CAutoStartOutputter : public ILogOutputter {
public:
CAutoStartOutputter(CString* msg) : m_msg(msg) { }
virtual ~CAutoStartOutputter() { }
// ILogOutputter overrides
virtual void open(const char*) { }
virtual void close() { }
virtual void show(bool) { }
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const { return ""; }
private:
CString* m_msg;
};
bool
CAutoStartOutputter::write(ELevel level, const char* message)
{
if (level <= CLog::kERROR) {
*m_msg = message;
}
return false;
}
//
// CAutoStart
//
CAutoStart* CAutoStart::s_singleton = NULL;
CAutoStart::CAutoStart(HWND parent, bool isServer, const CString& cmdLine) :
m_parent(parent),
m_isServer(isServer),
m_cmdLine(cmdLine),
m_name(isServer ? SERVER_DAEMON_NAME : CLIENT_DAEMON_NAME)
{
assert(s_singleton == NULL);
s_singleton = this;
}
CAutoStart::~CAutoStart()
{
s_singleton = NULL;
}
void
CAutoStart::doModal()
{
// install our log outputter
CLOG->insert(new CAutoStartOutputter(&m_errorMessage));
// do dialog
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_AUTOSTART),
m_parent, (DLGPROC)dlgProc, (LPARAM)this);
// remove log outputter
CLOG->pop_front();
}
void
CAutoStart::reinstallDaemon(bool isClient, const CString& cmdLine)
{
// get installation state
const char* name = (isClient ? CLIENT_DAEMON_NAME : SERVER_DAEMON_NAME);
bool installedSystem = ARCH->isDaemonInstalled(name, true);
bool installedUser = ARCH->isDaemonInstalled(name, false);
// reinstall if anything is installed
if (installedSystem || installedUser) {
ARCH->installDaemon(name,
isClient ? CLIENT_DAEMON_INFO : SERVER_DAEMON_INFO,
getAppPath(isClient ? CLIENT_APP : SERVER_APP).c_str(),
cmdLine.c_str(),
NULL,
installedSystem);
}
}
void
CAutoStart::uninstallDaemons(bool client)
{
if (client) {
try {
ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, true);
}
catch (...) {
}
try {
ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, false);
}
catch (...) {
}
}
else {
try {
ARCH->uninstallDaemon(SERVER_DAEMON_NAME, true);
}
catch (...) {
}
try {
ARCH->uninstallDaemon(SERVER_DAEMON_NAME, false);
}
catch (...) {
}
}
}
bool
CAutoStart::startDaemon()
{
const char* name = NULL;
if (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true)) {
name = CLIENT_DAEMON_NAME;
}
else if (ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true)) {
name = SERVER_DAEMON_NAME;
}
if (name == NULL) {
return false;
}
// open service manager
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
if (mgr == NULL) {
return false;
}
// open the service
SC_HANDLE service = OpenService(mgr, name, SERVICE_START);
if (service == NULL) {
CloseServiceHandle(mgr);
return false;
}
// start the service
BOOL okay = StartService(service, 0, NULL);
// clean up
CloseServiceHandle(service);
CloseServiceHandle(mgr);
return (okay != 0);
}
bool
CAutoStart::isDaemonInstalled()
{
return (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, false) ||
ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true) ||
ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, false) ||
ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true));
}
void
CAutoStart::update()
{
// get installation state
const bool installedSystem = ARCH->isDaemonInstalled(
m_name.c_str(), true);
const bool installedUser = ARCH->isDaemonInstalled(
m_name.c_str(), false);
// get user's permissions
const bool canInstallSystem = ARCH->canInstallDaemon(
m_name.c_str(), true);
const bool canInstallUser = ARCH->canInstallDaemon(
m_name.c_str(), false);
// update messages
CString msg, label;
if (canInstallSystem) {
if (canInstallUser) {
msg = getString(IDS_AUTOSTART_PERMISSION_ALL);
}
else {
msg = getString(IDS_AUTOSTART_PERMISSION_SYSTEM);
}
}
else if (canInstallUser) {
msg = getString(IDS_AUTOSTART_PERMISSION_USER);
}
else {
msg = getString(IDS_AUTOSTART_PERMISSION_NONE);
}
setWindowText(getItem(m_hwnd, IDC_AUTOSTART_PERMISSION_MSG), msg);
if (installedSystem) {
msg = getString(IDS_AUTOSTART_INSTALLED_SYSTEM);
label = getString(IDS_UNINSTALL_LABEL);
}
else if (installedUser) {
msg = getString(IDS_AUTOSTART_INSTALLED_USER);
label = getString(IDS_UNINSTALL_LABEL);
}
else {
msg = getString(IDS_AUTOSTART_INSTALLED_NONE);
label = getString(IDS_INSTALL_LABEL);
}
setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALLED_MSG), msg);
// update buttons
setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM), label);
setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER), label);
if (installedSystem) {
enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem);
enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, false);
m_install = false;
}
else if (installedUser) {
enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, false);
enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser);
m_install = false;
}
else {
enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem);
enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser);
m_install = true;
}
}
bool
CAutoStart::onInstall(bool allUsers)
{
if (!m_install) {
return onUninstall(allUsers);
}
// get the app path
CString appPath = getAppPath(m_isServer ? SERVER_APP : CLIENT_APP);
// clear error message
m_errorMessage = "";
// install
try {
ARCH->installDaemon(m_name.c_str(),
m_isServer ? SERVER_DAEMON_INFO : CLIENT_DAEMON_INFO,
appPath.c_str(), m_cmdLine.c_str(),
NULL, allUsers);
askOkay(m_hwnd, getString(IDS_INSTALL_TITLE),
getString(allUsers ?
IDS_INSTALLED_SYSTEM :
IDS_INSTALLED_USER));
return true;
}
catch (XArchDaemon& e) {
if (m_errorMessage.empty()) {
m_errorMessage = CStringUtil::format(
getString(IDS_INSTALL_GENERIC_ERROR).c_str(),
e.what().c_str());
}
showError(m_hwnd, m_errorMessage);
return false;
}
}
bool
CAutoStart::onUninstall(bool allUsers)
{
// clear error message
m_errorMessage = "";
// uninstall
try {
ARCH->uninstallDaemon(m_name.c_str(), allUsers);
askOkay(m_hwnd, getString(IDS_UNINSTALL_TITLE),
getString(allUsers ?
IDS_UNINSTALLED_SYSTEM :
IDS_UNINSTALLED_USER));
return true;
}
catch (XArchDaemon& e) {
if (m_errorMessage.empty()) {
m_errorMessage = CStringUtil::format(
getString(IDS_UNINSTALL_GENERIC_ERROR).c_str(),
e.what().c_str());
}
showError(m_hwnd, m_errorMessage);
return false;
}
}
BOOL
CAutoStart::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
{
switch (message) {
case WM_INITDIALOG:
// save our hwnd
m_hwnd = hwnd;
// update the controls
update();
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_AUTOSTART_INSTALL_SYSTEM:
onInstall(true);
update();
return TRUE;
case IDC_AUTOSTART_INSTALL_USER:
onInstall(false);
update();
return TRUE;
case IDCANCEL:
EndDialog(hwnd, 0);
m_hwnd = NULL;
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
BOOL CALLBACK
CAutoStart::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
}

90
cmd/launcher/CAutoStart.h Normal file
View File

@@ -0,0 +1,90 @@
/*
* 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 CAUTOSTART_H
#define CAUTOSTART_H
#include "CString.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
//! Auto start dialog for Microsoft Windows launcher
class CAutoStart {
public:
CAutoStart(HWND parent, bool isServer, const CString& cmdLine);
~CAutoStart();
//! @name manipulators
//@{
//! Run dialog
/*!
Display and handle the dialog until closed by the user.
*/
void doModal();
//! Reinstall daemon
/*!
Reinstalls the currently installed daemon.
*/
static void reinstallDaemon(bool isClient, const CString& cmdLine);
//! Uninstalls daemon
/*!
Uninstalls all installed client (\p client is \c true) or server daemons.
*/
static void uninstallDaemons(bool client);
//! Starts an installed daemon
/*!
Returns \c true iff a daemon was started. This will only start daemons
installed for all users.
*/
static bool startDaemon();
//@}
//! @name accessors
//@{
//! Tests if any daemons are installed
/*!
Returns \c true if any daemons are installed.
*/
static bool isDaemonInstalled();
//@}
private:
void update();
bool onInstall(bool allUsers);
bool onUninstall(bool allUsers);
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
private:
static CAutoStart* s_singleton;
HWND m_parent;
bool m_isServer;
CString m_cmdLine;
CString m_name;
HWND m_hwnd;
bool m_install;
CString m_errorMessage;
};
#endif

View File

@@ -0,0 +1,281 @@
/*
* 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 "CConfig.h"
#include "ProtocolTypes.h"
#include "CStringUtil.h"
#include "CArch.h"
#include "CGlobalOptions.h"
#include "LaunchUtil.h"
#include "resource.h"
static const int s_defaultDelay = 250;
static const int s_defaultHeartbeat = 5000;
//
// CGlobalOptions
//
CGlobalOptions* CGlobalOptions::s_singleton = NULL;
CGlobalOptions::CGlobalOptions(HWND parent, CConfig* config) :
m_parent(parent),
m_config(config),
m_delayTime(s_defaultDelay),
m_twoTapTime(s_defaultDelay),
m_heartbeatTime(s_defaultHeartbeat)
{
assert(s_singleton == NULL);
s_singleton = this;
}
CGlobalOptions::~CGlobalOptions()
{
s_singleton = NULL;
}
void
CGlobalOptions::doModal()
{
// do dialog
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_GLOBAL_OPTIONS),
m_parent, (DLGPROC)dlgProc, (LPARAM)this);
}
void
CGlobalOptions::init(HWND hwnd)
{
HWND child;
char buffer[30];
// reset options
sprintf(buffer, "%d", m_delayTime);
child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK);
setItemChecked(child, false);
child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME);
setWindowText(child, buffer);
sprintf(buffer, "%d", m_twoTapTime);
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK);
setItemChecked(child, false);
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME);
setWindowText(child, buffer);
sprintf(buffer, "%d", m_heartbeatTime);
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK);
setItemChecked(child, false);
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME);
setWindowText(child, buffer);
child = getItem(hwnd, IDC_GLOBAL_SCREENSAVER_SYNC);
setItemChecked(child, true);
child = getItem(hwnd, IDC_GLOBAL_RELATIVE_MOVES);
setItemChecked(child, false);
child = getItem(hwnd, IDC_GLOBAL_LEAVE_FOREGROUND);
setItemChecked(child, false);
// get the global options
const CConfig::CScreenOptions* options = m_config->getOptions("");
if (options != NULL) {
for (CConfig::CScreenOptions::const_iterator index = options->begin();
index != options->end(); ++index) {
const OptionID id = index->first;
const OptionValue value = index->second;
if (id == kOptionScreenSwitchDelay) {
if (value > 0) {
sprintf(buffer, "%d", value);
child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK);
setItemChecked(child, true);
child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME);
setWindowText(child, buffer);
}
}
else if (id == kOptionScreenSwitchTwoTap) {
if (value > 0) {
sprintf(buffer, "%d", value);
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK);
setItemChecked(child, true);
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME);
setWindowText(child, buffer);
}
}
else if (id == kOptionHeartbeat) {
if (value > 0) {
sprintf(buffer, "%d", value);
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK);
setItemChecked(child, true);
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME);
setWindowText(child, buffer);
}
}
else if (id == kOptionScreenSaverSync) {
child = getItem(hwnd, IDC_GLOBAL_SCREENSAVER_SYNC);
setItemChecked(child, (value != 0));
}
else if (id == kOptionRelativeMouseMoves) {
child = getItem(hwnd, IDC_GLOBAL_RELATIVE_MOVES);
setItemChecked(child, (value != 0));
}
else if (id == kOptionWin32KeepForeground) {
child = getItem(hwnd, IDC_GLOBAL_LEAVE_FOREGROUND);
setItemChecked(child, (value != 0));
}
}
}
}
bool
CGlobalOptions::save(HWND hwnd)
{
HWND child;
int newDelayTime = 0;
int newTwoTapTime = 0;
int newHeartbeatTime = 0;
// get requested options
child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK);
if (isItemChecked(child)) {
child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME);
newDelayTime = getTime(hwnd, child, true);
if (newDelayTime == 0) {
return false;
}
}
else {
child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME);
newDelayTime = getTime(hwnd, child, false);
if (newDelayTime == 0) {
newDelayTime = s_defaultDelay;
}
}
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK);
if (isItemChecked(child)) {
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME);
newTwoTapTime = getTime(hwnd, child, true);
if (newTwoTapTime == 0) {
return false;
}
}
else {
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME);
newTwoTapTime = getTime(hwnd, child, false);
if (newTwoTapTime == 0) {
newTwoTapTime = s_defaultDelay;
}
}
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK);
if (isItemChecked(child)) {
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME);
newHeartbeatTime = getTime(hwnd, child, true);
if (newHeartbeatTime == 0) {
return false;
}
}
else {
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME);
newHeartbeatTime = getTime(hwnd, child, false);
if (newHeartbeatTime == 0) {
newHeartbeatTime = s_defaultHeartbeat;
}
}
// remove existing config options
m_config->removeOption("", kOptionScreenSwitchDelay);
m_config->removeOption("", kOptionScreenSwitchTwoTap);
m_config->removeOption("", kOptionHeartbeat);
m_config->removeOption("", kOptionScreenSaverSync);
m_config->removeOption("", kOptionRelativeMouseMoves);
m_config->removeOption("", kOptionWin32KeepForeground);
// add requested options
child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK);
if (isItemChecked(child)) {
m_config->addOption("", kOptionScreenSwitchDelay, newDelayTime);
}
child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK);
if (isItemChecked(child)) {
m_config->addOption("", kOptionScreenSwitchTwoTap, newTwoTapTime);
}
child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK);
if (isItemChecked(child)) {
m_config->addOption("", kOptionHeartbeat, newHeartbeatTime);
}
child = getItem(hwnd, IDC_GLOBAL_SCREENSAVER_SYNC);
if (!isItemChecked(child)) {
m_config->addOption("", kOptionScreenSaverSync, 0);
}
child = getItem(hwnd, IDC_GLOBAL_RELATIVE_MOVES);
if (isItemChecked(child)) {
m_config->addOption("", kOptionRelativeMouseMoves, 1);
}
child = getItem(hwnd, IDC_GLOBAL_LEAVE_FOREGROUND);
if (isItemChecked(child)) {
m_config->addOption("", kOptionWin32KeepForeground, 1);
}
// save last values
m_delayTime = newDelayTime;
m_twoTapTime = newTwoTapTime;
m_heartbeatTime = newHeartbeatTime;
return true;
}
int
CGlobalOptions::getTime(HWND hwnd, HWND child, bool reportError)
{
CString valueString = getWindowText(child);
int value = atoi(valueString.c_str());
if (value < 1) {
if (reportError) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_TIME).c_str(),
valueString.c_str()));
SetFocus(child);
}
return 0;
}
return value;
}
BOOL
CGlobalOptions::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
{
switch (message) {
case WM_INITDIALOG:
init(hwnd);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (save(hwnd)) {
EndDialog(hwnd, 0);
}
return TRUE;
case IDCANCEL:
EndDialog(hwnd, 0);
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
BOOL CALLBACK
CGlobalOptions::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
}

View File

@@ -0,0 +1,67 @@
/*
* 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 CGLOBALOPTIONS_H
#define CGLOBALOPTIONS_H
#include "CString.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
class CConfig;
//! Global options dialog for Microsoft Windows launcher
class CGlobalOptions {
public:
CGlobalOptions(HWND parent, CConfig*);
~CGlobalOptions();
//! @name manipulators
//@{
//! Run dialog
/*!
Display and handle the dialog until closed by the user.
*/
void doModal();
//@}
//! @name accessors
//@{
//@}
private:
void init(HWND hwnd);
bool save(HWND hwnd);
int getTime(HWND hwnd, HWND child, bool reportError);
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
private:
static CGlobalOptions* s_singleton;
HWND m_parent;
CConfig* m_config;
int m_delayTime;
int m_twoTapTime;
int m_heartbeatTime;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,227 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2006 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 CHOTKEYOPTIONS_H
#define CHOTKEYOPTIONS_H
#include "CString.h"
#include "KeyTypes.h"
#include "MouseTypes.h"
#include "CInputFilter.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
class CConfig;
//! Hotkey options dialog for Microsoft Windows launcher
class CHotkeyOptions {
public:
CHotkeyOptions(HWND parent, CConfig*);
~CHotkeyOptions();
//! @name manipulators
//@{
//! Run dialog
/*!
Display and handle the dialog until closed by the user.
*/
void doModal();
//@}
//! @name accessors
//@{
//@}
private:
void doInit(HWND hwnd);
void fillHotkeys(HWND hwnd, UInt32 select = (UInt32)-1);
void updateHotkeysControls(HWND hwnd);
void addHotkey(HWND hwnd);
void removeHotkey(HWND hwnd);
void editHotkey(HWND hwnd);
void fillActions(HWND hwnd, UInt32 select = (UInt32)-1);
void updateActionsControls(HWND hwnd);
void addAction(HWND hwnd);
void removeAction(HWND hwnd);
void editAction(HWND hwnd);
bool editCondition(HWND hwnd, CInputFilter::CCondition*&);
bool editAction(HWND hwnd, CInputFilter::CAction*&,
bool& onActivate);
void openRule(HWND hwnd);
void closeRule(HWND hwnd);
UInt32 findMatchingAction(
const CInputFilter::CKeystrokeAction*) const;
UInt32 findMatchingAction(
const CInputFilter::CMouseButtonAction*) const;
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
// special actions we use to combine matching down/up actions into a
// single action for the convenience of the user.
class CKeystrokeDownUpAction : public CInputFilter::CKeystrokeAction {
public:
CKeystrokeDownUpAction(IPlatformScreen::CKeyInfo* adoptedInfo) :
CInputFilter::CKeystrokeAction(adoptedInfo, true) { }
// CAction overrides
virtual CInputFilter::CAction* clone() const
{
IKeyState::CKeyInfo* info = IKeyState::CKeyInfo::alloc(*getInfo());
return new CKeystrokeDownUpAction(info);
}
protected:
// CKeystrokeAction overrides
virtual const char* formatName() const { return "keystroke"; }
};
class CMouseButtonDownUpAction : public CInputFilter::CMouseButtonAction {
public:
CMouseButtonDownUpAction(IPrimaryScreen::CButtonInfo* adoptedInfo) :
CInputFilter::CMouseButtonAction(adoptedInfo, true) { }
// CAction overrides
virtual CInputFilter::CAction* clone() const
{
IPlatformScreen::CButtonInfo* info =
IPrimaryScreen::CButtonInfo::alloc(*getInfo());
return new CMouseButtonDownUpAction(info);
}
protected:
// CMouseButtonAction overrides
virtual const char* formatName() const { return "mousebutton"; }
};
class CConditionDialog {
public:
static bool doModal(HWND parent, CInputFilter::CCondition*&);
private:
static void doInit(HWND hwnd);
static void fillHotkey(HWND hwnd);
static void onButton(HWND hwnd, ButtonID button);
static void onKey(HWND hwnd, WPARAM wParam, LPARAM lParam);
static KeyID getChar(WPARAM wParam, LPARAM lParam);
static KeyModifierMask
getModifiers();
static bool isGoodCondition();
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
static LRESULT CALLBACK editProc(HWND hwnd, UINT, WPARAM, LPARAM);
private:
static CInputFilter::CCondition*
s_condition;
static CInputFilter::CCondition*
s_lastGoodCondition;
static WNDPROC s_editWndProc;
};
class CActionDialog {
public:
static bool doModal(HWND parent, CConfig* config,
CInputFilter::CAction*&, bool& onActivate);
private:
static void doInit(HWND hwnd);
static void fillHotkey(HWND hwnd);
static void updateControls(HWND hwnd);
static void onButton(HWND hwnd, ButtonID button);
static void onKey(HWND hwnd, WPARAM wParam, LPARAM lParam);
static void onLockAction(HWND hwnd);
static void onSwitchToAction(HWND hwnd);
static void onSwitchInAction(HWND hwnd);
static void onKeyboardBroadcastAction(HWND hwnd);
static KeyID getChar(WPARAM wParam, LPARAM lParam);
static KeyModifierMask
getModifiers();
static bool isGoodAction();
static void convertAction(HWND hwnd);
static bool isDownUpAction();
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
static LRESULT CALLBACK editProc(HWND hwnd, UINT, WPARAM, LPARAM);
private:
static CConfig* s_config;
static bool s_onActivate;
static CInputFilter::CAction*
s_action;
static CInputFilter::CAction*
s_lastGoodAction;
static std::set<CString> s_screens;
static WNDPROC s_editWndProc;
};
// public to allow CActionDialog to use it
public:
class CScreensDialog {
public:
static void doModal(HWND parent, CConfig* config,
CInputFilter::CKeystrokeAction*);
// public due to compiler brokenness
typedef std::set<CString> CScreens;
private:
static void doInit(HWND hwnd);
static void doFini(HWND hwnd);
static void fillScreens(HWND hwnd);
static void updateControls(HWND hwnd);
static void add(HWND hwnd);
static void remove(HWND hwnd);
static void getSelected(HWND hwnd, UINT id,
const CScreens& inScreens, CScreens& outScreens);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
private:
static CConfig* s_config;
static CInputFilter::CKeystrokeAction* s_action;
static CScreens s_nonTargets;
static CScreens s_targets;
static CString s_allScreens;
};
private:
static CHotkeyOptions* s_singleton;
HWND m_parent;
CConfig* m_config;
CInputFilter* m_inputFilter;
CInputFilter::CRule m_activeRule;
UInt32 m_activeRuleIndex;
};
#endif

111
cmd/launcher/CInfo.cpp Normal file
View File

@@ -0,0 +1,111 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2006 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 "ProtocolTypes.h"
#include "CStringUtil.h"
#include "Version.h"
#include "CArch.h"
#include "CInfo.h"
#include "LaunchUtil.h"
#include "resource.h"
//
// CInfo
//
CInfo* CInfo::s_singleton = NULL;
CInfo::CInfo(HWND parent) :
m_parent(parent)
{
assert(s_singleton == NULL);
s_singleton = this;
}
CInfo::~CInfo()
{
s_singleton = NULL;
}
void
CInfo::doModal()
{
// do dialog
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_INFO),
m_parent, (DLGPROC)dlgProc, (LPARAM)this);
}
void
CInfo::init(HWND hwnd)
{
// collect info
CString version =
CStringUtil::format(getString(IDS_TITLE).c_str(), VERSION);
CString hostname = ARCH->getHostName();
CString address = ARCH->addrToString(ARCH->nameToAddr(hostname));
CString userConfig = ARCH->getUserDirectory();
if (!userConfig.empty()) {
userConfig = ARCH->concatPath(userConfig, CONFIG_NAME);
}
CString sysConfig = ARCH->getSystemDirectory();
if (!sysConfig.empty()) {
sysConfig = ARCH->concatPath(sysConfig, CONFIG_NAME);
}
// set info
HWND child;
child = getItem(hwnd, IDC_INFO_VERSION);
setWindowText(child, version);
child = getItem(hwnd, IDC_INFO_HOSTNAME);
setWindowText(child, hostname);
child = getItem(hwnd, IDC_INFO_IP_ADDRESS);
setWindowText(child, address);
child = getItem(hwnd, IDC_INFO_USER_CONFIG);
setWindowText(child, userConfig);
child = getItem(hwnd, IDC_INFO_SYS_CONFIG);
setWindowText(child, sysConfig);
// focus on okay button
SetFocus(getItem(hwnd, IDOK));
}
BOOL
CInfo::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
{
switch (message) {
case WM_INITDIALOG:
init(hwnd);
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hwnd, 0);
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
BOOL CALLBACK
CInfo::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
}

57
cmd/launcher/CInfo.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2006 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 CINFO_H
#define CINFO_H
#include "CString.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
//! Info dialog for Microsoft Windows launcher
class CInfo {
public:
CInfo(HWND parent);
~CInfo();
//! @name manipulators
//@{
//! Run dialog
/*!
Display and handle the dialog until closed by the user.
*/
void doModal();
//@}
//! @name accessors
//@{
//@}
private:
void init(HWND hwnd);
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
private:
static CInfo* s_singleton;
HWND m_parent;
};
#endif

View File

@@ -0,0 +1,855 @@
/*
* 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 "CConfig.h"
#include "ProtocolTypes.h"
#include "CStringUtil.h"
#include "CArch.h"
#include "CScreensLinks.h"
#include "CAddScreen.h"
#include "LaunchUtil.h"
#include "resource.h"
//
// CScreensLinks
//
CScreensLinks* CScreensLinks::s_singleton = NULL;
CScreensLinks::CScreensLinks(HWND parent, CConfig* config) :
m_parent(parent),
m_mainConfig(config),
m_config(&m_scratchConfig)
{
assert(s_singleton == NULL);
s_singleton = this;
// get formatting strings
m_linkFormat = getString(IDS_LINK_FORMAT);
m_intervalFormat = getString(IDS_LINK_INTERVAL_FORMAT);
m_newLinkLabel = getString(IDS_NEW_LINK);
m_sideLabel[kLeft - kFirstDirection] = getString(IDS_SIDE_LEFT);
m_sideLabel[kRight - kFirstDirection] = getString(IDS_SIDE_RIGHT);
m_sideLabel[kTop - kFirstDirection] = getString(IDS_SIDE_TOP);
m_sideLabel[kBottom - kFirstDirection] = getString(IDS_SIDE_BOTTOM);
// GDI objects
m_redPen = CreatePen(PS_INSIDEFRAME, 1, RGB(255, 0, 0));
}
CScreensLinks::~CScreensLinks()
{
DeleteObject(m_redPen);
s_singleton = NULL;
}
void
CScreensLinks::doModal()
{
// do dialog
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_SCREENS_LINKS),
m_parent, (DLGPROC)dlgProc, (LPARAM)this);
}
void
CScreensLinks::init(HWND hwnd)
{
// get initial config
m_scratchConfig = *m_mainConfig;
// fill side list box (in EDirection order)
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
SendMessage(child, CB_ADDSTRING, 0, (LPARAM)TEXT("---"));
SendMessage(child, CB_ADDSTRING, 0,
(LPARAM)getString(IDS_EDGE_LEFT).c_str());
SendMessage(child, CB_ADDSTRING, 0,
(LPARAM)getString(IDS_EDGE_RIGHT).c_str());
SendMessage(child, CB_ADDSTRING, 0,
(LPARAM)getString(IDS_EDGE_TOP).c_str());
SendMessage(child, CB_ADDSTRING, 0,
(LPARAM)getString(IDS_EDGE_BOTTOM).c_str());
// create error boxes
m_srcSideError = createErrorBox(hwnd);
m_srcScreenError = createErrorBox(hwnd);
m_dstScreenError = createErrorBox(hwnd);
resizeErrorBoxes();
m_selectedLink = -1;
m_editedLink = CEdgeLink();
m_edgeLinks.clear();
updateScreens(hwnd, "");
updateScreensControls(hwnd);
updateLinks(hwnd);
updateLinksControls(hwnd);
}
bool
CScreensLinks::save(HWND /*hwnd*/)
{
*m_mainConfig = m_scratchConfig;
return true;
}
BOOL
CScreensLinks::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
init(hwnd);
return TRUE;
case WM_SIZE:
resizeErrorBoxes();
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
SetFocus(getItem(hwnd, IDOK));
if (save(hwnd)) {
EndDialog(hwnd, 0);
}
return TRUE;
case IDCANCEL:
EndDialog(hwnd, 0);
return TRUE;
case IDC_SCREENS_SCREENS:
switch (HIWORD(wParam)) {
case LBN_DBLCLK:
editScreen(hwnd);
return TRUE;
case LBN_SELCHANGE:
updateScreensControls(hwnd);
updateLinkView(hwnd);
return TRUE;
case LBN_SELCANCEL:
updateScreensControls(hwnd);
updateLinkView(hwnd);
return TRUE;
}
break;
case IDC_SCREENS_ADD_SCREEN:
addScreen(hwnd);
return TRUE;
case IDC_SCREENS_REMOVE_SCREEN:
removeScreen(hwnd);
return TRUE;
case IDC_SCREENS_EDIT_SCREEN:
editScreen(hwnd);
return TRUE;
case IDC_SCREENS_LINKS:
switch (HIWORD(wParam)) {
case LBN_SELCHANGE:
editLink(hwnd);
return TRUE;
case LBN_SELCANCEL:
editLink(hwnd);
return TRUE;
}
break;
case IDC_SCREENS_ADD_LINK:
addLink(hwnd);
return TRUE;
case IDC_SCREENS_REMOVE_LINK:
removeLink(hwnd);
return TRUE;
case IDC_SCREENS_SRC_SIDE:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
changeSrcSide(hwnd);
break;
}
break;
case IDC_SCREENS_SRC_SCREEN:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
changeSrcScreen(hwnd);
break;
}
break;
case IDC_SCREENS_DST_SCREEN:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
changeDstScreen(hwnd);
break;
}
break;
case IDC_SCREENS_SRC_START:
switch (HIWORD(wParam)) {
case EN_KILLFOCUS:
changeIntervalStart(hwnd, LOWORD(wParam),
m_editedLink.m_srcInterval);
break;
}
break;
case IDC_SCREENS_SRC_END:
switch (HIWORD(wParam)) {
case EN_KILLFOCUS:
changeIntervalEnd(hwnd, LOWORD(wParam),
m_editedLink.m_srcInterval);
break;
}
break;
case IDC_SCREENS_DST_START:
switch (HIWORD(wParam)) {
case EN_KILLFOCUS:
changeIntervalStart(hwnd, LOWORD(wParam),
m_editedLink.m_dstInterval);
break;
}
break;
case IDC_SCREENS_DST_END:
switch (HIWORD(wParam)) {
case EN_KILLFOCUS:
changeIntervalEnd(hwnd, LOWORD(wParam),
m_editedLink.m_dstInterval);
break;
}
break;
}
break;
case WM_CTLCOLORSTATIC:
switch (GetDlgCtrlID((HWND)lParam)) {
case IDC_SCREENS_OVERLAP_ERROR:
SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE));
SetTextColor((HDC)wParam, RGB(255, 0, 0));
return (BOOL)GetSysColorBrush(COLOR_3DFACE);
}
break;
// error outlines
case WM_DRAWITEM: {
DRAWITEMSTRUCT* di = (DRAWITEMSTRUCT*)lParam;
if (di->CtlType == ODT_STATIC) {
HGDIOBJ oldPen = SelectObject(di->hDC, m_redPen);
HGDIOBJ oldBrush = SelectObject(di->hDC,
GetStockObject(NULL_BRUSH));
Rectangle(di->hDC, di->rcItem.left, di->rcItem.top,
di->rcItem.right, di->rcItem.bottom);
SelectObject(di->hDC, oldPen);
SelectObject(di->hDC, oldBrush);
return TRUE;
}
break;
}
default:
break;
}
return FALSE;
}
BOOL CALLBACK
CScreensLinks::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
}
CString
CScreensLinks::getSelectedScreen(HWND hwnd) const
{
HWND child = getItem(hwnd, IDC_SCREENS_SCREENS);
LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0);
if (index == LB_ERR) {
return CString();
}
LRESULT size = SendMessage(child, LB_GETTEXTLEN, index, 0);
char* buffer = new char[size + 1];
SendMessage(child, LB_GETTEXT, index, (LPARAM)buffer);
buffer[size] = '\0';
CString result(buffer);
delete[] buffer;
return result;
}
void
CScreensLinks::addScreen(HWND hwnd)
{
CAddScreen dialog(hwnd, m_config, "");
if (dialog.doModal()) {
updateScreens(hwnd, dialog.getName());
updateScreensControls(hwnd);
updateLinks(hwnd);
updateLinksControls(hwnd);
}
}
void
CScreensLinks::editScreen(HWND hwnd)
{
CString oldName = getSelectedScreen(hwnd);
CAddScreen dialog(hwnd, m_config, oldName);
if (dialog.doModal()) {
CString newName = dialog.getName();
// rename screens in the edge list
if (newName != oldName) {
for (size_t i = 0; i < m_edgeLinks.size(); ++i) {
m_edgeLinks[i].rename(oldName, newName);
}
m_editedLink.rename(oldName, newName);
}
updateScreens(hwnd, newName);
updateScreensControls(hwnd);
updateLinks(hwnd);
updateLinksControls(hwnd);
}
}
void
CScreensLinks::removeScreen(HWND hwnd)
{
// remove screen from config (this also removes aliases)
m_config->removeScreen(getSelectedScreen(hwnd));
// update dialog
updateScreens(hwnd, "");
updateScreensControls(hwnd);
updateLinks(hwnd);
updateLinksControls(hwnd);
}
void
CScreensLinks::addLink(HWND hwnd)
{
if (m_editedLink.connect(m_config)) {
m_editedLink = CEdgeLink();
updateLinks(hwnd);
updateLinksControls(hwnd);
}
}
void
CScreensLinks::editLink(HWND hwnd)
{
// get selection
HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
DWORD i = SendMessage(child, LB_GETCURSEL, 0, 0);
if (i != LB_ERR && i != (DWORD)m_edgeLinks.size()) {
// existing link
m_selectedLink = (SInt32)SendMessage(child, LB_GETITEMDATA, i, 0);
m_editedLink = m_edgeLinks[m_selectedLink];
}
else {
// new link
m_selectedLink = -1;
m_editedLink = CEdgeLink();
}
updateLinksControls(hwnd);
}
void
CScreensLinks::removeLink(HWND hwnd)
{
if (m_editedLink.disconnect(m_config)) {
updateLinks(hwnd);
updateLinksControls(hwnd);
}
}
void
CScreensLinks::updateScreens(HWND hwnd, const CString& selectName)
{
HWND child;
// set screen list
child = getItem(hwnd, IDC_SCREENS_SCREENS);
SendMessage(child, LB_RESETCONTENT, 0, 0);
for (CConfig::const_iterator index = m_config->begin();
index != m_config->end(); ) {
const CString& name = *index;
++index;
if (index != m_config->end()) {
SendMessage(child, LB_INSERTSTRING,
(WPARAM)-1, (LPARAM)name.c_str());
}
else {
SendMessage(child, LB_ADDSTRING, 0, (LPARAM)name.c_str());
}
}
// find the named screen
if (!selectName.empty()) {
DWORD i = SendMessage(child, LB_FINDSTRINGEXACT,
(UINT)-1, (LPARAM)selectName.c_str());
if (i != LB_ERR) {
SendMessage(child, LB_SETSEL, TRUE, i);
}
}
}
void
CScreensLinks::updateScreensControls(HWND hwnd)
{
HWND child = getItem(hwnd, IDC_SCREENS_SCREENS);
bool screenSelected = (SendMessage(child, LB_GETCURSEL, 0, 0) != LB_ERR);
enableItem(hwnd, IDC_SCREENS_ADD_SCREEN, TRUE);
enableItem(hwnd, IDC_SCREENS_EDIT_SCREEN, screenSelected);
enableItem(hwnd, IDC_SCREENS_REMOVE_SCREEN, screenSelected);
}
void
CScreensLinks::updateLinks(HWND hwnd)
{
HWND links = getItem(hwnd, IDC_SCREENS_LINKS);
HWND srcScreens = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
HWND dstScreens = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
// get old selection
CEdgeLink oldLink;
if (m_selectedLink != -1) {
oldLink = m_edgeLinks[m_selectedLink];
}
// clear links and screens
SendMessage(links, LB_RESETCONTENT, 0, 0);
SendMessage(srcScreens, CB_RESETCONTENT, 0, 0);
SendMessage(dstScreens, CB_RESETCONTENT, 0, 0);
m_edgeLinks.clear();
// add "no screen" items
SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
// add links and screens
for (CConfig::const_iterator i = m_config->begin();
i != m_config->end(); ++i) {
const CString& name = *i;
// add screen
SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1,
(LPARAM)name.c_str());
SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1,
(LPARAM)name.c_str());
// add links for screen
for (CConfig::link_const_iterator j = m_config->beginNeighbor(name),
n = m_config->endNeighbor(name);
j != n; ++j) {
DWORD k = m_edgeLinks.size();
m_edgeLinks.push_back(CEdgeLink(name, *j));
SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
(LPARAM)formatLink(m_edgeLinks.back()).c_str());
SendMessage(links, LB_SETITEMDATA, (WPARAM)k, (LPARAM)k);
}
}
// add "new link" item to sort
SendMessage(links, LB_ADDSTRING, 0, (LPARAM)m_newLinkLabel.c_str());
// remove the "new link" item then insert it on the end
DWORD i = SendMessage(links, LB_FINDSTRINGEXACT,
(UINT)-1, (LPARAM)m_newLinkLabel.c_str());
if (i != LB_ERR) {
SendMessage(links, LB_DELETESTRING, i, 0);
}
SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
(LPARAM)getString(IDS_NEW_LINK).c_str());
SendMessage(links, LB_SETITEMDATA, (WPARAM)m_edgeLinks.size(),
(LPARAM)-1);
// select the same link as before
SendMessage(links, LB_SETCURSEL, (WPARAM)m_edgeLinks.size(), 0);
if (m_selectedLink != -1) {
m_selectedLink = -1;
for (size_t j = 0; j < m_edgeLinks.size(); ++j) {
if (m_edgeLinks[j] == oldLink) {
// found matching link
m_selectedLink = j;
for (size_t k = 0; k < m_edgeLinks.size(); ++k) {
if (SendMessage(links, LB_GETITEMDATA, k, 0) == (int)j) {
SendMessage(links, LB_SETCURSEL, k, 0);
break;
}
}
break;
}
}
// if we can't find the link anymore then reset edited link
if (m_selectedLink == -1) {
m_editedLink = CEdgeLink();
}
}
}
void
CScreensLinks::updateLinksControls(HWND hwnd)
{
// get selection. select "new link" if nothing is selected.
HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
if (m_selectedLink == -1) {
SendMessage(child, LB_SETCURSEL, m_edgeLinks.size(), 0);
}
// enable/disable remove button
enableItem(hwnd, IDC_SCREENS_REMOVE_LINK, m_selectedLink != -1);
// fill link entry controls from m_editedLink
updateLinkEditControls(hwnd, m_editedLink);
updateLinkValid(hwnd, m_editedLink);
updateLinkView(hwnd);
}
void
CScreensLinks::changeSrcSide(HWND hwnd)
{
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
m_editedLink.m_srcSide = (EDirection)SendMessage(child, CB_GETCURSEL, 0, 0);
updateLink(hwnd);
}
void
CScreensLinks::changeSrcScreen(HWND hwnd)
{
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
m_editedLink.m_srcName = getWindowText(child);
updateLink(hwnd);
}
void
CScreensLinks::changeDstScreen(HWND hwnd)
{
HWND child = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
m_editedLink.m_dstName = getWindowText(child);
updateLink(hwnd);
}
void
CScreensLinks::changeIntervalStart(HWND hwnd, int id, CConfig::CInterval& i)
{
int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
if (x < 0) {
x = 0;
}
else if (x > 99) {
x = 99;
}
i.first = 0.01f * (float)x;
if (i.first >= i.second) {
i.second = 0.01f * (float)(x + 1);
}
updateLinkIntervalControls(hwnd, m_editedLink);
updateLink(hwnd);
}
void
CScreensLinks::changeIntervalEnd(HWND hwnd, int id, CConfig::CInterval& i)
{
int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
if (x < 1) {
x = 1;
}
else if (x > 100) {
x = 100;
}
i.second = 0.01f * (float)x;
if (i.first >= i.second) {
i.first = 0.01f * (float)(x - 1);
}
updateLinkIntervalControls(hwnd, m_editedLink);
updateLink(hwnd);
}
void
CScreensLinks::selectScreen(HWND hwnd, int id, const CString& name)
{
HWND child = getItem(hwnd, id);
DWORD i = SendMessage(child, CB_FINDSTRINGEXACT, (WPARAM)-1,
(LPARAM)name.c_str());
if (i == CB_ERR) {
// no match, select no screen
SendMessage(child, CB_SETCURSEL, 0, 0);
}
else {
SendMessage(child, CB_SETCURSEL, i, 0);
}
}
void
CScreensLinks::updateLinkEditControls(HWND hwnd, const CEdgeLink& link)
{
// fill link entry controls from link
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
SendMessage(child, CB_SETCURSEL, link.m_srcSide, 0);
selectScreen(hwnd, IDC_SCREENS_SRC_SCREEN, link.m_srcName);
selectScreen(hwnd, IDC_SCREENS_DST_SCREEN, link.m_dstName);
updateLinkIntervalControls(hwnd, link);
}
void
CScreensLinks::updateLinkIntervalControls(HWND hwnd, const CEdgeLink& link)
{
HWND child;
// src interval
child = getItem(hwnd, IDC_SCREENS_SRC_START);
setWindowText(child, formatIntervalValue(link.m_srcInterval.first));
child = getItem(hwnd, IDC_SCREENS_SRC_END);
setWindowText(child, formatIntervalValue(link.m_srcInterval.second));
// dst interval
child = getItem(hwnd, IDC_SCREENS_DST_START);
setWindowText(child, formatIntervalValue(link.m_dstInterval.first));
child = getItem(hwnd, IDC_SCREENS_DST_END);
setWindowText(child, formatIntervalValue(link.m_dstInterval.second));
}
void
CScreensLinks::updateLink(HWND hwnd)
{
updateLinkValid(hwnd, m_editedLink);
// update link in config
if (m_selectedLink != -1 && m_editedLinkIsValid) {
// editing an existing link and entry is valid
if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
// successfully removed old link
if (!m_editedLink.connect(m_config)) {
// couldn't set new link so restore old link
m_edgeLinks[m_selectedLink].connect(m_config);
}
else {
m_edgeLinks[m_selectedLink] = m_editedLink;
updateLinks(hwnd);
updateLinkEditControls(hwnd, m_editedLink);
}
}
}
updateLinkView(hwnd);
}
void
CScreensLinks::updateLinkValid(HWND hwnd, const CEdgeLink& link)
{
m_editedLinkIsValid = true;
// check source side and screen
if (link.m_srcSide == kNoDirection) {
m_editedLinkIsValid = false;
ShowWindow(m_srcSideError, SW_SHOWNA);
}
else {
ShowWindow(m_srcSideError, SW_HIDE);
}
if (!m_config->isCanonicalName(link.m_srcName)) {
m_editedLinkIsValid = false;
ShowWindow(m_srcScreenError, SW_SHOWNA);
}
else {
ShowWindow(m_srcScreenError, SW_HIDE);
}
// check for overlap. if editing a link we must remove it, then
// check for overlap and restore the old link.
bool overlap = false;
if (m_editedLinkIsValid) {
if (m_selectedLink == -1) {
if (link.overlaps(m_config)) {
m_editedLinkIsValid = false;
overlap = true;
}
}
else {
if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
overlap = link.overlaps(m_config);
m_edgeLinks[m_selectedLink].connect(m_config);
if (overlap) {
m_editedLinkIsValid = false;
}
}
}
}
ShowWindow(getItem(hwnd, IDC_SCREENS_OVERLAP_ERROR),
overlap ? SW_SHOWNA : SW_HIDE);
// check dst screen
if (!m_config->isCanonicalName(link.m_dstName)) {
m_editedLinkIsValid = false;
ShowWindow(m_dstScreenError, SW_SHOWNA);
}
else {
ShowWindow(m_dstScreenError, SW_HIDE);
}
// update add link button
enableItem(hwnd, IDC_SCREENS_ADD_LINK,
m_selectedLink == -1 && m_editedLinkIsValid);
}
void
CScreensLinks::updateLinkView(HWND /*hwnd*/)
{
// XXX -- draw visual of selected screen, highlighting selected link
}
HWND
CScreensLinks::createErrorBox(HWND parent)
{
return CreateWindow(TEXT("STATIC"), TEXT(""),
WS_CHILD | SS_OWNERDRAW,
0, 0, 1, 1,
parent, (HMENU)-1,
s_instance, NULL);
}
void
CScreensLinks::resizeErrorBoxes()
{
HWND hwnd = GetParent(m_srcSideError);
resizeErrorBox(m_srcSideError, getItem(hwnd, IDC_SCREENS_SRC_SIDE));
resizeErrorBox(m_srcScreenError, getItem(hwnd, IDC_SCREENS_SRC_SCREEN));
resizeErrorBox(m_dstScreenError, getItem(hwnd, IDC_SCREENS_DST_SCREEN));
}
void
CScreensLinks::resizeErrorBox(HWND box, HWND assoc)
{
RECT rect;
GetWindowRect(assoc, &rect);
MapWindowPoints(NULL, GetParent(box), (POINT*)&rect, 2);
SetWindowPos(box, HWND_TOP, rect.left - 1, rect.top - 1,
rect.right - rect.left + 2,
rect.bottom - rect.top + 2, SWP_NOACTIVATE);
}
CString
CScreensLinks::formatIntervalValue(float x) const
{
return CStringUtil::print("%d", (int)(x * 100.0f + 0.5f));
}
CString
CScreensLinks::formatInterval(const CConfig::CInterval& i) const
{
if (i.first == 0.0f && i.second == 1.0f) {
return "";
}
else {
CString start = formatIntervalValue(i.first);
CString end = formatIntervalValue(i.second);
return CStringUtil::format(m_intervalFormat.c_str(),
start.c_str(), end.c_str());
}
}
CString
CScreensLinks::formatLink(const CEdgeLink& link) const
{
CString srcInterval = formatInterval(link.m_srcInterval);
CString dstInterval = formatInterval(link.m_dstInterval);
return CStringUtil::format(m_linkFormat.c_str(),
link.m_srcName.c_str(), srcInterval.c_str(),
m_sideLabel[link.m_srcSide - kFirstDirection].c_str(),
link.m_dstName.c_str(), dstInterval.c_str());
}
//
// CScreensLinks::CEdgeLink
//
CScreensLinks::CEdgeLink::CEdgeLink() :
m_srcName(),
m_srcSide(kNoDirection),
m_srcInterval(0.0f, 1.0f),
m_dstName(),
m_dstInterval(0.0f, 1.0f)
{
// do nothing
}
CScreensLinks::CEdgeLink::CEdgeLink(const CString& name,
const CConfigLink& link) :
m_srcName(name),
m_srcSide(link.first.getSide()),
m_srcInterval(link.first.getInterval()),
m_dstName(link.second.getName()),
m_dstInterval(link.second.getInterval())
{
// do nothing
}
bool
CScreensLinks::CEdgeLink::connect(CConfig* config)
{
return config->connect(m_srcName, m_srcSide,
m_srcInterval.first, m_srcInterval.second,
m_dstName,
m_dstInterval.first, m_dstInterval.second);
}
bool
CScreensLinks::CEdgeLink::disconnect(CConfig* config)
{
return config->disconnect(m_srcName, m_srcSide, 0.5f *
(m_srcInterval.first + m_srcInterval.second));
}
void
CScreensLinks::CEdgeLink::rename(const CString& oldName, const CString& newName)
{
if (m_srcName == oldName) {
m_srcName = newName;
}
if (m_dstName == oldName) {
m_dstName = newName;
}
}
bool
CScreensLinks::CEdgeLink::overlaps(const CConfig* config) const
{
return config->hasNeighbor(m_srcName, m_srcSide,
m_srcInterval.first, m_srcInterval.second);
}
bool
CScreensLinks::CEdgeLink::operator==(const CEdgeLink& x) const
{
return (m_srcName == x.m_srcName &&
m_srcSide == x.m_srcSide &&
m_srcInterval == x.m_srcInterval &&
m_dstName == x.m_dstName &&
m_dstInterval == x.m_dstInterval);
}

View File

@@ -0,0 +1,138 @@
/*
* 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 CSCREENSLINKS_H
#define CSCREENSLINKS_H
#include "CConfig.h"
#include "ProtocolTypes.h"
#include "CString.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
//! Screens and links dialog for Microsoft Windows launcher
class CScreensLinks {
public:
CScreensLinks(HWND parent, CConfig*);
~CScreensLinks();
//! @name manipulators
//@{
//! Run dialog
/*!
Display and handle the dialog until closed by the user.
*/
void doModal();
//@}
//! @name accessors
//@{
//@}
private:
typedef std::pair<CConfig::CCellEdge, CConfig::CCellEdge> CConfigLink;
struct CEdgeLink {
public:
CEdgeLink();
CEdgeLink(const CString& name, const CConfigLink&);
bool connect(CConfig*);
bool disconnect(CConfig*);
void rename(const CString& oldName, const CString& newName);
bool overlaps(const CConfig* config) const;
bool operator==(const CEdgeLink&) const;
public:
CString m_srcName;
EDirection m_srcSide;
CConfig::CInterval m_srcInterval;
CString m_dstName;
CConfig::CInterval m_dstInterval;
};
typedef std::vector<CEdgeLink> CEdgeLinkList;
void init(HWND hwnd);
bool save(HWND hwnd);
CString getSelectedScreen(HWND hwnd) const;
void addScreen(HWND hwnd);
void editScreen(HWND hwnd);
void removeScreen(HWND hwnd);
void addLink(HWND hwnd);
void editLink(HWND hwnd);
void removeLink(HWND hwnd);
void updateScreens(HWND hwnd, const CString& name);
void updateScreensControls(HWND hwnd);
void updateLinks(HWND hwnd);
void updateLinksControls(HWND hwnd);
void changeSrcSide(HWND hwnd);
void changeSrcScreen(HWND hwnd);
void changeDstScreen(HWND hwnd);
void changeIntervalStart(HWND hwnd, int id,
CConfig::CInterval&);
void changeIntervalEnd(HWND hwnd, int id,
CConfig::CInterval&);
void selectScreen(HWND hwnd, int id, const CString& name);
void updateLinkEditControls(HWND hwnd,
const CEdgeLink& link);
void updateLinkIntervalControls(HWND hwnd,
const CEdgeLink& link);
void updateLink(HWND hwnd);
void updateLinkValid(HWND hwnd, const CEdgeLink& link);
void updateLinkView(HWND hwnd);
HWND createErrorBox(HWND parent);
void resizeErrorBoxes();
void resizeErrorBox(HWND box, HWND assoc);
CString formatIntervalValue(float) const;
CString formatInterval(const CConfig::CInterval&) const;
CString formatLink(const CEdgeLink&) const;
// message handling
BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM);
static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);
private:
static CScreensLinks* s_singleton;
HWND m_parent;
CConfig* m_mainConfig;
CConfig m_scratchConfig;
CConfig* m_config;
CString m_linkFormat;
CString m_intervalFormat;
CString m_newLinkLabel;
CString m_sideLabel[kNumDirections];
CEdgeLinkList m_edgeLinks;
SInt32 m_selectedLink;
CEdgeLink m_editedLink;
bool m_editedLinkIsValid;
HPEN m_redPen;
HWND m_srcSideError;
HWND m_srcScreenError;
HWND m_dstScreenError;
};
#endif

261
cmd/launcher/LaunchUtil.cpp Normal file
View File

@@ -0,0 +1,261 @@
/*
* 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 "CConfig.h"
#include "LaunchUtil.h"
#include "CMSWindowsUtil.h"
#include "CArch.h"
#include "resource.h"
#include "stdfstream.h"
size_t s_showingDialog = 0;
CString
getString(DWORD id)
{
return CMSWindowsUtil::getString(s_instance, id);
}
CString
getErrorString(DWORD error)
{
return CMSWindowsUtil::getErrorString(s_instance, error, IDS_ERROR);
}
void
showError(HWND hwnd, const CString& msg)
{
CString title = getString(IDS_ERROR);
++s_showingDialog;
MessageBox(hwnd, msg.c_str(), title.c_str(), MB_OK | MB_APPLMODAL);
--s_showingDialog;
}
void
askOkay(HWND hwnd, const CString& title, const CString& msg)
{
++s_showingDialog;
MessageBox(hwnd, msg.c_str(), title.c_str(), MB_OK | MB_APPLMODAL);
--s_showingDialog;
}
bool
askVerify(HWND hwnd, const CString& msg)
{
CString title = getString(IDS_VERIFY);
++s_showingDialog;
int result = MessageBox(hwnd, msg.c_str(),
title.c_str(), MB_OKCANCEL | MB_APPLMODAL);
--s_showingDialog;
return (result == IDOK);
}
bool
isShowingDialog()
{
return (s_showingDialog != 0);
}
void
setWindowText(HWND hwnd, const CString& msg)
{
SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)msg.c_str());
}
CString
getWindowText(HWND hwnd)
{
LRESULT size = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
char* buffer = new char[size + 1];
SendMessage(hwnd, WM_GETTEXT, size + 1, (LPARAM)buffer);
buffer[size] = '\0';
CString result(buffer);
delete[] buffer;
return result;
}
HWND
getItem(HWND hwnd, int id)
{
return GetDlgItem(hwnd, id);
}
void
enableItem(HWND hwnd, int id, bool enabled)
{
EnableWindow(GetDlgItem(hwnd, id), enabled);
}
void
setItemChecked(HWND hwnd, bool checked)
{
SendMessage(hwnd, BM_SETCHECK, checked ? BST_CHECKED : BST_UNCHECKED, 0);
}
bool
isItemChecked(HWND hwnd)
{
return (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED);
}
CString
getAppPath(const CString& appName)
{
// prepare path to app
char myPathname[MAX_PATH];
GetModuleFileName(s_instance, myPathname, MAX_PATH);
const char* myBasename = ARCH->getBasename(myPathname);
CString appPath = CString(myPathname, myBasename - myPathname);
appPath += appName;
return appPath;
}
static
void
getFileTime(const CString& path, time_t& t)
{
struct _stat s;
if (_stat(path.c_str(), &s) != -1) {
t = s.st_mtime;
}
}
bool
isConfigNewer(time_t& oldTime, bool userConfig)
{
time_t newTime = oldTime;
if (userConfig) {
CString path = ARCH->getUserDirectory();
if (!path.empty()) {
path = ARCH->concatPath(path, CONFIG_NAME);
getFileTime(path, newTime);
}
}
else {
CString path = ARCH->getSystemDirectory();
if (!path.empty()) {
path = ARCH->concatPath(path, CONFIG_NAME);
getFileTime(path, newTime);
}
}
bool result = (newTime > oldTime);
oldTime = newTime;
return result;
}
static
bool
loadConfig(const CString& pathname, CConfig& config)
{
try {
std::ifstream stream(pathname.c_str());
if (stream) {
stream >> config;
return true;
}
}
catch (...) {
// ignore
}
return false;
}
bool
loadConfig(CConfig& config, time_t& t, bool& userConfig)
{
// load configuration
bool configLoaded = false;
CString path = ARCH->getUserDirectory();
if (!path.empty()) {
// try loading the user's configuration
path = ARCH->concatPath(path, CONFIG_NAME);
if (loadConfig(path, config)) {
configLoaded = true;
userConfig = true;
getFileTime(path, t);
}
else {
// try the system-wide config file
path = ARCH->getSystemDirectory();
if (!path.empty()) {
path = ARCH->concatPath(path, CONFIG_NAME);
if (loadConfig(path, config)) {
configLoaded = true;
userConfig = false;
getFileTime(path, t);
}
}
}
}
return configLoaded;
}
static
bool
saveConfig(const CString& pathname, const CConfig& config)
{
try {
std::ofstream stream(pathname.c_str());
if (stream) {
stream << config;
return !!stream;
}
}
catch (...) {
// ignore
}
return false;
}
bool
saveConfig(const CConfig& config, bool sysOnly, time_t& t)
{
// try saving the user's configuration
if (!sysOnly) {
CString path = ARCH->getUserDirectory();
if (!path.empty()) {
path = ARCH->concatPath(path, CONFIG_NAME);
if (saveConfig(path, config)) {
getFileTime(path, t);
return true;
}
}
}
// try the system-wide config file
else {
CString path = ARCH->getSystemDirectory();
if (!path.empty()) {
path = ARCH->concatPath(path, CONFIG_NAME);
if (saveConfig(path, config)) {
getFileTime(path, t);
return true;
}
}
}
return false;
}
const TCHAR* const*
getSettingsPath()
{
static const TCHAR* s_keyNames[] = {
TEXT("Software"),
TEXT("Synergy"),
TEXT("Synergy"),
NULL
};
return s_keyNames;
}

61
cmd/launcher/LaunchUtil.h Normal file
View File

@@ -0,0 +1,61 @@
/*
* 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 LAUNCHUTIL_H
#define LAUNCHUTIL_H
#include "CString.h"
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#define CLIENT_APP "synergyc.exe"
#define SERVER_APP "synergys.exe"
#define CONFIG_NAME "synergy.sgc"
class CConfig;
// client must define this and set it before calling any function here
extern HINSTANCE s_instance;
CString getString(DWORD id);
CString getErrorString(DWORD error);
void showError(HWND hwnd, const CString& msg);
void askOkay(HWND hwnd, const CString& title,
const CString& msg);
bool askVerify(HWND hwnd, const CString& msg);
bool isShowingDialog();
void setWindowText(HWND hwnd, const CString& msg);
CString getWindowText(HWND hwnd);
HWND getItem(HWND hwnd, int id);
void enableItem(HWND hwnd, int id, bool enabled);
void setItemChecked(HWND, bool);
bool isItemChecked(HWND);
CString getAppPath(const CString& appName);
bool isConfigNewer(time_t&, bool userConfig);
bool loadConfig(CConfig& config, time_t&, bool& userConfig);
bool saveConfig(const CConfig& config,
bool sysOnly, time_t&);
const TCHAR* const* getSettingsPath();
#endif

75
cmd/launcher/Makefile.am Normal file
View File

@@ -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.
## Process this file with automake to produce Makefile.in
NULL =
MSWINDOWS_SOURCE_FILES = \
CAddScreen.cpp \
CAdvancedOptions.cpp \
CAutoStart.cpp \
CGlobalOptions.cpp \
CHotkeyOptions.cpp \
CInfo.cpp \
CScreensLinks.cpp \
LaunchUtil.cpp \
launcher.cpp \
CAddScreen.h \
CAdvancedOptions.h \
CAutoStart.h \
CGlobalOptions.h \
CHotkeyOptions.h \
CInfo.h \
CScreensLinks.h \
LaunchUtil.h \
resource.h \
launcher.rc \
$(NULL)
EXTRA_DIST = \
Makefile.win \
synergy.ico \
$(MSWINDOWS_SOURCE_FILES) \
$(NULL)
MAINTAINERCLEANFILES = \
Makefile.in \
$(NULL)
if MSWINDOWS
bin_PROGRAMS = synergy
synergy_SOURCES = \
$(MSWINDOWS_SOURCE_FILES) \
$(NULL)
endif
synergy_LDADD = \
$(top_builddir)/lib/server/libserver.a \
$(top_builddir)/lib/platform/libplatform.a \
$(top_builddir)/lib/synergy/libsynergy.a \
$(top_builddir)/lib/net/libnet.a \
$(top_builddir)/lib/io/libio.a \
$(top_builddir)/lib/mt/libmt.a \
$(top_builddir)/lib/base/libbase.a \
$(top_builddir)/lib/common/libcommon.a \
$(top_builddir)/lib/arch/libarch.a \
$(NULL)
INCLUDES = \
-I$(top_srcdir)/lib/common \
-I$(top_srcdir)/lib/arch \
-I$(top_srcdir)/lib/base \
-I$(top_srcdir)/lib/mt \
-I$(top_srcdir)/lib/io \
-I$(top_srcdir)/lib/net \
-I$(top_srcdir)/lib/synergy \
-I$(top_srcdir)/lib/platform \
-I$(top_srcdir)/lib/server \
$(NULL)

101
cmd/launcher/Makefile.win Normal file
View File

@@ -0,0 +1,101 @@
# synergy -- mouse and keyboard sharing utility
# Copyright (C) 2007 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.
BIN_LAUNCHER_SRC = cmd\launcher
BIN_LAUNCHER_DST = $(BUILD_DST)\$(BIN_LAUNCHER_SRC)
BIN_LAUNCHER_EXE = "$(BUILD_DST)\synergy.exe"
BIN_LAUNCHER_CPP = \
"CAddScreen.cpp" \
"CAdvancedOptions.cpp" \
"CAutoStart.cpp" \
"CGlobalOptions.cpp" \
"CHotkeyOptions.cpp" \
"CInfo.cpp" \
"CScreensLinks.cpp" \
"LaunchUtil.cpp" \
"launcher.cpp" \
$(NULL)
BIN_LAUNCHER_OBJ = \
"$(BIN_LAUNCHER_DST)\CAddScreen.obj" \
"$(BIN_LAUNCHER_DST)\CAdvancedOptions.obj" \
"$(BIN_LAUNCHER_DST)\CAutoStart.obj" \
"$(BIN_LAUNCHER_DST)\CGlobalOptions.obj" \
"$(BIN_LAUNCHER_DST)\CHotkeyOptions.obj" \
"$(BIN_LAUNCHER_DST)\CInfo.obj" \
"$(BIN_LAUNCHER_DST)\CScreensLinks.obj" \
"$(BIN_LAUNCHER_DST)\LaunchUtil.obj" \
"$(BIN_LAUNCHER_DST)\launcher.obj" \
$(NULL)
BIN_LAUNCHER_RC = "$(BIN_LAUNCHER_SRC)\launcher.rc"
BIN_LAUNCHER_RES = "$(BIN_LAUNCHER_DST)\launcher.res"
BIN_LAUNCHER_INC = \
/I"lib\common" \
/I"lib\arch" \
/I"lib\base" \
/I"lib\mt" \
/I"lib\io" \
/I"lib\net" \
/I"lib\synergy" \
/I"lib\platform" \
/I"lib\server" \
$(NULL)
BIN_LAUNCHER_LIB = \
$(LIB_SERVER_LIB) \
$(LIB_PLATFORM_LIB) \
$(LIB_SYNERGY_LIB) \
$(LIB_NET_LIB) \
$(LIB_IO_LIB) \
$(LIB_MT_LIB) \
$(LIB_BASE_LIB) \
$(LIB_ARCH_LIB) \
$(LIB_COMMON_LIB) \
$(NULL)
CPP_FILES = $(CPP_FILES) $(BIN_LAUNCHER_CPP)
OBJ_FILES = $(OBJ_FILES) $(BIN_LAUNCHER_OBJ)
PROGRAMS = $(PROGRAMS) $(BIN_LAUNCHER_EXE)
# Need shell functions.
guilibs = $(guilibs) shell32.lib
# Dependency rules
$(BIN_LAUNCHER_OBJ): $(AUTODEP)
!if EXIST($(BIN_LAUNCHER_DST)\deps.mak)
!include $(BIN_LAUNCHER_DST)\deps.mak
!endif
# Build rules. Use batch-mode rules if possible.
!if DEFINED(_NMAKE_VER)
{$(BIN_LAUNCHER_SRC)\}.cpp{$(BIN_LAUNCHER_DST)\}.obj::
!else
{$(BIN_LAUNCHER_SRC)\}.cpp{$(BIN_LAUNCHER_DST)\}.obj:
!endif
@$(ECHO) Compile in $(BIN_LAUNCHER_SRC)
-@$(MKDIR) $(BIN_LAUNCHER_DST) 2>NUL:
$(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \
$(BIN_LAUNCHER_INC) \
/Fo$(BIN_LAUNCHER_DST)\ \
/Fd$(BIN_LAUNCHER_DST)\src.pdb \
$< | $(AUTODEP) $(BIN_LAUNCHER_SRC) $(BIN_LAUNCHER_DST)
$(BIN_LAUNCHER_RES): $(BIN_LAUNCHER_RC)
@$(ECHO) Compile $(**F)
-@$(MKDIR) $(BIN_LAUNCHER_DST) 2>NUL:
$(rc) $(rcflags) $(rcvars) \
/fo$@ \
$**
$(BIN_LAUNCHER_EXE): $(BIN_LAUNCHER_OBJ) $(BIN_LAUNCHER_RES) $(BIN_LAUNCHER_LIB)
@$(ECHO) Link $(@F)
$(link) $(ldebug) $(guilflags) $(guilibsmt) \
/out:$@ \
$**
$(AUTODEP) $(BIN_LAUNCHER_SRC) $(BIN_LAUNCHER_DST) \
$(BIN_LAUNCHER_OBJ:.obj=.d)

755
cmd/launcher/launcher.cpp Normal file
View File

@@ -0,0 +1,755 @@
/*
* 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 "CConfig.h"
#include "KeyTypes.h"
#include "OptionTypes.h"
#include "ProtocolTypes.h"
#include "CLog.h"
#include "CStringUtil.h"
#include "CArch.h"
#include "CArchMiscWindows.h"
#include "XArch.h"
#include "Version.h"
#include "stdvector.h"
#include "resource.h"
// these must come after the above because it includes windows.h
#include "LaunchUtil.h"
#include "CAddScreen.h"
#include "CAdvancedOptions.h"
#include "CAutoStart.h"
#include "CGlobalOptions.h"
#include "CHotkeyOptions.h"
#include "CInfo.h"
#include "CScreensLinks.h"
typedef std::vector<CString> CStringList;
class CChildWaitInfo {
public:
HWND m_dialog;
HANDLE m_child;
DWORD m_childID;
HANDLE m_ready;
HANDLE m_stop;
};
static const char* s_debugName[][2] = {
{ TEXT("Error"), "ERROR" },
{ TEXT("Warning"), "WARNING" },
{ TEXT("Note"), "NOTE" },
{ TEXT("Info"), "INFO" },
{ TEXT("Debug"), "DEBUG" },
{ TEXT("Debug1"), "DEBUG1" },
{ TEXT("Debug2"), "DEBUG2" }
};
static const int s_defaultDebug = 1; // WARNING
static const int s_minTestDebug = 3; // INFO
HINSTANCE s_instance = NULL;
static CGlobalOptions* s_globalOptions = NULL;
static CAdvancedOptions* s_advancedOptions = NULL;
static CHotkeyOptions* s_hotkeyOptions = NULL;
static CScreensLinks* s_screensLinks = NULL;
static CInfo* s_info = NULL;
static bool s_userConfig = true;
static time_t s_configTime = 0;
static CConfig s_lastConfig;
static const TCHAR* s_mainClass = TEXT("GoSynergy");
static const TCHAR* s_layoutClass = TEXT("SynergyLayout");
enum SaveMode {
SAVE_QUITING,
SAVE_NORMAL,
SAVE_QUIET
};
//
// program arguments
//
#define ARG CArgs::s_instance
class CArgs {
public:
CArgs() { s_instance = this; }
~CArgs() { s_instance = NULL; }
public:
static CArgs* s_instance;
CConfig m_config;
CStringList m_screens;
};
CArgs* CArgs::s_instance = NULL;
static
BOOL CALLBACK
addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static
bool
isClientChecked(HWND hwnd)
{
HWND child = getItem(hwnd, IDC_MAIN_CLIENT_RADIO);
return isItemChecked(child);
}
static
void
enableMainWindowControls(HWND hwnd)
{
bool client = isClientChecked(hwnd);
enableItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_LABEL, client);
enableItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT, client);
enableItem(hwnd, IDC_MAIN_SERVER_SCREENS_LABEL, !client);
enableItem(hwnd, IDC_MAIN_SCREENS, !client);
enableItem(hwnd, IDC_MAIN_OPTIONS, !client);
enableItem(hwnd, IDC_MAIN_HOTKEYS, !client);
}
static
bool
execApp(const char* app, const CString& cmdLine, PROCESS_INFORMATION* procInfo)
{
// prepare startup info
STARTUPINFO startup;
startup.cb = sizeof(startup);
startup.lpReserved = NULL;
startup.lpDesktop = NULL;
startup.lpTitle = NULL;
startup.dwX = (DWORD)CW_USEDEFAULT;
startup.dwY = (DWORD)CW_USEDEFAULT;
startup.dwXSize = (DWORD)CW_USEDEFAULT;
startup.dwYSize = (DWORD)CW_USEDEFAULT;
startup.dwXCountChars = 0;
startup.dwYCountChars = 0;
startup.dwFillAttribute = 0;
startup.dwFlags = STARTF_FORCEONFEEDBACK;
startup.wShowWindow = SW_SHOWDEFAULT;
startup.cbReserved2 = 0;
startup.lpReserved2 = NULL;
startup.hStdInput = NULL;
startup.hStdOutput = NULL;
startup.hStdError = NULL;
// prepare path to app
CString appPath = getAppPath(app);
// put path to app in command line
CString commandLine = "\"";
commandLine += appPath;
commandLine += "\" ";
commandLine += cmdLine;
// start child
if (CreateProcess(NULL, (char*)commandLine.c_str(),
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE |
CREATE_NEW_PROCESS_GROUP |
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&startup,
procInfo) == 0) {
return false;
}
else {
return true;
}
}
static
CString
getCommandLine(HWND hwnd, bool testing, bool silent)
{
CString cmdLine;
// add constant testing args
if (testing) {
cmdLine += " -z --no-restart --no-daemon";
}
// can't start as service on NT
else if (!CArchMiscWindows::isWindows95Family()) {
cmdLine += " --no-daemon";
}
// get the server name
CString server;
bool isClient = isClientChecked(hwnd);
if (isClient) {
// check server name
HWND child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT);
server = getWindowText(child);
if (!ARG->m_config.isValidScreenName(server)) {
if (!silent) {
showError(hwnd, CStringUtil::format(
getString(IDS_INVALID_SERVER_NAME).c_str(),
server.c_str()));
}
SetFocus(child);
return CString();
}
// compare server name to local host. a common error
// is to provide the client's name for the server. we
// don't bother to check the addresses though that'd be
// more accurate.
if (CStringUtil::CaselessCmp::equal(ARCH->getHostName(), server)) {
if (!silent) {
showError(hwnd, CStringUtil::format(
getString(IDS_SERVER_IS_CLIENT).c_str(),
server.c_str()));
}
SetFocus(child);
return CString();
}
}
// debug level. always include this.
if (true) {
HWND child = getItem(hwnd, IDC_MAIN_DEBUG);
int debug = (int)SendMessage(child, CB_GETCURSEL, 0, 0);
// if testing then we force the debug level to be no less than
// s_minTestDebug. what's the point of testing if you can't
// see the debugging info?
if (testing && debug < s_minTestDebug) {
debug = s_minTestDebug;
}
cmdLine += " --debug ";
cmdLine += s_debugName[debug][1];
}
// add advanced options
cmdLine += s_advancedOptions->getCommandLine(isClient, server);
return cmdLine;
}
static
bool
launchApp(HWND hwnd, bool testing, HANDLE* thread, DWORD* threadID)
{
if (thread != NULL) {
*thread = NULL;
}
if (threadID != NULL) {
*threadID = 0;
}
// start daemon if it's installed and we're not testing
if (!testing && CAutoStart::startDaemon()) {
return true;
}
// decide if client or server
const bool isClient = isClientChecked(hwnd);
const char* app = isClient ? CLIENT_APP : SERVER_APP;
// prepare command line
CString cmdLine = getCommandLine(hwnd, testing, false);
if (cmdLine.empty()) {
return false;
}
// start child
PROCESS_INFORMATION procInfo;
if (!execApp(app, cmdLine, &procInfo)) {
showError(hwnd, CStringUtil::format(
getString(IDS_STARTUP_FAILED).c_str(),
getErrorString(GetLastError()).c_str()));
return false;
}
// don't need process handle
CloseHandle(procInfo.hProcess);
// save thread handle and thread ID if desired
if (thread != NULL) {
*thread = procInfo.hThread;
}
if (threadID != NULL) {
*threadID = procInfo.dwThreadId;
}
return true;
}
static
BOOL CALLBACK
waitDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// only one wait dialog at a time!
static CChildWaitInfo* info = NULL;
switch (message) {
case WM_INITDIALOG:
// save info pointer
info = reinterpret_cast<CChildWaitInfo*>(lParam);
// save hwnd
info->m_dialog = hwnd;
// signal ready
SetEvent(info->m_ready);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCANCEL:
case IDOK:
// signal stop
SetEvent(info->m_stop);
// done
EndDialog(hwnd, 0);
return TRUE;
}
}
return FALSE;
}
static
DWORD WINAPI
waitForChildThread(LPVOID vinfo)
{
CChildWaitInfo* info = reinterpret_cast<CChildWaitInfo*>(vinfo);
// wait for ready
WaitForSingleObject(info->m_ready, INFINITE);
// wait for thread to complete or stop event
HANDLE handles[2];
handles[0] = info->m_child;
handles[1] = info->m_stop;
DWORD n = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
// if stop was raised then terminate child and wait for it
if (n == WAIT_OBJECT_0 + 1) {
PostThreadMessage(info->m_childID, WM_QUIT, 0, 0);
WaitForSingleObject(info->m_child, INFINITE);
}
// otherwise post IDOK to dialog box
else {
PostMessage(info->m_dialog, WM_COMMAND, MAKEWPARAM(IDOK, 0), 0);
}
return 0;
}
static
void
waitForChild(HWND hwnd, HANDLE thread, DWORD threadID)
{
// prepare info for child wait dialog and thread
CChildWaitInfo info;
info.m_dialog = NULL;
info.m_child = thread;
info.m_childID = threadID;
info.m_ready = CreateEvent(NULL, TRUE, FALSE, NULL);
info.m_stop = CreateEvent(NULL, TRUE, FALSE, NULL);
// create a thread to wait on the child thread and event
DWORD id;
HANDLE waiter = CreateThread(NULL, 0, &waitForChildThread, &info,0, &id);
// do dialog that let's the user terminate the test
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_WAIT), hwnd,
(DLGPROC)waitDlgProc, (LPARAM)&info);
// force the waiter thread to finish and wait for it
SetEvent(info.m_ready);
SetEvent(info.m_stop);
WaitForSingleObject(waiter, INFINITE);
// clean up
CloseHandle(waiter);
CloseHandle(info.m_ready);
CloseHandle(info.m_stop);
}
static
void
initMainWindow(HWND hwnd)
{
// append version number to title
CString titleFormat = getString(IDS_TITLE);
setWindowText(hwnd, CStringUtil::format(titleFormat.c_str(), VERSION));
// load configuration
bool configLoaded =
loadConfig(ARG->m_config, s_configTime, s_userConfig);
if (configLoaded) {
s_lastConfig = ARG->m_config;
}
// get settings from registry
bool isServer = configLoaded;
int debugLevel = s_defaultDebug;
CString server;
HKEY key = CArchMiscWindows::openKey(HKEY_CURRENT_USER, getSettingsPath());
if (key != NULL) {
if (isServer && CArchMiscWindows::hasValue(key, "isServer")) {
isServer = (CArchMiscWindows::readValueInt(key, "isServer") != 0);
}
if (CArchMiscWindows::hasValue(key, "debug")) {
debugLevel = static_cast<int>(
CArchMiscWindows::readValueInt(key, "debug"));
if (debugLevel < 0) {
debugLevel = 0;
}
else if (debugLevel > CLog::kDEBUG2) {
debugLevel = CLog::kDEBUG2;
}
}
server = CArchMiscWindows::readValueString(key, "server");
CArchMiscWindows::closeKey(key);
}
// choose client/server radio buttons
HWND child;
child = getItem(hwnd, IDC_MAIN_CLIENT_RADIO);
setItemChecked(child, !isServer);
child = getItem(hwnd, IDC_MAIN_SERVER_RADIO);
setItemChecked(child, isServer);
// set server name
child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT);
setWindowText(child, server);
// debug level
child = getItem(hwnd, IDC_MAIN_DEBUG);
for (unsigned int i = 0; i < sizeof(s_debugName) /
sizeof(s_debugName[0]); ++i) {
SendMessage(child, CB_ADDSTRING, 0, (LPARAM)s_debugName[i][0]);
}
SendMessage(child, CB_SETCURSEL, debugLevel, 0);
// update controls
enableMainWindowControls(hwnd);
}
static
bool
saveMainWindow(HWND hwnd, SaveMode mode, CString* cmdLineOut = NULL)
{
DWORD errorID = 0;
CString arg;
CString cmdLine;
// save dialog state
bool isClient = isClientChecked(hwnd);
HKEY key = CArchMiscWindows::addKey(HKEY_CURRENT_USER, getSettingsPath());
if (key != NULL) {
HWND child;
child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT);
CArchMiscWindows::setValue(key, "server", getWindowText(child));
child = getItem(hwnd, IDC_MAIN_DEBUG);
CArchMiscWindows::setValue(key, "debug",
SendMessage(child, CB_GETCURSEL, 0, 0));
CArchMiscWindows::setValue(key, "isServer", isClient ? 0 : 1);
CArchMiscWindows::closeKey(key);
}
// save user's configuration
if (!s_userConfig || ARG->m_config != s_lastConfig) {
time_t t;
if (!saveConfig(ARG->m_config, false, t)) {
errorID = IDS_SAVE_FAILED;
arg = getErrorString(GetLastError());
goto failed;
}
if (s_userConfig) {
s_configTime = t;
s_lastConfig = ARG->m_config;
}
}
// save autostart configuration
if (CAutoStart::isDaemonInstalled()) {
if (s_userConfig || ARG->m_config != s_lastConfig) {
time_t t;
if (!saveConfig(ARG->m_config, true, t)) {
errorID = IDS_AUTOSTART_SAVE_FAILED;
arg = getErrorString(GetLastError());
goto failed;
}
if (!s_userConfig) {
s_configTime = t;
s_lastConfig = ARG->m_config;
}
}
}
// get autostart command
cmdLine = getCommandLine(hwnd, false, mode == SAVE_QUITING);
if (cmdLineOut != NULL) {
*cmdLineOut = cmdLine;
}
if (cmdLine.empty()) {
return (mode == SAVE_QUITING);
}
// save autostart command
if (CAutoStart::isDaemonInstalled()) {
try {
CAutoStart::reinstallDaemon(isClient, cmdLine);
CAutoStart::uninstallDaemons(!isClient);
}
catch (XArchDaemon& e) {
errorID = IDS_INSTALL_GENERIC_ERROR;
arg = e.what();
goto failed;
}
}
return true;
failed:
CString errorMessage =
CStringUtil::format(getString(errorID).c_str(), arg.c_str());
if (mode == SAVE_QUITING) {
errorMessage += "\n";
errorMessage += getString(IDS_UNSAVED_DATA_REALLY_QUIT);
if (askVerify(hwnd, errorMessage)) {
return true;
}
}
else if (mode == SAVE_NORMAL) {
showError(hwnd, errorMessage);
}
return false;
}
static
LRESULT CALLBACK
mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_ACTIVATE:
if (LOWORD(wParam) != WA_INACTIVE) {
// activated
// see if the configuration changed
if (isConfigNewer(s_configTime, s_userConfig)) {
CString message = getString(IDS_CONFIG_CHANGED);
if (askVerify(hwnd, message)) {
time_t configTime;
bool userConfig;
CConfig newConfig;
if (loadConfig(newConfig, configTime, userConfig) &&
userConfig == s_userConfig) {
ARG->m_config = newConfig;
s_lastConfig = ARG->m_config;
}
else {
message = getString(IDS_LOAD_FAILED);
showError(hwnd, message);
s_lastConfig = CConfig();
}
}
}
}
else {
// deactivated; write configuration
if (!isShowingDialog()) {
saveMainWindow(hwnd, SAVE_QUIET);
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCANCEL:
// save data
if (saveMainWindow(hwnd, SAVE_QUITING)) {
// quit
PostQuitMessage(0);
}
return 0;
case IDOK:
case IDC_MAIN_TEST: {
// note if testing
const bool testing = (LOWORD(wParam) == IDC_MAIN_TEST);
// save data
if (saveMainWindow(hwnd, SAVE_NORMAL)) {
// launch child app
DWORD threadID;
HANDLE thread;
if (!launchApp(hwnd, testing, &thread, &threadID)) {
return 0;
}
// handle child program
if (testing) {
// wait for process to stop, allowing the user to kill it
waitForChild(hwnd, thread, threadID);
// clean up
CloseHandle(thread);
}
else {
// don't need thread handle
if (thread != NULL) {
CloseHandle(thread);
}
// notify of success
askOkay(hwnd, getString(IDS_STARTED_TITLE),
getString(IDS_STARTED));
// quit
PostQuitMessage(0);
}
}
return 0;
}
case IDC_MAIN_AUTOSTART: {
CString cmdLine;
if (saveMainWindow(hwnd, SAVE_NORMAL, &cmdLine)) {
// run dialog
CAutoStart autoStart(hwnd, !isClientChecked(hwnd), cmdLine);
autoStart.doModal();
}
return 0;
}
case IDC_MAIN_CLIENT_RADIO:
case IDC_MAIN_SERVER_RADIO:
enableMainWindowControls(hwnd);
return 0;
case IDC_MAIN_SCREENS:
s_screensLinks->doModal();
break;
case IDC_MAIN_OPTIONS:
s_globalOptions->doModal();
break;
case IDC_MAIN_ADVANCED:
s_advancedOptions->doModal(isClientChecked(hwnd));
break;
case IDC_MAIN_HOTKEYS:
s_hotkeyOptions->doModal();
break;
case IDC_MAIN_INFO:
s_info->doModal();
break;
}
default:
break;
}
return DefDlgProc(hwnd, message, wParam, lParam);
}
int WINAPI
WinMain(HINSTANCE instance, HINSTANCE, LPSTR cmdLine, int nCmdShow)
{
CArch arch(instance);
CLOG;
CArgs args;
s_instance = instance;
// if "/uninstall" is on the command line then just stop and
// uninstall the service and quit. this is the only option
// but we ignore any others.
if (CString(cmdLine).find("/uninstall") != CString::npos) {
CAutoStart::uninstallDaemons(false);
CAutoStart::uninstallDaemons(true);
return 0;
}
// register main window (dialog) class
WNDCLASSEX classInfo;
classInfo.cbSize = sizeof(classInfo);
classInfo.style = CS_HREDRAW | CS_VREDRAW;
classInfo.lpfnWndProc = &mainWndProc;
classInfo.cbClsExtra = 0;
classInfo.cbWndExtra = DLGWINDOWEXTRA;
classInfo.hInstance = instance;
classInfo.hIcon = (HICON)LoadImage(instance,
MAKEINTRESOURCE(IDI_SYNERGY),
IMAGE_ICON,
32, 32, LR_SHARED);
classInfo.hCursor = LoadCursor(NULL, IDC_ARROW);
classInfo.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_3DFACE + 1);
classInfo.lpszMenuName = NULL;
classInfo.lpszClassName = s_mainClass;
classInfo.hIconSm = (HICON)LoadImage(instance,
MAKEINTRESOURCE(IDI_SYNERGY),
IMAGE_ICON,
16, 16, LR_SHARED);
RegisterClassEx(&classInfo);
// create main window
HWND mainWindow = CreateDialog(s_instance,
MAKEINTRESOURCE(IDD_MAIN), 0, NULL);
// prep windows
initMainWindow(mainWindow);
s_globalOptions = new CGlobalOptions(mainWindow, &ARG->m_config);
s_advancedOptions = new CAdvancedOptions(mainWindow, &ARG->m_config);
s_hotkeyOptions = new CHotkeyOptions(mainWindow, &ARG->m_config);
s_screensLinks = new CScreensLinks(mainWindow, &ARG->m_config);
s_info = new CInfo(mainWindow);
// show window
ShowWindow(mainWindow, nCmdShow);
// main loop
MSG msg;
bool done = false;
do {
switch (GetMessage(&msg, NULL, 0, 0)) {
case -1:
// error
break;
case 0:
// quit
done = true;
break;
default:
if (!IsDialogMessage(mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
break;
}
} while (!done);
return msg.wParam;
}

617
cmd/launcher/launcher.rc Normal file
View File

@@ -0,0 +1,617 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include <winresrc.h>
#if !defined(IDC_STATIC)
#define IDC_STATIC (-1)
#endif
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include <winresrc.h>\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_MAIN DIALOG DISCARDABLE 32768, 0, 300, 199
STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU
CAPTION "Synergy"
CLASS "GoSynergy"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Choose to share or use a shared keyboard and mouse, provide the requested information, then click Test to check your settings or Start to save your settings and start Synergy.",
IDC_STATIC,7,7,286,19
GROUPBOX "",IDC_STATIC,7,29,286,36
GROUPBOX "",IDC_STATIC,7,72,286,36
GROUPBOX "Options",IDC_STATIC,7,115,286,56
CONTROL "&Use another computer's shared keyboard and mouse (client)",
IDC_MAIN_CLIENT_RADIO,"Button",BS_AUTORADIOBUTTON |
WS_GROUP | WS_TABSTOP,11,29,205,10
CONTROL "Share this computer's keyboard and mouse (server)",
IDC_MAIN_SERVER_RADIO,"Button",BS_AUTORADIOBUTTON,11,72,
177,10
LTEXT "Other Computer's &Host Name:",
IDC_MAIN_CLIENT_SERVER_NAME_LABEL,12,46,94,8
EDITTEXT IDC_MAIN_CLIENT_SERVER_NAME_EDIT,111,44,106,12,
ES_AUTOHSCROLL
LTEXT "&Screens && Links:",IDC_MAIN_SERVER_SCREENS_LABEL,12,89,
54,8
PUSHBUTTON "Configure...",IDC_MAIN_SCREENS,71,86,50,14
PUSHBUTTON "&Options...",IDC_MAIN_OPTIONS,12,129,50,14
PUSHBUTTON "Hot &Keys...",IDC_MAIN_HOTKEYS,68,129,50,14
PUSHBUTTON "Adva&nced...",IDC_MAIN_ADVANCED,124,129,50,14
PUSHBUTTON "&AutoStart...",IDC_MAIN_AUTOSTART,180,129,50,14
LTEXT "&Logging Level:",IDC_STATIC,12,154,48,8
COMBOBOX IDC_MAIN_DEBUG,68,151,61,60,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Info",IDC_MAIN_INFO,7,178,50,14
DEFPUSHBUTTON "&Test",IDC_MAIN_TEST,131,179,50,14
PUSHBUTTON "Start",IDOK,187,179,50,14
PUSHBUTTON "Quit",IDCANCEL,243,179,50,14
END
IDD_ADD DIALOG DISCARDABLE 0, 0, 192, 254
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Add Screen"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "&Screen Name:",IDC_STATIC,7,9,46,8
EDITTEXT IDC_ADD_SCREEN_NAME_EDIT,79,7,106,12,ES_AUTOHSCROLL
LTEXT "&Aliases:",IDC_STATIC,7,25,25,8
EDITTEXT IDC_ADD_ALIASES_EDIT,79,26,106,24,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
GROUPBOX "Options",IDC_STATIC,7,55,178,54
LTEXT "If your Caps, Num, or Scroll Lock keys behave strangely on this client screen then try turning the half-duplex options on and reconnect the client.",
IDC_STATIC,13,65,165,25
CONTROL "&Caps Lock",IDC_ADD_HD_CAPS_CHECK,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,93,51,10
CONTROL "&Num Lock",IDC_ADD_HD_NUM_CHECK,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,69,93,51,10
CONTROL "Sc&roll Lock",IDC_ADD_HD_SCROLL_CHECK,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,125,93,51,10
GROUPBOX "Modifiers",IDC_STATIC,7,113,178,65
LTEXT "Shift",IDC_STATIC,13,129,15,8
COMBOBOX IDC_ADD_MOD_SHIFT,37,126,48,60,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "Ctrl",IDC_STATIC,13,144,11,8
COMBOBOX IDC_ADD_MOD_CTRL,37,142,48,60,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "Alt",IDC_STATIC,13,160,9,8
COMBOBOX IDC_ADD_MOD_ALT,37,158,48,60,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "Meta",IDC_STATIC,101,128,17,8
COMBOBOX IDC_ADD_MOD_META,125,126,48,60,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "Super",IDC_STATIC,101,144,20,8
COMBOBOX IDC_ADD_MOD_SUPER,125,142,48,60,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
GROUPBOX "Dead Corners",IDC_STATIC,7,183,178,43
LTEXT "Don't switch in these corners:",IDC_STATIC,14,198,52,18
CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME,68,193,47,28
CONTROL "",IDC_ADD_DC_TOP_LEFT,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,76,197,16,8
CONTROL "",IDC_ADD_DC_TOP_RIGHT,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,98,197,16,8
CONTROL "",IDC_ADD_DC_BOTTOM_LEFT,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,76,210,16,8
CONTROL "",IDC_ADD_DC_BOTTOM_RIGHT,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,98,210,16,8
LTEXT "Size",IDC_STATIC,120,202,14,8
EDITTEXT IDC_ADD_DC_SIZE,139,200,40,12,ES_AUTOHSCROLL | ES_NUMBER
DEFPUSHBUTTON "OK",IDOK,79,233,50,14
PUSHBUTTON "Cancel",IDCANCEL,135,233,50,14
END
IDD_WAIT DIALOG DISCARDABLE 0, 0, 186, 54
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Running Test..."
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "Stop",IDOK,129,33,50,14
LTEXT "Running synergy. Press Stop to end the test.",
IDC_STATIC,7,7,172,15
END
IDD_AUTOSTART DIALOG DISCARDABLE 0, 0, 195, 189
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Auto Start"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "Close",IDCANCEL,138,168,50,14
LTEXT "Synergy can be configured to start automatically when you log in. If you have sufficient access rights, you can instead configure synergy to start automatically when your computer starts.",
IDC_STATIC,7,7,181,33
LTEXT "You have sufficient access rights to install and uninstall Auto Start for all users or for just yourself.",
IDC_AUTOSTART_PERMISSION_MSG,7,69,181,17
LTEXT "Synergy is configured to start automatically when the system starts.",
IDC_AUTOSTART_INSTALLED_MSG,7,93,181,17
GROUPBOX "When &You Log In",IDC_STATIC,7,119,84,40
PUSHBUTTON "Install",IDC_AUTOSTART_INSTALL_USER,23,133,50,14
GROUPBOX "When &Computer Starts",IDC_STATIC,104,119,84,40
PUSHBUTTON "Install",IDC_AUTOSTART_INSTALL_SYSTEM,119,134,50,14
LTEXT "Synergy can be configured to start automatically when the computer starts or when you log in but not both.",
IDC_STATIC,7,43,181,17
END
IDD_GLOBAL_OPTIONS DIALOG DISCARDABLE 0, 0, 207, 290
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Options"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "It's easy to unintentionally switch screens when the pointer is near a screen's edge. Synergy can prevent switching until certain conditions are met to reduce unintentional switching.",
IDC_STATIC,7,7,191,26
LTEXT "Synergy can wait to switch until the cursor has been at a screen's edge for some amount of time.",
IDC_STATIC,7,37,193,16
CONTROL "Switch after waiting",IDC_GLOBAL_DELAY_CHECK,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,59,77,10
EDITTEXT IDC_GLOBAL_DELAY_TIME,112,58,45,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "ms",IDC_STATIC,159,60,10,8
LTEXT "Synergy can switch only when the cursor hits a screen edge twice within some amount of time.",
IDC_STATIC,7,77,193,16
CONTROL "Switch on double tap within",IDC_GLOBAL_TWO_TAP_CHECK,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,99,103,10
EDITTEXT IDC_GLOBAL_TWO_TAP_TIME,112,98,45,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "ms",IDC_STATIC,159,100,10,8
LTEXT "Synergy can periodically check that clients are still alive and connected. Use this only if synergy doesn't detect when clients disconnect.",
IDC_STATIC,7,122,193,24
CONTROL "Check clients every",IDC_GLOBAL_HEARTBEAT_CHECK,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,153,78,10
EDITTEXT IDC_GLOBAL_HEARTBEAT_TIME,112,152,45,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "ms",IDC_STATIC,159,154,10,8
LTEXT "Synergy can synchronize screen savers across all screens.",
IDC_STATIC,7,176,193,8
CONTROL "Synchronize screen savers",IDC_GLOBAL_SCREENSAVER_SYNC,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,192,101,10
LTEXT "Relative mouse moves on secondary screens.",IDC_STATIC,
7,213,193,8
CONTROL "Use relative mouse moves",IDC_GLOBAL_RELATIVE_MOVES,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,229,99,10
CONTROL "Don't take foreground window on Windows servers",
IDC_GLOBAL_LEAVE_FOREGROUND,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,7,250,177,10
DEFPUSHBUTTON "OK",IDOK,94,269,50,14
PUSHBUTTON "Cancel",IDCANCEL,150,269,50,14
END
IDD_ADVANCED_OPTIONS DIALOG DISCARDABLE 0, 0, 230, 186
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Advanced Options"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Synergy normally uses this computer's name as its screen name. Enter another name here if you want to use a different screen name.",
IDC_STATIC,7,7,216,19
LTEXT "Screen &Name:",IDC_STATIC,7,34,46,8
EDITTEXT IDC_ADVANCED_NAME_EDIT,63,32,106,12,ES_AUTOHSCROLL
LTEXT "Synergy normally uses a particular network port number. Enter an alternative port here. (The server and all clients must use the same port number.)",
IDC_STATIC,7,56,216,26
LTEXT "&Port:",IDC_STATIC,7,90,16,8
EDITTEXT IDC_ADVANCED_PORT_EDIT,63,88,40,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "The server normally listens for client connections on all network interfaces. Enter the address of a particular interface to listen on just that interface.",
IDC_STATIC,7,110,216,26
LTEXT "&Interface:",IDC_STATIC,7,144,31,8
EDITTEXT IDC_ADVANCED_INTERFACE_EDIT,63,142,81,12,ES_AUTOHSCROLL
PUSHBUTTON "&Defaults",IDC_ADVANCED_DEFAULTS,7,165,50,14
DEFPUSHBUTTON "OK",IDOK,118,165,50,14
PUSHBUTTON "Cancel",IDCANCEL,173,165,50,14
END
IDD_SCREENS_LINKS DIALOG DISCARDABLE 0, 0, 354, 213
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Screens & Links"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "&Screens:",IDC_STATIC,7,7,29,8
LISTBOX IDC_SCREENS_SCREENS,7,18,100,36,LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "+",IDC_SCREENS_ADD_SCREEN,7,57,17,14
PUSHBUTTON "-",IDC_SCREENS_REMOVE_SCREEN,28,57,17,14
PUSHBUTTON "Edit",IDC_SCREENS_EDIT_SCREEN,49,57,24,14
LTEXT "&Links:",IDC_STATIC,7,83,20,8
LISTBOX IDC_SCREENS_LINKS,7,94,339,59,LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
EDITTEXT IDC_SCREENS_SRC_START,7,156,16,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "to",IDC_STATIC,25,158,8,8
EDITTEXT IDC_SCREENS_SRC_END,33,156,16,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "% of the",IDC_STATIC,52,158,27,8
COMBOBOX IDC_SCREENS_SRC_SIDE,80,156,48,69,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "of",IDC_STATIC,129,158,8,8
COMBOBOX IDC_SCREENS_SRC_SCREEN,139,156,59,53,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "goes to",IDC_STATIC,200,158,24,8
EDITTEXT IDC_SCREENS_DST_START,225,156,16,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "to",IDC_STATIC,243,158,8,8
EDITTEXT IDC_SCREENS_DST_END,251,156,16,12,ES_AUTOHSCROLL |
ES_NUMBER
LTEXT "% of",IDC_STATIC,270,158,15,8
COMBOBOX IDC_SCREENS_DST_SCREEN,287,156,59,53,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "+",IDC_SCREENS_ADD_LINK,7,172,17,14
PUSHBUTTON "-",IDC_SCREENS_REMOVE_LINK,28,172,17,14
DEFPUSHBUTTON "OK",IDOK,241,192,50,14
PUSHBUTTON "Cancel",IDCANCEL,297,192,50,14
LTEXT "Source edge overlaps an existing edge.",
IDC_SCREENS_OVERLAP_ERROR,72,175,126,8,NOT WS_VISIBLE |
NOT WS_GROUP
END
IDD_INFO DIALOG DISCARDABLE 0, 0, 186, 95
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Info"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Version:",IDC_STATIC,7,7,26,8
EDITTEXT IDC_INFO_VERSION,52,7,127,12,ES_AUTOHSCROLL |
ES_READONLY | NOT WS_BORDER
LTEXT "Hostname:",IDC_STATIC,7,19,35,8
EDITTEXT IDC_INFO_HOSTNAME,52,19,127,12,ES_AUTOHSCROLL |
ES_READONLY | NOT WS_BORDER
LTEXT "IP Address:",IDC_STATIC,7,31,37,8
EDITTEXT IDC_INFO_IP_ADDRESS,52,31,127,12,ES_AUTOHSCROLL |
ES_READONLY | NOT WS_BORDER
LTEXT "User Config:",IDC_STATIC,7,43,40,8
EDITTEXT IDC_INFO_USER_CONFIG,52,43,127,12,ES_AUTOHSCROLL |
ES_READONLY | NOT WS_BORDER
LTEXT "Sys Config:",IDC_STATIC,7,55,36,8
EDITTEXT IDC_INFO_SYS_CONFIG,52,55,127,12,ES_AUTOHSCROLL |
ES_READONLY | NOT WS_BORDER
DEFPUSHBUTTON "OK",IDOK,129,74,50,14
END
IDD_HOTKEY_OPTIONS DIALOG DISCARDABLE 0, 0, 360, 151
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Hot Keys"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "&Hot Keys:",IDC_STATIC,7,7,32,8
LISTBOX IDC_HOTKEY_HOTKEYS,7,18,169,88,LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "+",IDC_HOTKEY_ADD_HOTKEY,7,109,17,14
PUSHBUTTON "-",IDC_HOTKEY_REMOVE_HOTKEY,28,109,17,14
PUSHBUTTON "Edit",IDC_HOTKEY_EDIT_HOTKEY,49,109,24,14
LTEXT "&Actions:",IDC_STATIC,183,7,26,8
LISTBOX IDC_HOTKEY_ACTIONS,183,18,169,88,LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "+",IDC_HOTKEY_ADD_ACTION,183,109,17,14
PUSHBUTTON "-",IDC_HOTKEY_REMOVE_ACTION,204,109,17,14
PUSHBUTTON "Edit",IDC_HOTKEY_EDIT_ACTION,225,109,24,14
DEFPUSHBUTTON "OK",IDOK,302,130,50,14
END
IDD_HOTKEY_CONDITION DIALOG DISCARDABLE 0, 0, 183, 58
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Hot Key"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Enter &new hot key or mouse button:",IDC_STATIC,7,7,113,
8
EDITTEXT IDC_HOTKEY_CONDITION_HOTKEY,7,17,169,12,ES_WANTRETURN
DEFPUSHBUTTON "OK",IDOK,70,37,50,14
PUSHBUTTON "Cancel",IDCANCEL,126,37,50,14
END
IDD_HOTKEY_ACTION DIALOG DISCARDABLE 0, 0, 183, 218
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Action"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "&Action:",IDC_STATIC,7,7,23,8
CONTROL "Press:",IDC_HOTKEY_ACTION_DOWN,"Button",
BS_AUTORADIOBUTTON | WS_TABSTOP,7,19,35,10
CONTROL "Release:",IDC_HOTKEY_ACTION_UP,"Button",
BS_AUTORADIOBUTTON,7,31,44,10
CONTROL "Press && Release:",IDC_HOTKEY_ACTION_DOWNUP,"Button",
BS_AUTORADIOBUTTON,7,43,69,10
CONTROL "Switch To Screen:",IDC_HOTKEY_ACTION_SWITCH_TO,"Button",
BS_AUTORADIOBUTTON,7,85,75,10
CONTROL "Switch In Direction:",IDC_HOTKEY_ACTION_SWITCH_IN,
"Button",BS_AUTORADIOBUTTON,7,101,77,10
CONTROL "Lock Cursor to Screen:",IDC_HOTKEY_ACTION_LOCK,"Button",
BS_AUTORADIOBUTTON,7,117,89,10
CONTROL "Keyboard broadcasting:",
IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST,"Button",
BS_AUTORADIOBUTTON,7,133,89,10
LTEXT "&Hot key or mouse button:",IDC_STATIC,7,55,80,8
EDITTEXT IDC_HOTKEY_ACTION_HOTKEY,7,67,152,12,ES_WANTRETURN
PUSHBUTTON "...",IDC_HOTKEY_ACTION_SCREENS,162,67,14,12
COMBOBOX IDC_HOTKEY_ACTION_SWITCH_TO_LIST,87,83,89,62,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_HOTKEY_ACTION_SWITCH_IN_LIST,106,99,70,66,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_HOTKEY_ACTION_LOCK_LIST,106,115,70,58,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST,106,131,53,58,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "...",IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS,
162,131,14,12
LTEXT "Action takes place &when:",IDC_STATIC,7,153,81,8
CONTROL "Hot key is pressed",IDC_HOTKEY_ACTION_ON_ACTIVATE,
"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,165,74,10
CONTROL "Hot key is released",IDC_HOTKEY_ACTION_ON_DEACTIVATE,
"Button",BS_AUTORADIOBUTTON,7,177,76,10
DEFPUSHBUTTON "OK",IDOK,70,197,50,14
PUSHBUTTON "Cancel",IDCANCEL,126,197,50,14
END
IDD_HOTKEY_SCREENS DIALOG DISCARDABLE 0, 0, 237, 79
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Target Screens"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "&Available screens:",IDC_STATIC,7,7,58,8
LISTBOX IDC_HOTKEY_SCREENS_SRC,7,17,100,36,LBS_NOINTEGRALHEIGHT |
LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
LISTBOX IDC_HOTKEY_SCREENS_DST,130,17,100,36,
LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
WS_TABSTOP
PUSHBUTTON "-->",IDC_HOTKEY_SCREENS_ADD,109,21,17,14
PUSHBUTTON "<--",IDC_HOTKEY_SCREENS_REMOVE,109,38,17,14
DEFPUSHBUTTON "OK",IDOK,124,58,50,14
PUSHBUTTON "Cancel",IDCANCEL,180,58,50,14
LTEXT "&Send action to screens:",IDC_STATIC,130,7,76,8
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_MAIN, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 293
TOPMARGIN, 7
BOTTOMMARGIN, 192
END
IDD_ADD, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 185
TOPMARGIN, 7
BOTTOMMARGIN, 247
END
IDD_WAIT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 47
END
IDD_AUTOSTART, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 188
TOPMARGIN, 7
BOTTOMMARGIN, 182
END
IDD_GLOBAL_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 200
TOPMARGIN, 7
BOTTOMMARGIN, 283
END
IDD_ADVANCED_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 223
TOPMARGIN, 7
BOTTOMMARGIN, 179
END
IDD_SCREENS_LINKS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 347
TOPMARGIN, 7
BOTTOMMARGIN, 206
END
IDD_INFO, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
IDD_HOTKEY_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 353
TOPMARGIN, 7
BOTTOMMARGIN, 144
END
IDD_HOTKEY_CONDITION, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 176
TOPMARGIN, 7
BOTTOMMARGIN, 51
END
IDD_HOTKEY_ACTION, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 176
TOPMARGIN, 7
BOTTOMMARGIN, 195
END
IDD_HOTKEY_SCREENS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 230
TOPMARGIN, 7
BOTTOMMARGIN, 72
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_SYNERGY ICON DISCARDABLE "synergy.ico"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_ERROR "Error"
IDS_INVALID_SCREEN_NAME "Screen name `%{1}' is invalid."
IDS_DUPLICATE_SCREEN_NAME "The screen name `%{1}' is already being used."
IDS_SCREEN_NAME_IS_ALIAS "A name may not be an alias of itself."
IDS_VERIFY "Confirm"
IDS_UNSAVED_DATA_REALLY_QUIT "You have unsaved changes. Really quit?"
IDS_UNKNOWN_SCREEN_NAME "The screen name `%{1}' is not in the layout."
IDS_INVALID_PORT "The port `%{1}' is invalid. It must be between 1 and 65535 inclusive. %{2} is the standard port."
IDS_SAVE_FAILED "Failed to save configuration: %{1}"
IDS_STARTUP_FAILED "Failed to start synergy: %{1}"
IDS_STARTED_TITLE "Started"
IDS_STARTED "Synergy was successfully started. Use the task manager or tray icon to terminate it."
IDS_UNINSTALL_TITLE "Removed Auto-Start"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_AUTOSTART_PERMISSION_SYSTEM
"You have sufficient access rights to install and uninstall Auto Start for all users."
IDS_AUTOSTART_PERMISSION_USER
"You have sufficient access rights to install and uninstall Auto Start for just yourself."
IDS_AUTOSTART_PERMISSION_NONE
"You do not have sufficient access rights to install or uninstall Auto Start."
IDS_AUTOSTART_INSTALLED_SYSTEM
"Synergy is configured to start automatically when the system starts."
IDS_AUTOSTART_INSTALLED_USER
"Synergy is configured to start automatically when you log in."
IDS_AUTOSTART_INSTALLED_NONE
"Synergy is not configured to start automatically."
IDS_INSTALL_LABEL "Install"
IDS_UNINSTALL_LABEL "Uninstall"
IDS_INSTALL_GENERIC_ERROR "Install failed: %{1}"
IDS_UNINSTALL_GENERIC_ERROR "Uninstall failed: %{1}"
IDS_INSTALL_TITLE "Installed Auto-Start"
IDS_INSTALLED_SYSTEM "Installed auto-start. Synergy will automatically start each time you start your computer."
IDS_INSTALLED_USER "Installed auto-start. Synergy will automatically start each time you log in."
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_UNINSTALLED_SYSTEM "Removed auto-start. Synergy will not automatically start each time you start or reboot your computer."
IDS_UNINSTALLED_USER "Removed auto-start. Synergy will not automatically start each time you log in."
IDS_INVALID_SERVER_NAME "Server name `%{1}' is invalid."
IDS_TITLE "Synergy - Version %{1}"
IDS_SERVER_IS_CLIENT "Please enter the name of the computer sharing a\nkeyboard and mouse, not the name of this computer,\nin the Other Computer's Host Name field."
IDS_ADD_SCREEN "Add Screen"
IDS_EDIT_SCREEN "Edit Screen %{1}"
IDS_ERROR_CODE "Error code: %{1}"
IDS_AUTOSTART_PERMISSION_ALL
"You have sufficient access rights to install and uninstall Auto Start for all users or for just yourself."
IDS_INVALID_INTERFACE_NAME "The interface '%{1}' is invalid: %{2}"
IDS_INVALID_CORNER_SIZE "The dead corner size %{1} is invalid; it must be 0 or higher."
IDS_NEW_LINK "[New Link]"
IDS_SIDE_LEFT "left of"
IDS_SIDE_RIGHT "right of"
IDS_SIDE_TOP "above"
IDS_SIDE_BOTTOM "below"
END
STRINGTABLE DISCARDABLE
BEGIN
IDS_LINK_FORMAT "%{4}%{5} is %{3} %{1}%{2}"
IDS_LINK_INTERVAL_FORMAT "(%{1},%{2})"
IDS_EDGE_LEFT "left"
IDS_EDGE_RIGHT "right"
IDS_EDGE_TOP "top"
IDS_EDGE_BOTTOM "bottom"
IDS_AUTOSTART_SAVE_FAILED "Failed to save autostart configuration: %{1}"
IDS_LOAD_FAILED "Failed to load configuration."
IDS_CONFIG_CHANGED "Configuration changed on disk. Reload?"
IDS_MODE_OFF "off"
IDS_MODE_ON "on"
IDS_MODE_TOGGLE "toggle"
IDS_ALL_SCREENS "All Screens"
IDS_ACTIVE_SCREEN "Active Screen"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

186
cmd/launcher/resource.h Normal file
View File

@@ -0,0 +1,186 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by launcher.rc
//
#define IDS_ERROR 1
#define IDS_INVALID_SCREEN_NAME 2
#define IDS_DUPLICATE_SCREEN_NAME 3
#define IDS_SCREEN_NAME_IS_ALIAS 4
#define IDS_VERIFY 5
#define IDS_UNSAVED_DATA_REALLY_QUIT 6
#define IDS_UNKNOWN_SCREEN_NAME 7
#define IDS_INVALID_PORT 8
#define IDS_SAVE_FAILED 9
#define IDS_STARTUP_FAILED 10
#define IDS_STARTED_TITLE 11
#define IDS_STARTED 12
#define IDS_INSTALL_FAILED 13
#define IDS_UNINSTALL_TITLE 14
#define IDS_UNINSTALLED 15
#define IDS_UNINSTALL_FAILED 16
#define IDS_CLIENT 17
#define IDS_SERVER 18
#define IDS_AUTOSTART_PERMISSION_SYSTEM 19
#define IDS_AUTOSTART_PERMISSION_USER 20
#define IDS_AUTOSTART_PERMISSION_NONE 21
#define IDS_AUTOSTART_INSTALLED_SYSTEM 22
#define IDS_AUTOSTART_INSTALLED_USER 23
#define IDS_AUTOSTART_INSTALLED_NONE 24
#define IDS_INSTALL_LABEL 25
#define IDS_UNINSTALL_LABEL 26
#define IDS_INSTALL_GENERIC_ERROR 27
#define IDS_UNINSTALL_GENERIC_ERROR 28
#define IDS_INSTALL_TITLE 29
#define IDS_INSTALLED_SYSTEM 30
#define IDS_INSTALLED_USER 31
#define IDS_UNINSTALLED_SYSTEM 32
#define IDS_UNINSTALLED_USER 33
#define IDS_INVALID_SERVER_NAME 34
#define IDS_TITLE 35
#define IDS_SERVER_IS_CLIENT 36
#define IDS_ADD_SCREEN 37
#define IDS_EDIT_SCREEN 38
#define IDS_INVALID_TIME 39
#define IDS_ERROR_CODE 39
#define IDS_AUTOSTART_PERMISSION_ALL 40
#define IDS_INVALID_INTERFACE_NAME 41
#define IDS_INVALID_CORNER_SIZE 42
#define IDS_NEW_LINK 43
#define IDS_SIDE_LEFT 44
#define IDS_SIDE_RIGHT 45
#define IDS_SIDE_TOP 46
#define IDS_SIDE_BOTTOM 47
#define IDS_LINK_FORMAT 48
#define IDS_LINK_INTERVAL_FORMAT 49
#define IDS_EDGE_LEFT 50
#define IDS_EDGE_RIGHT 51
#define IDS_EDGE_TOP 52
#define IDS_EDGE_BOTTOM 53
#define IDS_AUTOSTART_SAVE_FAILED 54
#define IDS_LOAD_FAILED 55
#define IDS_CONFIG_CHANGED 56
#define IDS_MODE_OFF 57
#define IDS_MODE_ON 58
#define IDS_MODE_TOGGLE 59
#define IDS_ALL_SCREENS 60
#define IDS_ACTIVE_SCREEN 61
#define IDD_MAIN 101
#define IDD_ADD 102
#define IDD_WAIT 103
#define IDI_SYNERGY 104
#define IDD_AUTOSTART 105
#define IDD_ADVANCED_OPTIONS 106
#define IDD_GLOBAL_OPTIONS 107
#define IDD_SCREENS_LINKS 110
#define IDD_INFO 111
#define IDD_HOTKEY_OPTIONS 112
#define IDD_HOTKEY_CONDITION 113
#define IDD_HOTKEY_ACTION 114
#define IDD_HOTKEY_SCREENS 115
#define IDC_MAIN_CLIENT_RADIO 1000
#define IDC_MAIN_SERVER_RADIO 1001
#define IDC_MAIN_CLIENT_SERVER_NAME_LABEL 1002
#define IDC_MAIN_CLIENT_SERVER_NAME_EDIT 1003
#define IDC_MAIN_SERVER_SCREENS_LABEL 1004
#define IDC_MAIN_SCREENS 1005
#define IDC_MAIN_OPTIONS 1006
#define IDC_MAIN_ADVANCED 1007
#define IDC_MAIN_AUTOSTART 1008
#define IDC_MAIN_TEST 1009
#define IDC_MAIN_SAVE 1010
#define IDC_MAIN_HOTKEYS 1010
#define IDC_MAIN_DEBUG 1011
#define IDC_ADD_SCREEN_NAME_EDIT 1020
#define IDC_ADD_ALIASES_EDIT 1021
#define IDC_AUTOSTART_INSTALLED_MSG 1031
#define IDC_AUTOSTART_PERMISSION_MSG 1032
#define IDC_AUTOSTART_INSTALL_USER 1033
#define IDC_AUTOSTART_INSTALL_SYSTEM 1034
#define IDC_ADD_HD_CAPS_CHECK 1037
#define IDC_ADD_HD_NUM_CHECK 1038
#define IDC_ADVANCED_NAME_EDIT 1038
#define IDC_ADVANCED_PORT_EDIT 1039
#define IDC_ADD_HD_SCROLL_CHECK 1039
#define IDC_ADVANCED_INTERFACE_EDIT 1040
#define IDC_GLOBAL_DELAY_CHECK 1041
#define IDC_GLOBAL_DELAY_TIME 1042
#define IDC_GLOBAL_TWO_TAP_CHECK 1043
#define IDC_ADD_MOD_SHIFT 1043
#define IDC_GLOBAL_TWO_TAP_TIME 1044
#define IDC_ADD_MOD_CTRL 1044
#define IDC_ADD_MOD_ALT 1045
#define IDC_GLOBAL_HEARTBEAT_CHECK 1045
#define IDC_ADD_MOD_META 1046
#define IDC_GLOBAL_HEARTBEAT_TIME 1046
#define IDC_ADD_MOD_SUPER 1047
#define IDC_GLOBAL_SCREENSAVER_SYNC 1047
#define IDC_GLOBAL_RELATIVE_MOVES 1048
#define IDC_ADVANCED_DEFAULTS 1049
#define IDC_GLOBAL_LEAVE_FOREGROUND 1049
#define IDC_ADD_DC_SIZE 1052
#define IDC_ADD_DC_TOP_LEFT 1053
#define IDC_ADD_DC_TOP_RIGHT 1054
#define IDC_ADD_DC_BOTTOM_LEFT 1055
#define IDC_ADD_DC_BOTTOM_RIGHT 1056
#define IDC_SCREENS_SRC_SIDE 1057
#define IDC_SCREENS_SRC_START 1058
#define IDC_SCREENS_SRC_END 1059
#define IDC_SCREENS_SRC_SCREEN 1060
#define IDC_SCREENS_SCREENS 1061
#define IDC_SCREENS_ADD_SCREEN 1062
#define IDC_SCREENS_LINKS 1063
#define IDC_SCREENS_DST_START 1064
#define IDC_SCREENS_DST_END 1065
#define IDC_SCREENS_DST_SCREEN 1066
#define IDC_SCREENS_REMOVE_SCREEN 1067
#define IDC_SCREENS_EDIT_SCREEN 1068
#define IDC_SCREENS_ADD_LINK 1069
#define IDC_SCREENS_REMOVE_LINK 1070
#define IDC_SCREENS_OVERLAP_ERROR 1071
#define IDC_INFO_VERSION 1073
#define IDC_MAIN_INFO 1074
#define IDC_INFO_HOSTNAME 1076
#define IDC_HOTKEY_HOTKEYS 1076
#define IDC_INFO_IP_ADDRESS 1077
#define IDC_HOTKEY_ADD_HOTKEY 1077
#define IDC_INFO_USER_CONFIG 1078
#define IDC_HOTKEY_REMOVE_HOTKEY 1078
#define IDC_INFO_SYS_CONFIG 1079
#define IDC_HOTKEY_EDIT_HOTKEY 1079
#define IDC_HOTKEY_ACTIONS 1080
#define IDC_HOTKEY_CONDITION_HOTKEY 1080
#define IDC_HOTKEY_ACTION_DOWNUP 1081
#define IDC_HOTKEY_ADD_ACTION 1082
#define IDC_HOTKEY_ACTION_DOWN 1082
#define IDC_HOTKEY_REMOVE_ACTION 1083
#define IDC_HOTKEY_ACTION_UP 1083
#define IDC_HOTKEY_EDIT_ACTION 1084
#define IDC_HOTKEY_ACTION_HOTKEY 1085
#define IDC_HOTKEY_ACTION_SWITCH_TO_LIST 1086
#define IDC_HOTKEY_ACTION_SWITCH_TO 1087
#define IDC_HOTKEY_ACTION_SWITCH_IN 1088
#define IDC_HOTKEY_ACTION_LOCK 1089
#define IDC_HOTKEY_ACTION_SWITCH_IN_LIST 1090
#define IDC_HOTKEY_ACTION_LOCK_LIST 1091
#define IDC_HOTKEY_ACTION_ON_ACTIVATE 1092
#define IDC_HOTKEY_ACTION_ON_DEACTIVATE 1093
#define IDC_HOTKEY_ACTION_SCREENS 1094
#define IDC_HOTKEY_SCREENS_SRC 1095
#define IDC_HOTKEY_SCREENS_DST 1096
#define IDC_HOTKEY_SCREENS_ADD 1097
#define IDC_HOTKEY_SCREENS_REMOVE 1098
#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST 1099
#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST 1100
#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS 1101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 116
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1102
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

BIN
cmd/launcher/synergy.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -0,0 +1,136 @@
/*
* 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 "CClientTaskBarReceiver.h"
#include "CClient.h"
#include "CLock.h"
#include "CStringUtil.h"
#include "IEventQueue.h"
#include "CArch.h"
#include "Version.h"
//
// CClientTaskBarReceiver
//
CClientTaskBarReceiver::CClientTaskBarReceiver() :
m_state(kNotRunning)
{
// do nothing
}
CClientTaskBarReceiver::~CClientTaskBarReceiver()
{
// do nothing
}
void
CClientTaskBarReceiver::updateStatus(CClient* client, const CString& errorMsg)
{
{
// update our status
m_errorMessage = errorMsg;
if (client == NULL) {
if (m_errorMessage.empty()) {
m_state = kNotRunning;
}
else {
m_state = kNotWorking;
}
}
else {
m_server = client->getServerAddress().getHostname();
if (client->isConnected()) {
m_state = kConnected;
}
else if (client->isConnecting()) {
m_state = kConnecting;
}
else {
m_state = kNotConnected;
}
}
// let subclasses have a go
onStatusChanged(client);
}
// tell task bar
ARCH->updateReceiver(this);
}
CClientTaskBarReceiver::EState
CClientTaskBarReceiver::getStatus() const
{
return m_state;
}
const CString&
CClientTaskBarReceiver::getErrorMessage() const
{
return m_errorMessage;
}
void
CClientTaskBarReceiver::quit()
{
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
void
CClientTaskBarReceiver::onStatusChanged(CClient*)
{
// do nothing
}
void
CClientTaskBarReceiver::lock() const
{
// do nothing
}
void
CClientTaskBarReceiver::unlock() const
{
// do nothing
}
std::string
CClientTaskBarReceiver::getToolTip() const
{
switch (m_state) {
case kNotRunning:
return CStringUtil::print("%s: Not running", kAppVersion);
case kNotWorking:
return CStringUtil::print("%s: %s",
kAppVersion, m_errorMessage.c_str());
case kNotConnected:
return CStringUtil::print("%s: Not connected: %s",
kAppVersion, m_errorMessage.c_str());
case kConnecting:
return CStringUtil::print("%s: Connecting to %s...",
kAppVersion, m_server.c_str());
case kConnected:
return CStringUtil::print("%s: Connected to %s",
kAppVersion, m_server.c_str());
default:
return "";
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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 CCLIENTTASKBARRECEIVER_H
#define CCLIENTTASKBARRECEIVER_H
#include "CString.h"
#include "IArchTaskBarReceiver.h"
class CClient;
//! Implementation of IArchTaskBarReceiver for the synergy server
class CClientTaskBarReceiver : public IArchTaskBarReceiver {
public:
CClientTaskBarReceiver();
virtual ~CClientTaskBarReceiver();
//! @name manipulators
//@{
//! Update status
/*!
Determine the status and query required information from the client.
*/
void updateStatus(CClient*, const CString& errorMsg);
//@}
// IArchTaskBarReceiver overrides
virtual void showStatus() = 0;
virtual void runMenu(int x, int y) = 0;
virtual void primaryAction() = 0;
virtual void lock() const;
virtual void unlock() const;
virtual const Icon getIcon() const = 0;
virtual std::string getToolTip() const;
protected:
enum EState {
kNotRunning,
kNotWorking,
kNotConnected,
kConnecting,
kConnected,
kMaxState
};
//! Get status
EState getStatus() const;
//! Get error message
const CString& getErrorMessage() const;
//! Quit app
/*!
Causes the application to quit gracefully
*/
void quit();
//! Status change notification
/*!
Called when status changes. The default implementation does nothing.
*/
virtual void onStatusChanged(CClient* client);
private:
EState m_state;
CString m_errorMessage;
CString m_server;
};
#endif

View File

@@ -0,0 +1,346 @@
/*
* 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 "CMSWindowsClientTaskBarReceiver.h"
#include "CClient.h"
#include "CMSWindowsClipboard.h"
#include "LogOutputters.h"
#include "BasicTypes.h"
#include "CArch.h"
#include "CArchTaskBarWindows.h"
#include "resource.h"
//
// CMSWindowsClientTaskBarReceiver
//
const UINT CMSWindowsClientTaskBarReceiver::s_stateToIconID[kMaxState] =
{
IDI_TASKBAR_NOT_RUNNING,
IDI_TASKBAR_NOT_WORKING,
IDI_TASKBAR_NOT_CONNECTED,
IDI_TASKBAR_NOT_CONNECTED,
IDI_TASKBAR_CONNECTED
};
CMSWindowsClientTaskBarReceiver::CMSWindowsClientTaskBarReceiver(
HINSTANCE appInstance, const CBufferedLogOutputter* logBuffer) :
CClientTaskBarReceiver(),
m_appInstance(appInstance),
m_window(NULL),
m_logBuffer(logBuffer)
{
for (UInt32 i = 0; i < kMaxState; ++i) {
m_icon[i] = loadIcon(s_stateToIconID[i]);
}
m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR));
// don't create the window yet. we'll create it on demand. this
// has the side benefit of being created in the thread used for
// the task bar. that's good because it means the existence of
// the window won't prevent changing the main thread's desktop.
// add ourself to the task bar
ARCH->addReceiver(this);
}
CMSWindowsClientTaskBarReceiver::~CMSWindowsClientTaskBarReceiver()
{
ARCH->removeReceiver(this);
for (UInt32 i = 0; i < kMaxState; ++i) {
deleteIcon(m_icon[i]);
}
DestroyMenu(m_menu);
destroyWindow();
}
void
CMSWindowsClientTaskBarReceiver::showStatus()
{
// create the window
createWindow();
// lock self while getting status
lock();
// get the current status
std::string status = getToolTip();
// done getting status
unlock();
// update dialog
HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str());
if (!IsWindowVisible(m_window)) {
// position it by the mouse
POINT cursorPos;
GetCursorPos(&cursorPos);
RECT windowRect;
GetWindowRect(m_window, &windowRect);
int x = cursorPos.x;
int y = cursorPos.y;
int fw = GetSystemMetrics(SM_CXDLGFRAME);
int fh = GetSystemMetrics(SM_CYDLGFRAME);
int ww = windowRect.right - windowRect.left;
int wh = windowRect.bottom - windowRect.top;
int sw = GetSystemMetrics(SM_CXFULLSCREEN);
int sh = GetSystemMetrics(SM_CYFULLSCREEN);
if (fw < 1) {
fw = 1;
}
if (fh < 1) {
fh = 1;
}
if (x + ww - fw > sw) {
x -= ww - fw;
}
else {
x -= fw;
}
if (x < 0) {
x = 0;
}
if (y + wh - fh > sh) {
y -= wh - fh;
}
else {
y -= fh;
}
if (y < 0) {
y = 0;
}
SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh,
SWP_SHOWWINDOW);
}
}
void
CMSWindowsClientTaskBarReceiver::runMenu(int x, int y)
{
// do popup menu. we need a window to pass to TrackPopupMenu().
// the SetForegroundWindow() and SendMessage() calls around
// TrackPopupMenu() are to get the menu to be dismissed when
// another window gets activated and are just one of those
// win32 weirdnesses.
createWindow();
SetForegroundWindow(m_window);
HMENU menu = GetSubMenu(m_menu, 0);
SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE);
HMENU logLevelMenu = GetSubMenu(menu, 3);
CheckMenuRadioItem(logLevelMenu, 0, 6,
CLOG->getFilter() - CLog::kERROR, MF_BYPOSITION);
int n = TrackPopupMenu(menu,
TPM_NONOTIFY |
TPM_RETURNCMD |
TPM_LEFTBUTTON |
TPM_RIGHTBUTTON,
x, y, 0, m_window, NULL);
SendMessage(m_window, WM_NULL, 0, 0);
// perform the requested operation
switch (n) {
case IDC_TASKBAR_STATUS:
showStatus();
break;
case IDC_TASKBAR_LOG:
copyLog();
break;
case IDC_TASKBAR_SHOW_LOG:
ARCH->showConsole(true);
break;
case IDC_TASKBAR_LOG_LEVEL_ERROR:
CLOG->setFilter(CLog::kERROR);
break;
case IDC_TASKBAR_LOG_LEVEL_WARNING:
CLOG->setFilter(CLog::kWARNING);
break;
case IDC_TASKBAR_LOG_LEVEL_NOTE:
CLOG->setFilter(CLog::kNOTE);
break;
case IDC_TASKBAR_LOG_LEVEL_INFO:
CLOG->setFilter(CLog::kINFO);
break;
case IDC_TASKBAR_LOG_LEVEL_DEBUG:
CLOG->setFilter(CLog::kDEBUG);
break;
case IDC_TASKBAR_LOG_LEVEL_DEBUG1:
CLOG->setFilter(CLog::kDEBUG1);
break;
case IDC_TASKBAR_LOG_LEVEL_DEBUG2:
CLOG->setFilter(CLog::kDEBUG2);
break;
case IDC_TASKBAR_QUIT:
quit();
break;
}
}
void
CMSWindowsClientTaskBarReceiver::primaryAction()
{
showStatus();
}
const IArchTaskBarReceiver::Icon
CMSWindowsClientTaskBarReceiver::getIcon() const
{
return reinterpret_cast<Icon>(m_icon[getStatus()]);
}
void
CMSWindowsClientTaskBarReceiver::copyLog() const
{
if (m_logBuffer != NULL) {
// collect log buffer
CString data;
for (CBufferedLogOutputter::const_iterator index = m_logBuffer->begin();
index != m_logBuffer->end(); ++index) {
data += *index;
data += "\n";
}
// copy log to clipboard
if (!data.empty()) {
CMSWindowsClipboard clipboard(m_window);
clipboard.open(0);
clipboard.emptyUnowned();
clipboard.add(IClipboard::kText, data);
clipboard.close();
}
}
}
void
CMSWindowsClientTaskBarReceiver::onStatusChanged()
{
if (IsWindowVisible(m_window)) {
showStatus();
}
}
HICON
CMSWindowsClientTaskBarReceiver::loadIcon(UINT id)
{
HANDLE icon = LoadImage(m_appInstance,
MAKEINTRESOURCE(id),
IMAGE_ICON,
0, 0,
LR_DEFAULTCOLOR);
return reinterpret_cast<HICON>(icon);
}
void
CMSWindowsClientTaskBarReceiver::deleteIcon(HICON icon)
{
if (icon != NULL) {
DestroyIcon(icon);
}
}
void
CMSWindowsClientTaskBarReceiver::createWindow()
{
// ignore if already created
if (m_window != NULL) {
return;
}
// get the status dialog
m_window = CreateDialogParam(m_appInstance,
MAKEINTRESOURCE(IDD_TASKBAR_STATUS),
NULL,
(DLGPROC)&CMSWindowsClientTaskBarReceiver::staticDlgProc,
reinterpret_cast<LPARAM>(
reinterpret_cast<void*>(this)));
// window should appear on top of everything, including (especially)
// the task bar.
LONG_PTR style = GetWindowLongPtr(m_window, GWL_EXSTYLE);
style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
SetWindowLongPtr(m_window, GWL_EXSTYLE, style);
// tell the task bar about this dialog
CArchTaskBarWindows::addDialog(m_window);
}
void
CMSWindowsClientTaskBarReceiver::destroyWindow()
{
if (m_window != NULL) {
CArchTaskBarWindows::removeDialog(m_window);
DestroyWindow(m_window);
m_window = NULL;
}
}
BOOL
CMSWindowsClientTaskBarReceiver::dlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM)
{
switch (msg) {
case WM_INITDIALOG:
// use default focus
return TRUE;
case WM_ACTIVATE:
// hide when another window is activated
if (LOWORD(wParam) == WA_INACTIVE) {
ShowWindow(hwnd, SW_HIDE);
}
break;
}
return FALSE;
}
BOOL CALLBACK
CMSWindowsClientTaskBarReceiver::staticDlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM lParam)
{
// if msg is WM_INITDIALOG, extract the CMSWindowsClientTaskBarReceiver*
// and put it in the extra window data then forward the call.
CMSWindowsClientTaskBarReceiver* self = NULL;
if (msg == WM_INITDIALOG) {
self = reinterpret_cast<CMSWindowsClientTaskBarReceiver*>(
reinterpret_cast<void*>(lParam));
SetWindowLong(hwnd, GWL_USERDATA, lParam);
}
else {
// get the extra window data and forward the call
LONG data = GetWindowLong(hwnd, GWL_USERDATA);
if (data != 0) {
self = reinterpret_cast<CMSWindowsClientTaskBarReceiver*>(
reinterpret_cast<void*>(data));
}
}
// forward the message
if (self != NULL) {
return self->dlgProc(hwnd, msg, wParam, lParam);
}
else {
return (msg == WM_INITDIALOG) ? TRUE : FALSE;
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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 CMSWINDOWSCLIENTTASKBARRECEIVER_H
#define CMSWINDOWSCLIENTTASKBARRECEIVER_H
#define WIN32_LEAN_AND_MEAN
#include "CClientTaskBarReceiver.h"
#include <windows.h>
class CBufferedLogOutputter;
//! Implementation of CClientTaskBarReceiver for Microsoft Windows
class CMSWindowsClientTaskBarReceiver : public CClientTaskBarReceiver {
public:
CMSWindowsClientTaskBarReceiver(HINSTANCE, const CBufferedLogOutputter*);
virtual ~CMSWindowsClientTaskBarReceiver();
// IArchTaskBarReceiver overrides
virtual void showStatus();
virtual void runMenu(int x, int y);
virtual void primaryAction();
virtual const Icon getIcon() const;
protected:
void copyLog() const;
// CClientTaskBarReceiver overrides
virtual void onStatusChanged();
private:
HICON loadIcon(UINT);
void deleteIcon(HICON);
void createWindow();
void destroyWindow();
BOOL dlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM lParam);
static BOOL CALLBACK
staticDlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM lParam);
private:
HINSTANCE m_appInstance;
HWND m_window;
HMENU m_menu;
HICON m_icon[kMaxState];
const CBufferedLogOutputter* m_logBuffer;
static const UINT s_stateToIconID[];
};
#endif

View File

@@ -0,0 +1,56 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2004 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 "COSXClientTaskBarReceiver.h"
#include "CArch.h"
//
// COSXClientTaskBarReceiver
//
COSXClientTaskBarReceiver::COSXClientTaskBarReceiver(
const CBufferedLogOutputter*)
{
// add ourself to the task bar
ARCH->addReceiver(this);
}
COSXClientTaskBarReceiver::~COSXClientTaskBarReceiver()
{
ARCH->removeReceiver(this);
}
void
COSXClientTaskBarReceiver::showStatus()
{
// do nothing
}
void
COSXClientTaskBarReceiver::runMenu(int, int)
{
// do nothing
}
void
COSXClientTaskBarReceiver::primaryAction()
{
// do nothing
}
const IArchTaskBarReceiver::Icon
COSXClientTaskBarReceiver::getIcon() const
{
return NULL;
}

View File

@@ -0,0 +1,35 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2004 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 COSXCLIENTTASKBARRECEIVER_H
#define COSXCLIENTTASKBARRECEIVER_H
#include "CClientTaskBarReceiver.h"
class CBufferedLogOutputter;
//! Implementation of CClientTaskBarReceiver for OS X
class COSXClientTaskBarReceiver : public CClientTaskBarReceiver {
public:
COSXClientTaskBarReceiver(const CBufferedLogOutputter*);
virtual ~COSXClientTaskBarReceiver();
// IArchTaskBarReceiver overrides
virtual void showStatus();
virtual void runMenu(int x, int y);
virtual void primaryAction();
virtual const Icon getIcon() const;
};
#endif

View File

@@ -0,0 +1,56 @@
/*
* 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 "CXWindowsClientTaskBarReceiver.h"
#include "CArch.h"
//
// CXWindowsClientTaskBarReceiver
//
CXWindowsClientTaskBarReceiver::CXWindowsClientTaskBarReceiver(
const CBufferedLogOutputter*)
{
// add ourself to the task bar
ARCH->addReceiver(this);
}
CXWindowsClientTaskBarReceiver::~CXWindowsClientTaskBarReceiver()
{
ARCH->removeReceiver(this);
}
void
CXWindowsClientTaskBarReceiver::showStatus()
{
// do nothing
}
void
CXWindowsClientTaskBarReceiver::runMenu(int, int)
{
// do nothing
}
void
CXWindowsClientTaskBarReceiver::primaryAction()
{
// do nothing
}
const IArchTaskBarReceiver::Icon
CXWindowsClientTaskBarReceiver::getIcon() const
{
return NULL;
}

View File

@@ -0,0 +1,35 @@
/*
* 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 CXWINDOWSCLIENTTASKBARRECEIVER_H
#define CXWINDOWSCLIENTTASKBARRECEIVER_H
#include "CClientTaskBarReceiver.h"
class CBufferedLogOutputter;
//! Implementation of CClientTaskBarReceiver for X Windows
class CXWindowsClientTaskBarReceiver : public CClientTaskBarReceiver {
public:
CXWindowsClientTaskBarReceiver(const CBufferedLogOutputter*);
virtual ~CXWindowsClientTaskBarReceiver();
// IArchTaskBarReceiver overrides
virtual void showStatus();
virtual void runMenu(int x, int y);
virtual void primaryAction();
virtual const Icon getIcon() const;
};
#endif

98
cmd/synergyc/Makefile.am Normal file
View File

@@ -0,0 +1,98 @@
# 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.
## Process this file with automake to produce Makefile.in
NULL =
COMMON_SOURCE_FILES = \
CClientTaskBarReceiver.cpp \
CClientTaskBarReceiver.h \
synergyc.cpp \
$(NULL)
XWINDOWS_SOURCE_FILES = \
CXWindowsClientTaskBarReceiver.cpp \
CXWindowsClientTaskBarReceiver.h \
$(NULL)
MSWINDOWS_SOURCE_FILES = \
CMSWindowsClientTaskBarReceiver.cpp \
CMSWindowsClientTaskBarReceiver.h \
resource.h \
synergyc.rc \
$(NULL)
CARBON_SOURCE_FILES = \
COSXClientTaskBarReceiver.cpp \
COSXClientTaskBarReceiver.h \
$(NULL)
EXTRA_DIST = \
Makefile.win \
synergyc.ico \
tb_error.ico \
tb_idle.ico \
tb_run.ico \
tb_wait.ico \
$(XWINDOWS_SOURCE_FILES) \
$(MSWINDOWS_SOURCE_FILES) \
$(CARBON_SOURCE_FILES) \
$(NULL)
MAINTAINERCLEANFILES = \
Makefile.in \
$(NULL)
bin_PROGRAMS = synergyc
if XWINDOWS
synergyc_SOURCES = \
$(COMMON_SOURCE_FILES) \
$(XWINDOWS_SOURCE_FILES) \
$(NULL)
endif
if MSWINDOWS
synergyc_SOURCES = \
$(COMMON_SOURCE_FILES) \
$(MSWINDOWS_SOURCE_FILES) \
$(NULL)
endif
if CARBON
synergyc_SOURCES = \
$(COMMON_SOURCE_FILES) \
$(CARBON_SOURCE_FILES) \
$(NULL)
synergyc_LDFLAGS = \
-framework ScreenSaver \
-framework IOKit \
-framework ApplicationServices \
-framework Foundation \
$(NULL)
endif
synergyc_LDADD = \
$(top_builddir)/lib/client/libclient.a \
$(top_builddir)/lib/platform/libplatform.a \
$(top_builddir)/lib/synergy/libsynergy.a \
$(top_builddir)/lib/net/libnet.a \
$(top_builddir)/lib/io/libio.a \
$(top_builddir)/lib/mt/libmt.a \
$(top_builddir)/lib/base/libbase.a \
$(top_builddir)/lib/common/libcommon.a \
$(top_builddir)/lib/arch/libarch.a \
$(NULL)
INCLUDES = \
-I$(top_srcdir)/lib/common \
-I$(top_srcdir)/lib/arch \
-I$(top_srcdir)/lib/base \
-I$(top_srcdir)/lib/mt \
-I$(top_srcdir)/lib/io \
-I$(top_srcdir)/lib/net \
-I$(top_srcdir)/lib/synergy \
-I$(top_srcdir)/lib/platform \
-I$(top_srcdir)/lib/client \
$(NULL)

89
cmd/synergyc/Makefile.win Normal file
View File

@@ -0,0 +1,89 @@
# synergy -- mouse and keyboard sharing utility
# Copyright (C) 2007 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.
BIN_SYNERGYC_SRC = cmd\synergyc
BIN_SYNERGYC_DST = $(BUILD_DST)\$(BIN_SYNERGYC_SRC)
BIN_SYNERGYC_EXE = "$(BUILD_DST)\synergyc.exe"
BIN_SYNERGYC_CPP = \
"CClientTaskBarReceiver.cpp" \
"CMSWindowsClientTaskBarReceiver.cpp" \
"synergyc.cpp" \
$(NULL)
BIN_SYNERGYC_OBJ = \
"$(BIN_SYNERGYC_DST)\CClientTaskBarReceiver.obj" \
"$(BIN_SYNERGYC_DST)\CMSWindowsClientTaskBarReceiver.obj" \
"$(BIN_SYNERGYC_DST)\synergyc.obj" \
$(NULL)
BIN_SYNERGYC_RC = "$(BIN_SYNERGYC_SRC)\synergyc.rc"
BIN_SYNERGYC_RES = "$(BIN_SYNERGYC_DST)\synergyc.res"
BIN_SYNERGYC_INC = \
/I"lib\common" \
/I"lib\arch" \
/I"lib\base" \
/I"lib\mt" \
/I"lib\io" \
/I"lib\net" \
/I"lib\synergy" \
/I"lib\platform" \
/I"lib\client" \
$(NULL)
BIN_SYNERGYC_LIB = \
$(LIB_CLIENT_LIB) \
$(LIB_PLATFORM_LIB) \
$(LIB_SYNERGY_LIB) \
$(LIB_NET_LIB) \
$(LIB_IO_LIB) \
$(LIB_MT_LIB) \
$(LIB_BASE_LIB) \
$(LIB_ARCH_LIB) \
$(LIB_COMMON_LIB) \
$(NULL)
CPP_FILES = $(CPP_FILES) $(BIN_SYNERGYC_CPP)
OBJ_FILES = $(OBJ_FILES) $(BIN_SYNERGYC_OBJ)
PROGRAMS = $(PROGRAMS) $(BIN_SYNERGYC_EXE)
# Need shell functions.
guilibs = $(guilibs) shell32.lib
# Dependency rules
$(BIN_SYNERGYC_OBJ): $(AUTODEP)
!if EXIST($(BIN_SYNERGYC_DST)\deps.mak)
!include $(BIN_SYNERGYC_DST)\deps.mak
!endif
# Build rules. Use batch-mode rules if possible.
!if DEFINED(_NMAKE_VER)
{$(BIN_SYNERGYC_SRC)\}.cpp{$(BIN_SYNERGYC_DST)\}.obj::
!else
{$(BIN_SYNERGYC_SRC)\}.cpp{$(BIN_SYNERGYC_DST)\}.obj:
!endif
@$(ECHO) Compile in $(BIN_SYNERGYC_SRC)
-@$(MKDIR) $(BIN_SYNERGYC_DST) 2>NUL:
$(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \
$(BIN_SYNERGYC_INC) \
/Fo$(BIN_SYNERGYC_DST)\ \
/Fd$(BIN_SYNERGYC_DST)\src.pdb \
$< | $(AUTODEP) $(BIN_SYNERGYC_SRC) $(BIN_SYNERGYC_DST)
$(BIN_SYNERGYC_RES): $(BIN_SYNERGYC_RC)
@$(ECHO) Compile $(**F)
-@$(MKDIR) $(BIN_SYNERGYC_DST) 2>NUL:
$(rc) $(rcflags) $(rcvars) \
/fo$@ \
$**
$(BIN_SYNERGYC_EXE): $(BIN_SYNERGYC_OBJ) $(BIN_SYNERGYC_RES) $(BIN_SYNERGYC_LIB)
@$(ECHO) Link $(@F)
$(link) $(ldebug) $(guilflags) $(guilibsmt) \
/out:$@ \
$**
$(AUTODEP) $(BIN_SYNERGYC_SRC) $(BIN_SYNERGYC_DST) \
$(BIN_SYNERGYC_OBJ:.obj=.d)

37
cmd/synergyc/resource.h Normal file
View File

@@ -0,0 +1,37 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by synergyc.rc
//
#define IDS_FAILED 1
#define IDS_INIT_FAILED 2
#define IDS_UNCAUGHT_EXCEPTION 3
#define IDI_SYNERGY 101
#define IDI_TASKBAR_NOT_RUNNING 102
#define IDI_TASKBAR_NOT_WORKING 103
#define IDI_TASKBAR_NOT_CONNECTED 104
#define IDI_TASKBAR_CONNECTED 105
#define IDR_TASKBAR 107
#define IDD_TASKBAR_STATUS 108
#define IDC_TASKBAR_STATUS_STATUS 1000
#define IDC_TASKBAR_QUIT 40001
#define IDC_TASKBAR_STATUS 40002
#define IDC_TASKBAR_LOG 40003
#define IDC_TASKBAR_SHOW_LOG 40004
#define IDC_TASKBAR_LOG_LEVEL_ERROR 40009
#define IDC_TASKBAR_LOG_LEVEL_WARNING 40010
#define IDC_TASKBAR_LOG_LEVEL_NOTE 40011
#define IDC_TASKBAR_LOG_LEVEL_INFO 40012
#define IDC_TASKBAR_LOG_LEVEL_DEBUG 40013
#define IDC_TASKBAR_LOG_LEVEL_DEBUG1 40014
#define IDC_TASKBAR_LOG_LEVEL_DEBUG2 40015
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40016
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

910
cmd/synergyc/synergyc.cpp Normal file
View File

@@ -0,0 +1,910 @@
/*
* 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 "CClient.h"
#include "CScreen.h"
#include "ProtocolTypes.h"
#include "Version.h"
#include "XScreen.h"
#include "CNetworkAddress.h"
#include "CSocketMultiplexer.h"
#include "CTCPSocketFactory.h"
#include "XSocket.h"
#include "CThread.h"
#include "CEventQueue.h"
#include "CFunctionEventJob.h"
#include "CFunctionJob.h"
#include "CLog.h"
#include "CString.h"
#include "CStringUtil.h"
#include "LogOutputters.h"
#include "CArch.h"
#include "XArch.h"
#include <cstring>
#define DAEMON_RUNNING(running_)
#if WINAPI_MSWINDOWS
#include "CArchMiscWindows.h"
#include "CMSWindowsScreen.h"
#include "CMSWindowsUtil.h"
#include "CMSWindowsClientTaskBarReceiver.h"
#include "resource.h"
#undef DAEMON_RUNNING
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
#elif WINAPI_XWINDOWS
#include "CXWindowsScreen.h"
#include "CXWindowsClientTaskBarReceiver.h"
#elif WINAPI_CARBON
#include "COSXScreen.h"
#include "COSXClientTaskBarReceiver.h"
#endif
// platform dependent name of a daemon
#if SYSAPI_WIN32
#define DAEMON_NAME "Synergy Client"
#elif SYSAPI_UNIX
#define DAEMON_NAME "synergyc"
#endif
typedef int (*StartupFunc)(int, char**);
static bool startClient();
static void parse(int argc, const char* const* argv);
//
// program arguments
//
#define ARG CArgs::s_instance
class CArgs {
public:
CArgs() :
m_pname(NULL),
m_backend(false),
m_restartable(true),
m_daemon(true),
m_logFilter(NULL),
m_display(NULL),
m_serverAddress(NULL)
{ s_instance = this; }
~CArgs() { s_instance = NULL; }
public:
static CArgs* s_instance;
const char* m_pname;
bool m_backend;
bool m_restartable;
bool m_daemon;
const char* m_logFilter;
const char* m_display;
CString m_name;
CNetworkAddress* m_serverAddress;
};
CArgs* CArgs::s_instance = NULL;
//
// platform dependent factories
//
static
CScreen*
createScreen()
{
#if WINAPI_MSWINDOWS
return new CScreen(new CMSWindowsScreen(false));
#elif WINAPI_XWINDOWS
return new CScreen(new CXWindowsScreen(ARG->m_display, false));
#elif WINAPI_CARBON
return new CScreen(new COSXScreen(false));
#endif
}
static
CClientTaskBarReceiver*
createTaskBarReceiver(const CBufferedLogOutputter* logBuffer)
{
#if WINAPI_MSWINDOWS
return new CMSWindowsClientTaskBarReceiver(
CMSWindowsScreen::getInstance(), logBuffer);
#elif WINAPI_XWINDOWS
return new CXWindowsClientTaskBarReceiver(logBuffer);
#elif WINAPI_CARBON
return new COSXClientTaskBarReceiver(logBuffer);
#endif
}
//
// platform independent main
//
static CClient* s_client = NULL;
static CScreen* s_clientScreen = NULL;
static CClientTaskBarReceiver* s_taskBarReceiver = NULL;
static double s_retryTime = 0.0;
static bool s_suspened = false;
static
void
updateStatus()
{
s_taskBarReceiver->updateStatus(s_client, "");
}
static
void
updateStatus(const CString& msg)
{
s_taskBarReceiver->updateStatus(s_client, msg);
}
static
void
resetRestartTimeout()
{
s_retryTime = 0.0;
}
static
double
nextRestartTimeout()
{
// choose next restart timeout. we start with rapid retries
// then slow down.
if (s_retryTime < 1.0) {
s_retryTime = 1.0;
}
else if (s_retryTime < 3.0) {
s_retryTime = 3.0;
}
else if (s_retryTime < 5.0) {
s_retryTime = 5.0;
}
else if (s_retryTime < 15.0) {
s_retryTime = 15.0;
}
else if (s_retryTime < 30.0) {
s_retryTime = 30.0;
}
else {
s_retryTime = 60.0;
}
return s_retryTime;
}
static
void
handleScreenError(const CEvent&, void*)
{
LOG((CLOG_CRIT "error on screen"));
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
static
CScreen*
openClientScreen()
{
CScreen* screen = createScreen();
EVENTQUEUE->adoptHandler(IScreen::getErrorEvent(),
screen->getEventTarget(),
new CFunctionEventJob(
&handleScreenError));
return screen;
}
static
void
closeClientScreen(CScreen* screen)
{
if (screen != NULL) {
EVENTQUEUE->removeHandler(IScreen::getErrorEvent(),
screen->getEventTarget());
delete screen;
}
}
static
void
handleClientRestart(const CEvent&, void* vtimer)
{
// discard old timer
CEventQueueTimer* timer = reinterpret_cast<CEventQueueTimer*>(vtimer);
EVENTQUEUE->deleteTimer(timer);
EVENTQUEUE->removeHandler(CEvent::kTimer, timer);
// reconnect
startClient();
}
static
void
scheduleClientRestart(double retryTime)
{
// install a timer and handler to retry later
LOG((CLOG_DEBUG "retry in %.0f seconds", retryTime));
CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(retryTime, NULL);
EVENTQUEUE->adoptHandler(CEvent::kTimer, timer,
new CFunctionEventJob(&handleClientRestart, timer));
}
static
void
handleClientConnected(const CEvent&, void*)
{
LOG((CLOG_NOTE "connected to server"));
resetRestartTimeout();
updateStatus();
}
static
void
handleClientFailed(const CEvent& e, void*)
{
CClient::CFailInfo* info =
reinterpret_cast<CClient::CFailInfo*>(e.getData());
updateStatus(CString("Failed to connect to server: ") + info->m_what);
if (!ARG->m_restartable || !info->m_retry) {
LOG((CLOG_ERR "failed to connect to server: %s", info->m_what));
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
else {
LOG((CLOG_WARN "failed to connect to server: %s", info->m_what));
if (!s_suspened) {
scheduleClientRestart(nextRestartTimeout());
}
}
}
static
void
handleClientDisconnected(const CEvent&, void*)
{
LOG((CLOG_NOTE "disconnected from server"));
if (!ARG->m_restartable) {
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
else if (!s_suspened) {
s_client->connect();
}
updateStatus();
}
static
CClient*
openClient(const CString& name, const CNetworkAddress& address, CScreen* screen)
{
CClient* client = new CClient(name, address,
new CTCPSocketFactory, NULL, screen);
EVENTQUEUE->adoptHandler(CClient::getConnectedEvent(),
client->getEventTarget(),
new CFunctionEventJob(handleClientConnected));
EVENTQUEUE->adoptHandler(CClient::getConnectionFailedEvent(),
client->getEventTarget(),
new CFunctionEventJob(handleClientFailed));
EVENTQUEUE->adoptHandler(CClient::getDisconnectedEvent(),
client->getEventTarget(),
new CFunctionEventJob(handleClientDisconnected));
return client;
}
static
void
closeClient(CClient* client)
{
if (client == NULL) {
return;
}
EVENTQUEUE->removeHandler(CClient::getConnectedEvent(), client);
EVENTQUEUE->removeHandler(CClient::getConnectionFailedEvent(), client);
EVENTQUEUE->removeHandler(CClient::getDisconnectedEvent(), client);
delete client;
}
static
bool
startClient()
{
double retryTime;
CScreen* clientScreen = NULL;
try {
if (s_clientScreen == NULL) {
clientScreen = openClientScreen();
s_client = openClient(ARG->m_name,
*ARG->m_serverAddress, clientScreen);
s_clientScreen = clientScreen;
LOG((CLOG_NOTE "started client"));
}
s_client->connect();
updateStatus();
return true;
}
catch (XScreenUnavailable& e) {
LOG((CLOG_WARN "cannot open secondary screen: %s", e.what()));
closeClientScreen(clientScreen);
updateStatus(CString("Cannot open secondary screen: ") + e.what());
retryTime = e.getRetryTime();
}
catch (XScreenOpenFailure& e) {
LOG((CLOG_CRIT "cannot open secondary screen: %s", e.what()));
closeClientScreen(clientScreen);
return false;
}
catch (XBase& e) {
LOG((CLOG_CRIT "failed to start client: %s", e.what()));
closeClientScreen(clientScreen);
return false;
}
if (ARG->m_restartable) {
scheduleClientRestart(retryTime);
return true;
}
else {
// don't try again
return false;
}
}
static
void
stopClient()
{
closeClient(s_client);
closeClientScreen(s_clientScreen);
s_client = NULL;
s_clientScreen = NULL;
}
static
int
mainLoop()
{
// create socket multiplexer. this must happen after daemonization
// on unix because threads evaporate across a fork().
CSocketMultiplexer multiplexer;
// create the event queue
CEventQueue eventQueue;
// start the client. if this return false then we've failed and
// we shouldn't retry.
LOG((CLOG_DEBUG1 "starting client"));
if (!startClient()) {
return kExitFailed;
}
// run event loop. if startClient() failed we're supposed to retry
// later. the timer installed by startClient() will take care of
// that.
CEvent event;
DAEMON_RUNNING(true);
EVENTQUEUE->getEvent(event);
while (event.getType() != CEvent::kQuit) {
EVENTQUEUE->dispatchEvent(event);
CEvent::deleteData(event);
EVENTQUEUE->getEvent(event);
}
DAEMON_RUNNING(false);
// close down
LOG((CLOG_DEBUG1 "stopping client"));
stopClient();
updateStatus();
LOG((CLOG_NOTE "stopped client"));
return kExitSuccess;
}
static
int
daemonMainLoop(int, const char**)
{
#if SYSAPI_WIN32
CSystemLogger sysLogger(DAEMON_NAME, false);
#else
CSystemLogger sysLogger(DAEMON_NAME, true);
#endif
return mainLoop();
}
static
int
standardStartup(int argc, char** argv)
{
if (!ARG->m_daemon) {
ARCH->showConsole(false);
}
// parse command line
parse(argc, argv);
// daemonize if requested
if (ARG->m_daemon) {
return ARCH->daemonize(DAEMON_NAME, &daemonMainLoop);
}
else {
return mainLoop();
}
}
static
int
run(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
{
// general initialization
ARG->m_serverAddress = new CNetworkAddress;
ARG->m_pname = ARCH->getBasename(argv[0]);
// install caller's output filter
if (outputter != NULL) {
CLOG->insert(outputter);
}
// save log messages
CBufferedLogOutputter logBuffer(1000);
CLOG->insert(&logBuffer, true);
// make the task bar receiver. the user can control this app
// through the task bar.
s_taskBarReceiver = createTaskBarReceiver(&logBuffer);
// run
int result = startup(argc, argv);
// done with task bar receiver
delete s_taskBarReceiver;
// done with log buffer
CLOG->remove(&logBuffer);
delete ARG->m_serverAddress;
return result;
}
//
// command line parsing
//
#define BYE "\nTry `%s --help' for more information."
static void (*bye)(int) = &exit;
static
void
version()
{
LOG((CLOG_PRINT "%s %s, protocol version %d.%d\n%s",
ARG->m_pname,
kVersion,
kProtocolMajorVersion,
kProtocolMinorVersion,
kCopyright));
}
static
void
help()
{
#if WINAPI_XWINDOWS
# define USAGE_DISPLAY_ARG \
" [--display <display>]"
# define USAGE_DISPLAY_INFO \
" --display <display> connect to the X server at <display>\n"
#else
# define USAGE_DISPLAY_ARG
# define USAGE_DISPLAY_INFO
#endif
LOG((CLOG_PRINT
"Usage: %s"
" [--daemon|--no-daemon]"
" [--debug <level>]"
USAGE_DISPLAY_ARG
" [--name <screen-name>]"
" [--restart|--no-restart]"
" <server-address>"
"\n\n"
"Start the synergy mouse/keyboard sharing server.\n"
"\n"
" -d, --debug <level> filter out log messages with priorty below level.\n"
" level may be: FATAL, ERROR, WARNING, NOTE, INFO,\n"
" DEBUG, DEBUG1, DEBUG2.\n"
USAGE_DISPLAY_INFO
" -f, --no-daemon run the client in the foreground.\n"
"* --daemon run the client as a daemon.\n"
" -n, --name <screen-name> use screen-name instead the hostname to identify\n"
" ourself to the server.\n"
" -1, --no-restart do not try to restart the client if it fails for\n"
" some reason.\n"
"* --restart restart the client automatically if it fails.\n"
" -h, --help display this help and exit.\n"
" --version display version information and exit.\n"
"\n"
"* marks defaults.\n"
"\n"
"The server address is of the form: [<hostname>][:<port>]. The hostname\n"
"must be the address or hostname of the server. The port overrides the\n"
"default port, %d.\n"
"\n"
"Where log messages go depends on the platform and whether or not the\n"
"client is running as a daemon.",
ARG->m_pname, kDefaultPort));
}
static
bool
isArg(int argi, int argc, const char* const* argv,
const char* name1, const char* name2,
int minRequiredParameters = 0)
{
if ((name1 != NULL && strcmp(argv[argi], name1) == 0) ||
(name2 != NULL && strcmp(argv[argi], name2) == 0)) {
// match. check args left.
if (argi + minRequiredParameters >= argc) {
LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE,
ARG->m_pname, argv[argi], ARG->m_pname));
bye(kExitArgs);
}
return true;
}
// no match
return false;
}
static
void
parse(int argc, const char* const* argv)
{
assert(ARG->m_pname != NULL);
assert(argv != NULL);
assert(argc >= 1);
// set defaults
ARG->m_name = ARCH->getHostName();
// parse options
int i;
for (i = 1; i < argc; ++i) {
if (isArg(i, argc, argv, "-d", "--debug", 1)) {
// change logging level
ARG->m_logFilter = argv[++i];
}
else if (isArg(i, argc, argv, "-n", "--name", 1)) {
// save screen name
ARG->m_name = argv[++i];
}
else if (isArg(i, argc, argv, NULL, "--camp")) {
// ignore -- included for backwards compatibility
}
else if (isArg(i, argc, argv, NULL, "--no-camp")) {
// ignore -- included for backwards compatibility
}
else if (isArg(i, argc, argv, "-f", "--no-daemon")) {
// not a daemon
ARG->m_daemon = false;
}
else if (isArg(i, argc, argv, NULL, "--daemon")) {
// daemonize
ARG->m_daemon = true;
}
#if WINAPI_XWINDOWS
else if (isArg(i, argc, argv, "-display", "--display", 1)) {
// use alternative display
ARG->m_display = argv[++i];
}
#endif
else if (isArg(i, argc, argv, "-1", "--no-restart")) {
// don't try to restart
ARG->m_restartable = false;
}
else if (isArg(i, argc, argv, NULL, "--restart")) {
// try to restart
ARG->m_restartable = true;
}
else if (isArg(i, argc, argv, "-z", NULL)) {
ARG->m_backend = true;
}
else if (isArg(i, argc, argv, "-h", "--help")) {
help();
bye(kExitSuccess);
}
else if (isArg(i, argc, argv, NULL, "--version")) {
version();
bye(kExitSuccess);
}
else if (isArg(i, argc, argv, "--", NULL)) {
// remaining arguments are not options
++i;
break;
}
else if (argv[i][0] == '-') {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
ARG->m_pname, argv[i], ARG->m_pname));
bye(kExitArgs);
}
else {
// this and remaining arguments are not options
break;
}
}
// exactly one non-option argument (server-address)
if (i == argc) {
LOG((CLOG_PRINT "%s: a server address or name is required" BYE,
ARG->m_pname, ARG->m_pname));
bye(kExitArgs);
}
if (i + 1 != argc) {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
ARG->m_pname, argv[i], ARG->m_pname));
bye(kExitArgs);
}
// save server address
try {
*ARG->m_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
ARG->m_serverAddress->resolve();
}
catch (XSocketAddress& e) {
// allow an address that we can't look up if we're restartable.
// we'll try to resolve the address each time we connect to the
// server. a bad port will never get better. patch by Brent
// Priddy.
if (!ARG->m_restartable || e.getError() == XSocketAddress::kBadPort) {
LOG((CLOG_PRINT "%s: %s" BYE,
ARG->m_pname, e.what(), ARG->m_pname));
bye(kExitFailed);
}
}
// increase default filter level for daemon. the user must
// explicitly request another level for a daemon.
if (ARG->m_daemon && ARG->m_logFilter == NULL) {
#if SYSAPI_WIN32
if (CArchMiscWindows::isWindows95Family()) {
// windows 95 has no place for logging so avoid showing
// the log console window.
ARG->m_logFilter = "FATAL";
}
else
#endif
{
ARG->m_logFilter = "NOTE";
}
}
// set log filter
if (!CLOG->setFilter(ARG->m_logFilter)) {
LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
ARG->m_pname, ARG->m_logFilter, ARG->m_pname));
bye(kExitArgs);
}
// identify system
LOG((CLOG_INFO "Synergy client %s on %s", kVersion, ARCH->getOSName().c_str()));
}
//
// platform dependent entry points
//
#if SYSAPI_WIN32
static bool s_hasImportantLogMessages = false;
//
// CMessageBoxOutputter
//
// This class writes severe log messages to a message box
//
class CMessageBoxOutputter : public ILogOutputter {
public:
CMessageBoxOutputter() { }
virtual ~CMessageBoxOutputter() { }
// ILogOutputter overrides
virtual void open(const char*) { }
virtual void close() { }
virtual void show(bool) { }
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const { return ""; }
};
bool
CMessageBoxOutputter::write(ELevel level, const char* message)
{
// note any important messages the user may need to know about
if (level <= CLog::kWARNING) {
s_hasImportantLogMessages = true;
}
// FATAL and PRINT messages get a dialog box if not running as
// backend. if we're running as a backend the user will have
// a chance to see the messages when we exit.
if (!ARG->m_backend && level <= CLog::kFATAL) {
MessageBox(NULL, message, ARG->m_pname, MB_OK | MB_ICONWARNING);
return false;
}
else {
return true;
}
}
static
void
byeThrow(int x)
{
CArchMiscWindows::daemonFailed(x);
}
static
int
daemonNTMainLoop(int argc, const char** argv)
{
parse(argc, argv);
ARG->m_backend = false;
return CArchMiscWindows::runDaemon(mainLoop);
}
static
int
daemonNTStartup(int, char**)
{
CSystemLogger sysLogger(DAEMON_NAME, false);
bye = &byeThrow;
return ARCH->daemonize(DAEMON_NAME, &daemonNTMainLoop);
}
static
int
foregroundStartup(int argc, char** argv)
{
ARCH->showConsole(false);
// parse command line
parse(argc, argv);
// never daemonize
return mainLoop();
}
static
void
showError(HINSTANCE instance, const char* title, UINT id, const char* arg)
{
CString fmt = CMSWindowsUtil::getString(instance, id);
CString msg = CStringUtil::format(fmt.c_str(), arg);
MessageBox(NULL, msg.c_str(), title, MB_OK | MB_ICONWARNING);
}
int WINAPI
WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
{
try {
CArchMiscWindows::setIcons((HICON)LoadImage(instance,
MAKEINTRESOURCE(IDI_SYNERGY),
IMAGE_ICON,
32, 32, LR_SHARED),
(HICON)LoadImage(instance,
MAKEINTRESOURCE(IDI_SYNERGY),
IMAGE_ICON,
16, 16, LR_SHARED));
CArch arch(instance);
CMSWindowsScreen::init(instance);
CLOG;
CThread::getCurrentThread().setPriority(-14);
CArgs args;
// set title on log window
ARCH->openConsole((CString(kAppVersion) + " " + "Client").c_str());
// windows NT family starts services using no command line options.
// since i'm not sure how to tell the difference between that and
// a user providing no options we'll assume that if there are no
// arguments and we're on NT then we're being invoked as a service.
// users on NT can use `--daemon' or `--no-daemon' to force us out
// of the service code path.
StartupFunc startup = &standardStartup;
if (!CArchMiscWindows::isWindows95Family()) {
if (__argc <= 1) {
startup = &daemonNTStartup;
}
else {
startup = &foregroundStartup;
}
}
// send PRINT and FATAL output to a message box
int result = run(__argc, __argv, new CMessageBoxOutputter, startup);
// let user examine any messages if we're running as a backend
// by putting up a dialog box before exiting.
if (args.m_backend && s_hasImportantLogMessages) {
showError(instance, args.m_pname, IDS_FAILED, "");
}
delete CLOG;
return result;
}
catch (XBase& e) {
showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, e.what());
//throw;
}
catch (XArch& e) {
showError(instance, __argv[0], IDS_INIT_FAILED, e.what().c_str());
}
catch (...) {
showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, "<unknown>");
//throw;
}
return kExitFailed;
}
#elif SYSAPI_UNIX
int
main(int argc, char** argv)
{
CArgs args;
try {
int result;
CArch arch;
CLOG;
CArgs args;
result = run(argc, argv, NULL, &standardStartup);
delete CLOG;
return result;
}
catch (XBase& e) {
LOG((CLOG_CRIT "Uncaught exception: %s\n", e.what()));
throw;
}
catch (XArch& e) {
LOG((CLOG_CRIT "Initialization failed: %s" BYE, e.what().c_str()));
return kExitFailed;
}
catch (...) {
LOG((CLOG_CRIT "Uncaught exception: <unknown exception>\n"));
throw;
}
}
#else
#error no main() for platform
#endif

BIN
cmd/synergyc/synergyc.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

141
cmd/synergyc/synergyc.rc Normal file
View File

@@ -0,0 +1,141 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include <winresrc.h>
#if !defined(IDC_STATIC)
#define IDC_STATIC (-1)
#endif
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include <winresrc.h>\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_SYNERGY ICON DISCARDABLE "synergyc.ico"
IDI_TASKBAR_NOT_RUNNING ICON DISCARDABLE "tb_idle.ico"
IDI_TASKBAR_NOT_WORKING ICON DISCARDABLE "tb_error.ico"
IDI_TASKBAR_NOT_CONNECTED ICON DISCARDABLE "tb_wait.ico"
IDI_TASKBAR_CONNECTED ICON DISCARDABLE "tb_run.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_TASKBAR_STATUS DIALOG DISCARDABLE 0, 0, 145, 18
STYLE DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_TASKBAR_STATUS_STATUS,3,3,139,12,ES_AUTOHSCROLL |
ES_READONLY | NOT WS_BORDER
END
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_TASKBAR MENU DISCARDABLE
BEGIN
POPUP "Synergy"
BEGIN
MENUITEM "Show Status", IDC_TASKBAR_STATUS
MENUITEM "Show Log", IDC_TASKBAR_SHOW_LOG
MENUITEM "Copy Log To Clipboard", IDC_TASKBAR_LOG
POPUP "Set Log Level"
BEGIN
MENUITEM "Error", IDC_TASKBAR_LOG_LEVEL_ERROR
MENUITEM "Warning", IDC_TASKBAR_LOG_LEVEL_WARNING
MENUITEM "Note", IDC_TASKBAR_LOG_LEVEL_NOTE
MENUITEM "Info", IDC_TASKBAR_LOG_LEVEL_INFO
MENUITEM "Debug", IDC_TASKBAR_LOG_LEVEL_DEBUG
MENUITEM "Debug1", IDC_TASKBAR_LOG_LEVEL_DEBUG1
MENUITEM "Debug2", IDC_TASKBAR_LOG_LEVEL_DEBUG2
END
MENUITEM SEPARATOR
MENUITEM "Quit", IDC_TASKBAR_QUIT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_FAILED "Synergy is about to quit with errors or warnings. Please check the log then click OK."
IDS_INIT_FAILED "Synergy failed to initialize: %{1}"
IDS_UNCAUGHT_EXCEPTION "Uncaught exception: %{1}"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

BIN
cmd/synergyc/tb_error.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
cmd/synergyc/tb_idle.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
cmd/synergyc/tb_run.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
cmd/synergyc/tb_wait.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

@@ -0,0 +1,374 @@
/*
* 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 "CMSWindowsServerTaskBarReceiver.h"
#include "CServer.h"
#include "CMSWindowsClipboard.h"
#include "IEventQueue.h"
#include "LogOutputters.h"
#include "BasicTypes.h"
#include "CArch.h"
#include "CArchTaskBarWindows.h"
#include "resource.h"
extern CEvent::Type getReloadConfigEvent();
extern CEvent::Type getForceReconnectEvent();
//
// CMSWindowsServerTaskBarReceiver
//
const UINT CMSWindowsServerTaskBarReceiver::s_stateToIconID[kMaxState] =
{
IDI_TASKBAR_NOT_RUNNING,
IDI_TASKBAR_NOT_WORKING,
IDI_TASKBAR_NOT_CONNECTED,
IDI_TASKBAR_CONNECTED
};
CMSWindowsServerTaskBarReceiver::CMSWindowsServerTaskBarReceiver(
HINSTANCE appInstance, const CBufferedLogOutputter* logBuffer) :
CServerTaskBarReceiver(),
m_appInstance(appInstance),
m_window(NULL),
m_logBuffer(logBuffer)
{
for (UInt32 i = 0; i < kMaxState; ++i) {
m_icon[i] = loadIcon(s_stateToIconID[i]);
}
m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR));
// don't create the window yet. we'll create it on demand. this
// has the side benefit of being created in the thread used for
// the task bar. that's good because it means the existence of
// the window won't prevent changing the main thread's desktop.
// add ourself to the task bar
ARCH->addReceiver(this);
}
CMSWindowsServerTaskBarReceiver::~CMSWindowsServerTaskBarReceiver()
{
ARCH->removeReceiver(this);
for (UInt32 i = 0; i < kMaxState; ++i) {
deleteIcon(m_icon[i]);
}
DestroyMenu(m_menu);
destroyWindow();
}
void
CMSWindowsServerTaskBarReceiver::showStatus()
{
// create the window
createWindow();
// lock self while getting status
lock();
// get the current status
std::string status = getToolTip();
// get the connect clients, if any
const CClients& clients = getClients();
// done getting status
unlock();
// update dialog
HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS);
SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str());
child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_CLIENTS);
SendMessage(child, LB_RESETCONTENT, 0, 0);
for (CClients::const_iterator index = clients.begin();
index != clients.end(); ) {
const char* client = index->c_str();
if (++index == clients.end()) {
SendMessage(child, LB_ADDSTRING, 0, (LPARAM)client);
}
else {
SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)client);
}
}
if (!IsWindowVisible(m_window)) {
// position it by the mouse
POINT cursorPos;
GetCursorPos(&cursorPos);
RECT windowRect;
GetWindowRect(m_window, &windowRect);
int x = cursorPos.x;
int y = cursorPos.y;
int fw = GetSystemMetrics(SM_CXDLGFRAME);
int fh = GetSystemMetrics(SM_CYDLGFRAME);
int ww = windowRect.right - windowRect.left;
int wh = windowRect.bottom - windowRect.top;
int sw = GetSystemMetrics(SM_CXFULLSCREEN);
int sh = GetSystemMetrics(SM_CYFULLSCREEN);
if (fw < 1) {
fw = 1;
}
if (fh < 1) {
fh = 1;
}
if (x + ww - fw > sw) {
x -= ww - fw;
}
else {
x -= fw;
}
if (x < 0) {
x = 0;
}
if (y + wh - fh > sh) {
y -= wh - fh;
}
else {
y -= fh;
}
if (y < 0) {
y = 0;
}
SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh,
SWP_SHOWWINDOW);
}
}
void
CMSWindowsServerTaskBarReceiver::runMenu(int x, int y)
{
// do popup menu. we need a window to pass to TrackPopupMenu().
// the SetForegroundWindow() and SendMessage() calls around
// TrackPopupMenu() are to get the menu to be dismissed when
// another window gets activated and are just one of those
// win32 weirdnesses.
createWindow();
SetForegroundWindow(m_window);
HMENU menu = GetSubMenu(m_menu, 0);
SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE);
HMENU logLevelMenu = GetSubMenu(menu, 3);
CheckMenuRadioItem(logLevelMenu, 0, 6,
CLOG->getFilter() - CLog::kERROR, MF_BYPOSITION);
int n = TrackPopupMenu(menu,
TPM_NONOTIFY |
TPM_RETURNCMD |
TPM_LEFTBUTTON |
TPM_RIGHTBUTTON,
x, y, 0, m_window, NULL);
SendMessage(m_window, WM_NULL, 0, 0);
// perform the requested operation
switch (n) {
case IDC_TASKBAR_STATUS:
showStatus();
break;
case IDC_TASKBAR_LOG:
copyLog();
break;
case IDC_TASKBAR_SHOW_LOG:
ARCH->showConsole(true);
break;
case IDC_RELOAD_CONFIG:
EVENTQUEUE->addEvent(CEvent(getReloadConfigEvent(),
IEventQueue::getSystemTarget()));
break;
case IDC_FORCE_RECONNECT:
EVENTQUEUE->addEvent(CEvent(getForceReconnectEvent(),
IEventQueue::getSystemTarget()));
break;
case IDC_TASKBAR_LOG_LEVEL_ERROR:
CLOG->setFilter(CLog::kERROR);
break;
case IDC_TASKBAR_LOG_LEVEL_WARNING:
CLOG->setFilter(CLog::kWARNING);
break;
case IDC_TASKBAR_LOG_LEVEL_NOTE:
CLOG->setFilter(CLog::kNOTE);
break;
case IDC_TASKBAR_LOG_LEVEL_INFO:
CLOG->setFilter(CLog::kINFO);
break;
case IDC_TASKBAR_LOG_LEVEL_DEBUG:
CLOG->setFilter(CLog::kDEBUG);
break;
case IDC_TASKBAR_LOG_LEVEL_DEBUG1:
CLOG->setFilter(CLog::kDEBUG1);
break;
case IDC_TASKBAR_LOG_LEVEL_DEBUG2:
CLOG->setFilter(CLog::kDEBUG2);
break;
case IDC_TASKBAR_QUIT:
quit();
break;
}
}
void
CMSWindowsServerTaskBarReceiver::primaryAction()
{
showStatus();
}
const IArchTaskBarReceiver::Icon
CMSWindowsServerTaskBarReceiver::getIcon() const
{
return reinterpret_cast<Icon>(m_icon[getStatus()]);
}
void
CMSWindowsServerTaskBarReceiver::copyLog() const
{
if (m_logBuffer != NULL) {
// collect log buffer
CString data;
for (CBufferedLogOutputter::const_iterator index = m_logBuffer->begin();
index != m_logBuffer->end(); ++index) {
data += *index;
data += "\n";
}
// copy log to clipboard
if (!data.empty()) {
CMSWindowsClipboard clipboard(m_window);
clipboard.open(0);
clipboard.emptyUnowned();
clipboard.add(IClipboard::kText, data);
clipboard.close();
}
}
}
void
CMSWindowsServerTaskBarReceiver::onStatusChanged()
{
if (IsWindowVisible(m_window)) {
showStatus();
}
}
HICON
CMSWindowsServerTaskBarReceiver::loadIcon(UINT id)
{
HANDLE icon = LoadImage(m_appInstance,
MAKEINTRESOURCE(id),
IMAGE_ICON,
0, 0,
LR_DEFAULTCOLOR);
return reinterpret_cast<HICON>(icon);
}
void
CMSWindowsServerTaskBarReceiver::deleteIcon(HICON icon)
{
if (icon != NULL) {
DestroyIcon(icon);
}
}
void
CMSWindowsServerTaskBarReceiver::createWindow()
{
// ignore if already created
if (m_window != NULL) {
return;
}
// get the status dialog
m_window = CreateDialogParam(m_appInstance,
MAKEINTRESOURCE(IDD_TASKBAR_STATUS),
NULL,
(DLGPROC)&CMSWindowsServerTaskBarReceiver::staticDlgProc,
reinterpret_cast<LPARAM>(
reinterpret_cast<void*>(this)));
// window should appear on top of everything, including (especially)
// the task bar.
LONG_PTR style = GetWindowLongPtr(m_window, GWL_EXSTYLE);
style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
SetWindowLongPtr(m_window, GWL_EXSTYLE, style);
// tell the task bar about this dialog
CArchTaskBarWindows::addDialog(m_window);
}
void
CMSWindowsServerTaskBarReceiver::destroyWindow()
{
if (m_window != NULL) {
CArchTaskBarWindows::removeDialog(m_window);
DestroyWindow(m_window);
m_window = NULL;
}
}
BOOL
CMSWindowsServerTaskBarReceiver::dlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM)
{
switch (msg) {
case WM_INITDIALOG:
// use default focus
return TRUE;
case WM_ACTIVATE:
// hide when another window is activated
if (LOWORD(wParam) == WA_INACTIVE) {
ShowWindow(hwnd, SW_HIDE);
}
break;
}
return FALSE;
}
BOOL CALLBACK
CMSWindowsServerTaskBarReceiver::staticDlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM lParam)
{
// if msg is WM_INITDIALOG, extract the CMSWindowsServerTaskBarReceiver*
// and put it in the extra window data then forward the call.
CMSWindowsServerTaskBarReceiver* self = NULL;
if (msg == WM_INITDIALOG) {
self = reinterpret_cast<CMSWindowsServerTaskBarReceiver*>(
reinterpret_cast<void*>(lParam));
SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
}
else {
// get the extra window data and forward the call
LONG data = GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (data != 0) {
self = reinterpret_cast<CMSWindowsServerTaskBarReceiver*>(
reinterpret_cast<void*>(data));
}
}
// forward the message
if (self != NULL) {
return self->dlgProc(hwnd, msg, wParam, lParam);
}
else {
return (msg == WM_INITDIALOG) ? TRUE : FALSE;
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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 CMSWINDOWSSERVERTASKBARRECEIVER_H
#define CMSWINDOWSSERVERTASKBARRECEIVER_H
#define WIN32_LEAN_AND_MEAN
#include "CServerTaskBarReceiver.h"
#include <windows.h>
class CBufferedLogOutputter;
//! Implementation of CServerTaskBarReceiver for Microsoft Windows
class CMSWindowsServerTaskBarReceiver : public CServerTaskBarReceiver {
public:
CMSWindowsServerTaskBarReceiver(HINSTANCE, const CBufferedLogOutputter*);
virtual ~CMSWindowsServerTaskBarReceiver();
// IArchTaskBarReceiver overrides
virtual void showStatus();
virtual void runMenu(int x, int y);
virtual void primaryAction();
virtual const Icon getIcon() const;
protected:
void copyLog() const;
// CServerTaskBarReceiver overrides
virtual void onStatusChanged();
private:
HICON loadIcon(UINT);
void deleteIcon(HICON);
void createWindow();
void destroyWindow();
BOOL dlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM lParam);
static BOOL CALLBACK
staticDlgProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM lParam);
private:
HINSTANCE m_appInstance;
HWND m_window;
HMENU m_menu;
HICON m_icon[kMaxState];
const CBufferedLogOutputter* m_logBuffer;
static const UINT s_stateToIconID[];
};
#endif

View File

@@ -0,0 +1,56 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2004 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 "COSXServerTaskBarReceiver.h"
#include "CArch.h"
//
// COSXServerTaskBarReceiver
//
COSXServerTaskBarReceiver::COSXServerTaskBarReceiver(
const CBufferedLogOutputter*)
{
// add ourself to the task bar
ARCH->addReceiver(this);
}
COSXServerTaskBarReceiver::~COSXServerTaskBarReceiver()
{
ARCH->removeReceiver(this);
}
void
COSXServerTaskBarReceiver::showStatus()
{
// do nothing
}
void
COSXServerTaskBarReceiver::runMenu(int, int)
{
// do nothing
}
void
COSXServerTaskBarReceiver::primaryAction()
{
// do nothing
}
const IArchTaskBarReceiver::Icon
COSXServerTaskBarReceiver::getIcon() const
{
return NULL;
}

View File

@@ -0,0 +1,35 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2004 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 COSXSERVERTASKBARRECEIVER_H
#define COSXSERVERTASKBARRECEIVER_H
#include "CServerTaskBarReceiver.h"
class CBufferedLogOutputter;
//! Implementation of CServerTaskBarReceiver for OS X
class COSXServerTaskBarReceiver : public CServerTaskBarReceiver {
public:
COSXServerTaskBarReceiver(const CBufferedLogOutputter*);
virtual ~COSXServerTaskBarReceiver();
// IArchTaskBarReceiver overrides
virtual void showStatus();
virtual void runMenu(int x, int y);
virtual void primaryAction();
virtual const Icon getIcon() const;
};
#endif

View File

@@ -0,0 +1,133 @@
/*
* 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 "CServerTaskBarReceiver.h"
#include "CServer.h"
#include "CLock.h"
#include "CStringUtil.h"
#include "IEventQueue.h"
#include "CArch.h"
#include "Version.h"
//
// CServerTaskBarReceiver
//
CServerTaskBarReceiver::CServerTaskBarReceiver() :
m_state(kNotRunning)
{
// do nothing
}
CServerTaskBarReceiver::~CServerTaskBarReceiver()
{
// do nothing
}
void
CServerTaskBarReceiver::updateStatus(CServer* server, const CString& errorMsg)
{
{
// update our status
m_errorMessage = errorMsg;
if (server == NULL) {
if (m_errorMessage.empty()) {
m_state = kNotRunning;
}
else {
m_state = kNotWorking;
}
}
else {
m_clients.clear();
server->getClients(m_clients);
if (m_clients.size() <= 1) {
m_state = kNotConnected;
}
else {
m_state = kConnected;
}
}
// let subclasses have a go
onStatusChanged(server);
}
// tell task bar
ARCH->updateReceiver(this);
}
CServerTaskBarReceiver::EState
CServerTaskBarReceiver::getStatus() const
{
return m_state;
}
const CString&
CServerTaskBarReceiver::getErrorMessage() const
{
return m_errorMessage;
}
const CServerTaskBarReceiver::CClients&
CServerTaskBarReceiver::getClients() const
{
return m_clients;
}
void
CServerTaskBarReceiver::quit()
{
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
void
CServerTaskBarReceiver::onStatusChanged(CServer*)
{
// do nothing
}
void
CServerTaskBarReceiver::lock() const
{
// do nothing
}
void
CServerTaskBarReceiver::unlock() const
{
// do nothing
}
std::string
CServerTaskBarReceiver::getToolTip() const
{
switch (m_state) {
case kNotRunning:
return CStringUtil::print("%s: Not running", kAppVersion);
case kNotWorking:
return CStringUtil::print("%s: %s",
kAppVersion, m_errorMessage.c_str());
case kNotConnected:
return CStringUtil::print("%s: Waiting for clients", kAppVersion);
case kConnected:
return CStringUtil::print("%s: Connected", kAppVersion);
default:
return "";
}
}

View File

@@ -0,0 +1,88 @@
/*
* 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 CSERVERTASKBARRECEIVER_H
#define CSERVERTASKBARRECEIVER_H
#include "CString.h"
#include "IArchTaskBarReceiver.h"
#include "stdvector.h"
class CServer;
//! Implementation of IArchTaskBarReceiver for the synergy server
class CServerTaskBarReceiver : public IArchTaskBarReceiver {
public:
CServerTaskBarReceiver();
virtual ~CServerTaskBarReceiver();
//! @name manipulators
//@{
//! Update status
/*!
Determine the status and query required information from the server.
*/
void updateStatus(CServer*, const CString& errorMsg);
//@}
// IArchTaskBarReceiver overrides
virtual void showStatus() = 0;
virtual void runMenu(int x, int y) = 0;
virtual void primaryAction() = 0;
virtual void lock() const;
virtual void unlock() const;
virtual const Icon getIcon() const = 0;
virtual std::string getToolTip() const;
protected:
typedef std::vector<CString> CClients;
enum EState {
kNotRunning,
kNotWorking,
kNotConnected,
kConnected,
kMaxState
};
//! Get status
EState getStatus() const;
//! Get error message
const CString& getErrorMessage() const;
//! Get connected clients
const CClients& getClients() const;
//! Quit app
/*!
Causes the application to quit gracefully
*/
void quit();
//! Status change notification
/*!
Called when status changes. The default implementation does
nothing.
*/
virtual void onStatusChanged(CServer* server);
private:
EState m_state;
CString m_errorMessage;
CClients m_clients;
};
#endif

View File

@@ -0,0 +1,56 @@
/*
* 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 "CXWindowsServerTaskBarReceiver.h"
#include "CArch.h"
//
// CXWindowsServerTaskBarReceiver
//
CXWindowsServerTaskBarReceiver::CXWindowsServerTaskBarReceiver(
const CBufferedLogOutputter*)
{
// add ourself to the task bar
ARCH->addReceiver(this);
}
CXWindowsServerTaskBarReceiver::~CXWindowsServerTaskBarReceiver()
{
ARCH->removeReceiver(this);
}
void
CXWindowsServerTaskBarReceiver::showStatus()
{
// do nothing
}
void
CXWindowsServerTaskBarReceiver::runMenu(int, int)
{
// do nothing
}
void
CXWindowsServerTaskBarReceiver::primaryAction()
{
// do nothing
}
const IArchTaskBarReceiver::Icon
CXWindowsServerTaskBarReceiver::getIcon() const
{
return NULL;
}

View File

@@ -0,0 +1,35 @@
/*
* 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 CXWINDOWSSERVERTASKBARRECEIVER_H
#define CXWINDOWSSERVERTASKBARRECEIVER_H
#include "CServerTaskBarReceiver.h"
class CBufferedLogOutputter;
//! Implementation of CServerTaskBarReceiver for X Windows
class CXWindowsServerTaskBarReceiver : public CServerTaskBarReceiver {
public:
CXWindowsServerTaskBarReceiver(const CBufferedLogOutputter*);
virtual ~CXWindowsServerTaskBarReceiver();
// IArchTaskBarReceiver overrides
virtual void showStatus();
virtual void runMenu(int x, int y);
virtual void primaryAction();
virtual const Icon getIcon() const;
};
#endif

98
cmd/synergys/Makefile.am Normal file
View File

@@ -0,0 +1,98 @@
# 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.
## Process this file with automake to produce Makefile.in
NULL =
COMMON_SOURCE_FILES = \
CServerTaskBarReceiver.cpp \
CServerTaskBarReceiver.h \
synergys.cpp \
$(NULL)
XWINDOWS_SOURCE_FILES = \
CXWindowsServerTaskBarReceiver.cpp \
CXWindowsServerTaskBarReceiver.h \
$(NULL)
MSWINDOWS_SOURCE_FILES = \
CMSWindowsServerTaskBarReceiver.cpp \
CMSWindowsServerTaskBarReceiver.h \
resource.h \
synergys.rc \
$(NULL)
CARBON_SOURCE_FILES = \
COSXServerTaskBarReceiver.cpp \
COSXServerTaskBarReceiver.h \
$(NULL)
EXTRA_DIST = \
Makefile.win \
synergys.ico \
tb_error.ico \
tb_idle.ico \
tb_run.ico \
tb_wait.ico \
$(XWINDOWS_SOURCE_FILES) \
$(MSWINDOWS_SOURCE_FILES) \
$(CARBON_SOURCE_FILES) \
$(NULL)
MAINTAINERCLEANFILES = \
Makefile.in \
$(NULL)
bin_PROGRAMS = synergys
if XWINDOWS
synergys_SOURCES = \
$(COMMON_SOURCE_FILES) \
$(XWINDOWS_SOURCE_FILES) \
$(NULL)
endif
if MSWINDOWS
synergys_SOURCES = \
$(COMMON_SOURCE_FILES) \
$(MSWINDOWS_SOURCE_FILES) \
$(NULL)
endif
if CARBON
synergys_SOURCES = \
$(COMMON_SOURCE_FILES) \
$(CARBON_SOURCE_FILES) \
$(NULL)
synergys_LDFLAGS = \
-framework ScreenSaver \
-framework IOKit \
-framework ApplicationServices \
-framework Foundation \
$(NULL)
endif
synergys_LDADD = \
$(top_builddir)/lib/server/libserver.a \
$(top_builddir)/lib/platform/libplatform.a \
$(top_builddir)/lib/synergy/libsynergy.a \
$(top_builddir)/lib/net/libnet.a \
$(top_builddir)/lib/io/libio.a \
$(top_builddir)/lib/mt/libmt.a \
$(top_builddir)/lib/base/libbase.a \
$(top_builddir)/lib/common/libcommon.a \
$(top_builddir)/lib/arch/libarch.a \
$(NULL)
INCLUDES = \
-I$(top_srcdir)/lib/common \
-I$(top_srcdir)/lib/arch \
-I$(top_srcdir)/lib/base \
-I$(top_srcdir)/lib/mt \
-I$(top_srcdir)/lib/io \
-I$(top_srcdir)/lib/net \
-I$(top_srcdir)/lib/synergy \
-I$(top_srcdir)/lib/platform \
-I$(top_srcdir)/lib/server \
$(NULL)

89
cmd/synergys/Makefile.win Normal file
View File

@@ -0,0 +1,89 @@
# synergy -- mouse and keyboard sharing utility
# Copyright (C) 2007 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.
BIN_SYNERGYS_SRC = cmd\synergys
BIN_SYNERGYS_DST = $(BUILD_DST)\$(BIN_SYNERGYS_SRC)
BIN_SYNERGYS_EXE = "$(BUILD_DST)\synergys.exe"
BIN_SYNERGYS_CPP = \
"CServerTaskBarReceiver.cpp" \
"CMSWindowsServerTaskBarReceiver.cpp" \
"synergys.cpp" \
$(NULL)
BIN_SYNERGYS_OBJ = \
"$(BIN_SYNERGYS_DST)\CServerTaskBarReceiver.obj" \
"$(BIN_SYNERGYS_DST)\CMSWindowsServerTaskBarReceiver.obj" \
"$(BIN_SYNERGYS_DST)\synergys.obj" \
$(NULL)
BIN_SYNERGYS_RC = "$(BIN_SYNERGYS_SRC)\synergys.rc"
BIN_SYNERGYS_RES = "$(BIN_SYNERGYS_DST)\synergys.res"
BIN_SYNERGYS_INC = \
/I"lib\common" \
/I"lib\arch" \
/I"lib\base" \
/I"lib\mt" \
/I"lib\io" \
/I"lib\net" \
/I"lib\synergy" \
/I"lib\platform" \
/I"lib\server" \
$(NULL)
BIN_SYNERGYS_LIB = \
$(LIB_SERVER_LIB) \
$(LIB_PLATFORM_LIB) \
$(LIB_SYNERGY_LIB) \
$(LIB_NET_LIB) \
$(LIB_IO_LIB) \
$(LIB_MT_LIB) \
$(LIB_BASE_LIB) \
$(LIB_ARCH_LIB) \
$(LIB_COMMON_LIB) \
$(NULL)
CPP_FILES = $(CPP_FILES) $(BIN_SYNERGYS_CPP)
OBJ_FILES = $(OBJ_FILES) $(BIN_SYNERGYS_OBJ)
PROGRAMS = $(PROGRAMS) $(BIN_SYNERGYS_EXE)
# Need shell functions.
guilibs = $(guilibs) shell32.lib
# Dependency rules
$(BIN_SYNERGYS_OBJ): $(AUTODEP)
!if EXIST($(BIN_SYNERGYS_DST)\deps.mak)
!include $(BIN_SYNERGYS_DST)\deps.mak
!endif
# Build rules. Use batch-mode rules if possible.
!if DEFINED(_NMAKE_VER)
{$(BIN_SYNERGYS_SRC)\}.cpp{$(BIN_SYNERGYS_DST)\}.obj::
!else
{$(BIN_SYNERGYS_SRC)\}.cpp{$(BIN_SYNERGYS_DST)\}.obj:
!endif
@$(ECHO) Compile in $(BIN_SYNERGYS_SRC)
-@$(MKDIR) $(BIN_SYNERGYS_DST) 2>NUL:
$(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \
$(BIN_SYNERGYS_INC) \
/Fo$(BIN_SYNERGYS_DST)\ \
/Fd$(BIN_SYNERGYS_DST)\src.pdb \
$< | $(AUTODEP) $(BIN_SYNERGYS_SRC) $(BIN_SYNERGYS_DST)
$(BIN_SYNERGYS_RES): $(BIN_SYNERGYS_RC)
@$(ECHO) Compile $(**F)
-@$(MKDIR) $(BIN_SYNERGYS_DST) 2>NUL:
$(rc) $(rcflags) $(rcvars) \
/fo$@ \
$**
$(BIN_SYNERGYS_EXE): $(BIN_SYNERGYS_OBJ) $(BIN_SYNERGYS_RES) $(BIN_SYNERGYS_LIB)
@$(ECHO) Link $(@F)
$(link) $(ldebug) $(guilflags) $(guilibsmt) \
/out:$@ \
$**
$(AUTODEP) $(BIN_SYNERGYS_SRC) $(BIN_SYNERGYS_DST) \
$(BIN_SYNERGYS_OBJ:.obj=.d)

40
cmd/synergys/resource.h Normal file
View File

@@ -0,0 +1,40 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by synergys.rc
//
#define IDS_FAILED 1
#define IDS_INIT_FAILED 2
#define IDS_UNCAUGHT_EXCEPTION 3
#define IDI_SYNERGY 101
#define IDI_TASKBAR_NOT_RUNNING 102
#define IDI_TASKBAR_NOT_WORKING 103
#define IDI_TASKBAR_NOT_CONNECTED 104
#define IDI_TASKBAR_CONNECTED 105
#define IDR_TASKBAR 107
#define IDD_TASKBAR_STATUS 108
#define IDC_TASKBAR_STATUS_STATUS 1000
#define IDC_TASKBAR_STATUS_CLIENTS 1001
#define IDC_TASKBAR_QUIT 40003
#define IDC_TASKBAR_STATUS 40004
#define IDC_TASKBAR_LOG 40005
#define IDC_RELOAD_CONFIG 40006
#define IDC_FORCE_RECONNECT 40007
#define IDC_TASKBAR_SHOW_LOG 40008
#define IDC_TASKBAR_LOG_LEVEL_ERROR 40009
#define IDC_TASKBAR_LOG_LEVEL_WARNING 40010
#define IDC_TASKBAR_LOG_LEVEL_NOTE 40011
#define IDC_TASKBAR_LOG_LEVEL_INFO 40012
#define IDC_TASKBAR_LOG_LEVEL_DEBUG 40013
#define IDC_TASKBAR_LOG_LEVEL_DEBUG1 40014
#define IDC_TASKBAR_LOG_LEVEL_DEBUG2 40015
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40016
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

1312
cmd/synergys/synergys.cpp Normal file

File diff suppressed because it is too large Load Diff

BIN
cmd/synergys/synergys.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

146
cmd/synergys/synergys.rc Normal file
View File

@@ -0,0 +1,146 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include <winresrc.h>
#if !defined(IDC_STATIC)
#define IDC_STATIC (-1)
#endif
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include <winresrc.h>\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_SYNERGY ICON DISCARDABLE "synergys.ico"
IDI_TASKBAR_NOT_RUNNING ICON DISCARDABLE "tb_idle.ico"
IDI_TASKBAR_NOT_WORKING ICON DISCARDABLE "tb_error.ico"
IDI_TASKBAR_NOT_CONNECTED ICON DISCARDABLE "tb_wait.ico"
IDI_TASKBAR_CONNECTED ICON DISCARDABLE "tb_run.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_TASKBAR MENU DISCARDABLE
BEGIN
POPUP "Synergy"
BEGIN
MENUITEM "Show Status", IDC_TASKBAR_STATUS
MENUITEM "Show Log", IDC_TASKBAR_SHOW_LOG
MENUITEM "Copy Log To Clipboard", IDC_TASKBAR_LOG
POPUP "Set Log Level"
BEGIN
MENUITEM "Error", IDC_TASKBAR_LOG_LEVEL_ERROR
MENUITEM "Warning", IDC_TASKBAR_LOG_LEVEL_WARNING
MENUITEM "Note", IDC_TASKBAR_LOG_LEVEL_NOTE
MENUITEM "Info", IDC_TASKBAR_LOG_LEVEL_INFO
MENUITEM "Debug", IDC_TASKBAR_LOG_LEVEL_DEBUG
MENUITEM "Debug1", IDC_TASKBAR_LOG_LEVEL_DEBUG1
MENUITEM "Debug2", IDC_TASKBAR_LOG_LEVEL_DEBUG2
END
MENUITEM "Reload Configuration", IDC_RELOAD_CONFIG
MENUITEM "Force Reconnect", IDC_FORCE_RECONNECT
MENUITEM SEPARATOR
MENUITEM "Quit", IDC_TASKBAR_QUIT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_TASKBAR_STATUS DIALOG DISCARDABLE 0, 0, 145, 60
STYLE DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_TASKBAR_STATUS_STATUS,3,3,139,12,ES_AUTOHSCROLL |
ES_READONLY | NOT WS_BORDER
LISTBOX IDC_TASKBAR_STATUS_CLIENTS,3,17,139,40,NOT LBS_NOTIFY |
LBS_SORT | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL |
WS_TABSTOP
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_FAILED "Synergy is about to quit with errors or warnings. Please check the log then click OK."
IDS_INIT_FAILED "Synergy failed to initialize: %{1}"
IDS_UNCAUGHT_EXCEPTION "Uncaught exception: %{1}"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

BIN
cmd/synergys/tb_error.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
cmd/synergys/tb_idle.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
cmd/synergys/tb_run.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
cmd/synergys/tb_wait.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B