Skip to content

Conversation

@maik205
Copy link

@maik205 maik205 commented Dec 10, 2025

This PR adds a wrapper function and required enums for the SDL_SetWindowHitTest function in the video submodule.

The function is currently implemented with a trampoline function to wrap around bindgen's extern "C" function pointer type.

To replace SDL_SetWindowHitTest(SDL_Window* win, const SDL_Point* area, void* data)'s data void pointer, I've implemented the closure as an impl Fn to be able to capture variables as needed into the closure instead of passing them as function parameters.

This is my first time PR'ing to this repo so this might be a bad implementation/API, please give me feedback, thank you so much!

Copy link
Member

@revmischa revmischa left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution!

Comment on lines +2341 to +2342
let boxed: Box<Box<dyn Fn(crate::rect::Point) -> HitTestResult>> =
Box::new(Box::new(hit_test));
Copy link
Member

Choose a reason for hiding this comment

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

why is it in two boxes?

Copy link
Author

Choose a reason for hiding this comment

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

I wrapped the closure twice to relax the trait bounds when dereferencing the callback from c_void pointer, as only Box'ing it once would yield

expected a `Fn(Point)` closure, found `c_void`
the trait `Fn(Point)` is not implemented for `c_void`
required for the cast from `*mut c_void` to `*mut dyn Fn(Point) -> HitTestResult

Copy link
Member

Choose a reason for hiding this comment

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

let callback = &*(data as *const dyn Fn(Point) -> HitTestResult); might work

Copy link
Author

Choose a reason for hiding this comment

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

I tried your solution but it seems the compiler still stops us from casting it into a trait pointer...

expected a `Fn(Point)` closure, found `c_void`
the trait `Fn(Point)` is not implemented for `c_void`
required for the cast from `*mut c_void` to `*const dyn Fn(Point) -> HitTestResult

Casting the void pointer into the trait pointer still requires the void pointer to implement that trait (which c_void doesn't)
I think Box is still needed to relax the trait bounds


unsafe {
let result =
sys::video::SDL_SetWindowHitTest(self.context.raw, Some(hit_test_sys), userdata);
Copy link
Member

Choose a reason for hiding this comment

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

It seems like the hit_test will never be freed, we could store the userdata pointer on the Window struct and free it on Window drop perhaps.

Copy link
Author

@maik205 maik205 Dec 11, 2025

Choose a reason for hiding this comment

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

I moved hit_test into the Window struct in 96e8623

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

Successfully merging this pull request may close these issues.

2 participants