ofSystemLoadDialog and ofSystemSaveDialog hangs draw (SOLVED!)

#1

After I updated to XCode 5.1, ofSystemLoadDialog and ofSystemSaveDialogs hangs the update of the drawing, the function draw() gets called, but nothing on screen gets updated. Somebody else has the same problem, any idea of a solution? I am building a level editor, so I really need to use the Load/Save dialogs.

K.

#2

For those who have the same problem, here is to solution, the problem is that NSOpenPanel is changing the current GL context, so you need to save your current context before opening the panel and then making it current again.

Here is a modified ofSystemLoadDialog function:

@autoreleasepool {
	NSOpenGLContext *foo = [NSOpenGLContext currentContext];
	NSOpenPanel * loadDialog = [NSOpenPanel openPanel];
	[loadDialog setAllowsMultipleSelection:NO];
	[loadDialog setCanChooseDirectories:bFolderSelection];
	[loadDialog setResolvesAliases:YES];
	
	if(!windowTitle.empty()) {
		[loadDialog setTitle:[NSString stringWithUTF8String:windowTitle.c_str()]];
	}
	
	if(!defaultPath.empty()) {
		NSString * s = [NSString stringWithUTF8String:defaultPath.c_str()];
		s = [[s stringByExpandingTildeInPath] stringByResolvingSymlinksInPath];
		NSURL * defaultPathUrl = [NSURL fileURLWithPath:s];
		[loadDialog setDirectoryURL:defaultPathUrl];
	}
	
	NSInteger buttonClicked = [loadDialog runModal];
	restoreAppWindowFocus();
	[foo makeCurrentContext];
	if(buttonClicked == NSFileHandlingPanelOKButton) {
		NSURL * selectedFileURL = [[loadDialog URLs] objectAtIndex:0];
		results.filePath = string([[selectedFileURL path] UTF8String]);
	}
}
#3

thanks @kamend
fixed this with: https://github.com/openframeworks/openFrameworks/commit/60240487682c1bca058bbbf559d67457bec14f86

#4

hi !

I found the same problem with OF 0.84 in XCode 5.1 and OSX 10.9.1 … even it’s a post from so many months ago …

I dowloaded the OF 084 from the website … and when running the fileOpenSaveDialogExample i got
draw being freezed. With the original 084 ofSystemUtils.cpp it does freeze already on the “load dialog” …

I tried @theo commit code and so the ofSystemLoadDialog works ok now … so the app draws back the image selected on the dialog as it shoudl be.
But after ofSystemSaveDialog is called … draw() doens’t work on screen… so i guess openGL context is lost ¿? If i resize the window GL glitch appears on screen … although the app keeps running.

Has anybody experienced something like this ? Is the ofSystemSaveDialog ?¿ running ok for you with OF 084 ?

Thanks for any tip … totally lost ?¿ as far as i see … the GL context thing is done also on the save dialog … so lost .

EDIT : created an issue … not sure if i should do so or not … ?¿ https://github.com/openframeworks/openFrameworks/issues/3348

this is what i see if resizing …

#5

Well … just trying to solve it and i think i solve it … just looking at the loadDialog function and trying to compare with the saveDialog …

The only change was in

