Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing Win32 Cursor Constants in Windows Bindings #4808

Open
ruippgoncalves opened this issue Feb 8, 2025 · 9 comments
Open

Missing Win32 Cursor Constants in Windows Bindings #4808

ruippgoncalves opened this issue Feb 8, 2025 · 9 comments

Comments

@ruippgoncalves
Copy link

Context

Odin: dev-2025-01-nightly:2aae4cf
OS: Windows 11 Professional (version: 24H2), build 26100.3037
CPU: 11th Gen Intel(R) Core(TM) i7-11700KF @ 3.60GHz
RAM: 32605 MiB
Backend: LLVM 18.1.8

Expected Behavior

The Windows bindings should include all relevant cursor constants from winuser.h, such as:

OCR_NORMAL      :: 32512
OCR_IBEAM       :: 32513
OCR_WAIT        :: 32514
OCR_CROSS       :: 32515
OCR_UP          :: 32516
OCR_SIZENWSE    :: 32642
OCR_SIZENESW    :: 32643
OCR_SIZEWE      :: 32644
OCR_SIZENS      :: 32645
OCR_SIZEALL     :: 32646
OCR_NO          :: 32648
OCR_HAND        :: 32649
OCR_APPSTARTING :: 32650

Retrived from SetSystemCursor.

Current Behavior

The cursor constants listed above are missing from the Win32 bindings.

@bplu4t2f
Copy link

bplu4t2f commented Feb 9, 2025

For what it's worth, these use the same numbers as the IDC_* (and _IDC_*_) constants. Although I'm not a fan of how those are defined in general because of all the LPCSTR/LPCWSTR/DWORD type mismatches in those APIs, which become more apparent in Odin than they were in C. I think in such cases in general, the Odin libraries should have at least one definition that's just the number, and derive the various pointer types from that.

@Kelimion
Copy link
Member

Kelimion commented Feb 9, 2025

It's true that the OCR_* and IDC_* ones overlap, but if we make them a simple untyped numeric constant that the others derive from, that would still require IDI_* to be special cased, as those also use the same numbers for different purposes: ARROW versus APPLICATION, IBEAM versus HAND, and so forth. The OCR_* constants do line up with the IDC_*, true, but for greppability of OCR versus IDC when referencing the MSDN documentation, it's better to just duplicate the constants.

These APIs are a bit of a mess. They'll use a numeric constant typed as a ptr, and pass it as a cstring.

core/sys/windows/types.odin:_IDC_ARROW       := rawptr(uintptr(32512))
core/sys/windows/types.odin:_IDC_IBEAM       := rawptr(uintptr(32513))
core/sys/windows/types.odin:_IDC_WAIT        := rawptr(uintptr(32514))
core/sys/windows/types.odin:_IDC_CROSS       := rawptr(uintptr(32515))
core/sys/windows/types.odin:_IDC_UPARROW     := rawptr(uintptr(32516))
core/sys/windows/types.odin:IDC_ARROW        := cstring(_IDC_ARROW)
core/sys/windows/types.odin:IDC_IBEAM        := cstring(_IDC_IBEAM)
core/sys/windows/types.odin:IDC_WAIT         := cstring(_IDC_WAIT)
core/sys/windows/types.odin:IDC_CROSS        := cstring(_IDC_CROSS)
core/sys/windows/types.odin:IDC_HAND         := cstring(_IDC_HAND)
core/sys/windows/types.odin:IDC_UPARROW      := cstring(_IDC_UPARROW)


