Cocoa: memory leak fixes by David Jenkins, issue #40116

This commit is contained in:
Maxim Ganetsky 2023-02-27 23:44:23 +03:00
parent 1b9d3d4cbf
commit 01d60e2dfd
15 changed files with 100 additions and 37 deletions

View File

@ -67,6 +67,7 @@ type
fvscroll : NSScroller;
public
callback: ICommonCallback;
procedure dealloc; override;
function lclGetCallback: ICommonCallback; override;
procedure lclClearCallback; override;
function lclContentView: NSView; override;
@ -328,6 +329,13 @@ end;
{ TCocoaManualScrollView }
procedure TCocoaManualScrollView.dealloc;
begin
if Assigned(fhscroll) then fhscroll.release;
if Assigned(fvscroll) then fvscroll.release;
inherited dealloc;
end;
function TCocoaManualScrollView.lclGetCallback: ICommonCallback;
begin
Result := callback;

View File

@ -64,6 +64,7 @@ type
lclEnabled: Boolean;
// cocoa
class function alloc: id; override;
procedure dealloc; override;
procedure setFrame(aframe: NSRect); override;
// lcl
function lclIsEnabled: Boolean; override;
@ -421,6 +422,15 @@ begin
TCocoaTabControl(Result).fulltabs := NSMutableArray(NSMutableArray.alloc).init;
end;
procedure TCocoaTabControl.dealloc;
begin
if Assigned(fulltabs) then begin
fulltabs.release;
fulltabs := nil;
end;
inherited dealloc;
end;
procedure TCocoaTabControl.setFrame(aframe: NSRect);
begin
inherited setFrame(aframe);

View File

@ -501,6 +501,7 @@ end;
procedure TCocoaTableListView.dealloc;
begin
//if Assigned(Items) then FreeAndNil(Items);
if Assigned(beforeSel) then beforeSel.release;
if Assigned(smallimages) then smallimages.release; // all contents is released automatically
inherited dealloc;
end;
@ -790,8 +791,8 @@ var
dstl : NSUInteger;
data : TCompareData;
begin
rm := NSMutableIndexSet.alloc.init;
ad := NSMutableIndexSet.alloc.init;
rm := NSMutableIndexSet.alloc.init.autorelease;
ad := NSMutableIndexSet.alloc.init.autorelease;
removed := rm;
added := ad;

View File

@ -517,6 +517,7 @@ begin
menuItem.addTrackingArea(track);
track.release;
mn.setView(menuItem);
menuItem.release;
end;
end;

View File

@ -557,6 +557,7 @@ begin
NSNotificationCenter(NSNotificationCenter.defaultCenter).removeObserver(callback);
callback.release;
if (HdrCell<>nil) then hdrCell.Release;
if (BtnCell<>nil) then BtnCell.Release;
inherited Destroy;
end;

View File

@ -1196,6 +1196,7 @@ begin
cmp.setMinute(m);
cmp.setSecond(s);
Result := NSCalendar.currentCalendar.dateFromComponents(cmp);
cmp.release;
end;
function NSDateToDateTime(const aDateTime: NSDate): TDateTime;

View File

@ -518,6 +518,7 @@ end;
procedure TCocoaWindowContent.dealloc;
begin
if Assigned(_stringValue) then _stringValue.release;
inherited dealloc;
end;

View File

@ -223,7 +223,7 @@ begin
list.callback := TLCLCheckboxListCallback.CreateWithView(list, AWinControl);
list.lclSetFirstColumCheckboxes(true);
//list.list := TCocoaStringList.Create(list);
list.addTableColumn(NSTableColumn.alloc.init);
list.addTableColumn(NSTableColumn.alloc.init.autorelease);
list.setHeaderView(nil);
list.setDataSource(list);
list.setDelegate(list);
@ -235,7 +235,6 @@ begin
scroll := EmbedInScrollView(list);
if not Assigned(scroll) then
begin
list.dealloc;
Result := 0;
Exit;
end;

View File

@ -352,6 +352,7 @@ begin
lNSText := NSStringUtf8(lText);
pasteboard.setString_forType(lNSText, lCurFormat.CocoaFormat);
lNsText.release;
end;
ccdtCocoaStandard, ccdtNonStandard:
begin

View File

@ -1013,7 +1013,7 @@ begin
lTableLV := AllocCocoaTableListView.initWithFrame(ns);
if lTableLV = nil then
begin
lCocoaLV.dealloc;
lCocoaLV.release;
Result := 0;
exit;
end;
@ -1042,6 +1042,7 @@ begin
// Windows compatibility. on Windows there's no extra space between columns
sz.width := 0;
lTableLV.setIntercellSpacing(sz);;
lTableLV.release;
{$IFDEF COCOA_DEBUG_LISTVIEW}
WriteLn(Format('[TCocoaWSCustomListView.CreateHandle] headerView=%d', [PtrInt(lTableLV.headerView)]));
{$ENDIF}
@ -1117,6 +1118,7 @@ begin
lNSColumn.headerCell.setStringValue(lTitle);
lNSColumn.setResizingMask(NSTableColumnUserResizingMask);
lTableLV.addTableColumn(lNSColumn);
lNSColumn.release;
lTitle.release;
end;
@ -1643,7 +1645,7 @@ begin
lvpShowColumnHeaders:
if (AIsSet <> Assigned(lTableLV.headerView)) then
begin
if AIsSet then lTableLv.setHeaderView ( NSTableHeaderView.alloc.init )
if AIsSet then lTableLv.setHeaderView ( NSTableHeaderView.alloc.init.autorelease )
else lTableLv.setHeaderView(nil);
end;
{ lvpShowWorkAreas,
@ -1898,6 +1900,8 @@ begin
img := NSImage(NSImage.alloc).initWithSize( rep.size );
img.addRepresentation(rep);
Result := img;
rep.release;
finally
bmp.Free;
end;

View File

@ -72,6 +72,7 @@ begin
c := NSCalendar.alloc.initWithCalendarIdentifier(NSString.string_);
Result.setCalendar(c);
c.release;
TCocoaDatePicker(Result).callback:= TLCLCommonCallback.Create(Result, ATarget);

View File

@ -143,6 +143,8 @@ type
Filters: TStringList; // filled by updateFilterList()
NSFilters: NSMutableArray;
lastSelectedItemIndex: Integer; // -1 means invalid or none selected
class function alloc: id; override;
procedure dealloc; override;
procedure updateFilterList(); message 'updateFilterList';
function setDialogFilter(ASelectedFilterIndex: Integer): Integer; message 'setDialogFilter:';
procedure comboboxAction(sender: id); message 'comboboxAction:';
@ -565,7 +567,7 @@ begin
accessoryView.addSubview(okButton.autorelease);
accessoryView.addSubview(cancelButton.autorelease);
colorPanel.setDelegate(colorDelegate);
colorPanel.setDelegate(colorDelegate.autorelease);
colorPanel.setAccessoryView(accessoryView.autorelease);
colorPanel.setShowsAlpha(False);
colorPanel.setDefaultButtonCell(okButton.cell);
@ -740,7 +742,7 @@ begin
accessoryView.addSubview(okButton.autorelease);
accessoryView.addSubview(cancelButton.autorelease);
fontPanel.setDelegate(FontDelegate);
fontPanel.setDelegate(FontDelegate.autorelease);
fontPanel.setAccessoryView(accessoryView.autorelease);
fontPanel.setDefaultButtonCell(okButton.cell);
@ -891,6 +893,18 @@ end;
{ TCocoaFilterComboBox }
class function TCocoaFilterComboBox.alloc: id;
begin
Result := inherited alloc;
TCocoaFilterComboBox(Result).NSFilters := NSMutableArray.alloc.init;
end;
procedure TCocoaFilterComboBox.dealloc;
begin
NSFilters.release;
inherited dealloc;
end;
class procedure TCocoaFilterComboBox.DoParseFilters(AFileDialog: TFileDialog; AOutput: TStringList);
var
lFilterParser, lExtParser: TParseStringList;
@ -1032,6 +1046,7 @@ var
uti : CFStringRef;
ext : string;
j : integer;
UTIFilters: NSMutableArray;
begin
if (Filters = nil) or (Filters.Count=0) then
begin
@ -1044,14 +1059,14 @@ begin
ASelectedFilterIndex := 0;
Result := ASelectedFilterIndex;
lCurFilter := TStringList(Filters.Objects[ASelectedFilterIndex]);
NSFilters := NSMutableArray.alloc.init;
UTIFilters := NSMutableArray.alloc.init;
for i:=0 to lCurFilter.Count-1 do
begin
ext := lCurFilter[i];
if (ext='') then Continue;
if (ext='*.*') or (ext = '*') then begin
//uti:=CFSTR('public.content');
NSFilters.removeAllObjects;
UTIFilters.removeAllObjects;
break;
end else begin
// using the last part of the extension, as Cocoa doesn't suppot
@ -1066,28 +1081,21 @@ begin
CFStringRef(NSString.stringWithUTF8String(PChar(ext))), CFSTR('public.data'));
end;
if Assigned(uti) then
NSFilters.addObject(id(uti));
UTIFilters.addObject(id(uti));
end;
if (NSFilters.count = 0) then
if (UTIFilters.count = 0) then
begin
// select any file
NSFilters.addObject(id(CFSTR('public.content')));
NSFilters.addObject(id(CFSTR('public.data')));
UTIFilters.addObject(id(CFSTR('public.content')));
UTIFilters.addObject(id(CFSTR('public.data')));
end;
DialogHandle.setAllowedFileTypes(NSFilters);
NSFilters.autorelease;
DialogHandle.setAllowedFileTypes(UTIFilters);
UTIFilters.release;
exit;
end;
if NSFilters = nil then
begin
NSFilters := NSMutableArray.alloc.init;
end
else
begin
NSFilters.removeAllObjects();
end;
NSFilters.removeAllObjects();
if (Filters.Count > 0) and (ASelectedFilterIndex >= 0) and
(ASelectedFilterIndex < Filters.Count) then

