From 1e158e522f05d8676ebb5eee94ae5d03081e20f0 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <vital.had@gmail.com>
Date: Sat, 11 Oct 2025 11:08:20 +0800
Subject: [PATCH 2/4] gui/minimal_macosx/intf.m

---
 modules/gui/minimal_macosx/intf.m | 130 ++++++++++++++++++++----------
 1 file changed, 86 insertions(+), 44 deletions(-)

diff --git modules/gui/minimal_macosx/intf.m modules/gui/minimal_macosx/intf.m
index a778e3bc56..b476fd0c02 100644
--- modules/gui/minimal_macosx/intf.m
+++ modules/gui/minimal_macosx/intf.m
@@ -81,58 +81,105 @@ extern OSErr    CPSGetCurrentProcess(CPSProcessSerNum *psn);
 extern OSErr    CPSEnableForegroundOperation(CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
 extern OSErr    CPSSetFrontProcess(CPSProcessSerNum *psn);
 
-
 /*****************************************************************************
  * Run: main loop
  *****************************************************************************/
 static void Run(intf_thread_t *p_intf)
 {
     CPSProcessSerNum PSN;
-    @autoreleasepool {
-        [NSApplication sharedApplication];
-        if (!CPSGetCurrentProcess(&PSN))
-            if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
-                if (!CPSSetFrontProcess(&PSN))
-                    [NSApplication sharedApplication];
-    }
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    [NSApplication sharedApplication];
+    if (!CPSGetCurrentProcess(&PSN))
+        if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
+            if (!CPSSetFrontProcess(&PSN))
+                [NSApplication sharedApplication];
+    [pool release];
 }
 
 /*****************************************************************************
  * Vout window management
  *****************************************************************************/
+
 static int WindowControl(vout_window_t *, int i_query, va_list);
 
+struct minimal_window_create_ctx {
+    VLCMinimalVoutWindow **window_ptr;
+    NSRect rect;
+};
+
+static void minimal_create_window(void *context)
+{
+    struct minimal_window_create_ctx *ctx = (struct minimal_window_create_ctx *)context;
+    *(ctx->window_ptr) = [[VLCMinimalVoutWindow alloc] initWithContentRect:ctx->rect];
+    if (*(ctx->window_ptr))
+        [*(ctx->window_ptr) makeKeyAndOrderFront:nil];
+}
+
 int WindowOpen(vout_window_t *p_wnd, const vout_window_cfg_t *cfg)
 {
     if (cfg->type != VOUT_WINDOW_TYPE_INVALID
      && cfg->type != VOUT_WINDOW_TYPE_NSOBJECT)
         return VLC_EGENERIC;
 
-    @autoreleasepool {
-        NSRect proposedVideoViewPosition = NSMakeRect(cfg->x, cfg->y, cfg->width, cfg->height);
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
-        VLCMinimalVoutWindow *o_window = [[VLCMinimalVoutWindow alloc] initWithContentRect:proposedVideoViewPosition];
-        [o_window makeKeyAndOrderFront:nil];
+    NSRect proposedVideoViewPosition = NSMakeRect(cfg->x, cfg->y, cfg->width, cfg->height);
+    VLCMinimalVoutWindow *o_window = nil;
 
-        if (!o_window) {
-            msg_Err(p_wnd, "window creation failed");
-            return VLC_EGENERIC;
-        }
+    struct minimal_window_create_ctx ctx = { &o_window, proposedVideoViewPosition };
+    dispatch_sync_f(dispatch_get_main_queue(), &ctx, minimal_create_window);
 
-        msg_Dbg(p_wnd, "returning video window with proposed position x=%i, y=%i, width=%i, height=%i", cfg->x, cfg->y, cfg->width, cfg->height);
-        p_wnd->handle.nsobject = (void *)CFBridgingRetain([o_window contentView]);
-
-        p_wnd->type = VOUT_WINDOW_TYPE_NSOBJECT;
-        p_wnd->control = WindowControl;
+    if (!o_window) {
+        msg_Err(p_wnd, "window creation failed");
+        [pool release];
+        return VLC_EGENERIC;
     }
 
+    msg_Dbg(p_wnd, "returning video window with proposed position x=%i, y=%i, width=%i, height=%i", cfg->x, cfg->y, cfg->width, cfg->height);
+
+    p_wnd->handle.nsobject = (void *)[o_window contentView];
+
+    p_wnd->type = VOUT_WINDOW_TYPE_NSOBJECT;
+    p_wnd->control = WindowControl;
+
+    [pool release];
     vout_window_SetFullScreen(p_wnd, cfg->is_fullscreen);
     return VLC_SUCCESS;
 }
 
+struct minimal_size_ctx {
+    NSWindow *window;
+    unsigned int width;
+    unsigned int height;
+};
+
+static void minimal_set_size(void *context)
+{
+    struct minimal_size_ctx *ctx = (struct minimal_size_ctx *)context;
+    NSRect theFrame = [ctx->window frame];
+    theFrame.size.width = ctx->width;
+    theFrame.size.height = ctx->height;
+    [ctx->window setFrame:theFrame display:YES animate:YES];
+}
+
+struct minimal_fullscreen_ctx {
+    NSWindow *window;
+    int is_fullscreen;
+};
+
+static void minimal_set_fullscreen(void *context)
+{
+    struct minimal_fullscreen_ctx *ctx = (struct minimal_fullscreen_ctx *)context;
+    if (ctx->is_fullscreen)
+        [(VLCMinimalVoutWindow*)ctx->window enterFullscreen];
+    else
+        [(VLCMinimalVoutWindow*)ctx->window leaveFullscreen];
+}
+
 static int WindowControl(vout_window_t *p_wnd, int i_query, va_list args)
 {
-    NSWindow* o_window = [(__bridge id)p_wnd->handle.nsobject window];
+    NSView *view = (NSView*)p_wnd->handle.nsobject;
+    NSWindow* o_window = [view window];
     if (!o_window) {
         msg_Err(p_wnd, "failed to recover cocoa window");
         return VLC_EGENERIC;
@@ -142,36 +189,29 @@ static int WindowControl(vout_window_t *p_wnd, int i_query, va_list args)
         case VOUT_WINDOW_SET_STATE:
         {
             unsigned i_state = va_arg(args, unsigned);
-
             [o_window setLevel:i_state];
-
             return VLC_SUCCESS;
         }
         case VOUT_WINDOW_SET_SIZE:
         {
             unsigned int i_width  = va_arg(args, unsigned int);
             unsigned int i_height = va_arg(args, unsigned int);
-            @autoreleasepool {
-                dispatch_sync(dispatch_get_main_queue(), ^{
-                    NSRect theFrame = [o_window frame];
-                    theFrame.size.width = i_width;
-                    theFrame.size.height = i_height;
-                    [o_window setFrame:theFrame display:YES animate:YES];
-                });
-            }
+
+            struct minimal_size_ctx ctx;
+            ctx.window = o_window;
+            ctx.width = i_width;
+            ctx.height = i_height;
+            dispatch_sync_f(dispatch_get_main_queue(), &ctx, minimal_set_size);
             return VLC_SUCCESS;
         }
         case VOUT_WINDOW_SET_FULLSCREEN:
         {
             int i_full = va_arg(args, int);
-            @autoreleasepool {
-                dispatch_sync(dispatch_get_main_queue(), ^{
-                    if (i_full)
-                        [(VLCMinimalVoutWindow*)o_window enterFullscreen];
-                    else
-                        [(VLCMinimalVoutWindow*)o_window leaveFullscreen];
-                });
-            }
+
+            struct minimal_fullscreen_ctx ctx;
+            ctx.window = o_window;
+            ctx.is_fullscreen = i_full;
+            dispatch_sync_f(dispatch_get_main_queue(), &ctx, minimal_set_fullscreen);
             return VLC_SUCCESS;
         }
         default:
@@ -182,9 +222,11 @@ static int WindowControl(vout_window_t *p_wnd, int i_query, va_list args)
 
 void WindowClose(vout_window_t *p_wnd)
 {
-    @autoreleasepool {
-        NSWindow * o_window = [(__bridge id)p_wnd->handle.nsobject window];
-        if (o_window)
-            o_window = nil;
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSView *view = (NSView*)p_wnd->handle.nsobject;
+    NSWindow *o_window = [view window];
+    if (o_window) {
+        [o_window orderOut:nil];
     }
+    [pool release];
 }
-- 
2.51.0

