From f9644463a9eedf2fe7427d574a4acdddf305fb2c Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Sat, 26 Mar 2016 19:29:24 -0700 Subject: [PATCH 1/4] Fix broken template image support in Tray icon Between Electron `0.30.x` and `0.37.x`, the tray icon stopped automatically inverting template images when highlighted. NSImageView normally uses the correct color for template images magicaly, but I think the addition of event handlers in the container view prevents the image view from determining highlight state. This PR switches to drawing the image manually. The `drawRect` function decides whether to use `image` or `alternateImage`(pressed image) and then if that image is marked as a template, it fills it with the same color used for the text before drawing it. --- atom/browser/ui/tray_icon_cocoa.mm | 64 +++++++++++++++++------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index d2a2fe83460e..d833851eac54 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -27,7 +27,6 @@ const CGFloat kVerticalTitleMargin = 2; BOOL inMouseEventSequence_; base::scoped_nsobject image_; base::scoped_nsobject alternateImage_; - base::scoped_nsobject image_view_; base::scoped_nsobject title_; base::scoped_nsobject statusItem_; } @@ -44,15 +43,6 @@ const CGFloat kVerticalTitleMargin = 2; inMouseEventSequence_ = NO; if ((self = [super initWithFrame: CGRectZero])) { - // Setup the image view. - image_view_.reset([[NSImageView alloc] initWithFrame: CGRectZero]); - [image_view_ setImageScaling:NSImageScaleNone]; - [image_view_ setImageAlignment:NSImageAlignCenter]; - [self addSubview:image_view_]; - - // Unregister image_view_ as a dragged destination, allows its parent view - // (StatusItemView) handle dragging events. - [image_view_ unregisterDraggedTypes]; [self registerForDraggedTypes: @[NSFilenamesPboardType]]; // Create the status item. @@ -69,7 +59,6 @@ const CGFloat kVerticalTitleMargin = 2; - (void)updateDimensions { NSStatusBar * bar = [NSStatusBar systemStatusBar]; - [image_view_ setFrame: NSMakeRect(0, 0, [self iconWidth], [bar thickness])]; [self setFrame: NSMakeRect(0, 0, [self fullWidth], [bar thickness])]; [self setNeedsDisplay:YES]; } @@ -85,28 +74,44 @@ const CGFloat kVerticalTitleMargin = 2; // | icon | title | /// ---------------- - // Draw background. BOOL highlight = [self shouldHighlight]; + BOOL highlightContent = highlight | [self isDarkMode]; CGFloat thickness = [[statusItem_ statusBar] thickness]; + + // Draw the system bar background [statusItem_ drawStatusBarBackgroundInRect:self.bounds withHighlight:highlight]; - // Make use of NSImageView to draw the image, which can correctly draw - // template image under dark menu bar. - if (inMouseEventSequence_ && alternateImage_ && - [image_view_ image] != alternateImage_.get()) { - [image_view_ setImage:alternateImage_]; - } else if ([image_view_ image] != image_.get()) { - [image_view_ setImage:image_]; + // Determine which image to use + NSImage * image = image_.get(); + if (inMouseEventSequence_ && alternateImage_) { + image = alternateImage_.get(); } + // Apply the higlight color if the image is a template image. When this moves + // to using the new [NSStatusItem button] API, this should work automagically. + if ([image isTemplate] == YES) { + NSImage * imageWithColor = [image copy]; + [imageWithColor lockFocus]; + [[self colorWithHighlight: highlightContent] set]; + NSRectFillUsingOperation(self.bounds, NSCompositeSourceAtop); + [imageWithColor unlockFocus]; + image = imageWithColor; + } + + // Draw the image + [image drawInRect: CGRectMake( + roundf(([self iconWidth] - [image size].width) / 2), + roundf((thickness - [image size].height) / 2), + [image size].width, + [image size].height + )]; + if (title_) { - // Highlight the text when icon is highlighted or in dark mode. - highlight |= [self isDarkMode]; // Draw title. NSRect titleDrawRect = NSMakeRect( [self iconWidth], -kVerticalTitleMargin, [self titleWidth], thickness); [title_ drawInRect:titleDrawRect - withAttributes:[self titleAttributesWithHighlight:highlight]]; + withAttributes:[self titleAttributesWithHighlight:highlightContent]]; } } @@ -157,14 +162,17 @@ const CGFloat kVerticalTitleMargin = 2; return [attributes size].width; } +- (NSColor*)colorWithHighlight:(BOOL)highlight +{ + return highlight ? + [NSColor whiteColor] : + [NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0]; +} + - (NSDictionary*)titleAttributesWithHighlight:(BOOL)highlight { - NSFont* font = [NSFont menuBarFontOfSize:0]; - NSColor* foregroundColor = highlight ? - [NSColor whiteColor] : - [NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0]; return @{ - NSFontAttributeName: font, - NSForegroundColorAttributeName: foregroundColor + NSFontAttributeName: [NSFont menuBarFontOfSize:0], + NSForegroundColorAttributeName: [self colorWithHighlight: highlight] }; } From 91457fe7393c6b206e64f795beea221686e64259 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Sat, 26 Mar 2016 19:40:52 -0700 Subject: [PATCH 2/4] Support images larger than self.bounds --- atom/browser/ui/tray_icon_cocoa.mm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index d833851eac54..6d7cdfaf9818 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -86,24 +86,24 @@ const CGFloat kVerticalTitleMargin = 2; if (inMouseEventSequence_ && alternateImage_) { image = alternateImage_.get(); } - // Apply the higlight color if the image is a template image. When this moves // to using the new [NSStatusItem button] API, this should work automagically. if ([image isTemplate] == YES) { NSImage * imageWithColor = [image copy]; [imageWithColor lockFocus]; [[self colorWithHighlight: highlightContent] set]; - NSRectFillUsingOperation(self.bounds, NSCompositeSourceAtop); + CGRect imageBounds = CGRectMake(0,0, image.size.width, image.size.height); + NSRectFillUsingOperation(imageBounds, NSCompositeSourceAtop); [imageWithColor unlockFocus]; image = imageWithColor; } // Draw the image [image drawInRect: CGRectMake( - roundf(([self iconWidth] - [image size].width) / 2), - roundf((thickness - [image size].height) / 2), - [image size].width, - [image size].height + roundf(([self iconWidth] - image.size.width) / 2), + roundf((thickness - image.size.height) / 2), + image.size.width, + image.size.height )]; if (title_) { From e0ee60f290573fa889dbe448b6dd2c4b00a97a8c Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 5 Apr 2016 11:38:58 -0700 Subject: [PATCH 3/4] Fix memory leak --- atom/browser/ui/tray_icon_cocoa.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 6d7cdfaf9818..ed1a774f2eb5 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -89,7 +89,7 @@ const CGFloat kVerticalTitleMargin = 2; // Apply the higlight color if the image is a template image. When this moves // to using the new [NSStatusItem button] API, this should work automagically. if ([image isTemplate] == YES) { - NSImage * imageWithColor = [image copy]; + NSImage * imageWithColor = [image copy] autorelease]; [imageWithColor lockFocus]; [[self colorWithHighlight: highlightContent] set]; CGRect imageBounds = CGRectMake(0,0, image.size.width, image.size.height); From 548febfa4cc20835e1d4d537a97ea5ff8983a305 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 7 Apr 2016 13:58:51 +0900 Subject: [PATCH 4/4] Fix style issues --- atom/browser/ui/tray_icon_cocoa.mm | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index ed1a774f2eb5..c3fa3f3b9272 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -78,18 +78,18 @@ const CGFloat kVerticalTitleMargin = 2; BOOL highlightContent = highlight | [self isDarkMode]; CGFloat thickness = [[statusItem_ statusBar] thickness]; - // Draw the system bar background + // Draw the system bar background. [statusItem_ drawStatusBarBackgroundInRect:self.bounds withHighlight:highlight]; - // Determine which image to use - NSImage * image = image_.get(); + // Determine which image to use. + NSImage* image = image_.get(); if (inMouseEventSequence_ && alternateImage_) { image = alternateImage_.get(); } // Apply the higlight color if the image is a template image. When this moves // to using the new [NSStatusItem button] API, this should work automagically. if ([image isTemplate] == YES) { - NSImage * imageWithColor = [image copy] autorelease]; + NSImage* imageWithColor = [[image copy] autorelease]; [imageWithColor lockFocus]; [[self colorWithHighlight: highlightContent] set]; CGRect imageBounds = CGRectMake(0,0, image.size.width, image.size.height); @@ -162,17 +162,16 @@ const CGFloat kVerticalTitleMargin = 2; return [attributes size].width; } -- (NSColor*)colorWithHighlight:(BOOL)highlight -{ +- (NSColor*)colorWithHighlight:(BOOL)highlight { return highlight ? - [NSColor whiteColor] : - [NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0]; + [NSColor whiteColor] : + [NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0]; } - (NSDictionary*)titleAttributesWithHighlight:(BOOL)highlight { return @{ - NSFontAttributeName: [NSFont menuBarFontOfSize:0], - NSForegroundColorAttributeName: [self colorWithHighlight: highlight] + NSFontAttributeName:[NSFont menuBarFontOfSize:0], + NSForegroundColorAttributeName:[self colorWithHighlight: highlight] }; }