Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to don't orderOut the Window if the app is still active (another Window of the app is keyWindow) #6

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Classes/OBMenuBarWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ extern NSString * const OBMenuBarWindowDidAttachToMenuBar;
extern NSString * const OBMenuBarWindowDidDetachFromMenuBar;

// Constants
extern const CGFloat OBMenuBarWindowTitleBarHeight;
extern const CGFloat OBMenuBarWindowArrowHeight;
extern const CGFloat OBMenuBarWindowArrowWidth;

Expand Down Expand Up @@ -102,6 +101,14 @@ extern const CGFloat OBMenuBarWindowArrowWidth;
is set to `YES`. */
@property (nonatomic, assign) BOOL attachedToMenuBar;

/** Whether the window should 'orderOut' if looses focus but the app remains active.

Setting this to NO helps in case the window should remain visible if it opens a child Window,
like a Preferences Window.
Default is YES which will orderOut this Window if it opens another window, even if it is a child Window.
*/
@property (nonatomic, assign) BOOL isAllowOrderOutWindowIfAppActive;

/** Whether to hide the "traffic light" window controls when the window is
attached to the menu bar (default is `YES`). */
@property (nonatomic, assign) BOOL hideWindowControlsWhenAttached;
Expand All @@ -114,6 +121,9 @@ extern const CGFloat OBMenuBarWindowArrowWidth;
30.0 pixels). */
@property (assign) CGFloat snapDistance;

/** Height of the Title Bar */
@property (nonatomic, assign) CGFloat windowTitleBarHeight;

/** The icon to show in the menu bar. The image should have a maximum height of
22 pixels (or 44 pixels for retina displays). */
@property (nonatomic, strong) NSImage *menuBarIcon;
Expand Down
69 changes: 47 additions & 22 deletions Classes/OBMenuBarWindow.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
NSString * const OBMenuBarWindowDidDetachFromMenuBar = @"OBMenuBarWindowDidDetachFromMenuBar";

// You can alter these constants to change the appearance of the window
const CGFloat OBMenuBarWindowTitleBarHeight = 22.0;
const CGFloat OBMenuBarWindowTitleBarDefaultHeight = 22.0;
const CGFloat OBMenuBarWindowArrowHeight = 10.0;
const CGFloat OBMenuBarWindowArrowWidth = 20.0;

Expand Down Expand Up @@ -85,6 +85,8 @@ - (id)initWithContentRect:(NSRect)contentRect
snapDistance = 30.0;
hideWindowControlsWhenAttached = YES;
isDetachable = YES;
self.isAllowOrderOutWindowIfAppActive = YES;
self.windowTitleBarHeight = OBMenuBarWindowTitleBarDefaultHeight;
[self initialSetup];
}
return self;
Expand Down Expand Up @@ -204,7 +206,7 @@ - (void)layoutContent
// Position the content view
NSRect contentViewFrame = [self.contentView frame];
CGFloat currentTopMargin = NSHeight(self.frame) - NSHeight(contentViewFrame);
CGFloat titleBarHeight = OBMenuBarWindowTitleBarHeight + (self.attachedToMenuBar ? OBMenuBarWindowArrowHeight : 0) + 1;
CGFloat titleBarHeight = self.windowTitleBarHeight + (self.attachedToMenuBar ? OBMenuBarWindowArrowHeight : 0) + 1;
CGFloat delta = titleBarHeight - currentTopMargin;
contentViewFrame.size.height -= delta;
[self.contentView setFrame:contentViewFrame];
Expand All @@ -228,7 +230,7 @@ - (void)setHasMenuBarIcon:(BOOL)flag
statusItemView = [[OBMenuBarWindowIconView alloc] initWithFrame:NSMakeRect(0, 0, (self.menuBarIcon ? self.menuBarIcon.size.width : thickness) + 6, thickness)];
statusItemView.menuBarWindow = self;
statusItem.view = statusItemView;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusItemViewDidMove:) name:NSWindowDidMoveNotification object:statusItem.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusItemViewDidMove:) name:NSWindowDidMoveNotification object:statusItemView.window];
}
else
{
Expand Down Expand Up @@ -416,26 +418,33 @@ - (void)setTitle:(NSString *)aString
- (NSRect)titleBarRect
{
return NSMakeRect(0,
self.frame.size.height - OBMenuBarWindowTitleBarHeight - (self.attachedToMenuBar ? OBMenuBarWindowArrowHeight : 0),
self.frame.size.height - self.windowTitleBarHeight - (self.attachedToMenuBar ? OBMenuBarWindowArrowHeight : 0),
self.frame.size.width,
OBMenuBarWindowTitleBarHeight + (self.attachedToMenuBar ? OBMenuBarWindowArrowHeight : 0));
self.windowTitleBarHeight + (self.attachedToMenuBar ? OBMenuBarWindowArrowHeight : 0));
}

- (NSRect)toolbarRect
{
if (self.attachedToMenuBar)
{
return NSMakeRect(0,
self.frame.size.height - OBMenuBarWindowTitleBarHeight - OBMenuBarWindowArrowHeight,
self.frame.size.height - self.windowTitleBarHeight - OBMenuBarWindowArrowHeight,
self.frame.size.width,
OBMenuBarWindowTitleBarHeight);
self.windowTitleBarHeight);
}
else
{
return [self titleBarRect];
}
}

#pragma mark - Property methods

- (void)setWindowTitleBarHeight:(CGFloat)toTitleBarHeight {
_windowTitleBarHeight = toTitleBarHeight;
[self layoutContent];
}

