OSDN Git Service

Make the keyboard hooks global.
authorTomohiro Kashiwada <kikairoya@gmail.com>
Thu, 9 Jun 2011 07:50:31 +0000 (16:50 +0900)
committerKazuhiro Fujieda <fujieda@users.sourceforge.jp>
Fri, 10 Jun 2011 07:44:54 +0000 (16:44 +0900)
Each keyboard hook of 32bit and 64bit works only corresponding
applications and controls IME through a window message.
Make the reset of 64bit hooks disabled because it doesn't work.

xkeymacs/mainfrm.cpp
xkeymacs/xkeymacs64.cpp
xkeymacsdll/Commands.cpp
xkeymacsdll/Commands.h
xkeymacsdll/Utils.cpp
xkeymacsdll/Utils.h
xkeymacsdll/xkeymacsdll.cpp
xkeymacsdll/xkeymacsdll.h

index cc22cf7..57f3fa5 100644 (file)
@@ -576,9 +576,8 @@ void CMainFrame::OnExport()
 \r
 void CMainFrame::OnReset() \r
 {\r
-       CXkeymacsDll::ReleaseHooks();\r
-       CXkeymacsDll::SetHooks();\r
        TerminatePollThread();\r
+       CXkeymacsDll::ResetHook();\r
        StartPollThread();\r
        CXkeymacsApp *pApp = static_cast<CXkeymacsApp *>(AfxGetApp());\r
        if (!pApp->SendIPCMessage(XKEYMACS_RESET))\r
index 7e15352..08e1bc8 100644 (file)
@@ -64,8 +64,7 @@ UINT PollIPCMessage(LPVOID lpParam)
                                CXkeymacsDll::EnableKeyboardHook();\r
                        break;\r
                case XKEYMACS_RESET:\r
-                       CXkeymacsDll::ReleaseHooks();\r
-                       CXkeymacsDll::SetHooks();\r
+                       //CXkeymacsDll::ResetHook();\r
                        break;\r
                }\r
        }\r
index bde626d..497ea5e 100644 (file)
@@ -2815,7 +2815,24 @@ int CCommands::CompleteCloseInputMethod()
        return Reset(GOTO_HOOK);\r
 }\r
 \r
-void CCommands::SetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete)\r
+inline HWND ObtainFocus()\r
+{\r
+       const HWND hWnd = GetFocus();\r
+       if (hWnd)\r
+               return hWnd;\r
+       GUITHREADINFO gui;\r
+       gui.cbSize = sizeof(gui);\r
+       return GetGUIThreadInfo(GetWindowThreadProcessId(GetForegroundWindow(), 0), &gui) ? gui.hwndFocus : GetForegroundWindow();\r
+}\r
+\r
+void CCommands::SetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete) {\r
+       extern UINT g_ImeManipulationMessage;\r
+       HWND hWnd = ObtainFocus();\r
+       //CUtils::Log(_T(" post ime manip, %d, %d, %p"), status, isComplete, hWnd);\r
+       PostMessage(hWnd, g_ImeManipulationMessage, status, isComplete);\r
+}\r
+\r
+void CCommands::DoSetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete)\r
 {\r
        ClearNumericArgument();\r
        HKL hKL = GetKeyboardLayout(0);\r
@@ -2823,8 +2840,9 @@ void CCommands::SetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL i
                Kdu(VK_KANJI);\r
        } else if (ImmIsIME(hKL)) {\r
                // default\r
-               HWND hWnd = GetFocus();\r
+               HWND hWnd = ObtainFocus();\r
                HIMC hIMC = ImmGetContext(hWnd);\r
+               //CUtils::Log(_T(" do ime manip, %d, %d, %d, %p, %p"), status, isComplete, ImmGetOpenStatus(hIMC), hWnd, hIMC);\r
 \r
                if (isComplete && ImmGetOpenStatus(hIMC)) {\r
                        ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);\r
index 6663db7..f7b53c8 100644 (file)
@@ -176,6 +176,7 @@ public:
        static int GetDefaultCommandType(int nCommandID, int nIndex);\r
        static int GetDefaultCommandKey(int nCommandID, int nIndex);\r
        static int GetDefaultControlID(int nCommandID, int nIndex);\r
+       static void DoSetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete = FALSE);\r
        CCommands();\r
        virtual ~CCommands();\r
 \r
index 0628dd3..a8680d2 100644 (file)
@@ -68,6 +68,11 @@ BOOL CUtils::IsAstecX()
        return !_tcsicmp(m_szApplicationName, _T("astecx.exe"));\r
 }\r
 \r
