WM: access the windows DPI directly to calculate the mouse-cursor scaling

Instead of relying on the the `U.ui_scale` being set when activating
the window, calculate the cursor size from the windows DPI.

This also de-duplicates cursor scale calculation.
This commit is contained in:
Campbell Barton
2025-07-13 11:53:06 +10:00
parent 41fc42697c
commit 566afb8201
4 changed files with 35 additions and 15 deletions

View File

@@ -390,6 +390,12 @@ wmWindow *WM_window_open(bContext *C,
void *area_setup_user_data) ATTR_NONNULL(1, 3);
void WM_window_dpi_set_userdef(const wmWindow *win);
/**
* Return the windows DPI as a scale, bypassing UI scale preference.
*
* \note Use for calculating cursor size which doesn't use the UI scale.
*/
float WM_window_dpi_get_scale(const wmWindow *win);
/**
* Give a title to a window. With "Title" unspecified or nullptr, it is generated

View File

@@ -138,7 +138,10 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs)
}
}
static int wm_cursor_size()
/**
* Calculate the cursor in pixels to use when setting the cursor.
*/
static int wm_cursor_size(const wmWindow *win)
{
/* Keep for testing. */
if (false) {
@@ -146,14 +149,14 @@ static int wm_cursor_size()
return std::lround(21.0f * UI_SCALE_FAC);
}
/* The DPI as a scale without the UI scale preference. */
const float system_scale = UI_SCALE_FAC / U.ui_scale;
#if (OS_MAC)
/* MacOS always scales up this type of cursor for high-dpi displays. */
return 21;
#endif
/* The DPI as a scale without the UI scale preference. */
const float system_scale = WM_window_dpi_get_scale(win);
return std::lround(WM_cursor_preferred_logical_size() * system_scale);
}
@@ -237,7 +240,7 @@ static bool window_set_custom_cursor_pixmap(wmWindow *win, const BCursor &cursor
* has a limit of 256. MacOS is likely 256 or larger, but unconfirmed. 255 is
* probably large enough for now. */
const int max_size = use_rgba ? 255 : 32;
const int size = std::min(wm_cursor_size(), max_size);
const int size = std::min(wm_cursor_size(win), max_size);
int bitmap_size[2] = {0, 0};
uint8_t *bitmap_rgba = cursor_bitmap_from_svg(
@@ -691,7 +694,7 @@ static bool wm_cursor_text_pixmap(wmWindow *win, const std::string &text, int fo
int bitmap_size[2];
uint8_t *bitmap_rgba = cursor_bitmap_from_text(
text,
wm_cursor_size(),
wm_cursor_size(win),
font_id,
[](size_t size) -> uint8_t * { return MEM_malloc_arrayN<uint8_t>(size, "wm.cursor"); },
bitmap_size);
@@ -731,7 +734,7 @@ void WM_cursor_time(wmWindow *win, int nr)
if (WM_capabilities_flag() & WM_CAPABILITY_CURSOR_RGBA) {
wm_cursor_text(win, std::to_string(nr), blf_mono_font);
}
else if (wm_cursor_size() < 24 || !wm_cursor_time_large(win, nr)) {
else if (wm_cursor_size(win) < 24 || !wm_cursor_time_large(win, nr)) {
wm_cursor_time_small(win, nr);
}

View File

@@ -240,7 +240,8 @@ static void wm_software_cursor_motion_clear_with_window(const wmWindow *win)
}
}
static void wm_software_cursor_draw_bitmap(const int event_xy[2],
static void wm_software_cursor_draw_bitmap(const float system_scale,
const int event_xy[2],
const GHOST_CursorBitmapRef *bitmap)
{
GPU_blend(GPU_BLEND_ALPHA);
@@ -254,8 +255,6 @@ static void wm_software_cursor_draw_bitmap(const int event_xy[2],
GPU_matrix_push();
/* The DPI as a scale without the UI scale preference. */
const float system_scale = UI_SCALE_FAC / U.ui_scale;
/* With RGBA cursors, the cursor will have been generated at the correct size,
* there is no need to perform additional scaling.
*
@@ -311,14 +310,12 @@ static void wm_software_cursor_draw_bitmap(const int event_xy[2],
GPU_blend(GPU_BLEND_NONE);
}
static void wm_software_cursor_draw_crosshair(const int event_xy[2])
static void wm_software_cursor_draw_crosshair(const float system_scale, const int event_xy[2])
{
/* Draw a primitive cross-hair cursor.
* NOTE: the `win->cursor` could be used for drawing although it's complicated as some cursors
* are set by the operating-system, where the pixel information isn't easily available. */
/* The DPI as a scale without the UI scale preference. */
const float system_scale = UI_SCALE_FAC / U.ui_scale;
/* The cursor scaled by the "default" size. */
const float cursor_scale = float(WM_cursor_preferred_logical_size()) /
float(WM_CURSOR_DEFAULT_LOGICAL_SIZE);
@@ -380,14 +377,16 @@ static void wm_software_cursor_draw(wmWindow *win, const GrabState *grab_state)
}
}
const float system_scale = WM_window_dpi_get_scale(win);
GHOST_CursorBitmapRef bitmap = {nullptr};
if (GHOST_GetCursorBitmap(static_cast<GHOST_WindowHandle>(win->ghostwin), &bitmap) ==
GHOST_kSuccess)
{
wm_software_cursor_draw_bitmap(event_xy, &bitmap);
wm_software_cursor_draw_bitmap(system_scale, event_xy, &bitmap);
}
else {
wm_software_cursor_draw_crosshair(event_xy);
wm_software_cursor_draw_crosshair(system_scale, event_xy);
}
}

View File

@@ -651,6 +651,18 @@ void WM_window_dpi_set_userdef(const wmWindow *win)
U.widget_unit = int(roundf(18.0f * U.scale_factor)) + (2 * pixelsize);
}
float WM_window_dpi_get_scale(const wmWindow *win)
{
GHOST_WindowHandle win_handle = static_cast<GHOST_WindowHandle>(win->ghostwin);
const uint16_t dpi_base = 96;
const uint16_t dpi_fixed = std::max<uint16_t>(dpi_base, GHOST_GetDPIHint(win_handle));
float dpi = float(dpi_fixed);
if (OS_MAC) {
dpi *= GHOST_GetNativePixelSize(win_handle);
}
return dpi / float(dpi_base);
}
/** \} */
/* -------------------------------------------------------------------- */