#pragma mark - Active/key events

- (BOOL)canBecomeKeyWindow
Expand All @@ -451,13 +460,16 @@ - (void)applicationDidChangeActiveStatus:(NSNotification *)aNotification
- (void)windowDidBecomeKey:(NSNotification *)aNotification
{
[[self.contentView superview] setNeedsDisplayInRect:[self titleBarRect]];
[self updateWindowPositionByMenuBar];
}

- (void)windowDidResignKey:(NSNotification *)aNotification
{
if (self.attachedToMenuBar)
{
[self orderOut:self];
if( self.isAllowOrderOutWindowIfAppActive || (!self.isAllowOrderOutWindowIfAppActive && ![NSApp keyWindow]) ) {
[self orderOut:self];
}
}
[[self.contentView superview] setNeedsDisplayInRect:[self titleBarRect]];
}
Expand All @@ -470,9 +482,20 @@ - (NSPoint)originForAttachedState
{
NSRect statusItemFrame = [[statusItemView window] frame];
NSPoint midPoint = NSMakePoint(NSMidX(statusItemFrame),
NSMinY(statusItemFrame));
return NSMakePoint(midPoint.x - (self.frame.size.width / 2),
midPoint.y - self.frame.size.height);
statusItemFrame.origin.y);

NSScreen *screenWithMenuBar = [[NSScreen screens] objectAtIndex:0];
if( screenWithMenuBar ) {
// correct the top position by the 'screen with the MenuBar's height
// workaround: without this the window will be off-placed when the user plugs in an external display,
// a display with more height
NSRect visibleRect = [screenWithMenuBar visibleFrame];
midPoint.y = visibleRect.size.height + visibleRect.origin.y;
}

NSPoint originPoint = NSMakePoint(midPoint.x - (self.frame.size.width / 2),
midPoint.y - self.frame.size.height);
return originPoint;
}
else
{
Expand All @@ -482,10 +505,7 @@ - (NSPoint)originForAttachedState

- (void)makeKeyAndOrderFront:(id)sender
{
if (self.attachedToMenuBar)
{
[self setFrameOrigin:[self originForAttachedState]];
}
[self updateWindowPositionByMenuBar];
[super makeKeyAndOrderFront:sender];
}

Expand Down Expand Up @@ -586,14 +606,19 @@ - (void)windowDidMove:(NSNotification *)aNotification
[self layoutContent];
}

- (void)statusItemViewDidMove:(NSNotification *)aNotification
- (void)updateWindowPositionByMenuBar
{
if (self.attachedToMenuBar)
{
[self setFrameOrigin:[self originForAttachedState]];
}
}

- (void)statusItemViewDidMove:(NSNotification *)aNotification
{
[self updateWindowPositionByMenuBar];
}

- (void)setFrame:(NSRect)frameRect display:(BOOL)flag
{
if ([self inLiveResize] && self.attachedToMenuBar)
Expand Down Expand Up @@ -698,7 +723,7 @@ - (void)drawRect:(NSRect)dirtyRect
NSRectFill(dirtyRect);

// Erase the default title bar
CGFloat titleBarHeight = OBMenuBarWindowTitleBarHeight + (isAttached ? OBMenuBarWindowArrowHeight : 0);
CGFloat titleBarHeight = window.windowTitleBarHeight + (isAttached ? OBMenuBarWindowArrowHeight : 0);
[[NSColor clearColor] set];
NSRectFillUsingOperation([window titleBarRect], NSCompositeClear);

Expand All @@ -723,9 +748,9 @@ - (void)drawRect:(NSRect)dirtyRect
NSPoint topRight = NSMakePoint(originX + width,
originY + height - (isAttached ? OBMenuBarWindowArrowHeight : 0));
NSPoint bottomLeft = NSMakePoint(originX,
originY + height - arrowHeight - OBMenuBarWindowTitleBarHeight);
originY + height - arrowHeight - window.windowTitleBarHeight);
NSPoint bottomRight = NSMakePoint(originX + width,
originY + height - arrowHeight - OBMenuBarWindowTitleBarHeight);
originY + height - arrowHeight - window.windowTitleBarHeight);

NSBezierPath *border = [NSBezierPath bezierPath];
[border moveToPoint:arrowPointLeft];
Expand All @@ -748,11 +773,11 @@ - (void)drawRect:(NSRect)dirtyRect
NSRect headingRect = NSMakeRect(originX,
originY + height - titleBarHeight,
width,
OBMenuBarWindowTitleBarHeight);
window.windowTitleBarHeight);
NSRect titleBarRect = NSMakeRect(originX,
originY + height - titleBarHeight,
width,
OBMenuBarWindowTitleBarHeight + OBMenuBarWindowArrowHeight);
window.windowTitleBarHeight + OBMenuBarWindowArrowHeight);

// Colors
NSColor *bottomColor, *topColor, *topColorTransparent;
Expand Down Expand Up @@ -818,7 +843,7 @@ - (void)drawRect:(NSRect)dirtyRect
// Draw separator line between the titlebar and the content view
[[NSColor colorWithCalibratedWhite:0.5 alpha:1.0] set];
NSRect separatorRect = NSMakeRect(originX,
originY + height - OBMenuBarWindowTitleBarHeight - (isAttached ? OBMenuBarWindowArrowHeight : 0) - 1,
originY + height - window.windowTitleBarHeight - (isAttached ? OBMenuBarWindowArrowHeight : 0) - 1,
width,
1);
NSRectFill(separatorRect);
Expand Down