core/sys/windows/types.odin:_IDI_APPLICATION := rawptr(uintptr(32512))
core/sys/windows/types.odin:_IDI_HAND        := rawptr(uintptr(32513))
core/sys/windows/types.odin:_IDI_QUESTION    := rawptr(uintptr(32514))
core/sys/windows/types.odin:_IDI_EXCLAMATION := rawptr(uintptr(32515))
core/sys/windows/types.odin:_IDI_ASTERISK    := rawptr(uintptr(32516))
core/sys/windows/types.odin:IDI_APPLICATION  := cstring(_IDI_APPLICATION)
core/sys/windows/types.odin:IDI_HAND         := cstring(_IDI_HAND)
core/sys/windows/types.odin:IDI_QUESTION     := cstring(_IDI_QUESTION)
core/sys/windows/types.odin:IDI_EXCLAMATION  := cstring(_IDI_EXCLAMATION)
core/sys/windows/types.odin:IDI_ASTERISK     := cstring(_IDI_ASTERISK)

@bplu4t2f
Copy link

bplu4t2f commented Feb 9, 2025

@Kelimion The OP of this issue was complaining about missing OCR, which have a corresponding, equally named IDC constant, nothing to do with IDI.

IDI are semantically totally different, they refer to, like, those standard Win32 message box pictures that can be displayed next to the text.

The fact that the numbers coincide is just a consequence of how those APIs treat their arguments if they're below 65536.

I like using the ...W functions personally in every case anyway, so I can't use Odin's IDC_ definitions because they're not LPCWSTR. It's a mess but it could be worse. It's what you get when you "overload" functions in C by accepting entirely different arguments and treating them differently based on numeric value.

@Kelimion
Copy link
Member

Kelimion commented Feb 9, 2025

Yes, that's exactly my point with respect to the IDI ones.

We may even want to get rid of LoadCursorA as we're using the W procedures only everywhere else, and retool the IDC constants to work with LoadCursorW instead.

@Kelimion
Copy link
Member

Kelimion commented Feb 9, 2025

I'm not opposed to _IBEAM :: 32513 which can be used to derive OCR_IBEAM and IDC_IBEAM both. That's a good shout.

@bplu4t2f
Copy link

bplu4t2f commented Feb 9, 2025

Oh I see. I thought you were suggesting that there's a connection between IDC and IDI.

Regarding _IBEAM, it'll probably work fine, but something doesn't sit right with me. It might cause naming conflicts because it's not "namespaced" like most other things (see IDI_HAND and IDC_HAND); it may not be as discoverable for the same reason; and it doesn't read like... let's call it "idiomatic Win32 code". Probably just me, but reading IDC_ gives me umm... inner peace.

@Kelimion
Copy link
Member

Kelimion commented Feb 9, 2025

Oh I see. I thought you were suggesting that there's a connection between IDC and IDI.

No, just exploring whether if we're going to add purely numeric constants from which to derive IDC and OCR, whether they pop up elsewhere, given the commonality these have. And IDI is the odd duck out in sharing these ids.

Regarding IBEAM, it'll probably work fine, but something doesn't sit right with me. It might cause naming conflicts because it's not "namespaced" like most other things (see IDI_HAND and IDC_HAND); it may not be as discoverable for the same reason; and it doesn't read like... let's call it "idiomatic Win32 code". Probably just me, but reading IDC gives me umm... inner peace.

You'd still have IDC_FOO inner peace. It would just come from IDC_FOO :: cstring(rawptr(uintptr(_FOO)) or the W equivalent, whereas OCR_FOO would then become OCR_FOO :: DWORD(_FOO)?

@bplu4t2f
Copy link

bplu4t2f commented Feb 9, 2025

Hmm, ultimately I don't think I have a strong enough opinion about that. If someone's programming win32, I think they're used to wonky arguments and questionable constants. Just a little worried about potential naming conflicts.

@Kelimion
Copy link
Member

Kelimion commented Feb 9, 2025

As Microsoft namespaces all of their enum constants, I don't imagine that to be an issue.

Another option would be to use OCR_FOO :: 12345, as it's used as a DWORD param and so the untyped numeric constant would be fine. Then IDC_FOO could become IDC_FOO :: rawptr(uintptr(OCR_FOO)) or what have you, to show they're really the same thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants