diff options
author | Jacek Antonelli | 2008-08-15 23:44:59 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:59 -0500 |
commit | a408bac29378072fbf36864164149458c978cfcc (patch) | |
tree | 67feccf1a5d3816611ba48d6762f86f0f7f4b1f6 /linden/indra/llwindow | |
parent | Second Life viewer sources 1.17.0.12 (diff) | |
download | meta-impy-a408bac29378072fbf36864164149458c978cfcc.zip meta-impy-a408bac29378072fbf36864164149458c978cfcc.tar.gz meta-impy-a408bac29378072fbf36864164149458c978cfcc.tar.bz2 meta-impy-a408bac29378072fbf36864164149458c978cfcc.tar.xz |
Second Life viewer sources 1.17.1.0
Diffstat (limited to 'linden/indra/llwindow')
-rw-r--r-- | linden/indra/llwindow/llwindow.cpp | 50 | ||||
-rw-r--r-- | linden/indra/llwindow/llwindow.h | 13 | ||||
-rw-r--r-- | linden/indra/llwindow/llwindowmacosx.cpp | 75 | ||||
-rw-r--r-- | linden/indra/llwindow/llwindowmacosx.h | 8 | ||||
-rw-r--r-- | linden/indra/llwindow/llwindowsdl.cpp | 7 | ||||
-rw-r--r-- | linden/indra/llwindow/llwindowwin32.cpp | 172 | ||||
-rw-r--r-- | linden/indra/llwindow/llwindowwin32.h | 11 |
7 files changed, 325 insertions, 11 deletions
diff --git a/linden/indra/llwindow/llwindow.cpp b/linden/indra/llwindow/llwindow.cpp index cad1dc4..faa5e61 100644 --- a/linden/indra/llwindow/llwindow.cpp +++ b/linden/indra/llwindow/llwindow.cpp | |||
@@ -241,7 +241,8 @@ LLWindow::LLWindow(BOOL fullscreen, U32 flags) | |||
241 | mIsMouseClipping(FALSE), | 241 | mIsMouseClipping(FALSE), |
242 | mSwapMethod(SWAP_METHOD_UNDEFINED), | 242 | mSwapMethod(SWAP_METHOD_UNDEFINED), |
243 | mHideCursorPermanent(FALSE), | 243 | mHideCursorPermanent(FALSE), |
244 | mFlags(flags) | 244 | mFlags(flags), |
245 | mHighSurrogate(0) | ||
245 | { | 246 | { |
246 | for (U32 i = 0; i < 6; i++) | 247 | for (U32 i = 0; i < 6; i++) |
247 | { | 248 | { |
@@ -296,6 +297,53 @@ void LLWindow::setCallbacks(LLWindowCallbacks *callbacks) | |||
296 | } | 297 | } |
297 | } | 298 | } |
298 | 299 | ||
300 | #define UTF16_IS_HIGH_SURROGATE(U) ((U16)((U) - 0xD800) < 0x0400) | ||
301 | #define UTF16_IS_LOW_SURROGATE(U) ((U16)((U) - 0xDC00) < 0x0400) | ||
302 | #define UTF16_SURROGATE_PAIR_TO_UTF32(H,L) (((H) << 10) + (L) - (0xD800 << 10) - 0xDC00 + 0x00010000) | ||
303 | |||
304 | void LLWindow::handleUnicodeUTF16(U16 utf16, MASK mask) | ||
305 | { | ||
306 | // Note that we could discard unpaired surrogates, but I'm | ||
307 | // following the Unicode Consortium's recommendation here; | ||
308 | // that is, to preserve those unpaired surrogates in UTF-32 | ||
309 | // values. _To_preserve_ means to pass to the callback in our | ||
310 | // context. | ||
311 | |||
312 | if (mHighSurrogate == 0) | ||
313 | { | ||
314 | if (UTF16_IS_HIGH_SURROGATE(utf16)) | ||
315 | { | ||
316 | mHighSurrogate = utf16; | ||
317 | } | ||
318 | else | ||
319 | { | ||
320 | mCallbacks->handleUnicodeChar(utf16, mask); | ||
321 | } | ||
322 | } | ||
323 | else | ||
324 | { | ||
325 | if (UTF16_IS_LOW_SURROGATE(utf16)) | ||
326 | { | ||
327 | /* A legal surrogate pair. */ | ||
328 | mCallbacks->handleUnicodeChar(UTF16_SURROGATE_PAIR_TO_UTF32(mHighSurrogate, utf16), mask); | ||
329 | mHighSurrogate = 0; | ||
330 | } | ||
331 | else if (UTF16_IS_HIGH_SURROGATE(utf16)) | ||
332 | { | ||
333 | /* Two consecutive high surrogates. */ | ||
334 | mCallbacks->handleUnicodeChar(mHighSurrogate, mask); | ||
335 | mHighSurrogate = utf16; | ||
336 | } | ||
337 | else | ||
338 | { | ||
339 | /* A non-low-surrogate preceeded by a high surrogate. */ | ||
340 | mCallbacks->handleUnicodeChar(mHighSurrogate, mask); | ||
341 | mHighSurrogate = 0; | ||
342 | mCallbacks->handleUnicodeChar(utf16, mask); | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
299 | // | 347 | // |
300 | // LLSplashScreen | 348 | // LLSplashScreen |
301 | // | 349 | // |
diff --git a/linden/indra/llwindow/llwindow.h b/linden/indra/llwindow/llwindow.h index 2bb49e9..1016bce 100644 --- a/linden/indra/llwindow/llwindow.h +++ b/linden/indra/llwindow/llwindow.h | |||
@@ -218,6 +218,10 @@ public: | |||
218 | // return a platform-specific window reference (HWND on Windows, WindowRef on the Mac) | 218 | // return a platform-specific window reference (HWND on Windows, WindowRef on the Mac) |
219 | virtual void *getPlatformWindow() = 0; | 219 | virtual void *getPlatformWindow() = 0; |
220 | 220 | ||
221 | // control platform's Language Text Input mechanisms. | ||
222 | virtual void allowLanguageTextInput( BOOL b ) {}; | ||
223 | virtual void setLanguageTextInput( LLCoordWindow pos ) {}; | ||
224 | |||
221 | protected: | 225 | protected: |
222 | LLWindow(BOOL fullscreen, U32 flags); | 226 | LLWindow(BOOL fullscreen, U32 flags); |
223 | virtual ~LLWindow() {} | 227 | virtual ~LLWindow() {} |
@@ -246,6 +250,15 @@ protected: | |||
246 | U32 mFlags; | 250 | U32 mFlags; |
247 | F32 mJoyAxis[6]; | 251 | F32 mJoyAxis[6]; |
248 | U8 mJoyButtonState[16]; | 252 | U8 mJoyButtonState[16]; |
253 | U16 mHighSurrogate; | ||
254 | |||
255 | // Handle a UTF-16 encoding unit received from keyboard. | ||
256 | // Converting the series of UTF-16 encoding units to UTF-32 data, | ||
257 | // this method passes the resulting UTF-32 data to mCallback's | ||
258 | // handleUnicodeChar. The mask should be that to be passed to the | ||
259 | // callback. This method uses mHighSurrogate as a dedicated work | ||
260 | // variable. | ||
261 | void handleUnicodeUTF16(U16 utf16, MASK mask); | ||
249 | 262 | ||
250 | friend class LLWindowManager; | 263 | friend class LLWindowManager; |
251 | }; | 264 | }; |
diff --git a/linden/indra/llwindow/llwindowmacosx.cpp b/linden/indra/llwindow/llwindowmacosx.cpp index 0c5d6ed..021d7a4 100644 --- a/linden/indra/llwindow/llwindowmacosx.cpp +++ b/linden/indra/llwindow/llwindowmacosx.cpp | |||
@@ -239,6 +239,10 @@ LLWindowMacOSX::LLWindowMacOSX(char *title, char *name, S32 x, S32 y, S32 width, | |||
239 | mNeedsResize = FALSE; | 239 | mNeedsResize = FALSE; |
240 | mOverrideAspectRatio = 0.f; | 240 | mOverrideAspectRatio = 0.f; |
241 | mMinimized = FALSE; | 241 | mMinimized = FALSE; |
242 | mTSMDocument = NULL; // Just in case. | ||
243 | mLanguageTextInputAllowed = FALSE; | ||
244 | mTSMScriptCode = 0; | ||
245 | mTSMLangCode = 0; | ||
242 | 246 | ||
243 | // For reasons that aren't clear to me, LLTimers seem to be created in the "started" state. | 247 | // For reasons that aren't clear to me, LLTimers seem to be created in the "started" state. |
244 | // Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state. | 248 | // Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state. |
@@ -479,6 +483,29 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits | |||
479 | 483 | ||
480 | } | 484 | } |
481 | 485 | ||
486 | { | ||
487 | // Create and initialize our TSM document for language text input. | ||
488 | // If an error occured, we can do nothing better than simply ignore it. | ||
489 | // mTSMDocument will be kept NULL in case. | ||
490 | if (mTSMDocument) | ||
491 | { | ||
492 | DeactivateTSMDocument(mTSMDocument); | ||
493 | DeleteTSMDocument(mTSMDocument); | ||
494 | mTSMDocument = NULL; | ||
495 | } | ||
496 | static InterfaceTypeList types = { kUnicodeDocument }; | ||
497 | OSErr err = NewTSMDocument(1, types, &mTSMDocument, 0); | ||
498 | if (err != noErr) | ||
499 | { | ||
500 | llwarns << "createContext: couldn't create a TSMDocument (" << err << ")" << llendl; | ||
501 | } | ||
502 | if (mTSMDocument) | ||
503 | { | ||
504 | UseInputWindow(mTSMDocument, TRUE); | ||
505 | ActivateTSMDocument(mTSMDocument); | ||
506 | } | ||
507 | } | ||
508 | |||
482 | if(mContext == NULL) | 509 | if(mContext == NULL) |
483 | { | 510 | { |
484 | AGLRendererInfo rendererInfo = NULL; | 511 | AGLRendererInfo rendererInfo = NULL; |
@@ -924,6 +951,15 @@ void LLWindowMacOSX::destroyContext() | |||
924 | mWindowHandlerRef = NULL; | 951 | mWindowHandlerRef = NULL; |
925 | } | 952 | } |
926 | 953 | ||
954 | // Cleanup any TSM document we created. | ||
955 | if(mTSMDocument != NULL) | ||
956 | { | ||
957 | llinfos << "destroyContext: deleting TSM document" << llendl; | ||
958 | DeactivateTSMDocument(mTSMDocument); | ||
959 | DeleteTSMDocument(mTSMDocument); | ||
960 | mTSMDocument = NULL; | ||
961 | } | ||
962 | |||
927 | // Close the window | 963 | // Close the window |
928 | if(mWindow != NULL) | 964 | if(mWindow != NULL) |
929 | { | 965 | { |
@@ -1529,7 +1565,7 @@ void LLWindowMacOSX::flashIcon(F32 seconds) | |||
1529 | OSErr err; | 1565 | OSErr err; |
1530 | 1566 | ||
1531 | mBounceTime = seconds; | 1567 | mBounceTime = seconds; |
1532 | memset(&mBounceRec, sizeof(mBounceRec), 0); | 1568 | memset(&mBounceRec, 0, sizeof(mBounceRec)); |
1533 | mBounceRec.qType = nmType; | 1569 | mBounceRec.qType = nmType; |
1534 | mBounceRec.nmMark = 1; | 1570 | mBounceRec.nmMark = 1; |
1535 | err = NMInstall(&mBounceRec); | 1571 | err = NMInstall(&mBounceRec); |
@@ -2241,6 +2277,10 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e | |||
2241 | switch(evtKind) | 2277 | switch(evtKind) |
2242 | { | 2278 | { |
2243 | case kEventWindowActivated: | 2279 | case kEventWindowActivated: |
2280 | if (mTSMDocument) | ||
2281 | { | ||
2282 | ActivateTSMDocument(mTSMDocument); | ||
2283 | } | ||
2244 | mCallbacks->handleFocus(this); | 2284 | mCallbacks->handleFocus(this); |
2245 | break; | 2285 | break; |
2246 | case kEventWindowDeactivated: | 2286 | case kEventWindowDeactivated: |
@@ -2952,4 +2992,37 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key) | |||
2952 | return int_value; // otherwise return the long value | 2992 | return int_value; // otherwise return the long value |
2953 | } | 2993 | } |
2954 | 2994 | ||
2995 | void LLWindowMacOSX::allowLanguageTextInput(BOOL b) | ||
2996 | { | ||
2997 | ScriptLanguageRecord script_language; | ||
2998 | |||
2999 | if (b == mLanguageTextInputAllowed) | ||
3000 | { | ||
3001 | return; | ||
3002 | } | ||
3003 | mLanguageTextInputAllowed = b; | ||
3004 | |||
3005 | if (b) | ||
3006 | { | ||
3007 | if (mTSMScriptCode != smRoman) | ||
3008 | { | ||
3009 | script_language.fScript = mTSMScriptCode; | ||
3010 | script_language.fLanguage = mTSMLangCode; | ||
3011 | SetTextServiceLanguage(&script_language); | ||
3012 | } | ||
3013 | } | ||
3014 | else | ||
3015 | { | ||
3016 | GetTextServiceLanguage(&script_language); | ||
3017 | mTSMScriptCode = script_language.fScript; | ||
3018 | mTSMLangCode = script_language.fLanguage; | ||
3019 | if (mTSMScriptCode != smRoman) | ||
3020 | { | ||
3021 | script_language.fScript = smRoman; | ||
3022 | script_language.fLanguage = langEnglish; | ||
3023 | SetTextServiceLanguage(&script_language); | ||
3024 | } | ||
3025 | } | ||
3026 | } | ||
3027 | |||
2955 | #endif // LL_DARWIN | 3028 | #endif // LL_DARWIN |
diff --git a/linden/indra/llwindow/llwindowmacosx.h b/linden/indra/llwindow/llwindowmacosx.h index 63d846e..01b9303 100644 --- a/linden/indra/llwindow/llwindowmacosx.h +++ b/linden/indra/llwindow/llwindowmacosx.h | |||
@@ -108,6 +108,8 @@ public: | |||
108 | /*virtual*/ void *getPlatformWindow(); | 108 | /*virtual*/ void *getPlatformWindow(); |
109 | /*virtual*/ void bringToFront() {}; | 109 | /*virtual*/ void bringToFront() {}; |
110 | 110 | ||
111 | /*virtual*/ void allowLanguageTextInput(BOOL b); | ||
112 | |||
111 | protected: | 113 | protected: |
112 | LLWindowMacOSX( | 114 | LLWindowMacOSX( |
113 | char *title, char *name, int x, int y, int width, int height, U32 flags, | 115 | char *title, char *name, int x, int y, int width, int height, U32 flags, |
@@ -183,6 +185,12 @@ protected: | |||
183 | NMRec mBounceRec; | 185 | NMRec mBounceRec; |
184 | LLTimer mBounceTimer; | 186 | LLTimer mBounceTimer; |
185 | 187 | ||
188 | // Imput method management through Text Service Manager. | ||
189 | TSMDocumentID mTSMDocument; | ||
190 | BOOL mLanguageTextInputAllowed; | ||
191 | ScriptCode mTSMScriptCode; | ||
192 | LangCode mTSMLangCode; | ||
193 | |||
186 | friend class LLWindowManager; | 194 | friend class LLWindowManager; |
187 | }; | 195 | }; |
188 | 196 | ||
diff --git a/linden/indra/llwindow/llwindowsdl.cpp b/linden/indra/llwindow/llwindowsdl.cpp index a1cdeb3..94111e7 100644 --- a/linden/indra/llwindow/llwindowsdl.cpp +++ b/linden/indra/llwindow/llwindowsdl.cpp | |||
@@ -42,7 +42,9 @@ | |||
42 | #include "indra_constants.h" | 42 | #include "indra_constants.h" |
43 | 43 | ||
44 | #if LL_GTK | 44 | #if LL_GTK |
45 | extern "C" { | ||
45 | # include "gtk/gtk.h" | 46 | # include "gtk/gtk.h" |
47 | } | ||
46 | #endif // LL_GTK | 48 | #endif // LL_GTK |
47 | 49 | ||
48 | #if LL_LINUX | 50 | #if LL_LINUX |
@@ -1984,7 +1986,10 @@ void LLWindowSDL::gatherInput() | |||
1984 | SDLReallyCaptureInput(TRUE); | 1986 | SDLReallyCaptureInput(TRUE); |
1985 | 1987 | ||
1986 | if (event.key.keysym.unicode) | 1988 | if (event.key.keysym.unicode) |
1987 | mCallbacks->handleUnicodeChar(event.key.keysym.unicode, gKeyboard->currentMask(FALSE)); | 1989 | { |
1990 | handleUnicodeUTF16(event.key.keysym.unicode, | ||
1991 | gKeyboard->currentMask(FALSE)); | ||
1992 | } | ||
1988 | break; | 1993 | break; |
1989 | 1994 | ||
1990 | case SDL_KEYUP: | 1995 | case SDL_KEYUP: |
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 |
85 | BOOL LLWindowWin32::sIsClassRegistered = FALSE; | 86 | BOOL LLWindowWin32::sIsClassRegistered = FALSE; |
86 | 87 | ||
88 | BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE; /* XXX */ | ||
89 | BOOL LLWindowWin32::sWinIMEOpened = FALSE; | ||
90 | HKL LLWindowWin32::sWinInputLocale; | ||
91 | DWORD LLWindowWin32::sWinIMEConversionMode; | ||
92 | DWORD 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 | |||
103 | class LLWinImm | ||
104 | { | ||
105 | public: | ||
106 | static bool isAvailable() { return sTheInstance.mHImmDll != NULL; } | ||
107 | |||
108 | public: | ||
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 | |||
118 | private: | ||
119 | LLWinImm(); | ||
120 | ~LLWinImm(); | ||
121 | |||
122 | private: | ||
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 | |||
132 | private: | ||
133 | HMODULE mHImmDll; | ||
134 | static LLWinImm sTheInstance; | ||
135 | }; | ||
136 | |||
137 | LLWinImm LLWinImm::sTheInstance; | ||
138 | |||
139 | LLWinImm::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 | |||
172 | LLWinImm::~LLWinImm() | ||
173 | { | ||
174 | if (mHImmDll != NULL) | ||
175 | { | ||
176 | FreeLibrary(mHImmDll); | ||
177 | mHImmDll = NULL; | ||
178 | } | ||
179 | } | ||
87 | 180 | ||
88 | 181 | ||
89 | LPDIRECTINPUT8 g_pDI = NULL; | 182 | LPDIRECTINPUT8 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() | |||
3102 | void LLWindowWin32::focusClient() | 3206 | void LLWindowWin32::focusClient() |
3103 | { | 3207 | { |
3104 | SetFocus ( mWindowHandle ); | 3208 | SetFocus ( mWindowHandle ); |
3105 | }; | 3209 | } |
3210 | |||
3211 | void 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 |
diff --git a/linden/indra/llwindow/llwindowwin32.h b/linden/indra/llwindow/llwindowwin32.h index 691c648..0f0cf7c 100644 --- a/linden/indra/llwindow/llwindowwin32.h +++ b/linden/indra/llwindow/llwindowwin32.h | |||
@@ -106,6 +106,8 @@ public: | |||
106 | /*virtual*/ void bringToFront(); | 106 | /*virtual*/ void bringToFront(); |
107 | /*virtual*/ void focusClient(); | 107 | /*virtual*/ void focusClient(); |
108 | 108 | ||
109 | /*virtual*/ void allowLanguageTextInput(BOOL b); | ||
110 | |||
109 | protected: | 111 | protected: |
110 | LLWindowWin32( | 112 | LLWindowWin32( |
111 | char *title, char *name, int x, int y, int width, int height, U32 flags, | 113 | char *title, char *name, int x, int y, int width, int height, U32 flags, |
@@ -174,6 +176,15 @@ protected: | |||
174 | BOOL mMousePositionModified; | 176 | BOOL mMousePositionModified; |
175 | BOOL mInputProcessingPaused; | 177 | BOOL mInputProcessingPaused; |
176 | 178 | ||
179 | // The following five variables are for Language Text Input control. | ||
180 | // They are all static, since one context is shared by all LLWindowWin32 | ||
181 | // instances. | ||
182 | static BOOL sLanguageTextInputAllowed; | ||
183 | static BOOL sWinIMEOpened; | ||
184 | static HKL sWinInputLocale; | ||
185 | static DWORD sWinIMEConversionMode; | ||
186 | static DWORD sWinIMESentenceMode; | ||
187 | |||
177 | friend class LLWindowManager; | 188 | friend class LLWindowManager; |
178 | }; | 189 | }; |
179 | 190 | ||