diff options
Diffstat (limited to 'indra/llwindow')
-rw-r--r-- | indra/llwindow/llwindow.h | 2 | ||||
-rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 194 | ||||
-rw-r--r-- | indra/llwindow/llwindowwin32.h | 4 |
3 files changed, 160 insertions, 40 deletions
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 1347d8e94c..f1c188f8e9 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -200,7 +200,7 @@ public: // control platform's Language Text Input mechanisms. virtual void allowLanguageTextInput( BOOL b ) {}; - virtual void setLanguageTextInput( LLCoordWindow pos ) {}; + virtual void setLanguageTextInput( const LLCoordGL & pos ) {}; protected: LLWindow(BOOL fullscreen, U32 flags); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 299ccc39f3..cb108143f4 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -65,11 +65,10 @@ void show_window_creation_error(const char* title) //static BOOL LLWindowWin32::sIsClassRegistered = FALSE; -BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE; /* XXX */ -BOOL LLWindowWin32::sWinIMEOpened = FALSE; -HKL LLWindowWin32::sWinInputLocale; -DWORD LLWindowWin32::sWinIMEConversionMode; -DWORD LLWindowWin32::sWinIMESentenceMode; +BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE; +HKL LLWindowWin32::sWinInputLocale = 0; +DWORD LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE; +DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; // The following class LLWinImm delegates Windows IMM APIs. // We need this because some language versions of Windows, @@ -87,13 +86,15 @@ public: public: // Wrappers for IMM API. - static BOOL isIME(HKL hkl) { return sTheInstance.mImmIsIME(hkl); } - static HIMC getContext(HWND hwnd) { return sTheInstance.mImmGetContext(hwnd); } - static BOOL releaseContext(HWND hwnd, HIMC himc) { return sTheInstance.mImmReleaseContext(hwnd, himc); } - static BOOL getOpenStatus(HIMC himc) { return sTheInstance.mImmGetOpenStatus(himc); } - static BOOL setOpenStatus(HIMC himc, BOOL status) { return sTheInstance.mImmSetOpenStatus(himc, status); } - static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) { return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); } - static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) { return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); } + static BOOL isIME(HKL hkl); + static HIMC getContext(HWND hwnd); + static BOOL releaseContext(HWND hwnd, HIMC himc); + static BOOL getOpenStatus(HIMC himc); + static BOOL setOpenStatus(HIMC himc, BOOL status); + static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence); + static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence); + static BOOL getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form); + static BOOL setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form); private: LLWinImm(); @@ -108,6 +109,8 @@ private: BOOL (WINAPI *mImmSetOpenStatus)(HIMC, BOOL); BOOL (WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD); BOOL (WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD); + BOOL (WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); + BOOL (WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); private: HMODULE mHImmDll; @@ -116,8 +119,13 @@ private: LLWinImm LLWinImm::sTheInstance; -LLWinImm::LLWinImm() +LLWinImm::LLWinImm() : mHImmDll(NULL) { + // Check system metrics + if ( !GetSystemMetrics( SM_DBCSENABLED ) ) + return; + + mHImmDll = LoadLibraryA("Imm32"); if (mHImmDll != NULL) { @@ -128,13 +136,18 @@ LLWinImm::LLWinImm() mImmSetOpenStatus = (BOOL (WINAPI *)(HIMC, BOOL)) GetProcAddress(mHImmDll, "ImmSetOpenStatus"); mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus"); mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmSetConversionStatus"); + mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmGetCompositionWindow"); + mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmSetCompositionWindow"); + if (mImmIsIME == NULL || mImmGetContext == NULL || mImmReleaseContext == NULL || mImmGetOpenStatus == NULL || mImmSetOpenStatus == NULL || mImmGetConversionStatus == NULL || - mImmSetConversionStatus == NULL) + mImmSetConversionStatus == NULL || + mImmGetCompostitionWindow == NULL || + mImmSetCompostitionWindow == NULL) { // If any of the above API entires are not found, we can't use IMM API. // So, turn off the IMM support. We should log some warning message in @@ -145,10 +158,96 @@ LLWinImm::LLWinImm() // is one of disadvantages to use static constraction to DLL loading. FreeLibrary(mHImmDll); mHImmDll = NULL; + + // If we unload the library, make sure all the function pointers are cleared + mImmIsIME = NULL; + mImmGetContext = NULL; + mImmReleaseContext = NULL; + mImmGetOpenStatus = NULL; + mImmSetOpenStatus = NULL; + mImmGetConversionStatus = NULL; + mImmSetConversionStatus = NULL; + mImmGetCompostitionWindow = NULL; + mImmSetCompostitionWindow = NULL; } } } + +// static +BOOL LLWinImm::isIME(HKL hkl) +{ + if ( sTheInstance.mImmIsIME ) + return sTheInstance.mImmIsIME(hkl); + return FALSE; +} + +// static +HIMC LLWinImm::getContext(HWND hwnd) +{ + if ( sTheInstance.mImmGetContext ) + return sTheInstance.mImmGetContext(hwnd); + return 0; +} + +//static +BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc) +{ + if ( sTheInstance.mImmIsIME ) + return sTheInstance.mImmReleaseContext(hwnd, himc); + return FALSE; +} + +// static +BOOL LLWinImm::getOpenStatus(HIMC himc) +{ + if ( sTheInstance.mImmGetOpenStatus ) + return sTheInstance.mImmGetOpenStatus(himc); + return FALSE; +} + +// static +BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) +{ + if ( sTheInstance.mImmSetOpenStatus ) + return sTheInstance.mImmSetOpenStatus(himc, status); + return FALSE; +} + +// static +BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) +{ + if ( sTheInstance.mImmGetConversionStatus ) + return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); + return FALSE; +} + +// static +BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) +{ + if ( sTheInstance.mImmSetConversionStatus ) + return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); + return FALSE; +} + +// static +BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) +{ + if ( sTheInstance.mImmGetCompostitionWindow ) + return sTheInstance.mImmGetCompostitionWindow(himc, form); + return FALSE; +} + +// static +BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) +{ + if ( sTheInstance.mImmSetCompostitionWindow ) + return sTheInstance.mImmSetCompostitionWindow(himc, form); + return FALSE; +} + + +// ---------------------------------------------------------------------------------------- LLWinImm::~LLWinImm() { if (mHImmDll != NULL) @@ -3202,53 +3301,74 @@ void LLWindowWin32::focusClient() void LLWindowWin32::allowLanguageTextInput(BOOL b) { - if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable()) + if ( !LLWinImm::isAvailable() ) { - /* Not actually allowing/disallowing. Do nothing. */ return; } sLanguageTextInputAllowed = b; if (b) { - /* Allowing: Restore the previous IME status, - so that the user has a feeling that the previous - text input continues naturally. Be careful, however, - the IME status is meaningful only during the user keeps - using same Input Locale (aka Keyboard Layout). */ - if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale) + // Allowing: Restore the previous IME status, so that the user has a feeling that the previous + // text input continues naturally. Be careful, however, the IME status is meaningful only during the user keeps + // using same Input Locale (aka Keyboard Layout). + HIMC himc = LLWinImm::getContext(mWindowHandle); + LLWinImm::setOpenStatus(himc, TRUE); + if (GetKeyboardLayout(0) == sWinInputLocale && sWinIMEConversionMode != IME_CMODE_RESERVED) { - HIMC himc = LLWinImm::getContext(mWindowHandle); - LLWinImm::setOpenStatus(himc, TRUE); LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode); - LLWinImm::releaseContext(mWindowHandle, himc); + sWinIMEConversionMode = IME_CMODE_RESERVED; // Set saved state so we won't do this repeatedly } + LLWinImm::releaseContext(mWindowHandle, himc); } else { - /* Disallowing: Turn off the IME so that succeeding - key events bypass IME and come to us directly. - However, do it after saving the current IME - status. We need to restore the status when - allowing language text input again. */ + // Disallowing: Turn off the IME so that succeeding key events bypass IME and come to us directly. + // However, do it after saving the current IME status. We need to restore the status when + // allowing language text input again. sWinInputLocale = GetKeyboardLayout(0); - sWinIMEOpened = LLWinImm::isIME(sWinInputLocale); - if (sWinIMEOpened) + if ( LLWinImm::isIME(sWinInputLocale) ) { HIMC himc = LLWinImm::getContext(mWindowHandle); - sWinIMEOpened = LLWinImm::getOpenStatus(himc); - if (sWinIMEOpened) + if ( LLWinImm::getOpenStatus(himc) ) { LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode); - /* We need both ImmSetConversionStatus and ImmSetOpenStatus here - to surely disable IME's keyboard hooking, because Some IME reacts - only on the former and some other on the latter... */ + // We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's + // keyboard hooking, because Some IME reacts only on the former and some other on the latter... LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode); LLWinImm::setOpenStatus(himc, FALSE); } LLWinImm::releaseContext(mWindowHandle, himc); + } + } + +} + + +// Put the IME window at the right place (near current text input). Point coordinates should be the top of the current text line. +void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position ) +{ + if (sLanguageTextInputAllowed && LLWinImm::isAvailable()) + { + HIMC himc = LLWinImm::getContext(mWindowHandle); + + LLCoordWindow win_pos; + convertCoords( position, &win_pos ); + + if ( win_pos.mX >= 0 && win_pos.mY >= 0 ) + { + COMPOSITIONFORM ime_form; + memset( &ime_form, 0, sizeof(ime_form) ); + ime_form.dwStyle = CFS_POINT; + ime_form.ptCurrentPos.x = win_pos.mX; + ime_form.ptCurrentPos.y = win_pos.mY; + + LLWinImm::setCompositionWindow( himc, &ime_form ); } + + LLWinImm::releaseContext(mWindowHandle, himc); + } } diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 5eb2cfbb79..cb105c2128 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -87,6 +87,7 @@ public: /*virtual*/ void focusClient(); /*virtual*/ void allowLanguageTextInput(BOOL b); + /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos ); protected: LLWindowWin32( @@ -156,11 +157,10 @@ protected: BOOL mMousePositionModified; BOOL mInputProcessingPaused; - // The following five variables are for Language Text Input control. + // The following variables are for Language Text Input control. // They are all static, since one context is shared by all LLWindowWin32 // instances. static BOOL sLanguageTextInputAllowed; - static BOOL sWinIMEOpened; static HKL sWinInputLocale; static DWORD sWinIMEConversionMode; static DWORD sWinIMESentenceMode; |