From d831f750b142d60b245492dde985aae2bc273bac Mon Sep 17 00:00:00 2001 From: JusticarProgramming Date: Sat, 29 Aug 2026 08:48:12 +0200 Subject: [PATCH 1/3] Fix cursor display on higher resolutions --- code/wincursor.cpp | 25 ++++++++++++++++++------- code/wwmouse.cpp | 3 +++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/code/wincursor.cpp b/code/wincursor.cpp index d8121cbf..88b2edcf 100644 --- a/code/wincursor.cpp +++ b/code/wincursor.cpp @@ -91,8 +91,19 @@ static HCURSOR Build_Cursor(ShapeSet const * shape, int frame, int hotx, int hot return(NULL); } - int width = shape->Get_Width() * scale; - int height = shape->Get_Height() * scale; + int eff = scale; + int maxw = GetSystemMetrics(SM_CXCURSOR); + int maxh = GetSystemMetrics(SM_CYCURSOR); + if (shape->Get_Width() > 0 && shape->Get_Height() > 0 && maxw > 0 && maxh > 0) { + int capw = maxw / shape->Get_Width(); + int caph = maxh / shape->Get_Height(); + if (eff > capw) eff = capw; + if (eff > caph) eff = caph; + if (eff < 1) eff = 1; + } + + int width = shape->Get_Width() * eff; + int height = shape->Get_Height() * eff; if (width <= 0 || height <= 0) { return(NULL); @@ -134,9 +145,9 @@ static HCURSOR Build_Cursor(ShapeSet const * shape, int frame, int hotx, int hot unsigned long blue = (pixel & 0x1F) << 3; unsigned long argb = 0xFF000000UL | (red << 16) | (green << 8) | blue; - for (int suby = 0; suby < scale; suby++) { - unsigned long * row = (unsigned long *)bits + ((rect.Y + y) * scale + suby) * width + (rect.X + x) * scale; - for (int subx = 0; subx < scale; subx++) { + for (int suby = 0; suby < eff; suby++) { + unsigned long * row = (unsigned long *)bits + ((rect.Y + y) * eff + suby) * width + (rect.X + x) * eff; + for (int subx = 0; subx < eff; subx++) { row[subx] = argb; } } @@ -151,8 +162,8 @@ static HCURSOR Build_Cursor(ShapeSet const * shape, int frame, int hotx, int hot HBITMAP mask = CreateBitmap(width, height, 1, 1, mask_bits); delete [] mask_bits; - int cursor_hotx = hotx * scale; - int cursor_hoty = hoty * scale; + int cursor_hotx = hotx * eff; + int cursor_hoty = hoty * eff; if (cursor_hotx < 0) cursor_hotx = 0; if (cursor_hoty < 0) cursor_hoty = 0; if (cursor_hotx >= width) cursor_hotx = width - 1; diff --git a/code/wwmouse.cpp b/code/wwmouse.cpp index a533581a..a8c4462d 100644 --- a/code/wwmouse.cpp +++ b/code/wwmouse.cpp @@ -293,6 +293,9 @@ void WWMouseClass::Release_Mouse(void) ClipCursor(NULL); if (GetCapture() == Window) ReleaseCapture(); while (ShowCursor(TRUE) < 0) {} + + SetCursor(LoadCursor(NULL, IDC_ARROW)); + Show_Mouse(); } } From f7e017b23d0e9ae387823370116c263f57fa2c48 Mon Sep 17 00:00:00 2001 From: JusticarProgramming Date: Sat, 29 Aug 2026 08:51:48 +0200 Subject: [PATCH 2/3] Document the pointer display fixes --- manual/changes/cursor-dialog-visibility.md | 17 +++++++++++++++++ manual/changes/cursor-size-cap.md | 19 +++++++++++++++++++ manual/content/keys/cursorscale.md | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 manual/changes/cursor-dialog-visibility.md create mode 100644 manual/changes/cursor-size-cap.md diff --git a/manual/changes/cursor-dialog-visibility.md b/manual/changes/cursor-dialog-visibility.md new file mode 100644 index 00000000..33441427 --- /dev/null +++ b/manual/changes/cursor-dialog-visibility.md @@ -0,0 +1,17 @@ +--- +title: Show the pointer when a dialog takes the mouse +category: fix +release: 0.1.0 +targets: +- type: key + id: CursorScale + effect: changed +credit: [JusticarProgramming] +--- + +When the game gave the mouse back to the operating system so a dialog could use it, the +pointer was hidden and stayed hidden until it next moved. The release path cleared the cursor +but nothing put it back, so a dialog that opened under the pointer came up over a blank cursor. + +The release path now restores the arrow as it gives up the mouse, so the pointer is visible +the moment a dialog appears. diff --git a/manual/changes/cursor-size-cap.md b/manual/changes/cursor-size-cap.md new file mode 100644 index 00000000..b11ce604 --- /dev/null +++ b/manual/changes/cursor-size-cap.md @@ -0,0 +1,19 @@ +--- +title: Keep the pointer within the system cursor size +category: fix +release: 0.1.0 +targets: +- type: key + id: CursorScale + effect: changed +credit: [JusticarProgramming] +--- + +The pointer is drawn at the size its setting asks for times the size of its artwork. On a +display where the picture is enlarged a lot, that could come to a bitmap larger than the +cursor the operating system actually renders, and Windows then clips the cursor to its own +size. The clipped corner holds no artwork, so the pointer disappeared. + +The pointer is now reduced to the largest whole size the system cursor can hold, so it always +shows. `CursorScale` still accepts its usual values; a size the display cannot render is +drawn as large as it can be. diff --git a/manual/content/keys/cursorscale.md b/manual/content/keys/cursorscale.md index c67d2ab8..6b334613 100644 --- a/manual/content/keys/cursorscale.md +++ b/manual/content/keys/cursorscale.md @@ -12,3 +12,5 @@ The pointer is a real system cursor built from the game's own artwork, so it sta Left at `0` it follows the picture: the enlargement is rounded to the nearest whole number and used as the pointer's size, so a picture displayed at roughly double size gets a double-size pointer. A value above zero sets the size directly, and eight is the largest accepted. A value below zero draws the pointer at the size the artwork was drawn at, however large the picture is displayed. The pointer is rebuilt whenever the size it should be drawn at changes, so resizing the window resizes the pointer with it. + +However large the size asks to be, the pointer is held to the size the operating system can draw a cursor at. A display that cannot show the requested size draws the pointer as large as it can rather than clipping it to an invisible corner. From 1f3509b37e6d48415e9eded0930a5d0e11429f2d Mon Sep 17 00:00:00 2001 From: JusticarProgramming Date: Sat, 29 Aug 2026 17:14:19 +0200 Subject: [PATCH 3/3] Update release target --- manual/changes/cursor-dialog-visibility.md | 2 +- manual/changes/cursor-size-cap.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manual/changes/cursor-dialog-visibility.md b/manual/changes/cursor-dialog-visibility.md index 33441427..5cad8ef4 100644 --- a/manual/changes/cursor-dialog-visibility.md +++ b/manual/changes/cursor-dialog-visibility.md @@ -1,7 +1,7 @@ --- title: Show the pointer when a dialog takes the mouse category: fix -release: 0.1.0 +release: 0.2.0 targets: - type: key id: CursorScale diff --git a/manual/changes/cursor-size-cap.md b/manual/changes/cursor-size-cap.md index b11ce604..2d823a66 100644 --- a/manual/changes/cursor-size-cap.md +++ b/manual/changes/cursor-size-cap.md @@ -1,7 +1,7 @@ --- title: Keep the pointer within the system cursor size category: fix -release: 0.1.0 +release: 0.2.0 targets: - type: key id: CursorScale