diff options
Diffstat (limited to 'indra/llwindow')
-rw-r--r-- | indra/llwindow/CMakeLists.txt | 16 | ||||
-rw-r--r-- | indra/llwindow/lldxhardware.cpp | 2 | ||||
-rw-r--r-- | indra/llwindow/llkeyboardwin32.cpp | 24 | ||||
-rw-r--r-- | indra/llwindow/llopenglview-objc.mm | 7 | ||||
-rw-r--r-- | indra/llwindow/llwindow.cpp | 3 | ||||
-rw-r--r-- | indra/llwindow/llwindow.h | 3 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx-objc.h | 2 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx-objc.mm | 137 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx.cpp | 27 | ||||
-rw-r--r-- | indra/llwindow/llwindowmacosx.h | 1 | ||||
-rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 191 |
11 files changed, 245 insertions, 168 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index dbab58c5de..ca08e38f77 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -169,5 +169,17 @@ endif (llwindow_HEADER_FILES) ${viewer_SOURCE_FILES} ) -target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) -target_include_directories( llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +if (SDL_FOUND) + set_property(TARGET llwindow + PROPERTY COMPILE_DEFINITIONS LL_SDL=1 + ) +endif (SDL_FOUND) + + target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) + target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(CARBON_LIBRARY Carbon) + target_link_libraries(llwindow ${CARBON_LIBRARY}) +endif (DARWIN) diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp index 81e938edbe..391a377280 100644 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -1098,7 +1098,7 @@ LLSD LLDXHardware::getDisplayInfo() } LCleanup: - if (ret.emptyMap()) + if (!ret.isMap() || (ret.size() == 0)) { LL_INFOS() << "Failed to get data, cleaning up" << LL_ENDL; } diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index 2123ed3939..4c207faa81 100644 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -247,31 +247,9 @@ void LLKeyboardWin32::scanKeyboard() { S32 key; MSG msg; - BOOL pending_key_events = PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD); + PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD); for (key = 0; key < KEY_COUNT; key++) { - // On Windows, verify key down state. JC - // RN: only do this if we don't have further key events in the queue - // as otherwise there might be key repeat events still waiting for this key we are now dumping - if (!pending_key_events && mKeyLevel[key]) - { - // *TODO: I KNOW there must be a better way of - // interrogating the key state than this, using async key - // state can cause ALL kinds of bugs - Doug - if ((key < KEY_BUTTON0) && ((key < '0') || (key > '9'))) - { - // ...under windows make sure the key actually still is down. - // ...translate back to windows key - U16 virtual_key = inverseTranslateExtendedKey(key); - // keydown in highest bit - if (!pending_key_events && !(GetAsyncKeyState(virtual_key) & 0x8000)) - { - //LL_INFOS() << "Key up event missed, resetting" << LL_ENDL; - mKeyLevel[key] = FALSE; - } - } - } - // Generate callback if any event has occurred on this key this frame. // Can't just test mKeyLevel, because this could be a slow frame and // key might have gone down then up. JC diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 049226db65..7936245744 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -495,7 +495,12 @@ attributedStringInfo getSegments(NSAttributedString *str) // e.g. OS Window for upload something or Input Window... // mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit) mModifiers = [theEvent modifierFlags]; - unichar ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; + NSString *str_no_modifiers = [theEvent charactersIgnoringModifiers]; + unichar ch = 0; + if (str_no_modifiers.length) + { + ch = [str_no_modifiers characterAtIndex:0]; + } bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers, ch); if (acceptsText && diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index f4678a70c5..c5725677b4 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -117,7 +117,8 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags) mSwapMethod(SWAP_METHOD_UNDEFINED), mHideCursorPermanent(FALSE), mFlags(flags), - mHighSurrogate(0) + mHighSurrogate(0), + mRefreshRate(0) { } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0edf39f6ef..4380bbdb73 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -196,6 +196,8 @@ public: // windows only DirectInput8 for joysticks virtual void* getDirectInput8() { return NULL; }; virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; }; + + virtual S32 getRefreshRate() { return mRefreshRate; } protected: LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags); virtual ~LLWindow(); @@ -229,6 +231,7 @@ protected: U16 mHighSurrogate; S32 mMinWindowWidth; S32 mMinWindowHeight; + S32 mRefreshRate; // Handle a UTF-16 encoding unit received from keyboard. // Converting the series of UTF-16 encoding units to UTF-32 data, diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 43edc0110d..77024d3a9c 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -83,7 +83,7 @@ int createNSApp(int argc, const char **argv); void setupCocoa(); bool pasteBoardAvailable(); bool copyToPBoard(const unsigned short *str, unsigned int len); -const unsigned short *copyFromPBoard(); +unsigned short *copyFromPBoard(); CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY); short releaseImageCursor(CursorRef ref); short setImageCursor(CursorRef ref); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 5ec9b017cf..690fe058db 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -49,14 +49,12 @@ void setupCocoa() if(!inited) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents. - // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' - // when init'ing the Cocoa App window. - [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; - - [pool release]; + @autoreleasepool { + // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents. + // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' + // when init'ing the Cocoa App window. + [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; + } inited = true; } @@ -64,13 +62,13 @@ void setupCocoa() bool copyToPBoard(const unsigned short *str, unsigned int len) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - [pboard clearContents]; - - NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil]; - [pool release]; - return [pboard writeObjects:contentsToPaste]; + @autoreleasepool { + NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + [pboard clearContents]; + + NSArray *contentsToPaste = [[[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil] autorelease]; + return [pboard writeObjects:contentsToPaste]; + } } bool pasteBoardAvailable() @@ -79,39 +77,39 @@ bool pasteBoardAvailable() return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; } -const unsigned short *copyFromPBoard() +unsigned short *copyFromPBoard() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; - NSString *str = NULL; - BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; - if (ok) - { - NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; - str = [objToPaste objectAtIndex:0]; - } - unichar* temp = (unichar*)calloc([str length]+1, sizeof(unichar)); - [str getCharacters:temp]; - [pool release]; - return temp; + @autoreleasepool { + NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSString *str = NULL; + BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; + if (ok) + { + NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; + str = [objToPaste objectAtIndex:0]; + } + NSUInteger str_len = [str length]; + unichar* temp = (unichar*)calloc(str_len+1, sizeof(unichar)); + [str getCharacters:temp range:NSMakeRange(0, str_len)]; + return temp; + } } CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // extra retain on the NSCursor since we want it to live for the lifetime of the app. - NSCursor *cursor = - [[[NSCursor alloc] - initWithImage: - [[[NSImage alloc] initWithContentsOfFile: - [NSString stringWithUTF8String:fullpath] - ]autorelease] - hotSpot:NSMakePoint(hotspotX, hotspotY) - ]retain]; - - [pool release]; + NSCursor *cursor = nil; + @autoreleasepool { + // extra retain on the NSCursor since we want it to live for the lifetime of the app. + cursor = + [[[NSCursor alloc] + initWithImage: + [[[NSImage alloc] initWithContentsOfFile: + [NSString stringWithUTF8String:fullpath] + ] autorelease] + hotSpot:NSMakePoint(hotspotX, hotspotY) + ] retain]; + } return (CursorRef)cursor; } @@ -178,10 +176,10 @@ OSErr releaseImageCursor(CursorRef ref) { if( ref != NULL ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSCursor *cursor = (NSCursor*)ref; - [cursor release]; - [pool release]; + @autoreleasepool { + NSCursor *cursor = (NSCursor*)ref; + [cursor autorelease]; + } } else { @@ -195,10 +193,10 @@ OSErr setImageCursor(CursorRef ref) { if( ref != NULL ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSCursor *cursor = (NSCursor*)ref; - [cursor set]; - [pool release]; + @autoreleasepool { + NSCursor *cursor = (NSCursor*)ref; + [cursor set]; + } } else { @@ -217,6 +215,7 @@ NSWindowRef createNSWindow(int x, int y, int width, int height) styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO]; [window makeKeyAndOrderFront:nil]; [window setAcceptsMouseMovedEvents:TRUE]; + [window setRestorable:FALSE]; // Viewer manages state from own settings return window; } @@ -419,24 +418,26 @@ void requestUserAttention() long showAlert(std::string text, std::string title, int type) { - NSAlert *alert = [[NSAlert alloc] init]; - - [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]]; - [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]]; - if (type == 0) - { - [alert addButtonWithTitle:@"Okay"]; - } else if (type == 1) - { - [alert addButtonWithTitle:@"Okay"]; - [alert addButtonWithTitle:@"Cancel"]; - } else if (type == 2) - { - [alert addButtonWithTitle:@"Yes"]; - [alert addButtonWithTitle:@"No"]; + long ret = 0; + @autoreleasepool { + NSAlert *alert = [[[NSAlert alloc] init] autorelease]; + + [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]]; + [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]]; + if (type == 0) + { + [alert addButtonWithTitle:@"Okay"]; + } else if (type == 1) + { + [alert addButtonWithTitle:@"Okay"]; + [alert addButtonWithTitle:@"Cancel"]; + } else if (type == 2) + { + [alert addButtonWithTitle:@"Yes"]; + [alert addButtonWithTitle:@"No"]; + } + ret = [alert runModal]; } - long ret = [alert runModal]; - [alert dealloc]; if (ret == NSAlertFirstButtonReturn) { diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 22a5462c7f..2c841d4703 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -49,6 +49,8 @@ BOOL gHiDPISupport = TRUE; const S32 BITS_PER_PIXEL = 32; const S32 MAX_NUM_RESOLUTIONS = 32; +const S32 DEFAULT_REFRESH_RATE = 60; + namespace { NSKeyEventRef mRawKeyEvent = NULL; @@ -654,6 +656,13 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits } } + mRefreshRate = CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(mDisplay)); + if(mRefreshRate == 0) + { + //consider adding more appropriate fallback later + mRefreshRate = DEFAULT_REFRESH_RATE; + } + // Disable vertical sync for swap toggleVSync(enable_vsync); @@ -667,11 +676,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits if (cgl_err != kCGLNoError ) { - LL_DEBUGS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL; + LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL; } else { - LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; + LL_INFOS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; } } makeFirstResponder(mWindow, mGLView); @@ -1245,8 +1254,11 @@ BOOL LLWindowMacOSX::isClipboardTextAvailable() } BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) -{ - llutf16string str(copyFromPBoard()); +{ + unsigned short* pboard_data = copyFromPBoard(); // must free returned data + llutf16string str(pboard_data); + free(pboard_data); + dst = utf16str_to_wstring(str); if (dst != L"") { @@ -1279,7 +1291,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r { if (!mSupportedResolutions) { - CFArrayRef modes = CGDisplayAvailableModes(mDisplay); + CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, nullptr); if(modes != NULL) { @@ -1318,6 +1330,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r } } } + CFRelease(modes); } } @@ -1713,6 +1726,10 @@ void LLSplashScreenMacOSX::showImpl() void LLSplashScreenMacOSX::updateImpl(const std::string& mesg) { + if(mWindow != NULL) + { + CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8); + } } diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index b0f339e1db..851c860017 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -228,6 +228,7 @@ protected: BOOL mLanguageTextInputAllowed; LLPreeditor* mPreeditor; +public: static BOOL sUseMultGL; friend class LLWindowManager; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4c3aeb4695..2e560ddb0a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -583,7 +583,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, { current_refresh = 60; } - + mRefreshRate = current_refresh; //----------------------------------------------------------------------- // Drop resolution and go fullscreen // use a display mode with our desired size and depth, with a refresh @@ -874,21 +874,20 @@ void LLWindowWin32::close() // Restore gamma to the system values. restoreGamma(); - if (mhDC) - { - if (!ReleaseDC(mWindowHandle, mhDC)) - { - LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL; - } - mhDC = NULL; - } - LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; mWindowThread->post([=]() { if (IsWindow(mWindowHandle)) { + if (mhDC) + { + if (!ReleaseDC(mWindowHandle, mhDC)) + { + LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL; + } + } + // Make sure we don't leave a blank toolbar button. ShowWindow(mWindowHandle, SW_HIDE); @@ -914,6 +913,7 @@ void LLWindowWin32::close() // Even though the above lambda might not yet have run, we've already // bound mWindowHandle into it by value, which should suffice for the // operations we're asking. That's the last time WE should touch it. + mhDC = NULL; mWindowHandle = NULL; mWindowThread->close(); } @@ -1061,6 +1061,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO { current_refresh = 60; } + mRefreshRate = current_refresh; gGLManager.shutdownGL(); //destroy gl context @@ -1506,12 +1507,10 @@ const S32 max_format = (S32)num_formats - 1; { wglDeleteContext (mhRC); // Release The Rendering Context mhRC = 0; // Zero The Rendering Context - } - ReleaseDC (mWindowHandle, mhDC); // Release The Device Context - mhDC = 0; // Zero The Device Context } + // will release and recreate mhDC, mWindowHandle recreateWindow(window_rect, dw_ex_style, dw_style); RECT rect; @@ -1661,7 +1660,8 @@ const S32 max_format = (S32)num_formats - 1; void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style) { - auto oldHandle = mWindowHandle; + auto oldWindowHandle = mWindowHandle; + auto oldDCHandle = mhDC; // zero out mWindowHandle and mhDC before destroying window so window // thread falls back to peekmessage @@ -1673,7 +1673,8 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw auto window_work = [this, self=mWindowThread, - oldHandle, + oldWindowHandle, + oldDCHandle, // bind CreateWindowEx() parameters by value instead of // back-referencing LLWindowWin32 members windowClassName=mWindowClassName, @@ -1689,11 +1690,20 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw self->mWindowHandle = 0; self->mhDC = 0; - // important to call DestroyWindow() from the window thread - if (oldHandle && !destroy_window_handler(oldHandle)) + if (oldWindowHandle) { - LL_WARNS("Window") << "Failed to properly close window before recreating it!" - << LL_ENDL; + if (oldDCHandle && !ReleaseDC(oldWindowHandle, oldDCHandle)) + { + LL_WARNS("Window") << "Failed to ReleaseDC" << LL_ENDL; + } + + // important to call DestroyWindow() from the window thread + if (!destroy_window_handler(oldWindowHandle)) + { + + LL_WARNS("Window") << "Failed to properly close window before recreating it!" + << LL_ENDL; + } } auto handle = CreateWindowEx(dw_ex_style, @@ -1731,7 +1741,7 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw }; // But how we pass window_work to the window thread depends on whether we // already have a window handle. - if (! oldHandle) + if (!oldWindowHandle) { // Pass window_work using the WorkQueue: without an existing window // handle, the window thread can't call GetMessage(). @@ -1744,7 +1754,7 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw // PostMessage(oldHandle) because oldHandle won't be destroyed until // the window thread has retrieved and executed window_work. LL_DEBUGS("Window") << "posting window_work to message queue" << LL_ENDL; - mWindowThread->Post(oldHandle, window_work); + mWindowThread->Post(oldWindowHandle, window_work); } auto future = promise.get_future(); @@ -3058,18 +3068,54 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ { LLMutexLock lock(&window_imp->mRawMouseMutex); - S32 speed; - const S32 DEFAULT_SPEED(10); - SystemParametersInfo(SPI_GETMOUSESPEED, 0, &speed, 0); - if (speed == DEFAULT_SPEED) + bool absolute_coordinates = (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE); + + if (absolute_coordinates) { - window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX; - window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY; + static S32 prev_absolute_x = 0; + static S32 prev_absolute_y = 0; + S32 absolute_x; + S32 absolute_y; + + if ((raw->data.mouse.usFlags & 0x10) == 0x10) // touch screen? touch? Not defined in header + { + // touch screen spams (0,0) coordinates in a number of situations + // (0,0) might need to be filtered + absolute_x = raw->data.mouse.lLastX; + absolute_y = raw->data.mouse.lLastY; + } + else + { + bool v_desktop = (raw->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) == MOUSE_VIRTUAL_DESKTOP; + + S32 width = GetSystemMetrics(v_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); + S32 height = GetSystemMetrics(v_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); + + absolute_x = (raw->data.mouse.lLastX / 65535.0f) * width; + absolute_y = (raw->data.mouse.lLastY / 65535.0f) * height; + } + + window_imp->mRawMouseDelta.mX += absolute_x - prev_absolute_x; + window_imp->mRawMouseDelta.mY -= absolute_y - prev_absolute_y; + + prev_absolute_x = absolute_x; + prev_absolute_y = absolute_y; } else { - window_imp->mRawMouseDelta.mX += round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED); - window_imp->mRawMouseDelta.mY -= round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED); + S32 speed; + const S32 DEFAULT_SPEED(10); + SystemParametersInfo(SPI_GETMOUSESPEED, 0, &speed, 0); + if (speed == DEFAULT_SPEED) + { + window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX; + window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY; + } + else + { + window_imp->mRawMouseDelta.mX += round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED); + window_imp->mRawMouseDelta.mY -= round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED); + } } } } @@ -3859,42 +3905,48 @@ void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) sLanguageTextInputAllowed = b; - if ( sLanguageTextInputAllowed ) - { - // 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) - { - HIMC himc = LLWinImm::getContext(mWindowHandle); - LLWinImm::setOpenStatus(himc, TRUE); - LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode); - 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. - sWinInputLocale = GetKeyboardLayout(0); - sWinIMEOpened = LLWinImm::isIME(sWinInputLocale); - if (sWinIMEOpened) - { - HIMC himc = LLWinImm::getContext(mWindowHandle); - sWinIMEOpened = LLWinImm::getOpenStatus(himc); - if (sWinIMEOpened) - { - LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode); + if (sLanguageTextInputAllowed) + { + mWindowThread->post([=]() + { + // 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) + { + HIMC himc = LLWinImm::getContext(mWindowHandle); + LLWinImm::setOpenStatus(himc, TRUE); + LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode); + LLWinImm::releaseContext(mWindowHandle, himc); + } + }); + } + else + { + mWindowThread->post([=]() + { + // 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) + { + HIMC himc = LLWinImm::getContext(mWindowHandle); + sWinIMEOpened = LLWinImm::getOpenStatus(himc); + if (sWinIMEOpened) + { + 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... - LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode); - LLWinImm::setOpenStatus(himc, FALSE); - } - LLWinImm::releaseContext(mWindowHandle, himc); - } - } + // 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); + } + }); + } } void LLWindowWin32::fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds, @@ -4091,6 +4143,10 @@ void LLWindowWin32::handleStartCompositionMessage() void LLWindowWin32::handleCompositionMessage(const U32 indexes) { + if (!mPreeditor) + { + return; + } BOOL needs_update = FALSE; LLWString result_string; LLWString preedit_string; @@ -4206,7 +4262,10 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes) if (needs_update) { - mPreeditor->resetPreedit(); + if (preedit_string.length() != 0 || result_string.length() != 0) + { + mPreeditor->resetPreedit(); + } if (result_string.length() > 0) { @@ -4386,7 +4445,7 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res LLWString context = find_context(wtext, preedit, preedit_length, &context_offset); preedit -= context_offset; preedit_length = llmin(preedit_length, (S32)context.length() - preedit); - if (preedit_length && preedit >= 0) + if (preedit_length > 0 && preedit >= 0) { // IMR_DOCUMENTFEED may be called when we have an active preedit. // We should pass the context string *excluding* the preedit string. |