Skip to content

Macos: Rendering to an external NSView doesn't work in practice #12141

@leksiso

Description

@leksiso

I'm trying to use SDL to render custom content in a mac cocoa application with Metal as the SDL backend. What I want to do is to manually initialize an NSView (that doesn't fill the whole window) and tell SDL to render to it. I can see that there's some support for the above scenario in SDL. However, it doesn't seem to work very well (unless I'm missing something).

As a proof of concept, I'm trying to achieve the following:

  • Create a native view with some coords & size, make it blue with the platform APIs:
Image
  • Create a SDL window with a reference to that native view using SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER.
  • When the button is pressed, fill the SDL window with red
Image

What currently happens:

Image

SDL_CreateWindowWithProperties takes the view I gave to it and makes it the window root view (NSWindow.contentView).
I understand that SDL is usually used in a full window context, but I'd argue that it's a bug in this case.

This can be fixed by moving [nswindow setContentView:nsview]; from line 2357 in SDL_cocoawindow.m to line 2319 (i.e. to the end of the else branch of if (nswindow) {)

With that change, the window constructor doesn't hijack the whole window. However pressing the button doesn't still do quite what I'd like it to do:

Image

Clearing the SDL window fills the whole NSWindow instead of just the NSView. This is caused by the fact that Cocoa_Metal_CreateView uses data.nswindow.contentView as the superview of the metal view. I think using data.sdlContentView would be more appropriate in that function.
If we do that, my test works almost as expected:

Image

Now the only problem is that the origin of the metal view is wrong. This could be fixed by changing line SDL_cocoametalview.m:144 from newview = [[SDL3_cocoametalview alloc] initWithFrame:view.frame to newview = [[SDL3_cocoametalview alloc] initWithFrame:view.bounds.

With these changes, the rendering works more like I would expect it to. Could give some comments on this? Is the API even supposed to work as I'm presenting above? If yes, would you like me to submit a PR with the above changes?

I'll include my test setup code as a zip.

SDLMetalViewTest.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions