Xcode 10 - NSVisualEffectView added to NSWindow when displayed modally (Mac OS) - macos

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.

Related

NSOutlineView cell-based background glitch while editing in 10.12

I have an cell-based NSOutlineView under 10.12 with Source-View highlighting. When I first click on the cell and it goes into edit mode, everything is ok:
However, as soon as I start editing, the background turns blue like the highlight.
I have tried (without success):
#interface NonBackgroundDrawingTextView : NSTextView
#end
#implementation NonBackgroundDrawingTextView
-(BOOL)drawsBackground
{
return NO;
}
#end
-(NSTextView *)fieldEditorForView:(NSView *)controlView
{
NSTextView* textView = [[NonBackgroundDrawingTextView alloc] initWithFrame:NSZeroRect];
[textView setFieldEditor:YES];
[textView setFocusRingType:NSFocusRingTypeDefault];
return textView;
}
Any ideas? It works fine in 10.10 and 10.11.
Subclass NSTextFiled, and set datacell to this
then override
- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength
{
NSRect textFrame = [self titleRectForBounds:aRect];
[super selectWithFrame:textFrame inView:controlView editor:textObj delegate:anObject start:selStart length:selLength];
[textObj setBackgroundColor:[NSColor whiteColor]];
[textObj setDrawsBackground:YES];
}

NSButton Toggle : OnClick title get removed on OSX 10.11

