How to draw on a transparent NSWindow with a transparent NSView? - cocoa

I want to draw on the screen with a transparent background, so that everything (e.g. open applications are still visible).
In windowDidLoad of my custom NSWindowController i have the follwing:
[self.window setOpaque: NO];
[self.window setHasShadow:NO];
[self.window setBackgroundColor:[NSColor clearColor]];
[self.window setStyleMask:NSBorderlessWindowMask];
My custom NSWindow overrides canBecomeKeyWindow
- (BOOL)canBecomeKeyWindow {
return YES;
}
My View overrides drawRect
- (void)drawRect:(NSRect)rect {
[[NSColor clearColor]set];
NSRectFill(rect);
...
}
Problem: Trying to draw by using mouse events inside of my custom view results in the view/application beneath my Window to receive these events.
It justs works when i do not set the NSWindow styleMask to NSBorderlessWindowMask or by setting the background color of the custom view to semitransparent.
[[NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:0.05] set]
How can i draw on screen with full transparency and NSBorderlessWindowMask?

Adding
[self.window setIgnoresMouseEvents:NO];
to windowDidLoad of my custom NSWindowController solved it

Related

Update NSView Background color in fullscreen

I want to set a background color to a view and as of now I have subclassed that view in Xib and in drawRect method I am setting the color.
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor blackColor] setFill];
NSRectFill(dirtyRect);
[super drawRect:dirtyRect];
}
Am using [self.view enterFullScreenMode:screen withOptions:nil]; to show the view(which contains an image) in fullscreen. But when view is in fullscreen it shows a default gray background instead of black color. How can I set the background to black ?
Are you sure your methods calling? Put a NSLog to make sure.
If it is, then delete the line [super drawRect:dirtyRect];

Layer-Backed view no longer punches hole in transparent NSWindow

I am trying to make a "hole" in an NSWindow using a CAShapeLayer or even just a CALayer.
When using regular NSViews or even layer-backed views, I can override drawRect: using code like this:
[spotImage drawInRect:self.bounds fromRect:NSZeroRect operation:NSCompositeXOR fraction:1.0];
where spotImage is an NSImage with pure white content and some gradations, and the window has a black background with 0.5 alpha. The NSView subclass where this drawRect is defined has a clearColor background.
The end result is a grey window (It is a transparent window with a styleMask of NSBorderlessWindowMask as can be found in many samples.
If I turn the NSView into a layer-backed view, it calls the drawRect methods and works fine.
When I turn this into a layer-hosting view, and again use the same structure (NSWindow > contentView > CustomView) then, the drawInRect method just draws the image. It no longer punches a hole through it.
It is like the layer itself can no longer punch the hole when it is part of a layer-hosting hierarchy.
Here is some sample code:
The custom NSWindow subclass initializer:
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag {
self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
if (self) {
[self setBackgroundColor: [NSColor lightGrayColor]]; //[NSColor clearColor]];
[self setAlphaValue:0.5];
[self setOpaque:NO];
[self setHasShadow: NO];
[self useOptimizedDrawing:YES];
[self setIgnoresMouseEvents:YES];
}
return self;
}
the code in my applicationDidFinishLaunching method:
PPContentView *thisView = [[PPContentView alloc]
initWithFrame:CGRectInset([self.window.contentView bounds], 50, 50)];
//[thisView setWantsLayer:YES]; enabling this makes things opaque again
[self.window.contentView addSubview:thisView];
thisView.layer.backgroundColor = [NSColor clearColor].CGColor;
//Create custom content
[thisView setNeedsDisplay:YES];
}
and my custom view's drawRect contains:
[[NSImage imageNamed:#"spotFuzzy.png"] drawInRect:self.bounds fromRect:NSZeroRect operation:NSCompositeXOR fraction:1.0];

NSScrollView background image in Lion

I'm working on a Mac application with an NSScrollView, and I want the NSScrollView to have a custom background image. I used this code in the custom documentView NSView subclass:
- (void)drawRect:(NSRect)rect {
[[NSColor colorWithPatternImage:[NSImage imageNamed:#"wood.jpg"]] set];
NSRectFill(rect);
}
That displays a pattern image as a background for the documentView.
But now in Mac OS X Lion, the NSScrollView bounces when scrolling further than possible, showing ugly white space. How can I make the white space also being covered by the background image?
Instead of overriding drawRect:, use the scroll view's setBackgroundColor: method, passing the NSColor you created with the pattern image.
You should subclass use NSScrollView setBackgroundColor, but then you should subclass NSClipView like this to pin the texture origin to the top:
#implementation MYClipView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
if (self.drawsBackground)
{
NSGraphicsContext* theContext = [NSGraphicsContext currentContext];
[theContext saveGraphicsState];
float xOffset = NSMinX([self convertRect:[self frame] toView:nil]);
float yOffset = NSMaxY([self convertRect:[self frame] toView:nil]);
[theContext setPatternPhase:NSMakePoint(xOffset, yOffset)];
NSColor* color = self.backgroundColor;
[color set];
NSRectFill([self bounds]);
[theContext restoreGraphicsState];
}
// Note: We don't call [super drawRect:dirtyRect] because we don't need it to draw over our background.
}
+ (void)replaceClipViewInScrollView:(NSScrollView*)scrollView
{
NSView* docView = [scrollView documentView]; //[[scrollView documentView] retain];
MYClipView* newClipView = nil;
newClipView = [[[self class] alloc] initWithFrame:[[scrollView contentView] frame]];
[newClipView setBackgroundColor:[[scrollView contentView] backgroundColor]];
[scrollView setContentView:(NSClipView*)newClipView]; [scrollView setDocumentView:docView];
// [newClipView release];
// [docView release];
}
#end
And call + (void)replaceClipViewInScrollView:(NSScrollView*)scrollView with the NSScrollView instance.
Put your drawRect code in an NSScrollView subclass. In IB, change the NSScrollView to use your custom subclass instead of NSScrollView. Also make sure to uncheck Draw Background in the scroll view's attributes inspector.

NSTextView background not resizing appropriately

I have an NSTextView inside an NSScrollView. The scroll view has the auto resize masks for height and width, so it changes size with the window it's in.
The text view is set up much in the way the apple documentation recommends here.
But no matter what settings I put on the text view, I cannot get the background color to resize along with the scroll view.
Here's a picture of what I'm dealing with:
The width works, but not the height.
Here's my setup code for the textview as it is for this picture:
NSTextView *view = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, scrollview.contentSize.width, scrollview.contentSize.height) textContainer:textContainer];
[view setMinSize:NSMakeSize(0.0, scrollview.contentSize.height)];
[view setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[view setVerticallyResizable:YES];
[view setHorizontallyResizable:NO];
[view setAllowsDocumentBackgroundColorChange:YES];
[view setDrawsBackground:YES];
[view setAutomaticLinkDetectionEnabled:YES];
[view setAutoresizingMask:NSViewWidthSizable];
The white background colour isn’t that of the NSTextView, but rather that of its enclosing NSScrollView.
To change it, either select the NSScrollView in Interface Builder/Xcode 4. Or, to do it programmatically, use -[NSView encosingScrollView]:
NSScrollView *scrollView = [textView enclosingScrollView];
[scrollView setBackgroundColor:[NSColor blackColor]];

How to create an OSD-like window with Cocoa on Mac OSX?

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.

Resources