Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

SRossi

macrumors regular
Original poster
May 27, 2009
202
0
Glasgow, Scotland
Hello all,

I have searched the internet on a stub of code or so that may help me allow to switch between fullscreen and windowed mode. I have set up a menu item to allow me to change to fullscreen but now i am stuck.

What i am looking for is a start or any help so that i can display the NSTextView in full screen and allow the user to continue editing text on it.

Any help will be appreciated.

Thanks in advance

Stephen
 
In your MainView's M file (the one that is direct to the Full Screen Window) include this:

Code:
- (BOOL) canBecomeKeyWindow
{
    return YES;
}

That will allow everything to be activated and made editable again. Text Fields and Views tend to disable themselves for some odd reason. :D
If there is anything else you need, just reply or PM.
 
Thanks man.

Can you point me in the direction I should go with the fullscreen coding, as I am beat in what to do. I have learned about using carbon to hide the menu and dock but as for making the text view appear I have no knowledge to where to start or that.

Thanks

Stephen
 
Thanks man.

Can you point me in the direction I should go with the fullscreen coding, as I am beat in what to do. I have learned about using carbon to hide the menu and dock but as for making the text view appear I have no knowledge to where to start or that.

Thanks

Stephen

Create a title-bar-less window the size of the screen, position correctly and add the NSTextView to it. Basically read the NSWindow documentation.
 
Create a title-bar-less window the size of the screen, position correctly and add the NSTextView to it. Basically read the NSWindow documentation.

Right I understand what you are saying but do I take the NSWindow of the MyDocument.xib and set it to a NSWindow variable in MyDocument.h?

I have found a tutorial on cocoadevcentral but thats using a panel, would I need to create a panel and add a NSTextView or just use the existing MyDocument.xib window?

Sorry for being a bit stupid im just totally lost.

Stephen
 
I wasn't suggesting you do anything in Interface Builder at all. I would suggest that you have different windows for full screen and windowed mode. Your full-screen window would be created entirely in code with the appropriate styleMask.
 
I wasn't suggesting you do anything in Interface Builder at all. I would suggest that you have different windows for full screen and windowed mode. Your full-screen window would be created entirely in code with the appropriate styleMask.

Ahhhh I get you now so what I have to do is create a boarderless window, then add my textView into it. Thanks for your help :). If I have any other problems i'll post them up.

Can I ask though how is it that I add a NSTextView to my new window?

Thanks

Stephen
 
Ahhhh I get you now so what I have to do is create a boarderless window, then add my textView into it. Thanks for your help :). If I have any other problems i'll post them up.

Can I ask though how is it that I add a NSTextView to my new window?

Thanks

Stephen

Get the contentView of the window then add your NSTextView instance as a subView.
 
Right I have done some code, I dont wether I am correct yet as it isn't running
my program at all. But can anyone see if there is anything wrong with my code.

iWriteDelegate.h
Code:
#import <AppKit/AppKit.h>


@interface iWriteDelegate : NSObject 
{
	BOOL fullScreen;
	NSWindow *mainWindow;
}
- (IBAction)fullScreen:(id)sender;

- (void)showFullScreen;
- (void)exitFullScreen;

- (BOOL)isFullScreen;
- (void)setFullScreen:(BOOL)sender;
@end

iWriteDelegate.m
Code:
#import "iWriteDelegate.h"
#import "MyDocument.h"

@implementation iWriteDelegate

- (IBAction)fullScreen:(id)sender
{
	BOOL inFullScreen = [self isFullScreen];
	
	if (inFullScreen = YES) {
		[self exitFullScreen];
	} else {
		[self showFullScreen];
	}
}

- (void)showFullScreen
{
	[self setFullScreen:YES];
	
	int WindowLevel;
	NSRect screenRect;
	
	if (CGDisplayCapture(kCGDirectMainDisplay) != kCGErrorSuccess) {
		NSLog(@"Couldnt capture the main display!");
	}
	
	WindowLevel = CGShieldingWindowLevel();
	
	screenRect = [[NSScreen mainScreen] frame];
	
	mainWindow = [[NSWindow alloc] initWithContentRect:screenRect
											 styleMask:NSBorderlessWindowMask
											   backing:NSBackingStoreBuffered
												 defer:NO screen:[NSScreen mainScreen]];
	
	[mainWindow setLevel:WindowLevel];
	
	[mainWindow setBackgroundColor:[NSColor blackColor]];
	
	NSRect cFrame = [[mainWindow contentView] frame];
	
	NSTextView *theTextView = [[NSTextView alloc] initWithFrame:cFrame];
	[mainWindow setContentView:theTextView];
	[mainWindow makeKeyAndOrderFront:nil];
	[mainWindow makeFirstResponder:theTextView];
	
	[theTextView insertText:mString];
	
}

- (void)exitFullScreen
{
	[mainWindow orderOut:self];
	[self setFullScreen:NO];
	
	if (CGDisplayRelease(kCGDirectMainDisplay) != kCGErrorSuccess) {
		NSLog(@"Couldnt release the displays");
	}
}

