aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llwindow/llwindowwin32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llwindow/llwindowwin32.cpp')
-rw-r--r--linden/indra/llwindow/llwindowwin32.cpp172
1 files changed, 164 insertions, 8 deletions
diff --git a/linden/indra/llwindow/llwindowwin32.cpp b/linden/indra/llwindow/llwindowwin32.cpp
index 2cd1353..0b3cdd4 100644
--- a/linden/indra/llwindow/llwindowwin32.cpp
+++ b/linden/indra/llwindow/llwindowwin32.cpp
@@ -37,6 +37,7 @@
37#include <mapi.h> 37#include <mapi.h>
38#include <process.h> // for _spawn 38#include <process.h> // for _spawn
39#include <shellapi.h> 39#include <shellapi.h>
40#include <Imm.h>
40 41
41// Require DirectInput version 8 42// Require DirectInput version 8
42#define DIRECTINPUT_VERSION 0x0800 43#define DIRECTINPUT_VERSION 0x0800
@@ -84,6 +85,98 @@ void show_window_creation_error(const char* title)
84//static 85//static
85BOOL LLWindowWin32::sIsClassRegistered = FALSE; 86BOOL LLWindowWin32::sIsClassRegistered = FALSE;
86 87
88BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE; /* XXX */
89BOOL LLWindowWin32::sWinIMEOpened = FALSE;
90HKL LLWindowWin32::sWinInputLocale;
91DWORD LLWindowWin32::sWinIMEConversionMode;
92DWORD LLWindowWin32::sWinIMESentenceMode;
93
94// The following class LLWinImm delegates Windows IMM APIs.
95// We need this because some language versions of Windows,
96// e.g., US version of Windows XP, doesn't install IMM32.DLL
97// as a default, and we can't link against imm32.lib statically.
98// I believe DLL loading of this type is best suited to do
99// in a static initialization of a class. What I'm not sure is
100// whether it follows the Linden Conding Standard...
101// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members
102
103class LLWinImm
104{
105public:
106 static bool isAvailable() { return sTheInstance.mHImmDll != NULL; }
107
108public:
109 // Wrappers for IMM API.
110 static BOOL isIME(HKL hkl) { return sTheInstance.mImmIsIME(hkl); }
111 static HIMC getContext(HWND hwnd) { return sTheInstance.mImmGetContext(hwnd); }
112 static BOOL releaseContext(HWND hwnd, HIMC himc) { return sTheInstance.mImmReleaseContext(hwnd, himc); }
113 static BOOL getOpenStatus(HIMC himc) { return sTheInstance.mImmGetOpenStatus(himc); }
114 static BOOL setOpenStatus(HIMC himc, BOOL status) { return sTheInstance.mImmSetOpenStatus(himc, status); }
115 static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) { return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); }
116 static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) { return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); }
117
118private:
119 LLWinImm();
120 ~LLWinImm();
121
122private:
123 // Pointers to IMM API.
124 BOOL (WINAPI *mImmIsIME)(HKL);
125 HIMC (WINAPI *mImmGetContext)(HWND);
126 BOOL (WINAPI *mImmReleaseContext)(HWND, HIMC);
127 BOOL (WINAPI *mImmGetOpenStatus)(HIMC);
128 BOOL (WINAPI *mImmSetOpenStatus)(HIMC, BOOL);
129 BOOL (WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
130 BOOL (WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD);
131
132private:
133 HMODULE mHImmDll;
134 static LLWinImm sTheInstance;
135};
136
137LLWinImm LLWinImm::sTheInstance;
138
139LLWinImm::LLWinImm()
140{
141 mHImmDll = LoadLibraryA("Imm32");
142 if (mHImmDll != NULL)
143 {
144 mImmIsIME = (BOOL (WINAPI *)(HKL)) GetProcAddress(mHImmDll, "ImmIsIME");
145 mImmGetContext = (HIMC (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetContext");
146 mImmReleaseContext = (BOOL (WINAPI *)(HWND, HIMC)) GetProcAddress(mHImmDll, "ImmReleaseContext");
147 mImmGetOpenStatus = (BOOL (WINAPI *)(HIMC)) GetProcAddress(mHImmDll, "ImmGetOpenStatus");
148 mImmSetOpenStatus = (BOOL (WINAPI *)(HIMC, BOOL)) GetProcAddress(mHImmDll, "ImmSetOpenStatus");
149 mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus");
150 mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmSetConversionStatus");
151 if (mImmIsIME == NULL ||
152 mImmGetContext == NULL ||
153 mImmReleaseContext == NULL ||
154 mImmGetOpenStatus == NULL ||
155 mImmSetOpenStatus == NULL ||
156 mImmGetConversionStatus == NULL ||
157 mImmSetConversionStatus == NULL)
158 {
159 // If any of the above API entires are not found, we can't use IMM API.
160 // So, turn off the IMM support. We should log some warning message in
161 // the case, since it is very unusual; these APIs are available from
162 // the beginning, and all versions of IMM32.DLL should have them all.
163 // Unfortunately, this code may be executed before initialization of
164 // the logging channel (llwarns), and we can't do it here... Yes, this
165 // is one of disadvantages to use static constraction to DLL loading.
166 FreeLibrary(mHImmDll);
167 mHImmDll = NULL;
168 }
169 }
170}
171
172LLWinImm::~LLWinImm()
173{
174 if (mHImmDll != NULL)
175 {
176 FreeLibrary(mHImmDll);
177 mHImmDll = NULL;
178 }
179}
87 180
88 181
89LPDIRECTINPUT8 g_pDI = NULL; 182LPDIRECTINPUT8 g_pDI = NULL;
@@ -111,6 +204,10 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
111 // Initialize the keyboard 204 // Initialize the keyboard
112 gKeyboard = new LLKeyboardWin32(); 205 gKeyboard = new LLKeyboardWin32();
113 206
207 // Initialize (boot strap) the Language text input management,
208 // based on the system's (user's) default settings.
209 allowLanguageTextInput(FALSE);
210
114 GLuint pixel_format; 211 GLuint pixel_format;
115 WNDCLASS wc; 212 WNDCLASS wc;
116 DWORD dw_ex_style; 213 DWORD dw_ex_style;
@@ -347,7 +444,6 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
347 444
348 if (!mWindowHandle) 445 if (!mWindowHandle)
349 { 446 {
350 DestroyWindow(mWindowHandle);
351 OSMessageBox("Window creation error", "Error", OSMB_OK); 447 OSMessageBox("Window creation error", "Error", OSMB_OK);
352 return; 448 return;
353 } 449 }
@@ -1926,6 +2022,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
1926 case WM_CHAR: 2022 case WM_CHAR:
1927 // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need 2023 // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need
1928 // to figure out how that works. - Doug 2024 // to figure out how that works. - Doug
2025 //
2026 // ... Well, I don't think so.
2027 // How it works is explained in Win32 API document, but WM_UNICHAR didn't work
2028 // as specified at least on Windows XP SP1 Japanese version. I have never used
2029 // it since then, and I'm not sure whether it has been fixed now, but I don't think
2030 // it is worth trying. The good old WM_CHAR works just fine even for supplementary
2031 // characters. We just need to take care of surrogate pairs sent as two WM_CHAR's
2032 // by ourselves. It is not that tough. -- Alissa Sabre @ SL
2033 //
1929 // llinfos << "WM_CHAR: " << w_param << llendl; 2034 // llinfos << "WM_CHAR: " << w_param << llendl;
1930 if (gDebugWindowProc) 2035 if (gDebugWindowProc)
1931 { 2036 {
@@ -1933,11 +2038,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
1933 << " key " << S32(w_param) 2038 << " key " << S32(w_param)
1934 << llendl; 2039 << llendl;
1935 } 2040 }
1936 if (window_imp->mCallbacks->handleUnicodeChar(w_param, gKeyboard->currentMask(FALSE))) 2041 // Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE,
1937 { 2042 // we *did* processed the event, so I believe we should not pass it to DefWindowProc...
1938 return 0; 2043 window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
1939 } 2044 return 0;
1940 break;
1941 2045
1942 case WM_LBUTTONDOWN: 2046 case WM_LBUTTONDOWN:
1943 { 2047 {
@@ -2971,7 +3075,7 @@ void spawn_web_browser(const char* escaped_url )
2971 char reg_path_str[256]; /* Flawfinder: ignore */ 3075 char reg_path_str[256]; /* Flawfinder: ignore */
2972 snprintf(reg_path_str, sizeof(reg_path_str), "%s\\shell\\open\\command", gURLProtocolWhitelistHandler[i]); /* Flawfinder: ignore */ 3076 snprintf(reg_path_str, sizeof(reg_path_str), "%s\\shell\\open\\command", gURLProtocolWhitelistHandler[i]); /* Flawfinder: ignore */
2973 WCHAR reg_path_wstr[256]; 3077 WCHAR reg_path_wstr[256];
2974 mbstowcs(reg_path_wstr, reg_path_str, 1024); 3078 mbstowcs(reg_path_wstr, reg_path_str, sizeof(reg_path_wstr)/sizeof(reg_path_wstr[0]));
2975 3079
2976 HKEY key; 3080 HKEY key;
2977 WCHAR browser_open_wstr[1024]; 3081 WCHAR browser_open_wstr[1024];
@@ -3102,6 +3206,58 @@ void LLWindowWin32::bringToFront()
3102void LLWindowWin32::focusClient() 3206void LLWindowWin32::focusClient()
3103{ 3207{
3104 SetFocus ( mWindowHandle ); 3208 SetFocus ( mWindowHandle );
3105}; 3209}
3210
3211void LLWindowWin32::allowLanguageTextInput(BOOL b)
3212{
3213 if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable())
3214 {
3215 /* Not actually allowing/disallowing. Do nothing. */
3216 return;
3217 }
3218 sLanguageTextInputAllowed = b;
3219
3220 if (b)
3221 {
3222 /* Allowing: Restore the previous IME status,
3223 so that the user has a feeling that the previous
3224 text input continues naturally. Be careful, however,
3225 the IME status is meaningful only during the user keeps
3226 using same Input Locale (aka Keyboard Layout). */
3227 if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale)
3228 {
3229 HIMC himc = LLWinImm::getContext(mWindowHandle);
3230 LLWinImm::setOpenStatus(himc, TRUE);
3231 LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode);
3232 LLWinImm::releaseContext(mWindowHandle, himc);
3233 }
3234 }
3235 else
3236 {
3237 /* Disallowing: Turn off the IME so that succeeding
3238 key events bypass IME and come to us directly.
3239 However, do it after saving the current IME
3240 status. We need to restore the status when
3241 allowing language text input again. */
3242 sWinInputLocale = GetKeyboardLayout(0);
3243 sWinIMEOpened = LLWinImm::isIME(sWinInputLocale);
3244 if (sWinIMEOpened)
3245 {
3246 HIMC himc = LLWinImm::getContext(mWindowHandle);
3247 sWinIMEOpened = LLWinImm::getOpenStatus(himc);
3248 if (sWinIMEOpened)
3249 {
3250 LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode);
3251
3252 /* We need both ImmSetConversionStatus and ImmSetOpenStatus here
3253 to surely disable IME's keyboard hooking, because Some IME reacts
3254 only on the former and some other on the latter... */
3255 LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode);
3256 LLWinImm::setOpenStatus(himc, FALSE);
3257 }
3258 LLWinImm::releaseContext(mWindowHandle, himc);
3259 }
3260 }
3261}
3106 3262
3107#endif // LL_WINDOWS 3263#endif // LL_WINDOWS