示例#1
0
int
CClientApp::mainLoop()
{
    // create socket multiplexer.  this must happen after daemonization
    // on unix because threads evaporate across a fork().
    CSocketMultiplexer multiplexer;

    // create the event queue
    CEventQueue eventQueue;

    // start client, etc
    ARCH->util().startNode();

    // run event loop.  if startClient() failed we're supposed to retry
    // later.  the timer installed by startClient() will take care of
    // that.
    CEvent event;
    DAEMON_RUNNING(true);
    EVENTQUEUE->getEvent(event);
    while (event.getType() != CEvent::kQuit) {
        EVENTQUEUE->dispatchEvent(event);
        CEvent::deleteData(event);
        EVENTQUEUE->getEvent(event);
    }
    DAEMON_RUNNING(false);

    // close down
    LOG((CLOG_DEBUG1 "stopping client"));
    stopClient();
    updateStatus();
    LOG((CLOG_NOTE "stopped client"));

    return kExitSuccess;
}
示例#2
0
void
CEventQueue::addEvent(const CEvent& event)
{
	// discard bogus event types
	switch (event.getType()) {
	case CEvent::kUnknown:
	case CEvent::kSystem:
	case CEvent::kTimer:
		return;

	default:
		break;
	}
	
	if ((event.getFlags() & CEvent::kDeliverImmediately) != 0) {
		dispatchEvent(event);
		CEvent::deleteData(event);
	}
	else {
		CArchMutexLock lock(m_mutex);
		
		// store the event's data locally
		UInt32 eventID = saveEvent(event);
		
		// add it
		if (!m_buffer->addEvent(eventID)) {
			// failed to send event
			removeEvent(eventID);
			CEvent::deleteData(event);
		}
	}
}
示例#3
0
CInputFilter::EFilterStatus		
CInputFilter::CMouseButtonCondition::match(const CEvent& event)
{
	static const KeyModifierMask s_ignoreMask =
		KeyModifierAltGr | KeyModifierCapsLock |
		KeyModifierNumLock | KeyModifierScrollLock;

	EFilterStatus status;

	// check for hotkey events
	CEvent::Type type = event.getType();
	if (type == IPrimaryScreen::getButtonDownEvent()) {
		status = kActivate;
	}
	else if (type == IPrimaryScreen::getButtonUpEvent()) {
		status = kDeactivate;
	}
	else {
		return kNoMatch;
	}

	// check if it's the right button and modifiers.  ignore modifiers
	// that cannot be combined with a mouse button.
	IPlatformScreen::CButtonInfo* minfo =
		reinterpret_cast<IPlatformScreen::CButtonInfo*>(event.getData());
	if (minfo->m_button != m_button ||
		(minfo->m_mask & ~s_ignoreMask) != m_mask) {
		return kNoMatch;
	}

	return status;
}
示例#4
0
void
CInputFilter::sendEvent(CEvent& event)
{
	CEvent::Type type = event.getType();
	// process keyboard modifiers here
	if (type == IPlatformScreen::getKeyDownEvent() ||
		type == IPlatformScreen::getKeyUpEvent() || 
		type == IPlatformScreen::getKeyRepeatEvent()) {
		// get CKeyInfo from event
		IPlatformScreen::CKeyInfo* kinfo =
			reinterpret_cast<IPlatformScreen::CKeyInfo*>(event.getData());

		// save mask
		m_lastMask = kinfo->m_mask;

		// prepare new mask
		KeyModifierMask newMask = kinfo->m_mask;
		updateModifiers();
		newMask &= ~m_clearMask;
		newMask |= m_modifierMask;

		// set new mask
		kinfo->m_mask = newMask;
	}

	// add event to eventqueue
	EVENTQUEUE->addEvent(event);
}
示例#5
0
void
CServerApp::closeServer(CServer* server)
{
	if (server == NULL) {
		return;
	}

	// tell all clients to disconnect
	server->disconnect();

	// wait for clients to disconnect for up to timeout seconds
	double timeout = 3.0;
	CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(timeout, NULL);
	EVENTQUEUE->adoptHandler(CEvent::kTimer, timer,
		new TMethodEventJob<CServerApp>(this, &CServerApp::handleClientsDisconnected));
	EVENTQUEUE->adoptHandler(CServer::getDisconnectedEvent(), server,
		new TMethodEventJob<CServerApp>(this, &CServerApp::handleClientsDisconnected));
	CEvent event;
	EVENTQUEUE->getEvent(event);
	while (event.getType() != CEvent::kQuit) {
		EVENTQUEUE->dispatchEvent(event);
		CEvent::deleteData(event);
		EVENTQUEUE->getEvent(event);
	}
	EVENTQUEUE->removeHandler(CEvent::kTimer, timer);
	EVENTQUEUE->deleteTimer(timer);
	EVENTQUEUE->removeHandler(CServer::getDisconnectedEvent(), server);

	// done with server
	delete server;
}
示例#6
0
CInputFilter::EFilterStatus
CInputFilter::CKeystrokeCondition::match(CEvent& event, void*,
				EActionMode& outMode)
{
	// check for hotkey events
	CEvent::Type type = event.getType();
	if (type == IPrimaryScreen::getHotKeyDownEvent()) {
		outMode = kModeTurnOn;
	}
	else if (type == IPrimaryScreen::getHotKeyUpEvent()) {
		outMode = kModeTurnOff;
	}
	else {
		return kNoMatch;
	}

	// check if it's our hotkey
	IPrimaryScreen::CHotKeyInfo* kinfo =
		reinterpret_cast<IPlatformScreen::CHotKeyInfo*>(event.getData());
	if (kinfo->m_id != m_id) {
		return kNoMatch;
	}

	// convert event type for toggled conditions
	if (getActionMode() != kModePass) {
		if (type != IPlatformScreen::getHotKeyDownEvent()) {
			return kDiscard;
		}
		outMode = getActionMode();
	}
	return kMatch;
}
示例#7
0
CInputFilter::EFilterStatus
CInputFilter::CKeystrokeCondition::match(const CEvent& event)
{
	EFilterStatus status;

	// check for hotkey events
	CEvent::Type type = event.getType();
	if (type == IPrimaryScreen::getHotKeyDownEvent()) {
		status = kActivate;
	}
	else if (type == IPrimaryScreen::getHotKeyUpEvent()) {
		status = kDeactivate;
	}
	else {
		return kNoMatch;
	}

	// check if it's our hotkey
	IPrimaryScreen::CHotKeyInfo* kinfo =
		reinterpret_cast<IPlatformScreen::CHotKeyInfo*>(event.getData());
	if (kinfo->m_id != m_id) {
		return kNoMatch;
	}

	return status;
}
示例#8
0
static
int
mainLoop()
{
	// logging to files
	CFileLogOutputter* fileLog = NULL;

	if (ARG->m_logFile != NULL) {
		fileLog = new CFileLogOutputter(ARG->m_logFile);

		CLOG->insert(fileLog);

		LOG((CLOG_DEBUG1 "Logging to file (%s) enabled", ARG->m_logFile));
	}

	// create socket multiplexer.  this must happen after daemonization
	// on unix because threads evaporate across a fork().
	CSocketMultiplexer multiplexer;

	// create the event queue
	CEventQueue eventQueue;

	// start the client.  if this return false then we've failed and
	// we shouldn't retry.
	LOG((CLOG_DEBUG1 "starting client"));
	if (!startClient()) {
		return kExitFailed;
	}

	// run event loop.  if startClient() failed we're supposed to retry
	// later.  the timer installed by startClient() will take care of
	// that.
	CEvent event;
	DAEMON_RUNNING(true);
	EVENTQUEUE->getEvent(event);
	while (event.getType() != CEvent::kQuit) {
		EVENTQUEUE->dispatchEvent(event);
		CEvent::deleteData(event);
		EVENTQUEUE->getEvent(event);
	}
	DAEMON_RUNNING(false);

	// close down
	LOG((CLOG_DEBUG1 "stopping client"));
	stopClient();
	updateStatus();
	LOG((CLOG_NOTE "stopped client"));

	if (fileLog) {
		CLOG->remove(fileLog);
		delete fileLog;		
	}

	return kExitSuccess;
}
示例#9
0
void
CEventQueue::loop()
{
	CEvent event;
	getEvent(event);
	while (event.getType() != CEvent::kQuit) {
		dispatchEvent(event);
		CEvent::deleteData(event);
		getEvent(event);
	}
}
示例#10
0
void
CPacketStreamFilter::filterEvent(const CEvent& event)
{
    if (event.getType() == getInputReadyEvent()) {
        CLock lock(&m_mutex);
        if (!readMore()) {
            return;
        }
    }
    else if (event.getType() == getInputShutdownEvent()) {
        // discard this if we have buffered data
        CLock lock(&m_mutex);
        m_inputShutdown = true;
        if (m_size != 0) {
            return;
        }
    }

    // pass event
    CStreamFilter::filterEvent(event);
}
示例#11
0
CInputFilter::EFilterStatus
CInputFilter::CScreenConnectedCondition::match(const CEvent& event)
{
	if (event.getType() == CServer::getConnectedEvent()) {
		CServer::CScreenConnectedInfo* info = 
			reinterpret_cast<CServer::CScreenConnectedInfo*>(event.getData());
		if (m_screen == info->m_screen || m_screen.empty()) {
			return kActivate;
		}
	}

	return kNoMatch;
}
示例#12
0
void
CDaemonApp::mainLoop(bool logToFile)
{
	try
	{
		DAEMON_RUNNING(true);

		if (logToFile)
			CLOG->insert(new CFileLogOutputter(logPath().c_str()));

		CEventQueue eventQueue;

#if SYSAPI_WIN32
		// HACK: create a dummy screen, which can handle system events 
		// (such as a stop request from the service controller).
		CMSWindowsScreen::init(CArchMiscWindows::instanceWin32());
		CScreen dummyScreen(new CMSWindowsScreen(false, true, false));

		string command = ARCH->setting("Command");
		if (command != "") {
			LOG((CLOG_INFO "using last known command: %s", command.c_str()));
			m_relauncher.command(command);
		}

		m_relauncher.startAsync();
#endif

		CEvent event;
		EVENTQUEUE->getEvent(event);
		while (event.getType() != CEvent::kQuit) {
			EVENTQUEUE->dispatchEvent(event);
			CEvent::deleteData(event);
			EVENTQUEUE->getEvent(event);
		}

#if SYSAPI_WIN32
		m_relauncher.stop();
#endif

		DAEMON_RUNNING(false);
	}
	catch (XArch& e) {
		LOG((CLOG_ERR, e.what().c_str()));
	}
	catch (std::exception& e) {
		LOG((CLOG_ERR, e.what()));
	}
	catch (...) {
		LOG((CLOG_ERR, "Unrecognized error."));
	}
}
示例#13
0
bool
CEventQueue::dispatchEvent(const CEvent& event)
{
	void* target   = event.getTarget();
	IEventJob* job = getHandler(event.getType(), target);
	if (job == NULL) {
		job = getHandler(CEvent::kUnknown, target);
	}
	if (job != NULL) {
		job->run(event);
		return true;
	}
	return false;
}
示例#14
0
void
CEvent::deleteData(const CEvent& event)
{
	switch (event.getType()) {
	case kUnknown:
	case kQuit:
	case kSystem:
	case kTimer:
		break;

	default:
		free(event.getData());
		break;
	}
}
示例#15
0
void
CInputFilter::handleEvent(const CEvent& event, void* arg)
{
	// get a modifiable copy of this event.
	// set target to us, set kDontFreeData and kDeliverImmediately because the
	// original event will be destroyed after this method exits.
	CEvent evt(event.getType(), this, event.getData(),
								event.getFlags() | CEvent::kDontFreeData |
								CEvent::kDeliverImmediately);

	// clear dirty flag
	m_dirtyFlag = kNotDirty;

	EActionMode	actionMode = kModePass;
	// match event against filter rules and perform actions
	for (CRuleList::iterator rule  = m_ruleList.begin();
							 rule != m_ruleList.end(); ++rule) {
		EFilterStatus conditionStatus;
		EFilterStatus actionStatus;
		conditionStatus = rule->first->match(evt, arg, actionMode);
		if (conditionStatus == kDiscard) {
			return;
		}
		else if (conditionStatus == kNoMatch) {
			continue;
		}

		actionStatus = rule->second->perform(evt, arg, actionMode);
		if (actionStatus == kDiscard) {
			// discard event
			return;
		}
		else if (actionStatus == kNotHandled) {
			continue;
		}
		else if (actionStatus == kUpdateModifiers) {
			updateModifiers();
			return;
		}

		// if we got here then the rule has matched and action returned
		// kHandled, so send the event.
		break;
	}

	sendEvent(evt);
}
示例#16
0
void
CEvent::deleteData(const CEvent& event)
{
	switch (event.getType()) {
	case kUnknown:
	case kQuit:
	case kSystem:
	case kTimer:
		break;

	default:
		if ((event.getFlags() & kDontFreeData) == 0) {
			free(event.getData());
			delete event.getDataObject();
		}
		break;
	}
}
示例#17
0
void
CInputFilter::CSwitchToScreenAction::perform(const CEvent& event)
{
	// pick screen name.  if m_screen is empty then use the screen from
	// event if it has one.
	CString screen = m_screen;
	if (screen.empty() && event.getType() == CServer::getConnectedEvent()) {
		CServer::CScreenConnectedInfo* info = 
			reinterpret_cast<CServer::CScreenConnectedInfo*>(event.getData());
		screen = info->m_screen;
	}

	// send event
	CServer::CSwitchToScreenInfo* info =
		CServer::CSwitchToScreenInfo::alloc(screen);
	EVENTQUEUE->addEvent(CEvent(CServer::getSwitchToScreenEvent(),
								event.getTarget(), info,
								CEvent::kDeliverImmediately));
}
示例#18
0
void
CInputFilter::handleEvent(const CEvent& event, void*)
{
	// copy event and adjust target
	CEvent myEvent(event.getType(), this, event.getData(),
								event.getFlags() | CEvent::kDontFreeData |
								CEvent::kDeliverImmediately);

	// let each rule try to match the event until one does
	for (CRuleList::iterator rule  = m_ruleList.begin();
							 rule != m_ruleList.end(); ++rule) {
		if (rule->handleEvent(myEvent)) {
			// handled
			return;
		}
	}

	// not handled so pass through
	EVENTQUEUE->addEvent(myEvent);
}
示例#19
0
CInputFilter::EFilterStatus		
CInputFilter::CMouseButtonCondition::match(CEvent& event, void*,
				EActionMode& outMode)
{
	// check for hotkey events
	bool down;
	CEvent::Type type = event.getType();
	if (type == IPrimaryScreen::getButtonDownEvent()) {
		outMode = kModeTurnOn;
		down    = true;
	}
	else if (type == IPrimaryScreen::getButtonUpEvent()) {
		outMode = kModeTurnOff;
		down    = false;
	}
	else {
		return kNoMatch;
	}

	// check if it's the right button and modifiers
	IPlatformScreen::CButtonInfo* minfo =
		reinterpret_cast<IPlatformScreen::CButtonInfo*>(event.getData());
	if (minfo->m_button != m_button || getLastMask() != m_mask) {
		return kNoMatch;
	}

	// convert event type for toggled conditions
	if (getActionMode() != kModePass) {
		if (type != IPlatformScreen::getButtonDownEvent()) {
			return kDiscard;
		}
		outMode = getActionMode();
	}

	setClearMask(down ? m_mask : 0);
	return kMatch;
}
示例#20
0
void
CStreamFilter::filterEvent(const CEvent& event)
{
	EVENTQUEUE->dispatchEvent(CEvent(event.getType(),
						getEventTarget(), event.getData()));
}
示例#21
0
int CServerApp::mainLoop()
{
	// create socket multiplexer.  this must happen after daemonization
	// on unix because threads evaporate across a fork().
	CSocketMultiplexer multiplexer;

	// create the event queue
	CEventQueue eventQueue;

	// if configuration has no screens then add this system
	// as the default
	if (args().m_config->begin() == args().m_config->end()) {
		args().m_config->addScreen(args().m_name);
	}

	// set the contact address, if provided, in the config.
	// otherwise, if the config doesn't have an address, use
	// the default.
	if (args().m_synergyAddress->isValid()) {
		args().m_config->setSynergyAddress(*args().m_synergyAddress);
	}
	else if (!args().m_config->getSynergyAddress().isValid()) {
		args().m_config->setSynergyAddress(CNetworkAddress(kDefaultPort));
	}

	// canonicalize the primary screen name
	CString primaryName = args().m_config->getCanonicalName(args().m_name);
	if (primaryName.empty()) {
		LOG((CLOG_CRIT "unknown screen name `%s'", args().m_name.c_str()));
		return kExitFailed;
	}

	// start server, etc
	ARCH->util().startNode();

	// handle hangup signal by reloading the server's configuration
	ARCH->setSignalHandler(CArch::kHANGUP, &reloadSignalHandler, NULL);
	EVENTQUEUE->adoptHandler(getReloadConfigEvent(),
		IEventQueue::getSystemTarget(),
		new TMethodEventJob<CServerApp>(this, &CServerApp::reloadConfig));

	// handle force reconnect event by disconnecting clients.  they'll
	// reconnect automatically.
	EVENTQUEUE->adoptHandler(getForceReconnectEvent(),
		IEventQueue::getSystemTarget(),
		new TMethodEventJob<CServerApp>(this, &CServerApp::forceReconnect));

	// to work around the sticky meta keys problem, we'll give users
	// the option to reset the state of synergys
	EVENTQUEUE->adoptHandler(getResetServerEvent(),
		IEventQueue::getSystemTarget(),
		new TMethodEventJob<CServerApp>(this, &CServerApp::resetServer));

	// run event loop.  if startServer() failed we're supposed to retry
	// later.  the timer installed by startServer() will take care of
	// that.
	CEvent event;
	DAEMON_RUNNING(true);
	EVENTQUEUE->getEvent(event);
	while (event.getType() != CEvent::kQuit) {
		EVENTQUEUE->dispatchEvent(event);
		CEvent::deleteData(event);
		EVENTQUEUE->getEvent(event);
	}
	DAEMON_RUNNING(false);

	// close down
	LOG((CLOG_DEBUG1 "stopping server"));
	EVENTQUEUE->removeHandler(getForceReconnectEvent(),
		IEventQueue::getSystemTarget());
	EVENTQUEUE->removeHandler(getReloadConfigEvent(),
		IEventQueue::getSystemTarget());
	cleanupServer();
	updateStatus();
	LOG((CLOG_NOTE "stopped server"));

	return kExitSuccess;
}