• Main Page
  • Classes
  • Files
  • File List

CInputFilter.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2005 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CInputFilter.h"
00020 #include "CServer.h"
00021 #include "CPrimaryClient.h"
00022 #include "CKeyMap.h"
00023 #include "CEventQueue.h"
00024 #include "CLog.h"
00025 #include "TMethodEventJob.h"
00026 #include <cstdlib>
00027 #include <cstring>
00028 
00029 // -----------------------------------------------------------------------------
00030 // Input Filter Condition Classes
00031 // -----------------------------------------------------------------------------
00032 CInputFilter::CCondition::CCondition()
00033 {
00034     // do nothing
00035 }
00036 
00037 CInputFilter::CCondition::~CCondition()
00038 {
00039     // do nothing
00040 }
00041 
00042 void
00043 CInputFilter::CCondition::enablePrimary(CPrimaryClient*)
00044 {
00045     // do nothing
00046 }
00047 
00048 void
00049 CInputFilter::CCondition::disablePrimary(CPrimaryClient*)
00050 {
00051     // do nothing
00052 }
00053 
00054 CInputFilter::CKeystrokeCondition::CKeystrokeCondition(
00055         IPlatformScreen::CKeyInfo* info) :
00056     m_id(0),
00057     m_key(info->m_key),
00058     m_mask(info->m_mask)
00059 {
00060     free(info);
00061 }
00062 
00063 CInputFilter::CKeystrokeCondition::CKeystrokeCondition(
00064         KeyID key, KeyModifierMask mask) :
00065     m_id(0),
00066     m_key(key),
00067     m_mask(mask)
00068 {
00069     // do nothing
00070 }
00071 
00072 CInputFilter::CKeystrokeCondition::~CKeystrokeCondition()
00073 {
00074     // do nothing
00075 }
00076 
00077 KeyID
00078 CInputFilter::CKeystrokeCondition::getKey() const
00079 {
00080     return m_key;
00081 }
00082 
00083 KeyModifierMask
00084 CInputFilter::CKeystrokeCondition::getMask() const
00085 {
00086     return m_mask;
00087 }
00088 
00089 CInputFilter::CCondition*
00090 CInputFilter::CKeystrokeCondition::clone() const
00091 {
00092     return new CKeystrokeCondition(m_key, m_mask);
00093 }
00094 
00095 CString
00096 CInputFilter::CKeystrokeCondition::format() const
00097 {
00098     return CStringUtil::print("keystroke(%s)",
00099                             CKeyMap::formatKey(m_key, m_mask).c_str());
00100 }
00101 
00102 CInputFilter::EFilterStatus
00103 CInputFilter::CKeystrokeCondition::match(const CEvent& event)
00104 {
00105     EFilterStatus status;
00106 
00107     // check for hotkey events
00108     CEvent::Type type = event.getType();
00109     if (type == IPrimaryScreen::getHotKeyDownEvent()) {
00110         status = kActivate;
00111     }
00112     else if (type == IPrimaryScreen::getHotKeyUpEvent()) {
00113         status = kDeactivate;
00114     }
00115     else {
00116         return kNoMatch;
00117     }
00118 
00119     // check if it's our hotkey
00120     IPrimaryScreen::CHotKeyInfo* kinfo =
00121         reinterpret_cast<IPlatformScreen::CHotKeyInfo*>(event.getData());
00122     if (kinfo->m_id != m_id) {
00123         return kNoMatch;
00124     }
00125 
00126     return status;
00127 }
00128 
00129 void
00130 CInputFilter::CKeystrokeCondition::enablePrimary(CPrimaryClient* primary)
00131 {
00132     m_id = primary->registerHotKey(m_key, m_mask);
00133 }
00134 
00135 void
00136 CInputFilter::CKeystrokeCondition::disablePrimary(CPrimaryClient* primary)
00137 {
00138     primary->unregisterHotKey(m_id);
00139     m_id = 0;
00140 }
00141 
00142 CInputFilter::CMouseButtonCondition::CMouseButtonCondition(
00143         IPlatformScreen::CButtonInfo* info) :
00144     m_button(info->m_button),
00145     m_mask(info->m_mask)
00146 {
00147     free(info);
00148 }
00149 
00150 CInputFilter::CMouseButtonCondition::CMouseButtonCondition(
00151         ButtonID button, KeyModifierMask mask) :
00152     m_button(button),
00153     m_mask(mask)
00154 {
00155     // do nothing
00156 }
00157 
00158 CInputFilter::CMouseButtonCondition::~CMouseButtonCondition()
00159 {
00160     // do nothing
00161 }
00162 
00163 ButtonID
00164 CInputFilter::CMouseButtonCondition::getButton() const
00165 {
00166     return m_button;
00167 }
00168 
00169 KeyModifierMask
00170 CInputFilter::CMouseButtonCondition::getMask() const
00171 {
00172     return m_mask;
00173 }
00174 
00175 CInputFilter::CCondition*
00176 CInputFilter::CMouseButtonCondition::clone() const
00177 {
00178     return new CMouseButtonCondition(m_button, m_mask);
00179 }
00180 
00181 CString
00182 CInputFilter::CMouseButtonCondition::format() const
00183 {
00184     CString key = CKeyMap::formatKey(kKeyNone, m_mask);
00185     if (!key.empty()) {
00186         key += "+";
00187     }
00188     return CStringUtil::print("mousebutton(%s%d)", key.c_str(), m_button);
00189 }
00190 
00191 CInputFilter::EFilterStatus     
00192 CInputFilter::CMouseButtonCondition::match(const CEvent& event)
00193 {
00194     static const KeyModifierMask s_ignoreMask =
00195         KeyModifierAltGr | KeyModifierCapsLock |
00196         KeyModifierNumLock | KeyModifierScrollLock;
00197 
00198     EFilterStatus status;
00199 
00200     // check for hotkey events
00201     CEvent::Type type = event.getType();
00202     if (type == IPrimaryScreen::getButtonDownEvent()) {
00203         status = kActivate;
00204     }
00205     else if (type == IPrimaryScreen::getButtonUpEvent()) {
00206         status = kDeactivate;
00207     }
00208     else {
00209         return kNoMatch;
00210     }
00211 
00212     // check if it's the right button and modifiers.  ignore modifiers
00213     // that cannot be combined with a mouse button.
00214     IPlatformScreen::CButtonInfo* minfo =
00215         reinterpret_cast<IPlatformScreen::CButtonInfo*>(event.getData());
00216     if (minfo->m_button != m_button ||
00217         (minfo->m_mask & ~s_ignoreMask) != m_mask) {
00218         return kNoMatch;
00219     }
00220 
00221     return status;
00222 }
00223 
00224 CInputFilter::CScreenConnectedCondition::CScreenConnectedCondition(
00225                 const CString& screen) :
00226     m_screen(screen)
00227 {
00228     // do nothing
00229 }
00230 
00231 CInputFilter::CScreenConnectedCondition::~CScreenConnectedCondition()
00232 {
00233     // do nothing
00234 }
00235 
00236 CInputFilter::CCondition*
00237 CInputFilter::CScreenConnectedCondition::clone() const
00238 {
00239     return new CScreenConnectedCondition(m_screen);
00240 }
00241 
00242 CString
00243 CInputFilter::CScreenConnectedCondition::format() const
00244 {
00245     return CStringUtil::print("connect(%s)", m_screen.c_str());
00246 }
00247 
00248 CInputFilter::EFilterStatus
00249 CInputFilter::CScreenConnectedCondition::match(const CEvent& event)
00250 {
00251     if (event.getType() == CServer::getConnectedEvent()) {
00252         CServer::CScreenConnectedInfo* info = 
00253             reinterpret_cast<CServer::CScreenConnectedInfo*>(event.getData());
00254         if (m_screen == info->m_screen || m_screen.empty()) {
00255             return kActivate;
00256         }
00257     }
00258 
00259     return kNoMatch;
00260 }
00261 
00262 // -----------------------------------------------------------------------------
00263 // Input Filter Action Classes
00264 // -----------------------------------------------------------------------------
00265 CInputFilter::CAction::CAction()
00266 {
00267     // do nothing
00268 }
00269 
00270 CInputFilter::CAction::~CAction()
00271 {
00272     // do nothing
00273 }
00274 
00275 CInputFilter::CLockCursorToScreenAction::CLockCursorToScreenAction(Mode mode) :
00276     m_mode(mode)
00277 {
00278     // do nothing
00279 }
00280 
00281 CInputFilter::CLockCursorToScreenAction::Mode
00282 CInputFilter::CLockCursorToScreenAction::getMode() const
00283 {
00284     return m_mode;
00285 }
00286 
00287 CInputFilter::CAction*
00288 CInputFilter::CLockCursorToScreenAction::clone() const
00289 {
00290     return new CLockCursorToScreenAction(*this);
00291 }
00292 
00293 CString
00294 CInputFilter::CLockCursorToScreenAction::format() const
00295 {
00296     static const char* s_mode[] = { "off", "on", "toggle" };
00297 
00298     return CStringUtil::print("lockCursorToScreen(%s)", s_mode[m_mode]);
00299 }
00300 
00301 void
00302 CInputFilter::CLockCursorToScreenAction::perform(const CEvent& event)
00303 {
00304     static const CServer::CLockCursorToScreenInfo::State s_state[] = {
00305         CServer::CLockCursorToScreenInfo::kOff,
00306         CServer::CLockCursorToScreenInfo::kOn,
00307         CServer::CLockCursorToScreenInfo::kToggle
00308     };
00309 
00310     // send event
00311     CServer::CLockCursorToScreenInfo* info = 
00312         CServer::CLockCursorToScreenInfo::alloc(s_state[m_mode]);
00313     EVENTQUEUE->addEvent(CEvent(CServer::getLockCursorToScreenEvent(),
00314                                 event.getTarget(), info,
00315                                 CEvent::kDeliverImmediately));
00316 }
00317 
00318 CInputFilter::CSwitchToScreenAction::CSwitchToScreenAction(
00319                 const CString& screen) :
00320     m_screen(screen)
00321 {
00322     // do nothing
00323 }
00324 
00325 CString
00326 CInputFilter::CSwitchToScreenAction::getScreen() const
00327 {
00328     return m_screen;
00329 }
00330 
00331 CInputFilter::CAction*
00332 CInputFilter::CSwitchToScreenAction::clone() const
00333 {
00334     return new CSwitchToScreenAction(*this);
00335 }
00336 
00337 CString
00338 CInputFilter::CSwitchToScreenAction::format() const
00339 {
00340     return CStringUtil::print("switchToScreen(%s)", m_screen.c_str());
00341 }
00342 
00343 void
00344 CInputFilter::CSwitchToScreenAction::perform(const CEvent& event)
00345 {
00346     // pick screen name.  if m_screen is empty then use the screen from
00347     // event if it has one.
00348     CString screen = m_screen;
00349     if (screen.empty() && event.getType() == CServer::getConnectedEvent()) {
00350         CServer::CScreenConnectedInfo* info = 
00351             reinterpret_cast<CServer::CScreenConnectedInfo*>(event.getData());
00352         screen = info->m_screen;
00353     }
00354 
00355     // send event
00356     CServer::CSwitchToScreenInfo* info =
00357         CServer::CSwitchToScreenInfo::alloc(screen);
00358     EVENTQUEUE->addEvent(CEvent(CServer::getSwitchToScreenEvent(),
00359                                 event.getTarget(), info,
00360                                 CEvent::kDeliverImmediately));
00361 }
00362 
00363 CInputFilter::CSwitchInDirectionAction::CSwitchInDirectionAction(
00364                 EDirection direction) :
00365     m_direction(direction)
00366 {
00367     // do nothing
00368 }
00369 
00370 EDirection
00371 CInputFilter::CSwitchInDirectionAction::getDirection() const
00372 {
00373     return m_direction;
00374 }
00375 
00376 CInputFilter::CAction*
00377 CInputFilter::CSwitchInDirectionAction::clone() const
00378 {
00379     return new CSwitchInDirectionAction(*this);
00380 }
00381 
00382 CString
00383 CInputFilter::CSwitchInDirectionAction::format() const
00384 {
00385     static const char* s_names[] = {
00386         "",
00387         "left",
00388         "right",
00389         "up",
00390         "down"
00391     };
00392 
00393     return CStringUtil::print("switchInDirection(%s)", s_names[m_direction]);
00394 }
00395 
00396 void
00397 CInputFilter::CSwitchInDirectionAction::perform(const CEvent& event)
00398 {
00399     CServer::CSwitchInDirectionInfo* info =
00400         CServer::CSwitchInDirectionInfo::alloc(m_direction);
00401     EVENTQUEUE->addEvent(CEvent(CServer::getSwitchInDirectionEvent(),
00402                                 event.getTarget(), info,
00403                                 CEvent::kDeliverImmediately));
00404 }
00405 
00406 CInputFilter::CKeyboardBroadcastAction::CKeyboardBroadcastAction(Mode mode) :
00407     m_mode(mode)
00408 {
00409     // do nothing
00410 }
00411 
00412 CInputFilter::CKeyboardBroadcastAction::CKeyboardBroadcastAction(
00413         Mode mode,
00414         const std::set<CString>& screens) :
00415     m_mode(mode),
00416     m_screens(IKeyState::CKeyInfo::join(screens))
00417 {
00418     // do nothing
00419 }
00420 
00421 CInputFilter::CKeyboardBroadcastAction::Mode
00422 CInputFilter::CKeyboardBroadcastAction::getMode() const
00423 {
00424     return m_mode;
00425 }
00426 
00427 std::set<CString>
00428 CInputFilter::CKeyboardBroadcastAction::getScreens() const
00429 {
00430     std::set<CString> screens;
00431     IKeyState::CKeyInfo::split(m_screens.c_str(), screens);
00432     return screens;
00433 }
00434 
00435 CInputFilter::CAction*
00436 CInputFilter::CKeyboardBroadcastAction::clone() const
00437 {
00438     return new CKeyboardBroadcastAction(*this);
00439 }
00440 
00441 CString
00442 CInputFilter::CKeyboardBroadcastAction::format() const
00443 {
00444     static const char* s_mode[] = { "off", "on", "toggle" };
00445     static const char* s_name = "keyboardBroadcast";
00446 
00447     if (m_screens.empty() || m_screens[0] == '*') {
00448         return CStringUtil::print("%s(%s)", s_name, s_mode[m_mode]);
00449     }
00450     else {
00451         return CStringUtil::print("%s(%s,%.*s)", s_name, s_mode[m_mode],
00452                             m_screens.size() - 2,
00453                             m_screens.c_str() + 1);
00454     }
00455 }
00456 
00457 void
00458 CInputFilter::CKeyboardBroadcastAction::perform(const CEvent& event)
00459 {
00460     static const CServer::CKeyboardBroadcastInfo::State s_state[] = {
00461         CServer::CKeyboardBroadcastInfo::kOff,
00462         CServer::CKeyboardBroadcastInfo::kOn,
00463         CServer::CKeyboardBroadcastInfo::kToggle
00464     };
00465 
00466     // send event
00467     CServer::CKeyboardBroadcastInfo* info = 
00468         CServer::CKeyboardBroadcastInfo::alloc(s_state[m_mode], m_screens);
00469     EVENTQUEUE->addEvent(CEvent(CServer::getKeyboardBroadcastEvent(),
00470                                 event.getTarget(), info,
00471                                 CEvent::kDeliverImmediately));
00472 }
00473 
00474 CInputFilter::CKeystrokeAction::CKeystrokeAction(
00475         IPlatformScreen::CKeyInfo* info, bool press) :
00476     m_keyInfo(info),
00477     m_press(press)
00478 {
00479     // do nothing
00480 }
00481 
00482 CInputFilter::CKeystrokeAction::~CKeystrokeAction()
00483 {
00484     free(m_keyInfo);
00485 }
00486 
00487 void
00488 CInputFilter::CKeystrokeAction::adoptInfo(IPlatformScreen::CKeyInfo* info)
00489 {
00490     free(m_keyInfo);
00491     m_keyInfo = info;
00492 }
00493 
00494 const IPlatformScreen::CKeyInfo*
00495 CInputFilter::CKeystrokeAction::getInfo() const
00496 {
00497     return m_keyInfo;
00498 }
00499 
00500 bool
00501 CInputFilter::CKeystrokeAction::isOnPress() const
00502 {
00503     return m_press;
00504 }
00505 
00506 CInputFilter::CAction*
00507 CInputFilter::CKeystrokeAction::clone() const
00508 {
00509     IKeyState::CKeyInfo* info = IKeyState::CKeyInfo::alloc(*m_keyInfo);
00510     return new CKeystrokeAction(info, m_press);
00511 }
00512 
00513 CString
00514 CInputFilter::CKeystrokeAction::format() const
00515 {
00516     const char* type = formatName();
00517 
00518     if (m_keyInfo->m_screens[0] == '\0') {
00519         return CStringUtil::print("%s(%s)", type,
00520                             CKeyMap::formatKey(m_keyInfo->m_key,
00521                                 m_keyInfo->m_mask).c_str());
00522     }
00523     else if (m_keyInfo->m_screens[0] == '*') {
00524         return CStringUtil::print("%s(%s,*)", type,
00525                             CKeyMap::formatKey(m_keyInfo->m_key,
00526                                 m_keyInfo->m_mask).c_str());
00527     }
00528     else {
00529         return CStringUtil::print("%s(%s,%.*s)", type,
00530                             CKeyMap::formatKey(m_keyInfo->m_key,
00531                                 m_keyInfo->m_mask).c_str(),
00532                             strlen(m_keyInfo->m_screens + 1) - 1,
00533                             m_keyInfo->m_screens + 1);
00534     }
00535 }
00536 
00537 void
00538 CInputFilter::CKeystrokeAction::perform(const CEvent& event)
00539 {
00540     CEvent::Type type = m_press ? IPlatformScreen::getKeyDownEvent(*EVENTQUEUE) :
00541                                 IPlatformScreen::getKeyUpEvent(*EVENTQUEUE);
00542     EVENTQUEUE->addEvent(CEvent(IPlatformScreen::getFakeInputBeginEvent(),
00543                                 event.getTarget(), NULL,
00544                                 CEvent::kDeliverImmediately));
00545     EVENTQUEUE->addEvent(CEvent(type, event.getTarget(), m_keyInfo,
00546                                 CEvent::kDeliverImmediately |
00547                                 CEvent::kDontFreeData));
00548     EVENTQUEUE->addEvent(CEvent(IPlatformScreen::getFakeInputEndEvent(),
00549                                 event.getTarget(), NULL,
00550                                 CEvent::kDeliverImmediately));
00551 }
00552 
00553 const char*
00554 CInputFilter::CKeystrokeAction::formatName() const
00555 {
00556     return (m_press ? "keyDown" : "keyUp");
00557 }
00558 
00559 CInputFilter::CMouseButtonAction::CMouseButtonAction(
00560         IPlatformScreen::CButtonInfo* info, bool press) : 
00561     m_buttonInfo(info),
00562     m_press(press)
00563 {
00564     // do nothing
00565 }
00566 
00567 CInputFilter::CMouseButtonAction::~CMouseButtonAction()
00568 {
00569     free(m_buttonInfo);
00570 }
00571 
00572 const IPlatformScreen::CButtonInfo*
00573 CInputFilter::CMouseButtonAction::getInfo() const
00574 {
00575     return m_buttonInfo;
00576 }
00577 
00578 bool
00579 CInputFilter::CMouseButtonAction::isOnPress() const
00580 {
00581     return m_press;
00582 }
00583 
00584 CInputFilter::CAction*
00585 CInputFilter::CMouseButtonAction::clone() const
00586 {
00587     IPlatformScreen::CButtonInfo* info =
00588         IPrimaryScreen::CButtonInfo::alloc(*m_buttonInfo);
00589     return new CMouseButtonAction(info, m_press);
00590 }
00591 
00592 CString
00593 CInputFilter::CMouseButtonAction::format() const
00594 {
00595     const char* type = formatName();
00596 
00597     CString key = CKeyMap::formatKey(kKeyNone, m_buttonInfo->m_mask);
00598     return CStringUtil::print("%s(%s%s%d)", type,
00599                             key.c_str(), key.empty() ? "" : "+",
00600                             m_buttonInfo->m_button);
00601 }
00602 
00603 void
00604 CInputFilter::CMouseButtonAction::perform(const CEvent& event)
00605 
00606 {
00607     // send modifiers
00608     IPlatformScreen::CKeyInfo* modifierInfo = NULL;
00609     if (m_buttonInfo->m_mask != 0) {
00610         KeyID key = m_press ? kKeySetModifiers : kKeyClearModifiers;
00611         modifierInfo =
00612             IKeyState::CKeyInfo::alloc(key, m_buttonInfo->m_mask, 0, 1);
00613         EVENTQUEUE->addEvent(CEvent(IPlatformScreen::getKeyDownEvent(*EVENTQUEUE),
00614                                 event.getTarget(), modifierInfo,
00615                                 CEvent::kDeliverImmediately));
00616     }
00617 
00618     // send button
00619     CEvent::Type type = m_press ? IPlatformScreen::getButtonDownEvent() :
00620                                 IPlatformScreen::getButtonUpEvent();
00621     EVENTQUEUE->addEvent(CEvent(type, event.getTarget(), m_buttonInfo,
00622                                 CEvent::kDeliverImmediately |
00623                                 CEvent::kDontFreeData));
00624 }
00625 
00626 const char*
00627 CInputFilter::CMouseButtonAction::formatName() const
00628 {
00629     return (m_press ? "mouseDown" : "mouseUp");
00630 }
00631 
00632 //
00633 // CInputFilter::CRule
00634 //
00635 
00636 CInputFilter::CRule::CRule() :
00637     m_condition(NULL)
00638 {
00639     // do nothing
00640 }
00641 
00642 CInputFilter::CRule::CRule(CCondition* adoptedCondition) :
00643     m_condition(adoptedCondition)
00644 {
00645     // do nothing
00646 }
00647 
00648 CInputFilter::CRule::CRule(const CRule& rule) :
00649     m_condition(NULL)
00650 {
00651     copy(rule);
00652 }
00653 
00654 CInputFilter::CRule::~CRule()
00655 {
00656     clear();
00657 }
00658 
00659 CInputFilter::CRule&
00660 CInputFilter::CRule::operator=(const CRule& rule)
00661 {
00662     if (&rule != this) {
00663         copy(rule);
00664     }
00665     return *this;
00666 }
00667 
00668 void
00669 CInputFilter::CRule::clear()
00670 {
00671     delete m_condition;
00672     for (CActionList::iterator i = m_activateActions.begin();
00673                                 i != m_activateActions.end(); ++i) {
00674         delete *i;
00675     }
00676     for (CActionList::iterator i = m_deactivateActions.begin();
00677                                 i != m_deactivateActions.end(); ++i) {
00678         delete *i;
00679     }
00680 
00681     m_condition = NULL;
00682     m_activateActions.clear();
00683     m_deactivateActions.clear();
00684 }
00685 
00686 void
00687 CInputFilter::CRule::copy(const CRule& rule)
00688 {
00689     clear();
00690     if (rule.m_condition != NULL) {
00691         m_condition = rule.m_condition->clone();
00692     }
00693     for (CActionList::const_iterator i = rule.m_activateActions.begin();
00694                                 i != rule.m_activateActions.end(); ++i) {
00695         m_activateActions.push_back((*i)->clone());
00696     }
00697     for (CActionList::const_iterator i = rule.m_deactivateActions.begin();
00698                                 i != rule.m_deactivateActions.end(); ++i) {
00699         m_deactivateActions.push_back((*i)->clone());
00700     }
00701 }
00702 
00703 void
00704 CInputFilter::CRule::setCondition(CCondition* adopted)
00705 {
00706     delete m_condition;
00707     m_condition = adopted;
00708 }
00709 
00710 void
00711 CInputFilter::CRule::adoptAction(CAction* action, bool onActivation)
00712 {
00713     if (action != NULL) {
00714         if (onActivation) {
00715             m_activateActions.push_back(action);
00716         }
00717         else {
00718             m_deactivateActions.push_back(action);
00719         }
00720     }
00721 }
00722 
00723 void
00724 CInputFilter::CRule::removeAction(bool onActivation, UInt32 index)
00725 {
00726     if (onActivation) {
00727         delete m_activateActions[index];
00728         m_activateActions.erase(m_activateActions.begin() + index);
00729     }
00730     else {
00731         delete m_deactivateActions[index];
00732         m_deactivateActions.erase(m_deactivateActions.begin() + index);
00733     }
00734 }
00735 
00736 void
00737 CInputFilter::CRule::replaceAction(CAction* adopted,
00738                 bool onActivation, UInt32 index)
00739 {
00740     if (adopted == NULL) {
00741         removeAction(onActivation, index);
00742     }
00743     else if (onActivation) {
00744         delete m_activateActions[index];
00745         m_activateActions[index] = adopted;
00746     }
00747     else {
00748         delete m_deactivateActions[index];
00749         m_deactivateActions[index] = adopted;
00750     }
00751 }
00752 
00753 void
00754 CInputFilter::CRule::enable(CPrimaryClient* primaryClient)
00755 {
00756     if (m_condition != NULL) {
00757         m_condition->enablePrimary(primaryClient);
00758     }
00759 }
00760 
00761 void
00762 CInputFilter::CRule::disable(CPrimaryClient* primaryClient)
00763 {
00764     if (m_condition != NULL) {
00765         m_condition->disablePrimary(primaryClient);
00766     }
00767 }
00768 
00769 bool
00770 CInputFilter::CRule::handleEvent(const CEvent& event)
00771 {
00772     // NULL condition never matches
00773     if (m_condition == NULL) {
00774         return false;
00775     }
00776 
00777     // match
00778     const CActionList* actions;
00779     switch (m_condition->match(event)) {
00780     default:
00781         // not handled
00782         return false;
00783 
00784     case kActivate:
00785         actions = &m_activateActions;
00786         LOG((CLOG_DEBUG1 "activate actions"));
00787         break;
00788 
00789     case kDeactivate:
00790         actions = &m_deactivateActions;
00791         LOG((CLOG_DEBUG1 "deactivate actions"));
00792         break;
00793     }
00794 
00795     // perform actions
00796     for (CActionList::const_iterator i = actions->begin();
00797                                 i != actions->end(); ++i) {
00798         LOG((CLOG_DEBUG1 "hotkey: %s", (*i)->format().c_str()));
00799         (*i)->perform(event);
00800     }
00801 
00802     return true;
00803 }
00804 
00805 CString
00806 CInputFilter::CRule::format() const
00807 {
00808     CString s;
00809     if (m_condition != NULL) {
00810         // condition
00811         s += m_condition->format();
00812         s += " = ";
00813 
00814         // activate actions
00815         CActionList::const_iterator i = m_activateActions.begin();
00816         if (i != m_activateActions.end()) {
00817             s += (*i)->format();
00818             while (++i != m_activateActions.end()) {
00819                 s += ", ";
00820                 s += (*i)->format();
00821             }
00822         }
00823 
00824         // deactivate actions
00825         if (!m_deactivateActions.empty()) {
00826             s += "; ";
00827             i = m_deactivateActions.begin();
00828             if (i != m_deactivateActions.end()) {
00829                 s += (*i)->format();
00830                 while (++i != m_deactivateActions.end()) {
00831                     s += ", ";
00832                     s += (*i)->format();
00833                 }
00834             }
00835         }
00836     }
00837     return s;
00838 }
00839 
00840 const CInputFilter::CCondition*
00841 CInputFilter::CRule::getCondition() const
00842 {
00843     return m_condition;
00844 }
00845 
00846 UInt32
00847 CInputFilter::CRule::getNumActions(bool onActivation) const
00848 {
00849     if (onActivation) {
00850         return static_cast<UInt32>(m_activateActions.size());
00851     }
00852     else {
00853         return static_cast<UInt32>(m_deactivateActions.size());
00854     }
00855 }
00856 
00857 const CInputFilter::CAction&
00858 CInputFilter::CRule::getAction(bool onActivation, UInt32 index) const
00859 {
00860     if (onActivation) {
00861         return *m_activateActions[index];
00862     }
00863     else {
00864         return *m_deactivateActions[index];
00865     }
00866 }
00867 
00868 
00869 // -----------------------------------------------------------------------------
00870 // Input Filter Class
00871 // -----------------------------------------------------------------------------
00872 CInputFilter::CInputFilter() :
00873     m_primaryClient(NULL)
00874 {
00875     // do nothing
00876 }
00877 
00878 CInputFilter::CInputFilter(const CInputFilter& x) :
00879     m_ruleList(x.m_ruleList),
00880     m_primaryClient(NULL)
00881 {
00882     setPrimaryClient(x.m_primaryClient);
00883 }
00884 
00885 CInputFilter::~CInputFilter()
00886 {
00887     setPrimaryClient(NULL);
00888 }
00889 
00890 CInputFilter&
00891 CInputFilter::operator=(const CInputFilter& x)
00892 {
00893     if (&x != this) {
00894         CPrimaryClient* oldClient = m_primaryClient;
00895         setPrimaryClient(NULL);
00896 
00897         m_ruleList = x.m_ruleList;
00898 
00899         setPrimaryClient(oldClient);
00900     }
00901     return *this;
00902 }
00903 
00904 void
00905 CInputFilter::addFilterRule(const CRule& rule)
00906 {
00907     m_ruleList.push_back(rule);
00908     if (m_primaryClient != NULL) {
00909         m_ruleList.back().enable(m_primaryClient);
00910     }
00911 }
00912 
00913 void
00914 CInputFilter::removeFilterRule(UInt32 index)
00915 {
00916     if (m_primaryClient != NULL) {
00917         m_ruleList[index].disable(m_primaryClient);
00918     }
00919     m_ruleList.erase(m_ruleList.begin() + index);
00920 }
00921 
00922 CInputFilter::CRule&
00923 CInputFilter::getRule(UInt32 index)
00924 {
00925     return m_ruleList[index];
00926 }
00927 
00928 void
00929 CInputFilter::setPrimaryClient(CPrimaryClient* client)
00930 {
00931     if (m_primaryClient == client) {
00932         return;
00933     }
00934 
00935     if (m_primaryClient != NULL) {
00936         for (CRuleList::iterator rule  = m_ruleList.begin();
00937                                  rule != m_ruleList.end(); ++rule) {
00938             rule->disable(m_primaryClient);
00939         }
00940 
00941         EVENTQUEUE->removeHandler(IPlatformScreen::getKeyDownEvent(*EVENTQUEUE),
00942                             m_primaryClient->getEventTarget());
00943         EVENTQUEUE->removeHandler(IPlatformScreen::getKeyUpEvent(*EVENTQUEUE),
00944                             m_primaryClient->getEventTarget());
00945         EVENTQUEUE->removeHandler(IPlatformScreen::getKeyRepeatEvent(*EVENTQUEUE),
00946                             m_primaryClient->getEventTarget());
00947         EVENTQUEUE->removeHandler(IPlatformScreen::getButtonDownEvent(),
00948                             m_primaryClient->getEventTarget());
00949         EVENTQUEUE->removeHandler(IPlatformScreen::getButtonUpEvent(),
00950                             m_primaryClient->getEventTarget());
00951         EVENTQUEUE->removeHandler(IPlatformScreen::getHotKeyDownEvent(),
00952                             m_primaryClient->getEventTarget());
00953         EVENTQUEUE->removeHandler(IPlatformScreen::getHotKeyUpEvent(),
00954                             m_primaryClient->getEventTarget());
00955         EVENTQUEUE->removeHandler(CServer::getConnectedEvent(),
00956                             m_primaryClient->getEventTarget());
00957     }
00958 
00959     m_primaryClient = client;
00960 
00961     if (m_primaryClient != NULL) {
00962         EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyDownEvent(*EVENTQUEUE),
00963                             m_primaryClient->getEventTarget(),
00964                             new TMethodEventJob<CInputFilter>(this,
00965                                 &CInputFilter::handleEvent));
00966         EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyUpEvent(*EVENTQUEUE),
00967                             m_primaryClient->getEventTarget(),
00968                             new TMethodEventJob<CInputFilter>(this,
00969                                 &CInputFilter::handleEvent));
00970         EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyRepeatEvent(*EVENTQUEUE),
00971                             m_primaryClient->getEventTarget(),
00972                             new TMethodEventJob<CInputFilter>(this,
00973                                 &CInputFilter::handleEvent));
00974         EVENTQUEUE->adoptHandler(IPlatformScreen::getButtonDownEvent(),
00975                             m_primaryClient->getEventTarget(),
00976                             new TMethodEventJob<CInputFilter>(this,
00977                                 &CInputFilter::handleEvent));
00978         EVENTQUEUE->adoptHandler(IPlatformScreen::getButtonUpEvent(),
00979                             m_primaryClient->getEventTarget(),
00980                             new TMethodEventJob<CInputFilter>(this,
00981                                 &CInputFilter::handleEvent));
00982         EVENTQUEUE->adoptHandler(IPlatformScreen::getHotKeyDownEvent(),
00983                             m_primaryClient->getEventTarget(),
00984                             new TMethodEventJob<CInputFilter>(this,
00985                                 &CInputFilter::handleEvent));
00986         EVENTQUEUE->adoptHandler(IPlatformScreen::getHotKeyUpEvent(),
00987                             m_primaryClient->getEventTarget(),
00988                             new TMethodEventJob<CInputFilter>(this,
00989                                 &CInputFilter::handleEvent));
00990         EVENTQUEUE->adoptHandler(CServer::getConnectedEvent(),
00991                             m_primaryClient->getEventTarget(),
00992                             new TMethodEventJob<CInputFilter>(this,
00993                                 &CInputFilter::handleEvent));
00994 
00995         for (CRuleList::iterator rule  = m_ruleList.begin();
00996                                  rule != m_ruleList.end(); ++rule) {
00997             rule->enable(m_primaryClient);
00998         }
00999     }
01000 }
01001 
01002 CString
01003 CInputFilter::format(const CString& linePrefix) const
01004 {
01005     CString s;
01006     for (CRuleList::const_iterator i = m_ruleList.begin();
01007                                 i != m_ruleList.end(); ++i) {
01008         s += linePrefix;
01009         s += i->format();
01010         s += "\n";
01011     }
01012     return s;
01013 }
01014 
01015 UInt32
01016 CInputFilter::getNumRules() const
01017 {
01018     return static_cast<UInt32>(m_ruleList.size());
01019 }
01020 
01021 bool
01022 CInputFilter::operator==(const CInputFilter& x) const
01023 {
01024     // if there are different numbers of rules then we can't be equal
01025     if (m_ruleList.size() != x.m_ruleList.size()) {
01026         return false;
01027     }
01028 
01029     // compare rule lists.  the easiest way to do that is to format each
01030     // rule into a string, sort the strings, then compare the results.
01031     std::vector<CString> aList, bList;
01032     for (CRuleList::const_iterator i = m_ruleList.begin();
01033                                 i != m_ruleList.end(); ++i) {
01034         aList.push_back(i->format());
01035     }
01036     for (CRuleList::const_iterator i = x.m_ruleList.begin();
01037                                 i != x.m_ruleList.end(); ++i) {
01038         bList.push_back(i->format());
01039     }
01040     std::partial_sort(aList.begin(), aList.end(), aList.end());
01041     std::partial_sort(bList.begin(), bList.end(), bList.end());
01042     return (aList == bList);
01043 }
01044 
01045 bool
01046 CInputFilter::operator!=(const CInputFilter& x) const
01047 {
01048     return !operator==(x);
01049 }
01050 
01051 void
01052 CInputFilter::handleEvent(const CEvent& event, void*)
01053 {
01054     // copy event and adjust target
01055     CEvent myEvent(event.getType(), this, event.getData(),
01056                                 event.getFlags() | CEvent::kDontFreeData |
01057                                 CEvent::kDeliverImmediately);
01058 
01059     // let each rule try to match the event until one does
01060     for (CRuleList::iterator rule  = m_ruleList.begin();
01061                              rule != m_ruleList.end(); ++rule) {
01062         if (rule->handleEvent(myEvent)) {
01063             // handled
01064             return;
01065         }
01066     }
01067 
01068     // not handled so pass through
01069     EVENTQUEUE->addEvent(myEvent);
01070 }

Generated on Tue May 21 2013 00:00:05 for Synergy by  doxygen 1.7.1