- (BOOL)isFullScreen
{
	return fullScreen;
}

- (void)setFullScreen:(BOOL)sender
{
	fullScreen = sender;
}

@end

It is not posting any errors it just wont open my application think it is trying to open it in fullscreen to start with.

Thanks in advance.

Stephen
 
Get the contentView of the window then add your NSTextView instance as a subView.
An alternative, which is more or less exactly what I'm doing is to set up everything you want for your ordinary window in Interface Builder, then to do something like:

Code:
NSView *content = [normalWindow contentView];
[content retain];
[normalWindow setContentView:nil];
[fullScreenWindow setContentView:content];
[content release];

Which should transfer the content you drew in Interface Builder from the NIB window to the one you just created, applying all the sizing criteria you set there. It's a slightly longer-than-one-line switch because an NSView can belong to only one window at a time and setContentView: will release the previous NSView.

EDIT: sorry, we appear to have posted near simultaneously. Do you set the initial value of fullScreen anywhere?
 
Well, I don't seem to be able to make the full screen window able to become first responder (which is also a problem I'm having in my own code), but by going the Interface Builder route and otherwise copying most of your code, the attached and should happily switch some window contents between windowed mode and fullscreen (on command+enter, since command+f is already taken by one of the standard Edit menu entries).

Application delegate code (also in the archive) is:

Code:
#import "IWriteAppDelegate.h"

@interface IWriteWindow: NSWindow
{
}
@end

@implementation IWriteWindow

- (BOOL)acceptsFirstResponder
{
	NSLog(@"accepts\n");
	return YES;
}

@end


@implementation IWriteAppDelegate
- (BOOL)isFullScreen
{
	return fullScreen;
}

- (void)setFullScreen:(BOOL)sender
{
	fullScreen = sender;
}

- (void)exitFullScreen
{
	[self setFullScreen:NO];
	
	NSView *content = [fullScreenWindow contentView];
	[content retain];
	[fullScreenWindow setContentView:nil];
	[desktopWindow setContentView:content];
	[content release];

	[fullScreenWindow orderOut:self];
	[fullScreenWindow release];
	if(CGDisplayRelease(kCGDirectMainDisplay) != kCGErrorSuccess)
	{
		NSLog(@"Couldn't release the display");
	}
}

- (void)enterFullScreen
{
	[self setFullScreen:YES];
	
	int windowLevel;
	NSRect screenRect;
	
	if(CGDisplayCapture(kCGDirectMainDisplay) != kCGErrorSuccess)
	{
		NSLog(@"Couldn't capture the main display!");
	}
	
	windowLevel = CGShieldingWindowLevel();
	screenRect = [[NSScreen mainScreen] frame];
	
	NSView *content = [desktopWindow contentView];
	[content retain];
	[desktopWindow setContentView:nil];

	fullScreenWindow = [[IWriteWindow alloc] initWithContentRect:screenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO screen:[NSScreen mainScreen]];
	[fullScreenWindow setContentView:content];
	[content release];
	
	[fullScreenWindow makeKeyAndOrderFront:nil];
	[fullScreenWindow makeFirstResponder:content];
	[fullScreenWindow setLevel:windowLevel];
}

- (IBAction)toggleFullScreen:(id)sender {
    
	if([self isFullScreen])
		[self exitFullScreen];
	else
		[self enterFullScreen];
}

- (void)applicationDidFinishLaunching:(NSNotification *) note
{
	fullScreen = NO;
}

@end
 

Attachments

  • Archive.zip
    55.7 KB · Views: 92
Words cannot express how much that has helped me :D

Thanks soo much, if there is anything you need help with please ask :D

Thanks sooo much

Stephen
 
Words cannot express how much that has helped me :D

Thanks soo much, if there is anything you need help with please ask :D

Thanks sooo much

Stephen
If you do figure out how to get the borderless window to become key (it's the reason I've subclassed NSWindow, albeit not successful with respect to the goal), I'd be really grateful if you could post it! Sadly I have to return to work for the rest of the afternoon...
 
If you only need 10.5+ compatibility, just use the new API:

Code:
NSView *view = [[self window] contentView];
if ([view isInFullScreenMode])
    [view exitFullScreenModeWithOptions:nil];
