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

CreateWindowFrom on macOS doesn't work with sub-widgets, only top level window #3613

Closed
SDLBugzilla opened this issue Feb 11, 2021 · 0 comments
Labels
enhancement New feature or request

Comments

@SDLBugzilla
Copy link
Collaborator

SDLBugzilla commented Feb 11, 2021

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: HG 2.1
Reported for operating system, platform: Mac OS X (All), x86

Comments on the original bug report:

On 2020-03-25 23:51:29 +0000, wrote:

On Windows and X11, we can use CreateWindowFrom on arbitrary native widgets (referenced with either HWND or the xid) to embed an SDL window inside a larger widget layout.

On macOS, CreateWindowFrom only supports being called with an NSWindow* object. It should support being called with NSView* objects as well.

This is useful for e.g. games, game editors, simulations, etc.

On 2020-03-25 23:57:09 +0000, wrote:

Created attachment 4280
[PATCH] cocoa: allow calling CreateWindowFrom on an NSView

Here's an attempt at allowing CreateWindowFrom to work with NSViews.

It expands the role of the existing sdlContentView field (caches [nswindow contentView] for created windows, since Cocoa complains if contentview is called off the main thread) to hold the NSView for non-created windows as well. All calls to [nswindow contentView] have been replaced with references to sdlContentView.

When an NSView is passed into CreateWindowFrom, it sets sdlContentView directly, and finds the associated window with [nsview window].

Tested with a basic Qt application, and with testdraw2 and testgl2 from the tests directory.

On 2020-03-26 00:04:11 +0000, wrote:

Comment on attachment 4280
[PATCH] cocoa: allow calling CreateWindowFrom on an NSView

HG changeset patch

User Michael Maltese michaeljosephmaltese@gmail.com

Date 1585179643 25200

Wed Mar 25 16:40:43 2020 -0700

Node ID aaec3f2027fc1efe5473bbd8477d5860f97487ff

Parent 389ce8cfa2a31f765c3d751c911c73abf5c60e33

cocoa: allow calling CreateWindowFrom on an NSView

This lets applications embed SDL with other widgets surrounding it.
Already possible on Windows and X11.

