From 399b99b91841249227baa3adb1f87e369fdfa101 Mon Sep 17 00:00:00 2001 From: Ge Wang Date: Tue, 19 Nov 2024 02:58:08 -0800 Subject: [PATCH] add Mouse scaled support (Windows); alter semantics of Mouse.xy() --- src/core/chuck_io.cpp | 53 +++++++++++++----------------------- src/core/chuck_io.h | 4 +-- src/core/util_hid.cpp | 62 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 40 deletions(-) diff --git a/src/core/chuck_io.cpp b/src/core/chuck_io.cpp index 936f32b33..e903df7a1 100644 --- a/src/core/chuck_io.cpp +++ b/src/core/chuck_io.cpp @@ -1500,42 +1500,35 @@ t_CKBOOL init_class_HID( Chuck_Env * env ) // init Mouse class | 1.5.4.2 (ge & spencer) added if( !type_engine_import_class_begin( env, "Mouse", "Object", env->global(), Mouse_ctor, Mouse_dtor, - "Global mouse tracking object." ) ) + "Mouse position tracking. (For full access to mouse input, see the Hid class.)" ) ) return FALSE; + // add examples + if( !type_engine_import_add_ex( env, "hid/ezmouse.ck" ) ) goto error; + // add pos() | 1.5.4.2 (ge & spencer ) added - func = make_new_sfun( "vec2", "pos", Mouse_pos ); - func->doc = "get the normalized X and Y positions of the mouse cursor, respectively in the range [0.0,1.0]; same as .xy()."; + func = make_new_sfun( "vec2", "scaled", Mouse_scaled ); + func->doc = "get the current X and Y normalized positions of the mouse cursor relative to its containing monitor; yields X and Y values in the range [0.0,1.0]"; + if( !type_engine_import_sfun( env, func ) ) goto error; + + // add abs() | 1.5.4.2 (ge & spencer ) added + func = make_new_sfun( "vec2", "abs", Mouse_abs ); + func->doc = "get the current X and Y absolute coordinates of the mouse cursor; dependent on screen resolution; could yield positive and negative values in a multi-monitor setup; same as .xy()"; if( !type_engine_import_sfun( env, func ) ) goto error; // add xy() | 1.5.4.2 (ge & spencer ) added - func = make_new_sfun( "vec2", "xy", Mouse_pos ); - func->doc = "get the normalized X and Y positions of the mouse cursor, respectively in the range [0.0,1.0]; same as .pos()."; + func = make_new_sfun( "vec2", "xy", Mouse_abs ); + func->doc = "get the current X and Y absolute coordinates of the mouse cursor; dependent on screen resolution; could yield positive and negative values in a multi-monitor setup; same as .abs()"; if( !type_engine_import_sfun( env, func ) ) goto error; // add x() | 1.5.4.2 (ge & spencer ) added - func = make_new_sfun( "float", "x", Mouse_pos_x ); - func->doc = "get the normalized X position of the mouse cursor, in the range [0.0,1.0]."; + func = make_new_sfun( "float", "x", Mouse_abs_x ); + func->doc = "get the current X absolute coordinate of the mouse cursor; dependent on screen resolution; could yield positive and negative values in a multi-monitor setup"; if( !type_engine_import_sfun( env, func ) ) goto error; // add y() | 1.5.4.2 (ge & spencer ) added - func = make_new_sfun( "float", "y", Mouse_pos_y ); - func->doc = "get the normalized Y positions of the mouse cursor, in the range [0.0,1.0]."; - if( !type_engine_import_sfun( env, func ) ) goto error; - - // add abs() | 1.5.4.2 (ge & spencer ) added - func = make_new_sfun( "vec2", "abs", Mouse_abs ); - func->doc = "get the absolute X and Y coordinates of the mouse cursor; this is dependent on screen resolution."; - if( !type_engine_import_sfun( env, func ) ) goto error; - - // add abs() | 1.5.4.2 (ge & spencer ) added - func = make_new_sfun( "vec2", "absX", Mouse_abs_x ); - func->doc = "get the absolute X coordinate of the mouse cursor; this is dependent on screen resolution."; - if( !type_engine_import_sfun( env, func ) ) goto error; - - // add abs() | 1.5.4.2 (ge & spencer ) added - func = make_new_sfun( "vec2", "absY", Mouse_abs_y ); - func->doc = "get the absolute Y coordinate of the mouse cursor; this is dependent on screen resolution."; + func = make_new_sfun( "float", "y", Mouse_abs_y ); + func->doc = "get the current Y absolute coordinate of the mouse cursor; dependent on screen resolution; could yield positive and negative values in a multi-monitor setup"; if( !type_engine_import_sfun( env, func ) ) goto error; // end the class import @@ -3057,21 +3050,11 @@ CK_DLL_CTOR( Mouse_ctor ) { } CK_DLL_DTOR( Mouse_dtor ) { } // get normalized mouse XY position, range [0,1] -CK_DLL_SFUN( Mouse_pos ) +CK_DLL_SFUN( Mouse_scaled ) { RETURN->v_vec2 = ck_get_mouse_xy_normalize(); } -CK_DLL_SFUN( Mouse_pos_x ) -{ - RETURN->v_float = ck_get_mouse_xy_normalize().x; -} - -CK_DLL_SFUN( Mouse_pos_y ) -{ - RETURN->v_float = ck_get_mouse_xy_normalize().y; -} - CK_DLL_SFUN( Mouse_abs ) { RETURN->v_vec2 = ck_get_mouse_xy_absolute(); diff --git a/src/core/chuck_io.h b/src/core/chuck_io.h index 9ff171e2d..6a68b7a20 100644 --- a/src/core/chuck_io.h +++ b/src/core/chuck_io.h @@ -611,9 +611,7 @@ CK_DLL_MFUN( HidOut_send ); CK_DLL_CTOR( Mouse_ctor ); CK_DLL_DTOR( Mouse_dtor ); -CK_DLL_SFUN( Mouse_pos ); -CK_DLL_SFUN( Mouse_pos_x ); -CK_DLL_SFUN( Mouse_pos_y ); +CK_DLL_SFUN( Mouse_scaled ); CK_DLL_SFUN( Mouse_abs ); CK_DLL_SFUN( Mouse_abs_x ); CK_DLL_SFUN( Mouse_abs_y ); diff --git a/src/core/util_hid.cpp b/src/core/util_hid.cpp index faee74c88..ebeaa25f7 100644 --- a/src/core/util_hid.cpp +++ b/src/core/util_hid.cpp @@ -7800,6 +7800,33 @@ const char * Keyboard_name( int k ) #endif +#ifdef __PLATFORM_WINDOWS__ + +// multiple monitors info: +// https://stackoverflow.com/questions/4631292/how-to-detect-the-current-screen-resolution +t_CKBOOL GetMonitorRealResolution( HMONITOR monitor, t_CKFLOAT * pixelsWidth, t_CKFLOAT * pixelsHeight ) +{ + // zero out + *pixelsWidth = *pixelsHeight = 0; + + // get monitor info + MONITORINFOEX info; info.cbSize = sizeof( MONITORINFOEX ); + if( !GetMonitorInfoA( monitor, &info ) ) return FALSE; + + // get display setting + DEVMODE devmode; devmode.dmSize = sizeof( DEVMODE ); + if( !EnumDisplaySettingsA( info.szDevice, ENUM_CURRENT_SETTINGS, &devmode ) ) return FALSE; + + // get monitor pixel dimensions (note does not take DPI scaling into account; see below for alternate method) + *pixelsWidth = (t_CKFLOAT)devmode.dmPelsWidth; + *pixelsHeight = (t_CKFLOAT)devmode.dmPelsHeight; + + // done + return TRUE; +} + +#endif + //----------------------------------------------------------------------------- // unified easy mouse functions //----------------------------------------------------------------------------- @@ -7831,14 +7858,45 @@ t_CKVEC2 ck_get_mouse_xy_normalize() // reclaim CFRelease( cg_event ); #elif defined(__PLATFORM_WINDOWS__) - // multiple monitors info - // https://stackoverflow.com/questions/4631292/how-to-detect-the-current-screen-resolution + t_CKINT x = 0, y = 0; + t_CKFLOAT logicalWidth = 0, logicalHeight = 0; + POINT pt; + MONITORINFOEX info; info.cbSize = sizeof( MONITORINFOEX ); + DEVMODE devmode; devmode.dmSize = sizeof( DEVMODE ); + HMONITOR monitor = NULL; + + // get cursor position; in a mutliple monitor setup, this could return negative values + // for monitors to the left or above the primary monitor + if( !GetCursorPos( &pt ) ) goto done; + // get the monitor that contains the point + monitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST ); if( !monitor ) goto done; + // get monitor info + if( !GetMonitorInfo( monitor, &info ) ) goto done; + // get logical width and height, this takes DPI scaling into account + // e.g., in Settings->Display->Make everything bigger (Windows 10, 11) + logicalWidth = (t_CKFLOAT)info.rcMonitor.right - info.rcMonitor.left; + logicalHeight = (t_CKFLOAT)info.rcMonitor.bottom - info.rcMonitor.top; + // map to monitor coordinate + x = (t_CKINT)pt.x - info.rcMonitor.left; + y = (t_CKINT)pt.y - info.rcMonitor.top; + // normalize + retval.x = x / logicalWidth; + retval.y = y / logicalHeight; + + // cerr << pt.x << " " << pt.y << " => " << x << " " << y << " " << " offset: " + // << info.rcMonitor.left << " " << info.rcMonitor.top + // << " dim: " << logicalWidth << " " << logicalHeight + // << " return: " << retval.x << " " << retval.y << endl; + + // t_CKFLOAT screenWidth = GetSystemMetrics( SM_CXVIRTUALSCREEN ); + // t_CKFLOAT screenHeight = GetSystemMetrics( SM_CYVIRTUALSCREEN ); #elif defined(__PLATFORM_LINUX__) #else // unsupported, for now; return 0,0 #endif +done: // done return retval; }