I am facing a weird issue when trying to make a full screen application. I am currently using a a NSWindow with a NSBorderlessWindowMask to make the screen show at top, and I subclassed NSWindow to accept keys:
- (BOOL) canBecomeKeyWindow
{
return YES;
}
This works fine, and I can use keys in my window, and quit out of the application with Command + Q. However, when I try to force quit the application on my Mac, the screen freezes, and I must restart my computer. I have a simple WebView inside my Window:
mainWindow = [[MyBorderWindow alloc] initWithContentRect:screenRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO screen:[NSScreen mainScreen]];
[mainWindow setLevel:windowLevel];
[mainWindow setBackgroundColor:[NSColor blackColor]];
[mainWindow makeKeyAndOrderFront:nil];
NSView *contentView = [mainWindow contentView];
WebView *customView = [[WebView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
I have tried the application on another computer, and force quit does not freeze the screen. Both computers are running OS X Mavericks.
Please let me know if there is anything else I should add.
Thanks in advance,
Bucco
Edit:
I think that my applicationWillTerminate method in AppDelegate might be part of the issue, but am not sure. Why would this method work fine on another computer, but not mine?
- (void)applicationWillTerminate:(NSNotification *)notification
{
[mainWindow orderOut:self];
// Release the display(s)
if (CGDisplayRelease( kCGDirectMainDisplay ) != kCGErrorSuccess) {
NSLog( #"Couldn't release the display(s)!" );
}
}
Related
I have a NSWindow that I display modally on some other window to display alerts.
The code is:
// This code is in MyAlert .m file. MyAlert inherits from NSWindow
- (void)showInWindow:(NSWindow *) {
[window beginSheet:self completionHandler:NULL];
}
Thing is that when compiled with Xcode 10.1 in a Mac running Mojave I see a gray "blurring" view behind the alert which I don't want there: I want the background window where it's shown to be visible.
Same code compiled with Xcode 9.4.1 does not show this blurring view.
Furthermore, I debugged the UI and there's indeed a NSVisualEffectView inserted in the Xcode 10.1 compiled version which is not there when compiling on 9.4.1, but I can't seem to find a way to get rid of it.
Below are screenshots of the UI debugged in both versions.
Has someone faced and figured this one out?
Update (Minimal Project reproducing issue of inserted nsvisualeffectview): http://s000.tinyupload.com/?file_id=43114618701497778758
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
__weak typeof(self)weakSelf = self;
NSView *contentView = self.window.contentView;
contentView.wantsLayer = YES;
[self.window setOpaque:NO];
[self.window setHasShadow:NO];
contentView.layer.backgroundColor = [NSColor redColor].CGColor;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf showAlert];
});
}
- (void)showAlert {
DummyAlertWindowController *alertController = [[DummyAlertWindowController alloc] initWithWindowNibName:#"DummyAlertWindowController"];
[self.window beginSheet:alertController.window completionHandler:^(NSModalResponse returnCode) {
;
}];
}
#implementation DummyAlertWindowController
- (void)windowDidLoad {
[super windowDidLoad];
self.properContentView.wantsLayer = YES;
self.properContentView.layer.backgroundColor = [NSColor blueColor].CGColor;
[self.window setOpaque:NO];
[self.window setHasShadow:NO];
self.window.contentView.wantsLayer = YES;
self.window.contentView.layer.backgroundColor = [NSColor clearColor].CGColor;
}
#end
You can recover your non-frosted appearance by making your window borderless.
Add this class to your project.
#interface BorderlessWindow : NSWindow
#end
#implementation BorderlessWindow
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag {
self = [super initWithContentRect:contentRect
styleMask:NSWindowStyleMaskBorderless
backing:backingStoreType
defer:flag];
return self;
}
#end
And set the window class in your XIB to BorderlessWindow
Lastly set the backgroundColor on the window to get the transparency.
#implementation DummyAlertWindowController
- (void)windowDidLoad {
[super windowDidLoad];
//stuff
[self.window setOpaque:NO];
[self.window setHasShadow:NO];
[self.window setBackgroundColor:[NSColor clearColor]];
}
#end
As a side note using wantsLayer to get backgroundColors is better served now by using a custom style NSBox with a custom color or using the backgroundColor property on the window.
I got a dialog instead of sheet.It worked when the app was not document-based.
Now it doesn't work.
- (IBAction) showSheet:(NSWindow*)window
{
// User has asked to see the dialog. Display it.
NSLog(#"%#", self.contragentsSheet);
if (!_contragentsSheet)
[NSBundle loadNibNamed: #"contragentsSheet" owner: self];
[NSApp beginSheet:self.contragentsSheet
modalForWindow: [[NSApp delegate]window]
//modalForWindow: window
modalDelegate: self
didEndSelector: NULL
contextInfo: NULL];
//[contragentSearch becomeFirstResponder];
//NSLog ( #"Sheet is launched");
NSLog(#"%#", [[NSApp delegate]window]);
}
Don't use [[NSApp delegate] window] you need to explicitly tell the method which window you want to display the sheet on. Document based Apps can have many windows and a sheet is attached to one.
I'm very new for mac application. Previously I've worked only for iPhone application and now I've started to learn mac application. I've created a simple application, for every application we have default toolbar at the top of the screen. So on clicking new I want to stay on the current window and switch to different view where I've a back button on clicking that I want to move back to previous view. Same as in iphone "PushviewController" and "Popviewcontroller" please suggest me any way. I've tried with following code but they are not working properly as I need.
-(IBAction)newDocument:(id)sender
{
NSLog(#"<><><>Test");
NewWindow *newWindow = [[[NewWindow alloc] initWithWindowNibName:#"NewWindow"] autorelease];
NSView *view = [[newWindow window] contentView];
NSLog(#"%#",view);
[[self window] setContentView:view];
//[[newWindow window] becomeKeyWindow];
//[NSApp beginSheet:[newWindow window] modalForWindow:[self window] modalDelegate:self didEndSelector:nil contextInfo:nil];
}
- (IBAction)goBack:(NSButton *)sender
{
[[self window] resignKeyWindow];
}
Please keep in mind that I'm a really newbie Cocoa developer
Scenario: I've a search the when reaches the end of document restarts from begin, a so called "wrap around".
When I do the wrap I want to show a window that flashes on screen for some time (one second??) like and OSD (On Screen Display) control window, TextWrangler and XCode do that when text search restarts from the begin.
How can I implement a similar window?
Implementing a view to do this would be relatively simple. The following code in an NSView subclass would display a partially transparent rounded rect which ignores events when placed in a window.
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor colorWithDeviceWhite:0 alpha:.7] set];
[[NSBezierPath bezierPathWithRoundedRect:self.bounds xRadius:10 yRadius:10] fill];
//Additional drawing
}
- (NSView *)hitTest:(NSPoint)aPoint {
return nil;
}
- (BOOL)acceptsFirstResponder {
return NO;
}
- (BOOL)isOpaque {
return NO;
}
If you do want to do this in a window, you will need to create a borderless, non-opaque window and set this as the content view. Also, you will need to have the view fill it's bounds with a clear color at the start of the drawRect: method.
//Create and display window
NSPanel *panel = [[NSPanel alloc] initWithFrame:NSMakeRect(0,0,300,200) styleMask:NSBorderlessWindowMask|NSNonactivatingPanelMask backing:NSBackingStoreBuffered defer:YES];
[panel setOpaque:NO];
MyViewSubview *view = [MyViewSubview new];
[panel setContentView:view];
[view release];
[p setLevel:NSScreenSaverWindowLevel];
[p orderFront:nil];
//Add these two lines to the beginning of the drawRect: method
[[NSColor clearColor set];
NSRectFill(self.bounds);
However, this window will intercept events and I have not been able to disable this using standard methods.
To fade the view, check out NSViewAnimation, or use an NSTimer object and do it manually.
I am trying to open one window from another using makeKeyAndOrderFront. The new window appears, but does not receive focus.
The code for the main window is:
#import "SecondWindowController.h"
#implementation FirstWindowController
-(IBAction)showSecondWindow:(id)sender
{
if (!secondWindowController)
secondWindowController = [[SecondWindowController alloc] init];
[[secondWindowController window] makeKeyAndOrderFront:self];
}
SecondWindowController is a NSWindowController, as follows:
#implementation SecondWindowController
-(id)init
{
if (![super initWithWindowNibName:#"SecondWindow"])
return nil;
return self;
}
I've also tried putting [secondWindowController showWindow:self] before the makeKeyAndOrderFront but it doesn't make a difference.
Did you make sure the window outlet for SecondWindowController is hooked up to the window in your NIB? The window could be displayed just by loading the NIB, even if the outlet is not hooked up.
Are you using a borderless window? If so you need to override canBecomeKeyWindow and return YES
Try this:
if (!secondWindowController)
secondWindowController = [[SecondWindowController alloc] init];
NSApplication *thisApp = [NSApplication sharedApplication];
[thisApp activateIgnoringOtherApps:YES];
[[secondWindowController window] makeKeyAndOrderFront:self];