work in progress

This commit is contained in:
2026-01-16 12:43:06 +01:00
parent 77a9579025
commit c8ee7defe8
236 changed files with 11405 additions and 28 deletions

View File

@@ -0,0 +1,265 @@
// Window controller implementation
#include "window_controller.h"
#include <iostream>
#include <chrono>
#include <thread>
namespace mosis::test {
bool WindowController::FindWindow(const std::string& title) {
m_hwnd = ::FindWindowA(nullptr, title.c_str());
if (!m_hwnd) {
return false;
}
m_info.hwnd = m_hwnd;
// Get window rect
::GetWindowRect(m_hwnd, &m_info.windowRect);
// Get client rect (relative to window)
RECT clientRect;
::GetClientRect(m_hwnd, &clientRect);
m_info.clientRect = clientRect;
// Convert client area origin to screen coordinates
POINT clientOrigin = {0, 0};
::ClientToScreen(m_hwnd, &clientOrigin);
m_info.clientX = clientOrigin.x;
m_info.clientY = clientOrigin.y;
// Calculate client size and DPI scale
int clientWidth = clientRect.right - clientRect.left;
int clientHeight = clientRect.bottom - clientRect.top;
m_info.clientWidth = clientWidth;
m_info.clientHeight = clientHeight;
m_info.scaleX = static_cast<float>(clientWidth) / PHONE_WIDTH;
m_info.scaleY = static_cast<float>(clientHeight) / PHONE_HEIGHT;
std::cout << "Found window: " << title << std::endl;
std::cout << " Window rect: " << m_info.windowRect.left << "," << m_info.windowRect.top
<< " - " << m_info.windowRect.right << "," << m_info.windowRect.bottom << std::endl;
std::cout << " Client origin: " << m_info.clientX << "," << m_info.clientY << std::endl;
std::cout << " Client size: " << clientWidth << "x" << clientHeight << std::endl;
std::cout << " DPI scale: " << m_info.scaleX << " x " << m_info.scaleY << std::endl;
return true;
}
bool WindowController::WaitForWindow(const std::string& title, int timeoutMs) {
auto startTime = std::chrono::steady_clock::now();
while (true) {
if (FindWindow(title)) {
return true;
}
auto elapsed = std::chrono::steady_clock::now() - startTime;
if (std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count() >= timeoutMs) {
std::cerr << "Timeout waiting for window: " << title << std::endl;
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
LPARAM WindowController::PhoneToClientLParam(int phoneX, int phoneY) {
// Scale phone coordinates to client coordinates
int clientX = static_cast<int>(phoneX * m_info.scaleX);
int clientY = static_cast<int>(phoneY * m_info.scaleY);
// Clamp to client area bounds
clientX = std::max(0, std::min(clientX, static_cast<int>(PHONE_WIDTH * m_info.scaleX) - 1));
clientY = std::max(0, std::min(clientY, static_cast<int>(PHONE_HEIGHT * m_info.scaleY) - 1));
return MAKELPARAM(clientX, clientY);
}
bool WindowController::SendMouseDown(int phoneX, int phoneY) {
if (!m_hwnd) return false;
// Convert to screen coordinates for SendInput
int clientX = static_cast<int>(phoneX * m_info.scaleX);
int clientY = static_cast<int>(phoneY * m_info.scaleY);
int screenX = m_info.clientX + clientX;
int screenY = m_info.clientY + clientY;
// Use SendInput for proper GLFW compatibility
// First move the cursor to the position
SetCursorPos(screenX, screenY);
// Send mouse down via SendInput
INPUT input = {};
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &input, sizeof(INPUT));
std::cout << "MouseDown at phone(" << phoneX << "," << phoneY << ") -> screen("
<< screenX << "," << screenY << ")" << std::endl;
return true;
}
bool WindowController::SendMouseUp(int phoneX, int phoneY) {
if (!m_hwnd) return false;
// Send mouse up via SendInput
INPUT input = {};
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(INPUT));
std::cout << "MouseUp at phone(" << phoneX << "," << phoneY << ")" << std::endl;
return true;
}
bool WindowController::SendMouseMove(int phoneX, int phoneY) {
if (!m_hwnd) return false;
int clientX = static_cast<int>(phoneX * m_info.scaleX);
int clientY = static_cast<int>(phoneY * m_info.scaleY);
int screenX = m_info.clientX + clientX;
int screenY = m_info.clientY + clientY;
SetCursorPos(screenX, screenY);
return true;
}
bool WindowController::SendClick(int phoneX, int phoneY) {
if (!m_hwnd) return false;
// Save current cursor position
POINT oldPos;
GetCursorPos(&oldPos);
// Ensure window is active
SetForegroundWindow(m_hwnd);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// Perform click
SendMouseDown(phoneX, phoneY);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
SendMouseUp(phoneX, phoneY);
// Restore cursor position (optional - comment out if cursor restoration causes issues)
// std::this_thread::sleep_for(std::chrono::milliseconds(50));
// SetCursorPos(oldPos.x, oldPos.y);
return true;
}
bool WindowController::SendKey(UINT vkCode) {
if (!m_hwnd) return false;
// Send key down and up
LPARAM lParam = 1; // Repeat count = 1
::PostMessage(m_hwnd, WM_KEYDOWN, vkCode, lParam);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
::PostMessage(m_hwnd, WM_KEYUP, vkCode, lParam | (1 << 30) | (1 << 31));
return true;
}
bool WindowController::SendChar(char c) {
if (!m_hwnd) return false;
::PostMessage(m_hwnd, WM_CHAR, static_cast<WPARAM>(c), 0);
return true;
}
bool WindowController::Activate() {
if (!m_hwnd) return false;
::SetForegroundWindow(m_hwnd);
return true;
}
bool WindowController::Close() {
if (!m_hwnd) return false;
::PostMessage(m_hwnd, WM_CLOSE, 0, 0);
return true;
}
bool WindowController::ResizeToPhone() {
if (!m_hwnd) return false;
// Get current window rect to preserve position
RECT currentRect;
::GetWindowRect(m_hwnd, &currentRect);
// 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);
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);
// Re-acquire window info
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return FindWindow("Mosis Designer");
}
bool WindowController::SendClickFromBottom(int clientX, int offsetFromBottom) {
if (!m_hwnd) return false;
// Calculate Y position from bottom of client area
int clientY = m_info.clientHeight - offsetFromBottom;
// Convert to screen coordinates
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);
INPUT input = {};
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &input, sizeof(INPUT));
std::this_thread::sleep_for(std::chrono::milliseconds(50));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(INPUT));
std::cout << "ClickFromBottom at client(" << clientX << "," << clientY
<< ") -> screen(" << screenX << "," << screenY << ")" << std::endl;
return true;
}
} // namespace mosis::test