2012-06-10 16:50:54 +00:00
|
|
|
/*
|
|
|
|
* synergy -- mouse and keyboard sharing utility
|
2014-11-02 12:12:05 +00:00
|
|
|
* Copyright (C) 2012 Synergy Si Ltd.
|
2012-09-04 02:09:56 +00:00
|
|
|
* Copyright (C) 2002 Chris Schoeneman
|
2012-06-10 16:50:54 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2014-02-28 12:36:45 +00:00
|
|
|
#include "synergy/App.h"
|
2014-10-23 10:30:51 +00:00
|
|
|
|
2014-02-28 12:36:45 +00:00
|
|
|
#include "base/Log.h"
|
|
|
|
#include "common/Version.h"
|
|
|
|
#include "synergy/protocol_types.h"
|
|
|
|
#include "arch/Arch.h"
|
|
|
|
#include "base/XBase.h"
|
|
|
|
#include "arch/XArch.h"
|
|
|
|
#include "base/log_outputters.h"
|
|
|
|
#include "synergy/XSynergy.h"
|
|
|
|
#include "synergy/ArgsBase.h"
|
|
|
|
#include "ipc/IpcServerProxy.h"
|
|
|
|
#include "base/TMethodEventJob.h"
|
|
|
|
#include "ipc/IpcMessage.h"
|
|
|
|
#include "ipc/Ipc.h"
|
|
|
|
#include "base/EventQueue.h"
|
2012-06-10 16:50:54 +00:00
|
|
|
|
|
|
|
#if SYSAPI_WIN32
|
2014-02-28 12:36:45 +00:00
|
|
|
#include "arch/win32/ArchMiscWindows.h"
|
|
|
|
#include "base/IEventQueue.h"
|
|
|
|
#include "base/TMethodJob.h"
|
2012-06-10 16:50:54 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#if WINAPI_CARBON
|
|
|
|
#include <ApplicationServices/ApplicationServices.h>
|
|
|
|
#endif
|
|
|
|
|
2013-09-18 14:12:19 +00:00
|
|
|
#if defined(__APPLE__)
|
2014-02-28 12:36:45 +00:00
|
|
|
#include "platform/OSXDragSimulator.h"
|
2013-09-18 14:12:19 +00:00
|
|
|
#endif
|
|
|
|
|
2014-11-11 13:51:47 +00:00
|
|
|
App* App::s_instance = nullptr;
|
2012-06-10 16:50:54 +00:00
|
|
|
|
2014-10-23 10:30:51 +00:00
|
|
|
//
|
2014-11-11 13:51:47 +00:00
|
|
|
// App
|
2014-10-23 10:30:51 +00:00
|
|
|
//
|
|
|
|
|
2014-11-11 13:51:47 +00:00
|
|
|
App::App(IEventQueue* events, CreateTaskBarReceiverFunc createTaskBarReceiver, ArgsBase* args) :
|
2013-06-29 14:17:49 +00:00
|
|
|
m_bye(&exit),
|
|
|
|
m_taskBarReceiver(NULL),
|
|
|
|
m_suspended(false),
|
2014-02-25 15:03:43 +00:00
|
|
|
m_events(events),
|
|
|
|
m_args(args),
|
|
|
|
m_createTaskBarReceiver(createTaskBarReceiver),
|
|
|
|
m_appUtil(events),
|
|
|
|
m_ipcClient(nullptr)
|
2012-06-10 16:50:54 +00:00
|
|
|
{
|
|
|
|
assert(s_instance == nullptr);
|
|
|
|
s_instance = this;
|
|
|
|
}
|
|
|
|
|
2014-11-11 13:51:47 +00:00
|
|
|
App::~App()
|
2012-06-10 16:50:54 +00:00
|
|
|
{
|
2014-10-22 15:52:08 +00:00
|
|
|
s_instance = nullptr;
|
2012-06-10 16:50:54 +00:00
|
|
|
delete m_args;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::version()
|
2012-06-10 16:50:54 +00:00
|
|
|
{
|
|
|
|
char buffer[500];
|
|
|
|
sprintf(
|
|
|
|
buffer,
|
|
|
|
"%s %s, protocol version %d.%d\n%s",
|
|
|
|
argsBase().m_pname,
|
|
|
|
kVersion,
|
|
|
|
kProtocolMajorVersion,
|
|
|
|
kProtocolMinorVersion,
|
|
|
|
kCopyright
|
|
|
|
);
|
|
|
|
|
|
|
|
std::cout << buffer << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-11-11 13:51:47 +00:00
|
|
|
App::run(int argc, char** argv)
|
2013-03-15 16:14:43 +00:00
|
|
|
{
|
2012-06-10 16:50:54 +00:00
|
|
|
#if MAC_OS_X_VERSION_10_7
|
|
|
|
// dock hide only supported on lion :(
|
|
|
|
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
2014-02-25 15:03:43 +00:00
|
|
|
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
2012-06-10 16:50:54 +00:00
|
|
|
GetCurrentProcess(&psn);
|
2014-02-25 15:03:43 +00:00
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
|
2012-06-10 16:50:54 +00:00
|
|
|
TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// install application in to arch
|
|
|
|
appUtil().adoptApp(this);
|
|
|
|
|
|
|
|
// HACK: fail by default (saves us setting result in each catch)
|
|
|
|
int result = kExitFailed;
|
|
|
|
|
|
|
|
try {
|
|
|
|
result = appUtil().run(argc, argv);
|
|
|
|
}
|
|
|
|
catch (XExitApp& e) {
|
|
|
|
// instead of showing a nasty error, just exit with the error code.
|
|
|
|
// not sure if i like this behaviour, but it's probably better than
|
|
|
|
// using the exit(int) function!
|
|
|
|
result = e.getCode();
|
|
|
|
}
|
|
|
|
catch (std::exception& e) {
|
2014-03-14 18:30:21 +00:00
|
|
|
LOG((CLOG_CRIT "An error occurred: %s\n", e.what()));
|
2012-06-10 16:50:54 +00:00
|
|
|
}
|
|
|
|
catch (...) {
|
2014-03-14 18:30:21 +00:00
|
|
|
LOG((CLOG_CRIT "An unknown error occurred.\n"));
|
2012-06-10 16:50:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
appUtil().beforeAppExit();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-11-11 13:51:47 +00:00
|
|
|
App::daemonMainLoop(int, const char**)
|
2012-06-10 16:50:54 +00:00
|
|
|
{
|
|
|
|
#if SYSAPI_WIN32
|
2014-11-11 13:51:47 +00:00
|
|
|
SystemLogger sysLogger(daemonName(), false);
|
2012-06-10 16:50:54 +00:00
|
|
|
#else
|
2014-11-11 13:51:47 +00:00
|
|
|
SystemLogger sysLogger(daemonName(), true);
|
2012-06-10 16:50:54 +00:00
|
|
|
#endif
|
|
|
|
return mainLoop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::setupFileLogging()
|
2012-06-10 16:50:54 +00:00
|
|
|
{
|
|
|
|
if (argsBase().m_logFile != NULL) {
|
2014-11-11 13:51:47 +00:00
|
|
|
m_fileLog = new FileLogOutputter(argsBase().m_logFile);
|
2012-06-10 16:50:54 +00:00
|
|
|
CLOG->insert(m_fileLog);
|
|
|
|
LOG((CLOG_DEBUG1 "logging to file (%s) enabled", argsBase().m_logFile));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::loggingFilterWarning()
|
2012-06-10 16:50:54 +00:00
|
|
|
{
|
|
|
|
if (CLOG->getFilter() > CLOG->getConsoleMaxLevel()) {
|
|
|
|
if (argsBase().m_logFile == NULL) {
|
|
|
|
LOG((CLOG_WARN "log messages above %s are NOT sent to console (use file logging)",
|
|
|
|
CLOG->getFilterName(CLOG->getConsoleMaxLevel())));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::initApp(int argc, const char** argv)
|
2012-06-10 16:50:54 +00:00
|
|
|
{
|
|
|
|
// parse command line
|
|
|
|
parseArgs(argc, argv);
|
2015-03-04 11:15:07 +00:00
|
|
|
|
|
|
|
ARCH->setProfileDirectory(argsBase().m_profileDirectory);
|
|
|
|
ARCH->setPluginDirectory(argsBase().m_pluginDirectory);
|
2012-06-10 16:50:54 +00:00
|
|
|
|
2014-10-23 10:30:51 +00:00
|
|
|
// set log filter
|
|
|
|
if (!CLOG->setFilter(argsBase().m_logFilter)) {
|
|
|
|
LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
|
|
|
|
argsBase().m_pname, argsBase().m_logFilter, argsBase().m_pname));
|
|
|
|
m_bye(kExitArgs);
|
|
|
|
}
|
|
|
|
loggingFilterWarning();
|
|
|
|
|
|
|
|
if (argsBase().m_enableDragDrop) {
|
|
|
|
LOG((CLOG_INFO "drag and drop enabled"));
|
|
|
|
}
|
|
|
|
|
2012-06-10 16:50:54 +00:00
|
|
|
// setup file logging after parsing args
|
|
|
|
setupFileLogging();
|
|
|
|
|
|
|
|
// load configuration
|
|
|
|
loadConfig();
|
|
|
|
|
|
|
|
if (!argsBase().m_disableTray) {
|
|
|
|
|
|
|
|
// create a log buffer so we can show the latest message
|
|
|
|
// as a tray icon tooltip
|
2014-11-11 13:51:47 +00:00
|
|
|
BufferedLogOutputter* logBuffer = new BufferedLogOutputter(1000);
|
2012-06-10 16:50:54 +00:00
|
|
|
CLOG->insert(logBuffer, true);
|
|
|
|
|
|
|
|
// make the task bar receiver. the user can control this app
|
|
|
|
// through the task bar.
|
2013-06-29 14:17:49 +00:00
|
|
|
m_taskBarReceiver = m_createTaskBarReceiver(logBuffer, m_events);
|
2012-06-10 16:50:54 +00:00
|
|
|
}
|
|
|
|
}
|
2012-07-05 18:05:35 +00:00
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::initIpcClient()
|
2012-07-05 18:05:35 +00:00
|
|
|
{
|
2014-11-11 13:51:47 +00:00
|
|
|
m_ipcClient = new IpcClient(m_events, m_socketMultiplexer);
|
2012-07-05 18:05:35 +00:00
|
|
|
m_ipcClient->connect();
|
|
|
|
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->adoptHandler(
|
2014-11-11 13:51:47 +00:00
|
|
|
m_events->forIpcClient().messageReceived(), m_ipcClient,
|
|
|
|
new TMethodEventJob<App>(this, &App::handleIpcMessage));
|
2012-07-05 18:05:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::cleanupIpcClient()
|
2012-07-05 18:05:35 +00:00
|
|
|
{
|
2012-07-10 01:51:51 +00:00
|
|
|
m_ipcClient->disconnect();
|
2014-11-11 13:51:47 +00:00
|
|
|
m_events->removeHandler(m_events->forIpcClient().messageReceived(), m_ipcClient);
|
2012-07-10 01:51:51 +00:00
|
|
|
delete m_ipcClient;
|
2012-07-05 18:05:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::handleIpcMessage(const Event& e, void*)
|
2012-07-05 18:05:35 +00:00
|
|
|
{
|
2014-11-11 13:51:47 +00:00
|
|
|
IpcMessage* m = static_cast<IpcMessage*>(e.getDataObject());
|
2012-07-10 01:51:51 +00:00
|
|
|
if (m->type() == kIpcShutdown) {
|
2012-07-05 18:05:35 +00:00
|
|
|
LOG((CLOG_INFO "got ipc shutdown message"));
|
2014-11-11 13:51:47 +00:00
|
|
|
m_events->addEvent(Event(Event::kQuit));
|
2013-09-16 15:21:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 13:51:47 +00:00
|
|
|
App::runEventsLoop(void*)
|
2013-09-16 15:21:36 +00:00
|
|
|
{
|
|
|
|
m_events->loop();
|
2013-09-18 14:12:19 +00:00
|
|
|
|
|
|
|
#if defined(MAC_OS_X_VERSION_10_7)
|
|
|
|
|
|
|
|
stopCocoaLoop();
|
|
|
|
|
|
|
|
#endif
|
2012-07-05 18:05:35 +00:00
|
|
|
}
|
2014-10-27 16:39:18 +00:00
|
|
|
|
|
|
|
//
|
2014-11-11 14:50:09 +00:00
|
|
|
// MinimalApp
|
2014-10-27 16:39:18 +00:00
|
|
|
//
|
|
|
|
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::MinimalApp() :
|
|
|
|
App(NULL, NULL, new ArgsBase())
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
2015-05-06 15:36:49 +00:00
|
|
|
m_arch.init();
|
2014-10-27 16:39:18 +00:00
|
|
|
setEvents(m_events);
|
|
|
|
}
|
|
|
|
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::~MinimalApp()
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::standardStartup(int argc, char** argv)
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::startNode()
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::mainLoop()
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::foregroundStartup(int argc, char** argv)
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-11 17:45:24 +00:00
|
|
|
synergy::Screen*
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::createScreen()
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::loadConfig()
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::loadConfig(const String& pathname)
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char*
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::daemonInfo() const
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
const char*
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::daemonName() const
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-11-11 14:50:09 +00:00
|
|
|
MinimalApp::parseArgs(int argc, const char* const* argv)
|
2014-10-27 16:39:18 +00:00
|
|
|
{
|
|
|
|
}
|