else
    [view enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
 
If you do figure out how to get the borderless window to become key (it's the reason I've subclassed NSWindow, albeit not successful with respect to the goal), I'd be really grateful if you could post it! Sadly I have to return to work for the rest of the afternoon...

As described here I think you need to override the canBecomeKeyWindow method in your NSWindow subclass to return YES.
 
As described here I think you need to override the canBecomeKeyWindow method in your NSWindow subclass to return YES.
I thought I'd tried that immediately before acceptsFirstResponder, I guess I typed something incorrectly and was insufficiently thorough in my investigation of that. Thanks!

kainjow> does that give the Quicktime-style full screen transition animation? I guess you could use [view respondsToSelector:mad:selector(enterFullScreenMode:withOptions:)] to determine whether the 10.5 API is available at runtime?

EDIT: no animation, but presumably the following is smart?
Code:
#import "IWriteAppDelegate.h"

@interface IWriteWindow: NSWindow
{
}
@end

@implementation IWriteWindow

- (BOOL)canBecomeKeyWindow
{
	return YES;
}

@end


@implementation IWriteAppDelegate
- (BOOL)isFullScreen
{
	return fullScreen;
}

- (void)setFullScreen:(BOOL)sender
{
	fullScreen = sender;
}

- (void)exitFullScreen
{
	[self setFullScreen:NO];

	if(fullScreenWindow)
	{
		NSView *content = [fullScreenWindow contentView];
		[content retain];
		[fullScreenWindow setContentView:nil];
		[desktopWindow setContentView:content];
		[content release];

		[fullScreenWindow orderOut:self];
		[fullScreenWindow release]; fullScreenWindow = nil;
		if(CGDisplayRelease(kCGDirectMainDisplay) != kCGErrorSuccess)
		{
			NSLog(@"Couldn't release the display");
		}
	}
	else
	{
		[[desktopWindow contentView] exitFullScreenModeWithOptions:nil];
	}
}

- (void)enterFullScreen
{
	[self setFullScreen:YES];

	NSView *content = [desktopWindow contentView];
	if([content respondsToSelector:@selector(enterFullScreenMode:withOptions:)])
	{
		[content enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
	}
	else
	{
		int windowLevel;
		NSRect screenRect;

		if(CGDisplayCapture(kCGDirectMainDisplay) != kCGErrorSuccess)
		{
			NSLog(@"Couldn't capture the main display!");
		}

		windowLevel = CGShieldingWindowLevel();
		screenRect = [[NSScreen mainScreen] frame];

		[content retain];
		[desktopWindow setContentView:nil];

		fullScreenWindow = [[IWriteWindow alloc] initWithContentRect:screenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO screen:[NSScreen mainScreen]];
		[fullScreenWindow setContentView:content];
		[content release];

		[fullScreenWindow makeKeyAndOrderFront:nil];
		[fullScreenWindow makeFirstResponder:content];
		[fullScreenWindow setLevel:windowLevel];
	}
}

- (IBAction)toggleFullScreen:(id)sender {
    
	if([self isFullScreen])
		[self exitFullScreen];
	else
		[self enterFullScreen];
}

- (void)applicationDidFinishLaunching:(NSNotification *) note
{
	fullScreen = NO;
	fullScreenWindow = nil;
}

@end
 
kainjow> does that give the Quicktime-style full screen transition animation? I guess you could use [view respondsToSelector:@selector(enterFullScreenMode:withOptions:)] to determine whether the 10.5 API is available at runtime?

It doesn't, and although there are options you can pass I didn't see anything related to that effect. Probably would have to use the CGDisplay functions for that I imagine.

respondsToSelector could definitely be used if you need to build for 10.4 but want to use the new API for 10.5+ users, but if you have code that works on 10.4 I would just use that instead.
 
If you want animation in the 10.4 compatible code set the full screen/borderless window to the size/position of the initial window and then call the setFrame:display:animate: method. If your contents are set to auto-size it should look pretty sweet :)
 
Oh, yep, got that in the code I have back at home from a few days ago that made me so willing and able to help out here so quickly. It's not identical to Quicktime since in that the viewer frame resizes with the content but fades away as the desktop goes with it, whereas with a CGDisplayCapture the background is just blanked out instantly, but it looks pretty good. And the animation is blocking, for want of a better word, so you don't even have to jump through hoops to figure out when to switch the content view back to the normal window when exiting full screen.

Something else I preferred to the code posted here was to use [[[[desktopWindow screen] deviceDescription] @"NSScreenNumber"] unsignedIntValue] to get the value for CGDisplayCapture rather than always capturing the main screen; it should cause a window to become full screen on whichever display that the majority of it is on. NSScreenNumber still doesn't seem to be in the official docs, but per various resources located by Google has been present since at least 2003. Probably best to include a fallback though.

EDIT: my home code is actually implemented in a multiple document application (as per my thread earlier in the week); I put it straight into my NSDocument derivative, having connected the full screen toggle from the menu bar to the first responder in that .xib, which leads to it being passed all the way down to the frontmost document.
 
Aww cause I was connecting my toggle full screen menu item to a controller i created with new document files. Which is what arron hillegass done int his book.

But if i connect it to the first responder of mainmenu.xib i will be able to acces the main window?

Thanks

Stephen
 
Aww cause I was connecting my toggle full screen menu item to a controller i created with new document files. Which is what arron hillegass done int his book.

But if i connect it to the first responder of mainmenu.xib i will be able to acces the main window?
I'm really no expert; I've recently returned to Interface Builder/Xcode after several years of absence and am still a tiny bit lost with the 3.0 rejig. If what I say is contrary to almost any other source, it's probably smarter to trust the other source.

That said, my code does work fine. I'll try to remember to bring it to work (where I have the internet) tomorrow in case this thread is still ongoing.
 
To be honest Thomas anything that you say I would believe because youve gave nothing but good advice all day :)

If you could do that id be grateful, sorry if im keeping you from your work.

Stephen
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.