Is there Any way to imitate Lion's Launchpad? - objective-c

I have been struggling to imitate Launchpad.
At the beginning I thought about making NSWindow bgcolor transparent:
//make NSWindow's bgcolor transparent
[window setOpaque:NO];
[window setBackgroundColor:[NSColor clearColor]];
But now I realized it's way more ideal to
capture wallpaper
blur it and make it bg-image for NSWindow or a view
Rather than hiding all the opened windows and menubar, which was the first idea I had have come with (Still not sure with better, if you had any better idea...).
Capture & blur wallpaper used by a user
Make it background image for nswindow or a view
Fade-in to fullscreen view
Click somewhere blank or press ESC to fade-out
Are those possible to achieve without using private APIs?
Sorry if it's not clear my poor English.
Simply I'm trying to imitate Launchpad-styled full screen.
Thanks for any advice.

To get an image of the desktop background, use:
NSURL *imageURL = [[NSWorkspace sharedWorkspace] desktopImageuRLForScreen:[NSScreen mainScreen]
NSImage *theDekstopImage = [[NSImage alloc] initWithContentsOfURL:imageURL];
You can blur the image using CIFilter. Here's a Apple doc describing how to apply filters.
And then you can load that image into a color and set that as the background color for the window. Additionally, set the window to have no style mask (no close buttons, title frame, etc.), cover the screen, and be in front of everything except the dock:
[yourWindow setBackgroundColor:[NSColor colorWithPatternImage:theDesktopImage]];
[yourWindow setStyleMask:NSBorderlessWindowMask];
[yourWindow setLevel:kCGDockWindowLevel - 1];
[yourWindow setFrame:[[NSScreen mainScreen] frame] display:YES];
To have the window fade in, you can use NSWindow's animator proxy. (Replace 1.0 with 0.0 to make it fade out.)
[[yourWindow animator] setAlphaValue:1.0];
Of course you could customize that a bit more with things like CoreAnimation, but this should work just fine.
To handle background clicking, I suggest making a subclass of NSView where you -orderOut: your window on -mouseDown:. Then put an instance of that subclass that spans the entire frame of your window.
Also, NSViews sometimes don't respond to key events, so you can add an event listener to detect any time the escape key is pressed while your app is active:
[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:(NSEvent *ev)^ {
if([ev keyCode] == 0x53) {
[yourWindow orderOut:self];
}
return ev;
}

Related

Invisible Fullscreen View with Cocoa

I'm trying to create an application which change the mouse cursor, but to do that the cursor must be inside a NSView. To do this all the time, I would need to have an intangible and invisible fullscreen view.
I've created a subclass of NSView which implement the following code to became full screen in initWithFrame:
[self enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
And using that code, I can change the cursor inside the view:
- (void)resetCursorRects{
[self addCursorRect:[self bounds] cursor:appCursor];
}
The cursor changed successfully, but here comes the first problem: the view is in fullscreen, but it's visible, like a gray background. I've tried this method:
[[self window] setOpaque:NO];
And this one:
[[self window] setBackgroundColor:[NSColor colorWithWhite:1.0 alpha:0.0]];
But both of them just change the view color to black instead of gray. How can I fix that?

Show up a custom UI somewhere on screen

I've programmed a custom UI which looks like this: http://www.youtube.com/watch?v=XLsrVVhEs94
Currently it is only working within a NSView itself but I want it to show up in every corner of my screen.
So I programmatically created an NSWindow like so [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered
defer:NO];
This works great but there is a problem: Every time I open this UI I can barley see that the NSWindow was just created. I can see a shadow that has the size of the NSWindow and after that it disappears (because of [NSColor clearColor]). I think that [NSColor clearColor] applies too slow to the just created NSWindow.
The NSWindow was set up with [window setOpaque:NO] so it is transparent.
Is there another way to display a custom UI somewhere on my screen?
- Timo
I think you want to set the defer to YES. Referring to the documentation, the defer property will either create the window immediately, or defer it until it is displayed on the screen. In this case you can then set all the window properties, add subviews, etc before showing on the screen.
NSWindow *myWin = [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
... do window setup here ...
[myWin orderFront:self];
Additionally if that still flickers, you can call 'display' on the window so it draws all the subviews into it's buffer first (including your clear), then call orderFront.

Creating a custom title bar on a standard NSWindow

I've been trying to build a specific look for my menubar app.
I've been using a NSWindow with a NSBorderlessWindowMask style mask and setting [window setOpaque:NO] and [window setBackgroundColor:[NSColor clearColor]]. That gives me a blank canvas which works great for the title bar.
Now I'm having problems with the view-based NSTableView I'm using for the listing. How can I clip the NSTableCellViews to the window's rounded corners?
I started out just having a custom view wrapping the NSTableView, drawing the background with rounded corners. Using [view addClip:path] doesn't clip child views though.
I've also tried using a [view setWantsLayer:YES] with a mask. That worked great, but the table view cells would sporadically glitch out. It seems that having a NSScrollView be a child of a layer is a known problem:
My current view structure looks something like:
NSWindow
- MyTitleBarView
- MyBackgroundView
- NSScrollView
- NSTableView
I found one way to do it:
The trick is to keep the window style as the default and not set NSBorderlessWindowMask. Then you can add your custom title bar view to the window's theme frame like so:
NSView *themeFrame = [[window contentView] superview];
NSView *firstSubview = [[themeFrame subviews] objectAtIndex:0];
[titleBarView setAutoresizingMask:(NSViewMinYMargin | NSViewWidthSizable)];
[themeFrame addSubview:titleBarView positioned:NSWindowBelow relativeTo:firstSubview];
This basically just puts your custom title bar view on top of the standard title bar. You'll probably have to do some rejiggering to the view frames and window buttons. See INAppStoreWindow for some code examples of this.
The INAppStoreWindow project says that this method doesn't use any private APIs, and thus is able to be used on the App Store.
If you require the window to be transparent, you can just set the following on the window:
[window setOpaque:NO];
[window setBackgroundColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.5]];

Drawing a Window at Coordinates or Drawing outside of NSStatus Item

I am trying to display something off the side of a NSStatusItem. I think I could do this in two ways:
Display a transparent window with the image I need at the coordinates of the mouse cursor.
OR
Use a custom NSStatusItem and move the controls/images in the view to the left so they are actually off the status item
The problem is, setting the NSRect frame negative (-200,0,100,50) doesn't seem to actually work. So, how can I render things outside of the bounds of the status item (think the CSS overflow property) or render a transparent window at specific coordinates?
The system will prevent you from drawing outside the status item, but using a transparent window will work.
NSRect rect; //The location of the window
NSWindow *win = [[NSWindow alloc] initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
[win setOpaque:NO];
[win setBackgroundColor:[NSColor clearColor]];
//or
[win setContentView:myView];
Here, myView is a custom view which will be the background of the window. In order for the window to be transparent, you either have to set the background color to clear or use a custom content view which only draws where it is not transparent. You will probably want to use a floating window so that it stays on top. Be careful not to cover up something important because your window could intercept events intended for something underneath it.

Animate setContent of an NSWindow

In the past I've been successfully able to fade in an NSWindow using the following code;
if (![statusWindow isVisible])
{
statusWindow.alphaValue = 0.0;
[statusWindow.animator setAlphaValue:1.0];
}
CAAnimation *anim = [CABasicAnimation animation];
[anim setDelegate:self];
[statusWindow setAnimations:[NSDictionary dictionaryWithObject:anim forKey:#"alphaValue"]];
[statusWindow makeKeyAndOrderFront:self];
For my current project I'm trying to make a flash similar to the one in Photo Booth. I've created a white NSPanel and was planning to set my NSWindow's content to the panel, and quickly set it back.
Is it possible to set the contentView of an NSWindow using a nice fade effect?
P.S - If there is an easier way you know of how to achieve the flash, please tell me!
Thanks in advance,
Ricky.
Why use another window? It looks like you're trying to use CoreAnimation already so why not just add a white CALayer to your existing view and animate its opacity?