View File

@ -307,6 +307,7 @@ begin
TCocoaPanel(win).callback := cb;
win.setContentView(cnt);
doc.release;
Result := TLCLIntfHandle(cnt);
end;
@ -832,7 +833,9 @@ begin
cnt.addSubview_positioned_relativeTo(ds, NSWindowAbove, nil);
doc.overlay := ds;
ds.release;
end;
doc.release;
Result := TLCLIntfHandle(cnt);
end;

View File

@ -65,6 +65,7 @@ type
attachedAppleMenu: Boolean;
isKeyEq: Boolean;
public
procedure dealloc; override;
procedure lclItemSelected(sender: id); message 'lclItemSelected:';
procedure createAppleMenu(); message 'createAppleMenu';
procedure overrideAppleMenu(AItem: TCocoaMenuItem); message 'overrideAppleMenu:';
@ -299,6 +300,17 @@ end;
{ TCocoaMenu }
procedure TCocoaMenu.dealloc;
begin
if appleMenu <> nil then begin
if indexOfItem(appleMenu) >= 0 then
removeItem(appleMenu);
appleMenu.release;
appleMenu := nil;
end;
inherited dealloc;
end;
procedure TCocoaMenu.lclItemSelected(sender:id);
begin
@ -319,6 +331,7 @@ begin
// add the submenu
lNSSubmenu := NSMenu.alloc.initWithTitle(NSString.string_);
appleMenu.setSubmenu(lNSSubmenu);
lNSSubmenu.release;
appleMenu.attachAppleMenuItems();
end;
@ -419,6 +432,7 @@ end;
procedure TCocoaMenuItem.attachAppleMenuItems();
var
item : NSMenuItem;
itemSubMenu: NSMenu;
begin
if attachedAppleMenuItems then Exit;
if not hasSubmenu() then Exit;
@ -431,8 +445,11 @@ begin
item.setTarget(nil);
item.setAction(nil);
submenu.insertItem_atIndex(item, submenu.itemArray.count);
item.setSubmenu(NSMenu.alloc.initWithTitle( ControlTitleToNSStr(rsMacOSMenuServices)));
itemSubMenu := NSMenu.alloc.initWithTitle( ControlTitleToNSStr(rsMacOSMenuServices));
item.setSubmenu(itemSubMenu);
itemSubMenu.release;
NSApplication(NSApp).setServicesMenu(item.submenu);
item.release;
// Separator
submenu.insertItem_atIndex(NSMenuItem.separatorItem, submenu.itemArray.count);
@ -440,14 +457,17 @@ begin
// Hide App Meta-H
item := LCLMenuItemInit( TCocoaMenuItem_HideApp.alloc, Format(rsMacOSMenuHide, [Application.Title]), VK_H, [ssMeta]);
submenu.insertItem_atIndex(item, submenu.itemArray.count);
item.release;
// Hide Others Meta-Alt-H
item := LCLMenuItemInit( TCocoaMenuItem_HideOthers.alloc, rsMacOSMenuHideOthers, VK_H, [ssMeta, ssAlt]);
submenu.insertItem_atIndex(item, submenu.itemArray.count);
item.release;
// Show All
item := LCLMenuItemInit( TCocoaMenuItem_ShowAllApp.alloc, rsMacOSMenuShowAll);
submenu.insertItem_atIndex(item, submenu.itemArray.count);
item.release;
// Separator
submenu.insertItem_atIndex(NSMenuItem.separatorItem, submenu.itemArray.count);
@ -455,6 +475,7 @@ begin
// Quit Meta-Q
item := LCLMenuItemInit( TCocoaMenuItem_Quit.alloc, Format(rsMacOSMenuQuit, [Application.Title]), VK_Q, [ssMeta]);
submenu.insertItem_atIndex(item, submenu.itemArray.count);
item.release;
attachedAppleMenuItems := True;
end;
@ -627,6 +648,7 @@ begin
Parent := AllocCocoaMenu(AMenuItem.Parent.Caption);
Parent.setDelegate(TCocoaMenuItem(ParObj));
NSMenuItem(ParObj).setSubmenu(Parent);
Parent.release;
// no longer respond to clicks. LCL might still need to get an event
// yet the menu should not close
@ -639,23 +661,22 @@ begin
else
Exit;
item := nil;
idx := AMenuItem.MenuVisibleIndex;
if idx < 0 then idx := Parent.numberOfItems;
MenuObj := NSObject(AMenuItem.Handle);
if MenuObj.isKindOfClass(NSMenuItem) then
item := NSMenuItem(MenuObj)
if MenuObj.isKindOfClass(NSMenuItem) then begin
item := NSMenuItem(MenuObj);
Parent.insertItem_atIndex(NSMenuItem(item), idx)
end
else if MenuObj.isKindOfClass(NSMenu) then
begin
Menu := NSMenu(MenuObj);
item := NSMenuItem(NSMenuItem.alloc).initWithTitle_action_keyEquivalent(
ControlTitleToNSStr(AMenuItem.Caption), nil, NSString.string_ );
item.setSubmenu( Menu );
end;
if Assigned(item) then
begin
idx := AMenuItem.MenuVisibleIndex;
if idx < 0 then idx := Parent.numberOfItems;
Parent.insertItem_atIndex(NSMenuItem(item), idx)
Parent.insertItem_atIndex(NSMenuItem(item), idx);
item.release;
end;
end;
@ -702,6 +723,7 @@ begin
ANSMenu := AllocCocoaMenu(AMenuItem.Caption);
ANSMenu.setDelegate(TCocoaMenuItem(item));
item.setSubmenu(ANSMenu);
ANSMenu.release;
end;
TCocoaMenuItem(item).menuItemCallback:=TLCLMenuItemCallback.Create(item, AMenuItem);
@ -762,6 +784,8 @@ begin
if nsitem.isSeparatorItem and Assigned(nsitem.menu) then
nsitem.menu.removeItem(nsitem);
// separator items are not "alloced", thus should not be released
end else if item.isKindOfClass_(TCocoaMenu) then begin
item.release;
end;
end;

View File

@ -1565,6 +1565,7 @@ begin
TextViewSetAllignment(txt, TCustomMemo(AWinControl).Alignment);
txt.wantReturns := TCustomMemo(AWinControl).WantReturns;
txt.callback.SetTabSuppress(not TCustomMemo(AWinControl).WantTabs);
txt.release;
Result := TLCLIntfHandle(scr);
end;
@ -2224,7 +2225,7 @@ begin
end;
cb := TLCLListBoxCallback.CreateWithView(list, AWinControl);
list.callback := cb;
list.addTableColumn(NSTableColumn.alloc.init);
list.addTableColumn(NSTableColumn.alloc.init.autorelease);
list.setHeaderView(nil);
list.setDataSource(list);
list.setDelegate(list);
@ -2244,7 +2245,6 @@ begin
scroll := EmbedInScrollView(list);
if not Assigned(scroll) then
begin
list.dealloc;
Result := 0;
Exit;
end;