From 1f33b401b3abe92fc42e062ec2e40510436fb150 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Thu, 16 Jan 2025 02:59:49 +0100 Subject: [PATCH] Fix #49117: Larger Alternative for Frame Cursor Internally our "Time" mouse cursor, it comprises up to four digits in a 2x2 grid. With each digit being just 7x7 pixels this is very small on high DPI displays. This PR adds an alternative that shows 12x14 pixel digits, shown when the UI Scale > 1.45. It also changes both small and large versions to not show a solid black background for empty digit positions. Pull Request: https://projects.blender.org/blender/blender/pulls/132767 --- .../windowmanager/intern/wm_cursors.cc | 118 ++++++++++++++---- 1 file changed, 94 insertions(+), 24 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_cursors.cc b/source/blender/windowmanager/intern/wm_cursors.cc index 38c90ae553c..18d35efb93e 100644 --- a/source/blender/windowmanager/intern/wm_cursors.cc +++ b/source/blender/windowmanager/intern/wm_cursors.cc @@ -112,20 +112,7 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) } } -static void window_set_custom_cursor( - wmWindow *win, const uchar mask[16][2], const uchar bitmap[16][2], int hotx, int hoty) -{ - GHOST_SetCustomCursorShape(static_cast(win->ghostwin), - (uint8_t *)bitmap, - (uint8_t *)mask, - 16, - 16, - hotx, - hoty, - true); -} - -static void window_set_custom_cursor_ex(wmWindow *win, BCursor *cursor) +static void window_set_custom_cursor(wmWindow *win, BCursor *cursor) { GHOST_SetCustomCursorShape(static_cast(win->ghostwin), (uint8_t *)cursor->bitmap, @@ -177,7 +164,7 @@ void WM_cursor_set(wmWindow *win, int curs) BCursor *bcursor = BlenderCursor[curs]; if (bcursor) { /* Use custom bitmap cursor. */ - window_set_custom_cursor_ex(win, bcursor); + window_set_custom_cursor(win, bcursor); } else { /* Fallback to default cursor if no bitmap found. */ @@ -354,7 +341,73 @@ bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event) return false; } -void WM_cursor_time(wmWindow *win, int nr) +static bool wm_cursor_time_large(wmWindow *win, int nr) +{ + /* 10 16x16 digits. */ + const uchar number_bitmaps[][32] = { + {0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x1f, 0x1c, 0x38, 0x0c, 0x30, 0x0c, + 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, + 0x0c, 0x30, 0x1c, 0x38, 0xf8, 0x1f, 0xf0, 0x0f, 0x00, 0x00}, + {0x00, 0x00, 0x80, 0x01, 0xc0, 0x01, 0xf0, 0x01, 0xbc, 0x01, 0x8c, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0xfc, 0x3f, 0xfc, 0x3f, 0x00, 0x00}, + {0x00, 0x00, 0xf0, 0x1f, 0xf8, 0x3f, 0x1c, 0x30, 0x0c, 0x30, 0x00, + 0x30, 0x00, 0x30, 0xe0, 0x3f, 0xf0, 0x1f, 0x38, 0x00, 0x1c, 0x00, + 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x3f, 0xfc, 0x3f, 0x00, 0x00}, + {0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x1f, 0x1c, 0x38, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x38, 0xf0, 0x1f, 0xf0, 0x1f, 0x00, 0x38, 0x00, 0x30, + 0x00, 0x30, 0x1c, 0x38, 0xf8, 0x1f, 0xf0, 0x0f, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x0f, 0x80, 0x0f, 0xc0, 0x0d, 0xe0, 0x0c, 0x70, + 0x0c, 0x38, 0x0c, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0xfc, 0x3f, 0xfc, 0x3f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00}, + {0x00, 0x00, 0xfc, 0x3f, 0xfc, 0x3f, 0x0c, 0x00, 0x0c, 0x00, 0x0c, + 0x00, 0xfc, 0x0f, 0xfc, 0x1f, 0x00, 0x38, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x0c, 0x38, 0xfc, 0x1f, 0xf8, 0x0f, 0x00, 0x00}, + {0x00, 0x00, 0xc0, 0x3f, 0xe0, 0x3f, 0x70, 0x00, 0x38, 0x00, 0x1c, + 0x00, 0xfc, 0x0f, 0xfc, 0x1f, 0x0c, 0x38, 0x0c, 0x30, 0x0c, 0x30, + 0x0c, 0x30, 0x1c, 0x38, 0xf8, 0x1f, 0xf0, 0x0f, 0x00, 0x00}, + {0x00, 0x00, 0xfc, 0x3f, 0xfc, 0x3f, 0x0c, 0x30, 0x0c, 0x38, 0x00, + 0x18, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x07, + 0x00, 0x03, 0x80, 0x03, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00}, + {0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x1f, 0x1c, 0x38, 0x0c, 0x30, 0x0c, + 0x30, 0x1c, 0x38, 0xf8, 0x1f, 0xf8, 0x1f, 0x1c, 0x38, 0x0c, 0x30, + 0x0c, 0x30, 0x1c, 0x38, 0xf8, 0x1f, 0xf0, 0x0f, 0x00, 0x00}, + {0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x1f, 0x1c, 0x38, 0x0c, 0x30, 0x0c, + 0x30, 0x0c, 0x30, 0x1c, 0x30, 0xf8, 0x3f, 0xf0, 0x3f, 0x00, 0x38, + 0x00, 0x1c, 0x00, 0x0e, 0xfc, 0x07, 0xfc, 0x03, 0x00, 0x00}, + }; + uchar mask[32][4] = {{0}}; + uchar bitmap[32][4] = {{0}}; + + /* Print number bottom right justified. */ + for (int idx = 3; nr && idx >= 0; idx--) { + const uchar *digit = number_bitmaps[nr % 10]; + int x = idx % 2; + int y = idx / 2; + + for (int i = 0; i < 16; i++) { + bitmap[i + y * 16][x * 2] = digit[i * 2]; + bitmap[i + y * 16][(x * 2) + 1] = digit[(i * 2) + 1]; + } + for (int i = 0; i < 16; i++) { + mask[i + y * 16][x * 2] = 0xFF; + mask[i + y * 16][(x * 2) + 1] = 0xFF; + } + + nr /= 10; + } + + return GHOST_SetCustomCursorShape(static_cast(win->ghostwin), + (uint8_t *)bitmap, + (uint8_t *)mask, + 32, + 32, + 15, + 15, + false) == GHOST_kSuccess; +} + +static void wm_cursor_time_small(wmWindow *win, int nr) { /* 10 8x8 digits. */ const char number_bitmaps[10][8] = { @@ -369,15 +422,9 @@ void WM_cursor_time(wmWindow *win, int nr) {0, 60, 66, 66, 60, 66, 66, 60}, {0, 56, 68, 68, 120, 64, 68, 56}, }; - uchar mask[16][2]; + uchar mask[16][2] = {{0}}; uchar bitmap[16][2] = {{0}}; - if (win->lastcursor == 0) { - win->lastcursor = win->cursor; - } - - memset(&mask, 0xFF, sizeof(mask)); - /* Print number bottom right justified. */ for (int idx = 3; nr && idx >= 0; idx--) { const char *digit = number_bitmaps[nr % 10]; @@ -387,10 +434,33 @@ void WM_cursor_time(wmWindow *win, int nr) for (int i = 0; i < 8; i++) { bitmap[i + y * 8][x] = digit[i]; } + for (int i = 0; i < 8; i++) { + mask[i + y * 8][x] = 0xFF; + } nr /= 10; } - window_set_custom_cursor(win, mask, bitmap, 7, 7); + GHOST_SetCustomCursorShape(static_cast(win->ghostwin), + (uint8_t *)bitmap, + (uint8_t *)mask, + 16, + 16, + 7, + 7, + false); +} + +void WM_cursor_time(wmWindow *win, int nr) +{ + if (win->lastcursor == 0) { + win->lastcursor = win->cursor; + } + + /* Use `U.ui_scale` instead of `UI_SCALE_FAC` here to ignore HiDPI/Retina scaling. */ + if (U.ui_scale < 1.45f || !wm_cursor_time_large(win, nr)) { + wm_cursor_time_small(win, nr); + } + /* Unset current cursor value so it's properly reset to wmWindow.lastcursor. */ win->cursor = 0; }