I am using a Toggle button in XIB,
in AwakeFromNib :I set title and BG image of the button.
Code works very well till OSX 10.10.5 and below but on higher versions when I click on button the text gets removed.
Set attributed Title
[self.deleteButton setWantsLayer:YES];
self.deleteButton.layer.backgroundColor = [self setButtonBGColor];
[self setButtonTitleFor:self.deleteButton
toString:#"Delete"];
[self.deleteButton setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay];
- (void)setButtonTitleFor:(NSButton*)button toString:(NSString*)title
{
NSAttributedString *attrString = [self getAttributedStringForString:title];
[button setAttributedTitle:attrString];
}
Any idea hat should be done.
So finally got it right
Subclassing NSButtonCell helped me out
RPButtonTextTopCell.h
#interface RPButtonTextTopCell : NSButtonCell
#end
RPButtonTextTopCell.m
#implementation RPButtonTextTopCell
-(id) init
{
self = [super init];
if (self) {
}
return self;
}
-(id) initWithCoder:(NSCoder *)decoder
{
return [super initWithCoder:decoder];
}
-(id) initTextCell:(NSString *)string
{
return [super initTextCell:string];
}
-(NSRect)titleRectForBounds:(NSRect)theRect
{
NSRect titleFrame = [super titleRectForBounds:theRect];
NSSize titleSize = [[self attributedStringValue] size];
titleFrame.origin.y = (theRect.origin.y - (theRect.size.height-titleSize.height)*0.5) + 5;
return titleFrame;
}
#end
Utilizing This Custom Class
RPButtonTextTopCell *deleteCell = [[RPButtonTextTopCell alloc] init];
deleteCell.backgroundColor = [self setNSButtonBGColor];
[self.deleteButton setCell:deleteCell];
[self setButtonTitleFor:self.deleteButton
toString:#"Delete"];
[self.deleteButton setAction:#selector(deleteButtonClicked:)];
[self.deleteButton setTarget:self];
and its solved....

How to drag-move NSWindow with a NSImageView on its contentView?

I'm creating a mini window like the iTunes mini window:
It's draggable and have a background image on it.
Then I created a NSWindow's subclass and overrides its initWithContentRect:styleMask:backing:defer: method, and added an NSImageView to it:
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
contentRect.size = CGSizeMake(287, 287);
self = [super initWithContentRect:contentRect styleMask:aStyle backing:bufferingType defer:flag];
if (self)
{
[self setMovableByWindowBackground:YES];
[self setOpaque:NO];
[self setBackgroundColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.5]];
NSImageView *imageView = [[NSImageView alloc] initWithFrame:(CGRect){CGPointZero, contentRect.size}];
imageView.image = [NSImage imageNamed:#"MiniWindow.png"];
[self.contentView addSubview:imageView];
}
return self;
}
But after I add the NSImageView to window's contentView, the window become undraggable.
How to make the window become draggable again?
Best regards
Create an subclass of NSImageView and override mouseDownCanMoveWindow method:
- (BOOL)mouseDownCanMoveWindow
{
return YES;
}

Changing view in NSWindow removes contents of view

I am using an NSToolbar and NSWindowController to change the views of an NSWindow. When the toolbar items are selected, the view is successfully changed for the window and the window changes it's size according to the view size. Upon the initial loading of the window, the contents of the view appear as expected. However, once a toolbar item is selected the contents of the new view are not visible and when the view is switched back to the original view, it's contents are no longer visible either. Not sure what is causing this so any help would be appreciated.
#import <Cocoa/Cocoa.h>
#interface WindowController : NSWindowController {
IBOutlet NSView *firstView;
IBOutlet NSView *secondView;
int currentViewTag;
}
- (IBAction)switchView:(id)sender;
#end
and
#import "WindowController.h"
#interface WindowController ()
#end
#implementation WindowController
- (id)init {
self = [super initWithWindowNibName:#"WindowController"];
if (self) {
}
return self;
}
- (void)windowDidLoad {
[super windowDidLoad];
}
- (NSRect)newFrameForNewContentView:(NSView*)view {
NSWindow *window = [self window];
NSRect newFrameRect = [window frameRectForContentRect:[view frame]];
NSRect oldFrameRect = [window frame];
NSSize newSize = newFrameRect.size;
NSSize oldSize = oldFrameRect.size;
NSRect frame = [window frame];
frame.size = newSize;
frame.origin.y -= (newSize.height - oldSize.height);
return frame;
}
- (NSView *)viewForTag:(int)tag {
NSView *view = nil;
switch (tag) {
case 0:
view = firstView;
break;
case 1:
view = secondView;
break;
}
return view;
}
- (BOOL)validateToolbarItem:(NSToolbarItem *)item {
if ([item tag] == currentViewTag) return NO;
else return YES;
}
- (void)awakeFromNib {
[[self window] setContentSize:[firstView frame].size];
[[[self window] contentView] addSubview:firstView];
[[[self window] contentView] setWantsLayer:YES];
}
- (IBAction)switchView:(id)sender {
double tag = [sender tag];
NSView *view = [self viewForTag:tag];
NSView *previousView = [self viewForTag:currentViewTag];
currentViewTag = tag;
NSRect newFrame = [self newFrameForNewContentView:view];
[NSAnimationContext beginGrouping];
if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
[[NSAnimationContext currentContext] setDuration:1.0];
[[[[self window] contentView] animator] replaceSubview:previousView with:view];
[[[self window] animator] setFrame:newFrame display:YES];
[NSAnimationContext endGrouping];
}
#end
I tried out your code, and what I saw was not that the views disappeared, but that they were positioned wrongly and moved out of view. I fixed this by turning off auto layout in IB, and deselecting all the struts and springs in the size inspector. I also deselected the window's "restorable" property so that if you closed the program with view 2 visible, and reopened, the window (with view 1 inside) would be the correct size for view 1.

Cocoa -- getting a simple NSImageView to work

I am confused about why this code does not display any image:
In the app delegate:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSRect rect = window.frame;
rect.origin.x = 0;
rect.origin.y = 0;
BlueImageView *blueImageView = [[BlueImageView alloc]initWithFrame:rect];
window.contentView = blueImageView; // also tried [window.contentView addSubview: blueImageView];
}
BlueImageView.h:
#interface BlueImageView : NSImageView {
}
#end
BlueImageView.m:
#implementation BlueImageView
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setImage: [NSImage imageNamed:#"imagefile.png"]];
NSAssert(self.image, #"");
NSLog (#"Initialized");
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
}
#end
The file imagefile.png exists. The NSAssert is not causing an exception. The NSLog is firing. But no image shows up in the window.
The drawRect: method is called to draw the view, and your implementation immediately returns. To get NSImageView to draw the image for you, call [super drawRect:dirtyRect]; in your implementation of drawRect:. If you aren't going to do any other drawing in drawRect:, just remove the method to speed up drawing.

Resources