My app uses macOSlib to take care of the various windows menus: minimize etc.
It happens that a window containing a movieplayer, when such windows is called, clicking in Menubar-Windows, at the bottom of the menuitems, after the title of the last window called, an empty menuitem gets added.
Now, closing that window and clicking again in the menubar-windows the app crashes.
The misbehavior can be easily replicated in macOSlibrary: add a Movieplayer in any window of the Examples, and after running the app select (open) the modified window, click in the menubar.windows, close the window, click again the menubar-windows and the app crashes generating a long crash report.
Suggestions how to avoid the crash while keeping the windows functionatily of macOSlib?
Thanks.
This may not be the best fix, just digging into this part of MacOSLib now.
Every time the Window Menu is displayed MenuItemWindowMenu.AddNewWindowItems is called. It receives array windowList of items to put in the menu, but in the loop where this is actually done…
for each w as Ptr in windowList
items get filtered out for various reasons…
if not (d.HasKey(w) OR isExcludedFromWindowsMenu(w) OR Cocoa.InheritsFromClass( w, "NSPanel" ) OR Cocoa.InheritsFromClass( w, "NSTextViewCompletionWindow" ) OR viewsNeedDisplay(w)) then
It appears somehow a MoviePlayer is adding an NSWindow to windowList and this passes the filtering so it gets added to the menu as a blank item. Then after the MoviePlayer is closed I think this blank item still holds a reference to something now nil so there’s a crash.
I haven’t been able to pin down exactly where it crashes but by filtering out this NSWindow so you don’t have the blank menu item it seems to work ok.
Add these to the declare section…
declare function object_getClass lib "Cocoa" (obj As Ptr) As Ptr
declare function NSStringFromClass lib "Cocoa" (aClass As Ptr) As CFStringRef
then add this after the “if not (d.HasKey(w) OR” line to filter the blank item…
if NSStringFromClass(object_getClass(w)) = "NSWindow" then continue for w
(or you could add it into the filtering line)
Again, maybe there’s a better way and I don’t know how/where this NSWindow comes from the MoviePlayer.
I added the relevant snippets and there is no more crash. The name of the window too is no more added, but this is really a minor annoyance compared to the crash.
Thank you very much, Will.
Thanks Carlo, glad it helped.
Now peeking into where this NSWindow comes from reveals a leak of XOJWindows.
I tried last week to discover what Xojo uses for MoviePlayer: AVPlayer, QTMovieView, or…? Movie.Handle is always nil and MoviePlayer.Handle is a XOJMovieView which is just a subclass of NSView. So I made a Listbox that displays the entire view hierarchy and this still doesn’t reveal what’s used.
Anyways, I modified the Listbox to start with all windows returned from NSApplication.sharedApplication.windows and this reveals that for every MoviePlayer there’s an extra NSWindow created for it’s volume control…
NSWindow (NSResponder, NSObject)
|--XOJVolumeContentView (NSView, NSResponder, NSObject)
|--XOJVolumeSlider (NSSlider, NSControl, NSView, NSResponder, NSObject)
|--NSButton (NSControl, NSView, NSResponder, NSObject)
And this is the hierarchy of a Window with a MoviePlayer on it (no OS player here either)…
XOJWindow (NSWindow, )
|--XOJContentView (NSView, )
|--XOJMovieView (NSView, ) <--MoviePlayer.Handle returns this
|--NSView <--guessing the OS player is hidden in here
|--XOJMovieControlsBackgroundView (NSView, )
|--NSButton
|--XOJMovieScrubber (NSSlider, )
|--NSButton
|--NSButton
|--NSButton
Close the Xojo Window and the associated volume-NSWindow goes away but the now closed XOJWindow continues to be listed in sharedApplication.windows. This is the leak, whether it’s implicit instance or not, every time you close a Window it hangs around in that windows list with only a XOJContentView (otherwise empty).
related to the leak…
<https://xojo.com/issue/34956>
https://forum.xojo.com/18061-cocoa-memory-leaks/0
https://forum.xojo.com/15159-window-memory-leak-and-if-on-mac-os-x-only/0
So that clarifies what this extra window is and maybe the MacOSLib authors can account for it.
Wish the Movie or MoviePlayer Handle still went to something so we could declare against them.
This may or may not actually help, I’m not using the MacOSLib (but as it’s chock full of declares I follow the conversations). When using declares in my own code to create a Windows menu, I don’t get an extra menu item when a window has a movie player on it.
Below is the code I use to get the system to maintain a windows menu for me. I still have to maintain the various minimize and such, but the actual window listing is handled by OS X.
[code]Sub setAsWindowMenu(Extends m as menuItem)
#if TargetCocoa then
m.Name = “WindowMenu”
m.Text = kWindowMenuCaption
Dim maximizeItem as new MenuItem( kMinimizeMenuCaption )
maximizeItem.Name = "WindowMinimize"
maximizeItem.KeyboardShortcut = "M"
maximizeItem.AutoEnable = false
AddHandler maximizeItem.action, addressOF handleWindowMinimize
managedMenuItems.append maximizeItem
m.append maxiMizeItem
Dim zoomItem as new MenuItem( kZoomMenuItemCaption )
zoomItem.Name = "WindowZoom"
zoomItem.AutoEnable = false
AddHandler zoomItem.action, addressOF handleWindowZoom
managedMenuItems.append zoomItem
m.append zoomItem
m.Append new MenuItem( "-" )
m.Append new MenuItem( kBringAllToFrontMenuCaption )
m.Item( 3 ).Name = "WindowBringAllToFront"
AddHandler m.item( 3 ).action, addressOf handleWindowBringAllToFront
m.Append new MenuItem( "-" )
m.append new MenuItem( "-" )
declare function getSubMenu lib AppKit selector "submenu" ( NSMenuItemRef as integer ) as Ptr
Dim subMenuRef as Ptr = getSubMenu( m.handle( menuitem.handleType.CocoaNSMenuItem ) )
declare sub setMySubMenuAsWindowsMenu lib AppKit selector "setWindowsMenu:" ( appRef as Ptr, inNSMenu as Ptr )
setMySubMenuAsWindowsMenu( sharedApplication, subMenuRef )
#endif
End Sub
[/code]
I usually lift code out of macoslib if I need to use it rather than drop the whole thing into a project
Can’t say I’ve run into the extra blank menu business doing this
That happens only when using the MenuItemWindowMenu in the Cocoa Menuitems > Window Menu (Additional Modules)
Correction, the leak I mentioned was something odd with my computer. I’ve had to reboot for unrelated reasons and now closed Windows don’t hang around in sharedApplication.windows anymore. (And XOJMovieControlsBackgroundView has only 2 NSButtons)
Also, thanks Sam for your code
It’s incomplete as it requires a bunch of other things in my own AppKit, but the key functions are there and hopefully they’ll help to narrow down the issue.
Which as you found out was something weird on your Mac. As Yosemite fixes have been released, I do have to restart less and less.