diff --git a/cmd/synergyc/synergyc.cpp b/cmd/synergyc/synergyc.cpp index f1707e90..bd415e6a 100644 --- a/cmd/synergyc/synergyc.cpp +++ b/cmd/synergyc/synergyc.cpp @@ -27,6 +27,6 @@ int main(int argc, char** argv) { - CClientApp app; - return app.run(argc, argv, createTaskBarReceiver); + CClientApp app(createTaskBarReceiver); + return app.run(argc, argv); } diff --git a/cmd/synergys/synergys.cpp b/cmd/synergys/synergys.cpp index bee31152..6272cdae 100644 --- a/cmd/synergys/synergys.cpp +++ b/cmd/synergys/synergys.cpp @@ -27,6 +27,6 @@ int main(int argc, char** argv) { - CServerApp app; - return app.run(argc, argv, createTaskBarReceiver); + CServerApp app(createTaskBarReceiver); + return app.run(argc, argv); } diff --git a/gui/qsynergy.pro b/gui/qsynergy.pro index f67e03af..442b33e8 100644 --- a/gui/qsynergy.pro +++ b/gui/qsynergy.pro @@ -1,87 +1,83 @@ QT += network - TEMPLATE = app TARGET = qsynergy -DEPENDPATH += . res -INCLUDEPATH += . src - -FORMS += \ - res/MainWindowBase.ui \ - res/AboutDialogBase.ui \ - res/ServerConfigDialogBase.ui \ - res/ScreenSettingsDialogBase.ui \ - res/ActionDialogBase.ui \ - res/HotkeyDialogBase.ui \ - res/SettingsDialogBase.ui \ - res/LogDialogBase.ui -SOURCES += \ - src/main.cpp \ - src/MainWindow.cpp \ - src/AboutDialog.cpp \ - src/ServerConfig.cpp \ - src/ServerConfigDialog.cpp \ - src/ScreenSetupView.cpp \ - src/Screen.cpp \ - src/ScreenSetupModel.cpp \ - src/NewScreenWidget.cpp \ - src/TrashScreenWidget.cpp \ - src/ScreenSettingsDialog.cpp \ - src/BaseConfig.cpp \ - src/HotkeyDialog.cpp \ - src/ActionDialog.cpp \ - src/Hotkey.cpp \ - src/Action.cpp \ - src/KeySequence.cpp \ - src/KeySequenceWidget.cpp \ - src/LogDialog.cpp \ - src/SettingsDialog.cpp \ - src/AppConfig.cpp \ - src/QSynergyApplication.cpp -HEADERS += \ - src/MainWindow.h \ - src/AboutDialog.h \ - src/ServerConfig.h \ - src/ServerConfigDialog.h \ - src/ScreenSetupView.h \ - src/Screen.h \ - src/ScreenSetupModel.h \ - src/NewScreenWidget.h \ - src/TrashScreenWidget.h \ - src/ScreenSettingsDialog.h \ - src/BaseConfig.h \ - src/HotkeyDialog.h \ - src/ActionDialog.h \ - src/Hotkey.h \ - src/Action.h \ - src/KeySequence.h \ - src/KeySequenceWidget.h \ - src/LogDialog.h \ - src/SettingsDialog.h \ - src/AppConfig.h \ - src/QSynergyApplication.h +DEPENDPATH += . \ + res +INCLUDEPATH += . \ + src +FORMS += res/MainWindowBase.ui \ + res/AboutDialogBase.ui \ + res/ServerConfigDialogBase.ui \ + res/ScreenSettingsDialogBase.ui \ + res/ActionDialogBase.ui \ + res/HotkeyDialogBase.ui \ + res/SettingsDialogBase.ui \ + res/LogDialogBase.ui \ + res/WindowsServicesBase.ui +SOURCES += src/main.cpp \ + src/MainWindow.cpp \ + src/AboutDialog.cpp \ + src/ServerConfig.cpp \ + src/ServerConfigDialog.cpp \ + src/ScreenSetupView.cpp \ + src/Screen.cpp \ + src/ScreenSetupModel.cpp \ + src/NewScreenWidget.cpp \ + src/TrashScreenWidget.cpp \ + src/ScreenSettingsDialog.cpp \ + src/BaseConfig.cpp \ + src/HotkeyDialog.cpp \ + src/ActionDialog.cpp \ + src/Hotkey.cpp \ + src/Action.cpp \ + src/KeySequence.cpp \ + src/KeySequenceWidget.cpp \ + src/LogDialog.cpp \ + src/SettingsDialog.cpp \ + src/AppConfig.cpp \ + src/QSynergyApplication.cpp \ + src/WindowsServices.cpp +HEADERS += src/MainWindow.h \ + src/AboutDialog.h \ + src/ServerConfig.h \ + src/ServerConfigDialog.h \ + src/ScreenSetupView.h \ + src/Screen.h \ + src/ScreenSetupModel.h \ + src/NewScreenWidget.h \ + src/TrashScreenWidget.h \ + src/ScreenSettingsDialog.h \ + src/BaseConfig.h \ + src/HotkeyDialog.h \ + src/ActionDialog.h \ + src/Hotkey.h \ + src/Action.h \ + src/KeySequence.h \ + src/KeySequenceWidget.h \ + src/LogDialog.h \ + src/SettingsDialog.h \ + src/AppConfig.h \ + src/QSynergyApplication.h \ + src/WindowsServices.h RESOURCES += res/QSynergy.qrc RC_FILE = res/win/QSynergy.rc - -macx { - QMAKE_INFO_PLIST = res/mac/QSynergy.plist - QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 - TARGET = QSynergy - QSYNERGY_ICON.files = res/mac/QSynergy.icns - QSYNERGY_ICON.path = Contents/Resources - QMAKE_BUNDLE_DATA += QSYNERGY_ICON +macx { + QMAKE_INFO_PLIST = res/mac/QSynergy.plist + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 + TARGET = QSynergy + QSYNERGY_ICON.files = res/mac/QSynergy.icns + QSYNERGY_ICON.path = Contents/Resources + QMAKE_BUNDLE_DATA += QSYNERGY_ICON } - -debug { - OBJECTS_DIR = tmp/debug - MOC_DIR = tmp/debug - RCC_DIR = tmp/debug +debug { + OBJECTS_DIR = tmp/debug + MOC_DIR = tmp/debug + RCC_DIR = tmp/debug } - -release { - OBJECTS_DIR = tmp/release - MOC_DIR = tmp/release - RCC_DIR = tmp/release +release { + OBJECTS_DIR = tmp/release + MOC_DIR = tmp/release + RCC_DIR = tmp/release } - Debug:DESTDIR = ../bin/Debug Release:DESTDIR = ../bin/Release diff --git a/gui/res/MainWindowBase.ui b/gui/res/MainWindowBase.ui index ac52f236..ac78cb57 100644 --- a/gui/res/MainWindowBase.ui +++ b/gui/res/MainWindowBase.ui @@ -7,7 +7,7 @@ 0 0 400 - 247 + 260 @@ -19,13 +19,13 @@ 400 - 247 + 260 400 - 247 + 260 @@ -33,7 +33,7 @@ - + &Start @@ -133,19 +133,6 @@ - - - - Qt::Vertical - - - - 0 - 0 - - - - @@ -177,14 +164,14 @@ - + Ready - + Qt::Horizontal @@ -201,7 +188,7 @@ - &About QSynergy... + &About Synergy+... @@ -209,7 +196,7 @@ &Quit - Quit QSynergy. + Quit Ctrl+Q @@ -217,10 +204,10 @@ - &Start Synergy + &Start - Run synergy program. + Run Ctrl+S @@ -231,10 +218,10 @@ false - S&top Synergy + S&top - Stop Synergy program. + Stop Ctrl+T @@ -274,7 +261,7 @@ Settings - Edit settings for QSynergy and synergy itself + Edit settings @@ -282,7 +269,12 @@ Log output - Open a window with synergy's output + Open a window with output + + + + + Services diff --git a/gui/res/SettingsDialogBase.ui b/gui/res/SettingsDialogBase.ui index 53cdb2f3..a093f02a 100644 --- a/gui/res/SettingsDialogBase.ui +++ b/gui/res/SettingsDialogBase.ui @@ -7,7 +7,7 @@ 0 0 372 - 350 + 412 @@ -15,7 +15,7 @@ - + &Advanced @@ -81,7 +81,7 @@ - + &Start @@ -89,62 +89,13 @@ - A&utomatically start synergy when QSynergy starts + A&utomatically start server or client when GUI starts - - - - &Logging level: - - - m_pComboLogLevel - - - - - - - - Error - - - - - Warning - - - - - Note - - - - - Info - - - - - Debug - - - - - Debug1 - - - - - Debug2 - - - - @@ -156,11 +107,25 @@ - + &Programs + + + + + + Auto detect program paths + + + true + + + + + @@ -175,12 +140,19 @@ - + + + false + + + + false + - &Browse... + Browse... @@ -201,25 +173,103 @@ - - - - - - Bro&wse... + + + false - - + + + + false + + + Browse... + + + + + + + + + + Logging + + + + + + &Logging level: + + + m_pComboLogLevel + + + + + + + Log to file: + + + + + + + false + + + + + + + false + + + Browse... + + + + + - - - Auto detect program paths - - + + Error + - + + + Warning + + + + + Note + + + + + Info + + + + + Debug + + + + + Debug1 + + + + + Debug2 + + + @@ -237,6 +287,9 @@ m_pLineEditInterface m_pCheckBoxAutoConnect m_pComboLogLevel + m_pCheckBoxLogToFile + m_pLineEditLogFilename + m_pButtonBrowseLog buttonBox diff --git a/gui/res/WindowsServicesBase.ui b/gui/res/WindowsServicesBase.ui new file mode 100644 index 00000000..72440427 --- /dev/null +++ b/gui/res/WindowsServicesBase.ui @@ -0,0 +1,161 @@ + + + WindowsServicesBase + + + + 0 + 0 + 264 + 200 + + + + Windows Services + + + + + + Server + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Uninstall + + + + + + + + 0 + 0 + + + + Install + + + + + + + + + + Client + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Uninstall + + + + + + + Install + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + To start and stop a service, use the Windows services snap-in. + + + true + + + + + + + buttonBox + + + + + buttonBox + accepted() + WindowsServicesBase + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WindowsServicesBase + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/gui/src/AppConfig.cpp b/gui/src/AppConfig.cpp index ea1b850e..2ef35e0b 100644 --- a/gui/src/AppConfig.cpp +++ b/gui/src/AppConfig.cpp @@ -7,12 +7,24 @@ const char AppConfig::m_SynergysName[] = "synergys.exe"; const char AppConfig::m_SynergycName[] = "synergyc.exe"; const char AppConfig::m_SynergyProgramDir[] = "bin/"; +const char AppConfig::m_SynergyLogDir[] = "log/"; #else const char AppConfig::m_SynergysName[] = "synergys"; const char AppConfig::m_SynergycName[] = "synergyc"; const char AppConfig::m_SynergyProgramDir[] = "/usr/bin/"; +const char AppConfig::m_SynergyLogDir[] = "/var/log/"; #endif +static const char* logLevelNames[] = +{ + "ERROR", + "WARNING", + "NOTE", + "INFO", + "DEBUG", + "DEBUG1", + "DEBUG2" +}; AppConfig::AppConfig(QSettings* settings) : m_pSettings(settings), @@ -34,6 +46,33 @@ AppConfig::~AppConfig() saveSettings(); } +QString AppConfig::synergyLogDir() +{ +#if defined(Q_OS_WIN) + // on windows, we want to log to program files + return QString(QDir::currentPath() + "/log/"); +#else + // on unix, we'll log to the standard log dir + return "/var/log/"; +#endif +} + +void AppConfig::persistLogDir() +{ + QDir dir = synergyLogDir(); + + // persist the log directory + if (!dir.exists()) + { + dir.mkpath(dir.path()); + } +} + +QString AppConfig::logLevelText() const +{ + return logLevelNames[logLevel()]; +} + void AppConfig::loadSettings() { m_AutoConnect = settings().value("autoConnectChecked", false).toBool(); @@ -42,8 +81,10 @@ void AppConfig::loadSettings() m_ScreenName = settings().value("screenName", QHostInfo::localHostName()).toString(); m_Port = settings().value("port", 24800).toInt(); m_Interface = settings().value("interface").toString(); - m_LogLevel = settings().value("logLevelIndex", 0).toInt(); + m_LogLevel = settings().value("logLevel", 2).toInt(); m_AutoDetectPaths = settings().value("autoDetectPaths", true).toBool(); + m_LogToFile = settings().value("logToFile", true).toBool(); + m_LogFilename = settings().value("logFilename", synergyLogDir() + "synergy.log").toString(); } void AppConfig::saveSettings() @@ -54,7 +95,30 @@ void AppConfig::saveSettings() settings().setValue("screenName", m_ScreenName); settings().setValue("port", m_Port); settings().setValue("interface", m_Interface); - settings().setValue("logLevelIndex", m_LogLevel); + settings().setValue("logLevel", m_LogLevel); settings().setValue("autoDetectPaths", m_AutoDetectPaths); + settings().setValue("logToFile", m_LogToFile); + settings().setValue("logFilename", m_LogFilename); } +bool AppConfig::detectPath(const QString& name, QString& path) +{ + // look in current working dir and default dir + QStringList searchDirs; + searchDirs.append("./"); + searchDirs.append(synergyProgramDir()); + + // use the first valid path we find + for (int i = 0; i < searchDirs.length(); i++) + { + QFile f(searchDirs[i] + name); + if (f.exists()) + { + path = f.fileName(); + return true; + } + } + + // nothing found! + return false; +} diff --git a/gui/src/AppConfig.h b/gui/src/AppConfig.h index 591ba55d..572f8fa0 100644 --- a/gui/src/AppConfig.h +++ b/gui/src/AppConfig.h @@ -25,10 +25,17 @@ class AppConfig const QString& interface() const { return m_Interface; } int logLevel() const { return m_LogLevel; } bool autoDetectPaths() const { return m_AutoDetectPaths; } + bool logToFile() const { return m_LogToFile; } + const QString& logFilename() const { return m_LogFilename; } + QString logLevelText() const; QString synergysName() const { return m_SynergysName; } QString synergycName() const { return m_SynergycName; } QString synergyProgramDir() const { return m_SynergyProgramDir; } + QString synergyLogDir(); + + bool detectPath(const QString& name, QString& path); + void persistLogDir(); protected: QSettings& settings() { return *m_pSettings; } @@ -40,6 +47,8 @@ class AppConfig void setInterface(const QString& s) { m_Interface = s; } void setLogLevel(int i) { m_LogLevel = i; } void setAutoDetectPaths(bool b) { m_AutoDetectPaths = b; } + void setLogToFile(bool b) { m_LogToFile = b; } + void setLogFilename(const QString& s) { m_LogFilename = s; } void loadSettings(); void saveSettings(); @@ -54,10 +63,13 @@ class AppConfig QString m_Interface; int m_LogLevel; bool m_AutoDetectPaths; + bool m_LogToFile; + QString m_LogFilename; static const char m_SynergysName[]; static const char m_SynergycName[]; static const char m_SynergyProgramDir[]; + static const char m_SynergyLogDir[]; }; #endif diff --git a/gui/src/LogDialog.h b/gui/src/LogDialog.h index 52d8b21f..c6a83db1 100644 --- a/gui/src/LogDialog.h +++ b/gui/src/LogDialog.h @@ -17,6 +17,7 @@ class LogDialog : public QDialog, public Ui::LogDialogBase public: void append(const QString& s); + void clear() { m_pLogOutput->clear(); } public slots: void readSynergyOutput(); diff --git a/gui/src/MainWindow.cpp b/gui/src/MainWindow.cpp index b485b60e..c62ca99e 100644 --- a/gui/src/MainWindow.cpp +++ b/gui/src/MainWindow.cpp @@ -3,6 +3,7 @@ #include "ServerConfigDialog.h" #include "SettingsDialog.h" #include "LogDialog.h" +#include "WindowsServices.h" #include #include @@ -22,18 +23,6 @@ static const char* synergyIconFiles[] = ":/res/icons/16x16/synergy-connected.png" }; -static const char* logLevelNames[] = -{ - "ERROR", - "WARNING", - "NOTE", - "INFO", - "DEBUG", - "DEBUG1", - "DEBUG2" -}; - - MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), MainWindowBase(), @@ -121,6 +110,9 @@ void MainWindow::createMenuBar() pMenuFile->addSeparator(); pMenuFile->addAction(m_pActionQuit); pMenuEdit->addAction(m_pActionSettings); +#if defined(Q_OS_WIN) + pMenuEdit->addAction(m_pActionServices); +#endif pMenuView->addAction(m_pActionLogOutput); pMenuWindow->addAction(m_pActionMinimize); pMenuWindow->addAction(m_pActionRestore); @@ -131,13 +123,6 @@ void MainWindow::createMenuBar() void MainWindow::loadSettings() { - // gui - QRect rect = settings().value("windowGeometry", geometry()).toRect(); - move(rect.x(), rect.y()); - resize(rect.width(), rect.height()); - - // program settings - // the next two must come BEFORE loading groupServerChecked and groupClientChecked or // disabling and/or enabling the right widgets won't automatically work m_pRadioExternalConfig->setChecked(settings().value("externalConfig", false).toBool()); @@ -163,13 +148,6 @@ void MainWindow::initConnections() void MainWindow::saveSettings() { - // gui - settings().setValue("windowGeometry", geometry()); - -#if !defined(Q_OS_MAC) - settings().setValue("windowVisible", isVisible()); -#endif - // program settings settings().setValue("groupServerChecked", m_pGroupServer->isChecked()); settings().setValue("externalConfig", m_pRadioExternalConfig->isChecked()); @@ -205,7 +183,7 @@ void MainWindow::startSynergy() QString app; QStringList args; - args << "-f" << "--debug" << logLevelNames[appConfig().logLevel()]; + args << "-f" << "--debug" << appConfig().logLevelText(); if (!appConfig().screenName().isEmpty()) args << "--name" << appConfig().screenName(); @@ -236,39 +214,9 @@ void MainWindow::startSynergy() setSynergyState(synergyConnected); } -bool MainWindow::detectPath(const QString& name, QString& path) -{ - // look in current working dir and default dir - QStringList searchDirs; - searchDirs.append("./"); - searchDirs.append(appConfig().synergyProgramDir()); - - // use the first valid path we find - for (int i = 0; i < searchDirs.length(); i++) - { - QFile f(searchDirs[i] + name); - if (f.exists()) - { - path = f.fileName(); - return true; - } - } - - // nothing found! - return false; -} - bool MainWindow::clientArgs(QStringList& args, QString& app) { - if (appConfig().autoDetectPaths()) - { - // actually returns bool, but ignore for now - detectPath(appConfig().synergycName(), app); - } - else - { - app = appConfig().synergyc(); - } + app = appPath(appConfig().synergycName(), appConfig().synergyc()); if (!QFile::exists(app)) { @@ -289,22 +237,75 @@ bool MainWindow::clientArgs(QStringList& args, QString& app) return false; } + if (appConfig().logToFile()) + { + appConfig().persistLogDir(); + args << "--log" << appConfig().logFilename(); + } + args << m_pLineEditHostname->text() + ":" + QString::number(appConfig().port()); return true; } -bool MainWindow::serverArgs(QStringList& args, QString& app) +QString MainWindow::configFilename() { - if (appConfig().autoDetectPaths()) + QString filename; + if (m_pRadioInternalConfig->isChecked()) { - // actually returns bool, but ignore for now - detectPath(appConfig().synergysName(), app); + // TODO: no need to use a temporary file, since we need it to + // be permenant (since it'll be used for Windows services, etc). + m_pTempConfigFile = new QTemporaryFile(); + if (!m_pTempConfigFile->open()) + { + QMessageBox::critical(this, tr("Cannot write configuration file"), tr("The temporary configuration file required to start synergy can not be written.")); + return false; + } + + serverConfig().save(*m_pTempConfigFile); + filename = m_pTempConfigFile->fileName(); + + m_pTempConfigFile->close(); } else { - app = appConfig().synergys(); + if (!QFile::exists(m_pLineEditConfigFile->text())) + { + if (QMessageBox::warning(this, tr("Configuration filename invalid"), + tr("You have not filled in a valid configuration file for the synergy server. " + "Do you want to browse for the configuration file now?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes + || !on_m_pButtonBrowseConfigFile_clicked()) + return false; + } + + filename = m_pLineEditConfigFile->text(); } + return filename; +} + +QString MainWindow::address() +{ + return (!appConfig().interface().isEmpty() ? appConfig().interface() : "") + ":" + QString::number(appConfig().port()); +} + +QString MainWindow::appPath(const QString& name, const QString& defaultPath) +{ + QString app; + if (appConfig().autoDetectPaths()) + { + // actually returns bool, but ignore for now + appConfig().detectPath(name, app); + } + else + { + app = defaultPath; + } + return app; +} + +bool MainWindow::serverArgs(QStringList& args, QString& app) +{ + app = appPath(appConfig().synergysName(), appConfig().synergys()); if (!QFile::exists(app)) { @@ -319,36 +320,13 @@ bool MainWindow::serverArgs(QStringList& args, QString& app) appConfig().setSynergys(app); } - if (m_pRadioInternalConfig->isChecked()) + if (appConfig().logToFile()) { - m_pTempConfigFile = new QTemporaryFile(); - if (!m_pTempConfigFile->open()) - { - QMessageBox::critical(this, tr("Cannot write configuration file"), tr("The temporary configuration file required to start synergy can not be written.")); - return false; - } - - serverConfig().save(*m_pTempConfigFile); - args << "-c" << m_pTempConfigFile->fileName(); - - m_pTempConfigFile->close(); - // the file will be removed from disk when the object is deleted; this happens in stopSynergy() - } - else - { - if (!QFile::exists(m_pLineEditConfigFile->text())) - { - if (QMessageBox::warning(this, tr("Configuration filename invalid"), - tr("You have not filled in a valid configuration file for the synergy server. " - "Do you want to browse for the configuration file now?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes - || !on_m_pButtonBrowseConfigFile_clicked()) - return false; - } - - args << "-c" << m_pLineEditConfigFile->text(); + appConfig().persistLogDir(); + args << "--log" << appConfig().logFilename(); } - args << "--address" << (!appConfig().interface().isEmpty() ? appConfig().interface() : "") + ":" + QString::number(appConfig().port()); + args << "-c" << configFilename() << "--address" << address(); return true; } @@ -365,7 +343,9 @@ void MainWindow::stopSynergy() setSynergyState(synergyDisconnected); } - delete m_pTempConfigFile; + // HACK: deleting the object deletes the physical file, which is + // bad, since it could be in use by the Windows service! + //delete m_pTempConfigFile; m_pTempConfigFile = NULL; } @@ -460,6 +440,12 @@ void MainWindow::on_m_pActionSettings_triggered() dlg.exec(); } +void MainWindow::on_m_pActionServices_triggered() +{ + WindowsServices dlg(this, appConfig()); + dlg.exec(); +} + void MainWindow::on_m_pActionLogOutput_triggered() { Q_ASSERT(m_pLogDialog); diff --git a/gui/src/MainWindow.h b/gui/src/MainWindow.h index 0e107e3e..023b8b42 100644 --- a/gui/src/MainWindow.h +++ b/gui/src/MainWindow.h @@ -54,6 +54,10 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void setVisible(bool visible); int synergyType() const { return m_pGroupClient->isChecked() ? synergyClient : synergyServer; } int synergyState() const { return m_SynergyState; } + QString hostname() const { return m_pLineEditHostname->text(); } + QString configFilename(); + QString address(); + QString appPath(const QString& name, const QString& defaultPath); protected slots: void on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); } @@ -63,6 +67,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase bool on_m_pActionSave_triggered(); void on_m_pActionAbout_triggered(); void on_m_pActionSettings_triggered(); + void on_m_pActionServices_triggered(); void on_m_pActionLogOutput_triggered(); void synergyFinished(int exitCode, QProcess::ExitStatus); void iconActivated(QSystemTrayIcon::ActivationReason reason); @@ -87,7 +92,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase bool clientArgs(QStringList& args, QString& app); bool serverArgs(QStringList& args, QString& app); void setStatus(const QString& status); - bool detectPath(const QString& name, QString& path); private: QSettings m_Settings; diff --git a/gui/src/SettingsDialog.cpp b/gui/src/SettingsDialog.cpp index b64f3067..eaa27e9f 100644 --- a/gui/src/SettingsDialog.cpp +++ b/gui/src/SettingsDialog.cpp @@ -20,6 +20,8 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_pLineEditInterface->setText(appConfig().interface()); m_pComboLogLevel->setCurrentIndex(appConfig().logLevel()); m_pCheckBoxAutoDetectPaths->setChecked(appConfig().autoDetectPaths()); + m_pCheckBoxLogToFile->setChecked(appConfig().logToFile()); + m_pLineEditLogFilename->setText(appConfig().logFilename()); } QString SettingsDialog::browseForSynergyc(QWidget* parent, const QString& programDir, const QString& synergycName) @@ -76,7 +78,29 @@ void SettingsDialog::accept() appConfig().setInterface(m_pLineEditInterface->text()); appConfig().setLogLevel(m_pComboLogLevel->currentIndex()); appConfig().setAutoDetectPaths(m_pCheckBoxAutoDetectPaths->isChecked()); + appConfig().setLogToFile(m_pCheckBoxLogToFile->isChecked()); + appConfig().setLogFilename(m_pLineEditLogFilename->text()); QDialog::accept(); } +void SettingsDialog::on_m_pCheckBoxLogToFile_stateChanged(int i) +{ + bool checked = i == 2; + + m_pLineEditLogFilename->setEnabled(checked); + m_pButtonBrowseLog->setEnabled(checked); +} + +void SettingsDialog::on_m_pButtonBrowseLog_clicked() +{ + QString fileName = QFileDialog::getSaveFileName( + this, tr("Save log file to..."), + m_pLineEditLogFilename->text(), + "Logs (*.log *.txt)"); + + if (!fileName.isEmpty()) + { + m_pLineEditLogFilename->setText(fileName); + } +} diff --git a/gui/src/SettingsDialog.h b/gui/src/SettingsDialog.h index 75ba6e1e..5ecb515a 100644 --- a/gui/src/SettingsDialog.h +++ b/gui/src/SettingsDialog.h @@ -13,22 +13,22 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase public: SettingsDialog(QWidget* parent, AppConfig& config); - - public: static QString browseForSynergyc(QWidget* parent, const QString& programDir, const QString& synergycName); static QString browseForSynergys(QWidget* parent, const QString& programDir, const QString& synergysName); - protected slots: - bool on_m_pButtonBrowseSynergys_clicked(); - bool on_m_pButtonBrowseSynergyc_clicked(); - void on_m_pCheckBoxAutoDetectPaths_stateChanged(int i); - protected: void accept(); AppConfig& appConfig() { return m_AppConfig; } private: AppConfig& m_AppConfig; + + private slots: + void on_m_pCheckBoxLogToFile_stateChanged(int ); + bool on_m_pButtonBrowseSynergys_clicked(); + bool on_m_pButtonBrowseSynergyc_clicked(); + void on_m_pCheckBoxAutoDetectPaths_stateChanged(int i); + void on_m_pButtonBrowseLog_clicked(); }; #endif diff --git a/gui/src/WindowsServices.cpp b/gui/src/WindowsServices.cpp new file mode 100644 index 00000000..2d807e64 --- /dev/null +++ b/gui/src/WindowsServices.cpp @@ -0,0 +1,130 @@ +#include "WindowsServices.h" +#include "AppConfig.h" +#include "MainWindow.h" +#include "LogDialog.h" + +#include +#include +#include +#include + +WindowsServices::WindowsServices(QWidget* parent, AppConfig& appConfig) : + QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), + Ui::WindowsServicesBase(), + m_appConfig(appConfig), + m_log(new LogDialog(this, process())) +{ + setupUi(this); +} + +void WindowsServices::runProc(const QString& app, const QStringList& args, QPushButton* button) +{ + // disable until we know we've finished + button->setEnabled(false); + + // clear contents so user doesn't get confused by previous messages + m_log->clear(); + + // deleted at end of function + QProcess proc(this); + m_process = &proc; + + // send output to log window + connect(m_process, SIGNAL(readyReadStandardOutput()), m_log, SLOT(readSynergyOutput())); + connect(m_process, SIGNAL(readyReadStandardError()), m_log, SLOT(readSynergyOutput())); + + m_process->start(app, args); + m_log->show(); + + // service management should be instant + m_process->waitForFinished(); + + if (m_process->exitCode() == 0) + { + QMessageBox::information(m_log, "Service manager", "Completed successfully."); + } + else + { + QMessageBox::critical( + m_log, "Service manager error", + QString("Unable to install or uninstall service. Error code: " + + QString::number(m_process->exitCode()))); + } + + disconnect(m_process, SIGNAL(readyReadStandardOutput()), m_log, SLOT(readSynergyOutput())); + disconnect(m_process, SIGNAL(readyReadStandardError()), m_log, SLOT(readSynergyOutput())); + + button->setEnabled(true); +} + +void WindowsServices::on_m_pInstallServer_clicked() +{ + QString app = mainWindow()->appPath( + appConfig().synergysName(), appConfig().synergys()); + + QStringList args; + args << + "--service" << "install" << + "--relaunch" << + "--debug" << appConfig().logLevelText() << + "-c" << mainWindow()->configFilename() << + "--address" << mainWindow()->address(); + + if (appConfig().logToFile()) + { + appConfig().persistLogDir(); + args << "--log" << appConfig().logFilename(); + } + + runProc(app, args, m_pInstallServer); +} + +void WindowsServices::on_m_pUninstallServer_clicked() +{ + QString app = mainWindow()->appPath( + appConfig().synergysName(), appConfig().synergys()); + + QStringList args; + args << "--service" << "uninstall"; + runProc(app, args, m_pInstallServer); +} + +void WindowsServices::on_m_pInstallClient_clicked() +{ + if (mainWindow()->hostname().isEmpty()) + { + QMessageBox::critical( + this, "Service manager error", "Hostname was not specified on main screen."); + return; + } + + QString app = mainWindow()->appPath( + appConfig().synergycName(), appConfig().synergyc()); + + QStringList args; + args << + "--service" << "install" << + "--relaunch" << + "--debug" << appConfig().logLevelText(); + + if (appConfig().logToFile()) + { + appConfig().persistLogDir(); + args << "--log" << appConfig().logFilename(); + } + + // hostname must come last to be a valid arg + args << mainWindow()->hostname(); + + runProc(app, args, m_pInstallServer); +} + +void WindowsServices::on_m_pUninstallClient_clicked() +{ + QString app = mainWindow()->appPath( + appConfig().synergycName(), appConfig().synergyc()); + + QStringList args; + args << "--service" << "uninstall"; + runProc(app, args, m_pInstallServer); +} diff --git a/gui/src/WindowsServices.h b/gui/src/WindowsServices.h new file mode 100644 index 00000000..fb00594e --- /dev/null +++ b/gui/src/WindowsServices.h @@ -0,0 +1,41 @@ +#ifndef WINDOWSSERVICES_H +#define WINDOWSSERVICES_H + +#include "ui_WindowsServicesBase.h" + +class QWidget; +class QProcess; +class QPushButton; +class QProcess; + +class AppConfig; +class MainWindow; +class LogDialog; + +class WindowsServices : public QDialog, public Ui::WindowsServicesBase +{ + Q_OBJECT + + public: + WindowsServices(QWidget* parent, AppConfig& appConfig); + + protected: + AppConfig &appConfig() const { return m_appConfig; } + MainWindow* mainWindow() const { return (MainWindow*)parent(); } + QProcess*& process() { return m_process; } + void runProc(const QString& app, const QStringList& args, QPushButton* button); + + private: + QString m_app; + AppConfig &m_appConfig; + QProcess* m_process; + LogDialog* m_log; + + private slots: + void on_m_pUninstallClient_clicked(); + void on_m_pInstallClient_clicked(); + void on_m_pUninstallServer_clicked(); + void on_m_pInstallServer_clicked(); +}; + +#endif // WINDOWSSERVICES_H diff --git a/lib/arch/CArch.cpp b/lib/arch/CArch.cpp index 823d2d7e..b299ffc7 100644 --- a/lib/arch/CArch.cpp +++ b/lib/arch/CArch.cpp @@ -666,9 +666,9 @@ CArch::app() const } int -CArch::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) +CArch::run(int argc, char** argv) { - return m_appUtil->run(argc, argv, createTaskBarReceiver); + return m_appUtil->run(argc, argv); } void diff --git a/lib/arch/CArch.h b/lib/arch/CArch.h index a5822812..f6bb400a 100644 --- a/lib/arch/CArch.h +++ b/lib/arch/CArch.h @@ -186,7 +186,7 @@ public: virtual bool parseArg(const int& argc, const char* const* argv, int& i); virtual void adoptApp(CApp* app); virtual CApp& app() const; - virtual int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver); + virtual int run(int argc, char** argv); virtual void beforeAppExit(); // expose util so we don't need to re-implement all the functions diff --git a/lib/arch/CArchAppUtilWindows.cpp b/lib/arch/CArchAppUtilWindows.cpp index 5e01caa2..0a957e56 100644 --- a/lib/arch/CArchAppUtilWindows.cpp +++ b/lib/arch/CArchAppUtilWindows.cpp @@ -44,10 +44,13 @@ CArchAppUtilWindows::~CArchAppUtilWindows() BOOL WINAPI CArchAppUtilWindows::consoleHandler(DWORD CEvent) { - // HACK: it would be nice to delete the s_taskBarReceiver object, but - // this is best done by the CApp destructor; however i don't feel like - // opening up that can of worms today... i need sleep. - instance().app().s_taskBarReceiver->cleanup(); + if (instance().app().m_taskBarReceiver) + { + // HACK: it would be nice to delete the s_taskBarReceiver object, but + // this is best done by the CApp destructor; however i don't feel like + // opening up that can of worms today... i need sleep. + instance().app().m_taskBarReceiver->cleanup(); + } ExitProcess(kExitTerminated); return TRUE; @@ -83,8 +86,17 @@ CArchAppUtilWindows::parseArg(const int& argc, const char* const* argv, int& i) app().argsBase().m_debugServiceWait = true; } else if (app().isArg(i, argc, argv, NULL, "--relaunch")) { + app().argsBase().m_relaunchMode = true; } + else if (app().isArg(i, argc, argv, NULL, "--exit-pause")) { + + app().argsBase().m_pauseOnExit = true; + } + else if (app().isArg(i, argc, argv, NULL, "--no-tray")) { + + app().argsBase().m_disableTray = true; + } else { // option not supported here return false; @@ -258,20 +270,17 @@ foregroundStartupStatic(int argc, char** argv) void CArchAppUtilWindows::beforeAppExit() { - CString name; - CArchMiscWindows::getParentProcessName(name); - - // if the user did not launch from the command prompt (i.e. it was launched - // by double clicking, or through a debugger), allow user to read any error - // messages (instead of the window closing automatically). - if (name != "cmd.exe") { + // this can be handy for debugging, since the application is launched in + // a new console window, and will normally close on exit (making it so + // that we can't see error messages). + if (app().argsBase().m_pauseOnExit) { std::cout << std::endl << "Press any key to exit..." << std::endl; int c = _getch(); } } int -CArchAppUtilWindows::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) +CArchAppUtilWindows::run(int argc, char** argv) { // record window instance for tray icon, etc CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL)); @@ -287,7 +296,7 @@ CArchAppUtilWindows::run(int argc, char** argv, CreateTaskBarReceiverFunc create app().argsBase().m_daemon = false; } - return app().runInner(argc, argv, NULL, startup, createTaskBarReceiver); + return app().runInner(argc, argv, NULL, startup); } CArchAppUtilWindows& diff --git a/lib/arch/CArchAppUtilWindows.h b/lib/arch/CArchAppUtilWindows.h index 505a6526..158f718c 100644 --- a/lib/arch/CArchAppUtilWindows.h +++ b/lib/arch/CArchAppUtilWindows.h @@ -58,7 +58,7 @@ public: void debugServiceWait(); - int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver); + int run(int argc, char** argv); void exitApp(int code); diff --git a/lib/arch/IArchAppUtil.h b/lib/arch/IArchAppUtil.h index f2c88a65..028e4ce7 100644 --- a/lib/arch/IArchAppUtil.h +++ b/lib/arch/IArchAppUtil.h @@ -25,7 +25,7 @@ public: virtual bool parseArg(const int& argc, const char* const* argv, int& i) = 0; virtual void adoptApp(CApp* app) = 0; virtual CApp& app() const = 0; - virtual int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) = 0; + virtual int run(int argc, char** argv) = 0; virtual void beforeAppExit() = 0; virtual void startNode() = 0; }; diff --git a/lib/platform/CMSWindowsRelauncher.cpp b/lib/platform/CMSWindowsRelauncher.cpp index 61991b19..8341021e 100644 --- a/lib/platform/CMSWindowsRelauncher.cpp +++ b/lib/platform/CMSWindowsRelauncher.cpp @@ -30,7 +30,7 @@ CMSWindowsRelauncher::startAsync() void CMSWindowsRelauncher::startThread(void*) { - LOG((CLOG_DEBUG "starting relaunch loop")); + LOG((CLOG_NOTE "starting relaunch service")); int ret = relaunchLoop(); // HACK: this actually throws an exception to exit with 0 (nasty) diff --git a/lib/synergy/CApp.cpp b/lib/synergy/CApp.cpp index d6b01258..449fe3a6 100644 --- a/lib/synergy/CApp.cpp +++ b/lib/synergy/CApp.cpp @@ -30,11 +30,12 @@ CApp* CApp::s_instance = nullptr; -CApp::CApp(CArgsBase* args) : +CApp::CApp(CreateTaskBarReceiverFunc createTaskBarReceiver, CArgsBase* args) : +m_createTaskBarReceiver(createTaskBarReceiver), m_args(args), m_bye(&exit), -s_taskBarReceiver(NULL), -s_suspended(false) +m_taskBarReceiver(NULL), +m_suspended(false) { assert(s_instance == nullptr); s_instance = this; @@ -50,6 +51,8 @@ CApp::CArgsBase::CArgsBase() : m_daemon(false), // daemon mode not supported on windows (use --service) m_debugServiceWait(false), m_relaunchMode(false), +m_pauseOnExit(false), +m_disableTray(false), #else m_daemon(true), // backward compatibility for unix (daemon by default) #endif @@ -232,7 +235,7 @@ CApp::version() } int -CApp::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver) +CApp::run(int argc, char** argv) { #if SYSAPI_WIN32 // record window instance for tray icon, etc @@ -251,7 +254,7 @@ CApp::run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver int result = kExitFailed; try { - result = ARCH->run(argc, argv, createTaskBarReceiver); + result = ARCH->run(argc, argv); } catch (XExitApp& e) { // instead of showing a nasty error, just exit with the error code. @@ -322,4 +325,16 @@ CApp::initApp(int argc, const char** argv) // load configuration loadConfig(); + + if (!argsBase().m_disableTray) { + + // create a log buffer so we can show the latest message + // as a tray icon tooltip + CBufferedLogOutputter* logBuffer = new CBufferedLogOutputter(1000); + CLOG->insert(logBuffer, true); + + // make the task bar receiver. the user can control this app + // through the task bar. + m_taskBarReceiver = m_createTaskBarReceiver(logBuffer); + } } diff --git a/lib/synergy/CApp.h b/lib/synergy/CApp.h index d42373c4..0cdec89f 100644 --- a/lib/synergy/CApp.h +++ b/lib/synergy/CApp.h @@ -44,10 +44,12 @@ public: #if SYSAPI_WIN32 bool m_relaunchMode; bool m_debugServiceWait; + bool m_pauseOnExit; + bool m_disableTray; #endif }; - CApp(CArgsBase* args); + CApp(CreateTaskBarReceiverFunc createTaskBarReceiver, CArgsBase* args); virtual ~CApp(); // Returns args that are common between server and client. @@ -62,7 +64,7 @@ public: // Parse command line arguments. virtual void parseArgs(int argc, const char* const* argv) = 0; - int run(int argc, char** argv, CreateTaskBarReceiverFunc createTaskBarReceiver); + int run(int argc, char** argv); int daemonMainLoop(int, const char**); @@ -71,7 +73,7 @@ public: virtual int mainLoop() = 0; virtual int foregroundStartup(int argc, char** argv) = 0; virtual int standardStartup(int argc, char** argv) = 0; - virtual int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver) = 0; + virtual int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup) = 0; // Name of the daemon (used for Unix and Windows). virtual const char* daemonName() const = 0; @@ -90,8 +92,8 @@ public: static CApp& instance() { assert(s_instance != nullptr); return *s_instance; } - bool s_suspended; - IArchTaskBarReceiver* s_taskBarReceiver; + bool m_suspended; + IArchTaskBarReceiver* m_taskBarReceiver; // If --log was specified in args, then add a file logger. void setupFileLogging(); @@ -118,6 +120,7 @@ private: CArgsBase* m_args; static CApp* s_instance; CFileLogOutputter* m_fileLog; + CreateTaskBarReceiverFunc m_createTaskBarReceiver; }; #define BYE "\nTry `%s --help' for more information." @@ -166,6 +169,9 @@ private: " --service manage the windows service, valid options are:\n" \ " install/uninstall/start/stop\n" \ " --relaunch persistently relaunches process in current user \n" \ - " session (useful for vista and upward).\n" + " session (useful for vista and upward).\n" \ + " --exit-pause wait for key press on exit, can be useful for\n" \ + " reading error messages that occur on exit.\n" \ + " --no-tray disable the system tray icon.\n" #endif diff --git a/lib/synergy/CClientApp.cpp b/lib/synergy/CClientApp.cpp index 62cc6092..07e432b4 100644 --- a/lib/synergy/CClientApp.cpp +++ b/lib/synergy/CClientApp.cpp @@ -49,8 +49,8 @@ #define RETRY_TIME 1.0 -CClientApp::CClientApp() : -CApp(new CArgs()), +CClientApp::CClientApp(CreateTaskBarReceiverFunc createTaskBarReceiver) : +CApp(createTaskBarReceiver, new CArgs()), s_client(NULL), s_clientScreen(NULL) { @@ -168,6 +168,7 @@ CClientApp::help() "Usage: %s" " [--yscroll ]" WINAPI_ARG + HELP_SYS_ARGS HELP_COMMON_ARGS " " "\n\n" @@ -175,6 +176,7 @@ CClientApp::help() "\n" HELP_COMMON_INFO_1 WINAPI_INFO + HELP_SYS_INFO " --yscroll defines the vertical scrolling delta, which is\n" HELP_COMMON_INFO_2 "\n" @@ -224,14 +226,17 @@ CClientApp::createScreen() void CClientApp::updateStatus() { - s_taskBarReceiver->updateStatus(s_client, ""); + updateStatus(""); } void CClientApp::updateStatus(const CString& msg) { - s_taskBarReceiver->updateStatus(s_client, msg); + if (m_taskBarReceiver) + { + m_taskBarReceiver->updateStatus(s_client, msg); + } } @@ -343,7 +348,7 @@ CClientApp::handleClientFailed(const CEvent& e, void*) } else { LOG((CLOG_WARN "failed to connect to server: %s", info->m_what.c_str())); - if (!s_suspended) { + if (!m_suspended) { scheduleClientRestart(nextRestartTimeout()); } } @@ -358,7 +363,7 @@ CClientApp::handleClientDisconnected(const CEvent&, void*) if (!args().m_restartable) { EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); } - else if (!s_suspended) { + else if (!m_suspended) { s_client->connect(); } updateStatus(); @@ -530,7 +535,7 @@ CClientApp::standardStartup(int argc, char** argv) } int -CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver) +CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup) { // general initialization args().m_serverAddress = new CNetworkAddress; @@ -541,15 +546,6 @@ CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun CLOG->insert(outputter); } - // save log messages - // use heap memory because CLog deletes outputters on destruction - CBufferedLogOutputter* logBuffer = new CBufferedLogOutputter(1000); - CLOG->insert(logBuffer, true); - - // make the task bar receiver. the user can control this app - // through the task bar. - s_taskBarReceiver = createTaskBarReceiver(logBuffer); - int result; try { @@ -558,8 +554,11 @@ CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun } catch (...) { - // done with task bar receiver - delete s_taskBarReceiver; + if (m_taskBarReceiver) + { + // done with task bar receiver + delete m_taskBarReceiver; + } delete args().m_serverAddress; diff --git a/lib/synergy/CClientApp.h b/lib/synergy/CClientApp.h index be9b4b89..e7ddccf1 100644 --- a/lib/synergy/CClientApp.h +++ b/lib/synergy/CClientApp.h @@ -33,7 +33,7 @@ public: CNetworkAddress* m_serverAddress; }; - CClientApp(); + CClientApp(CreateTaskBarReceiverFunc createTaskBarReceiver); virtual ~CClientApp(); // Parse client specific command line arguments. @@ -54,7 +54,7 @@ public: int foregroundStartup(int argc, char** argv); int standardStartup(int argc, char** argv); - int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver); + int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup); CScreen* createScreen(); void updateStatus(); void updateStatus(const CString& msg); diff --git a/lib/synergy/CServerApp.cpp b/lib/synergy/CServerApp.cpp index b92ff07b..3d481000 100644 --- a/lib/synergy/CServerApp.cpp +++ b/lib/synergy/CServerApp.cpp @@ -50,8 +50,8 @@ CEvent::Type CServerApp::s_reloadConfigEvent = CEvent::kUnknown; -CServerApp::CServerApp() : -CApp(new CArgs()), +CServerApp::CServerApp(CreateTaskBarReceiverFunc createTaskBarReceiver) : +CApp(createTaskBarReceiver, new CArgs()), s_server(NULL), s_forceReconnectEvent(CEvent::kUnknown), s_resetServerEvent(CEvent::kUnknown), @@ -370,12 +370,15 @@ CServerApp::stopRetryTimer() void CServerApp::updateStatus() { - s_taskBarReceiver->updateStatus(s_server, ""); + updateStatus(""); } void CServerApp::updateStatus( const CString& msg ) { - s_taskBarReceiver->updateStatus(s_server, msg); + if (m_taskBarReceiver) + { + m_taskBarReceiver->updateStatus(s_server, msg); + } } void @@ -657,20 +660,20 @@ CServerApp::handleScreenError(const CEvent&, void*) void CServerApp::handleSuspend(const CEvent&, void*) { - if (!s_suspended) { + if (!m_suspended) { LOG((CLOG_INFO "suspend")); stopServer(); - s_suspended = true; + m_suspended = true; } } void CServerApp::handleResume(const CEvent&, void*) { - if (s_suspended) { + if (m_suspended) { LOG((CLOG_INFO "resume")); startServer(); - s_suspended = false; + m_suspended = false; } } @@ -796,7 +799,7 @@ void CServerApp::resetServer(const CEvent&, void*) } int -CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver) +CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup) { // general initialization args().m_synergyAddress = new CNetworkAddress; @@ -808,20 +811,14 @@ CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun CLOG->insert(outputter); } - // save log messages - // use heap memory because CLog deletes outputters on destruction - CBufferedLogOutputter* logBuffer = new CBufferedLogOutputter(1000); - CLOG->insert(logBuffer, true); - - // make the task bar receiver. the user can control this app - // through the task bar. - s_taskBarReceiver = createTaskBarReceiver(logBuffer); - // run int result = startup(argc, argv); - // done with task bar receiver - delete s_taskBarReceiver; + if (m_taskBarReceiver) + { + // done with task bar receiver + delete m_taskBarReceiver; + } delete args().m_config; delete args().m_synergyAddress; diff --git a/lib/synergy/CServerApp.h b/lib/synergy/CServerApp.h index c2ea50dd..5134423b 100644 --- a/lib/synergy/CServerApp.h +++ b/lib/synergy/CServerApp.h @@ -49,7 +49,7 @@ public: CConfig* m_config; }; - CServerApp(); + CServerApp(CreateTaskBarReceiverFunc createTaskBarReceiver); virtual ~CServerApp(); // Parse server specific command line arguments. @@ -99,7 +99,7 @@ public: void handleNoClients(const CEvent&, void*); bool startServer(); int mainLoop(); - int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup, CreateTaskBarReceiverFunc createTaskBarReceiver); + int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup); int standardStartup(int argc, char** argv); int foregroundStartup(int argc, char** argv); void startNode();