diff -r 389ce8cfa2a3 -r aaec3f2027fc src/video/cocoa/SDL_cocoaopengl.m
--- a/src/video/cocoa/SDL_cocoaopengl.m Wed Mar 25 09:38:45 2020 -0700
+++ b/src/video/cocoa/SDL_cocoaopengl.m Wed Mar 25 16:40:43 2020 -0700
@@ -97,17 +97,6 @@
SDL_WindowData *windowdata = (SDL_WindowData *)newWindow->driverdata;
NSView *contentview = windowdata->sdlContentView;

  •    /* This should never be nil since sdlContentView is only nil if the
    
  •       window was created via SDL_CreateWindowFrom, and SDL doesn't allow
    
  •       OpenGL contexts to be created in that case. However, it doesn't hurt
    
  •       to check. */
    
  •    if (contentview == nil) {
    
  •        /* Prefer to access the cached content view above instead of this,
    
  •           since as of Xcode 11 + SDK 10.15, [window contentView] causes
    
  •           Apple's Main Thread Checker to output a warning. */
    
  •        contentview = [windowdata->nswindow contentView];
    
  •    }
    
  •    /* Now sign up for scheduled updates for the new window. */
       NSMutableArray *contexts = windowdata->nscontexts;
       @synchronized (contexts) {
    

@@ -362,7 +351,7 @@
Cocoa_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
{
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;

  • NSView *contentView = [windata->nswindow contentView];
  • NSView *contentView = windata->sdlContentView;
    NSRect viewport = [contentView bounds];

    if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
    diff -r 389ce8cfa2a3 -r aaec3f2027fc src/video/cocoa/SDL_cocoashape.m
    --- a/src/video/cocoa/SDL_cocoashape.m Wed Mar 25 09:38:45 2020 -0700
    +++ b/src/video/cocoa/SDL_cocoashape.m Wed Mar 25 16:40:43 2020 -0700
    @@ -88,10 +88,10 @@
    [NSGraphicsContext setCurrentContext:data->context];

    [[NSColor clearColor] set];

  • NSRectFill([[windata->nswindow contentView] frame]);
  • NSRectFill([windata->sdlContentView frame]);
    data->shape = SDL_CalculateShapeTree(*shape_mode,shape);
  • closure.view = [windata->nswindow contentView];
  • closure.view = windata->sdlContentView;
    closure.path = [NSBezierPath bezierPath];
    closure.window = shaper->window;
    SDL_TraverseShapeTree(data->shape,&ConvertRects,&closure);
    diff -r 389ce8cfa2a3 -r aaec3f2027fc src/video/cocoa/SDL_cocoawindow.h
    --- a/src/video/cocoa/SDL_cocoawindow.h Wed Mar 25 09:38:45 2020 -0700
    +++ b/src/video/cocoa/SDL_cocoawindow.h Wed Mar 25 16:40:43 2020 -0700
    @@ -113,7 +113,7 @@
    {
    SDL_Window *window;
    NSWindow *nswindow;
  • NSView sdlContentView; / nil if window is created via CreateWindowFrom */
  • NSView *sdlContentView;
    NSMutableArray *nscontexts;
    SDL_bool created;
    SDL_bool inWindowFullscreenTransition;
    diff -r 389ce8cfa2a3 -r aaec3f2027fc src/video/cocoa/SDL_cocoawindow.m
    --- a/src/video/cocoa/SDL_cocoawindow.m Wed Mar 25 09:38:45 2020 -0700
    +++ b/src/video/cocoa/SDL_cocoawindow.m Wed Mar 25 16:40:43 2020 -0700
    @@ -297,15 +297,15 @@
    NSWindow *nswindow = data->nswindow;

    /* The view responder chain gets messed with during setStyleMask */

  • if ([[nswindow contentView] nextResponder] == data->listener) {
  •    [[nswindow contentView] setNextResponder:nil];
    
  • if ([data->sdlContentView nextResponder] == data->listener) {

  •    [data->sdlContentView setNextResponder:nil];
    

    }

    [nswindow setStyleMask:style];

    /* The view responder chain gets messed with during setStyleMask */

  • if ([[nswindow contentView] nextResponder] != data->listener) {
  •    [[nswindow contentView] setNextResponder:data->listener];
    
  • if ([data->sdlContentView nextResponder] != data->listener) {

  •    [data->sdlContentView setNextResponder:data->listener];
    

    }

    return SDL_TRUE;
    @@ -318,7 +318,7 @@
    {
    NSNotificationCenter *center;
    NSWindow *window = data->nswindow;

  • NSView *view = [window contentView];
  • NSView *view = data->sdlContentView;

    _data = data;
    observingVisible = YES;
    @@ -1360,7 +1360,7 @@
    @EnD

static int
-SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
+SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, NSView *nsview, SDL_bool created)
{ @autoreleasepool
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
@@ -1376,11 +1376,7 @@
data->created = created;
data->videodata = videodata;
data->nscontexts = [[NSMutableArray alloc] init];

  • /* 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;
  • data->sdlContentView = nsview;

    /* Create an event listener for the window */
    data->listener = [[Cocoa_WindowListener alloc] init];
    @@ -1541,7 +1537,7 @@
    [nswindow setContentView:contentView];
    [contentView release];

  • if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
  • if (SetupWindowData(_this, window, nswindow, contentView, SDL_TRUE) < 0) {
    [nswindow release];
    return -1;
    }
    @@ -1571,7 +1567,19 @@
    Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
    { @autoreleasepool
    {
  • NSWindow *nswindow = (NSWindow *) data;
  • NSView* nsview;

  • NSWindow *nswindow;

  • if ([(id)data isKindOfClass:[NSWindow class]]) {

  •  nswindow = (NSWindow*)data;
    
  •  nsview = [nswindow contentView];
    
  • } else if ([(id)data isKindOfClass:[NSView class]]) {

  •  nsview = (NSView*)data;
    
  •  nswindow = [nsview window];
    
  • } else {

  •  SDL_assert(false);
    
  • }

  • NSString *title;

    /* Query the title from the existing window */
    @@ -1580,7 +1588,7 @@
    window->title = SDL_strdup([title UTF8String]);
    }

  • return SetupWindowData(_this, window, nswindow, SDL_FALSE);
  • return SetupWindowData(_this, window, nswindow, nsview, SDL_FALSE);
    }}

void
@@ -1795,8 +1803,8 @@
NSRect rect;

 /* The view responder chain gets messed with during setStyleMask */
  • if ([[nswindow contentView] nextResponder] == data->listener) {
  •    [[nswindow contentView] setNextResponder:nil];
    
  • if ([data->sdlContentView nextResponder] == data->listener) {

  •    [data->sdlContentView setNextResponder:nil];
    

    }

    if (fullscreen) {
    @@ -1852,8 +1860,8 @@
    }

    /* The view responder chain gets messed with during setStyleMask */

  • if ([[nswindow contentView] nextResponder] != data->listener) {
  •    [[nswindow contentView] setNextResponder:data->listener];
    
  • if ([data->sdlContentView nextResponder] != data->listener) {

  •    [data->sdlContentView setNextResponder:data->listener];
    

    }

    s_moveHack = 0;

On 2020-03-26 18:20:04 +0000, Eric Shepherd (:sheppy) wrote:

This patch looks promising. I will try to come up with time to try it out myself as well.

On 2020-04-07 18:31:35 +0000, Ryan C. Gordon wrote:

This looks reasonable to me. I've put it in revision control at https://hg.libsdl.org/SDL/rev/6d22d6ce725c ... Eric, if you want to try it, just get the latest revision of SDL.

Thanks!

--ryan.

On 2020-09-16 03:38:11 +0000, zeb wrote:

I have tried the newest version from the hg repos. The problem has not been resolved.

Here is my test code:

# coding: utf-8

import os
import wx

import sdl2
import sdl2.ext
# import sdl2.sdlgfx

class MainFrame(wx.Frame):
  def __init__(self):
    wx.Frame.__init__(self, None, -1, 'MainFrame', pos=(0, 0), size = (400, 300), style = wx.DEFAULT_FRAME_STYLE)

    self.panelLeft = wx.Panel(self, style=wx.BORDER_SUNKEN)
    self.panelRight = wx.Panel(self, style=wx.BORDER_SUNKEN)

    sizer = wx.BoxSizer()
    sizer.Add(self.panelLeft, 1, wx.ALL|wx.EXPAND, border=10)
    sizer.Add(self.panelRight, 1, wx.ALL|wx.EXPAND, border=10)
    self.SetSizer(sizer)

    sdl2.ext.init()
    self.window = sdl2.SDL_CreateWindowFrom(self.panelRight.GetHandle())
    self.renderer = sdl2.SDL_CreateRenderer(self.window, -1, sdl2.SDL_RENDERER_ACCELERATED)
    sdl2.SDL_SetHint(sdl2.hints.SDL_HINT_RENDER_SCALE_QUALITY, b"1")

    self.Bind(wx.EVT_IDLE, self.render)

  def render(self, e):
    sdl2.SDL_SetRenderDrawColor(self.renderer, 225, 0, 0, 255)
    sdl2.SDL_RenderClear(self.renderer)
    # sdl2.sdlgfx.lineRGBA(self.renderer, 0, 0, 100, 100, 255, 255, 255, 255)
    sdl2.SDL_RenderPresent(self.renderer)

class App(wx.App):
  def OnInit(self):
    self.mainFrame = MainFrame()
    self.mainFrame.Show(True)
    self.mainFrame.CentreOnScreen()
    self.SetTopWindow(self.mainFrame)
    return True

  def getMainFrame(self):
    return self._mainFrame

app = App()
app.MainLoop()

The right panel should be filled with red color, but the whole window has beed filled.

On 2020-09-19 17:51:27 +0000, wrote:

@zeb This issue was about CreateWindowFrom not working at all on macOS, leading to crashes or at the least a failure to create a window. That issue has been fixed.

What you're writing about is not the same issue: CreateFromWindow gives you a working SDL window (what this bug fixed), just not the one you want (not part of this but). Honestly it sounds like a wxWidgets issue not giving an NSView for the widget you want.

I'm reclosing this — if you need support for your issue, please take it to the forums. (If in the end it is determined to be an SDL issue, then please create a new bug.)

On 2020-09-19 17:51:51 +0000, wrote:

.

@SDLBugzilla SDLBugzilla added the enhancement New feature or request label Feb 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant