Added switch delay and double-tap options to win32 and added a
tray icon to the client and server that gives status feedback to the user and allows the user to kill the app.
183
cmd/launcher/CAdvancedOptions.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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 "CAdvancedOptions.h"
|
||||
#include "LaunchUtil.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)
|
||||
{
|
||||
assert(s_singleton == NULL);
|
||||
s_singleton = this;
|
||||
}
|
||||
|
||||
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, (LPARAM)this);
|
||||
}
|
||||
|
||||
CString
|
||||
CAdvancedOptions::getScreenName() const
|
||||
{
|
||||
return m_screenName;
|
||||
}
|
||||
|
||||
int
|
||||
CAdvancedOptions::getPort() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
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 :";
|
||||
cmdLine += portString;
|
||||
}
|
||||
|
||||
return cmdLine;
|
||||
}
|
||||
|
||||
void
|
||||
CAdvancedOptions::init(HWND hwnd)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
bool
|
||||
CAdvancedOptions::save(HWND hwnd)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL
|
||||
CAdvancedOptions::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
|
||||
CAdvancedOptions::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
|
||||
}
|
||||
74
cmd/launcher/CAdvancedOptions.h
Normal 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 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;
|
||||
|
||||
//! Convert options to command line string
|
||||
CString getCommandLine(bool isClient,
|
||||
const CString& serverName) const;
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
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 CAdvancedOptions* s_singleton;
|
||||
|
||||
HWND m_parent;
|
||||
CConfig* m_config;
|
||||
bool m_isClient;
|
||||
CString m_screenName;
|
||||
int m_port;
|
||||
};
|
||||
|
||||
#endif
|
||||
211
cmd/launcher/CGlobalOptions.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
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, (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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CGlobalOptions::save(HWND hwnd)
|
||||
{
|
||||
HWND child;
|
||||
int newDelayTime = 0;
|
||||
int newTwoTapTime = 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;
|
||||
}
|
||||
}
|
||||
|
||||
// remove existing config options
|
||||
m_config->removeOption("", kOptionScreenSwitchDelay);
|
||||
m_config->removeOption("", kOptionScreenSwitchTwoTap);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// save last values
|
||||
m_delayTime = newDelayTime;
|
||||
m_twoTapTime = newTwoTapTime;
|
||||
|
||||
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);
|
||||
}
|
||||
66
cmd/launcher/CGlobalOptions.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -103,6 +103,18 @@ 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)
|
||||
{
|
||||
|
||||
@@ -42,6 +42,9 @@ 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 loadConfig(CConfig& config);
|
||||
|
||||
@@ -16,8 +16,12 @@ DEPTH = ../..
|
||||
VDEPTH = ./$(VPATH)/$(DEPTH)
|
||||
|
||||
EXTRA_DIST = \
|
||||
CAdvancedOptions.cpp \
|
||||
CAdvancedOptions.h \
|
||||
CAutoStart.cpp \
|
||||
CAutoStart.h \
|
||||
CGlobalOptions.cpp \
|
||||
CGlobalOptions.h \
|
||||
LaunchUtil.cpp \
|
||||
LaunchUtil.h \
|
||||
launcher.cpp \
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
*/
|
||||
|
||||
#include "CConfig.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "OptionTypes.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "CLog.h"
|
||||
#include "CStringUtil.h"
|
||||
@@ -24,6 +26,8 @@
|
||||
// these must come after the above because it includes windows.h
|
||||
#include "LaunchUtil.h"
|
||||
#include "CAutoStart.h"
|
||||
#include "CGlobalOptions.h"
|
||||
#include "CAdvancedOptions.h"
|
||||
|
||||
#define CONFIG_NAME "synergy.sgc"
|
||||
#define CLIENT_APP "synergyc.exe"
|
||||
@@ -47,10 +51,28 @@ public:
|
||||
HANDLE m_stop;
|
||||
};
|
||||
|
||||
HINSTANCE s_instance = NULL;
|
||||
struct CModifierInfo {
|
||||
public:
|
||||
int m_ctrlID;
|
||||
const char* m_name;
|
||||
KeyModifierID m_modifierID;
|
||||
OptionID m_optionID;
|
||||
};
|
||||
|
||||
static const TCHAR* s_mainClass = TEXT("GoSynergy");
|
||||
static const TCHAR* s_layoutClass = TEXT("SynergyLayout");
|
||||
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;
|
||||
|
||||
static const char* s_debugName[][2] = {
|
||||
{ TEXT("Error"), "ERROR" },
|
||||
@@ -63,6 +85,14 @@ static const char* s_debugName[][2] = {
|
||||
};
|
||||
static const int s_defaultDebug = 3; // INFO
|
||||
|
||||
HINSTANCE s_instance = NULL;
|
||||
|
||||
static CGlobalOptions* s_globalOptions = NULL;
|
||||
static CAdvancedOptions* s_advancedOptions = NULL;
|
||||
|
||||
static const TCHAR* s_mainClass = TEXT("GoSynergy");
|
||||
static const TCHAR* s_layoutClass = TEXT("SynergyLayout");
|
||||
|
||||
//
|
||||
// program arguments
|
||||
//
|
||||
@@ -127,7 +157,7 @@ bool
|
||||
isClientChecked(HWND hwnd)
|
||||
{
|
||||
HWND child = getItem(hwnd, IDC_MAIN_CLIENT_RADIO);
|
||||
return (SendMessage(child, BM_GETCHECK, 0, 0) == BST_CHECKED);
|
||||
return isItemChecked(child);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -476,58 +506,20 @@ static
|
||||
CString
|
||||
getCommandLine(HWND hwnd, bool testing)
|
||||
{
|
||||
// decide if client or server
|
||||
const bool isClient = isClientChecked(hwnd);
|
||||
|
||||
// get and verify screen name
|
||||
HWND child = getItem(hwnd, IDC_MAIN_ADVANCED_NAME_EDIT);
|
||||
CString name = getWindowText(child);
|
||||
if (!ARG->m_config.isValidScreenName(name)) {
|
||||
showError(hwnd, CStringUtil::format(
|
||||
getString(IDS_INVALID_SCREEN_NAME).c_str(),
|
||||
name.c_str()));
|
||||
SetFocus(child);
|
||||
return CString();
|
||||
}
|
||||
if (!isClient && !ARG->m_config.isScreen(name)) {
|
||||
showError(hwnd, CStringUtil::format(
|
||||
getString(IDS_UNKNOWN_SCREEN_NAME).c_str(),
|
||||
name.c_str()));
|
||||
SetFocus(child);
|
||||
return CString();
|
||||
}
|
||||
|
||||
// get and verify port
|
||||
child = getItem(hwnd, IDC_MAIN_ADVANCED_PORT_EDIT);
|
||||
CString portString = getWindowText(child);
|
||||
UInt32 port = (UInt32)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 CString();
|
||||
}
|
||||
|
||||
// prepare command line
|
||||
CString cmdLine;
|
||||
if (testing) {
|
||||
// constant testing args
|
||||
cmdLine += " -z --no-restart --no-daemon";
|
||||
|
||||
// debug level testing arg
|
||||
child = getItem(hwnd, IDC_MAIN_DEBUG);
|
||||
cmdLine += " --debug ";
|
||||
cmdLine += s_debugName[SendMessage(child, CB_GETCURSEL, 0, 0)][1];
|
||||
// add constant testing args
|
||||
if (testing) {
|
||||
cmdLine += " -z --no-restart --no-daemon";
|
||||
}
|
||||
cmdLine += " --name ";
|
||||
cmdLine += name;
|
||||
|
||||
// get the server name
|
||||
CString server;
|
||||
bool isClient = isClientChecked(hwnd);
|
||||
if (isClient) {
|
||||
// check server name
|
||||
child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT);
|
||||
CString server = getWindowText(child);
|
||||
HWND child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT);
|
||||
server = getWindowText(child);
|
||||
if (!ARG->m_config.isValidScreenName(server)) {
|
||||
showError(hwnd, CStringUtil::format(
|
||||
getString(IDS_INVALID_SERVER_NAME).c_str(),
|
||||
@@ -551,16 +543,19 @@ getCommandLine(HWND hwnd, bool testing)
|
||||
if (testing) {
|
||||
cmdLine += " --no-camp";
|
||||
}
|
||||
cmdLine += " ";
|
||||
cmdLine += server;
|
||||
cmdLine += ":";
|
||||
cmdLine += portString;
|
||||
}
|
||||
else {
|
||||
cmdLine += " --address :";
|
||||
cmdLine += portString;
|
||||
|
||||
// debug level
|
||||
if (testing) {
|
||||
HWND child = getItem(hwnd, IDC_MAIN_DEBUG);
|
||||
DWORD debug = SendMessage(child, CB_GETCURSEL, 0, 0);
|
||||
cmdLine += " --debug ";
|
||||
cmdLine += s_debugName[debug][1];
|
||||
}
|
||||
|
||||
// add advanced options
|
||||
cmdLine += s_advancedOptions->getCommandLine(isClient, server);
|
||||
|
||||
return cmdLine;
|
||||
}
|
||||
|
||||
@@ -711,11 +706,9 @@ initMainWindow(HWND hwnd)
|
||||
// choose client/server radio buttons
|
||||
HWND child;
|
||||
child = getItem(hwnd, IDC_MAIN_CLIENT_RADIO);
|
||||
SendMessage(child, BM_SETCHECK, !configLoaded ?
|
||||
BST_CHECKED : BST_UNCHECKED, 0);
|
||||
setItemChecked(child, !configLoaded);
|
||||
child = getItem(hwnd, IDC_MAIN_SERVER_RADIO);
|
||||
SendMessage(child, BM_SETCHECK, configLoaded ?
|
||||
BST_CHECKED : BST_UNCHECKED, 0);
|
||||
setItemChecked(child, configLoaded);
|
||||
|
||||
// if config is loaded then initialize server controls
|
||||
if (configLoaded) {
|
||||
@@ -729,16 +722,7 @@ initMainWindow(HWND hwnd)
|
||||
}
|
||||
}
|
||||
|
||||
// initialize other controls
|
||||
char buffer[256];
|
||||
sprintf(buffer, "%d", kDefaultPort);
|
||||
child = getItem(hwnd, IDC_MAIN_ADVANCED_PORT_EDIT);
|
||||
SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer);
|
||||
|
||||
CString hostname = ARCH->getHostName();
|
||||
child = getItem(hwnd, IDC_MAIN_ADVANCED_NAME_EDIT);
|
||||
SendMessage(child, WM_SETTEXT, 0, (LPARAM)hostname.c_str());
|
||||
|
||||
// debug level
|
||||
child = getItem(hwnd, IDC_MAIN_DEBUG);
|
||||
for (unsigned int i = 0; i < sizeof(s_debugName) /
|
||||
sizeof(s_debugName[0]); ++i) {
|
||||
@@ -794,19 +778,32 @@ addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
CConfig::CScreenOptions::const_iterator index;
|
||||
child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
|
||||
index = info->m_options.find(kOptionHalfDuplexCapsLock);
|
||||
if (index != info->m_options.end() && index->second != 0) {
|
||||
SendMessage(child, BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
else {
|
||||
SendMessage(child, BM_SETCHECK, BST_UNCHECKED, 0);
|
||||
}
|
||||
setItemChecked(child, (index != info->m_options.end() &&
|
||||
index->second != 0));
|
||||
child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
|
||||
index = info->m_options.find(kOptionHalfDuplexNumLock);
|
||||
if (index != info->m_options.end() && index->second != 0) {
|
||||
SendMessage(child, BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
else {
|
||||
SendMessage(child, BM_SETCHECK, BST_UNCHECKED, 0);
|
||||
setItemChecked(child, (index != info->m_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 = info->m_options.find(s_modifiers[i].m_optionID);
|
||||
KeyModifierID id = s_modifiers[i].m_modifierID;
|
||||
if (index != info->m_options.end()) {
|
||||
id = index->second;
|
||||
}
|
||||
SendMessage(child, CB_SETCURSEL, id - baseModifier, 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -883,20 +880,36 @@ addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
// save options
|
||||
child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
|
||||
if (SendMessage(child, BM_GETCHECK, 0, 0) == BST_CHECKED) {
|
||||
if (isItemChecked(child)) {
|
||||
info->m_options[kOptionHalfDuplexCapsLock] = 1;
|
||||
}
|
||||
else {
|
||||
info->m_options.erase(kOptionHalfDuplexCapsLock);
|
||||
}
|
||||
child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
|
||||
if (SendMessage(child, BM_GETCHECK, 0, 0) == BST_CHECKED) {
|
||||
if (isItemChecked(child)) {
|
||||
info->m_options[kOptionHalfDuplexNumLock] = 1;
|
||||
}
|
||||
else {
|
||||
info->m_options.erase(kOptionHalfDuplexNumLock);
|
||||
}
|
||||
|
||||
// save modifier options
|
||||
child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
|
||||
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) {
|
||||
info->m_options[s_modifiers[i].m_optionID] = id;
|
||||
}
|
||||
else {
|
||||
info->m_options.erase(s_modifiers[i].m_optionID);
|
||||
}
|
||||
}
|
||||
|
||||
// success
|
||||
EndDialog(hwnd, 1);
|
||||
info = NULL;
|
||||
@@ -1065,6 +1078,16 @@ mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_MAIN_OPTIONS:
|
||||
s_globalOptions->doModal();
|
||||
enableSaveControls(hwnd);
|
||||
break;
|
||||
|
||||
case IDC_MAIN_ADVANCED:
|
||||
s_advancedOptions->doModal(isClientChecked(hwnd));
|
||||
enableSaveControls(hwnd);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -1076,7 +1099,7 @@ mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
int WINAPI
|
||||
WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int nCmdShow)
|
||||
{
|
||||
CArch arch;
|
||||
CArch arch(instance);
|
||||
CLOG;
|
||||
CArgs args;
|
||||
|
||||
@@ -1108,8 +1131,10 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int nCmdShow)
|
||||
HWND m_mainWindow = CreateDialog(s_instance,
|
||||
MAKEINTRESOURCE(IDD_MAIN), 0, NULL);
|
||||
|
||||
// prep window
|
||||
// prep windows
|
||||
initMainWindow(m_mainWindow);
|
||||
s_globalOptions = new CGlobalOptions(m_mainWindow, &ARG->m_config);
|
||||
s_advancedOptions = new CAdvancedOptions(m_mainWindow, &ARG->m_config);
|
||||
|
||||
// show window
|
||||
ShowWindow(m_mainWindow, nCmdShow);
|
||||
|
||||
@@ -95,10 +95,18 @@ LINK32=link.exe
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CAdvancedOptions.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CAutoStart.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CGlobalOptions.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\launcher.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -115,10 +123,18 @@ SOURCE=.\LaunchUtil.cpp
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CAdvancedOptions.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CAutoStart.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CGlobalOptions.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LaunchUtil.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -40,11 +40,14 @@
|
||||
#define IDS_SERVER_IS_CLIENT 36
|
||||
#define IDS_ADD_SCREEN 37
|
||||
#define IDS_EDIT_SCREEN 38
|
||||
#define IDS_INVALID_TIME 39
|
||||
#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 IDC_MAIN_CLIENT_RADIO 1000
|
||||
#define IDC_MAIN_SERVER_RADIO 1001
|
||||
#define IDC_MAIN_CLIENT_SERVER_NAME_EDIT 1002
|
||||
@@ -76,18 +79,31 @@
|
||||
#define IDC_AUTOSTART_INSTALL_USER 1033
|
||||
#define IDC_AUTOSTART_INSTALL_SYSTEM 1034
|
||||
#define IDC_MAIN_AUTOSTART 1035
|
||||
#define IDC_MAIN_DEBUG 1036
|
||||
#define IDC_MAIN_OPTIONS 1036
|
||||
#define IDC_ADD_HD_CAPS_CHECK 1037
|
||||
#define IDC_MAIN_ADVANCED 1037
|
||||
#define IDC_ADD_HD_NUM_CHECK 1038
|
||||
#define IDC_ADVANCED_NAME_EDIT 1038
|
||||
#define IDC_ADVANCED_PORT_EDIT 1039
|
||||
#define IDC_MAIN_DEBUG 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_ADD_MOD_META 1046
|
||||
#define IDC_ADD_MOD_SUPER 1047
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 106
|
||||
#define _APS_NEXT_RESOURCE_VALUE 108
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1038
|
||||
#define _APS_NEXT_CONTROL_VALUE 1044
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
||||
163
cmd/synergyc/CClientTaskBarReceiver.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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 "TMethodJob.h"
|
||||
#include "CArch.h"
|
||||
|
||||
//
|
||||
// CClientTaskBarReceiver
|
||||
//
|
||||
|
||||
CClientTaskBarReceiver::CClientTaskBarReceiver() :
|
||||
m_quit(NULL),
|
||||
m_state(kNotRunning),
|
||||
m_client(NULL)
|
||||
{
|
||||
// create a job for getting notification when the client's
|
||||
// status changes.
|
||||
m_job = new TMethodJob<CClientTaskBarReceiver>(this,
|
||||
&CClientTaskBarReceiver::statusChanged, NULL);
|
||||
}
|
||||
|
||||
CClientTaskBarReceiver::~CClientTaskBarReceiver()
|
||||
{
|
||||
if (m_client != NULL) {
|
||||
m_client->removeStatusJob(m_job);
|
||||
}
|
||||
delete m_job;
|
||||
delete m_quit;
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::setClient(CClient* client)
|
||||
{
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
if (m_client != client) {
|
||||
if (m_client != NULL) {
|
||||
m_client->removeStatusJob(m_job);
|
||||
}
|
||||
m_client = client;
|
||||
if (m_client != NULL) {
|
||||
m_client->addStatusJob(m_job);
|
||||
}
|
||||
}
|
||||
}
|
||||
ARCH->updateReceiver(this);
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::setState(EState state)
|
||||
{
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
m_state = state;
|
||||
}
|
||||
ARCH->updateReceiver(this);
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::setQuitJob(IJob* job)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
delete m_quit;
|
||||
m_quit = job;
|
||||
}
|
||||
|
||||
CClientTaskBarReceiver::EState
|
||||
CClientTaskBarReceiver::getState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
CClient*
|
||||
CClientTaskBarReceiver::getClient() const
|
||||
{
|
||||
return m_client;
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::lock() const
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::unlock() const
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
std::string
|
||||
CClientTaskBarReceiver::getToolTip() const
|
||||
{
|
||||
switch (m_state) {
|
||||
case kNotRunning:
|
||||
return "Synergy: Not running";
|
||||
|
||||
case kNotWorking:
|
||||
return CString("Synergy: ") + m_errorMessage;
|
||||
|
||||
case kNotConnected:
|
||||
return "Synergy: Waiting for clients";
|
||||
|
||||
case kConnected:
|
||||
return "Synergy: Connected";
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::quit()
|
||||
{
|
||||
if (m_quit != NULL) {
|
||||
m_quit->run();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::onStatusChanged()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CClientTaskBarReceiver::statusChanged(void*)
|
||||
{
|
||||
// update our status
|
||||
switch (m_client->getStatus(&m_errorMessage)) {
|
||||
case CClient::kNotRunning:
|
||||
setState(kNotRunning);
|
||||
break;
|
||||
|
||||
case CClient::kRunning:
|
||||
setState(kConnected);
|
||||
break;
|
||||
|
||||
case CClient::kError:
|
||||
setState(kNotWorking);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// let subclasses have a go
|
||||
onStatusChanged();
|
||||
}
|
||||
110
cmd/synergyc/CClientTaskBarReceiver.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 "CMutex.h"
|
||||
#include "CString.h"
|
||||
#include "IArchTaskBarReceiver.h"
|
||||
|
||||
class CClient;
|
||||
class IJob;
|
||||
|
||||
//! Implementation of IArchTaskBarReceiver for the synergy server
|
||||
class CClientTaskBarReceiver : public IArchTaskBarReceiver {
|
||||
public:
|
||||
enum EState {
|
||||
kNotRunning,
|
||||
kNotWorking,
|
||||
kNotConnected,
|
||||
kConnected,
|
||||
kMaxState
|
||||
};
|
||||
|
||||
CClientTaskBarReceiver();
|
||||
virtual ~CClientTaskBarReceiver();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Set server
|
||||
/*!
|
||||
Sets the server. The receiver will query state from this server.
|
||||
*/
|
||||
void setClient(CClient*);
|
||||
|
||||
//! Set state
|
||||
/*!
|
||||
Sets the current server state.
|
||||
*/
|
||||
void setState(EState);
|
||||
|
||||
//! Set the quit job that causes the server to quit
|
||||
/*!
|
||||
Set the job that causes the server to quit.
|
||||
*/
|
||||
void setQuitJob(IJob* adopted);
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get state
|
||||
/*!
|
||||
Returns the current server state. The receiver is not locked
|
||||
by this call; the caller must do the locking.
|
||||
*/
|
||||
EState getState() const;
|
||||
|
||||
//! Get server
|
||||
/*!
|
||||
Returns the server set by \c setClient().
|
||||
*/
|
||||
CClient* getClient() const;
|
||||
|
||||
//@}
|
||||
|
||||
// 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:
|
||||
void quit();
|
||||
|
||||
//! Status change notification
|
||||
/*!
|
||||
Called when status changes. The default implementation does
|
||||
nothing.
|
||||
*/
|
||||
virtual void onStatusChanged();
|
||||
|
||||
private:
|
||||
void statusChanged(void*);
|
||||
|
||||
private:
|
||||
CMutex m_mutex;
|
||||
IJob* m_quit;
|
||||
EState m_state;
|
||||
CClient* m_client;
|
||||
IJob* m_job;
|
||||
CString m_errorMessage;
|
||||
};
|
||||
|
||||
#endif
|
||||
280
cmd/synergyc/CMSWindowsClientTaskBarReceiver.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* 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 "BasicTypes.h"
|
||||
#include "CArch.h"
|
||||
#include "CArchTaskBarWindows.h"
|
||||
#include "resource.h"
|
||||
|
||||
static const UINT g_stateToIconID[CMSWindowsClientTaskBarReceiver::kMaxState] =
|
||||
{
|
||||
IDI_TASKBAR_NOT_RUNNING,
|
||||
IDI_TASKBAR_NOT_WORKING,
|
||||
IDI_TASKBAR_NOT_CONNECTED,
|
||||
IDI_TASKBAR_CONNECTED
|
||||
};
|
||||
|
||||
//
|
||||
// CMSWindowsClientTaskBarReceiver
|
||||
//
|
||||
|
||||
CMSWindowsClientTaskBarReceiver::CMSWindowsClientTaskBarReceiver(
|
||||
HINSTANCE appInstance) :
|
||||
CClientTaskBarReceiver(),
|
||||
m_appInstance(appInstance),
|
||||
m_window(NULL)
|
||||
{
|
||||
for (UInt32 i = 0; i < kMaxState; ++i) {
|
||||
m_icon[i] = loadIcon(g_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);
|
||||
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_QUIT:
|
||||
quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsClientTaskBarReceiver::primaryAction()
|
||||
{
|
||||
showStatus();
|
||||
}
|
||||
|
||||
const IArchTaskBarReceiver::Icon
|
||||
CMSWindowsClientTaskBarReceiver::getIcon() const
|
||||
{
|
||||
return reinterpret_cast<Icon>(m_icon[getState()]);
|
||||
}
|
||||
|
||||
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,
|
||||
&CMSWindowsClientTaskBarReceiver::staticDlgProc,
|
||||
reinterpret_cast<LPARAM>(
|
||||
reinterpret_cast<void*>(this)));
|
||||
|
||||
// window should appear on top of everything, including (especially)
|
||||
// the task bar.
|
||||
DWORD style = GetWindowLong(m_window, GWL_EXSTYLE);
|
||||
style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
|
||||
SetWindowLong(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;
|
||||
}
|
||||
}
|
||||
58
cmd/synergyc/CMSWindowsClientTaskBarReceiver.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
//! Implementation of CClientTaskBarReceiver for Microsoft Windows
|
||||
class CMSWindowsClientTaskBarReceiver : public CClientTaskBarReceiver {
|
||||
public:
|
||||
CMSWindowsClientTaskBarReceiver(HINSTANCE);
|
||||
virtual ~CMSWindowsClientTaskBarReceiver();
|
||||
|
||||
// IArchTaskBarReceiver overrides
|
||||
virtual void showStatus();
|
||||
virtual void runMenu(int x, int y);
|
||||
virtual void primaryAction();
|
||||
virtual const Icon getIcon() const;
|
||||
|
||||
protected:
|
||||
// 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];
|
||||
};
|
||||
|
||||
#endif
|
||||
61
cmd/synergyc/CXWindowsClientTaskBarReceiver.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsClientTaskBarReceiver::onStatusChanged()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
37
cmd/synergyc/CXWindowsClientTaskBarReceiver.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
//! Implementation of CClientTaskBarReceiver for X Windows
|
||||
class CXWindowsClientTaskBarReceiver : public CClientTaskBarReceiver {
|
||||
public:
|
||||
CXWindowsClientTaskBarReceiver();
|
||||
virtual ~CXWindowsClientTaskBarReceiver();
|
||||
|
||||
// IArchTaskBarReceiver overrides
|
||||
virtual void showStatus();
|
||||
virtual void runMenu(int x, int y);
|
||||
virtual void primaryAction();
|
||||
virtual const Icon getIcon() const;
|
||||
|
||||
protected:
|
||||
// CClientTaskBarReceiver overrides
|
||||
virtual void onStatusChanged();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -15,19 +15,29 @@ NULL =
|
||||
DEPTH = ../..
|
||||
VDEPTH = ./$(VPATH)/$(DEPTH)
|
||||
|
||||
EXTRA_DIST = \
|
||||
resource.h \
|
||||
synergyc.dsp \
|
||||
synergyc.ico \
|
||||
synergyc.rc \
|
||||
EXTRA_DIST = \
|
||||
CMSWindowsClientTaskBarReceiver.cpp \
|
||||
CMSWindowsClientTaskBarReceiver.h \
|
||||
resource.h \
|
||||
synergyc.dsp \
|
||||
synergyc.ico \
|
||||
synergyc.rc \
|
||||
tb_error.ico \
|
||||
tb_idle.ico \
|
||||
tb_run.ico \
|
||||
tb_wait.ico \
|
||||
$(NULL)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in \
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in \
|
||||
$(NULL)
|
||||
|
||||
bin_PROGRAMS = synergyc
|
||||
synergyc_SOURCES = \
|
||||
CClientTaskBarReceiver.cpp \
|
||||
CClientTaskBarReceiver.h \
|
||||
CXWindowsClientTaskBarReceiver.cpp \
|
||||
CXWindowsClientTaskBarReceiver.h \
|
||||
synergyc.cpp \
|
||||
$(NULL)
|
||||
synergyc_LDADD = \
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
//
|
||||
#define IDS_FAILED 1
|
||||
#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 40003
|
||||
#define IDC_TASKBAR_STATUS 40004
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "CMutex.h"
|
||||
#include "CThread.h"
|
||||
#include "XThread.h"
|
||||
#include "CFunctionJob.h"
|
||||
#include "CLog.h"
|
||||
#include "LogOutputters.h"
|
||||
#include "CString.h"
|
||||
@@ -34,12 +35,15 @@
|
||||
|
||||
#define DAEMON_RUNNING(running_)
|
||||
#if WINDOWS_LIKE
|
||||
#include "CMSWindowsScreen.h"
|
||||
#include "CMSWindowsSecondaryScreen.h"
|
||||
#include "CMSWindowsClientTaskBarReceiver.h"
|
||||
#include "resource.h"
|
||||
#undef DAEMON_RUNNING
|
||||
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
|
||||
#elif UNIX_LIKE
|
||||
#include "CXWindowsSecondaryScreen.h"
|
||||
#include "CXWindowsClientTaskBarReceiver.h"
|
||||
#endif
|
||||
|
||||
// platform dependent name of a daemon
|
||||
@@ -112,11 +116,46 @@ CSecondaryScreenFactory::create(IScreenReceiver* receiver)
|
||||
}
|
||||
|
||||
|
||||
//! CQuitJob
|
||||
/*!
|
||||
A job that cancels a given thread.
|
||||
*/
|
||||
class CQuitJob : public IJob {
|
||||
public:
|
||||
CQuitJob(const CThread& thread);
|
||||
~CQuitJob();
|
||||
|
||||
// IJob overrides
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
CThread m_thread;
|
||||
};
|
||||
|
||||
CQuitJob::CQuitJob(const CThread& thread) :
|
||||
m_thread(thread)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CQuitJob::~CQuitJob()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CQuitJob::run()
|
||||
{
|
||||
m_thread.cancel();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// platform independent main
|
||||
//
|
||||
|
||||
static CClient* s_client = NULL;
|
||||
static CClient* s_client = NULL;
|
||||
static CClientTaskBarReceiver* s_taskBarReceiver = NULL;
|
||||
|
||||
static
|
||||
int
|
||||
@@ -137,6 +176,7 @@ realMain(void)
|
||||
|
||||
// open client
|
||||
try {
|
||||
s_taskBarReceiver->setClient(s_client);
|
||||
s_client->open();
|
||||
opened = true;
|
||||
|
||||
@@ -160,11 +200,10 @@ realMain(void)
|
||||
DAEMON_RUNNING(false); \
|
||||
locked = true; \
|
||||
} \
|
||||
if (s_client != NULL) { \
|
||||
if (opened) { \
|
||||
s_client->close(); \
|
||||
} \
|
||||
if (opened) { \
|
||||
s_client->close(); \
|
||||
} \
|
||||
s_taskBarReceiver->setClient(NULL); \
|
||||
delete s_client; \
|
||||
s_client = NULL; \
|
||||
} while (false)
|
||||
@@ -205,6 +244,43 @@ realMain(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
realMainEntry(void*)
|
||||
{
|
||||
CThread::exit(reinterpret_cast<void*>(realMain()));
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
runMainInThread(void)
|
||||
{
|
||||
CThread appThread(new CFunctionJob(&realMainEntry));
|
||||
try {
|
||||
#if WINDOWS_LIKE
|
||||
MSG msg;
|
||||
while (appThread.waitForEvent(-1.0) == CThread::kEvent) {
|
||||
// check for a quit event
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
CThread::getCurrentThread().cancel();
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
#else
|
||||
appThread.wait(-1.0);
|
||||
#endif
|
||||
return reinterpret_cast<int>(appThread.getResult());
|
||||
}
|
||||
catch (XThread&) {
|
||||
appThread.cancel();
|
||||
appThread.wait(-1.0);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// command line parsing
|
||||
@@ -273,7 +349,7 @@ help()
|
||||
|
||||
static
|
||||
bool
|
||||
isArg(int argi, int argc, const char** argv,
|
||||
isArg(int argi, int argc, const char* const* argv,
|
||||
const char* name1, const char* name2,
|
||||
int minRequiredParameters = 0)
|
||||
{
|
||||
@@ -294,7 +370,7 @@ isArg(int argi, int argc, const char** argv,
|
||||
|
||||
static
|
||||
void
|
||||
parse(int argc, const char** argv)
|
||||
parse(int argc, const char* const* argv)
|
||||
{
|
||||
assert(ARG->m_pname != NULL);
|
||||
assert(argv != NULL);
|
||||
@@ -424,16 +500,6 @@ parse(int argc, const char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
useSystemLog()
|
||||
{
|
||||
// redirect log messages
|
||||
ILogOutputter* logger = new CSystemLogOutputter;
|
||||
logger->open(DAEMON_NAME);
|
||||
CLOG->insert(new CStopLogOutputter);
|
||||
CLOG->insert(logger);
|
||||
}
|
||||
|
||||
//
|
||||
// platform dependent entry points
|
||||
@@ -441,8 +507,6 @@ useSystemLog()
|
||||
|
||||
#if WINDOWS_LIKE
|
||||
|
||||
#include "CMSWindowsScreen.h"
|
||||
|
||||
static bool s_hasImportantLogMessages = false;
|
||||
|
||||
//
|
||||
@@ -494,7 +558,10 @@ static
|
||||
int
|
||||
daemonStartup(int argc, const char** argv)
|
||||
{
|
||||
useSystemLog();
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
|
||||
// have to cancel this thread to quit
|
||||
s_taskBarReceiver->setQuitJob(new CQuitJob(CThread::getCurrentThread()));
|
||||
|
||||
// catch errors that would normally exit
|
||||
bye = &byeThrow;
|
||||
@@ -513,14 +580,62 @@ static
|
||||
int
|
||||
daemonStartup95(int, const char**)
|
||||
{
|
||||
useSystemLog();
|
||||
return realMain();
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
return runMainInThread();
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
run(int argc, char** argv)
|
||||
{
|
||||
// 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.
|
||||
if (argc <= 1 && !CArchMiscWindows::isWindows95Family()) {
|
||||
try {
|
||||
return ARCH->daemonize(DAEMON_NAME, &daemonStartup);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
}
|
||||
return kExitFailed;
|
||||
}
|
||||
|
||||
// parse command line
|
||||
parse(argc, argv);
|
||||
|
||||
// daemonize if requested
|
||||
if (ARG->m_daemon) {
|
||||
// start as a daemon
|
||||
if (CArchMiscWindows::isWindows95Family()) {
|
||||
try {
|
||||
return ARCH->daemonize(DAEMON_NAME, &daemonStartup95);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
}
|
||||
return kExitFailed;
|
||||
}
|
||||
else {
|
||||
// cannot start a service from the command line so just
|
||||
// run normally (except with log messages redirected).
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
return runMainInThread();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// run
|
||||
return runMainInThread();
|
||||
}
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
CArch arch;
|
||||
CArch arch(instance);
|
||||
CLOG;
|
||||
CArgs args;
|
||||
|
||||
@@ -533,52 +648,27 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
|
||||
// send PRINT and FATAL output to a message box
|
||||
CLOG->insert(new CMessageBoxOutputter);
|
||||
|
||||
// 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.
|
||||
if (__argc <= 1 && !CArchMiscWindows::isWindows95Family()) {
|
||||
int result = kExitFailed;
|
||||
try {
|
||||
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
}
|
||||
delete CLOG;
|
||||
return result;
|
||||
}
|
||||
// make the task bar receiver. the user can control this app
|
||||
// through the task bar.
|
||||
s_taskBarReceiver = new CMSWindowsClientTaskBarReceiver(instance);
|
||||
s_taskBarReceiver->setQuitJob(new CQuitJob(CThread::getCurrentThread()));
|
||||
|
||||
// parse command line
|
||||
parse(__argc, const_cast<const char**>(__argv));
|
||||
|
||||
// daemonize if requested
|
||||
int result;
|
||||
if (ARG->m_daemon) {
|
||||
// start as a daemon
|
||||
if (CArchMiscWindows::isWindows95Family()) {
|
||||
try {
|
||||
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup95);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
result = kExitFailed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// cannot start a service from the command line so just
|
||||
// run normally (except with log messages redirected).
|
||||
useSystemLog();
|
||||
result = realMain();
|
||||
}
|
||||
try {
|
||||
// run in foreground or as a daemon
|
||||
result = run(__argc, __argv);
|
||||
}
|
||||
else {
|
||||
// run
|
||||
result = realMain();
|
||||
catch (...) {
|
||||
// note that we don't rethrow thread cancellation. we'll
|
||||
// be exiting soon so it doesn't matter. what we'd like
|
||||
// is for everything after this try/catch to be in a
|
||||
// finally block.
|
||||
result = kExitFailed;
|
||||
}
|
||||
|
||||
// done with task bar receiver
|
||||
delete s_taskBarReceiver;
|
||||
|
||||
// let user examine any messages if we're running as a backend
|
||||
// by putting up a dialog box before exiting.
|
||||
if (ARG->m_backend && s_hasImportantLogMessages) {
|
||||
@@ -598,7 +688,7 @@ static
|
||||
int
|
||||
daemonStartup(int, const char**)
|
||||
{
|
||||
useSystemLog();
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
return realMain();
|
||||
}
|
||||
|
||||
@@ -612,8 +702,13 @@ main(int argc, char** argv)
|
||||
// get program name
|
||||
ARG->m_pname = ARCH->getBasename(argv[0]);
|
||||
|
||||
// make the task bar receiver. the user can control this app
|
||||
// through the task bar.
|
||||
s_taskBarReceiver = new CXWindowsClientTaskBarReceiver;
|
||||
s_taskBarReceiver->setQuitJob(new CQuitJob(CThread::getCurrentThread()));
|
||||
|
||||
// parse command line
|
||||
parse(argc, const_cast<const char**>(argv));
|
||||
parse(argc, argv);
|
||||
|
||||
// daemonize if requested
|
||||
int result;
|
||||
@@ -630,6 +725,9 @@ main(int argc, char** argv)
|
||||
result = realMain();
|
||||
}
|
||||
|
||||
// done with task bar receiver
|
||||
delete s_taskBarReceiver;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,14 @@ LINK32=link.exe
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CClientTaskBarReceiver.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CMSWindowsClientTaskBarReceiver.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\synergyc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -106,6 +114,14 @@ SOURCE=.\synergyc.rc
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CClientTaskBarReceiver.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CMSWindowsClientTaskBarReceiver.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# End Group
|
||||
@@ -116,6 +132,22 @@ SOURCE=.\resource.h
|
||||
|
||||
SOURCE=.\synergyc.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_error.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_idle.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_run.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_wait.ico
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
|
||||
BIN
cmd/synergyc/tb_error.ico
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
cmd/synergyc/tb_idle.ico
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
cmd/synergyc/tb_run.ico
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
cmd/synergyc/tb_wait.ico
Normal file
|
After Width: | Height: | Size: 318 B |
300
cmd/synergys/CMSWindowsServerTaskBarReceiver.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* 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 "BasicTypes.h"
|
||||
#include "CArch.h"
|
||||
#include "CArchTaskBarWindows.h"
|
||||
#include "resource.h"
|
||||
|
||||
static const UINT g_stateToIconID[CMSWindowsServerTaskBarReceiver::kMaxState] =
|
||||
{
|
||||
IDI_TASKBAR_NOT_RUNNING,
|
||||
IDI_TASKBAR_NOT_WORKING,
|
||||
IDI_TASKBAR_NOT_CONNECTED,
|
||||
IDI_TASKBAR_CONNECTED
|
||||
};
|
||||
|
||||
//
|
||||
// CMSWindowsServerTaskBarReceiver
|
||||
//
|
||||
|
||||
CMSWindowsServerTaskBarReceiver::CMSWindowsServerTaskBarReceiver(
|
||||
HINSTANCE appInstance) :
|
||||
CServerTaskBarReceiver(),
|
||||
m_appInstance(appInstance),
|
||||
m_window(NULL)
|
||||
{
|
||||
for (UInt32 i = 0; i < kMaxState; ++i) {
|
||||
m_icon[i] = loadIcon(g_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
|
||||
typedef std::vector<CString> CClientList;
|
||||
CClientList clients;
|
||||
CServer* server = getServer();
|
||||
if (server != NULL) {
|
||||
server->getClients(clients);
|
||||
}
|
||||
|
||||
// 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 (CClientList::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);
|
||||
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_QUIT:
|
||||
quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsServerTaskBarReceiver::primaryAction()
|
||||
{
|
||||
showStatus();
|
||||
}
|
||||
|
||||
const IArchTaskBarReceiver::Icon
|
||||
CMSWindowsServerTaskBarReceiver::getIcon() const
|
||||
{
|
||||
return reinterpret_cast<Icon>(m_icon[getState()]);
|
||||
}
|
||||
|
||||
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,
|
||||
&CMSWindowsServerTaskBarReceiver::staticDlgProc,
|
||||
reinterpret_cast<LPARAM>(
|
||||
reinterpret_cast<void*>(this)));
|
||||
|
||||
// window should appear on top of everything, including (especially)
|
||||
// the task bar.
|
||||
DWORD style = GetWindowLong(m_window, GWL_EXSTYLE);
|
||||
style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
|
||||
SetWindowLong(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));
|
||||
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<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;
|
||||
}
|
||||
}
|
||||
58
cmd/synergys/CMSWindowsServerTaskBarReceiver.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
//! Implementation of CServerTaskBarReceiver for Microsoft Windows
|
||||
class CMSWindowsServerTaskBarReceiver : public CServerTaskBarReceiver {
|
||||
public:
|
||||
CMSWindowsServerTaskBarReceiver(HINSTANCE);
|
||||
virtual ~CMSWindowsServerTaskBarReceiver();
|
||||
|
||||
// IArchTaskBarReceiver overrides
|
||||
virtual void showStatus();
|
||||
virtual void runMenu(int x, int y);
|
||||
virtual void primaryAction();
|
||||
virtual const Icon getIcon() const;
|
||||
|
||||
protected:
|
||||
// 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];
|
||||
};
|
||||
|
||||
#endif
|
||||
171
cmd/synergys/CServerTaskBarReceiver.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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 "TMethodJob.h"
|
||||
#include "CArch.h"
|
||||
|
||||
//
|
||||
// CServerTaskBarReceiver
|
||||
//
|
||||
|
||||
CServerTaskBarReceiver::CServerTaskBarReceiver() :
|
||||
m_quit(NULL),
|
||||
m_state(kNotRunning),
|
||||
m_server(NULL)
|
||||
{
|
||||
// create a job for getting notification when the server's
|
||||
// status changes.
|
||||
m_job = new TMethodJob<CServerTaskBarReceiver>(this,
|
||||
&CServerTaskBarReceiver::statusChanged, NULL);
|
||||
}
|
||||
|
||||
CServerTaskBarReceiver::~CServerTaskBarReceiver()
|
||||
{
|
||||
if (m_server != NULL) {
|
||||
m_server->removeStatusJob(m_job);
|
||||
}
|
||||
delete m_job;
|
||||
delete m_quit;
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::setServer(CServer* server)
|
||||
{
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
if (m_server != server) {
|
||||
if (m_server != NULL) {
|
||||
m_server->removeStatusJob(m_job);
|
||||
}
|
||||
m_server = server;
|
||||
if (m_server != NULL) {
|
||||
m_server->addStatusJob(m_job);
|
||||
}
|
||||
}
|
||||
}
|
||||
ARCH->updateReceiver(this);
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::setState(EState state)
|
||||
{
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
m_state = state;
|
||||
}
|
||||
ARCH->updateReceiver(this);
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::setQuitJob(IJob* job)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
delete m_quit;
|
||||
m_quit = job;
|
||||
}
|
||||
|
||||
CServerTaskBarReceiver::EState
|
||||
CServerTaskBarReceiver::getState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
CServer*
|
||||
CServerTaskBarReceiver::getServer() const
|
||||
{
|
||||
return m_server;
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::lock() const
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::unlock() const
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
std::string
|
||||
CServerTaskBarReceiver::getToolTip() const
|
||||
{
|
||||
switch (m_state) {
|
||||
case kNotRunning:
|
||||
return "Synergy: Not running";
|
||||
|
||||
case kNotWorking:
|
||||
return CString("Synergy: ") + m_errorMessage;
|
||||
|
||||
case kNotConnected:
|
||||
return "Synergy: Waiting for clients";
|
||||
|
||||
case kConnected:
|
||||
return "Synergy: Connected";
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::quit()
|
||||
{
|
||||
if (m_quit != NULL) {
|
||||
m_quit->run();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::onStatusChanged()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CServerTaskBarReceiver::statusChanged(void*)
|
||||
{
|
||||
// update our status
|
||||
switch (m_server->getStatus(&m_errorMessage)) {
|
||||
case CServer::kNotRunning:
|
||||
setState(kNotRunning);
|
||||
break;
|
||||
|
||||
case CServer::kRunning:
|
||||
if (m_server->getNumClients() > 1)
|
||||
setState(kConnected);
|
||||
else
|
||||
setState(kNotConnected);
|
||||
break;
|
||||
|
||||
case CServer::kServerNameUnknown:
|
||||
m_errorMessage = "Server name is not in configuration";
|
||||
setState(kNotWorking);
|
||||
break;
|
||||
|
||||
case CServer::kError:
|
||||
setState(kNotWorking);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// let subclasses have a go
|
||||
onStatusChanged();
|
||||
}
|
||||
110
cmd/synergys/CServerTaskBarReceiver.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 "CMutex.h"
|
||||
#include "CString.h"
|
||||
#include "IArchTaskBarReceiver.h"
|
||||
|
||||
class CServer;
|
||||
class IJob;
|
||||
|
||||
//! Implementation of IArchTaskBarReceiver for the synergy server
|
||||
class CServerTaskBarReceiver : public IArchTaskBarReceiver {
|
||||
public:
|
||||
enum EState {
|
||||
kNotRunning,
|
||||
kNotWorking,
|
||||
kNotConnected,
|
||||
kConnected,
|
||||
kMaxState
|
||||
};
|
||||
|
||||
CServerTaskBarReceiver();
|
||||
virtual ~CServerTaskBarReceiver();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Set server
|
||||
/*!
|
||||
Sets the server. The receiver will query state from this server.
|
||||
*/
|
||||
void setServer(CServer*);
|
||||
|
||||
//! Set state
|
||||
/*!
|
||||
Sets the current server state.
|
||||
*/
|
||||
void setState(EState);
|
||||
|
||||
//! Set the quit job that causes the server to quit
|
||||
/*!
|
||||
Set the job that causes the server to quit.
|
||||
*/
|
||||
void setQuitJob(IJob* adopted);
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get state
|
||||
/*!
|
||||
Returns the current server state. The receiver is not locked
|
||||
by this call; the caller must do the locking.
|
||||
*/
|
||||
EState getState() const;
|
||||
|
||||
//! Get server
|
||||
/*!
|
||||
Returns the server set by \c setServer().
|
||||
*/
|
||||
CServer* getServer() const;
|
||||
|
||||
//@}
|
||||
|
||||
// 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:
|
||||
void quit();
|
||||
|
||||
//! Status change notification
|
||||
/*!
|
||||
Called when status changes. The default implementation does
|
||||
nothing.
|
||||
*/
|
||||
virtual void onStatusChanged();
|
||||
|
||||
private:
|
||||
void statusChanged(void*);
|
||||
|
||||
private:
|
||||
CMutex m_mutex;
|
||||
IJob* m_quit;
|
||||
EState m_state;
|
||||
CServer* m_server;
|
||||
IJob* m_job;
|
||||
CString m_errorMessage;
|
||||
};
|
||||
|
||||
#endif
|
||||
61
cmd/synergys/CXWindowsServerTaskBarReceiver.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsServerTaskBarReceiver::onStatusChanged()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
37
cmd/synergys/CXWindowsServerTaskBarReceiver.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
//! Implementation of CServerTaskBarReceiver for X Windows
|
||||
class CXWindowsServerTaskBarReceiver : public CServerTaskBarReceiver {
|
||||
public:
|
||||
CXWindowsServerTaskBarReceiver();
|
||||
virtual ~CXWindowsServerTaskBarReceiver();
|
||||
|
||||
// IArchTaskBarReceiver overrides
|
||||
virtual void showStatus();
|
||||
virtual void runMenu(int x, int y);
|
||||
virtual void primaryAction();
|
||||
virtual const Icon getIcon() const;
|
||||
|
||||
protected:
|
||||
// CServerTaskBarReceiver overrides
|
||||
virtual void onStatusChanged();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -15,19 +15,29 @@ NULL =
|
||||
DEPTH = ../..
|
||||
VDEPTH = ./$(VPATH)/$(DEPTH)
|
||||
|
||||
EXTRA_DIST = \
|
||||
resource.h \
|
||||
synergys.ico \
|
||||
synergys.dsp \
|
||||
synergys.rc \
|
||||
EXTRA_DIST = \
|
||||
CMSWindowsServerTaskBarReceiver.cpp \
|
||||
CMSWindowsServerTaskBarReceiver.h \
|
||||
resource.h \
|
||||
synergys.ico \
|
||||
synergys.dsp \
|
||||
synergys.rc \
|
||||
tb_error.ico \
|
||||
tb_idle.ico \
|
||||
tb_run.ico \
|
||||
tb_wait.ico \
|
||||
$(NULL)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in \
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in \
|
||||
$(NULL)
|
||||
|
||||
bin_PROGRAMS = synergys
|
||||
synergys_SOURCES = \
|
||||
CServerTaskBarReceiver.cpp \
|
||||
CServerTaskBarReceiver.h \
|
||||
CXWindowsServerTaskBarReceiver.cpp \
|
||||
CXWindowsServerTaskBarReceiver.h \
|
||||
synergys.cpp \
|
||||
$(NULL)
|
||||
synergys_LDADD = \
|
||||
|
||||
@@ -4,14 +4,24 @@
|
||||
//
|
||||
#define IDS_FAILED 1
|
||||
#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
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_RESOURCE_VALUE 109
|
||||
#define _APS_NEXT_COMMAND_VALUE 40005
|
||||
#define _APS_NEXT_CONTROL_VALUE 1003
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "CMutex.h"
|
||||
#include "CThread.h"
|
||||
#include "XThread.h"
|
||||
#include "CFunctionJob.h"
|
||||
#include "CLog.h"
|
||||
#include "LogOutputters.h"
|
||||
#include "CArch.h"
|
||||
@@ -33,12 +34,15 @@
|
||||
|
||||
#define DAEMON_RUNNING(running_)
|
||||
#if WINDOWS_LIKE
|
||||
#include "CMSWindowsScreen.h"
|
||||
#include "CMSWindowsPrimaryScreen.h"
|
||||
#include "CMSWindowsServerTaskBarReceiver.h"
|
||||
#include "resource.h"
|
||||
#undef DAEMON_RUNNING
|
||||
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)
|
||||
#elif UNIX_LIKE
|
||||
#include "CXWindowsPrimaryScreen.h"
|
||||
#include "CXWindowsServerTaskBarReceiver.h"
|
||||
#endif
|
||||
|
||||
// platform dependent name of a daemon
|
||||
@@ -123,11 +127,46 @@ CPrimaryScreenFactory::create(IScreenReceiver* receiver,
|
||||
}
|
||||
|
||||
|
||||
//! CQuitJob
|
||||
/*!
|
||||
A job that cancels a given thread.
|
||||
*/
|
||||
class CQuitJob : public IJob {
|
||||
public:
|
||||
CQuitJob(const CThread& thread);
|
||||
~CQuitJob();
|
||||
|
||||
// IJob overrides
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
CThread m_thread;
|
||||
};
|
||||
|
||||
CQuitJob::CQuitJob(const CThread& thread) :
|
||||
m_thread(thread)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CQuitJob::~CQuitJob()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CQuitJob::run()
|
||||
{
|
||||
m_thread.cancel();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// platform independent main
|
||||
//
|
||||
|
||||
static CServer* s_server = NULL;
|
||||
static CServer* s_server = NULL;
|
||||
static CServerTaskBarReceiver* s_taskBarReceiver = NULL;
|
||||
|
||||
static
|
||||
int
|
||||
@@ -168,6 +207,7 @@ realMain(void)
|
||||
|
||||
// open server
|
||||
try {
|
||||
s_taskBarReceiver->setServer(s_server);
|
||||
s_server->open();
|
||||
opened = true;
|
||||
|
||||
@@ -177,18 +217,17 @@ realMain(void)
|
||||
s_server->mainLoop();
|
||||
|
||||
// clean up
|
||||
#define FINALLY do { \
|
||||
if (!locked) { \
|
||||
DAEMON_RUNNING(false); \
|
||||
locked = true; \
|
||||
} \
|
||||
if (s_server != NULL) { \
|
||||
if (opened) { \
|
||||
s_server->close(); \
|
||||
} \
|
||||
} \
|
||||
delete s_server; \
|
||||
s_server = NULL; \
|
||||
#define FINALLY do { \
|
||||
if (!locked) { \
|
||||
DAEMON_RUNNING(false); \
|
||||
locked = true; \
|
||||
} \
|
||||
if (opened) { \
|
||||
s_server->close(); \
|
||||
} \
|
||||
s_taskBarReceiver->setServer(NULL); \
|
||||
delete s_server; \
|
||||
s_server = NULL; \
|
||||
} while (false)
|
||||
FINALLY;
|
||||
}
|
||||
@@ -227,6 +266,41 @@ realMain(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
realMainEntry(void*)
|
||||
{
|
||||
CThread::exit(reinterpret_cast<void*>(realMain()));
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
runMainInThread(void)
|
||||
{
|
||||
CThread appThread(new CFunctionJob(&realMainEntry));
|
||||
try {
|
||||
#if WINDOWS_LIKE
|
||||
MSG msg;
|
||||
while (appThread.waitForEvent(-1.0) == CThread::kEvent) {
|
||||
// check for a quit event
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
CThread::getCurrentThread().cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
appThread.wait(-1.0);
|
||||
#endif
|
||||
return reinterpret_cast<int>(appThread.getResult());
|
||||
}
|
||||
catch (XThread&) {
|
||||
appThread.cancel();
|
||||
appThread.wait(-1.0);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// command line parsing
|
||||
@@ -329,7 +403,7 @@ PLATFORM_EXTRA
|
||||
|
||||
static
|
||||
bool
|
||||
isArg(int argi, int argc, const char** argv,
|
||||
isArg(int argi, int argc, const char* const* argv,
|
||||
const char* name1, const char* name2,
|
||||
int minRequiredParameters = 0)
|
||||
{
|
||||
@@ -350,7 +424,7 @@ isArg(int argi, int argc, const char** argv,
|
||||
|
||||
static
|
||||
void
|
||||
parse(int argc, const char** argv)
|
||||
parse(int argc, const char* const* argv)
|
||||
{
|
||||
assert(ARG->m_pname != NULL);
|
||||
assert(argv != NULL);
|
||||
@@ -553,16 +627,6 @@ loadConfig()
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
useSystemLog()
|
||||
{
|
||||
// redirect log messages
|
||||
ILogOutputter* logger = new CSystemLogOutputter;
|
||||
logger->open(DAEMON_NAME);
|
||||
CLOG->insert(new CStopLogOutputter);
|
||||
CLOG->insert(logger);
|
||||
}
|
||||
|
||||
//
|
||||
// platform dependent entry points
|
||||
@@ -570,8 +634,6 @@ useSystemLog()
|
||||
|
||||
#if WINDOWS_LIKE
|
||||
|
||||
#include "CMSWindowsScreen.h"
|
||||
|
||||
static bool s_hasImportantLogMessages = false;
|
||||
|
||||
//
|
||||
@@ -623,7 +685,10 @@ static
|
||||
int
|
||||
daemonStartup(int argc, const char** argv)
|
||||
{
|
||||
useSystemLog();
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
|
||||
// have to cancel this thread to quit
|
||||
s_taskBarReceiver->setQuitJob(new CQuitJob(CThread::getCurrentThread()));
|
||||
|
||||
// catch errors that would normally exit
|
||||
bye = &byeThrow;
|
||||
@@ -645,14 +710,65 @@ static
|
||||
int
|
||||
daemonStartup95(int, const char**)
|
||||
{
|
||||
useSystemLog();
|
||||
return realMain();
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
return runMainInThread();
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
run(int argc, char** argv)
|
||||
{
|
||||
// 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.
|
||||
if (argc <= 1 && !CArchMiscWindows::isWindows95Family()) {
|
||||
try {
|
||||
return ARCH->daemonize(DAEMON_NAME, &daemonStartup);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
}
|
||||
return kExitFailed;
|
||||
}
|
||||
|
||||
// parse command line
|
||||
parse(argc, argv);
|
||||
|
||||
// load configuration
|
||||
loadConfig();
|
||||
|
||||
// daemonize if requested
|
||||
if (ARG->m_daemon) {
|
||||
// start as a daemon
|
||||
if (CArchMiscWindows::isWindows95Family()) {
|
||||
try {
|
||||
return ARCH->daemonize(DAEMON_NAME, &daemonStartup95);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
}
|
||||
return kExitFailed;
|
||||
}
|
||||
else {
|
||||
// cannot start a service from the command line so just
|
||||
// run normally (except with log messages redirected).
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
return runMainInThread();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// run
|
||||
return runMainInThread();
|
||||
}
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
CArch arch;
|
||||
CArch arch(instance);
|
||||
CLOG;
|
||||
CArgs args;
|
||||
|
||||
@@ -665,55 +781,27 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
|
||||
// send PRINT and FATAL output to a message box
|
||||
CLOG->insert(new CMessageBoxOutputter);
|
||||
|
||||
// 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.
|
||||
if (__argc <= 1 && !CArchMiscWindows::isWindows95Family()) {
|
||||
int result = kExitFailed;
|
||||
try {
|
||||
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
}
|
||||
delete CLOG;
|
||||
return result;
|
||||
}
|
||||
// make the task bar receiver. the user can control this app
|
||||
// through the task bar.
|
||||
s_taskBarReceiver = new CMSWindowsServerTaskBarReceiver(instance);
|
||||
s_taskBarReceiver->setQuitJob(new CQuitJob(CThread::getCurrentThread()));
|
||||
|
||||
// parse command line
|
||||
parse(__argc, const_cast<const char**>(__argv));
|
||||
|
||||
// load configuration
|
||||
loadConfig();
|
||||
|
||||
// daemonize if requested
|
||||
int result;
|
||||
if (ARG->m_daemon) {
|
||||
// start as a daemon
|
||||
if (CArchMiscWindows::isWindows95Family()) {
|
||||
try {
|
||||
result = ARCH->daemonize(DAEMON_NAME, &daemonStartup95);
|
||||
}
|
||||
catch (XArchDaemon& e) {
|
||||
LOG((CLOG_CRIT "failed to start as a service: %s" BYE, e.what().c_str(), ARG->m_pname));
|
||||
result = kExitFailed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// cannot start a service from the command line so just
|
||||
// run normally (except with log messages redirected).
|
||||
useSystemLog();
|
||||
result = realMain();
|
||||
}
|
||||
try {
|
||||
// run in foreground or as a daemon
|
||||
result = run(__argc, __argv);
|
||||
}
|
||||
else {
|
||||
// run
|
||||
result = realMain();
|
||||
catch (...) {
|
||||
// note that we don't rethrow thread cancellation. we'll
|
||||
// be exiting soon so it doesn't matter. what we'd like
|
||||
// is for everything after this try/catch to be in a
|
||||
// finally block.
|
||||
result = kExitFailed;
|
||||
}
|
||||
|
||||
// done with task bar receiver
|
||||
delete s_taskBarReceiver;
|
||||
|
||||
// let user examine any messages if we're running as a backend
|
||||
// by putting up a dialog box before exiting.
|
||||
if (ARG->m_backend && s_hasImportantLogMessages) {
|
||||
@@ -733,7 +821,7 @@ static
|
||||
int
|
||||
daemonStartup(int, const char**)
|
||||
{
|
||||
useSystemLog();
|
||||
CSystemLogger sysLogger(DAEMON_NAME);
|
||||
return realMain();
|
||||
}
|
||||
|
||||
@@ -747,8 +835,13 @@ main(int argc, char** argv)
|
||||
// get program name
|
||||
ARG->m_pname = ARCH->getBasename(argv[0]);
|
||||
|
||||
// make the task bar receiver. the user can control this app
|
||||
// through the task bar.
|
||||
s_taskBarReceiver = new CXWindowsServerTaskBarReceiver;
|
||||
s_taskBarReceiver->setQuitJob(new CQuitJob(CThread::getCurrentThread()));
|
||||
|
||||
// parse command line
|
||||
parse(argc, const_cast<const char**>(argv));
|
||||
parse(argc, argv);
|
||||
|
||||
// load configuration
|
||||
loadConfig();
|
||||
@@ -768,6 +861,9 @@ main(int argc, char** argv)
|
||||
result = realMain();
|
||||
}
|
||||
|
||||
// done with task bar receiver
|
||||
delete s_taskBarReceiver;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,14 @@ LINK32=link.exe
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CMSWindowsServerTaskBarReceiver.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CServerTaskBarReceiver.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\synergys.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -106,6 +114,14 @@ SOURCE=.\synergys.rc
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CMSWindowsServerTaskBarReceiver.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CServerTaskBarReceiver.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# End Group
|
||||
@@ -116,6 +132,22 @@ SOURCE=.\resource.h
|
||||
|
||||
SOURCE=.\synergys.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_error.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_idle.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_run.ico
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tb_wait.ico
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
|
||||
BIN
cmd/synergys/tb_error.ico
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
cmd/synergys/tb_idle.ico
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
cmd/synergys/tb_run.ico
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
cmd/synergys/tb_wait.ico
Normal file
|
After Width: | Height: | Size: 318 B |