We also had this issue but found a solution without modifying the engine. Here a summary of the changes.
Problem: Reparenting a standalone Unreal window into a separate-process Win32 host using SetParent() stopped mouse navigation
- WM_MOVE reports parent-client-relative coordinates for child windows, but Slate expects its cached window position in desktop screen coordinates. See `WindowApplication.cpp | FWindowsApplication::ProcessMessage | WM_MOVE`
- Unreal can be considered inactive while the host is foreground, preventing Slate from applying some mouse-capture requests. See `SceneViewport.cpp | FSceneViewport::OnMouseButtonDown(…)` where the AcquireFocusAndCapture() is protected by if (FSlateApplication::Get().IsActive())
Solution: Apply two app-side corrections without modifying engine source.
1. Correct the Cached Screen Position
Subclass the UE window procedure inside the UE process. Let Unreal handle WM_MOVE first, then update the corresponding SWindow using its actual client origin in screen coordinates:
LRESULT CALLBACK EmbeddedWindowProc(
HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
const LRESULT result =
CallWindowProc(OriginalProc, hwnd, message, wParam, lParam);
if (message == WM_MOVE && FSlateApplication::IsInitialized())
{
if (TSharedPtr<SWindow> window = EmbeddedSlateWindow.Pin())
{
POINT clientOrigin{ 0, 0 };
if (!IsIconic(hwnd) && ClientToScreen(hwnd, &clientOrigin))
{
window->SetCachedScreenPosition(
FVector2f(clientOrigin.x, clientOrigin.y));
}
}
}
return result;
}
Install and remove the subclass on the window’s owning thread, remove it on exit.
Also refresh the position after the host moves: parent movement may change the child’s screen position without generating a child WM_MOVE.
Alternatively handle WM_WINDOWPOSCHANGED rather than WM_MOVE, but the principle is the same.
case WM_WINDOWPOSCHANGED:
{
POINT ClientOrigin{0,0};
ClientToScreen(hWnd, &ClientOrigin);
if (GSlateWindow.IsValid())
{
GSlateWindow->MoveWindowTo(
FVector2D(ClientOrigin.x, ClientOrigin.y));
}
break;
}
2. Allow Capture Processing
After Slate initialization, enable capture processing. For example:
if (FSlateApplication::IsInitialized())
{
FSlateApplication::Get()
.ProcessApplicationActivationEvent(true);
}
Call this on UE’s game thread. It allows Slate to apply mouse-capture requests.
Together, these changes restore mouse navigation with Capture During Mouse Down and Do Not Lock. Keep the cached position synchronized when the host moves.