oFileDialogResult ofSystemSaveDialog(string defaultName, string messageName){
#ifdef TARGET_OSX

and just put the GLcontext operation at the beginning … so changing from :

  NSSavePanel * saveDialog = [NSSavePanel savePanel];
  NSOpenGLContext *context = [NSOpenGLContext currentContext];

to

  NSOpenGLContext *context = [NSOpenGLContext currentContext];
  NSSavePanel * saveDialog = [NSSavePanel savePanel];

and now it works :wink:

#6

In my case the proposed solution does not work. The funny thing is that ofSystemSaveDialog works as normal and resumes drawing, while ofSystemLoadDialog freezes and window is not refreshed.

I’m using OS X 10.10.1 with OF 0.8.4.

edit: Now I can confirm that it works without a problem on OS X 10.9.
edit2: It works on macbook pro 15" late 2013 with Nvidia graphics but not on mine Macbook pro 13" late 2013 with Intel Iris (used the same bin)

Any new ideas?

Issue was created on git (https://github.com/openframeworks/openFrameworks/issues/3456)

Tnx.

#7

I didn’t solve the issue but instead wrote my own file loader with applescript. If somebody has the same issue can use this function. It works for file selection only, but could be easily modified to work with folder selection or different default path. Hope it helps.

ofFileDialogResult selectFileDialog()
{
    ofFileDialogResult result;

    @autoreleasepool
    {
        NSOpenGLContext *context = [NSOpenGLContext currentContext];
        NSDictionary *error = nil;

        NSAppleScript* openFile = [[NSAppleScript alloc] initWithSource:
                                   @"tell app \"SystemUIServer\"\n"
                                   @"    choose file default location \"/\" \n"
                                   @"    set result to (the POSIX path of result)\n"
                                   @"end tell"];

        NSString *absoluteFilePath = [[openFile executeAndReturnError: &error] stringValue];

        if(absoluteFilePath != NULL)
        {
            result.filePath = *new std::string([absoluteFilePath UTF8String]);
            NSLog(@"User selected %@\n",absoluteFilePath);
        }
        else
        {
            NSLog(@"User hit cancel\n");
            result.bSuccess = false;
        }

        //restore app window focus
        NSWindow * appWindow = (NSWindow *)ofGetCocoaWindow();
        if(appWindow) {
            [appWindow makeKeyAndOrderFront:nil];
        }

        [context makeCurrentContext];
    }

    if( result.filePath.length() > 0 )
    {
        result.bSuccess = true;
        result.fileName = ofFilePath::getFileName(result.filePath);
    }
    return result;
}
2 Likes
#8

@grega_pusnik

i just had the same issue with of0.9.3 on osx 10.10 and also didn’t find a way to fix it without apple script.
based on yours, here is a more complete solution:

ofxSystemUtils.h

#ifndef __ofxSystemUtils__
#define __ofxSystemUtils__

// ofxSystemUtils:
// util to get around the opengl issues with load/save panels in osx 10.10
// (platforms other than osx are unaffected)
// v1.1: added support for default name, remembers last used folder
// v1.0: initial version

#include "ofMain.h"

ofFileDialogResult ofxSystemSaveDialog(string defaultName = "", string windowMessage = "");
ofFileDialogResult ofxSystemLoadDialog( string windowMessage = "");

#endif

ofxSystemUtils.cp:

#include "ofxSystemUtils.h"

#ifdef TARGET_OSX
// ofSystemUtils.cpp is configured to build as
// objective-c++ so as able to use Cocoa dialog panels
// This is done with this compiler flag
//        -x objective-c++
// http://www.yakyak.org/viewtopic.php?p=1475838&sid=1e9dcb5c9fd652a6695ac00c5e957822#p1475838
// or by selecting
#include <Cocoa/Cocoa.h>
#endif

#ifdef TARGET_OSX

static NSString * getLastUserDir(){
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSString * file = [userDefaults stringForKey:@"current.dir"];
    NSString * result = (file == nil || [file isEqualToString:@""])? @"/Users":file;
    BOOL isDir;
    [[NSFileManager defaultManager] fileExistsAtPath:result isDirectory:&isDir];
    return isDir? result : [result stringByDeletingLastPathComponent];
}

static void setLastUserDir( NSString * dir ){
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setValue:dir forKey:@"current.dir"];
    [userDefaults synchronize];
}


#endif


ofFileDialogResult ofxSystemSaveDialog(string defaultName, string windowMessage){
    {
        
#ifdef TARGET_OSX
        ofFileDialogResult result;
        
        NSOpenGLContext *context = [NSOpenGLContext currentContext];
        NSDictionary *error = nil;
        
        NSString * dir = [getLastUserDir() stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
        NSString * name = [[NSString stringWithUTF8String:defaultName.c_str()] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
        NSString * msg = [[NSString stringWithUTF8String:windowMessage.c_str()] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
        NSString * script = [NSString stringWithFormat:
                             @"tell app \"SystemUIServer\"\n"
                             @"    choose file name default location \"%@\" default name \"%@\" with prompt \"%@\"\n"
                             @"    set result to (the POSIX path of result)\n"
                             @"end tell", dir, name, msg];
        
        
        NSAppleScript* openFile = [[NSAppleScript alloc] initWithSource:script];
        NSString *absoluteFilePath = [[openFile executeAndReturnError: &error] stringValue];
        
        if(absoluteFilePath != NULL){
            result.filePath = string([absoluteFilePath UTF8String]);
            setLastUserDir(absoluteFilePath);
            NSLog(@"User selected %@\n",absoluteFilePath);
        }
        else{
            NSLog(@"User hit cancel\n");
            result.bSuccess = false;
        }
        
        //restore app window focus
        NSWindow * appWindow = (NSWindow *)ofGetCocoaWindow();
        if(appWindow) {
            [appWindow makeKeyAndOrderFront:nil];
        }
        
        [context makeCurrentContext];
        
        if( result.filePath.length() > 0 ){
            result.bSuccess = true;
            result.fileName = ofFilePath::getFileName(result.filePath);
        }
        return result;
    }
#else
    return ofSystemSaveDialog(defaultName, windowMessage);
#endif
    
}



ofFileDialogResult ofxSystemLoadDialog( string windowMessage ){
    {
        
#ifdef TARGET_OSX
        ofFileDialogResult result;
        
        NSOpenGLContext *context = [NSOpenGLContext currentContext];
        NSDictionary *error = nil;
        
        NSString * dir = [getLastUserDir() stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
        NSString * msg = [[NSString stringWithUTF8String:windowMessage.c_str()] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
        NSString * script = [NSString stringWithFormat:
                             @"tell app \"SystemUIServer\"\n"
                             @"    choose file default location \"%@\" with prompt \"%@\"\n"
                             @"    set result to (the POSIX path of result)\n"
                             @"end tell", dir, msg];
        NSLog(script);
        
        NSAppleScript* openFile = [[NSAppleScript alloc] initWithSource:script];
        NSString *absoluteFilePath = [[openFile executeAndReturnError: &error] stringValue];
        
        if(absoluteFilePath != NULL){
            result.filePath = string([absoluteFilePath UTF8String]);
            setLastUserDir(absoluteFilePath);
            NSLog(@"User selected %@\n",absoluteFilePath);
        }
        else{
            NSLog(@"User hit cancel\n");
            result.bSuccess = false;
        }
        
        //restore app window focus
        NSWindow * appWindow = (NSWindow *)ofGetCocoaWindow();
        if(appWindow) {
            [appWindow makeKeyAndOrderFront:nil];
        }
        
        [context makeCurrentContext];
        
        if( result.filePath.length() > 0 ){
            result.bSuccess = true;
            result.fileName = ofFilePath::getFileName(result.filePath);
        }
        return result;
    }
#else
    return ofSystemLoadDialog(windowMessage);
#endif
    
}
#9

This is happening to me in windows, would this fix work on windows? I don’t think so