We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5188 - SDL_SetCursor does not work when Metal view is created
Summary: SDL_SetCursor does not work when Metal view is created
Status: RESOLVED INVALID
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: 2.0.13
Hardware: x86_64 macOS 10.15
: P2 normal
Assignee: Alex Szpakowski
QA Contact: Sam Lantinga
URL:
Keywords: target-2.0.14
Depends on:
Blocks:
 
Reported: 2020-06-14 16:10 UTC by Konrad
Modified: 2020-06-16 21:42 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Konrad 2020-06-14 16:10:20 UTC
I did actually notice it when I created my own MTKView and used setContentView on wminfo.info.cocoa.window. However, the same does apply to creating SDL2 renderer with Metal backend in which SDL_SetCursor does not change current cursor. If you create SDL2 renderer with OpenGL backend instead it all works fine.
Comment 1 Alex Szpakowski 2020-06-16 00:46:36 UTC
I tested in my own codebase and it works fine for me - although my cursor and Metal code is no doubt abstracted differently from yours. Do you have a standalone bit of code you can attach to the issue which reproduces the problem for you?
Comment 2 Alex Szpakowski 2020-06-16 00:47:48 UTC
I should also mention my codebase uses SDL_Metal_CreateView and friends, rather than messing with SDL's internal window/view structure.
Comment 3 Konrad 2020-06-16 07:19:22 UTC
I will try to write some example in such case. In my case I am using a MacBook Pro 16 2019 with Retina which made me wonder whether it is the cause since SDL2 Metal renderer itself is blurry (the view is stretched using linear filter and not nearest pixel filter like for OpenGL).

Anyway, at first I thought like yourself that I might be hijacking some important callbacks with changing the view, but I did notice in SDL2 2.0.12 this is all taken care of by Cocoa in which we do usually get contentView of nsWindow instead of using some previously cached value:

/* Only store this for windows created by us since the content view might
 * get replaced from under us otherwise, and we only need it when the
 * window is guaranteed to be created by us (OpenGL contexts). */
data->sdlContentView = created ? [nswindow contentView] : nil;

There is a regression in 2.0.13 in which sdlContentView is more cached (not only for OpenGL context of our own creation) which is rather wrong in cases such as mine (I prefer to set my own view, in this case MTKView) so I would very much appreciate it being reverted back like it was in 2.0.12. I've noticed that creating CAMetalLayer and injecting it into thew view (like SDL_Metal_CreateView does) is much less efficient than having MTKView in such way that I cannot push more than 1000 fps in a simple scene with SDL2 Metal renderer. In fact, my first approach to Metal renderer was using SDL_Metal_CreateView, but in general this approach doesn't allow me to push as many fps as MTKView does with its currentDrawable and currentDescriptor. It is actually funny when SDL2 renderer with OpenGL backend can push more fps on OS X than SDL2 renderer with Metal backend.

Getting back to the topic - the issue here happens with clear SDL2 renderer with Metal backend, too, so I did assume it's not an issue from my side. That being the case I will try to write some test code to replicate it.
Comment 4 Konrad 2020-06-16 08:23:01 UTC
I do very much apologize. I just ran some tests. I was in fact hijacking the content view anyway even though I was switching to SDL2 Metal renderer afterwards. Disabling contentView switching made it work even for Metal backend on SDL2. Anyway, that is indeed the cause of this issue, so I suppose I am hijacking some important things with setting the contentView to MTKView.

As much as I would love to use SDL_Metal_CreateView like I did before, I cannot accept how little frames compared to OpenGL I can push with very simple scene and I honestly don't know what is the cause of it. It seems to be mostly blocking on nextDrawable.
Comment 5 Konrad 2020-06-16 12:36:51 UTC
Again, I do apologize for the bug report itself which doesn't appear to originate from the core of SDL2, but I believe this might be useful for others, too.

Anyway, after setting contentView of cocoa window the only thing missing I could notice was lack of right click and changing cursor. Perhaps others, too, but I didn't notice anything other than that. SDL2 does receive mouse movements and left clicks just fine and generic events are handled properly.

In order to fix that I did try to hack into SDL2 internals (using nextResponder which I assumed was the case why I do lack of cursor changes and right clicks) with the following code, but it did not work. Perhaps someone has a better idea how to approach this issue:

// SGVIew interface dispatches events to internal SDL view

@interface SGPView : MTKView {

}

- (void)rightMouseDown:(NSEvent *)theEvent;
- (void)drawRect:(NSRect)dirtyRect;
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;
- (void)updateLayer;
@end

@implementation SGPView

- (void)drawRect:(NSRect)dirtyRect
{
    [sdlContentView drawRect:dirtyRect];
}

- (void)updateLayer
{
    [sdlContentView updateLayer];
}

- (void)rightMouseDown:(NSEvent *)theEvent
{
    [sdlContentView rightMouseDown:theEvent];
}

- (void)resetCursorRects
{
    [sdlContentView resetCursorRects];
}

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
    //return [sdlContentView ac]
    return YES;
}
@end

// ...

SGPView *metalView = [[SGPView alloc] init];
// ...
NSView *sdlContentView = [wminfo.info.cocoa.window contentView];

[metalView setNextResponder:[sdlContentView nextResponder]];
[metalView setAcceptsTouchEvents:YES];

[wminfo.info.cocoa.window setContentView:metalView];

[sdlContentView setNextResponder:[metalView nextResponder]];
Comment 6 Konrad 2020-06-16 20:22:27 UTC
I will take the liberty of closing this bug report since it's not an issue from SDL2 side.

On a side note I was able to do it a bit differently. I did destroy already created SDL_Window and instead I did create my own NSWindow with attached MTKView. Then I used this data to pass to SDL_CreateWindowFrom which actually made right click working fine and I believe this is the proper approach rather than messing with internal Cocoa window properties created by SDL2. However, cursors still do not work which I will have to look into even further.
Comment 7 Alex Szpakowski 2020-06-16 20:28:19 UTC
I think opening a separate bug for the performance difference you noticed would be fair, as well.
Comment 8 Konrad 2020-06-16 21:36:21 UTC
I just did.

Anyway, I've noticed that functions from:

@interface SDLView : NSView

Are not used when window is created with SDL_CreateWindowFrom. This is probably why setting cursors do not work. Isn't it a bug within SDL2 this time?
Comment 9 Alex Szpakowski 2020-06-16 21:42:45 UTC
If you use an external window then it will naturally be an external view. Some parts of Cocoa can't easily be hooked into without subclassing an NSView - I haven't looked into the specifics of your case but in general I wouldn't expect every part of SDL to be able to hook into external windows, on any platform.