From 3a16a54452eee72535e15a738c3678dc5671e24e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 8 Jun 2021 19:17:47 +0300 Subject: SL-15359 out_of_range exception --- indra/llwindow/llwindowwin32.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b2b123f0da..1d6b14e3a0 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4260,7 +4260,8 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res S32 context_offset; LLWString context = find_context(wtext, preedit, preedit_length, &context_offset); preedit -= context_offset; - if (preedit_length) + preedit_length = llmin(preedit_length, (S32)context.length() - preedit); + if (preedit_length && preedit >= 0) { // IMR_DOCUMENTFEED may be called when we have an active preedit. // We should pass the context string *excluding* the preedit string. -- cgit v1.2.3 From 014dd037dde0a93f6c591618e4c111c6b598b60e Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 20 Sep 2021 21:22:17 +0000 Subject: SL-16043 Fix DisableVerticalSync, default DisableVerticalSync to off, remove broken frame limiter code (use vsync if you want to limit framerate). --- indra/llwindow/llwindowwin32.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b2b123f0da..585905893b 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -784,7 +784,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, LLCoordScreen windowPos(x,y); LLCoordScreen windowSize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top); - if (!switchContext(mFullscreen, windowSize, TRUE, &windowPos)) + if (!switchContext(mFullscreen, windowSize, disable_vsync, &windowPos)) { return; } @@ -1764,6 +1764,7 @@ const S32 max_format = (S32)num_formats - 1; else { LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL; + wglSwapIntervalEXT(1); } SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this); -- cgit v1.2.3 From a35544c701b223ba08f0607c872d8afbb08114f5 Mon Sep 17 00:00:00 2001 From: Ptolemy Date: Tue, 21 Sep 2021 15:56:18 -0700 Subject: SL-16027: Add Tracy OpenGL support --- indra/llwindow/llwindowwin32.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b2b123f0da..1b8881cc86 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1748,6 +1748,8 @@ const S32 max_format = (S32)num_formats - 1; return FALSE; } + LL_PROFILER_GPU_CONTEXT + if (!gGLManager.initGL()) { close(); @@ -3474,6 +3476,8 @@ BOOL LLWindowWin32::resetDisplayResolution() void LLWindowWin32::swapBuffers() { SwapBuffers(mhDC); + + LL_PROFILER_GPU_COLLECT } -- cgit v1.2.3 From 851fef680164e3472b0516e7237bbcc4a35bc5a3 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Tue, 28 Sep 2021 15:24:42 -0700 Subject: SL-16102 Set window title to agent name (child of SL-15999 Support for low overhead, non interactive viewer sessions) --- indra/llwindow/llwindowwin32.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b2b123f0da..dc3e77cc57 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1811,6 +1811,13 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); } +void LLWindowWin32::setTitle(const std::string title) +{ + // TODO: Do we need to use the wide string version of this call + // to support non-ascii usernames (and region names??) + SetWindowTextA(mWindowHandle, title.c_str()); +} + BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) { mMousePositionModified = TRUE; -- cgit v1.2.3 From 2148e4c731e1c0926c32fedb3e7047c96cd9eebf Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 1 Oct 2021 15:51:12 +0000 Subject: SL-16094 Move LLWindowWin32::mainWindowProc and Windows message handling to a background thread to prevent frame stalls in LLWindowWin32::gatherInput --- indra/llwindow/llwindowwin32.cpp | 2580 +++++++++++++++++++++----------------- 1 file changed, 1452 insertions(+), 1128 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 714e07da31..4ce7c30bef 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -28,6 +28,8 @@ #if LL_WINDOWS && !LL_MESA_HEADLESS +#define LL_WINDOW_SINGLE_THREADED 0 + #include "llwindowwin32.h" // LLWindow library includes @@ -45,6 +47,7 @@ #include "lldir.h" #include "llsdutil.h" #include "llglslshader.h" +#include "llthreadsafequeue.h" // System includes #include @@ -79,6 +82,18 @@ const F32 ICON_FLASH_TIME = 0.5f; extern BOOL gDebugWindowProc; +static std::thread::id sWindowThreadId; +static std::thread::id sMainThreadId; + +#if 1 || LL_WINDOW_SINGLE_THREADED +#define ASSERT_MAIN_THREAD() +#define ASSERT_WINDOW_THREAD() +#else +#define ASSERT_MAIN_THREAD() llassert(LLThread::currentID() == sMainThreadId) +#define ASSERT_WINDOW_THREAD() llassert(LLThread::currentID() == sWindowThreadId) +#endif + + LPWSTR gIconResource = IDI_APPLICATION; LPDIRECTINPUT8 gDirectInput8; @@ -294,7 +309,7 @@ LLWinImm::LLWinImm() : mHImmDll(NULL) // static -BOOL LLWinImm::isIME(HKL hkl) +BOOL LLWinImm::isIME(HKL hkl) { if ( sTheInstance.mImmIsIME ) return sTheInstance.mImmIsIME(hkl); @@ -326,7 +341,7 @@ BOOL LLWinImm::getOpenStatus(HIMC himc) } // static -BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) +BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) { if ( sTheInstance.mImmSetOpenStatus ) return sTheInstance.mImmSetOpenStatus(himc, status); @@ -454,6 +469,8 @@ private: static LLMonitorInfo sMonitorInfo; + + LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, @@ -463,7 +480,11 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, U32 fsaa_samples) : LLWindow(callbacks, fullscreen, flags) { - + sMainThreadId = LLThread::currentID(); + mWindowThread = new LLWindowWin32Thread(this); +#if !LL_WINDOW_SINGLE_THREADED + mWindowThread->start(); +#endif //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways LoadLibrary(L"opengl32.dll"); @@ -811,6 +832,8 @@ LLWindowWin32::~LLWindowWin32() delete [] mWindowClassName; mWindowClassName = NULL; + + delete mWindowThread; } void LLWindowWin32::show() @@ -930,26 +953,35 @@ void LLWindowWin32::close() LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; - if (IsWindow(mWindowHandle)) - { - // Make sure we don't leave a blank toolbar button. - ShowWindow(mWindowHandle, SW_HIDE); - - // This causes WM_DESTROY to be sent *immediately* - if (!destroy_window_handler(mWindowHandle)) + mWindowThread->post([=]() { - OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), - mCallbacks->translateString("MBShutdownErr"), - OSMB_OK); - } - } - else + if (IsWindow(mWindowHandle)) + { + // Make sure we don't leave a blank toolbar button. + ShowWindow(mWindowHandle, SW_HIDE); + + // This causes WM_DESTROY to be sent *immediately* + if (!destroy_window_handler(mWindowHandle)) + { + OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), + mCallbacks->translateString("MBShutdownErr"), + OSMB_OK); + } + } + else + { + // Something killed the window while we were busy destroying gl or handle somehow got broken + LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; + } + mWindowHandle = NULL; + + mWindowThread->mFinished = true; + }); + + while (!mWindowThread->isStopped()) { - // Something killed the window while we were busy destroying gl or handle somehow got broken - LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - - mWindowHandle = NULL; } BOOL LLWindowWin32::isValid() @@ -1090,171 +1122,203 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size) } // changing fullscreen resolution -BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) +BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL disable_vsync, const LLCoordScreen* const posp) { - GLuint pixel_format; - DEVMODE dev_mode; - ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); - dev_mode.dmSize = sizeof(DEVMODE); - DWORD current_refresh; - DWORD dw_ex_style; - DWORD dw_style; - RECT window_rect = {0, 0, 0, 0}; - S32 width = size.mX; - S32 height = size.mY; - BOOL auto_show = FALSE; - - if (mhRC) - { - auto_show = TRUE; - resetDisplayResolution(); - } - - if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) - { - current_refresh = dev_mode.dmDisplayFrequency; - } - else - { - current_refresh = 60; - } - - gGLManager.shutdownGL(); - //destroy gl context - if (mhRC) - { - if (!wglMakeCurrent(NULL, NULL)) - { - LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; - } + //called from main thread + GLuint pixel_format; + DEVMODE dev_mode; + ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); + dev_mode.dmSize = sizeof(DEVMODE); + DWORD current_refresh; + DWORD dw_ex_style; + DWORD dw_style; + RECT window_rect = { 0, 0, 0, 0 }; + S32 width = size.mX; + S32 height = size.mY; + BOOL auto_show = FALSE; + + if (mhRC) + { + auto_show = TRUE; + resetDisplayResolution(); + } - if (!wglDeleteContext(mhRC)) - { - LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; - } + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) + { + current_refresh = dev_mode.dmDisplayFrequency; + } + else + { + current_refresh = 60; + } - mhRC = NULL; - } + gGLManager.shutdownGL(); + //destroy gl context + if (mhRC) + { + if (!wglMakeCurrent(NULL, NULL)) + { + LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; + } - if (fullscreen) - { - mFullscreen = TRUE; - BOOL success = FALSE; - DWORD closest_refresh = 0; + if (!wglDeleteContext(mhRC)) + { + LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; + } - for (S32 mode_num = 0;; mode_num++) - { - if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) - { - break; - } + mhRC = NULL; + } - if (dev_mode.dmPelsWidth == width && - dev_mode.dmPelsHeight == height && - dev_mode.dmBitsPerPel == BITS_PER_PIXEL) - { - success = TRUE; - if ((dev_mode.dmDisplayFrequency - current_refresh) - < (closest_refresh - current_refresh)) - { - closest_refresh = dev_mode.dmDisplayFrequency; - } - } - } + if (fullscreen) + { + mFullscreen = TRUE; + BOOL success = FALSE; + DWORD closest_refresh = 0; - if (closest_refresh == 0) - { - LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; - return FALSE; - } + for (S32 mode_num = 0;; mode_num++) + { + if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) + { + break; + } - // If we found a good resolution, use it. - if (success) - { - success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); - } + if (dev_mode.dmPelsWidth == width && + dev_mode.dmPelsHeight == height && + dev_mode.dmBitsPerPel == BITS_PER_PIXEL) + { + success = TRUE; + if ((dev_mode.dmDisplayFrequency - current_refresh) + < (closest_refresh - current_refresh)) + { + closest_refresh = dev_mode.dmDisplayFrequency; + } + } + } - // Keep a copy of the actual current device mode in case we minimize - // and change the screen resolution. JC - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); + if (closest_refresh == 0) + { + LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; + return FALSE; + } - if (success) - { - mFullscreen = TRUE; - mFullscreenWidth = dev_mode.dmPelsWidth; - mFullscreenHeight = dev_mode.dmPelsHeight; - mFullscreenBits = dev_mode.dmBitsPerPel; - mFullscreenRefresh = dev_mode.dmDisplayFrequency; + // If we found a good resolution, use it. + if (success) + { + success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); + } - LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth - << "x" << dev_mode.dmPelsHeight - << "x" << dev_mode.dmBitsPerPel - << " @ " << dev_mode.dmDisplayFrequency - << LL_ENDL; + // Keep a copy of the actual current device mode in case we minimize + // and change the screen resolution. JC + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); - window_rect.left = (long) 0; - window_rect.right = (long) width; // Windows GDI rects don't include rightmost pixel - window_rect.top = (long) 0; - window_rect.bottom = (long) height; - dw_ex_style = WS_EX_APPWINDOW; - dw_style = WS_POPUP; + if (success) + { + mFullscreen = TRUE; + mFullscreenWidth = dev_mode.dmPelsWidth; + mFullscreenHeight = dev_mode.dmPelsHeight; + mFullscreenBits = dev_mode.dmBitsPerPel; + mFullscreenRefresh = dev_mode.dmDisplayFrequency; + + LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth + << "x" << dev_mode.dmPelsHeight + << "x" << dev_mode.dmBitsPerPel + << " @ " << dev_mode.dmDisplayFrequency + << LL_ENDL; + + window_rect.left = (long)0; + window_rect.right = (long)width; // Windows GDI rects don't include rightmost pixel + window_rect.top = (long)0; + window_rect.bottom = (long)height; + dw_ex_style = WS_EX_APPWINDOW; + dw_style = WS_POPUP; + + // Move window borders out not to cover window contents. + // This converts client rect to window rect, i.e. expands it by the window border size. + AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); + } + // If it failed, we don't want to run fullscreen + else + { + mFullscreen = FALSE; + mFullscreenWidth = -1; + mFullscreenHeight = -1; + mFullscreenBits = -1; + mFullscreenRefresh = -1; - // Move window borders out not to cover window contents. - // This converts client rect to window rect, i.e. expands it by the window border size. - AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); - } - // If it failed, we don't want to run fullscreen - else - { - mFullscreen = FALSE; - mFullscreenWidth = -1; - mFullscreenHeight = -1; - mFullscreenBits = -1; - mFullscreenRefresh = -1; + LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL; + return FALSE; + } + } + else + { + mFullscreen = FALSE; + window_rect.left = (long)(posp ? posp->mX : 0); + window_rect.right = (long)width + window_rect.left; // Windows GDI rects don't include rightmost pixel + window_rect.top = (long)(posp ? posp->mY : 0); + window_rect.bottom = (long)height + window_rect.top; + // Window with an edge + dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dw_style = WS_OVERLAPPEDWINDOW; + } - LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL; - return FALSE; - } - } - else - { - mFullscreen = FALSE; - window_rect.left = (long) (posp ? posp->mX : 0); - window_rect.right = (long) width + window_rect.left; // Windows GDI rects don't include rightmost pixel - window_rect.top = (long) (posp ? posp->mY : 0); - window_rect.bottom = (long) height + window_rect.top; - // Window with an edge - dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - dw_style = WS_OVERLAPPEDWINDOW; - } + // don't post quit messages when destroying old windows + mPostQuit = FALSE; - // don't post quit messages when destroying old windows - mPostQuit = FALSE; - // create window + // create window LL_DEBUGS("Window") << "Creating window with X: " << window_rect.left << " Y: " << window_rect.top << " Width: " << (window_rect.right - window_rect.left) << " Height: " << (window_rect.bottom - window_rect.top) << " Fullscreen: " << mFullscreen << LL_ENDL; - if (mWindowHandle && !destroy_window_handler(mWindowHandle)) + + auto oldHandle = mWindowHandle; + + //zero out mWindowHandle and mhDC before destroying window so window thread falls back to peekmessage + mWindowHandle = 0; + mhDC = 0; + + if (oldHandle && !destroy_window_handler(oldHandle)) { LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; - } - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); + } + + mWindowHandle = NULL; + mhDC = 0; + + mWindowThread->post( + [this, window_rect, dw_ex_style, dw_style]() + { + mWindowHandle = CreateWindowEx(dw_ex_style, + mWindowClassName, + mWindowTitle, + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, + window_rect.left, // x pos + window_rect.top, // y pos + window_rect.right - window_rect.left, // width + window_rect.bottom - window_rect.top, // height + NULL, + NULL, + mhInstance, + NULL); + + if (mWindowHandle) + { + mhDC = GetDC(mWindowHandle); + } + } + ); + + // HACK wait for above handle to become populated + // TODO: use a future + int count = 1024; + while (!mhDC && count > 0) + { + Sleep(10); + --count; + } if (mWindowHandle) { @@ -1288,7 +1352,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO 0, 0, 0 }; - if (!(mhDC = GetDC(mWindowHandle))) + if (!mhDC) { close(); OSMessageBox(mCallbacks->translateString("MBDevContextErr"), @@ -1582,25 +1646,48 @@ const S32 max_format = (S32)num_formats - 1; mhDC = 0; // Zero The Device Context } + auto oldHandle = mWindowHandle; + mWindowHandle = NULL; + mhDC = 0; + // Destroy The Window - if (mWindowHandle && !destroy_window_handler(mWindowHandle)) + if (oldHandle && !destroy_window_handler(oldHandle)) { LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL; } - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); + mWindowThread->post( + [this, window_rect, dw_ex_style, dw_style]() + { + mWindowHandle = CreateWindowEx(dw_ex_style, + mWindowClassName, + mWindowTitle, + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, + window_rect.left, // x pos + window_rect.top, // y pos + window_rect.right - window_rect.left, // width + window_rect.bottom - window_rect.top, // height + NULL, + NULL, + mhInstance, + NULL); + + if (mWindowHandle) + { + mhDC = GetDC(mWindowHandle); + } + } + ); + // HACK wait for above handle to become populated + // TODO: use a future + int count = 1024; + while (!mhDC && count > 0) + { + PostMessage(oldHandle, WM_USER + 8, 0x1717, 0x3b3b); + Sleep(10); + --count; + } if (mWindowHandle) { @@ -1612,7 +1699,7 @@ const S32 max_format = (S32)num_formats - 1; LL_WARNS("Window") << "Window recreation failed, code: " << GetLastError() << LL_ENDL; } - if (!(mhDC = GetDC(mWindowHandle))) + if (!mhDC) { close(); OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); @@ -1816,31 +1903,41 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) { - mMousePositionModified = TRUE; + ASSERT_MAIN_THREAD(); + if (!mWindowHandle) { return FALSE; } - - // Inform the application of the new mouse position (needed for per-frame + // Inform the application of the new mouse position (needed for per-frame // hover/picking to function). mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); - // DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. - // Because we have preemptively notified the application of the new - // mouse position via handleMouseMove() above, we need to clear out - // any stale mouse move events. RN/JC - MSG msg; - while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - { } - - LLCoordScreen screen_pos(position.convert()); - return ::SetCursorPos(screen_pos.mX, screen_pos.mY); + mMousePositionModified = TRUE; + LLCoordScreen screen_pos(position.convert()); + + mWindowThread->post([=] + { + SetCursorPos(screen_pos.mX, screen_pos.mY); + // DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. + // Because we have preemptively notified the application of the new + // mouse position via handleMouseMove() above, we need to clear out + // any stale mouse move events. RN/JC + MSG msg; + while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) + { + } + + mMousePositionModified = FALSE; + }); + + return TRUE; } BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) { + ASSERT_MAIN_THREAD(); POINT cursor_point; if (!mWindowHandle @@ -1856,21 +1953,35 @@ BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) void LLWindowWin32::hideCursor() { - while (ShowCursor(FALSE) >= 0) - { - // nothing, wait for cursor to push down - } + ASSERT_MAIN_THREAD(); + + mWindowThread->post([=]() + { + while (ShowCursor(FALSE) >= 0) + { + // nothing, wait for cursor to push down + } + }); + mCursorHidden = TRUE; mHideCursorPermanent = TRUE; } void LLWindowWin32::showCursor() { - // makes sure the cursor shows up - while (ShowCursor(TRUE) < 0) - { - // do nothing, wait for cursor to pop out - } + LL_PROFILE_ZONE_SCOPED; + + ASSERT_MAIN_THREAD(); + + mWindowThread->post([=]() + { + // makes sure the cursor shows up + while (ShowCursor(TRUE) < 0) + { + // do nothing, wait for cursor to pop out + } + }); + mCursorHidden = FALSE; mHideCursorPermanent = FALSE; } @@ -1972,6 +2083,8 @@ void LLWindowWin32::initCursors() void LLWindowWin32::updateCursor() { + ASSERT_MAIN_THREAD(); + LL_PROFILE_ZONE_SCOPED if (mNextCursor == UI_CURSOR_ARROW && mBusyCount > 0) { @@ -1981,7 +2094,11 @@ void LLWindowWin32::updateCursor() if( mCurrentCursor != mNextCursor ) { mCurrentCursor = mNextCursor; - SetCursor( mCursor[mNextCursor] ); + auto nextCursor = mCursor[mNextCursor]; + mWindowThread->post([=]() + { + SetCursor(nextCursor); + }); } } @@ -1997,13 +2114,8 @@ void LLWindowWin32::captureMouse() void LLWindowWin32::releaseMouse() { - // *NOTE:Mani ReleaseCapture will spawn new windows messages... - // which will in turn call our MainWindowProc. It therefore requires - // pausing *and more importantly resumption* of the mainlooptimeout... - // just like DispatchMessage below. - mCallbacks->handlePauseWatchdog(this); + LL_PROFILE_ZONE_SCOPED; ReleaseCapture(); - mCallbacks->handleResumeWatchdog(this); } @@ -2012,1003 +2124,1129 @@ void LLWindowWin32::delayInputProcessing() mInputProcessingPaused = TRUE; } + void LLWindowWin32::gatherInput() { - MSG msg; - int msg_count = 0; + ASSERT_MAIN_THREAD(); + LL_PROFILE_ZONE_SCOPED + MSG msg; - while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput"); - TranslateMessage(&msg); +#if LL_WINDOW_SINGLE_THREADED + int msg_count = 0; + + while ((msg_count < MAX_MESSAGE_PER_UPDATE)) + { + LL_PROFILE_ZONE_NAMED("gi - loop"); + ++msg_count; + { + LL_PROFILE_ZONE_NAMED("gi - PeekMessage"); + if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + break; + } + } - // turn watchdog off in here to not fail if windows is doing something wacky - mCallbacks->handlePauseWatchdog(this); - DispatchMessage(&msg); - mCallbacks->handleResumeWatchdog(this); - msg_count++; + { + LL_PROFILE_ZONE_NAMED("gi - translate"); + TranslateMessage(&msg); + } - if ( mInputProcessingPaused ) - { - break; - } - /* Attempted workaround for problem where typing fast and hitting - return would result in only part of the text being sent. JC + { + LL_PROFILE_ZONE_NAMED("gi - dispatch"); + DispatchMessage(&msg); + } - BOOL key_posted = TranslateMessage(&msg); - DispatchMessage(&msg); - msg_count++; + if (mInputProcessingPaused) + { + break; + } - // If a key was translated, a WM_CHAR might have been posted to the end - // of the event queue. We need it immediately. - if (key_posted && msg.message == WM_KEYDOWN) - { - if (PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - msg_count++; - } - } - */ - mCallbacks->handlePingWatchdog(this, "Main:AsyncCallbackGatherInput"); - // For async host by name support. Really hacky. - if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) - { - gAsyncMsgCallback(msg); - } - } + // For async host by name support. Really hacky. + if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) + { + LL_PROFILE_ZONE_NAMED("gi - callback"); + gAsyncMsgCallback(msg); + } + } +#else //multi-threaded window impl + { + if (mWindowThread->mFunctionQueue.size() > 0) + { + LL_PROFILE_ZONE_NAMED("gi - PostMessage"); + if (mWindowHandle) + { // post a nonsense user message to wake up the Window Thread in case any functions are pending + // and no windows events came through this frame + PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + } + } + + while (mWindowThread->mMessageQueue.tryPopBack(msg)) + { + LL_PROFILE_ZONE_NAMED("gi - message queue"); + if (mInputProcessingPaused) + { + continue; + } + + // For async host by name support. Really hacky. + if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) + { + LL_PROFILE_ZONE_NAMED("gi - callback"); + gAsyncMsgCallback(msg); + } + } + } + + { + LL_PROFILE_ZONE_NAMED("gi - function queue"); + //process any pending functions + std::function curFunc; + while (mFunctionQueue.tryPopBack(curFunc)) + { + curFunc(); + } + } +#endif mInputProcessingPaused = FALSE; updateCursor(); - - // clear this once we've processed all mouse messages that might have occurred after - // we slammed the mouse position - mMousePositionModified = FALSE; } static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard"); static LLTrace::BlockTimerStatHandle FTM_MOUSEHANDLER("Handle Mouse"); +#if LL_WINDOW_SINGLE_THREADED +#define WINDOW_IMP_POST(x) x +#else +#define WINDOW_IMP_POST(x) window_imp->post([=]() { x; }) +#endif + LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { - // Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN. - // This helps prevent avatar walking after maximizing the window by double-clicking the title bar. - static bool sHandleLeftMouseUp = true; + ASSERT_WINDOW_THREAD(); + LL_PROFILE_ZONE_SCOPED; - // Ignore the double click received right after activating app. - // This is to avoid triggering double click teleport after returning focus (see MAINT-3786). - static bool sHandleDoubleClick = true; + // Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN. + // This helps prevent avatar walking after maximizing the window by double-clicking the title bar. + static bool sHandleLeftMouseUp = true; - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( h_wnd, GWLP_USERDATA ); + // Ignore the double click received right after activating app. + // This is to avoid triggering double click teleport after returning focus (see MAINT-3786). + static bool sHandleDoubleClick = true; - bool debug_window_proc = gDebugWindowProc || debugLoggingEnabled("Window"); + LLWindowWin32* window_imp = (LLWindowWin32*)GetWindowLongPtr(h_wnd, GWLP_USERDATA); + bool debug_window_proc = false; // gDebugWindowProc || debugLoggingEnabled("Window"); - if (NULL != window_imp) - { - window_imp->mCallbacks->handleResumeWatchdog(window_imp); - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:StartWndProc"); - // Has user provided their own window callback? - if (NULL != window_imp->mWndProc) - { - if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) - { - // user has handled window message - return 0; - } - } + if (NULL != window_imp) + { + // Has user provided their own window callback? + if (NULL != window_imp->mWndProc) + { + LL_PROFILE_ZONE_NAMED("mwp - WndProc"); + if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) + { + // user has handled window message + return 0; + } + } - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:PreSwitchWndProc"); - - // Juggle to make sure we can get negative positions for when - // mouse is outside window. - LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); + // Juggle to make sure we can get negative positions for when + // mouse is outside window. + LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); - // This doesn't work, as LOWORD returns unsigned short. - //LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param)); - LLCoordGL gl_coord; + // This doesn't work, as LOWORD returns unsigned short. + //LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param)); + LLCoordGL gl_coord; - // pass along extended flag in mask - MASK mask = (l_param>>16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; - BOOL eat_keystroke = TRUE; + // pass along extended flag in mask + MASK mask = (l_param >> 16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; + BOOL eat_keystroke = TRUE; - switch(u_msg) - { - RECT update_rect; - S32 update_width; - S32 update_height; + switch (u_msg) + { + RECT update_rect; + S32 update_width; + S32 update_height; - case WM_TIMER: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_TIMER"); - window_imp->mCallbacks->handleTimerEvent(window_imp); - break; + case WM_TIMER: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_TIMER"); + WINDOW_IMP_POST(window_imp->mCallbacks->handleTimerEvent(window_imp)); + break; + } - case WM_DEVICECHANGE: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DEVICECHANGE"); - if (debug_window_proc) - { - LL_INFOS("Window") << " WM_DEVICECHANGE: wParam=" << w_param - << "; lParam=" << l_param << LL_ENDL; - } - if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL) - { - if (window_imp->mCallbacks->handleDeviceChange(window_imp)) - { - return 0; - } - } - break; - - case WM_PAINT: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PAINT"); - GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE); - update_width = update_rect.right - update_rect.left + 1; - update_height = update_rect.bottom - update_rect.top + 1; - window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top, - update_width, update_height); - break; - case WM_PARENTNOTIFY: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PARENTNOTIFY"); - u_msg = u_msg; - break; - - case WM_SETCURSOR: - // This message is sent whenever the cursor is moved in a window. - // You need to set the appropriate cursor appearance. - - // Only take control of cursor over client region of window - // This allows Windows(tm) to handle resize cursors, etc. - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETCURSOR"); - if (LOWORD(l_param) == HTCLIENT) - { - SetCursor(window_imp->mCursor[ window_imp->mCurrentCursor] ); - return 0; - } - break; - - case WM_ENTERMENULOOP: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ENTERMENULOOP"); - window_imp->mCallbacks->handleWindowBlock(window_imp); - break; - - case WM_EXITMENULOOP: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_EXITMENULOOP"); - window_imp->mCallbacks->handleWindowUnblock(window_imp); - break; - - case WM_ACTIVATEAPP: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATEAPP"); - { - // This message should be sent whenever the app gains or loses focus. - BOOL activating = (BOOL) w_param; - BOOL minimized = window_imp->getMinimized(); - - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC ActivateApp " - << " activating " << S32(activating) - << " minimized " << S32(minimized) - << " fullscreen " << S32(window_imp->mFullscreen) - << LL_ENDL; - } - - if (window_imp->mFullscreen) - { - // When we run fullscreen, restoring or minimizing the app needs - // to switch the screen resolution - if (activating) - { - window_imp->setFullscreenResolution(); - window_imp->restore(); - } - else - { - window_imp->minimize(); - window_imp->resetDisplayResolution(); - } - } - - if (!activating) - { - sHandleDoubleClick = false; - } - - window_imp->mCallbacks->handleActivateApp(window_imp, activating); - - break; - } - - case WM_ACTIVATE: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATE"); - { - // Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE - BOOL activating = (LOWORD(w_param) != WA_INACTIVE); - - BOOL minimized = BOOL(HIWORD(w_param)); - - if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } - - // JC - I'm not sure why, but if we don't report that we handled the - // WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work - // properly when we run fullscreen. - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC Activate " - << " activating " << S32(activating) - << " minimized " << S32(minimized) - << LL_ENDL; - } - - // Don't handle this. - break; - } - - case WM_QUERYOPEN: - // TODO: use this to return a nice icon - break; - - case WM_SYSCOMMAND: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSCOMMAND"); - switch(w_param) - { - case SC_KEYMENU: - // Disallow the ALT key from triggering the default system menu. - return 0; - - case SC_SCREENSAVE: - case SC_MONITORPOWER: - // eat screen save messages and prevent them! - return 0; - } - break; - - case WM_CLOSE: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CLOSE"); - // Will the app allow the window to close? - if (window_imp->mCallbacks->handleCloseRequest(window_imp)) - { - // Get the app to initiate cleanup. - window_imp->mCallbacks->handleQuit(window_imp); - // The app is responsible for calling destroyWindow when done with GL - } - return 0; - - case WM_DESTROY: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DESTROY"); - if (window_imp->shouldPostQuit()) - { - PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0 - } - return 0; - - case WM_COMMAND: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COMMAND"); - if (!HIWORD(w_param)) // this message is from a menu - { - window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param)); - } - break; - - case WM_SYSKEYDOWN: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSKEYDOWN"); - // allow system keys, such as ALT-F4 to be processed by Windows - eat_keystroke = FALSE; - case WM_KEYDOWN: - window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next - window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; - window_imp->mKeyVirtualKey = w_param; - window_imp->mRawMsg = u_msg; - window_imp->mRawWParam = w_param; - window_imp->mRawLParam = l_param; - - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN"); - { - if (debug_window_proc) - { - LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN " - << " key " << S32(w_param) - << LL_ENDL; - } - if(gKeyboard->handleKeyDown(w_param, mask) && eat_keystroke) - { - return 0; - } - // pass on to windows if we didn't handle it - break; - } - case WM_SYSKEYUP: - eat_keystroke = FALSE; - case WM_KEYUP: - { - window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; - window_imp->mKeyVirtualKey = w_param; - window_imp->mRawMsg = u_msg; - window_imp->mRawWParam = w_param; - window_imp->mRawLParam = l_param; - - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP"); - LL_RECORD_BLOCK_TIME(FTM_KEYHANDLER); - - if (debug_window_proc) - { - LL_INFOS("Window") << "Debug WindowProc WM_KEYUP " - << " key " << S32(w_param) - << LL_ENDL; - } - if (gKeyboard->handleKeyUp(w_param, mask) && eat_keystroke) - { - return 0; - } - - // pass on to windows - break; - } - case WM_IME_SETCONTEXT: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_SETCONTEXT"); - if (debug_window_proc) - { - LL_INFOS("Window") << "WM_IME_SETCONTEXT" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW; - // Invoke DefWinProc with the modified LPARAM. - } - break; - - case WM_IME_STARTCOMPOSITION: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_STARTCOMPOSITION"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_STARTCOMPOSITION" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->handleStartCompositionMessage(); - return 0; - } - break; - - case WM_IME_ENDCOMPOSITION: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_ENDCOMPOSITION"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_ENDCOMPOSITION" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - return 0; - } - break; - - case WM_IME_COMPOSITION: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_COMPOSITION"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_COMPOSITION" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->handleCompositionMessage(l_param); - return 0; - } - break; - - case WM_IME_REQUEST: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_REQUEST"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_REQUEST" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - LRESULT result = 0; - if (window_imp->handleImeRequests(w_param, l_param, &result)) - { - return result; - } - } - break; - - case WM_CHAR: - window_imp->mKeyCharCode = w_param; - window_imp->mRawMsg = u_msg; - window_imp->mRawWParam = w_param; - window_imp->mRawLParam = l_param; - - // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need - // to figure out how that works. - Doug - // - // ... Well, I don't think so. - // How it works is explained in Win32 API document, but WM_UNICHAR didn't work - // as specified at least on Windows XP SP1 Japanese version. I have never used - // it since then, and I'm not sure whether it has been fixed now, but I don't think - // it is worth trying. The good old WM_CHAR works just fine even for supplementary - // characters. We just need to take care of surrogate pairs sent as two WM_CHAR's - // by ourselves. It is not that tough. -- Alissa Sabre @ SL - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CHAR"); - if (debug_window_proc) - { - LL_INFOS("Window") << "Debug WindowProc WM_CHAR " - << " key " << S32(w_param) - << LL_ENDL; - } - // Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE, - // we *did* processed the event, so I believe we should not pass it to DefWindowProc... - window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE)); - return 0; + case WM_DEVICECHANGE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_DEVICECHANGE"); + if (debug_window_proc) + { + LL_INFOS("Window") << " WM_DEVICECHANGE: wParam=" << w_param + << "; lParam=" << l_param << LL_ENDL; + } + if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp)); + + return TRUE; + } + break; + } - case WM_NCLBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_NCLBUTTONDOWN"); - // A click in a non-client area, e.g. title bar or window border. - sHandleLeftMouseUp = false; - sHandleDoubleClick = true; - } - break; + case WM_PAINT: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_PAINT"); + GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE); + update_width = update_rect.right - update_rect.left + 1; + update_height = update_rect.bottom - update_rect.top + 1; + + WINDOW_IMP_POST(window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top, + update_width, update_height)); + break; + } + case WM_PARENTNOTIFY: + { + break; + } - case WM_LBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - sHandleLeftMouseUp = true; + case WM_SETCURSOR: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SETCURSOR"); + // This message is sent whenever the cursor is moved in a window. + // You need to set the appropriate cursor appearance. - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + // Only take control of cursor over client region of window + // This allows Windows(tm) to handle resize cursors, etc. + if (LOWORD(l_param) == HTCLIENT) + { + SetCursor(window_imp->mCursor[window_imp->mCurrentCursor]); + return 0; + } + break; + } + case WM_ENTERMENULOOP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_ENTERMENULOOP"); + WINDOW_IMP_POST(window_imp->mCallbacks->handleWindowBlock(window_imp)); + break; + } - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_EXITMENULOOP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_EXITMENULOOP"); + WINDOW_IMP_POST(window_imp->mCallbacks->handleWindowUnblock(window_imp)); + break; + } - case WM_LBUTTONDBLCLK: - //RN: ignore right button double clicks for now - //case WM_RBUTTONDBLCLK: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK"); + case WM_ACTIVATEAPP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_ACTIVATEAPP"); + window_imp->post([=]() + { + // This message should be sent whenever the app gains or loses focus. + BOOL activating = (BOOL)w_param; + BOOL minimized = window_imp->getMinimized(); + + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC ActivateApp " + << " activating " << S32(activating) + << " minimized " << S32(minimized) + << " fullscreen " << S32(window_imp->mFullscreen) + << LL_ENDL; + } + + if (window_imp->mFullscreen) + { + // When we run fullscreen, restoring or minimizing the app needs + // to switch the screen resolution + if (activating) + { + window_imp->setFullscreenResolution(); + window_imp->restore(); + } + else + { + window_imp->minimize(); + window_imp->resetDisplayResolution(); + } + } + + if (!activating) + { + sHandleDoubleClick = false; + } + + window_imp->mCallbacks->handleActivateApp(window_imp, activating); + }); + break; + } + case WM_ACTIVATE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_ACTIVATE"); + window_imp->post([=]() + { + // Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE + BOOL activating = (LOWORD(w_param) != WA_INACTIVE); + + BOOL minimized = BOOL(HIWORD(w_param)); + + if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + // JC - I'm not sure why, but if we don't report that we handled the + // WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work + // properly when we run fullscreen. + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC Activate " + << " activating " << S32(activating) + << " minimized " << S32(minimized) + << LL_ENDL; + } + }); + + break; + } - if (!sHandleDoubleClick) - { - sHandleDoubleClick = true; - break; - } + case WM_QUERYOPEN: + // TODO: use this to return a nice icon + break; - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask) ) - { - return 0; - } - } - break; + case WM_SYSCOMMAND: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SYSCOMMAND"); + switch (w_param) + { + case SC_KEYMENU: + // Disallow the ALT key from triggering the default system menu. + return 0; + + case SC_SCREENSAVE: + case SC_MONITORPOWER: + // eat screen save messages and prevent them! + return 0; + } + break; + } + case WM_CLOSE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_CLOSE"); + window_imp->post([=]() + { + // Will the app allow the window to close? + if (window_imp->mCallbacks->handleCloseRequest(window_imp)) + { + // Get the app to initiate cleanup. + window_imp->mCallbacks->handleQuit(window_imp); + // The app is responsible for calling destroyWindow when done with GL + } + }); + return 0; + } + case WM_DESTROY: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_DESTROY"); + if (window_imp->shouldPostQuit()) + { + PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0 + } + return 0; + } + case WM_COMMAND: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_COMMAND"); + if (!HIWORD(w_param)) // this message is from a menu + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param))); + } + break; + } + case WM_SYSKEYDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SYSKEYDOWN"); + // allow system keys, such as ALT-F4 to be processed by Windows + eat_keystroke = FALSE; + } + case WM_KEYDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_KEYDOWN"); + window_imp->post([=]() + { + window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next + window_imp->mKeyScanCode = (l_param >> 16) & 0xff; + window_imp->mKeyVirtualKey = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; + + { + if (debug_window_proc) + { + LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN " + << " key " << S32(w_param) + << LL_ENDL; + } + + gKeyboard->handleKeyDown(w_param, mask); + } + }); + return eat_keystroke; + } + case WM_SYSKEYUP: + eat_keystroke = FALSE; + case WM_KEYUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_KEYUP"); + window_imp->post([=]() + { + window_imp->mKeyScanCode = (l_param >> 16) & 0xff; + window_imp->mKeyVirtualKey = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; + + { + LL_RECORD_BLOCK_TIME(FTM_KEYHANDLER); + + if (debug_window_proc) + { + LL_INFOS("Window") << "Debug WindowProc WM_KEYUP " + << " key " << S32(w_param) + << LL_ENDL; + } + gKeyboard->handleKeyUp(w_param, mask); + } + }); + return eat_keystroke; + } + case WM_IME_SETCONTEXT: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_SETCONTEXT"); + if (debug_window_proc) + { + LL_INFOS("Window") << "WM_IME_SETCONTEXT" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW; + // Invoke DefWinProc with the modified LPARAM. + } + break; + } + case WM_IME_STARTCOMPOSITION: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_STARTCOMPOSITION"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_STARTCOMPOSITION" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->handleStartCompositionMessage()); + return 0; + } + break; + } + case WM_IME_ENDCOMPOSITION: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_ENDCOMPOSITION"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_ENDCOMPOSITION" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + return 0; + } + break; + } + case WM_IME_COMPOSITION: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_COMPOSITION"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_COMPOSITION" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->handleCompositionMessage(l_param)); + return 0; + } + break; + } + case WM_IME_REQUEST: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_REQUEST"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_REQUEST" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + LRESULT result; + window_imp->handleImeRequests(w_param, l_param, &result); + return result; + } + break; + } + case WM_CHAR: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_CHAR"); + window_imp->post([=]() + { + window_imp->mKeyCharCode = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; + + // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need + // to figure out how that works. - Doug + // + // ... Well, I don't think so. + // How it works is explained in Win32 API document, but WM_UNICHAR didn't work + // as specified at least on Windows XP SP1 Japanese version. I have never used + // it since then, and I'm not sure whether it has been fixed now, but I don't think + // it is worth trying. The good old WM_CHAR works just fine even for supplementary + // characters. We just need to take care of surrogate pairs sent as two WM_CHAR's + // by ourselves. It is not that tough. -- Alissa Sabre @ SL + if (debug_window_proc) + { + LL_INFOS("Window") << "Debug WindowProc WM_CHAR " + << " key " << S32(w_param) + << LL_ENDL; + } + // Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE, + // we *did* processed the event, so I believe we should not pass it to DefWindowProc... + window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE)); + }); + return 0; + } + case WM_NCLBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_NCLBUTTONDOWN"); + { + // A click in a non-client area, e.g. title bar or window border. + window_imp->post([=]() + { + sHandleLeftMouseUp = false; + sHandleDoubleClick = true; + }); + } + break; + } + case WM_LBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDOWN"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + window_imp->post([=]() + { + auto glc = gl_coord; + sHandleLeftMouseUp = true; + + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + // Because we move the cursor position in the app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + glc = cursor_coord_window.convert(); + } + else + { + glc = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCallbacks->handleMouseMove(window_imp, glc, mask); + window_imp->mCallbacks->handleMouseDown(window_imp, glc, mask); + }); + + return 0; + } + break; + } - case WM_LBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + case WM_LBUTTONDBLCLK: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDBLCLK"); + //RN: ignore right button double clicks for now + //case WM_RBUTTONDBLCLK: + if (!sHandleDoubleClick) + { + sHandleDoubleClick = true; + return 0; + } - if (!sHandleLeftMouseUp) - { - sHandleLeftMouseUp = true; - break; - } - sHandleDoubleClick = true; - - //if (gDebugClicks) - //{ - // LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; - //} - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + // Because we move the cursor position in the app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + gl_coord = cursor_coord_window.convert(); + } + else + { + gl_coord = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->post([=]() + { + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask); + }); + return 0; + } + case WM_LBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONUP"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + + if (!sHandleLeftMouseUp) + { + sHandleLeftMouseUp = true; + return 0; + } + sHandleDoubleClick = true; + window_imp->post([=]() + { + auto glc = gl_coord; + + //if (gDebugClicks) + //{ + // LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; + //} + // Because we move the cursor position in the app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + glc = cursor_coord_window.convert(); + } + else + { + glc = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCallbacks->handleMouseMove(window_imp, glc, mask); + window_imp->mCallbacks->handleMouseUp(window_imp, glc, mask); + }); + } + return 0; + } + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONDOWN"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->interruptLanguageTextInput()); + } + + // Because we move the cursor position in the llviewerapp, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + gl_coord = cursor_coord_window.convert(); + } + else + { + gl_coord = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->post([=]() + { + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask); + }); + } + return 0; + } + break; - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + case WM_RBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONUP"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + // Because we move the cursor position in the app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + gl_coord = cursor_coord_window.convert(); + } + else + { + gl_coord = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask)) + { + return 0; + } + } + } + break; - // Because we move the cursor position in the llviewerapp, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_MBUTTONDOWN: + // case WM_MBUTTONDBLCLK: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONDOWN"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + // Because we move the cursor position in tllviewerhe app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + gl_coord = cursor_coord_window.convert(); + } + else + { + gl_coord = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) + { + return 0; + } + } + } + break; - case WM_RBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_MBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONUP"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + // Because we move the cursor position in the llviewer app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + gl_coord = cursor_coord_window.convert(); + } + else + { + gl_coord = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) + { + return 0; + } + } + } + break; + case WM_XBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONDOWN"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + S32 button = GET_XBUTTON_WPARAM(w_param); + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + // Because we move the cursor position in tllviewerhe app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + gl_coord = cursor_coord_window.convert(); + } + else + { + gl_coord = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + if (window_imp->mCallbacks->handleOtherMouseDown(window_imp, gl_coord, mask, button + 3)) + { + return 0; + } + } + } + break; - case WM_MBUTTONDOWN: -// case WM_MBUTTONDBLCLK: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + case WM_XBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONUP"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + S32 button = GET_XBUTTON_WPARAM(w_param); + // Because we move the cursor position in the llviewer app, we need to query + // to find out where the cursor at the time the event is handled. + // If we don't do this, many clicks could get buffered up, and if the + // first click changes the cursor position, all subsequent clicks + // will occur at the wrong location. JC + if (window_imp->mMousePositionModified) + { + LLCoordWindow cursor_coord_window; + window_imp->getCursorPosition(&cursor_coord_window); + gl_coord = cursor_coord_window.convert(); + } + else + { + gl_coord = window_coord.convert(); + } + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + if (window_imp->mCallbacks->handleOtherMouseUp(window_imp, gl_coord, mask, button + 3)) + { + return 0; + } + } + } + break; - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_MOUSEWHEEL: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEWHEEL"); + static short z_delta = 0; - case WM_MBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; - case WM_XBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + RECT client_rect; - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseDown(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } - break; + // eat scroll events that occur outside our window, since we use mouse position to direct scroll + // instead of keyboard focus + // NOTE: mouse_coord is in *window* coordinates for scroll events + POINT mouse_coord = { (S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param) }; - case WM_XBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseUp(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } - break; + if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) + && GetClientRect(window_imp->mWindowHandle, &client_rect)) + { + // we have a valid mouse point and client rect + if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x + || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) + { + // mouse is outside of client rect, so don't do anything + return 0; + } + } - case WM_MOUSEWHEEL: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL"); - static short z_delta = 0; + S16 incoming_z_delta = HIWORD(w_param); + z_delta += incoming_z_delta; + // cout << "z_delta " << z_delta << endl; + + // current mouse wheels report changes in increments of zDelta (+120, -120) + // Future, higher resolution mouse wheels may report smaller deltas. + // So we sum the deltas and only act when we've exceeded WHEEL_DELTA + // + // If the user rapidly spins the wheel, we can get messages with + // large deltas, like 480 or so. Thus we need to scroll more quickly. + if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) + { + window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA); + z_delta = 0; + } + return 0; + } + /* + // TODO: add this after resolving _WIN32_WINNT issue + case WM_MOUSELEAVE: + { + window_imp->mCallbacks->handleMouseLeave(window_imp); + + // TRACKMOUSEEVENT track_mouse_event; + // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); + // track_mouse_event.dwFlags = TME_LEAVE; + // track_mouse_event.hwndTrack = h_wnd; + // track_mouse_event.dwHoverTime = HOVER_DEFAULT; + // TrackMouseEvent( &track_mouse_event ); + return 0; + } + */ + case WM_MOUSEHWHEEL: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEHWHEEL"); + static short h_delta = 0; - RECT client_rect; + RECT client_rect; - // eat scroll events that occur outside our window, since we use mouse position to direct scroll - // instead of keyboard focus - // NOTE: mouse_coord is in *window* coordinates for scroll events - POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)}; + // eat scroll events that occur outside our window, since we use mouse position to direct scroll + // instead of keyboard focus + // NOTE: mouse_coord is in *window* coordinates for scroll events + POINT mouse_coord = { (S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param) }; - if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) - && GetClientRect(window_imp->mWindowHandle, &client_rect)) - { - // we have a valid mouse point and client rect - if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x - || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) - { - // mouse is outside of client rect, so don't do anything - return 0; - } - } + if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) + && GetClientRect(window_imp->mWindowHandle, &client_rect)) + { + // we have a valid mouse point and client rect + if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x + || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) + { + // mouse is outside of client rect, so don't do anything + return 0; + } + } - S16 incoming_z_delta = HIWORD(w_param); - z_delta += incoming_z_delta; - // cout << "z_delta " << z_delta << endl; - - // current mouse wheels report changes in increments of zDelta (+120, -120) - // Future, higher resolution mouse wheels may report smaller deltas. - // So we sum the deltas and only act when we've exceeded WHEEL_DELTA - // - // If the user rapidly spins the wheel, we can get messages with - // large deltas, like 480 or so. Thus we need to scroll more quickly. - if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) - { - window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA); - z_delta = 0; - } - return 0; - } - /* - // TODO: add this after resolving _WIN32_WINNT issue - case WM_MOUSELEAVE: - { - window_imp->mCallbacks->handleMouseLeave(window_imp); - - // TRACKMOUSEEVENT track_mouse_event; - // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); - // track_mouse_event.dwFlags = TME_LEAVE; - // track_mouse_event.hwndTrack = h_wnd; - // track_mouse_event.dwHoverTime = HOVER_DEFAULT; - // TrackMouseEvent( &track_mouse_event ); - return 0; - } - */ - case WM_MOUSEHWHEEL: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEHWHEEL"); - static short h_delta = 0; + S16 incoming_h_delta = HIWORD(w_param); + h_delta += incoming_h_delta; - RECT client_rect; + // If the user rapidly spins the wheel, we can get messages with + // large deltas, like 480 or so. Thus we need to scroll more quickly. + if (h_delta <= -WHEEL_DELTA || WHEEL_DELTA <= h_delta) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleScrollHWheel(window_imp, h_delta / WHEEL_DELTA)); + h_delta = 0; + } + return 0; + } + // Handle mouse movement within the window + case WM_MOUSEMOVE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE"); + if (!window_imp->mMousePositionModified) + { + MASK mask = gKeyboard->currentMask(TRUE); + WINDOW_IMP_POST(window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask)); + } + return 0; + } - // eat scroll events that occur outside our window, since we use mouse position to direct scroll - // instead of keyboard focus - // NOTE: mouse_coord is in *window* coordinates for scroll events - POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)}; + case WM_GETMINMAXINFO: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_GETMINMAXINFO"); + LPMINMAXINFO min_max = (LPMINMAXINFO)l_param; + min_max->ptMinTrackSize.x = window_imp->mMinWindowWidth; + min_max->ptMinTrackSize.y = window_imp->mMinWindowHeight; + return 0; + } - if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) - && GetClientRect(window_imp->mWindowHandle, &client_rect)) - { - // we have a valid mouse point and client rect - if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x - || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) - { - // mouse is outside of client rect, so don't do anything - return 0; - } - } + case WM_SIZE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SIZE"); + S32 width = S32(LOWORD(l_param)); + S32 height = S32(HIWORD(l_param)); - S16 incoming_h_delta = HIWORD(w_param); - h_delta += incoming_h_delta; + if (debug_window_proc) + { + BOOL maximized = (w_param == SIZE_MAXIMIZED); + BOOL restored = (w_param == SIZE_RESTORED); + BOOL minimized = (w_param == SIZE_MINIMIZED); + + LL_INFOS("Window") << "WINDOWPROC Size " + << width << "x" << height + << " max " << S32(maximized) + << " min " << S32(minimized) + << " rest " << S32(restored) + << LL_ENDL; + } - // If the user rapidly spins the wheel, we can get messages with - // large deltas, like 480 or so. Thus we need to scroll more quickly. - if (h_delta <= -WHEEL_DELTA || WHEEL_DELTA <= h_delta) - { - window_imp->mCallbacks->handleScrollHWheel(window_imp, h_delta / WHEEL_DELTA); - h_delta = 0; - } - return 0; - } - // Handle mouse movement within the window - case WM_MOUSEMOVE: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE"); - MASK mask = gKeyboard->currentMask(TRUE); - window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask); - return 0; - } + // There's an odd behavior with WM_SIZE that I would call a bug. If + // the window is maximized, and you call MoveWindow() with a size smaller + // than a maximized window, it ends up sending WM_SIZE with w_param set + // to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work. + // (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see + // LLWindowWin32::moveWindow in this file). - case WM_GETMINMAXINFO: - { - LPMINMAXINFO min_max = (LPMINMAXINFO)l_param; - min_max->ptMinTrackSize.x = window_imp->mMinWindowWidth; - min_max->ptMinTrackSize.y = window_imp->mMinWindowHeight; - return 0; - } + // If we are now restored, but we weren't before, this + // means that the window was un-minimized. + if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, TRUE)); + } - case WM_SIZE: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SIZE"); - S32 width = S32( LOWORD(l_param) ); - S32 height = S32( HIWORD(l_param) ); + // handle case of window being maximized from fully minimized state + if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, TRUE)); + } - if (debug_window_proc) - { - BOOL maximized = ( w_param == SIZE_MAXIMIZED ); - BOOL restored = ( w_param == SIZE_RESTORED ); - BOOL minimized = ( w_param == SIZE_MINIMIZED ); - - LL_INFOS("Window") << "WINDOWPROC Size " - << width << "x" << height - << " max " << S32(maximized) - << " min " << S32(minimized) - << " rest " << S32(restored) - << LL_ENDL; - } + // Also handle the minimization case + if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, FALSE)); + } - // There's an odd behavior with WM_SIZE that I would call a bug. If - // the window is maximized, and you call MoveWindow() with a size smaller - // than a maximized window, it ends up sending WM_SIZE with w_param set - // to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work. - // (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see - // LLWindowWin32::moveWindow in this file). + // Actually resize all of our views + if (w_param != SIZE_MINIMIZED) + { + // Ignore updates for minimizing and minimized "windows" + WINDOW_IMP_POST(window_imp->mCallbacks->handleResize(window_imp, + LOWORD(l_param), + HIWORD(l_param))); + } - // If we are now restored, but we weren't before, this - // means that the window was un-minimized. - if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED) - { - window_imp->mCallbacks->handleActivate(window_imp, TRUE); - } + window_imp->mLastSizeWParam = w_param; - // handle case of window being maximized from fully minimized state - if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED) - { - window_imp->mCallbacks->handleActivate(window_imp, TRUE); - } + return 0; + } - // Also handle the minimization case - if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED) - { - window_imp->mCallbacks->handleActivate(window_imp, FALSE); - } + case WM_DPICHANGED: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_DPICHANGED"); + LPRECT lprc_new_scale; + F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI); + lprc_new_scale = (LPRECT)l_param; + S32 new_width = lprc_new_scale->right - lprc_new_scale->left; + S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top; + WINDOW_IMP_POST(window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height)); + + SetWindowPos(h_wnd, + HWND_TOP, + lprc_new_scale->left, + lprc_new_scale->top, + new_width, + new_height, + SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } - // Actually resize all of our views - if (w_param != SIZE_MINIMIZED) - { - // Ignore updates for minimizing and minimized "windows" - window_imp->mCallbacks->handleResize( window_imp, - LOWORD(l_param), - HIWORD(l_param) ); - } + case WM_SETFOCUS: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SETFOCUS"); + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL; + } + WINDOW_IMP_POST(window_imp->mCallbacks->handleFocus(window_imp)); + return 0; + } - window_imp->mLastSizeWParam = w_param; + case WM_KILLFOCUS: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_KILLFOCUS"); + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL; + } + WINDOW_IMP_POST(window_imp->mCallbacks->handleFocusLost(window_imp)); + return 0; + } - return 0; - } + case WM_COPYDATA: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_COPYDATA"); + { + // received a URL + PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT)l_param; + void* data = new U8[myCDS->cbData]; + memcpy(data, myCDS->lpData, myCDS->cbData); + auto myType = myCDS->dwData; + + window_imp->post([=]() + { + window_imp->mCallbacks->handleDataCopy(window_imp, myType, data); + delete[] data; + }); + }; + return 0; + + break; + } + case WM_SETTINGCHANGE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SETTINGCHANGE"); + if (w_param == SPI_SETMOUSEVANISH) + { + if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0)) + { + WINDOW_IMP_POST(window_imp->mMouseVanish = TRUE); + } + } + } + break; - case WM_DPICHANGED: - { - LPRECT lprc_new_scale; - F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI); - lprc_new_scale = (LPRECT)l_param; - S32 new_width = lprc_new_scale->right - lprc_new_scale->left; - S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top; - if (window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height)) - { - SetWindowPos(h_wnd, - HWND_TOP, - lprc_new_scale->left, - lprc_new_scale->top, - new_width, - new_height, - SWP_NOZORDER | SWP_NOACTIVATE); - } - return 0; - } - - case WM_SETFOCUS: - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL; - } - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS"); - window_imp->mCallbacks->handleFocus(window_imp); - return 0; - - case WM_KILLFOCUS: - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL; - } - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KILLFOCUS"); - window_imp->mCallbacks->handleFocusLost(window_imp); - return 0; - - case WM_COPYDATA: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); - // received a URL - PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; - window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); - }; - return 0; - - break; - - case WM_SETTINGCHANGE: - { - if (w_param == SPI_SETMOUSEVANISH) - { - if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0)) - { - window_imp->mMouseVanish = TRUE; - } - } - } - break; - default: - { - if (debug_window_proc) - { - LL_INFOS("Window") << "Unhandled windows message code: " << U32(u_msg) << LL_ENDL; - } - } - break; - } - - window_imp->mCallbacks->handlePauseWatchdog(window_imp); - } + //list of messages we get often that we don't care to log about + case WM_NCHITTEST: + case WM_NCMOUSEMOVE: + case WM_NCMOUSELEAVE: + case WM_MOVING: + case WM_MOVE: + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + break; + + default: + { + LL_PROFILE_ZONE_NAMED("mwp - default"); + if (debug_window_proc) + { + LL_INFOS("Window") << "Unhandled windows message code: 0x" << std::hex << U32(u_msg) << LL_ENDL; + } + } + break; + } + } else { // (NULL == window_imp) LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL; } - // pass unhandled messages down to Windows - return DefWindowProc(h_wnd, u_msg, w_param, l_param); + // pass unhandled messages down to Windows + LRESULT ret; + { + LL_PROFILE_ZONE_NAMED("mwp - DefWindowProc"); + ret = DefWindowProc(h_wnd, u_msg, w_param, l_param); + } + return ret; } BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) @@ -3187,6 +3425,8 @@ BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr) // Constrains the mouse to the window. void LLWindowWin32::setMouseClipping( BOOL b ) { + LL_PROFILE_ZONE_SCOPED; + ASSERT_MAIN_THREAD(); if( b != mIsMouseClipping ) { BOOL success = FALSE; @@ -3263,6 +3503,7 @@ F32 LLWindowWin32::getGamma() BOOL LLWindowWin32::restoreGamma() { + ASSERT_MAIN_THREAD(); if (mCustomGammaSet != FALSE) { LL_DEBUGS("Window") << "Restoring gamma" << LL_ENDL; @@ -3274,6 +3515,7 @@ BOOL LLWindowWin32::restoreGamma() BOOL LLWindowWin32::setGamma(const F32 gamma) { + ASSERT_MAIN_THREAD(); mCurrentGamma = gamma; //Get the previous gamma ramp to restore later. @@ -3312,6 +3554,7 @@ BOOL LLWindowWin32::setGamma(const F32 gamma) void LLWindowWin32::setFSAASamples(const U32 fsaa_samples) { + ASSERT_MAIN_THREAD(); mFSAASamples = fsaa_samples; } @@ -3322,6 +3565,7 @@ U32 LLWindowWin32::getFSAASamples() LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions) { + ASSERT_MAIN_THREAD(); if (!mSupportedResolutions) { mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; @@ -3476,6 +3720,7 @@ BOOL LLWindowWin32::resetDisplayResolution() void LLWindowWin32::swapBuffers() { + ASSERT_MAIN_THREAD(); SwapBuffers(mhDC); LL_PROFILER_GPU_COLLECT @@ -3951,6 +4196,7 @@ void LLWindowWin32::updateLanguageTextInputArea() void LLWindowWin32::interruptLanguageTextInput() { + ASSERT_MAIN_THREAD(); if (mPreeditor && LLWinImm::isAvailable()) { HIMC himc = LLWinImm::getContext(mWindowHandle); @@ -4153,6 +4399,7 @@ static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_leng // for files and via IDropTarget interface requests. LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ) { + ASSERT_MAIN_THREAD(); return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url ); } @@ -4201,6 +4448,7 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL; return FALSE; } + fillCharPosition(caret_coord, preedit_bounds, text_control, char_position); *result = 1; @@ -4408,3 +4656,79 @@ std::vector LLWindowWin32::getDynamicFallbackFontList() #endif // LL_WINDOWS + +inline LLWindowWin32Thread::LLWindowWin32Thread(LLWindowWin32* window) + : LLThread("Window Thread"), + mWindow(window), + mFunctionQueue(MAX_QUEUE_SIZE) +{ + +} + +inline void LLWindowWin32Thread::run() +{ + sWindowThreadId = getID(); + while (!mFinished) + { + LL_PROFILE_ZONE_SCOPED; + + + if (mWindow && mWindow->mWindowHandle != 0) + { + MSG msg; + BOOL status; + if (mWindow->mhDC == 0) + { + LL_PROFILE_ZONE_NAMED("w32t - PeekMessage"); + status = PeekMessage(&msg, mWindow->mWindowHandle, 0, 0, PM_REMOVE); + } + else + { + LL_PROFILE_ZONE_NAMED("w32t - GetMessage"); + status = GetMessage(&msg, mWindow->mWindowHandle, 0, 0); + } + if (status > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + + mMessageQueue.pushFront(msg); + } + } + + { + LL_PROFILE_ZONE_NAMED("w32t - Function Queue"); + //process any pending functions + std::function curFunc; + while (mFunctionQueue.tryPopBack(curFunc)) + { + curFunc(); + } + } + +#if 0 + { + LL_PROFILE_ZONE_NAMED("w32t - Sleep"); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +#endif + } +} + +void LLWindowWin32Thread::post(const std::function& func) +{ +#if LL_WINDOW_SINGLE_THREADED + func(); +#else + mFunctionQueue.pushFront(func); +#endif +} + +void LLWindowWin32::post(const std::function& func) +{ +#if LL_WINDOW_SINGLE_THREADED + func(); +#else + mFunctionQueue.pushFront(func); +#endif +} \ No newline at end of file -- cgit v1.2.3 From d00272e0cc9974f35a46f0c313ee2c0e11cddbda Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 11 Oct 2021 16:03:40 +0000 Subject: SL-16099 Multi-threaded OpenGL usage on Windows, enable Core Profile and VAOs by default. --- indra/llwindow/llwindowwin32.cpp | 129 +++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 53 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4ce7c30bef..12d4c6c30e 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1774,58 +1774,11 @@ const S32 max_format = (S32)num_formats - 1; mhRC = 0; if (wglCreateContextAttribsARB) { //attempt to create a specific versioned context - S32 attribs[] = - { //start at 4.2 - WGL_CONTEXT_MAJOR_VERSION_ARB, 4, - WGL_CONTEXT_MINOR_VERSION_ARB, 2, - WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, - 0 - }; - - bool done = false; - while (!done) - { - mhRC = wglCreateContextAttribsARB(mhDC, mhRC, attribs); - - if (!mhRC) - { - if (attribs[3] > 0) - { //decrement minor version - attribs[3]--; - } - else if (attribs[1] > 3) - { //decrement major version and start minor version over at 3 - attribs[1]--; - attribs[3] = 3; - } - else - { //we reached 3.0 and still failed, bail out - done = true; - } - } - else - { - LL_INFOS() << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << - (LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << LL_ENDL; - done = true; - - // force sNoFixedFunction iff we're trying to use nsight debugging which does not support many legacy API uses - - // nSight doesn't support use of legacy API funcs in the fixed function pipe - if (LLRender::sGLCoreProfile || LLRender::sNsightDebugSupport) - { - LLGLSLShader::sNoFixedFunction = true; - } - } - } - } - - if (!mhRC && !(mhRC = wglCreateContext(mhDC))) - { - close(); - OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); - return FALSE; + mhRC = (HGLRC) createSharedContext(); + if (!mhRC) + { + return FALSE; + } } if (!wglMakeCurrent(mhDC, mhRC)) @@ -1880,6 +1833,75 @@ const S32 max_format = (S32)num_formats - 1; return TRUE; } +void* LLWindowWin32::createSharedContext() +{ + S32 attribs[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, 4, + WGL_CONTEXT_MINOR_VERSION_ARB, 2, + WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, + 0 + }; + + HGLRC rc = wglCreateContextAttribsARB(mhDC, mhRC, attribs); + + bool done = false; + while (!done) + { + rc = wglCreateContextAttribsARB(mhDC, mhRC, attribs); + + if (!rc) + { + if (attribs[3] > 0) + { //decrement minor version + attribs[3]--; + } + else if (attribs[1] > 3) + { //decrement major version and start minor version over at 3 + attribs[1]--; + attribs[3] = 3; + } + else + { //we reached 3.0 and still failed, bail out + done = true; + } + } + else + { + LL_INFOS() << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << + (LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << LL_ENDL; + done = true; + + // force sNoFixedFunction iff we're trying to use nsight debugging which does not support many legacy API uses + + // nSight doesn't support use of legacy API funcs in the fixed function pipe + if (LLRender::sGLCoreProfile || LLRender::sNsightDebugSupport) + { + LLGLSLShader::sNoFixedFunction = true; + } + } + } + + if (!rc && !(rc = wglCreateContext(mhDC))) + { + close(); + OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); + } + + return rc; +} + +void LLWindowWin32::makeContextCurrent(void* contextPtr) +{ + wglMakeCurrent(mhDC, (HGLRC) contextPtr); +} + +void LLWindowWin32::destroySharedContext(void* contextPtr) +{ + wglDeleteContext((HGLRC)contextPtr); +} + void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size ) { if( mIsMouseClipping ) @@ -3720,6 +3742,7 @@ BOOL LLWindowWin32::resetDisplayResolution() void LLWindowWin32::swapBuffers() { + LL_PROFILE_ZONE_SCOPED; ASSERT_MAIN_THREAD(); SwapBuffers(mhDC); @@ -4731,4 +4754,4 @@ void LLWindowWin32::post(const std::function& func) #else mFunctionQueue.pushFront(func); #endif -} \ No newline at end of file +} -- cgit v1.2.3 From 5553d614211998b5a10529f6b3ec68d2b25dc07a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 22 Oct 2021 17:01:33 +0000 Subject: SL-16203 Fix for wonky handling of mouse deltas. --- indra/llwindow/llwindowwin32.cpp | 530 ++++++++++++++------------------------- 1 file changed, 195 insertions(+), 335 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 12d4c6c30e..bf78bcba29 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -28,8 +28,6 @@ #if LL_WINDOWS && !LL_MESA_HEADLESS -#define LL_WINDOW_SINGLE_THREADED 0 - #include "llwindowwin32.h" // LLWindow library includes @@ -85,7 +83,7 @@ extern BOOL gDebugWindowProc; static std::thread::id sWindowThreadId; static std::thread::id sMainThreadId; -#if 1 || LL_WINDOW_SINGLE_THREADED +#if 1 // flip to zero to enable assertions for functions being called from wrong thread #define ASSERT_MAIN_THREAD() #define ASSERT_WINDOW_THREAD() #else @@ -482,9 +480,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, { sMainThreadId = LLThread::currentID(); mWindowThread = new LLWindowWin32Thread(this); -#if !LL_WINDOW_SINGLE_THREADED mWindowThread->start(); -#endif //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways LoadLibrary(L"opengl32.dll"); @@ -492,7 +488,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mIconResource = gIconResource; mOverrideAspectRatio = 0.f; mNativeAspectRatio = 0.f; - mMousePositionModified = FALSE; mInputProcessingPaused = FALSE; mPreeditor = NULL; mKeyCharCode = 0; @@ -814,6 +809,13 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, initCursors(); setCursor( UI_CURSOR_ARROW ); + mRawMouse.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC + mRawMouse.usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE + mRawMouse.dwFlags = 0; // adds mouse and also ignores legacy mouse messages + mRawMouse.hwndTarget = 0; + + RegisterRawInputDevices(&mRawMouse, 1, sizeof(mRawMouse)); + // Initialize (boot strap) the Language text input management, // based on the system's (or user's) default settings. allowLanguageTextInput(NULL, FALSE); @@ -1927,31 +1929,26 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) { ASSERT_MAIN_THREAD(); - if (!mWindowHandle) - { - return FALSE; - } + if (!mWindowHandle) + { + return FALSE; + } - // Inform the application of the new mouse position (needed for per-frame - // hover/picking to function). - mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); - - mMousePositionModified = TRUE; LLCoordScreen screen_pos(position.convert()); - - mWindowThread->post([=] + + // instantly set the cursor position from the app's point of view + mCursorPosition = position; + mLastCursorPosition = position; + + // Inform the application of the new mouse position (needed for per-frame + // hover/picking to function). + mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); + + // actually set the cursor position on the window thread + mWindowThread->post([=]() { + // actually set the OS cursor position SetCursorPos(screen_pos.mX, screen_pos.mY); - // DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. - // Because we have preemptively notified the application of the new - // mouse position via handleMouseMove() above, we need to clear out - // any stale mouse move events. RN/JC - MSG msg; - while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - { - } - - mMousePositionModified = FALSE; }); return TRUE; @@ -1960,19 +1957,27 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) { ASSERT_MAIN_THREAD(); - POINT cursor_point; - - if (!mWindowHandle - || !GetCursorPos(&cursor_point) - || !position) - { - return FALSE; - } + if (!position) + { + return FALSE; + } - *position = LLCoordScreen(cursor_point.x, cursor_point.y).convert(); + *position = mCursorPosition; return TRUE; } +BOOL LLWindowWin32::getCursorDelta(LLCoordCommon* delta) +{ + if (delta == nullptr) + { + return FALSE; + } + + *delta = mMouseFrameDelta; + + return TRUE; +} + void LLWindowWin32::hideCursor() { ASSERT_MAIN_THREAD(); @@ -2153,34 +2158,31 @@ void LLWindowWin32::gatherInput() LL_PROFILE_ZONE_SCOPED MSG msg; -#if LL_WINDOW_SINGLE_THREADED - int msg_count = 0; - - while ((msg_count < MAX_MESSAGE_PER_UPDATE)) { - LL_PROFILE_ZONE_NAMED("gi - loop"); - ++msg_count; - { - LL_PROFILE_ZONE_NAMED("gi - PeekMessage"); - if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - break; - } - } + LLMutexLock lock(&mRawMouseMutex); + mMouseFrameDelta = mRawMouseDelta; - { - LL_PROFILE_ZONE_NAMED("gi - translate"); - TranslateMessage(&msg); - } + mRawMouseDelta.mX = 0; + mRawMouseDelta.mY = 0; + } - { - LL_PROFILE_ZONE_NAMED("gi - dispatch"); - DispatchMessage(&msg); - } + if (mWindowThread->mFunctionQueue.size() > 0) + { + LL_PROFILE_ZONE_NAMED("gi - PostMessage"); + if (mWindowHandle) + { // post a nonsense user message to wake up the Window Thread in case any functions are pending + // and no windows events came through this frame + PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + } + } + + while (mWindowThread->mMessageQueue.tryPopBack(msg)) + { + LL_PROFILE_ZONE_NAMED("gi - message queue"); if (mInputProcessingPaused) { - break; + continue; } // For async host by name support. Really hacky. @@ -2190,45 +2192,35 @@ void LLWindowWin32::gatherInput() gAsyncMsgCallback(msg); } } -#else //multi-threaded window impl + { - if (mWindowThread->mFunctionQueue.size() > 0) + LL_PROFILE_ZONE_NAMED("gi - function queue"); + //process any pending functions + std::function curFunc; + while (mFunctionQueue.tryPopBack(curFunc)) { - LL_PROFILE_ZONE_NAMED("gi - PostMessage"); - if (mWindowHandle) - { // post a nonsense user message to wake up the Window Thread in case any functions are pending - // and no windows events came through this frame - PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); - } + curFunc(); } - - while (mWindowThread->mMessageQueue.tryPopBack(msg)) - { - LL_PROFILE_ZONE_NAMED("gi - message queue"); - if (mInputProcessingPaused) - { - continue; - } + } - // For async host by name support. Really hacky. - if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) - { - LL_PROFILE_ZONE_NAMED("gi - callback"); - gAsyncMsgCallback(msg); - } - } + // send one and only one mouse move event per frame BEFORE handling mouse button presses + if (mLastCursorPosition != mCursorPosition) + { + LL_PROFILE_ZONE_NAMED("gi - mouse move"); + mCallbacks->handleMouseMove(this, mCursorPosition.convert(), mMouseMask); } + + mLastCursorPosition = mCursorPosition; { - LL_PROFILE_ZONE_NAMED("gi - function queue"); - //process any pending functions + LL_PROFILE_ZONE_NAMED("gi - mouse queue"); + // handle mouse button presses AFTER updating mouse cursor position std::function curFunc; - while (mFunctionQueue.tryPopBack(curFunc)) + while (mMouseQueue.tryPopBack(curFunc)) { curFunc(); } } -#endif mInputProcessingPaused = FALSE; @@ -2238,11 +2230,7 @@ void LLWindowWin32::gatherInput() static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard"); static LLTrace::BlockTimerStatHandle FTM_MOUSEHANDLER("Handle Mouse"); -#if LL_WINDOW_SINGLE_THREADED -#define WINDOW_IMP_POST(x) x -#else #define WINDOW_IMP_POST(x) window_imp->post([=]() { x; }) -#endif LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { @@ -2278,10 +2266,6 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // mouse is outside window. LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); - // This doesn't work, as LOWORD returns unsigned short. - //LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param)); - LLCoordGL gl_coord; - // pass along extended flag in mask MASK mask = (l_param >> 16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; BOOL eat_keystroke = TRUE; @@ -2665,35 +2649,19 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - window_imp->post([=]() + window_imp->postMouseButtonEvent([=]() { - auto glc = gl_coord; sHandleLeftMouseUp = true; - + if (LLWinImm::isAvailable() && window_imp->mPreeditor) { window_imp->interruptLanguageTextInput(); } - - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - glc = cursor_coord_window.convert(); - } - else - { - glc = window_coord.convert(); - } + MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, glc, mask); - window_imp->mCallbacks->handleMouseDown(window_imp, glc, mask); + auto gl_coord = window_imp->mCursorPosition.convert(); + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask); }); return 0; @@ -2704,77 +2672,43 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_LBUTTONDBLCLK: { LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDBLCLK"); - //RN: ignore right button double clicks for now - //case WM_RBUTTONDBLCLK: - if (!sHandleDoubleClick) - { - sHandleDoubleClick = true; - return 0; - } - - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->post([=]() + window_imp->postMouseButtonEvent([=]() { - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask); + //RN: ignore right button double clicks for now + //case WM_RBUTTONDBLCLK: + if (!sHandleDoubleClick) + { + sHandleDoubleClick = true; + return; + } + MASK mask = gKeyboard->currentMask(TRUE); + + // generate move event to update mouse coordinates + window_imp->mCursorPosition = window_coord; + window_imp->mCallbacks->handleDoubleClick(window_imp, window_imp->mCursorPosition.convert(), mask); }); + return 0; } case WM_LBUTTONUP: { LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONUP"); { - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - - if (!sHandleLeftMouseUp) - { - sHandleLeftMouseUp = true; - return 0; - } - sHandleDoubleClick = true; - window_imp->post([=]() + window_imp->postMouseButtonEvent([=]() { - auto glc = gl_coord; - - //if (gDebugClicks) - //{ - // LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; - //} - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + if (!sHandleLeftMouseUp) { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - glc = cursor_coord_window.convert(); - } - else - { - glc = window_coord.convert(); + sHandleLeftMouseUp = true; + return; } + sHandleDoubleClick = true; + + MASK mask = gKeyboard->currentMask(TRUE); // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, glc, mask); - window_imp->mCallbacks->handleMouseUp(window_imp, glc, mask); + window_imp->mCursorPosition = window_coord; + window_imp->mCallbacks->handleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); }); } return 0; @@ -2785,30 +2719,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - WINDOW_IMP_POST(window_imp->interruptLanguageTextInput()); - } - - // Because we move the cursor position in the llviewerapp, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates window_imp->post([=]() { + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->interruptLanguageTextInput()); + } + + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + auto gl_coord = window_imp->mCursorPosition.convert(); window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask); }); @@ -2822,28 +2742,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONUP"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } + window_imp->postMouseButtonEvent([=]() + { + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleRightMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); + }); } } break; @@ -2854,33 +2757,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + window_imp->postMouseButtonEvent([=]() + { + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleMiddleMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask); + }); } } break; @@ -2890,99 +2776,47 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONUP"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } + window_imp->postMouseButtonEvent([=]() + { + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleMiddleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); + }); } } break; case WM_XBUTTONDOWN: { LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONDOWN"); - { - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) + window_imp->postMouseButtonEvent([=]() { - window_imp->interruptLanguageTextInput(); - } + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + S32 button = GET_XBUTTON_WPARAM(w_param); + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseDown(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } + MASK mask = gKeyboard->currentMask(TRUE); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + window_imp->mCallbacks->handleOtherMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3); + }); + } break; case WM_XBUTTONUP: { LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONUP"); - { - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) + window_imp->postMouseButtonEvent([=]() { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseUp(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } + + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + + S32 button = GET_XBUTTON_WPARAM(w_param); + MASK mask = gKeyboard->currentMask(TRUE); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + window_imp->mCallbacks->handleOtherMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3); + }); } break; @@ -3022,7 +2856,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // large deltas, like 480 or so. Thus we need to scroll more quickly. if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) { - window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA); + short clicks = -z_delta / WHEEL_DELTA; + WINDOW_IMP_POST(window_imp->mCallbacks->handleScrollWheel(window_imp, clicks)); z_delta = 0; } return 0; @@ -3082,11 +2917,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MOUSEMOVE: { LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE"); - if (!window_imp->mMousePositionModified) - { - MASK mask = gKeyboard->currentMask(TRUE); - WINDOW_IMP_POST(window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask)); - } + // DO NOT use mouse event queue for move events to ensure cursor position is updated + // when button events are handled + WINDOW_IMP_POST( + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE lambda"); + + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mMouseMask = mask; + window_imp->mCursorPosition = window_coord; + }); return 0; } @@ -3235,6 +3075,28 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } break; + case WM_INPUT: + { + LL_PROFILE_ZONE_NAMED("MWP - WM_INPUT"); + + UINT dwSize = 0; + GetRawInputData((HRAWINPUT)l_param, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); + llassert(dwSize < 1024); + + U8 lpb[1024]; + + if (GetRawInputData((HRAWINPUT)l_param, RID_INPUT, (void*)lpb, &dwSize, sizeof(RAWINPUTHEADER)) == dwSize) + { + RAWINPUT* raw = (RAWINPUT*)lpb; + + if (raw->header.dwType == RIM_TYPEMOUSE) + { + LLMutexLock lock(&window_imp->mRawMouseMutex); + window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX; + window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY; + } + } + } //list of messages we get often that we don't care to log about case WM_NCHITTEST: case WM_NCMOUSEMOVE: @@ -4740,18 +4602,16 @@ inline void LLWindowWin32Thread::run() void LLWindowWin32Thread::post(const std::function& func) { -#if LL_WINDOW_SINGLE_THREADED - func(); -#else mFunctionQueue.pushFront(func); -#endif } void LLWindowWin32::post(const std::function& func) { -#if LL_WINDOW_SINGLE_THREADED - func(); -#else mFunctionQueue.pushFront(func); -#endif } + +void LLWindowWin32::postMouseButtonEvent(const std::function& func) +{ + mMouseQueue.pushFront(func); +} + -- cgit v1.2.3 From 68b75be652575ff301172b7b19522d4f0494bdf0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 28 Oct 2021 22:09:22 +0000 Subject: SL-9436 Don't render 100% transparent objects. --- indra/llwindow/llwindowwin32.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 26bb56d72d..70cf839510 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -982,6 +982,8 @@ void LLWindowWin32::close() while (!mWindowThread->isStopped()) { + //nudge window thread + PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } -- cgit v1.2.3 From b6afa7f7dd5eb4f6df9580a25fbffb491ccef921 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 5 Nov 2021 17:48:40 +0200 Subject: SL-16288 FIXED Dragging a file across the viewer cancels the drag and freezes the File Explorer --- indra/llwindow/llwindowwin32.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 70cf839510..dddc8deb02 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -2202,6 +2202,17 @@ void LLWindowWin32::gatherInput() } } + { + LL_PROFILE_ZONE_NAMED("gi - PeekMessage"); + S32 msg_count = 0; + while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + msg_count++; + } + } + { LL_PROFILE_ZONE_NAMED("gi - function queue"); //process any pending functions -- cgit v1.2.3 From c7af4921db7f62005f3f668ca7fca45d01d80781 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 5 Nov 2021 17:20:11 -0400 Subject: SL-16094: Use ThreadPool for LLWindowWin32Thread. Move the whole LLWindowWin32Thread class inside LLWindowWin32, and make it a struct. Migrate the struct declaration to llwindowwin32.cpp. Derive it from ThreadPool, which provides the WorkQueue. Use runPending() instead of manually popping and running individual queue items. Make its post() operation always PostMessage(bogus) whenever we put an entry in the WorkQueue, so we won't remain blocked in GetMessage(). Instead of storing a back pointer to the LLWindowWin32 instance, store the relevant HWND and HDC in LLWindowWin32Thread itself to avoid cross-thread timing problems. Extract both instances of a large duplicated block of LLWindowWin32 code to a new recreateWindow() method, and call it in those places. Per the TODO, use a std::future to pass the new HWND and HDC back to LLWindowWin32 -- but also store them locally on the LLWindowWin32Thread instance. --- indra/llwindow/llwindowwin32.cpp | 240 ++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 131 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 70cf839510..4b40fae1bf 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -55,6 +55,8 @@ #include #include #include +#include +#include // std::pair // Require DirectInput version 8 #define DIRECTINPUT_VERSION 0x0800 @@ -468,6 +470,37 @@ private: static LLMonitorInfo sMonitorInfo; +// Thread that owns the Window Handle +// This whole struct is private to LLWindowWin32, which needs to mess with its +// members, which is why it's a struct rather than a class. In effect, we make +// the containing class a friend. +struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool +{ + static const int MAX_QUEUE_SIZE = 2048; + + LLThreadSafeQueue mMessageQueue; + + LLWindowWin32Thread(); + + void run() override; + + template + void post(CALLABLE&& func) + { + getQueue().post(std::forward(func)); + // bump us out of blocked GetMessage() call + if (mWindowHandle) + { + PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + } + } + + // call PeekMessage and pull enqueue messages for later processing + void gatherInput(); + HWND mWindowHandle = NULL; + HDC mhDC = 0; +}; + LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, @@ -479,8 +512,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, : LLWindow(callbacks, fullscreen, flags) { sMainThreadId = LLThread::currentID(); - mWindowThread = new LLWindowWin32Thread(this); - mWindowThread->start(); + mWindowThread = new LLWindowWin32Thread(); //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways LoadLibrary(L"opengl32.dll"); @@ -975,17 +1007,13 @@ void LLWindowWin32::close() // Something killed the window while we were busy destroying gl or handle somehow got broken LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; } - mWindowHandle = NULL; - mWindowThread->mFinished = true; }); - - while (!mWindowThread->isStopped()) - { - //nudge window thread - PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + // 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. + mWindowHandle = NULL; + mWindowThread->close(); } BOOL LLWindowWin32::isValid() @@ -1278,51 +1306,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO << " Fullscreen: " << mFullscreen << LL_ENDL; - auto oldHandle = mWindowHandle; - - //zero out mWindowHandle and mhDC before destroying window so window thread falls back to peekmessage - mWindowHandle = 0; - mhDC = 0; - - if (oldHandle && !destroy_window_handler(oldHandle)) - { - LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; - } - - mWindowHandle = NULL; - mhDC = 0; - - mWindowThread->post( - [this, window_rect, dw_ex_style, dw_style]() - { - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); - - if (mWindowHandle) - { - mhDC = GetDC(mWindowHandle); - } - } - ); - - // HACK wait for above handle to become populated - // TODO: use a future - int count = 1024; - while (!mhDC && count > 0) - { - Sleep(10); - --count; - } + recreateWindow(window_rect, dw_ex_style, dw_style); if (mWindowHandle) { @@ -1650,48 +1634,7 @@ const S32 max_format = (S32)num_formats - 1; mhDC = 0; // Zero The Device Context } - auto oldHandle = mWindowHandle; - mWindowHandle = NULL; - mhDC = 0; - - // Destroy The Window - if (oldHandle && !destroy_window_handler(oldHandle)) - { - LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL; - } - - mWindowThread->post( - [this, window_rect, dw_ex_style, dw_style]() - { - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); - - if (mWindowHandle) - { - mhDC = GetDC(mWindowHandle); - } - } - ); - - // HACK wait for above handle to become populated - // TODO: use a future - int count = 1024; - while (!mhDC && count > 0) - { - PostMessage(oldHandle, WM_USER + 8, 0x1717, 0x3b3b); - Sleep(10); - --count; - } + recreateWindow(window_rect, dw_ex_style, dw_style); if (mWindowHandle) { @@ -1837,6 +1780,64 @@ const S32 max_format = (S32)num_formats - 1; return TRUE; } +void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style) +{ + auto oldHandle = mWindowHandle; + + // zero out mWindowHandle and mhDC before destroying window so window + // thread falls back to peekmessage + mWindowHandle = 0; + mhDC = 0; + + if (oldHandle && !destroy_window_handler(oldHandle)) + { + LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; + } + + std::promise> promise; + mWindowThread->post( + [this, window_rect, dw_ex_style, dw_style, &promise]() + { + auto handle = CreateWindowEx(dw_ex_style, + mWindowClassName, + mWindowTitle, + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, + window_rect.left, // x pos + window_rect.top, // y pos + window_rect.right - window_rect.left, // width + window_rect.bottom - window_rect.top, // height + NULL, + NULL, + mhInstance, + NULL); + + if (! handle) + { + // Failed to create window: clear the variables. This + // assignment is valid because we're running on mWindowThread. + mWindowThread->mWindowHandle = NULL; + mWindowThread->mhDC = 0; + } + else + { + // Update mWindowThread's own mWindowHandle and mhDC. + mWindowThread->mWindowHandle = handle; + mWindowThread->mhDC = GetDC(handle); + } + + // It's important to wake up the future either way. + promise.set_value(std::make_pair(mWindowThread->mWindowHandle, mWindowThread->mhDC)); + } + ); + + auto future = promise.get_future(); + // This blocks until mWindowThread processes CreateWindowEx() and calls + // promise.set_value(). + auto pair = future.get(); + mWindowHandle = pair.first; + mhDC = pair.second; +} + void* LLWindowWin32::createSharedContext() { S32 attribs[] = @@ -2174,17 +2175,6 @@ void LLWindowWin32::gatherInput() mRawMouseDelta.mX = 0; mRawMouseDelta.mY = 0; } - - - if (mWindowThread->mFunctionQueue.size() > 0) - { - LL_PROFILE_ZONE_NAMED("gi - PostMessage"); - if (mWindowHandle) - { // post a nonsense user message to wake up the Window Thread in case any functions are pending - // and no windows events came through this frame - PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); - } - } while (mWindowThread->mMessageQueue.tryPopBack(msg)) { @@ -4551,35 +4541,32 @@ std::vector LLWindowWin32::getDynamicFallbackFontList() #endif // LL_WINDOWS -inline LLWindowWin32Thread::LLWindowWin32Thread(LLWindowWin32* window) - : LLThread("Window Thread"), - mWindow(window), - mFunctionQueue(MAX_QUEUE_SIZE) +inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() + : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) { - } -inline void LLWindowWin32Thread::run() +void LLWindowWin32::LLWindowWin32Thread::run() { - sWindowThreadId = getID(); - while (!mFinished) + sWindowThreadId = std::this_thread::get_id(); + while (! getQueue().done()) { LL_PROFILE_ZONE_SCOPED; - if (mWindow && mWindow->mWindowHandle != 0) + if (mWindowHandle != 0) { MSG msg; BOOL status; - if (mWindow->mhDC == 0) + if (mhDC == 0) { LL_PROFILE_ZONE_NAMED("w32t - PeekMessage"); - status = PeekMessage(&msg, mWindow->mWindowHandle, 0, 0, PM_REMOVE); + status = PeekMessage(&msg, mWindowHandle, 0, 0, PM_REMOVE); } else { LL_PROFILE_ZONE_NAMED("w32t - GetMessage"); - status = GetMessage(&msg, mWindow->mWindowHandle, 0, 0); + status = GetMessage(&msg, mWindowHandle, 0, 0); } if (status > 0) { @@ -4593,11 +4580,7 @@ inline void LLWindowWin32Thread::run() { LL_PROFILE_ZONE_NAMED("w32t - Function Queue"); //process any pending functions - std::function curFunc; - while (mFunctionQueue.tryPopBack(curFunc)) - { - curFunc(); - } + getQueue().runPending(); } #if 0 @@ -4609,11 +4592,6 @@ inline void LLWindowWin32Thread::run() } } -void LLWindowWin32Thread::post(const std::function& func) -{ - mFunctionQueue.pushFront(func); -} - void LLWindowWin32::post(const std::function& func) { mFunctionQueue.pushFront(func); -- cgit v1.2.3 From 08336bb469b8db41809893a2ed26599777383eed Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 8 Nov 2021 15:15:56 -0500 Subject: SL-16094: Zap thread safety land mine; thin PostMessage() calls. LLWindowWin32::mWndProc was a public WNDPROC member. If set non-NULL, mainWindowProc() would call that before falling into its own handler code. But now, mWndProc would be called on the window thread instead of on the main thread. Running arbitrary callback code on the window thread could cause all sorts of problems. It could be made safe by posting the callback call to the "mainloop" WorkQueue for execution on the main thread. But as no code actually references it, delete it instead. Per DaveP, the recent change to LLWindowsWin32Thread::post() could end up calling PostMessage() many times per frame, with nontrivial overhead. Reinstate the more selective code that calls PostMessage() with the dummy message (to bust us out of GetMessage() to check pending window-thread work requests) at most once per frame. --- indra/llwindow/llwindowwin32.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4b40fae1bf..a26924c2fb 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -488,11 +488,6 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool void post(CALLABLE&& func) { getQueue().post(std::forward(func)); - // bump us out of blocked GetMessage() call - if (mWindowHandle) - { - PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); - } } // call PeekMessage and pull enqueue messages for later processing @@ -583,7 +578,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, // Make an instance of our window then define the window class mhInstance = GetModuleHandle(NULL); - mWndProc = NULL; // Init Direct Input - needed for joystick / Spacemouse @@ -2175,6 +2169,19 @@ void LLWindowWin32::gatherInput() mRawMouseDelta.mX = 0; mRawMouseDelta.mY = 0; } + + + if (mWindowThread->getQueue().size()) + { + LL_PROFILE_ZONE_NAMED("gi - PostMessage"); + if (mWindowHandle) + { + // post a nonsense user message to wake up the Window Thread in + // case any functions are pending and no windows events came + // through this frame + PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + } + } while (mWindowThread->mMessageQueue.tryPopBack(msg)) { @@ -2250,17 +2257,6 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ if (NULL != window_imp) { - // Has user provided their own window callback? - if (NULL != window_imp->mWndProc) - { - LL_PROFILE_ZONE_NAMED("mwp - WndProc"); - if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) - { - // user has handled window message - return 0; - } - } - // Juggle to make sure we can get negative positions for when // mouse is outside window. LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); -- cgit v1.2.3 From 768b7a4d33b64dc3e9d7f7c0c384bb2aa37b458b Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 9 Nov 2021 17:17:49 +0200 Subject: SL-16330 Clean up vertical sync handling, add to UI --- indra/llwindow/llwindowwin32.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index dddc8deb02..e52624d66a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -473,7 +473,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, - BOOL disable_vsync, BOOL use_gl, + BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples) : LLWindow(callbacks, fullscreen, flags) @@ -800,7 +800,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, LLCoordScreen windowPos(x,y); LLCoordScreen windowSize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top); - if (!switchContext(mFullscreen, windowSize, disable_vsync, &windowPos)) + if (!switchContext(mFullscreen, windowSize, enable_vsync, &windowPos)) { return; } @@ -1126,7 +1126,7 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size) } // changing fullscreen resolution -BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL disable_vsync, const LLCoordScreen* const posp) +BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL enable_vsync, const LLCoordScreen* const posp) { //called from main thread GLuint pixel_format; @@ -1802,16 +1802,7 @@ const S32 max_format = (S32)num_formats - 1; } // Disable vertical sync for swap - if (disable_vsync && wglSwapIntervalEXT) - { - LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL; - wglSwapIntervalEXT(0); - } - else - { - LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL; - wglSwapIntervalEXT(1); - } + toggleVSync(enable_vsync); SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this); @@ -1906,6 +1897,20 @@ void LLWindowWin32::destroySharedContext(void* contextPtr) wglDeleteContext((HGLRC)contextPtr); } +void LLWindowWin32::toggleVSync(bool enable_vsync) +{ + if (!enable_vsync && wglSwapIntervalEXT) + { + LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL; + wglSwapIntervalEXT(0); + } + else + { + LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL; + wglSwapIntervalEXT(1); + } +} + void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size ) { if( mIsMouseClipping ) -- cgit v1.2.3 From 214d8d40c12c0a39dffdd837c861abe4c005caf1 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 10 Nov 2021 10:17:12 -0500 Subject: SL-16094: Statically link to Windows IMM32.LIB. llwindowwin32.cpp's LLWinImm class used to dynamically load IMM32.DLL and populate its methods using GetProcAddress(). That was to support Windows XP. Since we've dropped Windows XP, use static linking instead, with dramatically fewer lines of code (and less of a thread safety alarm trigger). We retain the LLWinImm wrapper class only as a hook for Tracy instrumentation. --- indra/llwindow/llwindowwin32.cpp | 182 ++++----------------------------------- 1 file changed, 19 insertions(+), 163 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index a26924c2fb..736887e286 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -176,23 +176,19 @@ DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1); // The following class LLWinImm delegates Windows IMM APIs. -// We need this because some language versions of Windows, -// e.g., US version of Windows XP, doesn't install IMM32.DLL -// as a default, and we can't link against imm32.lib statically. -// I believe DLL loading of this type is best suited to do -// in a static initialization of a class. What I'm not sure is -// whether it follows the Linden Conding Standard... -// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members +// It was originally introduced to support US Windows XP, on which we needed +// to dynamically load IMM32.DLL and use GetProcAddress to resolve its entry +// points. Now that that's moot, we retain this wrapper only for hooks for +// metrics. class LLWinImm { public: - static bool isAvailable() { return sTheInstance.mHImmDll != NULL; } + static bool isAvailable() { return true; } public: // Wrappers for IMM API. static BOOL isIME(HKL hkl); - static HWND getDefaultIMEWnd(HWND hwnd); static HIMC getContext(HWND hwnd); static BOOL releaseContext(HWND hwnd, HIMC himc); static BOOL getOpenStatus(HIMC himc); @@ -206,236 +202,96 @@ public: static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont); static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form); static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value); - -private: - LLWinImm(); - ~LLWinImm(); - -private: - // Pointers to IMM API. - BOOL (WINAPI *mImmIsIME)(HKL); - HWND (WINAPI *mImmGetDefaultIMEWnd)(HWND); - HIMC (WINAPI *mImmGetContext)(HWND); - BOOL (WINAPI *mImmReleaseContext)(HWND, HIMC); - BOOL (WINAPI *mImmGetOpenStatus)(HIMC); - 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); - LONG (WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD); - BOOL (WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD); - BOOL (WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW); - BOOL (WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM); - BOOL (WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD); - -private: - HMODULE mHImmDll; - static LLWinImm sTheInstance; }; -LLWinImm LLWinImm::sTheInstance; - -LLWinImm::LLWinImm() : mHImmDll(NULL) -{ - // Check system metrics - if ( !GetSystemMetrics( SM_IMMENABLED ) ) - return; - - mHImmDll = LoadLibraryA("Imm32"); - if (mHImmDll != NULL) - { - mImmIsIME = (BOOL (WINAPI *)(HKL)) GetProcAddress(mHImmDll, "ImmIsIME"); - mImmGetDefaultIMEWnd = (HWND (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd"); - mImmGetContext = (HIMC (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetContext"); - mImmReleaseContext = (BOOL (WINAPI *)(HWND, HIMC)) GetProcAddress(mHImmDll, "ImmReleaseContext"); - mImmGetOpenStatus = (BOOL (WINAPI *)(HIMC)) GetProcAddress(mHImmDll, "ImmGetOpenStatus"); - 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"); - mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmGetCompositionStringW"); - mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmSetCompositionStringW"); - mImmSetCompositionFont = (BOOL (WINAPI *)(HIMC, LPLOGFONTW)) GetProcAddress(mHImmDll, "ImmSetCompositionFontW"); - mImmSetCandidateWindow = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM)) GetProcAddress(mHImmDll, "ImmSetCandidateWindow"); - mImmNotifyIME = (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmNotifyIME"); - - if (mImmIsIME == NULL || - mImmGetDefaultIMEWnd == NULL || - mImmGetContext == NULL || - mImmReleaseContext == NULL || - mImmGetOpenStatus == NULL || - mImmSetOpenStatus == NULL || - mImmGetConversionStatus == NULL || - mImmSetConversionStatus == NULL || - mImmGetCompostitionWindow == NULL || - mImmSetCompostitionWindow == NULL || - mImmGetCompositionString == NULL || - mImmSetCompositionString == NULL || - mImmSetCompositionFont == NULL || - mImmSetCandidateWindow == NULL || - mImmNotifyIME == 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 - // the case, since it is very unusual; these APIs are available from - // the beginning, and all versions of IMM32.DLL should have them all. - // Unfortunately, this code may be executed before initialization of - // the logging channel (LL_WARNS()), and we can't do it here... Yes, this - // 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; - mImmGetDefaultIMEWnd = NULL; - mImmGetContext = NULL; - mImmReleaseContext = NULL; - mImmGetOpenStatus = NULL; - mImmSetOpenStatus = NULL; - mImmGetConversionStatus = NULL; - mImmSetConversionStatus = NULL; - mImmGetCompostitionWindow = NULL; - mImmSetCompostitionWindow = NULL; - mImmGetCompositionString = NULL; - mImmSetCompositionString = NULL; - mImmSetCompositionFont = NULL; - mImmSetCandidateWindow = NULL; - mImmNotifyIME = NULL; - } - } -} - - // static BOOL LLWinImm::isIME(HKL hkl) { - if ( sTheInstance.mImmIsIME ) - return sTheInstance.mImmIsIME(hkl); - return FALSE; + return ImmIsIME(hkl); } // static HIMC LLWinImm::getContext(HWND hwnd) { - if ( sTheInstance.mImmGetContext ) - return sTheInstance.mImmGetContext(hwnd); - return 0; + return ImmGetContext(hwnd); } //static BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc) { - if ( sTheInstance.mImmIsIME ) - return sTheInstance.mImmReleaseContext(hwnd, himc); - return FALSE; + return ImmReleaseContext(hwnd, himc); } // static BOOL LLWinImm::getOpenStatus(HIMC himc) { - if ( sTheInstance.mImmGetOpenStatus ) - return sTheInstance.mImmGetOpenStatus(himc); - return FALSE; + return ImmGetOpenStatus(himc); } // static BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) { - if ( sTheInstance.mImmSetOpenStatus ) - return sTheInstance.mImmSetOpenStatus(himc, status); - return FALSE; + return ImmSetOpenStatus(himc, status); } // static BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) { - if ( sTheInstance.mImmGetConversionStatus ) - return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); - return FALSE; + return ImmGetConversionStatus(himc, conversion, sentence); } // static BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) { - if ( sTheInstance.mImmSetConversionStatus ) - return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); - return FALSE; + return ImmSetConversionStatus(himc, conversion, sentence); } // static BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - if ( sTheInstance.mImmGetCompostitionWindow ) - return sTheInstance.mImmGetCompostitionWindow(himc, form); - return FALSE; + return ImmGetCompositionWindow(himc, form); } // static BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - if ( sTheInstance.mImmSetCompostitionWindow ) - return sTheInstance.mImmSetCompostitionWindow(himc, form); - return FALSE; + return ImmSetCompositionWindow(himc, form); } // static LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length) { - if ( sTheInstance.mImmGetCompositionString ) - return sTheInstance.mImmGetCompositionString(himc, index, data, length); - return FALSE; + return ImmGetCompositionString(himc, index, data, length); } // static BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength) { - if ( sTheInstance.mImmSetCompositionString ) - return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); - return FALSE; + return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); } // static BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont) { - if ( sTheInstance.mImmSetCompositionFont ) - return sTheInstance.mImmSetCompositionFont(himc, pFont); - return FALSE; + return ImmSetCompositionFont(himc, pFont); } // static BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form) { - if ( sTheInstance.mImmSetCandidateWindow ) - return sTheInstance.mImmSetCandidateWindow(himc, form); - return FALSE; + return ImmSetCandidateWindow(himc, form); } // static BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value) { - if ( sTheInstance.mImmNotifyIME ) - return sTheInstance.mImmNotifyIME(himc, action, index, value); - return FALSE; + return ImmNotifyIME(himc, action, index, value); } - -// ---------------------------------------------------------------------------------------- -LLWinImm::~LLWinImm() -{ - if (mHImmDll != NULL) - { - FreeLibrary(mHImmDll); - mHImmDll = NULL; - } -} - - class LLMonitorInfo { public: -- cgit v1.2.3 From 029b41c0419e975bbb28454538b46dc69ce5d2ba Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Mon, 15 Nov 2021 09:25:35 -0700 Subject: Revert "SL-16220: Merge branch 'origin/DRTVWR-546' into glthread" This reverts commit 5188a26a8521251dda07ac0140bb129f28417e49, reversing changes made to 819088563e13f1d75e048311fbaf0df4a79b7e19. --- indra/llwindow/llwindowwin32.cpp | 426 +++++++++++++++++++++++++++------------ 1 file changed, 298 insertions(+), 128 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 3f3dd43daf..e52624d66a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -55,8 +55,6 @@ #include #include #include -#include -#include // std::pair // Require DirectInput version 8 #define DIRECTINPUT_VERSION 0x0800 @@ -176,19 +174,23 @@ DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1); // The following class LLWinImm delegates Windows IMM APIs. -// It was originally introduced to support US Windows XP, on which we needed -// to dynamically load IMM32.DLL and use GetProcAddress to resolve its entry -// points. Now that that's moot, we retain this wrapper only for hooks for -// metrics. +// We need this because some language versions of Windows, +// e.g., US version of Windows XP, doesn't install IMM32.DLL +// as a default, and we can't link against imm32.lib statically. +// I believe DLL loading of this type is best suited to do +// in a static initialization of a class. What I'm not sure is +// whether it follows the Linden Conding Standard... +// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members class LLWinImm { public: - static bool isAvailable() { return true; } + static bool isAvailable() { return sTheInstance.mHImmDll != NULL; } public: // Wrappers for IMM API. static BOOL isIME(HKL hkl); + static HWND getDefaultIMEWnd(HWND hwnd); static HIMC getContext(HWND hwnd); static BOOL releaseContext(HWND hwnd, HIMC himc); static BOOL getOpenStatus(HIMC himc); @@ -202,96 +204,236 @@ public: static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont); static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form); static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value); + +private: + LLWinImm(); + ~LLWinImm(); + +private: + // Pointers to IMM API. + BOOL (WINAPI *mImmIsIME)(HKL); + HWND (WINAPI *mImmGetDefaultIMEWnd)(HWND); + HIMC (WINAPI *mImmGetContext)(HWND); + BOOL (WINAPI *mImmReleaseContext)(HWND, HIMC); + BOOL (WINAPI *mImmGetOpenStatus)(HIMC); + 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); + LONG (WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD); + BOOL (WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD); + BOOL (WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW); + BOOL (WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM); + BOOL (WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD); + +private: + HMODULE mHImmDll; + static LLWinImm sTheInstance; }; +LLWinImm LLWinImm::sTheInstance; + +LLWinImm::LLWinImm() : mHImmDll(NULL) +{ + // Check system metrics + if ( !GetSystemMetrics( SM_IMMENABLED ) ) + return; + + mHImmDll = LoadLibraryA("Imm32"); + if (mHImmDll != NULL) + { + mImmIsIME = (BOOL (WINAPI *)(HKL)) GetProcAddress(mHImmDll, "ImmIsIME"); + mImmGetDefaultIMEWnd = (HWND (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd"); + mImmGetContext = (HIMC (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetContext"); + mImmReleaseContext = (BOOL (WINAPI *)(HWND, HIMC)) GetProcAddress(mHImmDll, "ImmReleaseContext"); + mImmGetOpenStatus = (BOOL (WINAPI *)(HIMC)) GetProcAddress(mHImmDll, "ImmGetOpenStatus"); + 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"); + mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmGetCompositionStringW"); + mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmSetCompositionStringW"); + mImmSetCompositionFont = (BOOL (WINAPI *)(HIMC, LPLOGFONTW)) GetProcAddress(mHImmDll, "ImmSetCompositionFontW"); + mImmSetCandidateWindow = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM)) GetProcAddress(mHImmDll, "ImmSetCandidateWindow"); + mImmNotifyIME = (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmNotifyIME"); + + if (mImmIsIME == NULL || + mImmGetDefaultIMEWnd == NULL || + mImmGetContext == NULL || + mImmReleaseContext == NULL || + mImmGetOpenStatus == NULL || + mImmSetOpenStatus == NULL || + mImmGetConversionStatus == NULL || + mImmSetConversionStatus == NULL || + mImmGetCompostitionWindow == NULL || + mImmSetCompostitionWindow == NULL || + mImmGetCompositionString == NULL || + mImmSetCompositionString == NULL || + mImmSetCompositionFont == NULL || + mImmSetCandidateWindow == NULL || + mImmNotifyIME == 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 + // the case, since it is very unusual; these APIs are available from + // the beginning, and all versions of IMM32.DLL should have them all. + // Unfortunately, this code may be executed before initialization of + // the logging channel (LL_WARNS()), and we can't do it here... Yes, this + // 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; + mImmGetDefaultIMEWnd = NULL; + mImmGetContext = NULL; + mImmReleaseContext = NULL; + mImmGetOpenStatus = NULL; + mImmSetOpenStatus = NULL; + mImmGetConversionStatus = NULL; + mImmSetConversionStatus = NULL; + mImmGetCompostitionWindow = NULL; + mImmSetCompostitionWindow = NULL; + mImmGetCompositionString = NULL; + mImmSetCompositionString = NULL; + mImmSetCompositionFont = NULL; + mImmSetCandidateWindow = NULL; + mImmNotifyIME = NULL; + } + } +} + + // static BOOL LLWinImm::isIME(HKL hkl) { - return ImmIsIME(hkl); + if ( sTheInstance.mImmIsIME ) + return sTheInstance.mImmIsIME(hkl); + return FALSE; } // static HIMC LLWinImm::getContext(HWND hwnd) { - return ImmGetContext(hwnd); + if ( sTheInstance.mImmGetContext ) + return sTheInstance.mImmGetContext(hwnd); + return 0; } //static BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc) { - return ImmReleaseContext(hwnd, himc); + if ( sTheInstance.mImmIsIME ) + return sTheInstance.mImmReleaseContext(hwnd, himc); + return FALSE; } // static BOOL LLWinImm::getOpenStatus(HIMC himc) { - return ImmGetOpenStatus(himc); + if ( sTheInstance.mImmGetOpenStatus ) + return sTheInstance.mImmGetOpenStatus(himc); + return FALSE; } // static BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) { - return ImmSetOpenStatus(himc, status); + if ( sTheInstance.mImmSetOpenStatus ) + return sTheInstance.mImmSetOpenStatus(himc, status); + return FALSE; } // static BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) { - return ImmGetConversionStatus(himc, conversion, sentence); + if ( sTheInstance.mImmGetConversionStatus ) + return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); + return FALSE; } // static BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) { - return ImmSetConversionStatus(himc, conversion, sentence); + if ( sTheInstance.mImmSetConversionStatus ) + return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); + return FALSE; } // static BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - return ImmGetCompositionWindow(himc, form); + if ( sTheInstance.mImmGetCompostitionWindow ) + return sTheInstance.mImmGetCompostitionWindow(himc, form); + return FALSE; } // static BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - return ImmSetCompositionWindow(himc, form); + if ( sTheInstance.mImmSetCompostitionWindow ) + return sTheInstance.mImmSetCompostitionWindow(himc, form); + return FALSE; } // static LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length) { - return ImmGetCompositionString(himc, index, data, length); + if ( sTheInstance.mImmGetCompositionString ) + return sTheInstance.mImmGetCompositionString(himc, index, data, length); + return FALSE; } // static BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength) { - return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); + if ( sTheInstance.mImmSetCompositionString ) + return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); + return FALSE; } // static BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont) { - return ImmSetCompositionFont(himc, pFont); + if ( sTheInstance.mImmSetCompositionFont ) + return sTheInstance.mImmSetCompositionFont(himc, pFont); + return FALSE; } // static BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form) { - return ImmSetCandidateWindow(himc, form); + if ( sTheInstance.mImmSetCandidateWindow ) + return sTheInstance.mImmSetCandidateWindow(himc, form); + return FALSE; } // static BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value) { - return ImmNotifyIME(himc, action, index, value); + if ( sTheInstance.mImmNotifyIME ) + return sTheInstance.mImmNotifyIME(himc, action, index, value); + return FALSE; } + +// ---------------------------------------------------------------------------------------- +LLWinImm::~LLWinImm() +{ + if (mHImmDll != NULL) + { + FreeLibrary(mHImmDll); + mHImmDll = NULL; + } +} + + class LLMonitorInfo { public: @@ -326,32 +468,6 @@ private: static LLMonitorInfo sMonitorInfo; -// Thread that owns the Window Handle -// This whole struct is private to LLWindowWin32, which needs to mess with its -// members, which is why it's a struct rather than a class. In effect, we make -// the containing class a friend. -struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool -{ - static const int MAX_QUEUE_SIZE = 2048; - - LLThreadSafeQueue mMessageQueue; - - LLWindowWin32Thread(); - - void run() override; - - template - void post(CALLABLE&& func) - { - getQueue().post(std::forward(func)); - } - - // call PeekMessage and pull enqueue messages for later processing - void gatherInput(); - HWND mWindowHandle = NULL; - HDC mhDC = 0; -}; - LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, @@ -363,7 +479,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, : LLWindow(callbacks, fullscreen, flags) { sMainThreadId = LLThread::currentID(); - mWindowThread = new LLWindowWin32Thread(); + mWindowThread = new LLWindowWin32Thread(this); + mWindowThread->start(); //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways LoadLibrary(L"opengl32.dll"); @@ -434,6 +551,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, // Make an instance of our window then define the window class mhInstance = GetModuleHandle(NULL); + mWndProc = NULL; // Init Direct Input - needed for joystick / Spacemouse @@ -857,13 +975,17 @@ void LLWindowWin32::close() // Something killed the window while we were busy destroying gl or handle somehow got broken LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; } + mWindowHandle = NULL; + mWindowThread->mFinished = true; }); - // 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. - mWindowHandle = NULL; - mWindowThread->close(); + + while (!mWindowThread->isStopped()) + { + //nudge window thread + PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } } BOOL LLWindowWin32::isValid() @@ -1156,7 +1278,51 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO << " Fullscreen: " << mFullscreen << LL_ENDL; - recreateWindow(window_rect, dw_ex_style, dw_style); + auto oldHandle = mWindowHandle; + + //zero out mWindowHandle and mhDC before destroying window so window thread falls back to peekmessage + mWindowHandle = 0; + mhDC = 0; + + if (oldHandle && !destroy_window_handler(oldHandle)) + { + LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; + } + + mWindowHandle = NULL; + mhDC = 0; + + mWindowThread->post( + [this, window_rect, dw_ex_style, dw_style]() + { + mWindowHandle = CreateWindowEx(dw_ex_style, + mWindowClassName, + mWindowTitle, + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, + window_rect.left, // x pos + window_rect.top, // y pos + window_rect.right - window_rect.left, // width + window_rect.bottom - window_rect.top, // height + NULL, + NULL, + mhInstance, + NULL); + + if (mWindowHandle) + { + mhDC = GetDC(mWindowHandle); + } + } + ); + + // HACK wait for above handle to become populated + // TODO: use a future + int count = 1024; + while (!mhDC && count > 0) + { + Sleep(10); + --count; + } if (mWindowHandle) { @@ -1484,7 +1650,48 @@ const S32 max_format = (S32)num_formats - 1; mhDC = 0; // Zero The Device Context } - recreateWindow(window_rect, dw_ex_style, dw_style); + auto oldHandle = mWindowHandle; + mWindowHandle = NULL; + mhDC = 0; + + // Destroy The Window + if (oldHandle && !destroy_window_handler(oldHandle)) + { + LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL; + } + + mWindowThread->post( + [this, window_rect, dw_ex_style, dw_style]() + { + mWindowHandle = CreateWindowEx(dw_ex_style, + mWindowClassName, + mWindowTitle, + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, + window_rect.left, // x pos + window_rect.top, // y pos + window_rect.right - window_rect.left, // width + window_rect.bottom - window_rect.top, // height + NULL, + NULL, + mhInstance, + NULL); + + if (mWindowHandle) + { + mhDC = GetDC(mWindowHandle); + } + } + ); + + // HACK wait for above handle to become populated + // TODO: use a future + int count = 1024; + while (!mhDC && count > 0) + { + PostMessage(oldHandle, WM_USER + 8, 0x1717, 0x3b3b); + Sleep(10); + --count; + } if (mWindowHandle) { @@ -1621,64 +1828,6 @@ const S32 max_format = (S32)num_formats - 1; return TRUE; } -void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style) -{ - auto oldHandle = mWindowHandle; - - // zero out mWindowHandle and mhDC before destroying window so window - // thread falls back to peekmessage - mWindowHandle = 0; - mhDC = 0; - - if (oldHandle && !destroy_window_handler(oldHandle)) - { - LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; - } - - std::promise> promise; - mWindowThread->post( - [this, window_rect, dw_ex_style, dw_style, &promise]() - { - auto handle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); - - if (! handle) - { - // Failed to create window: clear the variables. This - // assignment is valid because we're running on mWindowThread. - mWindowThread->mWindowHandle = NULL; - mWindowThread->mhDC = 0; - } - else - { - // Update mWindowThread's own mWindowHandle and mhDC. - mWindowThread->mWindowHandle = handle; - mWindowThread->mhDC = GetDC(handle); - } - - // It's important to wake up the future either way. - promise.set_value(std::make_pair(mWindowThread->mWindowHandle, mWindowThread->mhDC)); - } - ); - - auto future = promise.get_future(); - // This blocks until mWindowThread processes CreateWindowEx() and calls - // promise.set_value(). - auto pair = future.get(); - mWindowHandle = pair.first; - mhDC = pair.second; -} - void* LLWindowWin32::createSharedContext() { S32 attribs[] = @@ -2032,14 +2181,12 @@ void LLWindowWin32::gatherInput() } - if (mWindowThread->getQueue().size()) + if (mWindowThread->mFunctionQueue.size() > 0) { LL_PROFILE_ZONE_NAMED("gi - PostMessage"); if (mWindowHandle) - { - // post a nonsense user message to wake up the Window Thread in - // case any functions are pending and no windows events came - // through this frame + { // post a nonsense user message to wake up the Window Thread in case any functions are pending + // and no windows events came through this frame PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); } } @@ -2129,6 +2276,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ if (NULL != window_imp) { + // Has user provided their own window callback? + if (NULL != window_imp->mWndProc) + { + LL_PROFILE_ZONE_NAMED("mwp - WndProc"); + if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) + { + // user has handled window message + return 0; + } + } + // Juggle to make sure we can get negative positions for when // mouse is outside window. LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); @@ -4409,32 +4567,35 @@ std::vector LLWindowWin32::getDynamicFallbackFontList() #endif // LL_WINDOWS -inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() - : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) +inline LLWindowWin32Thread::LLWindowWin32Thread(LLWindowWin32* window) + : LLThread("Window Thread"), + mWindow(window), + mFunctionQueue(MAX_QUEUE_SIZE) { + } -void LLWindowWin32::LLWindowWin32Thread::run() +inline void LLWindowWin32Thread::run() { - sWindowThreadId = std::this_thread::get_id(); - while (! getQueue().done()) + sWindowThreadId = getID(); + while (!mFinished) { LL_PROFILE_ZONE_SCOPED; - if (mWindowHandle != 0) + if (mWindow && mWindow->mWindowHandle != 0) { MSG msg; BOOL status; - if (mhDC == 0) + if (mWindow->mhDC == 0) { LL_PROFILE_ZONE_NAMED("w32t - PeekMessage"); - status = PeekMessage(&msg, mWindowHandle, 0, 0, PM_REMOVE); + status = PeekMessage(&msg, mWindow->mWindowHandle, 0, 0, PM_REMOVE); } else { LL_PROFILE_ZONE_NAMED("w32t - GetMessage"); - status = GetMessage(&msg, mWindowHandle, 0, 0); + status = GetMessage(&msg, mWindow->mWindowHandle, 0, 0); } if (status > 0) { @@ -4448,7 +4609,11 @@ void LLWindowWin32::LLWindowWin32Thread::run() { LL_PROFILE_ZONE_NAMED("w32t - Function Queue"); //process any pending functions - getQueue().runPending(); + std::function curFunc; + while (mFunctionQueue.tryPopBack(curFunc)) + { + curFunc(); + } } #if 0 @@ -4460,6 +4625,11 @@ void LLWindowWin32::LLWindowWin32Thread::run() } } +void LLWindowWin32Thread::post(const std::function& func) +{ + mFunctionQueue.pushFront(func); +} + void LLWindowWin32::post(const std::function& func) { mFunctionQueue.pushFront(func); -- cgit v1.2.3 From a633efdc0b62f28f145ec26c2efa8dfc06a3729e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 15 Nov 2021 14:34:30 -0500 Subject: SL-16094: In LLWindowWin32::recreateWindow(), kick window thread before blocking on the pending future. Otherwise the window thread can remain blocked in a GetMessage() call and deadlock the app. --- indra/llwindow/llwindowwin32.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 3f3dd43daf..b845f75ce4 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -346,7 +346,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool getQueue().post(std::forward(func)); } - // call PeekMessage and pull enqueue messages for later processing + // call GetMessage() and pull enqueue messages for later processing void gatherInput(); HWND mWindowHandle = NULL; HDC mhDC = 0; @@ -1671,6 +1671,13 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw } ); + // Having posted work to mWindowThread, bump it out of blocked + // GetMessage() call. Normally we could just wait for the next + // gatherInput() call to notice the pending work item and call + // kickWindowThread(), but that would be on THIS calling thread, and we're + // about to block this thread until we get a result from mWindowThread. + kickWindowThread(oldHandle); + auto future = promise.get_future(); // This blocks until mWindowThread processes CreateWindowEx() and calls // promise.set_value(). @@ -2035,13 +2042,7 @@ void LLWindowWin32::gatherInput() if (mWindowThread->getQueue().size()) { LL_PROFILE_ZONE_NAMED("gi - PostMessage"); - if (mWindowHandle) - { - // post a nonsense user message to wake up the Window Thread in - // case any functions are pending and no windows events came - // through this frame - PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); - } + kickWindowThread(); } while (mWindowThread->mMessageQueue.tryPopBack(msg)) @@ -4470,3 +4471,15 @@ void LLWindowWin32::postMouseButtonEvent(const std::function& func) mMouseQueue.pushFront(func); } +void LLWindowWin32::kickWindowThread(HWND windowHandle) +{ + if (! windowHandle) + windowHandle = mWindowHandle; + if (windowHandle) + { + // post a nonsense user message to wake up the Window Thread in + // case any functions are pending and no windows events came + // through this frame + PostMessage(windowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + } +} -- cgit v1.2.3 From 28f9fb06a9f4cb9edccb2ff8132c7f6a9b27c060 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 20 Nov 2021 18:49:19 +0000 Subject: SL-16289 Rigged mesh rendering overhaul --- indra/llwindow/llwindowwin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index e52624d66a..485d332068 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1833,7 +1833,7 @@ void* LLWindowWin32::createSharedContext() S32 attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 4, - WGL_CONTEXT_MINOR_VERSION_ARB, 2, + WGL_CONTEXT_MINOR_VERSION_ARB, 6, WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, 0 -- cgit v1.2.3 From 9b0d8c7e629597fd8e6dfb91a6b8f625b34ab274 Mon Sep 17 00:00:00 2001 From: Runitai Linden Date: Mon, 22 Nov 2021 18:42:56 -0600 Subject: SL-16094 More profile hooks for threading code, remove redundant wglCreateContextAttribs call --- indra/llwindow/llwindowwin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b845f75ce4..777117b7c8 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1697,7 +1697,7 @@ void* LLWindowWin32::createSharedContext() 0 }; - HGLRC rc = wglCreateContextAttribsARB(mhDC, mhRC, attribs); + HGLRC rc = 0; bool done = false; while (!done) -- cgit v1.2.3 From 37900e593d65e93913774f118a9aa461eeb8ef58 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 23 Nov 2021 15:40:36 -0500 Subject: SL-16094: Fix second startup hang. Add LLWindowWin32Thread::Post(), like post() except it uses PostMessage() to send the work item to the window thread. Support this in mainWindowProc(). Move LLWindowWin32::recreateWindow()'s destroy_window_handler() call onto the window thread. Delaying destruction of the old HWND ensures that we can use PostMessage() and GetMessage() with that HWND to pass the lambda work item. Moreover, it's likely to be less buggy to call DestroyWindow() on the same thread that created the window. Make recreateWindow()'s window thread lambda bind the window class parameters by value, rather than binding 'this' and back-referencing LLWindowWin32 members. Make recreateWindow() construct the window thread lambda and then decide whether to pass it to the window thread using post() or Post(), depending on whether we have a current HWND -- therefore whether the window thread is blocked on GetMessage(). That means we can eliminate the kickWindowThread() call. Make destroy_window_handler() accept HWND by value rather than by non-const reference. Since it doesn't attempt to modify the caller's value, this is a better match for the function's semantics anyway -- but importantly, it lets us pass a const HWND. --- indra/llwindow/llwindowwin32.cpp | 193 +++++++++++++++++++++++++++++++++------ 1 file changed, 166 insertions(+), 27 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b845f75ce4..162c38b862 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -46,6 +46,7 @@ #include "llsdutil.h" #include "llglslshader.h" #include "llthreadsafequeue.h" +#include "stringize.h" // System includes #include @@ -55,7 +56,9 @@ #include #include #include +#include #include +#include #include // std::pair // Require DirectInput version 8 @@ -80,6 +83,10 @@ const F32 ICON_FLASH_TIME = 0.5f; #define USER_DEFAULT_SCREEN_DPI 96 // Win7 #endif +// Claim a couple unused GetMessage() message IDs +const UINT WM_DUMMY_(WM_USER + 0x0017); +const UINT WM_POST_FUNCTION_(WM_USER + 0x0018); + extern BOOL gDebugWindowProc; static std::thread::id sWindowThreadId; @@ -340,12 +347,42 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool void run() override; + /// called by main thread to post work to this window thread template void post(CALLABLE&& func) { getQueue().post(std::forward(func)); } + /** + * Like post(), Post() is a way of conveying a single work item to this + * thread. Its virtue is that it will definitely be executed "soon" rather + * than potentially waiting for the next frame: it uses PostMessage() to + * break us out of the window thread's blocked GetMessage() call. It's + * more expensive, though, not only from the Windows API latency of + * PostMessage() and GetMessage(), but also because it involves heap + * allocation and release. + * + * Require HWND from caller, even though we store an HWND locally. + * Otherwise, if our mWindowHandle was accessed from both threads, we'd + * have to protect it with a mutex. + */ + template + void Post(HWND windowHandle, CALLABLE&& func) + { + // Move func to the heap. If we knew FuncType could fit into LPARAM, + // we could simply instantiate FuncType and pass it by value. But + // since we don't, we must put that on the heap as well as the + // internal heap allocation it likely requires to store func. + auto ptr = new FuncType(std::move(func)); + WPARAM wparam{ 0xF1C }; + LL_DEBUGS("Window") << "PostMessage(" << std::hex << windowHandle + << ", " << WM_POST_FUNCTION_ + << ", " << wparam << std::dec << LL_ENDL; + PostMessage(windowHandle, WM_POST_FUNCTION_, wparam, LPARAM(ptr)); + } + + using FuncType = std::function; // call GetMessage() and pull enqueue messages for later processing void gatherInput(); HWND mWindowHandle = NULL; @@ -757,7 +794,7 @@ void LLWindowWin32::restore() // I'm turning off optimizations for this part to be sure code executes as intended // (it is a straw, but I have no idea why else __try can get overruled) #pragma optimize("", off) -bool destroy_window_handler(HWND &hWnd) +bool destroy_window_handler(HWND hWnd) { bool res; __try @@ -1630,18 +1667,36 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw mWindowHandle = 0; mhDC = 0; - if (oldHandle && !destroy_window_handler(oldHandle)) - { - LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; - } - std::promise> promise; - mWindowThread->post( - [this, window_rect, dw_ex_style, dw_style, &promise]() + // What follows must be done on the window thread. + auto window_work = + [self=mWindowThread, + oldHandle, + // bind CreateWindowEx() parameters by value instead of + // back-referencing LLWindowWin32 members + windowClassName=mWindowClassName, + windowTitle=mWindowTitle, + hInstance=mhInstance, + window_rect, + dw_ex_style, + dw_style, + &promise] + () { + LL_DEBUGS("Window") << "recreateWindow(): window_work entry" << LL_ENDL; + self->mWindowHandle = 0; + self->mhDC = 0; + + // important to call DestroyWindow() from the window thread + if (oldHandle && !destroy_window_handler(oldHandle)) + { + LL_WARNS("Window") << "Failed to properly close window before recreating it!" + << LL_ENDL; + } + auto handle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, + windowClassName, + windowTitle, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, window_rect.left, // x pos window_rect.top, // y pos @@ -1649,34 +1704,44 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw window_rect.bottom - window_rect.top, // height NULL, NULL, - mhInstance, + hInstance, NULL); if (! handle) { // Failed to create window: clear the variables. This // assignment is valid because we're running on mWindowThread. - mWindowThread->mWindowHandle = NULL; - mWindowThread->mhDC = 0; + self->mWindowHandle = NULL; + self->mhDC = 0; } else { // Update mWindowThread's own mWindowHandle and mhDC. - mWindowThread->mWindowHandle = handle; - mWindowThread->mhDC = GetDC(handle); + self->mWindowHandle = handle; + self->mhDC = GetDC(handle); } // It's important to wake up the future either way. - promise.set_value(std::make_pair(mWindowThread->mWindowHandle, mWindowThread->mhDC)); - } - ); - - // Having posted work to mWindowThread, bump it out of blocked - // GetMessage() call. Normally we could just wait for the next - // gatherInput() call to notice the pending work item and call - // kickWindowThread(), but that would be on THIS calling thread, and we're - // about to block this thread until we get a result from mWindowThread. - kickWindowThread(oldHandle); + promise.set_value(std::make_pair(self->mWindowHandle, self->mhDC)); + LL_DEBUGS("Window") << "recreateWindow(): window_work done" << LL_ENDL; + }; + // But how we pass window_work to the window thread depends on whether we + // already have a window handle. + if (! oldHandle) + { + // Pass window_work using the WorkQueue: without an existing window + // handle, the window thread can't call GetMessage(). + LL_DEBUGS("Window") << "posting window_work to WorkQueue" << LL_ENDL; + mWindowThread->post(window_work); + } + else + { + // Pass window_work using PostMessage(). We can still + // 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); + } auto future = promise.get_future(); // This blocks until mWindowThread processes CreateWindowEx() and calls @@ -2116,6 +2181,23 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ ASSERT_WINDOW_THREAD(); LL_PROFILE_ZONE_SCOPED; + LL_DEBUGS("Window") << "mainWindowProc(" << std::hex << h_wnd + << ", " << u_msg + << ", " << w_param << ")" << std::dec << LL_ENDL; + + if (u_msg == WM_POST_FUNCTION_) + { + LL_DEBUGS("Window") << "WM_POST_FUNCTION_" << LL_ENDL; + // from LLWindowWin32Thread::Post() + // Cast l_param back to the pointer to the heap FuncType + // allocated by Post(). Capture in unique_ptr so we'll delete + // once we're done with it. + std::unique_ptr + ptr(reinterpret_cast(l_param)); + (*ptr)(); + return 0; + } + // Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN. // This helps prevent avatar walking after maximizing the window by double-clicking the title bar. static bool sHandleLeftMouseUp = true; @@ -4415,14 +4497,61 @@ inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() { } +/** + * LogChange is to log changes in status while trying to avoid spamming the + * log with repeated messages, especially in a tight loop. It refuses to log + * a continuous run of identical messages, but logs every time the message + * changes. (It will happily spam when messages quickly bounce back and + * forth.) + */ +class LogChange +{ +public: + LogChange(const std::string& tag): + mTag(tag) + {} + + template + void always(Items&&... items) + { + // This odd construct ensures that the stringize() call is only + // executed if DEBUG logging is enabled for the passed tag. + LL_DEBUGS(mTag.c_str()); + log(LL_CONT, stringize(std::forward(items)...)); + LL_ENDL; + } + + template + void onChange(Items&&... items) + { + LL_DEBUGS(mTag.c_str()); + auto str = stringize(std::forward(items)...); + if (str != mPrev) + { + log(LL_CONT, str); + } + LL_ENDL; + } + +private: + void log(std::ostream& out, const std::string& message) + { + mPrev = message; + out << message; + } + std::string mTag; + std::string mPrev; +}; + void LLWindowWin32::LLWindowWin32Thread::run() { sWindowThreadId = std::this_thread::get_id(); + LogChange logger("Window"); + while (! getQueue().done()) { LL_PROFILE_ZONE_SCOPED; - if (mWindowHandle != 0) { MSG msg; @@ -4430,15 +4559,19 @@ void LLWindowWin32::LLWindowWin32Thread::run() if (mhDC == 0) { LL_PROFILE_ZONE_NAMED("w32t - PeekMessage"); + logger.onChange("PeekMessage(", std::hex, mWindowHandle, ")"); status = PeekMessage(&msg, mWindowHandle, 0, 0, PM_REMOVE); } else { LL_PROFILE_ZONE_NAMED("w32t - GetMessage"); + logger.always("GetMessage(", std::hex, mWindowHandle, ")"); status = GetMessage(&msg, mWindowHandle, 0, 0); } if (status > 0) { + logger.always("got MSG (", std::hex, msg.hwnd, ", ", msg.message, + ", ", msg.wParam, ")"); TranslateMessage(&msg); DispatchMessage(&msg); @@ -4448,6 +4581,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() { LL_PROFILE_ZONE_NAMED("w32t - Function Queue"); + logger.onChange("runPending()"); //process any pending functions getQueue().runPending(); } @@ -4455,6 +4589,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() #if 0 { LL_PROFILE_ZONE_NAMED("w32t - Sleep"); + logger.always("sleep(1)"); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } #endif @@ -4480,6 +4615,10 @@ void LLWindowWin32::kickWindowThread(HWND windowHandle) // post a nonsense user message to wake up the Window Thread in // case any functions are pending and no windows events came // through this frame - PostMessage(windowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); + WPARAM wparam{ 0xB0B0 }; + LL_DEBUGS("Window") << "PostMessage(" << std::hex << windowHandle + << ", " << WM_DUMMY_ + << ", " << wparam << ")" << std::dec << LL_ENDL; + PostMessage(windowHandle, WM_DUMMY_, wparam, 0x1337); } } -- cgit v1.2.3 From 2b96f89c2a374d72c0a8bc28a7b06ad4db7eae6e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 23 Nov 2021 20:39:32 -0500 Subject: SL-16400: Add ThreadPool::start() method, and call it. It's sometimes important to finish other initialization before launching the threads in the ThreadPool, so make that an explicit step. In particular, we were launching the LLImageGL texture thread before initializing the GL context, resulting in all gray textures. --- indra/llwindow/llwindowwin32.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 51fd228619..af7b8d91f0 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4495,6 +4495,7 @@ std::vector LLWindowWin32::getDynamicFallbackFontList() inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) { + ThreadPool::start(); } /** -- cgit v1.2.3 From 67ace0df9953ce3264048c3946720a9df492edfa Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 23 Nov 2021 20:48:44 -0500 Subject: SL-16400: Address a couple shutdown crashes. It can happen that we try to post() work for LLWindowWin32's window thread after the thread's WorkQueue has been closed. Also, instead of giving the "General" ThreadPool static lifespan, put it on the heap, anchored with a static unique_ptr. --- indra/llwindow/llwindowwin32.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index af7b8d91f0..7f8f88a749 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -351,7 +351,15 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool template void post(CALLABLE&& func) { - getQueue().post(std::forward(func)); + try + { + getQueue().post(std::forward(func)); + } + catch (const LLThreadSafeQueueInterrupt&) + { + // Shutdown timing is tricky. The main thread can end up trying + // to post a cursor position after having closed the WorkQueue. + } } /** -- cgit v1.2.3 From 0b066539fe68dc5750900c3452189645c40adb45 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 24 Nov 2021 10:47:54 -0500 Subject: DRTVWR-546, SL-16220, SL-16094: Undo previous glthread branch revert. Reverting a merge is sticky: it tells git you never want to see that branch again. Merging the DRTVWR-546 branch, which contained the revert, into the glthread branch undid much of the development work on that branch. To restore it we must revert the revert. This reverts commit 029b41c0419e975bbb28454538b46dc69ce5d2ba. --- indra/llwindow/llwindowwin32.cpp | 321 ++++----------------------------------- 1 file changed, 32 insertions(+), 289 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 149a92ffff..062dd02903 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -183,23 +183,19 @@ DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1); // The following class LLWinImm delegates Windows IMM APIs. -// We need this because some language versions of Windows, -// e.g., US version of Windows XP, doesn't install IMM32.DLL -// as a default, and we can't link against imm32.lib statically. -// I believe DLL loading of this type is best suited to do -// in a static initialization of a class. What I'm not sure is -// whether it follows the Linden Conding Standard... -// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members +// It was originally introduced to support US Windows XP, on which we needed +// to dynamically load IMM32.DLL and use GetProcAddress to resolve its entry +// points. Now that that's moot, we retain this wrapper only for hooks for +// metrics. class LLWinImm { public: - static bool isAvailable() { return sTheInstance.mHImmDll != NULL; } + static bool isAvailable() { return true; } public: // Wrappers for IMM API. static BOOL isIME(HKL hkl); - static HWND getDefaultIMEWnd(HWND hwnd); static HIMC getContext(HWND hwnd); static BOOL releaseContext(HWND hwnd, HIMC himc); static BOOL getOpenStatus(HIMC himc); @@ -213,236 +209,96 @@ public: static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont); static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form); static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value); - -private: - LLWinImm(); - ~LLWinImm(); - -private: - // Pointers to IMM API. - BOOL (WINAPI *mImmIsIME)(HKL); - HWND (WINAPI *mImmGetDefaultIMEWnd)(HWND); - HIMC (WINAPI *mImmGetContext)(HWND); - BOOL (WINAPI *mImmReleaseContext)(HWND, HIMC); - BOOL (WINAPI *mImmGetOpenStatus)(HIMC); - 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); - LONG (WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD); - BOOL (WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD); - BOOL (WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW); - BOOL (WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM); - BOOL (WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD); - -private: - HMODULE mHImmDll; - static LLWinImm sTheInstance; }; -LLWinImm LLWinImm::sTheInstance; - -LLWinImm::LLWinImm() : mHImmDll(NULL) -{ - // Check system metrics - if ( !GetSystemMetrics( SM_IMMENABLED ) ) - return; - - mHImmDll = LoadLibraryA("Imm32"); - if (mHImmDll != NULL) - { - mImmIsIME = (BOOL (WINAPI *)(HKL)) GetProcAddress(mHImmDll, "ImmIsIME"); - mImmGetDefaultIMEWnd = (HWND (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd"); - mImmGetContext = (HIMC (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetContext"); - mImmReleaseContext = (BOOL (WINAPI *)(HWND, HIMC)) GetProcAddress(mHImmDll, "ImmReleaseContext"); - mImmGetOpenStatus = (BOOL (WINAPI *)(HIMC)) GetProcAddress(mHImmDll, "ImmGetOpenStatus"); - 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"); - mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmGetCompositionStringW"); - mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmSetCompositionStringW"); - mImmSetCompositionFont = (BOOL (WINAPI *)(HIMC, LPLOGFONTW)) GetProcAddress(mHImmDll, "ImmSetCompositionFontW"); - mImmSetCandidateWindow = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM)) GetProcAddress(mHImmDll, "ImmSetCandidateWindow"); - mImmNotifyIME = (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmNotifyIME"); - - if (mImmIsIME == NULL || - mImmGetDefaultIMEWnd == NULL || - mImmGetContext == NULL || - mImmReleaseContext == NULL || - mImmGetOpenStatus == NULL || - mImmSetOpenStatus == NULL || - mImmGetConversionStatus == NULL || - mImmSetConversionStatus == NULL || - mImmGetCompostitionWindow == NULL || - mImmSetCompostitionWindow == NULL || - mImmGetCompositionString == NULL || - mImmSetCompositionString == NULL || - mImmSetCompositionFont == NULL || - mImmSetCandidateWindow == NULL || - mImmNotifyIME == 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 - // the case, since it is very unusual; these APIs are available from - // the beginning, and all versions of IMM32.DLL should have them all. - // Unfortunately, this code may be executed before initialization of - // the logging channel (LL_WARNS()), and we can't do it here... Yes, this - // 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; - mImmGetDefaultIMEWnd = NULL; - mImmGetContext = NULL; - mImmReleaseContext = NULL; - mImmGetOpenStatus = NULL; - mImmSetOpenStatus = NULL; - mImmGetConversionStatus = NULL; - mImmSetConversionStatus = NULL; - mImmGetCompostitionWindow = NULL; - mImmSetCompostitionWindow = NULL; - mImmGetCompositionString = NULL; - mImmSetCompositionString = NULL; - mImmSetCompositionFont = NULL; - mImmSetCandidateWindow = NULL; - mImmNotifyIME = NULL; - } - } -} - - // static BOOL LLWinImm::isIME(HKL hkl) { - if ( sTheInstance.mImmIsIME ) - return sTheInstance.mImmIsIME(hkl); - return FALSE; + return ImmIsIME(hkl); } // static HIMC LLWinImm::getContext(HWND hwnd) { - if ( sTheInstance.mImmGetContext ) - return sTheInstance.mImmGetContext(hwnd); - return 0; + return ImmGetContext(hwnd); } //static BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc) { - if ( sTheInstance.mImmIsIME ) - return sTheInstance.mImmReleaseContext(hwnd, himc); - return FALSE; + return ImmReleaseContext(hwnd, himc); } // static BOOL LLWinImm::getOpenStatus(HIMC himc) { - if ( sTheInstance.mImmGetOpenStatus ) - return sTheInstance.mImmGetOpenStatus(himc); - return FALSE; + return ImmGetOpenStatus(himc); } // static BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) { - if ( sTheInstance.mImmSetOpenStatus ) - return sTheInstance.mImmSetOpenStatus(himc, status); - return FALSE; + return ImmSetOpenStatus(himc, status); } // static BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) { - if ( sTheInstance.mImmGetConversionStatus ) - return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); - return FALSE; + return ImmGetConversionStatus(himc, conversion, sentence); } // static BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) { - if ( sTheInstance.mImmSetConversionStatus ) - return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); - return FALSE; + return ImmSetConversionStatus(himc, conversion, sentence); } // static BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - if ( sTheInstance.mImmGetCompostitionWindow ) - return sTheInstance.mImmGetCompostitionWindow(himc, form); - return FALSE; + return ImmGetCompositionWindow(himc, form); } // static BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - if ( sTheInstance.mImmSetCompostitionWindow ) - return sTheInstance.mImmSetCompostitionWindow(himc, form); - return FALSE; + return ImmSetCompositionWindow(himc, form); } // static LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length) { - if ( sTheInstance.mImmGetCompositionString ) - return sTheInstance.mImmGetCompositionString(himc, index, data, length); - return FALSE; + return ImmGetCompositionString(himc, index, data, length); } // static BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength) { - if ( sTheInstance.mImmSetCompositionString ) - return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); - return FALSE; + return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); } // static BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont) { - if ( sTheInstance.mImmSetCompositionFont ) - return sTheInstance.mImmSetCompositionFont(himc, pFont); - return FALSE; + return ImmSetCompositionFont(himc, pFont); } // static BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form) { - if ( sTheInstance.mImmSetCandidateWindow ) - return sTheInstance.mImmSetCandidateWindow(himc, form); - return FALSE; + return ImmSetCandidateWindow(himc, form); } // static BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value) { - if ( sTheInstance.mImmNotifyIME ) - return sTheInstance.mImmNotifyIME(himc, action, index, value); - return FALSE; + return ImmNotifyIME(himc, action, index, value); } - -// ---------------------------------------------------------------------------------------- -LLWinImm::~LLWinImm() -{ - if (mHImmDll != NULL) - { - FreeLibrary(mHImmDll); - mHImmDll = NULL; - } -} - - class LLMonitorInfo { public: @@ -552,8 +408,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, : LLWindow(callbacks, fullscreen, flags) { sMainThreadId = LLThread::currentID(); - mWindowThread = new LLWindowWin32Thread(this); - mWindowThread->start(); + mWindowThread = new LLWindowWin32Thread(); //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways LoadLibrary(L"opengl32.dll"); @@ -624,7 +479,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, // Make an instance of our window then define the window class mhInstance = GetModuleHandle(NULL); - mWndProc = NULL; // Init Direct Input - needed for joystick / Spacemouse @@ -1048,17 +902,13 @@ void LLWindowWin32::close() // Something killed the window while we were busy destroying gl or handle somehow got broken LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; } - mWindowHandle = NULL; - mWindowThread->mFinished = true; }); - - while (!mWindowThread->isStopped()) - { - //nudge window thread - PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + // 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. + mWindowHandle = NULL; + mWindowThread->close(); } BOOL LLWindowWin32::isValid() @@ -1351,51 +1201,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO << " Fullscreen: " << mFullscreen << LL_ENDL; - auto oldHandle = mWindowHandle; - - //zero out mWindowHandle and mhDC before destroying window so window thread falls back to peekmessage - mWindowHandle = 0; - mhDC = 0; - - if (oldHandle && !destroy_window_handler(oldHandle)) - { - LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; - } - - mWindowHandle = NULL; - mhDC = 0; - - mWindowThread->post( - [this, window_rect, dw_ex_style, dw_style]() - { - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); - - if (mWindowHandle) - { - mhDC = GetDC(mWindowHandle); - } - } - ); - - // HACK wait for above handle to become populated - // TODO: use a future - int count = 1024; - while (!mhDC && count > 0) - { - Sleep(10); - --count; - } + recreateWindow(window_rect, dw_ex_style, dw_style); if (mWindowHandle) { @@ -1723,48 +1529,7 @@ const S32 max_format = (S32)num_formats - 1; mhDC = 0; // Zero The Device Context } - auto oldHandle = mWindowHandle; - mWindowHandle = NULL; - mhDC = 0; - - // Destroy The Window - if (oldHandle && !destroy_window_handler(oldHandle)) - { - LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL; - } - - mWindowThread->post( - [this, window_rect, dw_ex_style, dw_style]() - { - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); - - if (mWindowHandle) - { - mhDC = GetDC(mWindowHandle); - } - } - ); - - // HACK wait for above handle to become populated - // TODO: use a future - int count = 1024; - while (!mhDC && count > 0) - { - PostMessage(oldHandle, WM_USER + 8, 0x1717, 0x3b3b); - Sleep(10); - --count; - } + recreateWindow(window_rect, dw_ex_style, dw_style); if (mWindowHandle) { @@ -2347,7 +2112,7 @@ void LLWindowWin32::gatherInput() } - if (mWindowThread->mFunctionQueue.size() > 0) + if (mWindowThread->getQueue().size()) { LL_PROFILE_ZONE_NAMED("gi - PostMessage"); kickWindowThread(); @@ -2455,17 +2220,6 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ if (NULL != window_imp) { - // Has user provided their own window callback? - if (NULL != window_imp->mWndProc) - { - LL_PROFILE_ZONE_NAMED("mwp - WndProc"); - if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) - { - // user has handled window message - return 0; - } - } - // Juggle to make sure we can get negative positions for when // mouse is outside window. LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); @@ -4746,10 +4500,8 @@ std::vector LLWindowWin32::getDynamicFallbackFontList() #endif // LL_WINDOWS -inline LLWindowWin32Thread::LLWindowWin32Thread(LLWindowWin32* window) - : LLThread("Window Thread"), - mWindow(window), - mFunctionQueue(MAX_QUEUE_SIZE) +inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() + : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) { ThreadPool::start(); } @@ -4813,7 +4565,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() { MSG msg; BOOL status; - if (mWindow->mhDC == 0) + if (mhDC == 0) { LL_PROFILE_ZONE_NAMED("w32t - PeekMessage"); logger.onChange("PeekMessage(", std::hex, mWindowHandle, ")"); @@ -4840,11 +4592,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() LL_PROFILE_ZONE_NAMED("w32t - Function Queue"); logger.onChange("runPending()"); //process any pending functions - std::function curFunc; - while (mFunctionQueue.tryPopBack(curFunc)) - { - curFunc(); - } + getQueue().runPending(); } #if 0 @@ -4857,11 +4605,6 @@ void LLWindowWin32::LLWindowWin32Thread::run() } } -void LLWindowWin32Thread::post(const std::function& func) -{ - mFunctionQueue.pushFront(func); -} - void LLWindowWin32::post(const std::function& func) { mFunctionQueue.pushFront(func); -- cgit v1.2.3 From 68e09edad0d863d57ba06e2842b9399f3ff21618 Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Mon, 29 Nov 2021 17:07:25 -0700 Subject: SL-16386 remove references to (const true) LLGLSLShader::sNoFixedFunction --- indra/llwindow/llwindowwin32.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 062dd02903..b8bfa92279 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1798,14 +1798,6 @@ void* LLWindowWin32::createSharedContext() LL_INFOS() << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << (LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << LL_ENDL; done = true; - - // force sNoFixedFunction iff we're trying to use nsight debugging which does not support many legacy API uses - - // nSight doesn't support use of legacy API funcs in the fixed function pipe - if (LLRender::sGLCoreProfile || LLRender::sNsightDebugSupport) - { - LLGLSLShader::sNoFixedFunction = true; - } } } -- cgit v1.2.3 From 9689e606f4da78dd5654124b3e90913b4e934b1a Mon Sep 17 00:00:00 2001 From: Runitai Linden Date: Thu, 9 Dec 2021 14:01:41 -0600 Subject: SL-16480 Fix for window not saving its position on exit. --- indra/llwindow/llwindowwin32.cpp | 154 +++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 77 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b8bfa92279..4deebea7e8 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -955,49 +955,22 @@ BOOL LLWindowWin32::getFullscreen() BOOL LLWindowWin32::getPosition(LLCoordScreen *position) { - RECT window_rect; - - if (!mWindowHandle || - !GetWindowRect(mWindowHandle, &window_rect) || - NULL == position) - { - return FALSE; - } - - position->mX = window_rect.left; - position->mY = window_rect.top; + position->mX = mRect.left; + position->mY = mRect.top; return TRUE; } BOOL LLWindowWin32::getSize(LLCoordScreen *size) { - RECT window_rect; - - if (!mWindowHandle || - !GetWindowRect(mWindowHandle, &window_rect) || - NULL == size) - { - return FALSE; - } - - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + size->mX = mRect.right - mRect.left; + size->mY = mRect.bottom - mRect.top; return TRUE; } BOOL LLWindowWin32::getSize(LLCoordWindow *size) { - RECT client_rect; - - if (!mWindowHandle || - !GetClientRect(mWindowHandle, &client_rect) || - NULL == size) - { - return FALSE; - } - - size->mX = client_rect.right - client_rect.left; - size->mY = client_rect.bottom - client_rect.top; + size->mX = mClientRect.right - mClientRect.left; + size->mY = mClientRect.bottom - mClientRect.top; return TRUE; } @@ -1024,14 +997,17 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size) return FALSE; } - WINDOWPLACEMENT placement; - placement.length = sizeof(WINDOWPLACEMENT); - - if (!GetWindowPlacement(mWindowHandle, &placement)) return FALSE; - - placement.showCmd = SW_RESTORE; + mWindowThread->post([=]() + { + WINDOWPLACEMENT placement; + placement.length = sizeof(WINDOWPLACEMENT); - if (!SetWindowPlacement(mWindowHandle, &placement)) return FALSE; + if (GetWindowPlacement(mWindowHandle, &placement)) + { + placement.showCmd = SW_RESTORE; + SetWindowPlacement(mWindowHandle, &placement); + } + }); moveWindow(position, size); return TRUE; @@ -1043,7 +1019,7 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size) DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWORD dw_style = WS_OVERLAPPEDWINDOW; - AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); + AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); return setSizeImpl(LLCoordScreen(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top)); } @@ -1852,14 +1828,20 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre // THIS CAUSES DEV-15484 and DEV-15949 //ShowWindow(mWindowHandle, SW_RESTORE); // NOW we can call MoveWindow - MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); + mWindowThread->post([=]() + { + MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); + }); } void LLWindowWin32::setTitle(const std::string title) { // TODO: Do we need to use the wide string version of this call // to support non-ascii usernames (and region names?) - SetWindowTextA(mWindowHandle, title.c_str()); + mWindowThread->post([=]() + { + SetWindowTextA(mWindowHandle, title.c_str()); + }); } BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) @@ -2889,12 +2871,19 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ return 0; } + case WM_MOVE: + { + window_imp->updateWindowRect(); + return 0; + } case WM_SIZE: { LL_PROFILE_ZONE_NAMED("mwp - WM_SIZE"); + window_imp->updateWindowRect(); S32 width = S32(LOWORD(l_param)); S32 height = S32(HIWORD(l_param)); + if (debug_window_proc) { BOOL maximized = (w_param == SIZE_MAXIMIZED); @@ -3047,12 +3036,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } } } + //list of messages we get often that we don't care to log about case WM_NCHITTEST: case WM_NCMOUSEMOVE: case WM_NCMOUSELEAVE: case WM_MOVING: - case WM_MOVE: case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: break; @@ -3291,43 +3280,30 @@ void LLWindowWin32::setMouseClipping( BOOL b ) BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) { - BOOL success = FALSE; + S32 offsetx = mRect.left - mClientRect.left; + S32 offsety = mRect.top - mClientRect.top; - RECT client_rect; - if( mWindowHandle && GetClientRect(mWindowHandle, &client_rect) ) - { - POINT top_left; - top_left.x = client_rect.left; - top_left.y = client_rect.top; - ClientToScreen(mWindowHandle, &top_left); - - POINT bottom_right; - bottom_right.x = client_rect.right; - bottom_right.y = client_rect.bottom; - ClientToScreen(mWindowHandle, &bottom_right); - - SetRect( rectp, - top_left.x, - top_left.y, - bottom_right.x, - bottom_right.y ); - - success = TRUE; - } + rectp->left += offsetx; + rectp->right += offsetx; + rectp->bottom += offsety; + rectp->bottom += offsety; - return success; + return TRUE; } void LLWindowWin32::flashIcon(F32 seconds) { - FLASHWINFO flash_info; - - flash_info.cbSize = sizeof(FLASHWINFO); - flash_info.hwnd = mWindowHandle; - flash_info.dwFlags = FLASHW_TRAY; - flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); - flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds - FlashWindowEx(&flash_info); + mWindowThread->post([=]() + { + FLASHWINFO flash_info; + + flash_info.cbSize = sizeof(FLASHWINFO); + flash_info.hwnd = mWindowHandle; + flash_info.dwFlags = FLASHW_TRAY; + flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); + flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds + FlashWindowEx(&flash_info); + }); } F32 LLWindowWin32::getGamma() @@ -3783,13 +3759,19 @@ void *LLWindowWin32::getPlatformWindow() void LLWindowWin32::bringToFront() { - BringWindowToTop(mWindowHandle); + mWindowThread->post([=]() + { + BringWindowToTop(mWindowHandle); + }); } // set (OS) window focus back to the client void LLWindowWin32::focusClient() { - SetFocus ( mWindowHandle ); + mWindowThread->post([=]() + { + SetFocus(mWindowHandle); + }); } void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) @@ -4623,3 +4605,21 @@ void LLWindowWin32::kickWindowThread(HWND windowHandle) PostMessage(windowHandle, WM_DUMMY_, wparam, 0x1337); } } + +void LLWindowWin32::updateWindowRect() +{ + LL_PROFILE_ZONE_SCOPED; + //called from window thread + RECT rect; + RECT client_rect; + + if (GetWindowRect(mWindowHandle, &rect) && + GetClientRect(mWindowHandle, &client_rect)) + { + post([=] + { + mRect = rect; + mClientRect = client_rect; + }); + } +} -- cgit v1.2.3 From 7683477547131c8cb371e1357b3d25ca07b2feb4 Mon Sep 17 00:00:00 2001 From: Runitai Linden Date: Thu, 9 Dec 2021 16:44:44 -0600 Subject: SL-16480 Followup -- fix for unintialized mRect/mClientRect and bad getClientRectInScreenSpace --- indra/llwindow/llwindowwin32.cpp | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4deebea7e8..86eca6872e 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1654,7 +1654,8 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw std::promise> promise; // What follows must be done on the window thread. auto window_work = - [self=mWindowThread, + [this, + self=mWindowThread, oldHandle, // bind CreateWindowEx() parameters by value instead of // back-referencing LLWindowWin32 members @@ -1704,7 +1705,9 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw self->mWindowHandle = handle; self->mhDC = GetDC(handle); } - + + updateWindowRect(); + // It's important to wake up the future either way. promise.set_value(std::make_pair(self->mWindowHandle, self->mhDC)); LL_DEBUGS("Window") << "recreateWindow(): window_work done" << LL_ENDL; @@ -3280,15 +3283,31 @@ void LLWindowWin32::setMouseClipping( BOOL b ) BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) { - S32 offsetx = mRect.left - mClientRect.left; - S32 offsety = mRect.top - mClientRect.top; + BOOL success = FALSE; - rectp->left += offsetx; - rectp->right += offsetx; - rectp->bottom += offsety; - rectp->bottom += offsety; + RECT client_rect; + if (mWindowHandle && GetClientRect(mWindowHandle, &client_rect)) + { + POINT top_left; + top_left.x = client_rect.left; + top_left.y = client_rect.top; + ClientToScreen(mWindowHandle, &top_left); + + POINT bottom_right; + bottom_right.x = client_rect.right; + bottom_right.y = client_rect.bottom; + ClientToScreen(mWindowHandle, &bottom_right); + + SetRect(rectp, + top_left.x, + top_left.y, + bottom_right.x, + bottom_right.y); + + success = TRUE; + } - return TRUE; + return success; } void LLWindowWin32::flashIcon(F32 seconds) -- cgit v1.2.3 From c21dad82072c417d9a8b1af8c83a5af02a0a4845 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 13 Dec 2021 12:14:14 +0200 Subject: SL-16467 FIXED "Keyboard layout" is not switched --- indra/llwindow/llwindowwin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 86eca6872e..0064ee26d2 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4568,7 +4568,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() { LL_PROFILE_ZONE_NAMED("w32t - GetMessage"); logger.always("GetMessage(", std::hex, mWindowHandle, ")"); - status = GetMessage(&msg, mWindowHandle, 0, 0); + status = GetMessage(&msg, NULL, 0, 0); } if (status > 0) { -- cgit v1.2.3 From 3ac21ebbf6b354e16ead2d095a61152c95a7243c Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 17 Dec 2021 13:07:23 +0200 Subject: SL-16454 FIXED Performance viewer login screen is black --- indra/llwindow/llwindowwin32.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 0064ee26d2..e4d771978a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -427,6 +427,9 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, memset(mPrevGammaRamp, 0, sizeof(mPrevGammaRamp)); mCustomGammaSet = FALSE; mWindowHandle = NULL; + + mRect = {0, 0, 0, 0}; + mClientRect = {0, 0, 0, 0}; if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &mMouseVanish, 0)) { @@ -1506,6 +1509,16 @@ const S32 max_format = (S32)num_formats - 1; } recreateWindow(window_rect, dw_ex_style, dw_style); + + RECT rect; + RECT client_rect; + //initialize immediately on main thread + if (GetWindowRect(mWindowHandle, &rect) && + GetClientRect(mWindowHandle, &client_rect)) + { + mRect = rect; + mClientRect = client_rect; + }; if (mWindowHandle) { -- cgit v1.2.3 From 8c823b75c00bd8c49568fbcd6180469a02a3a6e3 Mon Sep 17 00:00:00 2001 From: Ptolemy Date: Thu, 13 Jan 2022 13:09:50 -0800 Subject: SL-16606: Add profiler category WIN32 --- indra/llwindow/llwindowwin32.cpp | 130 +++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 65 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index e4d771978a..8c792daac0 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1931,7 +1931,7 @@ void LLWindowWin32::hideCursor() void LLWindowWin32::showCursor() { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; ASSERT_MAIN_THREAD(); @@ -2046,7 +2046,7 @@ void LLWindowWin32::initCursors() void LLWindowWin32::updateCursor() { ASSERT_MAIN_THREAD(); - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32 if (mNextCursor == UI_CURSOR_ARROW && mBusyCount > 0) { @@ -2076,7 +2076,7 @@ void LLWindowWin32::captureMouse() void LLWindowWin32::releaseMouse() { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; ReleaseCapture(); } @@ -2090,7 +2090,7 @@ void LLWindowWin32::delayInputProcessing() void LLWindowWin32::gatherInput() { ASSERT_MAIN_THREAD(); - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32 MSG msg; { @@ -2104,13 +2104,13 @@ void LLWindowWin32::gatherInput() if (mWindowThread->getQueue().size()) { - LL_PROFILE_ZONE_NAMED("gi - PostMessage"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - PostMessage"); kickWindowThread(); } while (mWindowThread->mMessageQueue.tryPopBack(msg)) { - LL_PROFILE_ZONE_NAMED("gi - message queue"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - message queue"); if (mInputProcessingPaused) { continue; @@ -2119,13 +2119,13 @@ void LLWindowWin32::gatherInput() // For async host by name support. Really hacky. if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) { - LL_PROFILE_ZONE_NAMED("gi - callback"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - callback"); gAsyncMsgCallback(msg); } } { - LL_PROFILE_ZONE_NAMED("gi - PeekMessage"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - PeekMessage"); S32 msg_count = 0; while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_REMOVE)) { @@ -2136,7 +2136,7 @@ void LLWindowWin32::gatherInput() } { - LL_PROFILE_ZONE_NAMED("gi - function queue"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - function queue"); //process any pending functions std::function curFunc; while (mFunctionQueue.tryPopBack(curFunc)) @@ -2148,14 +2148,14 @@ void LLWindowWin32::gatherInput() // send one and only one mouse move event per frame BEFORE handling mouse button presses if (mLastCursorPosition != mCursorPosition) { - LL_PROFILE_ZONE_NAMED("gi - mouse move"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - mouse move"); mCallbacks->handleMouseMove(this, mCursorPosition.convert(), mMouseMask); } mLastCursorPosition = mCursorPosition; { - LL_PROFILE_ZONE_NAMED("gi - mouse queue"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - mouse queue"); // handle mouse button presses AFTER updating mouse cursor position std::function curFunc; while (mMouseQueue.tryPopBack(curFunc)) @@ -2177,7 +2177,7 @@ static LLTrace::BlockTimerStatHandle FTM_MOUSEHANDLER("Handle Mouse"); LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { ASSERT_WINDOW_THREAD(); - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; LL_DEBUGS("Window") << "mainWindowProc(" << std::hex << h_wnd << ", " << u_msg @@ -2226,14 +2226,14 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_TIMER: { - LL_PROFILE_ZONE_NAMED("mwp - WM_TIMER"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_TIMER"); WINDOW_IMP_POST(window_imp->mCallbacks->handleTimerEvent(window_imp)); break; } case WM_DEVICECHANGE: { - LL_PROFILE_ZONE_NAMED("mwp - WM_DEVICECHANGE"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DEVICECHANGE"); if (debug_window_proc) { LL_INFOS("Window") << " WM_DEVICECHANGE: wParam=" << w_param @@ -2250,7 +2250,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_PAINT: { - LL_PROFILE_ZONE_NAMED("mwp - WM_PAINT"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_PAINT"); GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE); update_width = update_rect.right - update_rect.left + 1; update_height = update_rect.bottom - update_rect.top + 1; @@ -2266,7 +2266,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_SETCURSOR: { - LL_PROFILE_ZONE_NAMED("mwp - WM_SETCURSOR"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETCURSOR"); // This message is sent whenever the cursor is moved in a window. // You need to set the appropriate cursor appearance. @@ -2281,21 +2281,21 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_ENTERMENULOOP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_ENTERMENULOOP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ENTERMENULOOP"); WINDOW_IMP_POST(window_imp->mCallbacks->handleWindowBlock(window_imp)); break; } case WM_EXITMENULOOP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_EXITMENULOOP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_EXITMENULOOP"); WINDOW_IMP_POST(window_imp->mCallbacks->handleWindowUnblock(window_imp)); break; } case WM_ACTIVATEAPP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_ACTIVATEAPP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ACTIVATEAPP"); window_imp->post([=]() { // This message should be sent whenever the app gains or loses focus. @@ -2338,7 +2338,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_ACTIVATE: { - LL_PROFILE_ZONE_NAMED("mwp - WM_ACTIVATE"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ACTIVATE"); window_imp->post([=]() { // Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE @@ -2372,7 +2372,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_SYSCOMMAND: { - LL_PROFILE_ZONE_NAMED("mwp - WM_SYSCOMMAND"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSCOMMAND"); switch (w_param) { case SC_KEYMENU: @@ -2388,7 +2388,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_CLOSE: { - LL_PROFILE_ZONE_NAMED("mwp - WM_CLOSE"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE"); window_imp->post([=]() { // Will the app allow the window to close? @@ -2403,7 +2403,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_DESTROY: { - LL_PROFILE_ZONE_NAMED("mwp - WM_DESTROY"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DESTROY"); if (window_imp->shouldPostQuit()) { PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0 @@ -2412,7 +2412,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_COMMAND: { - LL_PROFILE_ZONE_NAMED("mwp - WM_COMMAND"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_COMMAND"); if (!HIWORD(w_param)) // this message is from a menu { WINDOW_IMP_POST(window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param))); @@ -2421,13 +2421,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_SYSKEYDOWN: { - LL_PROFILE_ZONE_NAMED("mwp - WM_SYSKEYDOWN"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSKEYDOWN"); // allow system keys, such as ALT-F4 to be processed by Windows eat_keystroke = FALSE; } case WM_KEYDOWN: { - LL_PROFILE_ZONE_NAMED("mwp - WM_KEYDOWN"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_KEYDOWN"); window_imp->post([=]() { window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next @@ -2454,7 +2454,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ eat_keystroke = FALSE; case WM_KEYUP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_KEYUP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_KEYUP"); window_imp->post([=]() { window_imp->mKeyScanCode = (l_param >> 16) & 0xff; @@ -2479,7 +2479,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_IME_SETCONTEXT: { - LL_PROFILE_ZONE_NAMED("mwp - WM_IME_SETCONTEXT"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_IME_SETCONTEXT"); if (debug_window_proc) { LL_INFOS("Window") << "WM_IME_SETCONTEXT" << LL_ENDL; @@ -2493,7 +2493,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_IME_STARTCOMPOSITION: { - LL_PROFILE_ZONE_NAMED("mwp - WM_IME_STARTCOMPOSITION"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_IME_STARTCOMPOSITION"); if (debug_window_proc) { LL_INFOS() << "WM_IME_STARTCOMPOSITION" << LL_ENDL; @@ -2507,7 +2507,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_IME_ENDCOMPOSITION: { - LL_PROFILE_ZONE_NAMED("mwp - WM_IME_ENDCOMPOSITION"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_IME_ENDCOMPOSITION"); if (debug_window_proc) { LL_INFOS() << "WM_IME_ENDCOMPOSITION" << LL_ENDL; @@ -2520,7 +2520,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_IME_COMPOSITION: { - LL_PROFILE_ZONE_NAMED("mwp - WM_IME_COMPOSITION"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_IME_COMPOSITION"); if (debug_window_proc) { LL_INFOS() << "WM_IME_COMPOSITION" << LL_ENDL; @@ -2534,7 +2534,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_IME_REQUEST: { - LL_PROFILE_ZONE_NAMED("mwp - WM_IME_REQUEST"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_IME_REQUEST"); if (debug_window_proc) { LL_INFOS() << "WM_IME_REQUEST" << LL_ENDL; @@ -2549,7 +2549,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_CHAR: { - LL_PROFILE_ZONE_NAMED("mwp - WM_CHAR"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CHAR"); window_imp->post([=]() { window_imp->mKeyCharCode = w_param; @@ -2581,7 +2581,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_NCLBUTTONDOWN: { - LL_PROFILE_ZONE_NAMED("mwp - WM_NCLBUTTONDOWN"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_NCLBUTTONDOWN"); { // A click in a non-client area, e.g. title bar or window border. window_imp->post([=]() @@ -2594,7 +2594,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_LBUTTONDOWN: { - LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDOWN"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_LBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); window_imp->postMouseButtonEvent([=]() @@ -2619,7 +2619,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_LBUTTONDBLCLK: { - LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDBLCLK"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_LBUTTONDBLCLK"); window_imp->postMouseButtonEvent([=]() { //RN: ignore right button double clicks for now @@ -2640,7 +2640,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_LBUTTONUP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONUP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_LBUTTONUP"); { window_imp->postMouseButtonEvent([=]() { @@ -2664,7 +2664,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_RBUTTONDBLCLK: case WM_RBUTTONDOWN: { - LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONDOWN"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_RBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); window_imp->post([=]() @@ -2687,7 +2687,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_RBUTTONUP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONUP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_RBUTTONUP"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); window_imp->postMouseButtonEvent([=]() @@ -2702,7 +2702,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MBUTTONDOWN: // case WM_MBUTTONDBLCLK: { - LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONDOWN"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MBUTTONDOWN"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); window_imp->postMouseButtonEvent([=]() @@ -2721,7 +2721,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MBUTTONUP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONUP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MBUTTONUP"); { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); window_imp->postMouseButtonEvent([=]() @@ -2734,7 +2734,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ break; case WM_XBUTTONDOWN: { - LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONDOWN"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_XBUTTONDOWN"); window_imp->postMouseButtonEvent([=]() { LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); @@ -2754,7 +2754,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_XBUTTONUP: { - LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONUP"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_XBUTTONUP"); window_imp->postMouseButtonEvent([=]() { @@ -2770,7 +2770,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_MOUSEWHEEL: { - LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEWHEEL"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEWHEEL"); static short z_delta = 0; RECT client_rect; @@ -2827,7 +2827,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ */ case WM_MOUSEHWHEEL: { - LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEHWHEEL"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEHWHEEL"); static short h_delta = 0; RECT client_rect; @@ -2864,12 +2864,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // Handle mouse movement within the window case WM_MOUSEMOVE: { - LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEMOVE"); // DO NOT use mouse event queue for move events to ensure cursor position is updated // when button events are handled WINDOW_IMP_POST( { - LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE lambda"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEMOVE lambda"); MASK mask = gKeyboard->currentMask(TRUE); window_imp->mMouseMask = mask; @@ -2880,7 +2880,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_GETMINMAXINFO: { - LL_PROFILE_ZONE_NAMED("mwp - WM_GETMINMAXINFO"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_GETMINMAXINFO"); LPMINMAXINFO min_max = (LPMINMAXINFO)l_param; min_max->ptMinTrackSize.x = window_imp->mMinWindowWidth; min_max->ptMinTrackSize.y = window_imp->mMinWindowHeight; @@ -2894,7 +2894,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_SIZE: { - LL_PROFILE_ZONE_NAMED("mwp - WM_SIZE"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SIZE"); window_imp->updateWindowRect(); S32 width = S32(LOWORD(l_param)); S32 height = S32(HIWORD(l_param)); @@ -2956,7 +2956,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_DPICHANGED: { - LL_PROFILE_ZONE_NAMED("mwp - WM_DPICHANGED"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DPICHANGED"); LPRECT lprc_new_scale; F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI); lprc_new_scale = (LPRECT)l_param; @@ -2977,7 +2977,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_SETFOCUS: { - LL_PROFILE_ZONE_NAMED("mwp - WM_SETFOCUS"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETFOCUS"); if (debug_window_proc) { LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL; @@ -2988,7 +2988,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_KILLFOCUS: { - LL_PROFILE_ZONE_NAMED("mwp - WM_KILLFOCUS"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_KILLFOCUS"); if (debug_window_proc) { LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL; @@ -2999,7 +2999,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_COPYDATA: { - LL_PROFILE_ZONE_NAMED("mwp - WM_COPYDATA"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_COPYDATA"); { // received a URL PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT)l_param; @@ -3019,7 +3019,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } case WM_SETTINGCHANGE: { - LL_PROFILE_ZONE_NAMED("mwp - WM_SETTINGCHANGE"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETTINGCHANGE"); if (w_param == SPI_SETMOUSEVANISH) { if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0)) @@ -3032,7 +3032,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_INPUT: { - LL_PROFILE_ZONE_NAMED("MWP - WM_INPUT"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("MWP - WM_INPUT"); UINT dwSize = 0; GetRawInputData((HRAWINPUT)l_param, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); @@ -3064,7 +3064,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ default: { - LL_PROFILE_ZONE_NAMED("mwp - default"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - default"); if (debug_window_proc) { LL_INFOS("Window") << "Unhandled windows message code: 0x" << std::hex << U32(u_msg) << LL_ENDL; @@ -3082,7 +3082,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // pass unhandled messages down to Windows LRESULT ret; { - LL_PROFILE_ZONE_NAMED("mwp - DefWindowProc"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - DefWindowProc"); ret = DefWindowProc(h_wnd, u_msg, w_param, l_param); } return ret; @@ -3264,7 +3264,7 @@ BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr) // Constrains the mouse to the window. void LLWindowWin32::setMouseClipping( BOOL b ) { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; ASSERT_MAIN_THREAD(); if( b != mIsMouseClipping ) { @@ -3562,7 +3562,7 @@ BOOL LLWindowWin32::resetDisplayResolution() void LLWindowWin32::swapBuffers() { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; ASSERT_MAIN_THREAD(); SwapBuffers(mhDC); @@ -4565,7 +4565,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() while (! getQueue().done()) { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; if (mWindowHandle != 0) { @@ -4573,13 +4573,13 @@ void LLWindowWin32::LLWindowWin32Thread::run() BOOL status; if (mhDC == 0) { - LL_PROFILE_ZONE_NAMED("w32t - PeekMessage"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - PeekMessage"); logger.onChange("PeekMessage(", std::hex, mWindowHandle, ")"); status = PeekMessage(&msg, mWindowHandle, 0, 0, PM_REMOVE); } else { - LL_PROFILE_ZONE_NAMED("w32t - GetMessage"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - GetMessage"); logger.always("GetMessage(", std::hex, mWindowHandle, ")"); status = GetMessage(&msg, NULL, 0, 0); } @@ -4595,7 +4595,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() } { - LL_PROFILE_ZONE_NAMED("w32t - Function Queue"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Function Queue"); logger.onChange("runPending()"); //process any pending functions getQueue().runPending(); @@ -4603,7 +4603,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() #if 0 { - LL_PROFILE_ZONE_NAMED("w32t - Sleep"); + LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Sleep"); logger.always("sleep(1)"); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -4640,7 +4640,7 @@ void LLWindowWin32::kickWindowThread(HWND windowHandle) void LLWindowWin32::updateWindowRect() { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; //called from window thread RECT rect; RECT client_rect; -- cgit v1.2.3 From 0d6aa3c0fe184ae00899304cb3f71315f5c73314 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 17 Feb 2022 22:52:23 +0000 Subject: SL-16815 Remove frame stalls from occlusion queries, bumpmap updates, and querying for available video memory. --- indra/llwindow/llwindowwin32.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 8c792daac0..5ce51bb43e 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3564,6 +3564,7 @@ void LLWindowWin32::swapBuffers() { LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; ASSERT_MAIN_THREAD(); + glFlush(); //superstitious flush for maybe frame stall removal? SwapBuffers(mhDC); LL_PROFILER_GPU_COLLECT -- cgit v1.2.3 From 578087b7bdcc88613e526f80080df56c92fde5ae Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Thu, 24 Mar 2022 11:17:18 -0600 Subject: SL-17074 Fix Alt-F4 handling bug --- indra/llwindow/llwindowwin32.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index f26e3a84d2..9feccd7874 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -2426,6 +2426,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSKEYDOWN"); // allow system keys, such as ALT-F4 to be processed by Windows eat_keystroke = FALSE; + break; } case WM_KEYDOWN: { -- cgit v1.2.3 From e76a3b12e6fd463856074632fbd1e7e5d3267f2d Mon Sep 17 00:00:00 2001 From: Dave Houlton Date: Tue, 29 Mar 2022 11:36:28 -0600 Subject: SL-17074 fix ALT-F4 handling without impacting alt-zoom --- indra/llwindow/llwindowwin32.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 9feccd7874..26e624c6ec 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -2426,7 +2426,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSKEYDOWN"); // allow system keys, such as ALT-F4 to be processed by Windows eat_keystroke = FALSE; - break; + // intentional fall-through here } case WM_KEYDOWN: { @@ -2451,10 +2451,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ gKeyboard->handleKeyDown(w_param, mask); } }); - return eat_keystroke; + if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress + break; } case WM_SYSKEYUP: eat_keystroke = FALSE; + // intentional fall-through here case WM_KEYUP: { LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_KEYUP"); @@ -2478,7 +2480,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ gKeyboard->handleKeyUp(w_param, mask); } }); - return eat_keystroke; + if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress + break; } case WM_IME_SETCONTEXT: { -- cgit v1.2.3 From 904b16a0a7fddb1cd36de8a33d5475df93d9cabe Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 29 Sep 2020 23:39:00 +0300 Subject: SL-17124 switchContext and loadShaderFile crashes - Do not try initializing shaders if requirements are not met or if window does not exist - Warn user before closing window. Situation is unexpected, there is chance of more issues, like a freeze or a crash on close() - mHasMultitexture is a solid requirement, if it is not present, we won't be able to run --- indra/llwindow/llwindowwin32.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 33b4257706..ddf6658ece 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1251,9 +1251,9 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) { - close(); OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } @@ -1290,42 +1290,42 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO if (pfd.cColorBits < 32) { - close(); OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } if (pfd.cAlphaBits < 8) { - close(); OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } if (!SetPixelFormat(mhDC, pixel_format, &pfd)) { - close(); OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } if (!(mhRC = SafeCreateContext(mhDC))) { - close(); OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } if (!wglMakeCurrent(mhDC, mhRC)) { - close(); OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } @@ -1532,16 +1532,16 @@ const S32 max_format = (S32)num_formats - 1; if (!mhDC) { - close(); OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } if (!SetPixelFormat(mhDC, pixel_format, &pfd)) { - close(); OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } @@ -1577,8 +1577,8 @@ const S32 max_format = (S32)num_formats - 1; if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) { - close(); OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } @@ -1590,15 +1590,15 @@ const S32 max_format = (S32)num_formats - 1; // make sure we have 32 bits per pixel if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32) { - close(); OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } if (pfd.cAlphaBits < 8) { - close(); OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } @@ -1614,8 +1614,8 @@ const S32 max_format = (S32)num_formats - 1; if (!wglMakeCurrent(mhDC, mhRC)) { - close(); OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } @@ -1623,8 +1623,8 @@ const S32 max_format = (S32)num_formats - 1; if (!gGLManager.initGL()) { - close(); OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK); + close(); return FALSE; } -- cgit v1.2.3 From da6f4204b7b4887d519f66d586b2782fb6beff2e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 29 Apr 2022 22:13:16 +0300 Subject: SL-17124 make sure window thread wakes up to proces 'quit' message --- indra/llwindow/llwindowwin32.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index ddf6658ece..1f3823509c 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -907,6 +907,10 @@ void LLWindowWin32::close() } }); + // Window thread might be waiting for a getMessage(), give it + // a push to enshure it will process destroy_window_handler + kickWindowThread(); + // 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. -- cgit v1.2.3 From ce0286c33b6d0f6f37d90702c4800362e5c0e7d7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 27 May 2022 20:51:34 +0300 Subject: SL-17474 Device context not properly released at shutdown --- indra/llwindow/llwindowwin32.cpp | 49 ++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 1f3823509c..8635261103 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -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(); } @@ -1506,12 +1506,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 +1659,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 +1672,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 +1689,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 +1740,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 +1753,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(); -- cgit v1.2.3 From ff65e23f2097d4cca524d58b4fa2ab839184ee27 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 3 Jun 2022 14:08:04 +0300 Subject: SL-17515 FIXED Extreme Mouse Sensitivity for Certain Actions --- indra/llwindow/llwindowwin32.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 1f3823509c..4c3aeb4695 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3057,8 +3057,20 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ if (raw->header.dwType == RIM_TYPEMOUSE) { LLMutexLock lock(&window_imp->mRawMouseMutex); - window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX; - window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY; + + 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); + } } } } -- cgit v1.2.3