Skip to content

fix(v3/w32): call GetStockObject instead of GetDeviceCaps - #5875

Open
roachadam wants to merge 2 commits into
wailsapp:masterfrom
roachadam:fix/w32-gdi-wrappers
Open

fix(v3/w32): call GetStockObject instead of GetDeviceCaps#5875
roachadam wants to merge 2 commits into
wailsapp:masterfrom
roachadam:fix/w32-gdi-wrappers

Conversation

@roachadam

@roachadam roachadam commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Description

w32.GetStockObject invoked the wrong Win32 export and returned 0 for every input. It called procGetDeviceCaps rather than procGetStockObject, even though procGetStockObject is declared a few lines above at gdi32.go:40 and is otherwise unused.

GetDeviceCaps takes (HDC, index), so passing a stock-object constant such as DEFAULT_GUI_FONT (17) as the HDC is an invalid handle and the call returns 0. The function had never worked.

There are no callers in v3 today, which is why it went unnoticed. It only surfaces for a new caller, and then indirectly — the null handle is passed to some other GDI function, which fails for reasons that point away from the actual cause.

This is the same class of defect as the DestroyMenu argument bug already covered by pkg/w32/menu_windows_test.go, where a syscall wrapper passed the wrong arguments and silently returned failure for every call.

Fixes #5874

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • WEP (proposal only; no implementation)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Adds v3/pkg/w32/gdi32_windows_test.go, which runs on Windows CI via the //go:build windows constraint. It fails on the pre-fix code, where every call returns 0.

The test checks several stock objects are non-zero, then verifies the DEFAULT_GUI_FONT handle is genuinely usable — selecting it into a memory DC (not the screen DC, so there are no side effects on the CI desktop) and confirming a previous object comes back.

No manual testing was required; the behaviour is fully reproducible in CI.

GOOS=windows GOARCH=amd64 go build ./pkg/w32/ ./pkg/application/ succeeds, and go vet ./pkg/w32/ reports the same pre-existing findings as master — this branch adds none.

Since GetStockObject has no callers in v3, this cannot regress existing behaviour.

  • Windows
  • macOS
  • Linux

Not applicable to macOS or Linux: the change is inside a //go:build windows file.

Test Configuration

Wails:  v3.0.0-beta.2
OS:     Any Windows build — the defect is in the wrapper and is not version-specific
Arch:   amd64

Verified via the added test on Windows CI. My development machine is macOS, so I cannot provide wails3 doctor output; the test is the verification here.

Checklist:

  • (v2 only) I have updated website/src/pages/changelog.mdx with details of this PR (v3 changelog entries are added automatically) — n/a, v3 change
  • My code follows the general coding style of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation — n/a; no public API or documented behaviour change
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

I have also added an entry to v3/UNRELEASED_CHANGELOG.md to control the wording, as described in CONTRIBUTING.md.

Note on a related observation: while confirming this, I noticed SelectObject panics on failure rather than returning 0, which turns a null handle from this bug into a process termination since it is called from inside Windows message handlers. I deliberately did not change it here — panicking on failure is the established convention across pkg/w32 (39 call sites across 10 files, including SetTextColor and SetBkMode in this same file), so altering one function in isolation would be arbitrary. Happy to raise it separately as a design question.

AI Usage Disclosure: I used AI in investigating and preparing this change to confirm my own initial findings.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an issue where retrieving standard Windows graphics objects returned invalid results.
    • Standard stock objects now return usable handles as expected.
  • Tests

    • Added regression coverage verifying stock fonts and graphics objects can be selected, restored, and used successfully.
  • Documentation

    • Documented the corrected stock object retrieval behavior in the unreleased changelog.

@github-actions github-actions Bot added Documentation Improvements or additions to documentation v3-alpha labels Aug 2, 2026
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 13d78912-3036-4a01-a7ab-d25943b652f4

📥 Commits

Reviewing files that changed from the base of the PR and between 244cc48 and 2dce4d8.

📒 Files selected for processing (2)
  • v3/pkg/w32/gdi32.go
  • v3/pkg/w32/gdi32_windows_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • v3/pkg/w32/gdi32_windows_test.go
  • v3/pkg/w32/gdi32.go

Walkthrough

Changes

GetStockObject now calls the correct Windows procedure. Windows-only tests verify valid stock-object handles and font selection. The changelog records the defect.

