友人にSynergyを紹介していて、自分でも非常に便利なソフトだとおもったので、その仕組みを知る為にソースコードを読んでいました。読んだといっても核心の部分だけで、具体的にタイマーの処理だとかの部分は読んでいません。仕組みが知りたかっただけなので。
まず、読み始めたのはcmd/synergys/synergys.cppのmainです。これはソースコード名からも解るようにsynergyのサーバーの処理のmainのようです。
result = run(argc, argv, NULL, &standardStartup);
という部分があり、runの中ではstarndardStartupを実行しているようです。そこで、standardStartupを追っていきます。すると、mainLoop()に処理が投げられている事が解ります。
else { return mainLoop(); }
ではmainLoop()の中を追ってきます。内部ではMutexなどを作ったり、 ディスプレイ名のCanonicalizeをしたりして、
EVENTQUEUE->getEvent(event);
while (event.getType() != CEvent::kQuit) {
EVENTQUEUE->dispatchEvent(event);
CEvent::deleteData(event);
EVENTQUEUE->getEvent(event);
}
という部分にたどり着きます。見れば解るようにeventをdispatchしている部分のようです。dispatchEventを追ってみましょう。
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; }
この様な処理です。getHandlerという物がevenのTypeに併せてハンドルを返し、それをrunしているようですね。
ではgetHandlerはどのように処理を見つけているのでしょう。
CEventQueue::getHandler(CEvent::Type type, void* target) const { CArchMutexLock lock(m_mutex); CHandlerTable::const_iterator index = m_handlers.find(target); if (index != m_handlers.end()) { const CTypeHandlerTable& typeHandlers = index->second; CTypeHandlerTable::const_iterator index2 = typeHandlers.find(type); if (index2 != typeHandlers.end()) { return index2->second; } } return NULL; }
このような処理のようです。CHandlerTableに登録されている物をfindしているようですね。ではどの様な記述で登録しているのでしょうか?
CEventQueue::adoptHandler(CEvent::Type type, void* target, IEventJob* handler) { CArchMutexLock lock(m_mutex); IEventJob*& job = m_handlers[target][type]; delete job; job = handler; }
名前から察するにこの辺りですね。見ると同じm_handlersというのが登場しています。
これでどのような部分をgrepすれば具体的にイベントの定義が行われているか解りました。では
grep 'EVENTQUEUE->adoptHandler' **/*.{c,h,cpp} | lv
して、どの様なイベントがあるか確認しましょう。
ちょっと長くなったので一旦この記事はここまでです。