Main window loses focus after NSOpenPanel

Discussion in 'Mac Programming' started by Cactus Dan, Aug 5, 2011.

  1. Cactus Dan macrumors member

    Joined:
    Aug 8, 2010
    #1
    Howdy,

    I've created a C callable function to open the NSOpenPanel and convert the selected file name and path to a character array that's passed to the function:
    Code:
    //Create open panel dialog
    int callFileOpenDialog(int type, char **fName)
    {
    	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    	
    	NSOpenPanel *open = [NSOpenPanel openPanel];
    	NSString *pathName;
    	
    	[open setResolvesAliases: true]; //Enable alias resolving
    	[open setAllowsMultipleSelection: false]; //Disable multiple selection
    	
    	switch(type)
    	{
    		case FILE_SELECTION:
    			[open setCanChooseDirectories: false]; //Disable folder selection
    			[open setCanChooseFiles: true]; //Enable file selection
    			break;
    		case DIR_SELECTION:
    			[open setCanChooseDirectories: true]; //Enable folder selection
    			[open setCanChooseFiles: false]; //Disable file selection
    			break;
    	}
    	
    	//Display open panel
    	int result = [open runModal];
    	if(result == NSOKButton)
    	{
    		switch(type)
    		{
    			case FILE_SELECTION:
    				pathName = [open filename];
    				break;
    			case DIR_SELECTION:
    				pathName = [open directory];
    				break;
    		}
    		
    		*fName = (char *)malloc(strlen([pathName UTF8String]));
    		strcpy(*fName, [pathName UTF8String]);
    
    		[pool release];
    		return 1;
    	}
    	
    	[pool release];
    	return 0;
    }
    ... which works fine except that the main window loses it's focus after the NSOpenPanel is closed.

    Is there a way to get a pointer to the window that's in focus at the beginning of the above function, and then return the focus to that window at the end of the function?

    I've been searching, but don't really know what I'm looking for, so my search parameters are probably wrong.

    Adios,
    Cactus Dan
     
  2. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #2
    The focused window is called the key window in Cocoa. You can get the current key window with code like this (untested):
    Code:
    NSWindow *keyWindow = [NSApp keyWindow];
    After the NSOpenPanel runs, you can restore the key window with code like this (also untested):
    Code:
    [keyWindow makeKeyWindow];
     
  3. Cactus Dan thread starter macrumors member

    Joined:
    Aug 8, 2010
    #3
    Howdy,

    Thanks! That seems to work fine. ;)

    Edit:
    One more question: would you put that inside or outside the NSAutoreleasePool calls?

    Adios,
    Cactus Dan
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    The red-hilited code is wrong. You're not accounting for the NUL byte at the end of the C-string.

    I don't know if that's the cause of the problem you described, but the consequences of this bug can be grave.
     
  5. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #5
    Inside the autorelease pool, just in case NSApplication's keyWindow is implemented something like this:
    Code:
    return [[_keyWindow retain] autorelease];
     
  6. Cactus Dan thread starter macrumors member

    Joined:
    Aug 8, 2010
    #6
    Howdy,
    So, what is the correct way?

    Adios,
    Cactus Dan
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    The correct way is to account for all the bytes. That means counting all the bytes. Since a C string is always marked by a single terminating NUL byte, how do you think you should account for that byte?

    Suppose strlen() returns 54. What count should you pass to malloc()?

    Suppost strlen() returns 182. What count should you pass to malloc()?
     
  8. Cactus Dan thread starter macrumors member

    Joined:
    Aug 8, 2010
    #8
    Howdy,

    All I can say is, "DOH!" :D

    Thanks.

    Adios,
    Cactus Dan
     
  9. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #9
    Wouldn't this be easier?

    Code:
    *fName = strdup([pathName UTF8String]);
     
  10. fredrikaustin macrumors newbie

    Joined:
    Jan 20, 2008
    #10
    As long as we're talking about the "correct way", I think using fileSystemRepresentation is better than UTF8String
     
  11. Cactus Dan, Nov 8, 2011
    Last edited: Nov 9, 2011

    Cactus Dan thread starter macrumors member

    Joined:
    Aug 8, 2010
    #11
    Howdy,
    That looks like it's Cocoa specific, so that won't work. Thanks anyway.

    Edit:
    Oh wait, I just looked that up and it says it returns a const char*. Maybe I'll investigate this further.

    Adios,
    Cactus Dan
     

Share This Page