Windows GDI wrapper fix

Layer / File(s) Summary
Correct and validate stock-object retrieval
v3/pkg/w32/gdi32.go, v3/pkg/w32/gdi32_windows_test.go, v3/UNRELEASED_CHANGELOG.md
GetStockObject calls procGetStockObject. Tests verify usable handles, font selection, restoration, and device-context cleanup. The changelog records the defect.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit checks each handle bright,
Stock objects now return right.
Fonts enter the device context,
Then return safely when done.
Windows tests guard the path.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the primary fix: calling GetStockObject instead of GetDeviceCaps.
Description check ✅ Passed The description covers the change, linked issue, testing, configuration, scope, and checklist with only non-critical omissions.
Linked Issues check ✅ Passed The changes satisfy issue #5874 by correcting the Win32 procedure call and adding Windows regression tests for valid stock-object handles.
Out of Scope Changes check ✅ Passed The changelog update and Windows regression test directly support the requested fix, with no unrelated code changes identified.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@roachadam
roachadam force-pushed the fix/w32-gdi-wrappers branch from 358f49a to dfd883b Compare August 2, 2026 21:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@v3/pkg/w32/gdi32_windows_test.go`:
- Around line 53-55: Extend the Windows test around SelectObject to cover
failure by calling it with an invalid GDI object or device context and asserting
it returns 0, confirming failures do not panic. Capture the return value from
the restoration call and assert it equals font, while preserving the existing
successful-selection assertions.
🪄 Autofix

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cd0d9416-3ee5-4a2f-915a-b4e786ef1ef9

📥 Commits

Reviewing files that changed from the base of the PR and between 358f49a and dfd883b.

📒 Files selected for processing (3)
  • v3/UNRELEASED_CHANGELOG.md
  • v3/pkg/w32/gdi32.go
  • v3/pkg/w32/gdi32_windows_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • v3/pkg/w32/gdi32.go
  • v3/UNRELEASED_CHANGELOG.md

Comment thread v3/pkg/w32/gdi32_windows_test.go Outdated
Comment on lines +53 to +55
previous := w32.SelectObject(hdc, font)
i.True(previous != 0)
w32.SelectObject(hdc, previous)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Cover failed selections and verify restoration.

The test only exercises successful SelectObject calls. A regression to the old panic-on-failure behavior would pass this test. Add a Windows test with an invalid GDI object or device context and assert that w32.SelectObject(...) returns 0. Also capture the return value on Line 55 and assert that it equals font; the current call does not verify restoration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@v3/pkg/w32/gdi32_windows_test.go` around lines 53 - 55, Extend the Windows
test around SelectObject to cover failure by calling it with an invalid GDI
object or device context and asserting it returns 0, confirming failures do not
panic. Capture the return value from the restoration call and assert it equals
font, while preserving the existing successful-selection assertions.

@roachadam roachadam changed the title fix(v3/w32): call GetStockObject, and stop SelectObject panicking fix(v3/w32): call GetStockObject instead of GetDeviceCaps Aug 2, 2026
GetStockObject called procGetDeviceCaps rather than procGetStockObject, even
though procGetStockObject is declared a few lines above it. GetDeviceCaps takes
(HDC, index), so passing a stock-object constant as the HDC is an invalid handle
and the call returns 0. The function returned 0 for every input and had never
worked.

It has no callers in v3, which is why it went unnoticed - the bug only surfaces
for a new caller, and then as a GDI failure rather than anything obvious.

Adds a Windows regression test that fails on the pre-fix code: the returned
handles must be non-zero, and the DEFAULT_GUI_FONT handle must be usable when
selected into a memory DC.

This is the same class of defect as the DestroyMenu argument bug already
covered by pkg/w32/menu_windows_test.go.
@roachadam
roachadam force-pushed the fix/w32-gdi-wrappers branch from dfd883b to 244cc48 Compare August 2, 2026 22:47
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Cannot run autofix: This PR has merge conflicts.

Please resolve the conflicts with the base branch and try again.

Alternatively, use @coderabbitai resolve merge conflict to automatically resolve the conflicts.

@leaanthony

Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts on this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Improvements or additions to documentation v3-alpha

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v3] w32.GetStockObject calls GetDeviceCaps and always returns 0

3 participants