From e65dcd64b875253852d5e724dd432f94d3672799 Mon Sep 17 00:00:00 2001 From: Bruno Date: Sat, 21 Feb 2026 16:23:54 -0300 Subject: [PATCH] add bindings to allow custom cursors --- .../darwin/Foundation/NSBitmapImageRep.odin | 82 +++++++++++++------ core/sys/darwin/Foundation/NSColor.odin | 9 +- core/sys/darwin/Foundation/NSCursor.odin | 8 ++ core/sys/darwin/Foundation/NSImage.odin | 19 +++++ core/sys/darwin/Foundation/NSImageRep.odin | 4 + core/sys/windows/gdi32.odin | 8 ++ core/sys/windows/user32.odin | 1 + vendor/x11/xlib/xlib_procs.odin | 3 +- vendor/x11/xlib/xlib_types.odin | 13 +++ 9 files changed, 119 insertions(+), 28 deletions(-) create mode 100644 core/sys/darwin/Foundation/NSImage.odin create mode 100644 core/sys/darwin/Foundation/NSImageRep.odin diff --git a/core/sys/darwin/Foundation/NSBitmapImageRep.odin b/core/sys/darwin/Foundation/NSBitmapImageRep.odin index 059a75e43..d10043d7a 100644 --- a/core/sys/darwin/Foundation/NSBitmapImageRep.odin +++ b/core/sys/darwin/Foundation/NSBitmapImageRep.odin @@ -1,42 +1,72 @@ package objc_Foundation -import "base:intrinsics" - @(objc_class="NSBitmapImageRep") BitmapImageRep :: struct { using _: Object } +BitmapInteger :: distinct UInteger +BitmapFormatFlag :: enum BitmapInteger { + AlphaFirst = 0, + AlphaNonpremultiplied = 1, + FloatingPointSamples = 2, + SixteenBitLittleEndian = 8, + ThirtyTwoBitLittleEndian = 9, + SixteenBitBigEndian = 10, + ThirtyTwoBitBigEndian = 11, +} +BitmapFormatFlags :: bit_set[BitmapFormatFlag; BitmapInteger] + @(objc_type=BitmapImageRep, objc_name="alloc", objc_is_class_method=true) BitmapImageRep_alloc :: proc "c" () -> ^BitmapImageRep { return msgSend(^BitmapImageRep, BitmapImageRep, "alloc") } -@(objc_type=BitmapImageRep, objc_name="initWithBitmapDataPlanes") -BitmapImageRep_initWithBitmapDataPlanes :: proc "c" ( - self: ^BitmapImageRep, +BitmapImageRep_initWithBitmapDataPlanes_legacy :: proc "c" ( + self: ^BitmapImageRep, bitmapDataPlanes: ^^u8, - pixelsWide: Integer, - pixelsHigh: Integer, - bitsPerSample: Integer, + pixelsWide: Integer, + pixelsHigh: Integer, + bitsPerSample: Integer, samplesPerPixel: Integer, - hasAlpha: bool, - isPlanar: bool, - colorSpaceName: ^String, - bytesPerRow: Integer, - bitsPerPixel: Integer) -> ^BitmapImageRep { - - return msgSend(^BitmapImageRep, - self, + hasAlpha: bool, + isPlanar: bool, + colorSpaceName: ^String, + bytesPerRow: Integer, + bitsPerPixel: Integer, +) -> ^BitmapImageRep { + return msgSend( + ^BitmapImageRep, self, "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:", - bitmapDataPlanes, - pixelsWide, - pixelsHigh, - bitsPerSample, - samplesPerPixel, - hasAlpha, - isPlanar, - colorSpaceName, - bytesPerRow, - bitsPerPixel) + bitmapDataPlanes, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel, + hasAlpha, isPlanar, colorSpaceName, bytesPerRow, bitsPerPixel, + ) +} + +BitmapImageRep_initWithBitmapDataPlanes_bitmapFormat :: proc "c" ( + self: ^BitmapImageRep, + bitmapDataPlanes: ^^u8, + pixelsWide: Integer, + pixelsHigh: Integer, + bitsPerSample: Integer, + samplesPerPixel: Integer, + hasAlpha: bool, + isPlanar: bool, + colorSpaceName: ^String, + bitmapFormat: BitmapFormatFlags, + bytesPerRow: Integer, + bitsPerPixel: Integer, +) -> ^BitmapImageRep { + return msgSend( + ^BitmapImageRep, self, + "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:", + bitmapDataPlanes, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel, + hasAlpha, isPlanar, colorSpaceName, bitmapFormat, bytesPerRow, bitsPerPixel, + ) +} + +@(objc_type=BitmapImageRep, objc_name="initWithBitmapDataPlanes") +BitmapImageRep_initWithBitmapDataPlanes :: proc{ + BitmapImageRep_initWithBitmapDataPlanes_legacy, + BitmapImageRep_initWithBitmapDataPlanes_bitmapFormat, } @(objc_type=BitmapImageRep, objc_name="bitmapData") diff --git a/core/sys/darwin/Foundation/NSColor.odin b/core/sys/darwin/Foundation/NSColor.odin index 453b33144..b50e08af1 100644 --- a/core/sys/darwin/Foundation/NSColor.odin +++ b/core/sys/darwin/Foundation/NSColor.odin @@ -1,5 +1,7 @@ package objc_Foundation +foreign import "system:Foundation.framework" + @(objc_class="NSColorSpace") ColorSpace :: struct {using _: Object} @@ -146,4 +148,9 @@ Color_numberOfComponents :: proc "c" (self: ^Color) -> Integer { @(objc_type=Color, objc_name="getComponents") Color_getComponents :: proc "c" (self: ^Color, components: [^]Float) { msgSend(nil, self, "getComponents:", components) -} \ No newline at end of file +} + +@(link_prefix="NS", default_calling_convention="c") +foreign Foundation { + DeviceRGBColorSpace: ^String +} diff --git a/core/sys/darwin/Foundation/NSCursor.odin b/core/sys/darwin/Foundation/NSCursor.odin index 2bebf5362..5c43e1353 100644 --- a/core/sys/darwin/Foundation/NSCursor.odin +++ b/core/sys/darwin/Foundation/NSCursor.odin @@ -3,6 +3,14 @@ package objc_Foundation @(objc_class="NSCursor") Cursor :: struct {using _: Object} +@(objc_type=Cursor, objc_name="alloc", objc_is_class_method=true) +Cursor_alloc :: proc "c" () -> ^Cursor { + return msgSend(^Cursor, Cursor, "alloc") +} +@(objc_type=Cursor, objc_name="initWithImage") +Cursor_initWithImage :: proc "c" (self: ^Cursor, image: ^Image, hotSpot: Point) -> ^Cursor { + return msgSend(^Cursor, self, "initWithImage:hotSpot:", image, hotSpot) +} @(objc_type=Cursor, objc_name="hide", objc_is_class_method=true) Cursor_hide :: proc() { msgSend(nil, Cursor, "hide") diff --git a/core/sys/darwin/Foundation/NSImage.odin b/core/sys/darwin/Foundation/NSImage.odin new file mode 100644 index 000000000..33aae6c50 --- /dev/null +++ b/core/sys/darwin/Foundation/NSImage.odin @@ -0,0 +1,19 @@ +package objc_Foundation + +@(objc_class="NSImage") +Image :: struct { using _: Object } + +@(objc_type=Image, objc_name="alloc", objc_is_class_method=true) +Image_alloc :: proc "c" () -> ^Image { + return msgSend(^Image, Image, "alloc") +} + +@(objc_type=Image, objc_name="initWithSize") +Image_initWithSize :: proc "c" (self: ^Image, size: Size) -> ^Image { + return msgSend(^Image, self, "initWithSize:", size) +} + +@(objc_type=Image, objc_name="addRepresentation") +Image_addRepresentation :: proc(self: ^Image, rep: ^ImageRep) { + msgSend(nil, self, "addRepresentation:", rep) +} diff --git a/core/sys/darwin/Foundation/NSImageRep.odin b/core/sys/darwin/Foundation/NSImageRep.odin new file mode 100644 index 000000000..1e80cb336 --- /dev/null +++ b/core/sys/darwin/Foundation/NSImageRep.odin @@ -0,0 +1,4 @@ +package objc_Foundation + +@(objc_class="NSImageRep") +ImageRep :: struct { using _: Object } diff --git a/core/sys/windows/gdi32.odin b/core/sys/windows/gdi32.odin index e607aafcc..603eb4dd9 100644 --- a/core/sys/windows/gdi32.odin +++ b/core/sys/windows/gdi32.odin @@ -19,6 +19,7 @@ foreign gdi32 { RestoreDC :: proc(hdc: HDC, nSavedDC: INT) -> BOOL --- CreateDIBPatternBrush :: proc(h: HGLOBAL, iUsage: UINT) -> HBRUSH --- + CreateBitmap :: proc(nWidth: INT, nHeight: INT, nPlanes: UINT, nBitCount: UINT, lpBits: LPVOID) -> HBITMAP --- CreateDIBitmap :: proc(hdc: HDC, pbmih: ^BITMAPINFOHEADER, flInit: DWORD, pjBits: VOID, pbmi: ^BITMAPINFO, iUsage: UINT) -> HBITMAP --- CreateDIBSection :: proc(hdc: HDC, pbmi: ^BITMAPINFO, usage: UINT, ppvBits: ^^VOID, hSection: HANDLE, offset: DWORD) -> HBITMAP --- StretchDIBits :: proc(hdc: HDC, xDest, yDest, DestWidth, DestHeight, xSrc, ySrc, SrcWidth, SrcHeight: INT, lpBits: VOID, lpbmi: ^BITMAPINFO, iUsage: UINT, rop: DWORD) -> INT --- @@ -151,6 +152,13 @@ BKMODE :: enum { OPAQUE = 2, } +ICONINFO :: struct { + fIcon: BOOL, + xHotspot, yHotspot: DWORD, + hbmMask, hbmColor: HBITMAP, +} +PICONINFO :: ^ICONINFO + ICONINFOEXW :: struct { cbSize: DWORD, fIcon: BOOL, diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index 615d7a84d..d2f54b127 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -116,6 +116,7 @@ foreign user32 { CreateIcon :: proc(hInstance: HINSTANCE, nWidth, nHeight: INT, cPlanes: BYTE, cBitsPixel: BYTE, lpbANDbits: PBYTE, lpbXORbits: PBYTE) -> HICON --- CreateIconFromResource :: proc(presbits: PBYTE, dwResSize: DWORD, fIcon: BOOL, dwVer: DWORD) -> HICON --- + CreateIconIndirect :: proc(piconinfo: PICONINFO) -> HICON --- DestroyIcon :: proc(hIcon: HICON) -> BOOL --- DrawIcon :: proc(hDC: HDC, X, Y: INT, hIcon: HICON) -> BOOL --- diff --git a/vendor/x11/xlib/xlib_procs.odin b/vendor/x11/xlib/xlib_procs.odin index a7aa7a770..3ab4acd17 100644 --- a/vendor/x11/xlib/xlib_procs.odin +++ b/vendor/x11/xlib/xlib_procs.odin @@ -13,7 +13,8 @@ foreign xcursor { cursorGetDefaultSize :: proc(display: ^Display) -> i32 --- cursorLibraryLoadCursor :: proc(display: ^Display, name: cstring) -> Cursor --- cursorLibraryLoadImage :: proc(name: cstring, theme: cstring, size: i32) -> rawptr --- - cursorImageLoadCursor :: proc(display: ^Display, img: rawptr) -> Cursor --- + cursorImageCreate :: proc(width: i32, height: i32) -> ^CursorImage --- + cursorImageLoadCursor :: proc(display: ^Display, img: ^CursorImage) -> Cursor --- cursorImageDestroy :: proc(img: rawptr) --- } diff --git a/vendor/x11/xlib/xlib_types.odin b/vendor/x11/xlib/xlib_types.odin index a73b8e8b8..bdbaf441e 100644 --- a/vendor/x11/xlib/xlib_types.odin +++ b/vendor/x11/xlib/xlib_types.odin @@ -2257,3 +2257,16 @@ XIRawEvent :: struct { raw_values: [^]f64, } +CursorUInt :: u32 +CursorDim :: u32 +CursorPixel :: u32 +CursorImage :: struct { + version: CursorDim, + size: CursorDim, + width: CursorDim, + height: CursorDim, + xhot: CursorDim, + yhot: CursorDim, + delay: CursorUInt, + pixels: ^CursorPixel, // ARGB +}