+BOOL CUtils::IsXkeymacs()\r
+{\r
+       return !_tcsicmp(m_szApplicationName, _T("xkeymacs.exe")) || !_tcsicmp(m_szApplicationName, _T("xkeymacs64.exe"));\r
+}\r
+\r
 BOOL CUtils::IsBecky()\r
 {\r
        return !_tcsicmp(m_szApplicationName, _T("b2.exe"));\r
index 37032d8..4793c5e 100644 (file)
@@ -116,6 +116,7 @@ public:
        static BOOL IsExplorer();\r
        static BOOL IsBecky();\r
        static BOOL IsAstecX();\r
+       static BOOL IsXkeymacs();\r
        static BOOL CUtils::GetFindDialogTitle(CString *szDialogTitle);\r
        CUtils();\r
        virtual ~CUtils();\r
index b37160d..19c2b2a 100644 (file)
@@ -138,8 +138,42 @@ static const KeyName ControlCharacters[] = {
 \r
 static AFX_EXTENSION_MODULE XkeymacsdllDLL = { NULL, NULL };\r
 \r
-static __declspec(thread) HINSTANCE g_hDllInst = NULL;\r
-static __declspec(thread) HHOOK g_hHookKeyboard = NULL;\r
+HINSTANCE g_hDllInst = NULL;\r
+UINT g_ImeManipulationMessage = 0;\r
+#pragma data_seg(".xkmcs")\r
+HHOOK g_hHookKeyboard = NULL;\r
+HHOOK g_hHookDummy = NULL;\r
+#pragma data_seg()\r
+\r
+inline bool IsWow64(HANDLE mod) {\r
+       typedef BOOL (WINAPI *pfnIsWow64Process_t)(HANDLE, PBOOL);\r
+       if (const pfnIsWow64Process_t IsWow64Process = (pfnIsWow64Process_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "IsWow64Process")) {\r
+               BOOL b;\r
+               return IsWow64Process(mod, &b) && b;\r
+       }\r
+       return false;\r
+}\r
+\r
+inline bool Is64System() {\r
+       SYSTEM_INFO info;\r
+       GetNativeSystemInfo(&info);\r
+       return info.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL;\r
+}\r
+\r
+inline bool Is64Process(HANDLE mod) {\r
+       return Is64System() && !IsWow64(mod);\r
+}\r
+\r
+const bool IsDll64 = sizeof(void *) == 8;\r
+\r
+inline bool Is64ProcessHwnd(HWND hwnd) {\r
+       DWORD pid;\r
+       GetWindowThreadProcessId(hwnd, &pid);\r
+       HANDLE hmod = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);\r
+       bool b = Is64Process(hmod);\r
+       CloseHandle(hmod);\r
+       return b;\r
+}\r
 \r
 extern "C" int APIENTRY\r
 DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
@@ -152,6 +186,7 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
        switch (dwReason) {\r
        case DLL_PROCESS_ATTACH:\r
                TRACE0("XKEYMACSDLL.DLL Initializing!\n");\r
+               g_ImeManipulationMessage = RegisterWindowMessage(_T("XkManipulateIME"));\r
 \r
                // Extension DLL one-time initialization\r
                if (!AfxInitExtensionModule(XkeymacsdllDLL, hInstance)) {\r
@@ -177,15 +212,12 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
                        e->Delete();\r
 //                     CUtils::Log("DllMain: 'new' threw an exception");\r
                }\r
-       case DLL_THREAD_ATTACH:\r
-               CXkeymacsDll::SetKeyboardHook();\r
                break;\r
        case DLL_PROCESS_DETACH:\r
                TRACE0("XKEYMACSDLL.DLL Terminating!\n");\r
                // Terminate the library before destructors are called\r
                AfxTermExtensionModule(XkeymacsdllDLL);\r
-       case DLL_THREAD_DETACH:\r
-               CXkeymacsDll::ReleaseKeyboardHook();\r
+               break;\r
        }\r
        return 1;   // ok\r
 }\r
@@ -273,12 +305,18 @@ void CXkeymacsDll::SetHookAltRelease()
 }\r
 \r
 // set hooks\r
+LRESULT WINAPI DummyProc(int code, WPARAM wp, LPARAM lp) {\r
+       return CallNextHookEx(0, code, wp, lp);\r
+}\r
+\r
 void CXkeymacsDll::SetHooks()\r
 {\r
        m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0);\r
        m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0);\r
        m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0);\r
        m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0);\r
+       g_hHookDummy = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)DummyProc, g_hDllInst, 0);\r
+       g_hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, 0);\r
 }\r
 \r
 void CXkeymacsDll::EnableKeyboardHook()\r
@@ -286,35 +324,36 @@ void CXkeymacsDll::EnableKeyboardHook()
        m_bEnableKeyboardHook = TRUE;\r
 }\r
 \r
-void CXkeymacsDll::SetKeyboardHook()\r
+inline void unhook(HHOOK &hh) {\r
+       if (hh)\r
+               UnhookWindowsHookEx(hh);\r
+       hh = NULL;\r
+}\r
+\r
+void CXkeymacsDll::ResetHook() \r
 {\r
-       if (!g_hHookKeyboard)\r
-               SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, GetCurrentThreadId());\r
+       unhook(m_hHookCallWnd);\r
+       unhook(m_hHookCallWndRet);\r
+       unhook(m_hHookGetMessage);\r
+       unhook(m_hHookShell);\r
+       unhook(g_hHookKeyboard);\r
+       m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0);\r
+       m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0);\r
+       m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0);\r
+       m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0);\r
+       g_hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, 0);\r
 }\r
 \r
 // release hooks\r
 void CXkeymacsDll::ReleaseHooks()\r
 {\r
        m_bEnableKeyboardHook = FALSE;\r
-       if (m_hHookCallWnd)\r
-               UnhookWindowsHookEx(m_hHookCallWnd);\r
-       m_hHookCallWnd = NULL;\r
-       if (m_hHookCallWndRet)\r
-               UnhookWindowsHookEx(m_hHookCallWndRet);\r
-       m_hHookCallWndRet = NULL;\r
-       if (m_hHookGetMessage)\r
-               UnhookWindowsHookEx(m_hHookGetMessage);\r
-       m_hHookGetMessage = NULL;\r
-       if (m_hHookShell)\r
-               UnhookWindowsHookEx(m_hHookShell);\r
-       m_hHookShell = NULL;\r
-}\r
-\r
-void CXkeymacsDll::ReleaseKeyboardHook()\r
-{\r
-       if (g_hHookKeyboard)\r
-               UnhookWindowsHookEx(g_hHookKeyboard);\r
-       g_hHookKeyboard = NULL;\r
+       unhook(m_hHookCallWnd);\r
+       unhook(m_hHookCallWndRet);\r
+       unhook(m_hHookGetMessage);\r
+       unhook(m_hHookShell);\r
+       unhook(g_hHookKeyboard);\r
+       unhook(g_hHookDummy);\r
 }\r
 \r
 void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag)\r
@@ -544,7 +583,11 @@ LRESULT CALLBACK CXkeymacsDll::CallWndRetProc(int nCode, WPARAM wParam, LPARAM l
 LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)\r
 {\r
        MSG &msg = (*(MSG *)lParam);\r
-\r
+       if (msg.message == g_ImeManipulationMessage) {\r
+               if (wParam)\r
+                       CCommands::DoSetInputMethodOpenStatus((INPUT_METHOD_OPEN_STATUS)msg.wParam, msg.lParam);\r
+               return 1;\r
+       }\r
        switch (msg.message) {\r
        case WM_IME_STARTCOMPOSITION:\r
                InitKeyboardProc(TRUE);\r
@@ -763,9 +806,9 @@ LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lPa
        static BYTE nOneShotModifier[MAX_KEY] = {'\0'};\r
        static BOOL bCherryOneShotModifier = FALSE;\r
 \r
-//     CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %#x"), nCode, nKey, lParam);\r
+//     CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %p, en = %d, %d, %d"), nCode, nKey, lParam, m_bEnableKeyboardHook, IsDll64, Is64ProcessHwnd(GetForegroundWindow()));\r
 \r
-       if (!m_bEnableKeyboardHook)\r
+       if (Is64ProcessHwnd(GetForegroundWindow()) != IsDll64 || CUtils::IsXkeymacs())\r
                return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam);\r
 \r
        if (nCode < 0 || nCode == HC_NOREMOVE) {\r
index 8101c62..c081f67 100644 (file)
@@ -72,13 +72,12 @@ public:
        static void SetAtIbeamCursorOnly(int nApplicationID, int nCommandType, int nKey, BOOL bAtIbeamCursorOnly);\r
        static void SetApplicationName(int nApplicationID, CString szApplicationName);\r
        static void ReleaseHooks();\r
-       static void ReleaseKeyboardHook();\r
        static void SetEnableCUA(int nApplicationID, BOOL bEnableCUA);\r
        static void SetIgnoreUndefinedC_x(int nApplicationID, BOOL bIgnoreUndefinedC_x);\r
        static void SetIgnoreUndefinedMetaCtrl(int nApplicationID, BOOL bIgnoreUndefinedMetaCtrl);\r
        static void SetHooks();\r
        static void EnableKeyboardHook();\r
-       static void SetKeyboardHook();\r
+       static void ResetHook();\r
        static void SetSettingStyle(int nApplicationID, int nSettingStyle);\r
        static void SetUseDialogSetting(int nApplicationID, BOOL bUseDialogSetting);\r
        static void AddKillRing(BOOL bNewData = TRUE);\r
@@ -153,4 +152,6 @@ private:
        static CONFIG m_Config;\r
 };\r
 \r
+extern UINT g_ImeManipulationMessage;\r
+\r
 #endif // !defined(AFX_XKEYMACS_H__88552DEC_1233_4A0A_BE62_9EF7BC618EC6__INCLUDED_)\r