1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 #include "errormessage.h"
11 #include "windowstool.h"
19 void Engine::checkFocusWindow()
26 HWND hwndFore = GetForegroundWindow();
27 DWORD threadId = GetWindowThreadProcessId(hwndFore, NULL);
33 if (m_currentFocusOfThread &&
34 m_currentFocusOfThread->m_threadId == threadId &&
35 m_currentFocusOfThread->m_hwndFocus == m_hwndFocus)
38 m_emacsEditKillLine.reset();
41 if (!m_detachedThreadIds.empty())
43 for (DetachedThreadIds::iterator i = m_detachedThreadIds.begin();
44 i != m_detachedThreadIds.end(); i ++)
46 FocusOfThreads::iterator j = m_focusOfThreads.find((*i));
47 if (j != m_focusOfThreads.end())
49 FocusOfThread *fot = &((*j).second);
51 m_log << _T("RemoveThread") << std::endl;
52 m_log << _T("\tHWND:\t") << std::hex << (int)fot->m_hwndFocus
53 << std::dec << std::endl;
54 m_log << _T("\tTHREADID:") << fot->m_threadId << std::endl;
55 m_log << _T("\tCLASS:\t") << fot->m_className << std::endl;
56 m_log << _T("\tTITLE:\t") << fot->m_titleName << std::endl;
58 m_focusOfThreads.erase(j);
61 m_detachedThreadIds.erase
62 (m_detachedThreadIds.begin(), m_detachedThreadIds.end());
65 FocusOfThreads::iterator i = m_focusOfThreads.find(threadId);
66 if (i != m_focusOfThreads.end())
68 m_currentFocusOfThread = &((*i).second);
69 if (!m_currentFocusOfThread->m_isConsole || 2 <= count)
71 if (m_currentFocusOfThread->m_keymaps.empty())
72 setCurrentKeymap(NULL);
74 setCurrentKeymap(*m_currentFocusOfThread->m_keymaps.begin());
75 m_hwndFocus = m_currentFocusOfThread->m_hwndFocus;
76 checkShow(m_hwndFocus);
79 m_log << _T("FocusChanged") << std::endl;
80 m_log << _T("\tHWND:\t")
81 << std::hex << (int)m_currentFocusOfThread->m_hwndFocus
82 << std::dec << std::endl;
83 m_log << _T("\tTHREADID:")
84 << m_currentFocusOfThread->m_threadId << std::endl;
85 m_log << _T("\tCLASS:\t")
86 << m_currentFocusOfThread->m_className << std::endl;
87 m_log << _T("\tTITLE:\t")
88 << m_currentFocusOfThread->m_titleName << std::endl;
95 _TCHAR className[GANA_MAX_ATOM_LENGTH];
96 if (GetClassName(hwndFore, className, NUMBER_OF(className)))
98 if (_tcsicmp(className, _T("ConsoleWindowClass")) == 0)
100 _TCHAR titleName[1024];
101 if (GetWindowText(hwndFore, titleName, NUMBER_OF(titleName)) == 0)
102 titleName[0] = _T('\0');
103 setFocus(hwndFore, threadId, className, titleName, true);
104 Acquire a(&m_log, 1);
105 m_log << _T("HWND:\t") << std::hex << reinterpret_cast<int>(hwndFore)
106 << std::dec << std::endl;
107 m_log << _T("THREADID:") << threadId << std::endl;
108 m_log << _T("CLASS:\t") << className << std::endl;
109 m_log << _T("TITLE:\t") << titleName << std::endl << std::endl;
116 if (m_globalFocus.m_keymaps.empty())
118 Acquire a(&m_log, 1);
119 m_log << _T("NO GLOBAL FOCUS") << std::endl;
120 m_currentFocusOfThread = NULL;
121 setCurrentKeymap(NULL);
125 if (m_currentFocusOfThread != &m_globalFocus)
127 Acquire a(&m_log, 1);
128 m_log << _T("GLOBAL FOCUS") << std::endl;
129 m_currentFocusOfThread = &m_globalFocus;
130 setCurrentKeymap(m_globalFocus.m_keymaps.front());
138 // is modifier pressed ?
139 bool Engine::isPressed(Modifier::Type i_mt)
141 const Keymap::ModAssignments &ma = m_currentKeymap->getModAssignments(i_mt);
142 for (Keymap::ModAssignments::const_iterator i = ma.begin();
144 if ((*i).m_key->m_isPressed)
150 // fix modifier key (if fixed, return true)
151 bool Engine::fixModifierKey(ModifiedKey *io_mkey, Keymap::AssignMode *o_am)
153 // for all modifier ...
154 for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
156 // get modifier assignments (list of modifier keys)
157 const Keymap::ModAssignments &ma =
158 m_currentKeymap->getModAssignments(static_cast<Modifier::Type>(i));
160 for (Keymap::ModAssignments::const_iterator
161 j = ma.begin(); j != ma.end(); ++ j)
162 if (io_mkey->m_key == (*j).m_key) // is io_mkey a modifier ?
165 Acquire a(&m_log, 1);
166 m_log << _T("* Modifier Key") << std::endl;
168 // set dontcare for this modifier
169 io_mkey->m_modifier.dontcare(static_cast<Modifier::Type>(i));
170 *o_am = (*j).m_assignMode;
174 *o_am = Keymap::AM_notModifier;
180 void Engine::outputToLog(const Key *i_key, const ModifiedKey &i_mkey,
184 Acquire a(&m_log, i_debugLevel);
187 for (i = 0; i < i_key->getScanCodesSize(); ++ i)
189 if (i_key->getScanCodes()[i].m_flags & ScanCode::E0) m_log << _T("E0-");
190 if (i_key->getScanCodes()[i].m_flags & ScanCode::E1) m_log << _T("E1-");
191 if (!(i_key->getScanCodes()[i].m_flags & ScanCode::E0E1))
193 m_log << _T("0x") << std::hex << std::setw(2) << std::setfill(_T('0'))
194 << static_cast<int>(i_key->getScanCodes()[i].m_scan)
195 << std::dec << _T(" ");
198 if (!i_mkey.m_key) // key corresponds to no phisical key
204 m_log << _T(" ") << i_mkey << std::endl;
209 void Engine::describeBindings()
211 Acquire a(&m_log, 0);
213 Keymap::DescribeParam dp;
214 for (KeymapPtrList::iterator i = m_currentFocusOfThread->m_keymaps.begin();
215 i != m_currentFocusOfThread->m_keymaps.end(); ++ i)
216 (*i)->describe(m_log, &dp);
221 // update m_lastPressedKey
222 void Engine::updateLastPressedKey(Key *i_key)
224 m_lastPressedKey[1] = m_lastPressedKey[0];
225 m_lastPressedKey[0] = i_key;
228 // set current keymap
229 void Engine::setCurrentKeymap(const Keymap *i_keymap, bool i_doesAddToHistory)
231 if (i_doesAddToHistory)
233 m_keymapPrefixHistory.push_back(const_cast<Keymap *>(m_currentKeymap));
234 if (MAX_KEYMAP_PREFIX_HISTORY < m_keymapPrefixHistory.size())
235 m_keymapPrefixHistory.pop_front();
238 m_keymapPrefixHistory.clear();
239 m_currentKeymap = i_keymap;
243 // get current modifiers
244 Modifier Engine::getCurrentModifiers(Key *i_key, bool i_isPressed)
247 cmods.add(m_currentLock);
249 cmods.press(Modifier::Type_Shift , isPressed(Modifier::Type_Shift ));
250 cmods.press(Modifier::Type_Alt , isPressed(Modifier::Type_Alt ));
251 cmods.press(Modifier::Type_Control, isPressed(Modifier::Type_Control));
252 cmods.press(Modifier::Type_Windows, isPressed(Modifier::Type_Windows));
253 cmods.press(Modifier::Type_Up , !i_isPressed);
254 cmods.press(Modifier::Type_Down , i_isPressed);
256 cmods.press(Modifier::Type_Repeat , false);
257 if (m_lastPressedKey[0] == i_key)
260 cmods.press(Modifier::Type_Repeat, true);
262 if (m_lastPressedKey[1] == i_key)
263 cmods.press(Modifier::Type_Repeat, true);
266 for (int i = Modifier::Type_Mod0; i <= Modifier::Type_Mod9; ++ i)
267 cmods.press(static_cast<Modifier::Type>(i),
268 isPressed(static_cast<Modifier::Type>(i)));
274 // generate keyboard event for a key
275 void Engine::generateKeyEvent(Key *i_key, bool i_doPress, bool i_isByAssign)
277 // check if key is event
278 bool isEvent = false;
279 for (Key **e = Event::events; *e; ++ e)
286 bool isAlreadyReleased = false;
290 if (i_doPress && !i_key->m_isPressedOnWin32)
291 ++ m_currentKeyPressCountOnWin32;
294 if (i_key->m_isPressedOnWin32)
295 -- m_currentKeyPressCountOnWin32;
297 isAlreadyReleased = true;
299 i_key->m_isPressedOnWin32 = i_doPress;
302 i_key->m_isPressedByAssign = i_doPress;
304 Key *sync = m_setting->m_keyboard.getSyncKey();
306 if (!isAlreadyReleased || i_key == sync)
308 KEYBOARD_INPUT_DATA kid = { 0, 0, 0, 0, 0 };
309 const ScanCode *sc = i_key->getScanCodes();
310 for (size_t i = 0; i < i_key->getScanCodesSize(); ++ i)
312 kid.MakeCode = sc[i].m_scan;
313 kid.Flags = sc[i].m_flags;
315 kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;
317 injectInput(&kid, NULL);
320 WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);
321 CHECK_TRUE( GetOverlappedResult(m_device, &m_ol, &len, TRUE) );
325 m_lastGeneratedKey = i_doPress ? i_key : NULL;
330 Acquire a(&m_log, 1);
331 m_log << _T("\t\t =>\t");
332 if (isAlreadyReleased)
333 m_log << _T("(already released) ");
335 ModifiedKey mkey(i_key);
336 mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);
337 mkey.m_modifier.on(Modifier::Type_Down, i_doPress);
338 outputToLog(i_key, mkey, 1);
343 void Engine::generateEvents(Current i_c, const Keymap *i_keymap, Key *i_event)
346 i_c.m_keymap = i_keymap;
347 i_c.m_mkey.m_key = i_event;
348 if (const Keymap::KeyAssignment *keyAssign =
349 i_c.m_keymap->searchAssignment(i_c.m_mkey))
352 Acquire a(&m_log, 1);
353 m_log << std::endl << _T(" ")
354 << i_event->getName() << std::endl;
356 generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);
361 // genete modifier events
362 void Engine::generateModifierEvents(const Modifier &i_mod)
365 Acquire a(&m_log, 1);
366 m_log << _T("* Gen Modifiers\t{") << std::endl;
369 for (int i = Modifier::Type_begin; i < Modifier::Type_BASIC; ++ i)
371 Keyboard::Mods &mods =
372 m_setting->m_keyboard.getModifiers(static_cast<Modifier::Type>(i));
374 if (i_mod.isDontcare(static_cast<Modifier::Type>(i)))
375 // no need to process
377 else if (i_mod.isPressed(static_cast<Modifier::Type>(i)))
378 // we have to press this modifier
380 bool noneIsPressed = true;
381 bool noneIsPressedByAssign = true;
382 for (Keyboard::Mods::iterator i = mods.begin(); i != mods.end(); ++ i)
384 if ((*i)->m_isPressedOnWin32)
385 noneIsPressed = false;
386 if ((*i)->m_isPressedByAssign)
387 noneIsPressedByAssign = false;
391 if (noneIsPressedByAssign)
392 generateKeyEvent(mods.front(), true, false);
394 for (Keyboard::Mods::iterator
395 i = mods.begin(); i != mods.end(); ++ i)
396 if ((*i)->m_isPressedByAssign)
397 generateKeyEvent((*i), true, false);
402 // we have to release this modifier
404 // avoid such sequences as "Alt U-ALt" or "Windows U-Windows"
405 if (i == Modifier::Type_Alt || i == Modifier::Type_Windows)
407 for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)
408 if ((*j) == m_lastGeneratedKey)
410 Keyboard::Mods *mods =
411 &m_setting->m_keyboard.getModifiers(Modifier::Type_Shift);
412 if (mods->size() == 0)
413 mods = &m_setting->m_keyboard.getModifiers(
414 Modifier::Type_Control);
415 if (0 < mods->size())
417 generateKeyEvent(mods->front(), true, false);
418 generateKeyEvent(mods->front(), false, false);
424 for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)
426 if ((*j)->m_isPressedOnWin32)
427 generateKeyEvent((*j), false, false);
433 Acquire a(&m_log, 1);
434 m_log << _T("\t\t}") << std::endl;
439 // generate keyboard events for action
440 void Engine::generateActionEvents(const Current &i_c, const Action *i_a,
443 switch (i_a->getType())
446 case Action::Type_key:
448 const ModifiedKey &mkey
449 = reinterpret_cast<ActionKey *>(
450 const_cast<Action *>(i_a))->m_modifiedKey;
454 (mkey.m_modifier.isOn(Modifier::Type_Up) ||
455 mkey.m_modifier.isDontcare(Modifier::Type_Up)))
456 generateKeyEvent(mkey.m_key, false, true);
459 else if (i_doPress &&
460 (mkey.m_modifier.isOn(Modifier::Type_Down) ||
461 mkey.m_modifier.isDontcare(Modifier::Type_Down)))
463 Modifier modifier = mkey.m_modifier;
464 modifier.add(i_c.m_mkey.m_modifier);
465 generateModifierEvents(modifier);
466 generateKeyEvent(mkey.m_key, true, true);
472 case Action::Type_keySeq:
474 const ActionKeySeq *aks = reinterpret_cast<const ActionKeySeq *>(i_a);
475 generateKeySeqEvents(i_c, aks->m_keySeq,
476 i_doPress ? Part_down : Part_up);
481 case Action::Type_function:
483 const ActionFunction *af = reinterpret_cast<const ActionFunction *>(i_a);
484 bool is_up = (!i_doPress &&
485 (af->m_modifier.isOn(Modifier::Type_Up) ||
486 af->m_modifier.isDontcare(Modifier::Type_Up)));
487 bool is_down = (i_doPress &&
488 (af->m_modifier.isOn(Modifier::Type_Down) ||
489 af->m_modifier.isDontcare(Modifier::Type_Down)));
491 if (!is_down && !is_up)
495 Acquire a(&m_log, 1);
496 m_log << _T("\t\t >\t") << af->m_functionData;
500 param.m_isPressed = i_doPress;
501 param.m_hwnd = m_currentFocusOfThread->m_hwndFocus;
503 param.m_doesNeedEndl = true;
506 param.m_c.m_mkey.m_modifier.on(Modifier::Type_Up, !i_doPress);
507 param.m_c.m_mkey.m_modifier.on(Modifier::Type_Down, i_doPress);
509 af->m_functionData->exec(this, ¶m);
511 if (param.m_doesNeedEndl)
513 Acquire a(&m_log, 1);
522 // generate keyboard events for keySeq
523 void Engine::generateKeySeqEvents(const Current &i_c, const KeySeq *i_keySeq,
526 const KeySeq::Actions &actions = i_keySeq->getActions();
529 if (i_part == Part_up)
530 generateActionEvents(i_c, actions[actions.size() - 1], false);
534 for (i = 0 ; i < actions.size() - 1; ++ i)
536 generateActionEvents(i_c, actions[i], true);
537 generateActionEvents(i_c, actions[i], false);
539 generateActionEvents(i_c, actions[i], true);
540 if (i_part == Part_all)
541 generateActionEvents(i_c, actions[i], false);
546 // generate keyboard events for current key
547 void Engine::generateKeyboardEvents(const Current &i_c)
549 if (++ m_generateKeyboardEventsRecursionGuard ==
550 MAX_GENERATE_KEYBOARD_EVENTS_RECURSION_COUNT)
553 m_log << _T("error: too deep keymap recursion. there may be a loop.")
558 const Keymap::KeyAssignment *keyAssign
559 = i_c.m_keymap->searchAssignment(i_c.m_mkey);
562 const KeySeq *keySeq = i_c.m_keymap->getDefaultKeySeq();
564 generateKeySeqEvents(i_c, keySeq, i_c.isPressed() ? Part_down : Part_up);
568 if (keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Up) ||
569 keyAssign->m_modifiedKey.m_modifier.isOn(Modifier::Type_Down))
570 generateKeySeqEvents(i_c, keyAssign->m_keySeq, Part_all);
572 generateKeySeqEvents(i_c, keyAssign->m_keySeq,
573 i_c.isPressed() ? Part_down : Part_up);
575 m_generateKeyboardEventsRecursionGuard --;
579 // generate keyboard events for current key
580 void Engine::beginGeneratingKeyboardEvents(
581 const Current &i_c, bool i_isModifier)
583 // (1) (2) (3) (4) (1)
584 // up/down: D- U- D- U- D-
585 // keymap: m_currentKeymap m_currentKeymap X X m_currentKeymap
586 // memo: &Prefix(X) ... ... ... ...
587 // m_isPrefix: false true true false false
591 bool isPhysicallyPressed
592 = cnew.m_mkey.m_modifier.isPressed(Modifier::Type_Down);
595 ModifiedKey mkey = m_setting->m_keyboard.searchSubstitute(cnew.m_mkey);
599 if (isPhysicallyPressed)
601 cnew.m_mkey.m_modifier.off(Modifier::Type_Up);
602 cnew.m_mkey.m_modifier.on(Modifier::Type_Down);
606 cnew.m_mkey.m_modifier.on(Modifier::Type_Up);
607 cnew.m_mkey.m_modifier.off(Modifier::Type_Down);
609 for (int i = Modifier::Type_begin; i != Modifier::Type_end; ++ i)
611 Modifier::Type type = static_cast<Modifier::Type>(i);
612 if (cnew.m_mkey.m_modifier.isDontcare(type) &&
613 !i_c.m_mkey.m_modifier.isDontcare(type))
614 cnew.m_mkey.m_modifier.press(
615 type, i_c.m_mkey.m_modifier.isPressed(type));
619 Acquire a(&m_log, 1);
620 m_log << _T("* substitute") << std::endl;
622 outputToLog(mkey.m_key, cnew.m_mkey, 1);
626 const Keymap *tmpKeymap = m_currentKeymap;
627 if (i_isModifier || !m_isPrefix) ;
628 else if (isPhysicallyPressed) // when (3)
630 else if (!isPhysicallyPressed) // when (2)
631 m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();
633 // for m_emacsEditKillLine function
634 m_emacsEditKillLine.m_doForceReset = !i_isModifier;
636 // generate key event !
637 m_generateKeyboardEventsRecursionGuard = 0;
638 if (isPhysicallyPressed)
639 generateEvents(cnew, cnew.m_keymap, &Event::before_key_down);
640 generateKeyboardEvents(cnew);
641 if (!isPhysicallyPressed)
642 generateEvents(cnew, cnew.m_keymap, &Event::after_key_up);
644 // for m_emacsEditKillLine function
645 if (m_emacsEditKillLine.m_doForceReset)
646 m_emacsEditKillLine.reset();
651 else if (!m_isPrefix) // when (1), (4)
652 m_currentKeymap = m_currentFocusOfThread->m_keymaps.front();
653 else if (!isPhysicallyPressed) // when (2)
654 m_currentKeymap = tmpKeymap;
659 unsigned int Engine::injectInput(const KEYBOARD_INPUT_DATA *i_kid, const KBDLLHOOKSTRUCT *i_kidRaw)
662 kid.type = INPUT_KEYBOARD;
664 kid.ki.wScan = i_kid->MakeCode;
665 kid.ki.dwFlags = KEYEVENTF_SCANCODE;
666 kid.ki.time = i_kidRaw ? i_kidRaw->time : 0;
667 kid.ki.dwExtraInfo = i_kidRaw ? i_kidRaw->dwExtraInfo : 0;
668 if (i_kid->Flags & KEYBOARD_INPUT_DATA::BREAK)
670 kid.ki.dwFlags |= KEYEVENTF_KEYUP;
672 if (i_kid->Flags & KEYBOARD_INPUT_DATA::E0)
674 kid.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
676 SendInput(1, &kid, sizeof(kid));
682 // pop all pressed key on win32
683 void Engine::keyboardResetOnWin32()
685 for (Keyboard::KeyIterator
686 i = m_setting->m_keyboard.getKeyIterator(); *i; ++ i)
688 if ((*i)->m_isPressedOnWin32)
689 generateKeyEvent((*i), false, true);
695 unsigned int WINAPI Engine::keyboardDetour(Engine *i_this, KBDLLHOOKSTRUCT *i_kid)
697 return i_this->keyboardDetour(i_kid);
700 unsigned int Engine::keyboardDetour(KBDLLHOOKSTRUCT *i_kid)
703 Acquire a(&m_log, 1);
705 << _T("keyboardDetour: vkCode=") << i_kid->vkCode
706 << _T(" scanCode=") << i_kid->scanCode
707 << _T(" flags=") << i_kid->flags << std::endl;
709 if (i_kid->flags & LLKHF_INJECTED)
716 KEYBOARD_INPUT_DATA kid;
719 kid.MakeCode = i_kid->scanCode;
721 if (i_kid->flags & LLKHF_UP)
723 kid.Flags |= KEYBOARD_INPUT_DATA::BREAK;
725 if (i_kid->flags & LLKHF_EXTENDED)
727 kid.Flags |= KEYBOARD_INPUT_DATA::E0;
730 kid.ExtraInformation = 0;
732 Acquire a(&m_cskidq);
733 m_kidq.push_back(kid);
734 SetEvent(m_readEvent);
740 // keyboard handler thread
741 unsigned int WINAPI Engine::keyboardHandler(void *i_this)
743 reinterpret_cast<Engine *>(i_this)->keyboardHandler();
747 void Engine::keyboardHandler()
750 CHECK_TRUE( SetEvent(m_threadEvent) );
754 while (!m_doForceTerminate)
756 KEYBOARD_INPUT_DATA kid;
762 Acquire a(&m_log, 1);
763 m_log << _T("begin ReadFile();") << std::endl;
769 if (!ReadFile(m_device, &kid, sizeof(kid), &len, &m_ol))
771 if (GetLastError() != ERROR_IO_PENDING)
775 HANDLE handles[] = { m_readEvent, m_interruptThreadEvent };
777 switch (MsgWaitForMultipleObjects(NUMBER_OF(handles), &handles[0],
778 FALSE, INFINITE, QS_POSTMESSAGE))
780 case WAIT_OBJECT_0: // m_readEvent
783 Acquire a(&m_cskidq);
788 kid = m_kidq.front();
792 SetEvent(m_readEvent);
796 if (!GetOverlappedResult(m_device, &m_ol, &len, FALSE))
801 case WAIT_OBJECT_0 + 1: // m_interruptThreadEvent
803 switch (m_interruptThreadReason) {
806 Acquire a(&m_log, 0);
807 m_log << _T("internal error: m_interruptThreadReason == ")
808 << m_interruptThreadReason << std::endl;
812 case InterruptThreadReason_Terminate:
815 case InterruptThreadReason_Pause: {
816 CHECK_TRUE( SetEvent(m_threadEvent) );
817 while (WaitForMultipleObjects(1, &m_interruptThreadEvent,
818 FALSE, INFINITE) != WAIT_OBJECT_0)
820 switch (m_interruptThreadReason) {
821 case InterruptThreadReason_Terminate:
824 case InterruptThreadReason_Resume:
831 CHECK_TRUE( SetEvent(m_threadEvent) );
837 case WAIT_OBJECT_0 + NUMBER_OF(handles):
841 while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
843 switch (message.message)
849 m_currentLock.on(Modifier::Type_Touchpad);
850 m_currentLock.on(Modifier::Type_TouchpadSticky);
853 m_currentLock.off(Modifier::Type_Touchpad);
854 Acquire a(&m_log, 1);
855 m_log << _T("touchpad: ") << message.wParam
856 << _T(".") << (message.lParam & 0xffff)
857 << _T(".") << (message.lParam >> 16 & 0xffff)
874 Acquire a(&m_log, 1);
875 m_log << _T("end ReadFile();") << std::endl;
880 if (!m_setting || // m_setting has not been loaded
881 !m_isEnabled) // disabled
886 key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));
887 outputToLog(&key, ModifiedKey(), 0);
892 injectInput(&kid, NULL);
894 WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);
895 GetOverlappedResult(m_device, &m_ol, &len, TRUE);
898 updateLastPressedKey(NULL);
904 if (!m_currentFocusOfThread ||
908 WriteFile(m_device, &kid, sizeof(kid), &len, &m_ol);
909 GetOverlappedResult(m_device, &m_ol, &len, TRUE);
911 Acquire a(&m_log, 0);
912 if (!m_currentFocusOfThread)
913 m_log << _T("internal error: m_currentFocusOfThread == NULL")
915 if (!m_currentKeymap)
916 m_log << _T("internal error: m_currentKeymap == NULL")
918 updateLastPressedKey(NULL);
923 c.m_keymap = m_currentKeymap;
924 c.m_i = m_currentFocusOfThread->m_keymaps.begin();
927 key.addScanCode(ScanCode(kid.MakeCode, kid.Flags));
928 c.m_mkey = m_setting->m_keyboard.searchKey(key);
931 c.m_mkey.m_key = m_setting->m_keyboard.searchPrefixKey(key);
936 // press the key and update counter
937 bool isPhysicallyPressed
938 = !(key.getScanCodes()[0].m_flags & ScanCode::BREAK);
941 if (!c.m_mkey.m_key->m_isPressed && isPhysicallyPressed)
942 ++ m_currentKeyPressCount;
943 else if (c.m_mkey.m_key->m_isPressed && !isPhysicallyPressed)
944 -- m_currentKeyPressCount;
945 c.m_mkey.m_key->m_isPressed = isPhysicallyPressed;
949 c.m_mkey.m_modifier = getCurrentModifiers(c.m_mkey.m_key,
950 isPhysicallyPressed);
951 Keymap::AssignMode am;
952 bool isModifier = fixModifierKey(&c.m_mkey, &am);
955 if (isModifier && m_doesIgnoreModifierForPrefix)
956 am = Keymap::AM_true;
957 if (m_doesEditNextModifier)
959 Modifier modifier = m_modifierForNextKey;
960 modifier.add(c.m_mkey.m_modifier);
961 c.m_mkey.m_modifier = modifier;
966 outputToLog(&key, c.m_mkey, 0);
967 else if (am == Keymap::AM_true)
970 Acquire a(&m_log, 1);
971 m_log << _T("* true modifier") << std::endl;
973 // true modifier doesn't generate scan code
974 outputToLog(&key, c.m_mkey, 1);
976 else if (am == Keymap::AM_oneShot || am == Keymap::AM_oneShotRepeatable)
979 Acquire a(&m_log, 1);
980 if (am == Keymap::AM_oneShot)
981 m_log << _T("* one shot modifier") << std::endl;
983 m_log << _T("* one shot repeatable modifier") << std::endl;
985 // oneShot modifier doesn't generate scan code
986 outputToLog(&key, c.m_mkey, 1);
987 if (isPhysicallyPressed)
989 if (am == Keymap::AM_oneShotRepeatable // the key is repeating
990 && m_oneShotKey.m_key == c.m_mkey.m_key)
992 if (m_oneShotRepeatableRepeatCount <
993 m_setting->m_oneShotRepeatableDelay) {
997 beginGeneratingKeyboardEvents(cnew, false);
999 ++ m_oneShotRepeatableRepeatCount;
1001 m_oneShotKey = c.m_mkey;
1002 m_oneShotRepeatableRepeatCount = 0;
1007 if (m_oneShotKey.m_key)
1010 cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;
1011 cnew.m_mkey.m_modifier.off(Modifier::Type_Up);
1012 cnew.m_mkey.m_modifier.on(Modifier::Type_Down);
1013 beginGeneratingKeyboardEvents(cnew, false);
1016 cnew.m_mkey.m_modifier = m_oneShotKey.m_modifier;
1017 cnew.m_mkey.m_modifier.on(Modifier::Type_Up);
1018 cnew.m_mkey.m_modifier.off(Modifier::Type_Down);
1019 beginGeneratingKeyboardEvents(cnew, false);
1021 m_oneShotKey.m_key = NULL;
1022 m_oneShotRepeatableRepeatCount = 0;
1025 else if (c.m_mkey.m_key)
1028 outputToLog(&key, c.m_mkey, 1);
1029 if (isPhysicallyPressed)
1030 m_oneShotKey.m_key = NULL;
1031 beginGeneratingKeyboardEvents(c, isModifier);
1034 // if counter is zero, reset modifiers and keys on win32
1035 if (m_currentKeyPressCount <= 0)
1038 Acquire a(&m_log, 1);
1039 m_log << _T("* No key is pressed") << std::endl;
1041 generateModifierEvents(Modifier());
1042 if (0 < m_currentKeyPressCountOnWin32)
1043 keyboardResetOnWin32();
1044 m_currentKeyPressCount = 0;
1045 m_currentKeyPressCountOnWin32 = 0;
1046 m_oneShotKey.m_key = NULL;
1047 if (m_currentLock.isOn(Modifier::Type_Touchpad) == false)
1048 m_currentLock.off(Modifier::Type_TouchpadSticky);
1052 updateLastPressedKey(isPhysicallyPressed ? c.m_mkey.m_key : NULL);
1055 CHECK_TRUE( SetEvent(m_threadEvent) );
1059 Engine::Engine(tomsgstream &i_log)
1060 : m_hwndAssocWindow(NULL),
1062 m_device(INVALID_HANDLE_VALUE),
1063 m_didMayuStartDevice(false),
1064 m_threadEvent(NULL),
1065 m_mayudVersion(_T("unknown")),
1067 m_interruptThreadEvent(NULL),
1070 m_doForceTerminate(false),
1073 m_isSynchronizing(false),
1075 m_generateKeyboardEventsRecursionGuard(0),
1076 m_currentKeyPressCount(0),
1077 m_currentKeyPressCountOnWin32(0),
1078 m_lastGeneratedKey(NULL),
1079 m_oneShotRepeatableRepeatCount(0),
1081 m_currentKeymap(NULL),
1082 m_currentFocusOfThread(NULL),
1084 m_afShellExecute(NULL),
1088 for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)
1089 m_lastPressedKey[i] = NULL;
1091 // set default lock state
1092 for (int i = 0; i < Modifier::Type_end; ++ i)
1093 m_currentLock.dontcare(static_cast<Modifier::Type>(i));
1094 for (int i = Modifier::Type_Lock0; i <= Modifier::Type_Lock9; ++ i)
1095 m_currentLock.release(static_cast<Modifier::Type>(i));
1099 throw ErrorMessage() << loadString(IDS_driverNotInstalled);
1101 #endif // !NO_DRIVER
1105 TCHAR versionBuf[256];
1108 if (DeviceIoControl(m_device, IOCTL_MAYU_GET_VERSION, NULL, 0,
1109 versionBuf, sizeof(versionBuf), &length, NULL)
1111 && length < sizeof(versionBuf)) // fail safe
1112 m_mayudVersion = tstring(versionBuf, length / 2);
1114 #endif // !NO_DRIVER
1115 // create event for sync
1116 CHECK_TRUE( m_eSync = CreateEvent(NULL, FALSE, FALSE, NULL) );
1117 // create named pipe for &SetImeString
1118 m_hookPipe = CreateNamedPipe(addSessionId(HOOK_PIPE_NAME).c_str(),
1119 PIPE_ACCESS_OUTBOUND,
1122 StrExprArg::setEngine(this);
1129 // open mayu m_device
1131 m_device = CreateFile(MAYU_DEVICE_FILE_NAME, GENERIC_READ | GENERIC_WRITE,
1132 0, NULL, OPEN_EXISTING,
1133 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1134 #endif // !NO_DRIVER
1136 if (m_device != INVALID_HANDLE_VALUE) {
1142 SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
1145 SC_HANDLE hs = OpenService(hscm, MAYU_DRIVER_NAME, SERVICE_START);
1148 StartService(hs, 0, NULL);
1149 CloseServiceHandle(hs);
1150 m_didMayuStartDevice = true;
1152 CloseServiceHandle(hscm);
1155 // open mayu m_device
1156 m_device = CreateFile(MAYU_DEVICE_FILE_NAME, GENERIC_READ | GENERIC_WRITE,
1157 0, NULL, OPEN_EXISTING,
1158 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
1159 #endif // !NO_DRIVER
1160 return (m_device != INVALID_HANDLE_VALUE);
1164 // close mayu device
1165 void Engine::close()
1167 if (m_device != INVALID_HANDLE_VALUE) {
1169 CHECK_TRUE( CloseHandle(m_device) );
1170 #endif // !NO_DRIVER
1172 m_device = INVALID_HANDLE_VALUE;
1176 // start keyboard handler thread
1177 void Engine::start()
1179 CHECK_TRUE( m_threadEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );
1181 CHECK_TRUE( m_readEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );
1182 CHECK_TRUE( m_interruptThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL) );
1184 m_ol.OffsetHigh = 0;
1185 m_ol.hEvent = m_readEvent;
1187 CHECK_TRUE( m_threadHandle = (HANDLE)_beginthreadex(NULL, 0, keyboardHandler, this, 0, &m_threadId) );
1188 CHECK( WAIT_OBJECT_0 ==, WaitForSingleObject(m_threadEvent, INFINITE) );
1192 // stop keyboard handler thread
1197 m_doForceTerminate = true;
1200 m_interruptThreadReason = InterruptThreadReason_Terminate;
1201 SetEvent(m_interruptThreadEvent);
1203 //M_DeviceIoControl(m_device, IOCTL_MAYU_DETOUR_CANCEL,
1204 // &buf, sizeof(buf), &buf, sizeof(buf), &buf, NULL);
1206 // wait for message handler thread terminate
1207 } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);
1208 CHECK_TRUE( CloseHandle(m_threadEvent) );
1209 m_threadEvent = NULL;
1210 WaitForSingleObject(m_threadHandle, 100);
1211 CHECK_TRUE( CloseHandle(m_threadHandle) );
1212 m_threadHandle = NULL;
1215 if (m_didMayuStartDevice)
1217 SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
1220 SC_HANDLE hs = OpenService(hscm, MAYU_DRIVER_NAME, SERVICE_STOP);
1224 ControlService(hs, SERVICE_CONTROL_STOP, &ss);
1225 CloseServiceHandle(hs);
1227 CloseServiceHandle(hscm);
1231 CHECK_TRUE( CloseHandle(m_readEvent) );
1233 CHECK_TRUE( CloseHandle(m_interruptThreadEvent) );
1234 m_interruptThreadEvent = NULL;
1238 bool Engine::pause()
1240 if (m_device != INVALID_HANDLE_VALUE) {
1242 m_interruptThreadReason = InterruptThreadReason_Pause;
1243 SetEvent(m_interruptThreadEvent);
1244 } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);
1247 #endif // !NO_DRIVER
1253 bool Engine::resume()
1255 if (m_device == INVALID_HANDLE_VALUE) {
1258 return false; // FIXME
1260 #endif // !NO_DRIVER
1262 m_interruptThreadReason = InterruptThreadReason_Resume;
1263 SetEvent(m_interruptThreadEvent);
1264 } while (WaitForSingleObject(m_threadEvent, 100) != WAIT_OBJECT_0);
1270 bool Engine::prepairQuit()
1272 // terminate and unload DLL for ThumbSense support if loaded
1273 manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),
1274 false, &m_sts4mayu);
1275 manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),
1276 false, &m_cts4mayu);
1284 CHECK_TRUE( CloseHandle(m_eSync) );
1289 #endif // !NO_DRIVER
1290 // destroy named pipe for &SetImeString
1291 if (m_hookPipe && m_hookPipe != INVALID_HANDLE_VALUE)
1293 DisconnectNamedPipe(m_hookPipe);
1294 CHECK_TRUE( CloseHandle(m_hookPipe) );
1299 void Engine::manageTs4mayu(TCHAR *i_ts4mayuDllName,
1300 TCHAR *i_dependDllName,
1301 bool i_load, HMODULE *i_pTs4mayu)
1303 Acquire a(&m_log, 0);
1305 if (i_load == false)
1309 bool (WINAPI *pTs4mayuTerm)();
1311 pTs4mayuTerm = (bool (WINAPI*)())GetProcAddress(*i_pTs4mayu, "ts4mayuTerm");
1312 if (pTs4mayuTerm() == true)
1313 FreeLibrary(*i_pTs4mayu);
1315 m_log << i_ts4mayuDllName <<_T(" unloaded") << std::endl;
1322 m_log << i_ts4mayuDllName << _T(" already loaded") << std::endl;
1326 if (SearchPath(NULL, i_dependDllName, NULL, 0, NULL, NULL) == 0)
1328 m_log << _T("load ") << i_ts4mayuDllName
1329 << _T(" failed: can't find ") << i_dependDllName
1334 *i_pTs4mayu = LoadLibrary(i_ts4mayuDllName);
1335 if (*i_pTs4mayu == NULL)
1337 m_log << _T("load ") << i_ts4mayuDllName
1338 << _T(" failed: can't find it") << std::endl;
1342 bool (WINAPI *pTs4mayuInit)(UINT);
1344 pTs4mayuInit = (bool (WINAPI*)(UINT))GetProcAddress(*i_pTs4mayu, "ts4mayuInit");
1345 if (pTs4mayuInit(m_threadId) == true)
1346 m_log << i_ts4mayuDllName <<_T(" loaded") << std::endl;
1348 m_log << i_ts4mayuDllName
1349 <<_T(" load failed: can't initialize") << std::endl;
1358 bool Engine::setSetting(Setting *i_setting)
1361 if (m_isSynchronizing)
1366 for (Keyboard::KeyIterator i = m_setting->m_keyboard.getKeyIterator();
1369 Key *key = i_setting->m_keyboard.searchKey(*(*i));
1372 key->m_isPressed = (*i)->m_isPressed;
1373 key->m_isPressedOnWin32 = (*i)->m_isPressedOnWin32;
1374 key->m_isPressedByAssign = (*i)->m_isPressedByAssign;
1377 if (m_lastGeneratedKey)
1378 m_lastGeneratedKey =
1379 i_setting->m_keyboard.searchKey(*m_lastGeneratedKey);
1380 for (size_t i = 0; i < NUMBER_OF(m_lastPressedKey); ++ i)
1381 if (m_lastPressedKey[i])
1382 m_lastPressedKey[i] =
1383 i_setting->m_keyboard.searchKey(*m_lastPressedKey[i]);
1386 m_setting = i_setting;
1388 manageTs4mayu(_T("sts4mayu.dll"), _T("SynCOM.dll"),
1389 m_setting->m_sts4mayu, &m_sts4mayu);
1390 manageTs4mayu(_T("cts4mayu.dll"), _T("TouchPad.dll"),
1391 m_setting->m_cts4mayu, &m_cts4mayu);
1393 g_hookData->m_correctKanaLockHandling = m_setting->m_correctKanaLockHandling;
1394 if (m_currentFocusOfThread)
1396 for (FocusOfThreads::iterator i = m_focusOfThreads.begin();
1397 i != m_focusOfThreads.end(); i ++)
1399 FocusOfThread *fot = &(*i).second;
1400 m_setting->m_keymaps.searchWindow(&fot->m_keymaps,
1401 fot->m_className, fot->m_titleName);
1404 m_setting->m_keymaps.searchWindow(&m_globalFocus.m_keymaps, _T(""), _T(""));
1405 if (m_globalFocus.m_keymaps.empty())
1407 Acquire a(&m_log, 0);
1408 m_log << _T("internal error: m_globalFocus.m_keymap is empty")
1411 m_currentFocusOfThread = &m_globalFocus;
1412 setCurrentKeymap(m_globalFocus.m_keymaps.front());
1418 void Engine::checkShow(HWND i_hwnd)
1420 // update show style of window
1421 // this update should be done in hook DLL, but to
1422 // avoid update-loss for some applications(such as
1423 // cmd.exe), we update here.
1424 bool isMaximized = false;
1425 bool isMinimized = false;
1426 bool isMDIMaximized = false;
1427 bool isMDIMinimized = false;
1431 LONG_PTR exStyle = GetWindowLongPtr(i_hwnd, GWL_EXSTYLE);
1433 LONG exStyle = GetWindowLong(i_hwnd, GWL_EXSTYLE);
1435 if (exStyle & WS_EX_MDICHILD)
1437 WINDOWPLACEMENT placement;
1438 placement.length = sizeof(WINDOWPLACEMENT);
1439 if (GetWindowPlacement(i_hwnd, &placement))
1441 switch (placement.showCmd)
1443 case SW_SHOWMAXIMIZED:
1444 isMDIMaximized = true;
1446 case SW_SHOWMINIMIZED:
1447 isMDIMinimized = true;
1457 LONG_PTR style = GetWindowLongPtr(i_hwnd, GWL_STYLE);
1459 LONG style = GetWindowLong(i_hwnd, GWL_STYLE);
1461 if ((style & WS_CHILD) == 0)
1463 WINDOWPLACEMENT placement;
1464 placement.length = sizeof(WINDOWPLACEMENT);
1465 if (GetWindowPlacement(i_hwnd, &placement))
1467 switch (placement.showCmd)
1469 case SW_SHOWMAXIMIZED:
1472 case SW_SHOWMINIMIZED:
1481 i_hwnd = GetParent(i_hwnd);
1483 setShow(isMDIMaximized, isMDIMinimized, true);
1484 setShow(isMaximized, isMinimized, false);
1489 bool Engine::setFocus(HWND i_hwndFocus, DWORD i_threadId,
1490 const tstringi &i_className, const tstringi &i_titleName,
1494 if (m_isSynchronizing)
1496 if (i_hwndFocus == NULL)
1499 // remove newly created thread's id from m_detachedThreadIds
1500 if (!m_detachedThreadIds.empty())
1502 DetachedThreadIds::iterator i;
1507 for (i = m_detachedThreadIds.begin();
1508 i != m_detachedThreadIds.end(); ++ i)
1509 if (*i == i_threadId)
1511 m_detachedThreadIds.erase(i);
1519 FocusOfThreads::iterator i = m_focusOfThreads.find(i_threadId);
1520 if (i != m_focusOfThreads.end())
1523 if (fot->m_hwndFocus == i_hwndFocus &&
1524 fot->m_isConsole == i_isConsole &&
1525 fot->m_className == i_className &&
1526 fot->m_titleName == i_titleName)
1531 i = m_focusOfThreads.insert(
1532 FocusOfThreads::value_type(i_threadId, FocusOfThread())).first;
1534 fot->m_threadId = i_threadId;
1536 fot->m_hwndFocus = i_hwndFocus;
1537 fot->m_isConsole = i_isConsole;
1538 fot->m_className = i_className;
1539 fot->m_titleName = i_titleName;
1543 m_setting->m_keymaps.searchWindow(&fot->m_keymaps,
1544 i_className, i_titleName);
1545 ASSERT(0 < fot->m_keymaps.size());
1548 fot->m_keymaps.clear();
1549 checkShow(i_hwndFocus);
1555 bool Engine::setLockState(bool i_isNumLockToggled,
1556 bool i_isCapsLockToggled,
1557 bool i_isScrollLockToggled,
1558 bool i_isKanaLockToggled,
1559 bool i_isImeLockToggled,
1560 bool i_isImeCompToggled)
1563 if (m_isSynchronizing)
1565 m_currentLock.on(Modifier::Type_NumLock, i_isNumLockToggled);
1566 m_currentLock.on(Modifier::Type_CapsLock, i_isCapsLockToggled);
1567 m_currentLock.on(Modifier::Type_ScrollLock, i_isScrollLockToggled);
1568 m_currentLock.on(Modifier::Type_KanaLock, i_isKanaLockToggled);
1569 m_currentLock.on(Modifier::Type_ImeLock, i_isImeLockToggled);
1570 m_currentLock.on(Modifier::Type_ImeComp, i_isImeCompToggled);
1576 bool Engine::setShow(bool i_isMaximized, bool i_isMinimized,
1580 if (m_isSynchronizing)
1582 Acquire b(&m_log, 1);
1583 Modifier::Type max, min;
1584 if (i_isMDI == true) {
1585 max = Modifier::Type_MdiMaximized;
1586 min = Modifier::Type_MdiMinimized;
1590 max = Modifier::Type_Maximized;
1591 min = Modifier::Type_Minimized;
1593 m_currentLock.on(max, i_isMaximized);
1594 m_currentLock.on(min, i_isMinimized);
1595 m_log << _T("Set show to ") << (i_isMaximized ? _T("Maximized") :
1596 i_isMinimized ? _T("Minimized") : _T("Normal"));
1597 if (i_isMDI == true)
1599 m_log << _T(" (MDI)");
1607 bool Engine::syncNotify()
1610 if (!m_isSynchronizing)
1612 CHECK_TRUE( SetEvent(m_eSync) );
1617 // thread detach notify
1618 bool Engine::threadDetachNotify(DWORD i_threadId)
1621 m_detachedThreadIds.push_back(i_threadId);
1627 void Engine::getHelpMessages(tstring *o_helpMessage, tstring *o_helpTitle)
1630 *o_helpMessage = m_helpMessage;
1631 *o_helpTitle = m_helpTitle;
1636 void Engine::commandNotify(
1637 HWND i_hwnd, UINT i_message, WPARAM i_wParam, LPARAM i_lParam)
1639 Acquire b(&m_log, 0);
1640 HWND hf = m_hwndFocus;
1644 if (GetWindowThreadProcessId(hf, NULL) ==
1645 GetWindowThreadProcessId(m_hwndAssocWindow, NULL))
1646 return; // inhibit the investigation of MADO TSUKAI NO YUUTSU
1648 const _TCHAR *target = NULL;
1649 int number_target = 0;
1652 target = _T("ToItself");
1653 else if (i_hwnd == GetParent(hf))
1654 target = _T("ToParentWindow");
1657 // Function::toMainWindow
1661 HWND p = GetParent(h);
1667 target = _T("ToMainWindow");
1670 // Function::toOverlappedWindow
1675 LONG_PTR style = GetWindowLongPtr(h, GWL_STYLE);
1677 LONG style = GetWindowLong(h, GWL_STYLE);
1679 if ((style & WS_CHILD) == 0)
1684 target = _T("ToOverlappedWindow");
1689 for (number_target = 0; h; number_target ++, h = GetParent(h))
1697 m_log << _T("&PostMessage(");
1701 m_log << number_target;
1702 m_log << _T(", ") << i_message
1703 << _T(", 0x") << std::hex << i_wParam
1704 << _T(", 0x") << i_lParam << _T(") # hwnd = ")
1705 << reinterpret_cast<int>(i_hwnd) << _T(", ")
1706 << _T("message = ") << std::dec;
1707 if (i_message == WM_COMMAND)
1708 m_log << _T("WM_COMMAND, ");
1709 else if (i_message == WM_SYSCOMMAND)
1710 m_log << _T("WM_SYSCOMMAND, ");
1712 m_log << i_message << _T(", ");
1713 m_log << _T("wNotifyCode = ") << HIWORD(i_wParam) << _T(", ")
1714 << _T("wID = ") << LOWORD(i_wParam) << _T(", ")
1715 << _T("hwndCtrl = 0x") << std::hex << i_lParam << std::dec << std::endl;