# HG changeset patch # User Olaf Wintermann # Date 1780761894 -7200 # Node ID 8b8da1adef7dedb8bb2a2b0c183bbfc51047c8c6 # Parent ce0e443174d790440866f9b5d7f6230edddbe01a fix window memory management (Cocoa) diff -r ce0e443174d7 -r 8b8da1adef7d make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj --- a/make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj Sat Jun 06 16:53:39 2026 +0200 +++ b/make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj Sat Jun 06 18:04:54 2026 +0200 @@ -158,7 +158,7 @@ ED6581522CFF3CA000F5402F /* range.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = range.h; path = ../../../ui/ui/range.h; sourceTree = ""; }; ED6581542CFF3CA000F5402F /* text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = text.h; path = ../../../ui/ui/text.h; sourceTree = ""; }; ED6581552CFF3CA000F5402F /* toolbar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = toolbar.h; path = ../../../ui/ui/toolbar.h; sourceTree = ""; }; - ED6581562CFF3CA000F5402F /* toolkit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = toolkit.h; path = ../../../ui/ui/toolkit.h; sourceTree = ""; }; + ED6581562CFF3CA000F5402F /* toolkit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = toolkit.h; path = /Users/olaf/Projekte/toolkit/ui/ui/toolkit.h; sourceTree = ""; }; ED6581582CFF3CA000F5402F /* ui.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ui.h; path = ../../../ui/ui/ui.h; sourceTree = ""; }; ED6581592CFF3CA000F5402F /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = window.h; path = ../../../ui/ui/window.h; sourceTree = ""; }; ED65815A2CFF3EE900F5402F /* MainWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainWindow.h; path = ../../../ui/cocoa/MainWindow.h; sourceTree = ""; }; @@ -356,6 +356,7 @@ EDBC4D262EAD4BB0005CDF38 /* webview.m */, ED895DA82EA0CACC00040078 /* TabView.h */, ED895DA92EA0CACC00040078 /* TabView.m */, + ED6581562CFF3CA000F5402F /* toolkit.h */, ED83C2BD2E8EA49200054B22 /* BoxContainer.h */, ED83C2BE2E8EA49200054B22 /* BoxContainer.m */, ED18C9212E76CA5500B64EA5 /* entry.h */, @@ -421,7 +422,6 @@ ED6581522CFF3CA000F5402F /* range.h */, ED6581542CFF3CA000F5402F /* text.h */, ED6581552CFF3CA000F5402F /* toolbar.h */, - ED6581562CFF3CA000F5402F /* toolkit.h */, ED6581582CFF3CA000F5402F /* ui.h */, ED6581592CFF3CA000F5402F /* window.h */, ); diff -r ce0e443174d7 -r 8b8da1adef7d make/xcode/toolkit/toolkit/main.m --- a/make/xcode/toolkit/toolkit/main.m Sat Jun 06 16:53:39 2026 +0200 +++ b/make/xcode/toolkit/toolkit/main.m Sat Jun 06 18:04:54 2026 +0200 @@ -162,12 +162,35 @@ ui_list_update(doc->srclist); } +static void action_window_close(UiEvent *event, void *data) { + ui_close(event->obj); +} + +static void action_window_ref(UiEvent *event, void *data) { + ui_object_ref(data); +} + +static void action_window_unref(UiEvent *event, void *data) { + ui_object_unref(data); +} + +static void action_objref_window(UiEvent *event, void *data) { + UiObject *obj = ui_simple_window("Ref Window"); + ui_vbox(obj, .spacing = 10, .margin = 10, .fill = TRUE) { + ui_button(obj, .label = "Ref", .onclick = action_window_ref, .onclickdata = data); + ui_button(obj, .label = "Unref", .onclick = action_window_unref, .onclickdata = data); + } + ui_show(obj); + +} + static void next_tab(UiEvent *event, void *data) { ui_var_set_int(event->obj->ctx, "tabview", 1); } void application_startup(UiEvent *event, void *data) { UiObject *obj = ui_splitview_window("My Window", TRUE); + //WindowData *wdata = ui_malloc(obj->ctx, sizeof(WindowData)); //wdata->tbtoggle = ui_int_new(obj->ctx, "tbtoggle"); //obj->window = wdata; @@ -196,7 +219,9 @@ ui_left_panel0(obj) { ui_grid(obj, .margin_left = 10, .margin_right = 10, .columnspacing = 10, .rowspacing = 10, .fill = TRUE) { - ui_button(obj, .label = "left", .hexpand = TRUE, .hfill = TRUE); + ui_button(obj, .label = "Close Window", .hexpand = TRUE, .hfill = TRUE, .onclick = action_window_close); + ui_newline(obj); + ui_button(obj, .label = "Ref/Unref Window", .onclick = action_objref_window, .onclickdata = obj, .hexpand = TRUE, .hfill = TRUE); ui_newline(obj); ui_linkbutton(obj, .varname = "link", .hexpand = TRUE, .hfill = TRUE); ui_newline(obj); diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/MainWindow.h --- a/ui/cocoa/MainWindow.h Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/MainWindow.h Sat Jun 06 18:04:54 2026 +0200 @@ -29,7 +29,7 @@ #import "toolkit.h" #import "../ui/window.h" -@interface MainWindow : NSWindow +@interface MainWindow : NSWindow @property UiObject *obj; @property (strong) NSSplitView *splitview; diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/MainWindow.m --- a/ui/cocoa/MainWindow.m Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/MainWindow.m Sat Jun 06 18:04:54 2026 +0200 @@ -27,6 +27,7 @@ */ #import "MainWindow.h" +#import "WindowManager.h" #import "container.h" #import "GridLayout.h" #import "BoxContainer.h" @@ -38,6 +39,8 @@ #import "menu.h" #import "Toolbar.h" + + @implementation MainWindow - (MainWindow*)init:(UiObject*)obj withSidebar:(BOOL)hasSidebar withSplitview:(BOOL)hasSplitview{ @@ -51,7 +54,7 @@ backing:NSBackingStoreBuffered defer:false]; _obj = obj; - + self.delegate = self; int top = 4; NSView *content = self.contentView; @@ -137,7 +140,6 @@ [self setToolbar:toolbar]; } - return self; } @@ -153,7 +155,37 @@ } } +- (void) windowWillClose:(NSNotification *) notification { + UiObject *obj = _obj; + + if(obj->onclose) { + UiEvent event; + memset(&event, 0, sizeof(UiEvent)); + event.obj = obj; + event.window = obj->window; + event.document = obj->ctx->document; + obj->onclose(&event, obj->onclosedata); + } + + if(obj->ref > 0) { + obj->ref--; + } else { + // warn about invalid reference counting + NSLog(@"Error: UiObject %p ref == 0\n", obj); + } + + if(obj->ref == 0) { + // this cleans up any widget references from the context + uic_context_prepare_close(obj->ctx); + + [[WindowManager sharedWindowManager] closeWindow:self]; + } +} +- (void) dealloc { + uic_object_destroy(_obj); + NSLog(@"MainWindow dealloc"); +} @end diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/Toolbar.h --- a/ui/cocoa/Toolbar.h Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/Toolbar.h Sat Jun 06 18:04:54 2026 +0200 @@ -50,7 +50,7 @@ NSMutableArray *defaultItems; } -@property MainWindow *window; +@property (weak) MainWindow *window; @property UiObject *obj; - (UiToolbar*) initWithWindow:(MainWindow*)window; diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/WindowManager.h --- a/ui/cocoa/WindowManager.h Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/WindowManager.h Sat Jun 06 18:04:54 2026 +0200 @@ -28,14 +28,16 @@ #import "toolkit.h" -@interface WindowManager : NSObject +@interface WindowManager : NSObject -@property NSMutableArray *windows; +@property NSMutableArray *windows; + (WindowManager*) sharedWindowManager; - (WindowManager*)init; -- (void)addWindow:(NSWindow*)win; +- (void)addWindow:(NSWindowController*)win; + +- (void)closeWindow:(NSWindow*)win; @end diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/WindowManager.m --- a/ui/cocoa/WindowManager.m Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/WindowManager.m Sat Jun 06 18:04:54 2026 +0200 @@ -44,14 +44,12 @@ return self; } -- (void)addWindow:(NSWindow*)win { +- (void)addWindow:(NSWindowController*)win { [_windows addObject:win]; - [win setDelegate:self]; } -- (void) windowWillClose:(NSNotification *) notification { - NSWindow *window = notification.object; - [_windows removeObject:window]; +- (void)closeWindow:(NSWindow*)win { + [_windows removeObject:win.windowController]; } @end diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/toolkit.m --- a/ui/cocoa/toolkit.m Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/toolkit.m Sat Jun 06 18:04:54 2026 +0200 @@ -147,7 +147,7 @@ void ui_main(void) { main_thr_check("ui_main"); - NSApplicationMain(app_argc, app_argv); + NSApplicationMain(app_argc,app_argv); //[NSApp finishLaunching]; //[NSApp activateIgnoringOtherApps:YES]; //[NSApp run]; diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/webview.m --- a/ui/cocoa/webview.m Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/webview.m Sat Jun 06 18:04:54 2026 +0200 @@ -52,7 +52,7 @@ data->webview = (__bridge void*)webview; data->javascript = TRUE; data->zoom = 1; - value->value = value; + value->value = data; } } diff -r ce0e443174d7 -r 8b8da1adef7d ui/cocoa/window.m --- a/ui/cocoa/window.m Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/cocoa/window.m Sat Jun 06 18:04:54 2026 +0200 @@ -50,19 +50,23 @@ static int splitview_window_default_pos = -1; static UiBool splitview_window_use_prop = TRUE; +static void main_window_destroy(UiObject *obj) { + MainWindow *window = (__bridge MainWindow*)obj->wobj; + [[WindowManager sharedWindowManager] closeWindow:window]; +} + static UiObject* create_window(const char *title, BOOL simple, BOOL sidebar, BOOL splitview) { UiObject *obj = uic_object_new_toplevel(); MainWindow *window = [[MainWindow alloc] init:obj withSidebar:sidebar withSplitview:splitview]; - [[WindowManager sharedWindowManager] addWindow:window]; - window.releasedWhenClosed = false; // TODO: we still need a cleanup strategy obj->wobj = (__bridge void*)window; + obj->destroy = main_window_destroy; MainWindowController *controller = [[MainWindowController alloc] initWithWindow:obj window:window]; window.windowController = controller; [window setNextResponder:(NSResponder*)controller]; - objc_setAssociatedObject(window, "windowcontroller", controller, OBJC_ASSOCIATION_RETAIN); + [[WindowManager sharedWindowManager] addWindow:controller]; return obj; } diff -r ce0e443174d7 -r 8b8da1adef7d ui/common/types.c --- a/ui/common/types.c Sat Jun 06 16:53:39 2026 +0200 +++ b/ui/common/types.c Sat Jun 06 18:04:54 2026 +0200 @@ -760,6 +760,9 @@ void uic_generic_save(UiGeneric *g) { if(!g->obj) return; + // TODO: this leaks memory + // we can't just use get on Generic and ignore the result + // probably a separate save method is required g->get(g); }