Fix desktop designer click handling and add goHome API
Designer click handling: - Fix DPI scaling in MouseButtonCallback and CursorPosCallback - Scale coordinates from window space to framebuffer/RmlUi context - Remove window resizing in ResizeToPhone (caused DPI mismatches) Test framework: - Fix SendMouseDown to use MOUSEEVENTF_MOVE before button down - Remove double-scaling in ScaleToPhysical (WindowController handles it) - All 5 UI navigation tests now pass Kernel API: - Add goHome() Lua function to return to home screen - Stops any running third-party apps before navigating Test app: - Update sandbox-test to use goHome() instead of goBack() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -107,33 +107,47 @@ LPARAM WindowController::PhoneToClientLParam(int phoneX, int phoneY) {
|
||||
bool WindowController::SendMouseDown(int phoneX, int phoneY) {
|
||||
if (!m_hwnd) return false;
|
||||
|
||||
// Convert phone coordinates to client coordinates
|
||||
// Convert phone coordinates to client coordinates (using window scale)
|
||||
int clientX = static_cast<int>(phoneX * m_info.scaleX);
|
||||
int clientY = static_cast<int>(phoneY * m_info.scaleY);
|
||||
|
||||
// Calculate screen coordinates
|
||||
int screenX = m_info.clientX + clientX;
|
||||
int screenY = m_info.clientY + clientY;
|
||||
|
||||
// Get DPI info for debugging
|
||||
UINT dpi = GetDpiForWindow(m_hwnd);
|
||||
|
||||
// Calculate screen coordinates from client position
|
||||
// On DPI-aware systems, Windows APIs return consistent coordinate spaces
|
||||
int screenX = m_info.clientX + clientX;
|
||||
int screenY = m_info.clientY + clientY;
|
||||
|
||||
// Ensure window is foreground before clicking
|
||||
SetForegroundWindow(m_hwnd);
|
||||
Sleep(10); // Small delay
|
||||
Sleep(10);
|
||||
|
||||
// Use SendInput for GLFW compatibility
|
||||
SetCursorPos(screenX, screenY);
|
||||
Sleep(10); // Small delay for cursor move
|
||||
// Get screen dimensions for absolute coordinate conversion
|
||||
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
INPUT input = {};
|
||||
input.type = INPUT_MOUSE;
|
||||
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
|
||||
SendInput(1, &input, sizeof(INPUT));
|
||||
// Convert to normalized absolute coordinates (0-65535)
|
||||
LONG absX = static_cast<LONG>((screenX * 65535) / screenWidth);
|
||||
LONG absY = static_cast<LONG>((screenY * 65535) / screenHeight);
|
||||
|
||||
std::cout << "MouseDown at phone(" << phoneX << "," << phoneY << ") -> screen("
|
||||
<< screenX << "," << screenY << ") dpi=" << dpi << std::endl;
|
||||
// Send mouse move then button down
|
||||
INPUT moveInput = {};
|
||||
moveInput.type = INPUT_MOUSE;
|
||||
moveInput.mi.dx = absX;
|
||||
moveInput.mi.dy = absY;
|
||||
moveInput.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
|
||||
SendInput(1, &moveInput, sizeof(INPUT));
|
||||
|
||||
Sleep(20);
|
||||
|
||||
INPUT clickInput = {};
|
||||
clickInput.type = INPUT_MOUSE;
|
||||
clickInput.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
|
||||
SendInput(1, &clickInput, sizeof(INPUT));
|
||||
|
||||
std::cout << "MouseDown at phone(" << phoneX << "," << phoneY << ") -> client("
|
||||
<< clientX << "," << clientY << ") screen(" << screenX << "," << screenY
|
||||
<< ") dpi=" << dpi << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -226,38 +240,20 @@ bool WindowController::Close() {
|
||||
bool WindowController::ResizeToPhone() {
|
||||
if (!m_hwnd) return false;
|
||||
|
||||
// Get current window rect to preserve position
|
||||
// Skip resizing - the designer creates the window at the correct size
|
||||
// and resizing causes DPI scaling mismatches between window and framebuffer.
|
||||
// Just move window to top-left for consistent test positioning.
|
||||
|
||||
RECT currentRect;
|
||||
::GetWindowRect(m_hwnd, ¤tRect);
|
||||
int currentWidth = currentRect.right - currentRect.left;
|
||||
int currentHeight = currentRect.bottom - currentRect.top;
|
||||
|
||||
// Calculate window size needed for phone-sized client area
|
||||
RECT desiredRect = {0, 0, PHONE_WIDTH, PHONE_HEIGHT};
|
||||
DWORD style = ::GetWindowLong(m_hwnd, GWL_STYLE);
|
||||
DWORD exStyle = ::GetWindowLong(m_hwnd, GWL_EXSTYLE);
|
||||
::AdjustWindowRectEx(&desiredRect, style, FALSE, exStyle);
|
||||
std::cout << "ResizeToPhone: keeping current size " << currentWidth << "x" << currentHeight
|
||||
<< ", moving to (0,0)" << std::endl;
|
||||
|
||||
int newWidth = desiredRect.right - desiredRect.left;
|
||||
int newHeight = desiredRect.bottom - desiredRect.top;
|
||||
|
||||
// Check screen dimensions
|
||||
int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
|
||||
int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
std::cout << "ResizeToPhone: screen=" << screenWidth << "x" << screenHeight
|
||||
<< ", needed=" << newWidth << "x" << newHeight << std::endl;
|
||||
|
||||
// If screen is too small, we can't resize to full phone size
|
||||
if (newHeight > screenHeight) {
|
||||
std::cout << " Warning: Screen too small for full phone resolution, keeping current size" << std::endl;
|
||||
return true; // Not an error, just can't resize
|
||||
}
|
||||
|
||||
// Move window to top-left to ensure it fits on screen
|
||||
int newX = 0;
|
||||
int newY = 0;
|
||||
|
||||
std::cout << " Moving to (" << newX << "," << newY << ") size " << newWidth << "x" << newHeight << std::endl;
|
||||
::MoveWindow(m_hwnd, newX, newY, newWidth, newHeight, TRUE);
|
||||
// Move window to top-left for consistent positioning
|
||||
::MoveWindow(m_hwnd, 0, 0, currentWidth, currentHeight, TRUE);
|
||||
|
||||
// Re-acquire window info
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -274,26 +270,36 @@ bool WindowController::SendClickFromBottom(int clientX, int offsetFromBottom) {
|
||||
int screenX = m_info.clientX + clientX;
|
||||
int screenY = m_info.clientY + clientY;
|
||||
|
||||
// Save current cursor position
|
||||
POINT oldPos;
|
||||
GetCursorPos(&oldPos);
|
||||
|
||||
// Ensure window is active
|
||||
SetForegroundWindow(m_hwnd);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
|
||||
// Move cursor and click
|
||||
SetCursorPos(screenX, screenY);
|
||||
// Get screen dimensions for absolute coordinate conversion
|
||||
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
INPUT input = {};
|
||||
input.type = INPUT_MOUSE;
|
||||
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
|
||||
SendInput(1, &input, sizeof(INPUT));
|
||||
// Convert to normalized absolute coordinates (0-65535)
|
||||
LONG absX = static_cast<LONG>((screenX * 65535) / screenWidth);
|
||||
LONG absY = static_cast<LONG>((screenY * 65535) / screenHeight);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
// Use SendInput with absolute move + click
|
||||
INPUT inputs[3] = {};
|
||||
|
||||
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
|
||||
SendInput(1, &input, sizeof(INPUT));
|
||||
// Move cursor
|
||||
inputs[0].type = INPUT_MOUSE;
|
||||
inputs[0].mi.dx = absX;
|
||||
inputs[0].mi.dy = absY;
|
||||
inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
|
||||
|
||||
// Mouse down
|
||||
inputs[1].type = INPUT_MOUSE;
|
||||
inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
|
||||
|
||||
// Mouse up
|
||||
inputs[2].type = INPUT_MOUSE;
|
||||
inputs[2].mi.dwFlags = MOUSEEVENTF_LEFTUP;
|
||||
|
||||
SendInput(3, inputs, sizeof(INPUT));
|
||||
|
||||
std::cout << "ClickFromBottom at client(" << clientX << "," << clientY
|
||||
<< ") -> screen(" << screenX << "," << screenY << ")" << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user