Commit 85cd2a96 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

Delete Cocoa message_center and switch to the Views version.

This also removes some now-unused Cocoa control classes in //ui/base and
several unneeded resources.

Bug: 739386, 832676
Change-Id: I9289cc5613c4303521aaed9271ddc7574e2611a0
Reviewed-on: https://chromium-review.googlesource.com/c/1343055Reviewed-by: default avatarNico Weber <thakis@chromium.org>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609810}
parent 0fc5f9d3
...@@ -1817,6 +1817,8 @@ jumbo_split_static_library("ui") { ...@@ -1817,6 +1817,8 @@ jumbo_split_static_library("ui") {
"user_manager.h", "user_manager.h",
"views/external_protocol_dialog.cc", "views/external_protocol_dialog.cc",
"views/external_protocol_dialog.h", "views/external_protocol_dialog.h",
"views/message_center/popups_only_ui_delegate.cc",
"views/message_center/popups_only_ui_delegate.h",
"views/profiles/badged_profile_photo.cc", "views/profiles/badged_profile_photo.cc",
"views/profiles/badged_profile_photo.h", "views/profiles/badged_profile_photo.h",
"views/profiles/dice_accounts_menu.cc", "views/profiles/dice_accounts_menu.cc",
...@@ -2027,8 +2029,6 @@ jumbo_split_static_library("ui") { ...@@ -2027,8 +2029,6 @@ jumbo_split_static_library("ui") {
"cocoa/media_picker/desktop_media_picker_item.mm", "cocoa/media_picker/desktop_media_picker_item.mm",
"cocoa/native_window_tracker_cocoa.h", "cocoa/native_window_tracker_cocoa.h",
"cocoa/native_window_tracker_cocoa.mm", "cocoa/native_window_tracker_cocoa.mm",
"cocoa/notifications/message_center_bridge.h",
"cocoa/notifications/message_center_bridge.mm",
"cocoa/nsmenuitem_additions.h", "cocoa/nsmenuitem_additions.h",
"cocoa/nsmenuitem_additions.mm", "cocoa/nsmenuitem_additions.mm",
"cocoa/profiles/profile_menu_controller.h", "cocoa/profiles/profile_menu_controller.h",
...@@ -3035,8 +3035,6 @@ jumbo_split_static_library("ui") { ...@@ -3035,8 +3035,6 @@ jumbo_split_static_library("ui") {
"views/frame/browser_non_client_frame_view_factory_views.cc", "views/frame/browser_non_client_frame_view_factory_views.cc",
"views/frame/desktop_browser_frame_aura.cc", "views/frame/desktop_browser_frame_aura.cc",
"views/frame/desktop_browser_frame_aura.h", "views/frame/desktop_browser_frame_aura.h",
"views/message_center/popups_only_ui_delegate.cc",
"views/message_center/popups_only_ui_delegate.h",
] ]
} }
} }
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_MESSAGE_CENTER_BRIDGE_H_
#define CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_MESSAGE_CENTER_BRIDGE_H_
#import <AppKit/AppKit.h>
#include <memory>
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/notifications/popups_only_ui_controller.h"
#include "components/prefs/pref_member.h"
#include "ui/message_center/message_center.h"
@class MCPopupCollection;
namespace message_center {
class MessageCenter;
} // namespace message_center
// MessageCenterBridge is the owner of all the Cocoa UI objects for the
// message_center. It bridges C++ notifications from the PoupsOnlyUiController
// to the various UI objects.
class MessageCenterBridge : public PopupsOnlyUiController::Delegate {
public:
explicit MessageCenterBridge(message_center::MessageCenter* message_center);
~MessageCenterBridge() override;
// PopupsUiController::Delegate:
void ShowPopups() override;
void HidePopups() override;
private:
friend class MessageCenterBridgeTest;
// The global, singleton message center model object. Weak.
message_center::MessageCenter* const message_center_;
// Obj-C controller for the on-screen popup notifications.
base::scoped_nsobject<MCPopupCollection> popup_collection_;
DISALLOW_COPY_AND_ASSIGN(MessageCenterBridge);
};
#endif // CHROME_BROWSER_UI_COCOA_NOTIFICATIONS_MESSAGE_CENTER_BRIDGE_H_
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/cocoa/notifications/message_center_bridge.h"
#include "base/bind.h"
#include "base/i18n/number_formatting.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#import "ui/message_center/cocoa/popup_collection.h"
#include "ui/message_center/message_center.h"
// static
std::unique_ptr<PopupsOnlyUiController::Delegate>
PopupsOnlyUiController::CreateDelegate() {
return std::make_unique<MessageCenterBridge>(
message_center::MessageCenter::Get());
}
MessageCenterBridge::MessageCenterBridge(
message_center::MessageCenter* message_center)
: message_center_(message_center) {}
MessageCenterBridge::~MessageCenterBridge() {}
void MessageCenterBridge::ShowPopups() {
popup_collection_.reset(
[[MCPopupCollection alloc] initWithMessageCenter:message_center_]);
}
void MessageCenterBridge::HidePopups() {
popup_collection_.reset();
}
...@@ -116,10 +116,6 @@ jumbo_component("base") { ...@@ -116,10 +116,6 @@ jumbo_component("base") {
"cocoa/focus_tracker.mm", "cocoa/focus_tracker.mm",
"cocoa/focus_window_set.h", "cocoa/focus_window_set.h",
"cocoa/focus_window_set.mm", "cocoa/focus_window_set.mm",
"cocoa/hover_button.h",
"cocoa/hover_button.mm",
"cocoa/hover_image_button.h",
"cocoa/hover_image_button.mm",
"cocoa/menu_controller.h", "cocoa/menu_controller.h",
"cocoa/menu_controller.mm", "cocoa/menu_controller.mm",
"cocoa/nib_loading.h", "cocoa/nib_loading.h",
...@@ -851,8 +847,6 @@ test("ui_base_unittests") { ...@@ -851,8 +847,6 @@ test("ui_base_unittests") {
"cocoa/cocoa_base_utils_unittest.mm", "cocoa/cocoa_base_utils_unittest.mm",
"cocoa/constrained_window/constrained_window_animation_unittest.mm", "cocoa/constrained_window/constrained_window_animation_unittest.mm",
"cocoa/focus_tracker_unittest.mm", "cocoa/focus_tracker_unittest.mm",
"cocoa/hover_button_unittest.mm",
"cocoa/hover_image_button_unittest.mm",
"cocoa/menu_controller_unittest.mm", "cocoa/menu_controller_unittest.mm",
"cocoa/touch_bar_util_unittest.mm", "cocoa/touch_bar_util_unittest.mm",
"cocoa/tracking_area_unittest.mm", "cocoa/tracking_area_unittest.mm",
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_COCOA_HOVER_BUTTON_
#define UI_BASE_COCOA_HOVER_BUTTON_
#import <Cocoa/Cocoa.h>
#import "ui/base/cocoa/tracking_area.h"
#import "ui/base/ui_base_export.h"
@class HoverButtonCocoa;
// Assign an object which conforms to this protocol to a HoverButtonCocoa's
// dragDelegate property to make the button draggable.
UI_BASE_EXPORT
@protocol HoverButtonDragDelegate
// When the user performs a drag on the HoverButtonCocoa, this method will be
// called with the button and the mouse down event. The delegate is expected to
// begin a drag by calling -[NSView beginDraggingSessionWithItems:event:source:]
// with the event or run a nested tracking loop. When it returns, the
// HoverButtonCocoa returns to kHoverStateNone and stops tracking the mouse.
- (void)beginDragFromHoverButton:(HoverButtonCocoa*)button
event:(NSEvent*)event;
@end
// A button that changes when you hover over it and click it.
UI_BASE_EXPORT
@interface HoverButtonCocoa : NSButton {
@protected
// Enumeration of the hover states that the close button can be in at any one
// time. The button cannot be in more than one hover state at a time.
enum CloseButtonHoverState {
kHoverStateNone = 0,
kHoverStateMouseOver = 1,
kHoverStateMouseDown = 2
};
CloseButtonHoverState hoverState_;
@private
// Tracking area for button mouseover states. Nil if not enabled.
ui::ScopedCrTrackingArea trackingArea_;
BOOL mouseDown_;
BOOL sendActionOnMouseDown_;
}
@property(nonatomic) CloseButtonHoverState hoverState;
// Enables or disables the tracking for the button.
@property(nonatomic) BOOL trackingEnabled;
// Assign an object to make the button a drag source.
@property(nonatomic, assign) id<HoverButtonDragDelegate> dragDelegate;
// Enables or disables sending the action on mouse down event.
@property(nonatomic) BOOL sendActionOnMouseDown;
// An NSRect in the view's coordinate space which is used for hover and hit
// testing. Default value is NSZeroRect, which makes the hitbox equal to the
// view's bounds. May be overridden by subclasses. Example: A button in the
// corner of a fullscreen window might extend its hitbox to the edges of the
// window so that it can be clicked more easily (Fitts's law).
@property(readonly, nonatomic) NSRect hitbox;
// Common initialization called from initWithFrame: and awakeFromNib.
// Subclassers should call [super commonInit].
- (void)commonInit;
// Text that would be announced by screen readers.
- (void)setAccessibilityTitle:(NSString*)accessibilityTitle;
// Checks to see whether the mouse is in the button's bounds and update
// the image in case it gets out of sync. This occurs to the close button
// when you close a tab so the tab to the left of it takes its place, and
// drag the button without moving the mouse before you press the button down.
- (void)checkImageState;
@end
#endif // UI_BASE_COCOA_HOVER_BUTTON_
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/base/cocoa/hover_button.h"
#include <cmath>
namespace {
// Distance to start a drag when a dragDelegate is assigned.
constexpr CGFloat kDragDistance = 5;
} // namespace
@implementation HoverButtonCocoa
@synthesize hoverState = hoverState_;
@synthesize trackingEnabled = trackingEnabled_;
@synthesize dragDelegate = dragDelegate_;
@synthesize sendActionOnMouseDown = sendActionOnMouseDown_;
- (instancetype)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) {
[self commonInit];
}
return self;
}
- (void)awakeFromNib {
[self commonInit];
}
- (void)commonInit {
self.hoverState = kHoverStateNone;
self.trackingEnabled = YES;
}
- (void)dealloc {
self.trackingEnabled = NO;
[super dealloc];
}
- (NSRect)hitbox {
return NSZeroRect;
}
- (void)setTrackingEnabled:(BOOL)trackingEnabled {
if (trackingEnabled == trackingEnabled_)
return;
trackingEnabled_ = trackingEnabled;
[self updateTrackingAreas];
}
- (void)setEnabled:(BOOL)enabled {
if (enabled == self.enabled)
return;
super.enabled = enabled;
[self updateTrackingAreas];
}
- (void)mouseEntered:(NSEvent*)theEvent {
if (trackingArea_.get())
self.hoverState = kHoverStateMouseOver;
}
- (void)mouseMoved:(NSEvent*)theEvent {
[self checkImageState];
}
- (void)mouseExited:(NSEvent*)theEvent {
if (trackingArea_.get())
self.hoverState = kHoverStateNone;
}
- (void)mouseDown:(NSEvent*)theEvent {
if (!self.enabled)
return;
mouseDown_ = YES;
self.hoverState = kHoverStateMouseDown;
if (sendActionOnMouseDown_)
[self sendAction:self.action to:self.target];
// The hover button needs to hold onto itself here for a bit. Otherwise,
// it can be freed while in the tracking loop below.
// http://crbug.com/28220
base::scoped_nsobject<HoverButtonCocoa> myself([self retain]);
// Begin tracking the mouse.
if ([theEvent type] == NSLeftMouseDown) {
NSWindow* window = [self window];
NSEvent* nextEvent = nil;
// For the tracking loop ignore key events so that they don't pile up in
// the queue and get processed after the user releases the mouse.
const NSEventMask eventMask = (NSLeftMouseDraggedMask | NSLeftMouseUpMask |
NSKeyDownMask | NSKeyUpMask);
while ((nextEvent = [window nextEventMatchingMask:eventMask])) {
if ([nextEvent type] == NSLeftMouseUp)
break;
// Update the image state, which will change if the user moves the mouse
// into or out of the button.
[self checkImageState];
if (dragDelegate_ && [nextEvent type] == NSLeftMouseDragged) {
const NSPoint startPos = [theEvent locationInWindow];
const NSPoint pos = [nextEvent locationInWindow];
if (std::abs(startPos.x - pos.x) > kDragDistance ||
std::abs(startPos.y - pos.y) > kDragDistance) {
[dragDelegate_ beginDragFromHoverButton:self event:nextEvent];
mouseDown_ = NO;
self.hoverState = kHoverStateNone;
return;
}
}
}
}
// If the mouse is still over the button, it means the user clicked the
// button.
if (!sendActionOnMouseDown_ && self.hoverState == kHoverStateMouseDown) {
[self sendAction:self.action to:self.target];
}
// Clean up.
mouseDown_ = NO;
[self checkImageState];
}
- (void)setAccessibilityTitle:(NSString*)accessibilityTitle {
NSCell* cell = [self cell];
[cell accessibilitySetOverrideValue:accessibilityTitle
forAttribute:NSAccessibilityTitleAttribute];
}
- (void)updateTrackingAreas {
if (trackingEnabled_ && self.enabled) {
NSRect hitbox = self.hitbox;
if (CrTrackingArea* trackingArea = trackingArea_.get()) {
if (NSEqualRects(trackingArea.rect, hitbox))
return;
[self removeTrackingArea:trackingArea];
}
trackingArea_.reset([[CrTrackingArea alloc]
initWithRect:hitbox
options:NSTrackingMouseEnteredAndExited |
NSTrackingMouseMoved |
NSTrackingActiveAlways |
(NSIsEmptyRect(hitbox) ? NSTrackingInVisibleRect : 0)
owner:self
userInfo:nil]);
[self addTrackingArea:trackingArea_.get()];
// If you have a separate window that overlaps the close button, and you
// move the mouse directly over the close button without entering another
// part of the tab strip, we don't get any mouseEntered event since the
// tracking area was disabled when we entered.
// Done with a delay of 0 because sometimes an event appears to be missed
// between the activation of the tracking area and the call to
// checkImageState resulting in the button state being incorrect.
[self performSelector:@selector(checkImageState)
withObject:nil
afterDelay:0];
} else {
if (trackingArea_.get()) {
self.hoverState = kHoverStateNone;
[self removeTrackingArea:trackingArea_.get()];
trackingArea_.reset(nil);
}
}
[super updateTrackingAreas];
[self checkImageState];
}
- (void)checkImageState {
if (!trackingArea_.get())
return;
NSEvent* currentEvent = [NSApp currentEvent];
if (!currentEvent || currentEvent.window != self.window)
return;
// Update the button's state if the button has moved.
const NSPoint mouseLoc =
[self.superview convertPoint:currentEvent.locationInWindow fromView:nil];
BOOL mouseInBounds = [self hitTest:mouseLoc] != nil;
if (mouseDown_ && mouseInBounds) {
self.hoverState = kHoverStateMouseDown;
} else {
self.hoverState = mouseInBounds ? kHoverStateMouseOver : kHoverStateNone;
}
}
- (void)setHoverState:(CloseButtonHoverState)hoverState {
if (hoverState == hoverState_)
return;
hoverState_ = hoverState;
self.needsDisplay = YES;
}
- (NSView*)hitTest:(NSPoint)point {
if (NSPointInRect([self.superview convertPoint:point toView:self],
self.hitbox)) {
return self;
}
return [super hitTest:point];
}
@end
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/base/cocoa/hover_button.h"
#import <Cocoa/Cocoa.h>
#import "ui/base/test/cocoa_helper.h"
#import "ui/events/test/cocoa_test_event_utils.h"
@interface TestHoverButton : HoverButtonCocoa
@property(readwrite, nonatomic) NSRect hitbox;
@end
@implementation TestHoverButton
@synthesize hitbox = hitbox_;
- (void)setHitbox:(NSRect)hitbox {
hitbox_ = hitbox;
[self updateTrackingAreas];
}
@end
@interface HoverButtonTestTarget : NSObject
@property(nonatomic, copy) void (^actionHandler)(id);
@end
@implementation HoverButtonTestTarget
@synthesize actionHandler = actionHandler_;
- (void)dealloc {
[actionHandler_ release];
[super dealloc];
}
- (IBAction)action:(id)sender {
actionHandler_(sender);
}
@end
@interface HoverButtonTestDragDelegate : NSObject<HoverButtonDragDelegate>
@property(nonatomic, copy) void (^dragHandler)(HoverButtonCocoa*, NSEvent*);
@end
@implementation HoverButtonTestDragDelegate
@synthesize dragHandler = dragHandler_;
- (void)dealloc {
[dragHandler_ release];
[super dealloc];
}
- (void)beginDragFromHoverButton:(HoverButtonCocoa*)button
event:(NSEvent*)event {
dragHandler_(button, event);
}
@end
namespace {
class HoverButtonTest : public ui::CocoaTest {
public:
HoverButtonTest() {
NSRect frame = NSMakeRect(0, 0, 20, 20);
base::scoped_nsobject<TestHoverButton> button(
[[TestHoverButton alloc] initWithFrame:frame]);
button_ = button;
target_.reset([[HoverButtonTestTarget alloc] init]);
button_.target = target_;
button_.action = @selector(action:);
[[test_window() contentView] addSubview:button_];
}
protected:
void HoverAndExpect(CloseButtonHoverState hoverState) {
EXPECT_EQ(kHoverStateNone, button_.hoverState);
[button_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
EXPECT_EQ(hoverState, button_.hoverState);
[button_ mouseExited:cocoa_test_event_utils::ExitEvent()];
EXPECT_EQ(kHoverStateNone, button_.hoverState);
}
bool HandleMouseDown(NSEvent* mouseDownEvent) {
__block bool action_sent = false;
target_.get().actionHandler = ^(id sender) {
action_sent = true;
EXPECT_EQ(kHoverStateMouseDown, button_.hoverState);
};
[NSApp sendEvent:mouseDownEvent];
target_.get().actionHandler = nil;
return action_sent;
}
TestHoverButton* button_; // Weak, owned by test_window().
base::scoped_nsobject<HoverButtonTestTarget> target_;
};
TEST_VIEW(HoverButtonTest, button_)
TEST_F(HoverButtonTest, Hover) {
EXPECT_EQ(kHoverStateNone, button_.hoverState);
// Default
HoverAndExpect(kHoverStateMouseOver);
// Tracking disabled
button_.trackingEnabled = NO;
HoverAndExpect(kHoverStateNone);
button_.trackingEnabled = YES;
// Button disabled
button_.enabled = NO;
HoverAndExpect(kHoverStateNone);
button_.enabled = YES;
// Back to normal
HoverAndExpect(kHoverStateMouseOver);
}
TEST_F(HoverButtonTest, Click) {
EXPECT_EQ(kHoverStateNone, button_.hoverState);
const auto click = cocoa_test_event_utils::MouseClickInView(button_, 1);
[NSApp postEvent:click.second atStart:YES];
EXPECT_TRUE(HandleMouseDown(click.first));
button_.enabled = NO;
EXPECT_FALSE(HandleMouseDown(click.first));
EXPECT_EQ(kHoverStateNone, button_.hoverState);
}
TEST_F(HoverButtonTest, CustomHitbox) {
NSRect hitbox = button_.frame;
hitbox.size.width += 10;
NSPoint inside_hit_point =
NSMakePoint(NSMaxX(button_.frame) + 5, NSMidY(button_.frame));
NSPoint outside_hit_point =
NSMakePoint(inside_hit_point.x + 10, inside_hit_point.y);
{
NSRect trackingRect = button_.trackingAreas[0].rect;
EXPECT_FALSE(NSPointInRect(inside_hit_point, trackingRect));
EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
EXPECT_NE(button_, [button_ hitTest:inside_hit_point]);
EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
}
button_.hitbox = hitbox;
{
NSRect trackingRect = button_.trackingAreas[0].rect;
EXPECT_TRUE(NSPointInRect(inside_hit_point, trackingRect));
EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
EXPECT_EQ(button_, [button_ hitTest:inside_hit_point]);
EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
}
button_.hitbox = NSZeroRect;
{
NSRect trackingRect = button_.trackingAreas[0].rect;
EXPECT_FALSE(NSPointInRect(inside_hit_point, trackingRect));
EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
EXPECT_NE(button_, [button_ hitTest:inside_hit_point]);
EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
}
}
TEST_F(HoverButtonTest, DragDelegate) {
base::scoped_nsobject<HoverButtonTestDragDelegate> dragDelegate(
[[HoverButtonTestDragDelegate alloc] init]);
__block bool dragged = false;
dragDelegate.get().dragHandler = ^(HoverButtonCocoa* button, NSEvent* event) {
dragged = true;
};
button_.dragDelegate = dragDelegate;
const auto click = cocoa_test_event_utils::MouseClickInView(button_, 1);
NSPoint targetPoint = click.first.locationInWindow;
targetPoint.x += 5; // *Not* enough to trigger a drag.
[NSApp postEvent:cocoa_test_event_utils::MouseEventAtPointInWindow(
targetPoint, NSEventTypeLeftMouseDragged,
[button_ window], 1)
atStart:NO];
[NSApp postEvent:click.second atStart:NO];
EXPECT_TRUE(HandleMouseDown(click.first));
EXPECT_FALSE(dragged);
targetPoint.x += 1; // Now it's enough to trigger a drag.
[NSApp postEvent:cocoa_test_event_utils::MouseEventAtPointInWindow(
targetPoint, NSEventTypeLeftMouseDragged,
[button_ window], 1)
atStart:NO];
[NSApp postEvent:click.second atStart:NO];
EXPECT_FALSE(HandleMouseDown(click.first));
EXPECT_TRUE(dragged);
}
} // namespace
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_COCOA_HOVER_IMAGE_BUTTON_H_
#define UI_BASE_COCOA_HOVER_IMAGE_BUTTON_H_
#import <Cocoa/Cocoa.h>
#import "base/mac/scoped_nsobject.h"
#import "ui/base/cocoa/hover_button.h"
#include "ui/base/ui_base_export.h"
// A button that changes images when you hover over it and click it.
UI_BASE_EXPORT
@interface HoverImageButton : HoverButtonCocoa {
@private
base::scoped_nsobject<NSImage> defaultImage_;
base::scoped_nsobject<NSImage> hoverImage_;
base::scoped_nsobject<NSImage> pressedImage_;
}
// Disables a click within the button from activating the application.
@property(nonatomic) BOOL disableActivationOnClick;
// Sets the default image.
- (void)setDefaultImage:(NSImage*)image;
// Sets the hover image.
- (void)setHoverImage:(NSImage*)image;
// Sets the pressed image.
- (void)setPressedImage:(NSImage*)image;
@end
#endif // UI_BASE_COCOA_HOVER_IMAGE_BUTTON_H_
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/base/cocoa/hover_image_button.h"
@implementation HoverImageButton
@synthesize disableActivationOnClick = disableActivationOnClick_;
- (void)drawRect:(NSRect)rect {
if (hoverState_ == kHoverStateMouseDown && pressedImage_) {
[super setImage:pressedImage_.get()];
} else if (hoverState_ == kHoverStateMouseOver && hoverImage_) {
[super setImage:hoverImage_.get()];
} else {
[super setImage:defaultImage_.get()];
}
[super drawRect:rect];
}
- (void)setDefaultImage:(NSImage*)image {
defaultImage_.reset([image retain]);
}
- (void)setHoverImage:(NSImage*)image {
hoverImage_.reset([image retain]);
}
- (void)setPressedImage:(NSImage*)image {
pressedImage_.reset([image retain]);
}
- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)theEvent {
// To avoid activating the app on a click inside the button, first tell
// the Appkit not to immediately order the HoverImageButton's window front in
// response to theEvent.
return disableActivationOnClick_;
}
- (void)mouseDown:(NSEvent*)mouseDownEvent {
// If disabling activation on click, tell the Appkit to cancel window ordering
// for this mouse down.
if (disableActivationOnClick_) {
[[NSApplication sharedApplication] preventWindowOrdering];
}
[super mouseDown:mouseDownEvent];
}
@end
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/base/cocoa/hover_image_button.h"
#import "base/mac/scoped_nsobject.h"
#import "ui/base/test/cocoa_helper.h"
#include "ui/events/test/cocoa_test_event_utils.h"
namespace {
class HoverImageButtonTest : public ui::CocoaTest {
public:
HoverImageButtonTest() {
NSRect content_frame = [[test_window() contentView] frame];
base::scoped_nsobject<HoverImageButton> button(
[[HoverImageButton alloc] initWithFrame:content_frame]);
button_ = button.get();
[[test_window() contentView] addSubview:button_];
}
void DrawRect() {
[button_ lockFocus];
[button_ drawRect:[button_ bounds]];
[button_ unlockFocus];
}
HoverImageButton* button_;
};
// Test mouse events.
TEST_F(HoverImageButtonTest, ImageSwap) {
NSImage* image = [NSImage imageNamed:NSImageNameStatusAvailable];
NSImage* hover = [NSImage imageNamed:NSImageNameStatusNone];
[button_ setDefaultImage:image];
[button_ setHoverImage:hover];
[button_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
DrawRect();
EXPECT_EQ([button_ image], hover);
[button_ mouseExited:cocoa_test_event_utils::ExitEvent()];
DrawRect();
EXPECT_NE([button_ image], hover);
EXPECT_EQ([button_ image], image);
}
} // namespace
...@@ -62,14 +62,6 @@ jumbo_component("message_center") { ...@@ -62,14 +62,6 @@ jumbo_component("message_center") {
"//build/config/compiler:no_size_t_to_int_warning", "//build/config/compiler:no_size_t_to_int_warning",
] ]
sources = [ sources = [
"cocoa/notification_controller.h",
"cocoa/notification_controller.mm",
"cocoa/opaque_views.h",
"cocoa/opaque_views.mm",
"cocoa/popup_collection.h",
"cocoa/popup_collection.mm",
"cocoa/popup_controller.h",
"cocoa/popup_controller.mm",
"lock_screen/empty_lock_screen_controller.cc", "lock_screen/empty_lock_screen_controller.cc",
"lock_screen/empty_lock_screen_controller.h", "lock_screen/empty_lock_screen_controller.h",
"lock_screen/lock_screen_controller.h", "lock_screen/lock_screen_controller.h",
...@@ -103,13 +95,6 @@ jumbo_component("message_center") { ...@@ -103,13 +95,6 @@ jumbo_component("message_center") {
] ]
} }
if (is_mac) {
libs = [
"AppKit.framework",
"Foundation.framework",
]
}
if (toolkit_views) { if (toolkit_views) {
sources += [ sources += [
"views/bounded_label.cc", "views/bounded_label.cc",
...@@ -193,9 +178,6 @@ if (enable_message_center) { ...@@ -193,9 +178,6 @@ if (enable_message_center) {
test("message_center_unittests") { test("message_center_unittests") {
sources = [ sources = [
"cocoa/notification_controller_unittest.mm",
"cocoa/popup_collection_unittest.mm",
"cocoa/popup_controller_unittest.mm",
"lock_screen/fake_lock_screen_controller.cc", "lock_screen/fake_lock_screen_controller.cc",
"lock_screen/fake_lock_screen_controller.h", "lock_screen/fake_lock_screen_controller.h",
"message_center_impl_unittest.cc", "message_center_impl_unittest.cc",
...@@ -242,10 +224,6 @@ if (enable_message_center) { ...@@ -242,10 +224,6 @@ if (enable_message_center) {
] ]
} }
if (is_mac) {
deps += [ "//ui/gfx:test_support" ]
}
if (toolkit_views) { if (toolkit_views) {
sources += [ sources += [
"views/bounded_label_unittest.cc", "views/bounded_label_unittest.cc",
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_MESSAGE_CENTER_COCOA_NOTIFICATION_CONTROLLER_H_
#define UI_MESSAGE_CENTER_COCOA_NOTIFICATION_CONTROLLER_H_
#import <Cocoa/Cocoa.h>
#include <string>
#import "base/mac/scoped_nsobject.h"
#include "ui/message_center/message_center_export.h"
namespace message_center {
class MessageCenter;
class Notification;
}
@class HoverImageButton;
namespace message_center {
// A struct that can hold all the temporary frames
// created when adjusting a view
struct NotificationLayoutParams {
NSRect rootFrame;
NSRect titleFrame;
NSRect messageFrame;
NSRect contextMessageFrame;
NSRect settingsButtonFrame;
NSRect listFrame;
NSRect progressBarFrame;
};
}
// The base view controller class for notifications. A notification at minimum
// has an image, title, body, and close button. This controller can be used as
// the content for both a popup bubble and a view in the notification tray.
MESSAGE_CENTER_EXPORT
@interface MCNotificationController : NSViewController {
@protected
// The message object. Weak.
const message_center::Notification* notification_;
// A copy of the notification ID.
std::string notificationID_;
// Controller of the notifications, where action messages are forwarded. Weak.
message_center::MessageCenter* messageCenter_;
// The button that invokes |-close:|, in the upper-right corner.
base::scoped_nsobject<HoverImageButton> closeButton_;
// The button that invokes |-settingsClicked:|, in the bottom right corner of
// the context message.
base::scoped_nsobject<HoverImageButton> settingsButton_;
// The small icon associated with the notification, on the bottom right.
base::scoped_nsobject<NSImageView> smallImage_;
// The large icon associated with the notification, on the left side.
base::scoped_nsobject<NSImageView> icon_;
// The title of the message.
base::scoped_nsobject<NSTextView> title_;
// Body text of the message. Hidden for list notifications.
base::scoped_nsobject<NSTextView> message_;
// Context-giving text of the message. Alternate font used to distinguish it.
base::scoped_nsobject<NSTextView> contextMessage_;
// Container for optional list view that contains multiple items.
base::scoped_nsobject<NSView> listView_;
// Container for optional progress bar view.
base::scoped_nsobject<NSProgressIndicator> progressBarView_;
// Container for optional items at the bottom of the notification.
base::scoped_nsobject<NSView> bottomView_;
}
// Creates a new controller for a given notification.
- (id)initWithNotification:(const message_center::Notification*)notification
messageCenter:(message_center::MessageCenter*)messageCenter;
// If the model object changes, this method will update the views to reflect
// the new model object. Returns the updated frame of the notification.
- (NSRect)updateNotification:(const message_center::Notification*)notification;
// Action for clicking on the notification's |closeButton_|.
- (void)close:(id)sender;
// Action for clicking on the notification's |settingsButton_|.
- (void)settingsClicked:(id)sender;
// Accessor for the notification.
- (const message_center::Notification*)notification;
// Gets the notification ID. This string is owned by the NotificationController
// rather than the model object, so it's safe to use after the Notification has
// been deleted.
- (const std::string&)notificationID;
// Called when the user clicks within the notification view.
- (void)notificationClicked;
// Adjust the position and height of all the internal frames by |delta|.
- (void)adjustFrameHeight:(message_center::NotificationLayoutParams*)frames
delta:(CGFloat)delta;
@end
@interface MCNotificationController (TestingInterface)
- (NSImageView*)smallImageView;
- (NSImageView*)iconView;
@end
#endif // UI_MESSAGE_CENTER_COCOA_NOTIFICATION_CONTROLLER_H_
This diff is collapsed.
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_MESSAGE_CENTER_COCOA_OPAQUE_VIEWS_H_
#define UI_MESSAGE_CENTER_COCOA_OPAQUE_VIEWS_H_
#import <Cocoa/Cocoa.h>
#include "base/mac/scoped_nsobject.h"
// MCDropDown is the same as an NSPopupButton except that it fills its
// background with a settable color.
@interface MCDropDown : NSPopUpButton {
@private
base::scoped_nsobject<NSColor> backgroundColor_;
}
// Gets and sets the bubble's background color.
- (NSColor*)backgroundColor;
- (void)setBackgroundColor:(NSColor*)backgroundColor;
@end
// MCTextField fills its background with an opaque color. It also configures
// the view to have a plan appearance, without bezel, border, editing, etc.
@interface MCTextField : NSTextField {
@private
base::scoped_nsobject<NSColor> backgroundColor_;
}
// Use this method to create the text field. The color is required so it
// can correctly subpixel antialias.
- (id)initWithFrame:(NSRect)frameRect backgroundColor:(NSColor*)color;
@end
#endif // UI_MESSAGE_CENTER_COCOA_OPAQUE_VIEWS_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/message_center/cocoa/opaque_views.h"
@implementation MCDropDown
// The view must be opaque to render subpixel antialiasing.
- (BOOL)isOpaque {
return YES;
}
// The view must also fill its background to render subpixel antialiasing.
- (void)drawRect:(NSRect)dirtyRect {
[backgroundColor_ set];
NSRectFill(dirtyRect);
[super drawRect:dirtyRect];
}
- (NSColor*)backgroundColor {
return backgroundColor_;
}
- (void)setBackgroundColor:(NSColor*)backgroundColor {
backgroundColor_.reset([backgroundColor retain]);
}
@end
@implementation MCTextField
- (id)initWithFrame:(NSRect)frameRect backgroundColor:(NSColor*)color {
self = [self initWithFrame:frameRect];
if (self) {
[self setBackgroundColor:color];
backgroundColor_.reset([color retain]);
}
return self;
}
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self) {
[self setAutoresizingMask:NSViewMinYMargin];
[self setBezeled:NO];
[self setBordered:NO];
[self setEditable:NO];
[self setSelectable:NO];
[self setDrawsBackground:YES];
}
return self;
}
// The view must be opaque to render subpixel antialiasing.
- (BOOL)isOpaque {
return YES;
}
// The view must also fill its background to render subpixel antialiasing.
- (void)drawRect:(NSRect)dirtyRect {
[backgroundColor_ set];
NSRectFill(dirtyRect);
[super drawRect:dirtyRect];
}
@end
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_MESSAGE_CENTER_COCOA_POPUP_COLLECTION_H_
#define UI_MESSAGE_CENTER_COCOA_POPUP_COLLECTION_H_
#import <Cocoa/Cocoa.h>
#include <memory>
#include <set>
#include "base/mac/scoped_block.h"
#import "base/mac/scoped_nsobject.h"
#include "ui/message_center/message_center_export.h"
namespace message_center {
class MessageCenter;
class MessageCenterObserver;
}
namespace message_center {
typedef void(^AnimationEndedCallback)();
}
// A popup collection interfaces with the MessageCenter as an observer. It will
// arrange notifications on the screen as popups, starting in the upper-right
// corner, going to the bottom of the screen. This class maintains ownership of
// the Cocoa controllers and windows of the notifications.
MESSAGE_CENTER_EXPORT
@interface MCPopupCollection : NSObject {
@private
// The message center that is responsible for the notifications. Weak, global.
message_center::MessageCenter* messageCenter_;
// MessageCenterObserver implementation.
std::unique_ptr<message_center::MessageCenterObserver> observer_;
// Array of all on-screen popup notifications.
base::scoped_nsobject<NSMutableArray> popups_;
// Array of all on-screen popup notifications that are being faded out
// for removal.
base::scoped_nsobject<NSMutableArray> popupsBeingRemoved_;
// For testing only. If not a zero rect, this is the screen size to use
// for laying out popups.
NSRect testingScreenFrame_;
// The duration of the popup animation, in the number of seconds.
NSTimeInterval popupAnimationDuration_;
// Set of notification IDs for those popups to be updated when all existing
// animations end.
std::set<std::string> pendingUpdateNotificationIDs_;
// Set of notification IDs for those popups to be closed when all existing
// animations end.
std::set<std::string> pendingRemoveNotificationIDs_;
// Set of notification IDs for those popups that are being animated due to
// showing, bounds change or closing.
std::set<std::string> animatingNotificationIDs_;
// For testing only. If set, the callback will be called when the animation
// ends.
base::mac::ScopedBlock<message_center::AnimationEndedCallback>
testingAnimationEndedCallback_;
}
// Designated initializer that construct an instance to observe |messageCenter|.
- (id)initWithMessageCenter:(message_center::MessageCenter*)messageCenter;
// Returns true if an animation is being played.
- (BOOL)isAnimating;
// Returns the duration of the popup animation.
- (NSTimeInterval)popupAnimationDuration;
// Called when the animation of a popup ends.
- (void)onPopupAnimationEnded:(const std::string&)notificationID;
@end
@interface MCPopupCollection (ExposedForTesting)
- (NSArray*)popups;
// Setter for the testingScreenFrame_.
- (void)setScreenFrame:(NSRect)frame;
// Setter for changing the animation duration. The testing code could set it
// to a very small value to expedite the test running.
- (void)setAnimationDuration:(NSTimeInterval)duration;
// Setter for testingAnimationEndedCallback_. The testing code could set it
// to get called back when the animation ends.
- (void)setAnimationEndedCallback:
(message_center::AnimationEndedCallback)callback;
@end
#endif // UI_MESSAGE_CENTER_COCOA_POPUP_COLLECTION_H_
This diff is collapsed.
This diff is collapsed.
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_MESSAGE_CENTER_COCOA_POPUP_CONTROLLER_H_
#define UI_MESSAGE_CENTER_COCOA_POPUP_CONTROLLER_H_
#import <Cocoa/Cocoa.h>
#include <string>
#import "base/mac/scoped_nsobject.h"
#import "ui/base/cocoa/tracking_area.h"
#include "ui/message_center/message_center_export.h"
namespace message_center {
class MessageCenter;
class Notification;
}
@class MCNotificationController;
@class MCPopupCollection;
// A window controller that hosts a notification as a popup balloon on the
// user's desktop. The window controller manages its lifetime because the
// popup collection will be destructed when the last popup is closed.
MESSAGE_CENTER_EXPORT
@interface MCPopupController : NSWindowController<NSAnimationDelegate> {
@private
// Global message center. Weak.
message_center::MessageCenter* messageCenter_;
// The collection that contains the popup. Weak.
MCPopupCollection* popupCollection_;
// The view controller that provide's the popup content view.
base::scoped_nsobject<MCNotificationController> notificationController_;
// If the swipe-away gesture received NSEventPhaseEnded.
BOOL swipeGestureEnded_;
// The frame of the popup before any swipe animation started. Used to
// calculate the animating position of the window when swiping away.
NSRect originalFrame_;
// Is the popup currently being closed?
BOOL isClosing_;
#ifndef NDEBUG
// Has the popup been closed before being dealloc-ed.
BOOL hasBeenClosed_;
#endif
// The current bounds of the popup frame if no animation is playing.
// Otherwise, it is the target bounds of the popup frame.
NSRect bounds_;
// Used to play animation when the popup shows, changes bounds and closes.
base::scoped_nsobject<NSViewAnimation> boundsAnimation_;
// Used to track the popup for mouse entered and exited events.
ui::ScopedCrTrackingArea trackingArea_;
}
// Designated initializer.
- (id)initWithNotification:(const message_center::Notification*)notification
messageCenter:(message_center::MessageCenter*)messageCenter
popupCollection:(MCPopupCollection*)popupCollection;
// Accessor for the view controller.
- (MCNotificationController*)notificationController;
// Accessor for the notification model object.
- (const message_center::Notification*)notification;
// Gets the notification ID. This string is owned by the NotificationController
// rather than the model object, so it's safe to use after the Notification has
// been deleted.
- (const std::string&)notificationID;
// Shows the window with the sliding animation.
- (void)showWithAnimation:(NSRect)newBounds;
// Closes the window with the fade-out animation.
- (void)closeWithAnimation;
// Tells that the popupCollection_ is gone.
- (void)markPopupCollectionGone;
// Returns the window bounds. This is the target bounds to go to if the bounds
// animation is playing.
- (NSRect)bounds;
// Changes the window bounds with animation.
- (void)setBounds:(NSRect)newBounds;
@end
#endif // UI_MESSAGE_CENTER_COCOA_POPUP_CONTROLLER_H_
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/message_center/cocoa/popup_controller.h"
#include <cmath>
#import "base/mac/foundation_util.h"
#import "base/mac/sdk_forward_declarations.h"
#import "ui/base/cocoa/window_size_constants.h"
#import "ui/message_center/cocoa/notification_controller.h"
#import "ui/message_center/cocoa/popup_collection.h"
#include "ui/message_center/message_center.h"
////////////////////////////////////////////////////////////////////////////////
@interface MCPopupController (Private)
- (void)notificationSwipeStarted;
- (void)notificationSwipeMoved:(CGFloat)amount;
- (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete;
// This setter for |boundsAnimation_| also cleans up the state of the previous
// |boundsAnimation_|.
- (void)setBoundsAnimation:(NSViewAnimation*)animation;
// Constructs an NSViewAnimation from |dictionary|, which should be a view
// animation dictionary.
- (NSViewAnimation*)animationWithDictionary:(NSDictionary*)dictionary;
@end
// Window Subclass /////////////////////////////////////////////////////////////
@interface MCPopupWindow : NSPanel {
// The cumulative X and Y scrollingDeltas since the -scrollWheel: event began.
NSPoint totalScrollDelta_;
}
@end
@implementation MCPopupWindow
- (void)scrollWheel:(NSEvent*)event {
// Gesture swiping only exists on 10.7+.
if (![event respondsToSelector:@selector(phase)])
return;
NSEventPhase phase = [event phase];
BOOL shouldTrackSwipe = NO;
if (phase == NSEventPhaseBegan) {
totalScrollDelta_ = NSZeroPoint;
} else if (phase == NSEventPhaseChanged) {
shouldTrackSwipe = YES;
totalScrollDelta_.x += [event scrollingDeltaX];
totalScrollDelta_.y += [event scrollingDeltaY];
}
// Only allow horizontal scrolling.
if (std::abs(totalScrollDelta_.x) < std::abs(totalScrollDelta_.y))
return;
if (shouldTrackSwipe) {
MCPopupController* controller =
base::mac::ObjCCastStrict<MCPopupController>([self windowController]);
BOOL directionInverted = [event isDirectionInvertedFromDevice];
auto handler = ^(CGFloat gestureAmount, NSEventPhase phase,
BOOL isComplete, BOOL* stop) {
// The swipe direction should match the direction the user's fingers
// are moving, not the interpreted scroll direction.
if (directionInverted)
gestureAmount *= -1;
if (phase == NSEventPhaseBegan) {
[controller notificationSwipeStarted];
return;
}
[controller notificationSwipeMoved:gestureAmount];
BOOL ended = phase == NSEventPhaseEnded;
if (ended || isComplete)
[controller notificationSwipeEnded:ended complete:isComplete];
};
[event trackSwipeEventWithOptions:NSEventSwipeTrackingLockDirection
dampenAmountThresholdMin:-1
max:1
usingHandler:handler];
}
}
@end
////////////////////////////////////////////////////////////////////////////////
@implementation MCPopupController
- (id)initWithNotification:(const message_center::Notification*)notification
messageCenter:(message_center::MessageCenter*)messageCenter
popupCollection:(MCPopupCollection*)popupCollection {
base::scoped_nsobject<MCPopupWindow> window([[MCPopupWindow alloc]
initWithContentRect:ui::kWindowSizeDeterminedLater
styleMask:NSNonactivatingPanelMask
backing:NSBackingStoreBuffered
defer:NO]);
if ((self = [super initWithWindow:window])) {
messageCenter_ = messageCenter;
popupCollection_ = popupCollection;
notificationController_.reset(
[[MCNotificationController alloc] initWithNotification:notification
messageCenter:messageCenter_]);
bounds_ = [[notificationController_ view] frame];
[window setFloatingPanel:YES];
[window setBecomesKeyOnlyIfNeeded:YES];
[window
setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces |
NSWindowCollectionBehaviorFullScreenAuxiliary];
[window setHasShadow:YES];
[window setContentView:[notificationController_ view]];
trackingArea_.reset(
[[CrTrackingArea alloc] initWithRect:NSZeroRect
options:NSTrackingInVisibleRect |
NSTrackingMouseEnteredAndExited |
NSTrackingActiveAlways
owner:self
userInfo:nil]);
[[window contentView] addTrackingArea:trackingArea_.get()];
}
return self;
}
#ifndef NDEBUG
- (void)dealloc {
DCHECK(hasBeenClosed_);
[super dealloc];
}
#endif
- (void)close {
#ifndef NDEBUG
hasBeenClosed_ = YES;
#endif
[self setBoundsAnimation:nil];
if (trackingArea_.get())
[[[self window] contentView] removeTrackingArea:trackingArea_.get()];
[super close];
[self performSelectorOnMainThread:@selector(release)
withObject:nil
waitUntilDone:NO
modes:@[ NSDefaultRunLoopMode ]];
}
- (MCNotificationController*)notificationController {
return notificationController_.get();
}
- (const message_center::Notification*)notification {
return [notificationController_ notification];
}
- (const std::string&)notificationID {
return [notificationController_ notificationID];
}
// Private /////////////////////////////////////////////////////////////////////
- (void)notificationSwipeStarted {
originalFrame_ = [[self window] frame];
swipeGestureEnded_ = NO;
}
- (void)notificationSwipeMoved:(CGFloat)amount {
NSWindow* window = [self window];
[window setAlphaValue:1.0 - std::abs(amount)];
NSRect frame = [window frame];
CGFloat originalMin = NSMinX(originalFrame_);
frame.origin.x = originalMin + (NSMidX(originalFrame_) - originalMin) *
-amount;
[window setFrame:frame display:YES];
}
- (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete {
swipeGestureEnded_ |= ended;
if (swipeGestureEnded_ && isComplete) {
messageCenter_->RemoveNotification([self notificationID], /*by_user=*/true);
[popupCollection_ onPopupAnimationEnded:[self notificationID]];
}
}
- (void)setBoundsAnimation:(NSViewAnimation*)animation {
[boundsAnimation_ stopAnimation];
[boundsAnimation_ setDelegate:nil];
boundsAnimation_.reset([animation retain]);
}
- (NSViewAnimation*)animationWithDictionary:(NSDictionary*)dictionary {
return [[[NSViewAnimation alloc]
initWithViewAnimations:@[ dictionary ]] autorelease];
}
- (void)animationDidEnd:(NSAnimation*)animation {
DCHECK_EQ(animation, boundsAnimation_.get());
[self setBoundsAnimation:nil];
[popupCollection_ onPopupAnimationEnded:[self notificationID]];
if (isClosing_)
[self close];
}
- (void)showWithAnimation:(NSRect)newBounds {
bounds_ = newBounds;
NSRect startBounds = newBounds;
startBounds.origin.x += startBounds.size.width;
[[self window] setFrame:startBounds display:NO];
[[self window] setAlphaValue:0];
[[self window] setCanHide:NO];
[self showWindow:nil];
// Slide-in and fade-in simultaneously.
NSDictionary* animationDict = @{
NSViewAnimationTargetKey : [self window],
NSViewAnimationEndFrameKey : [NSValue valueWithRect:newBounds],
NSViewAnimationEffectKey : NSViewAnimationFadeInEffect
};
NSViewAnimation* animation = [self animationWithDictionary:animationDict];
[self setBoundsAnimation:animation];
[boundsAnimation_ setDuration:[popupCollection_ popupAnimationDuration]];
[boundsAnimation_ setDelegate:self];
[boundsAnimation_ startAnimation];
}
- (void)closeWithAnimation {
if (isClosing_)
return;
#ifndef NDEBUG
hasBeenClosed_ = YES;
#endif
isClosing_ = YES;
// If the notification was swiped closed, do not animate it as the
// notification has already faded out.
if (swipeGestureEnded_) {
[self close];
return;
}
NSDictionary* animationDict = @{
NSViewAnimationTargetKey : [self window],
NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect
};
NSViewAnimation* animation = [self animationWithDictionary:animationDict];
[self setBoundsAnimation:animation];
[boundsAnimation_ setDuration:[popupCollection_ popupAnimationDuration]];
[boundsAnimation_ setDelegate:self];
[boundsAnimation_ startAnimation];
}
- (void)markPopupCollectionGone {
popupCollection_ = nil;
}
- (NSRect)bounds {
return bounds_;
}
- (void)setBounds:(NSRect)newBounds {
if (isClosing_ || NSEqualRects(bounds_ , newBounds))
return;
bounds_ = newBounds;
NSDictionary* animationDict = @{
NSViewAnimationTargetKey : [self window],
NSViewAnimationEndFrameKey : [NSValue valueWithRect:newBounds]
};
NSViewAnimation* animation = [self animationWithDictionary:animationDict];
[self setBoundsAnimation:animation];
[boundsAnimation_ setDuration:[popupCollection_ popupAnimationDuration]];
[boundsAnimation_ setDelegate:self];
[boundsAnimation_ startAnimation];
}
- (void)mouseEntered:(NSEvent*)event {
messageCenter_->PausePopupTimers();
}
- (void)mouseExited:(NSEvent*)event {
messageCenter_->RestartPopupTimers();
}
@end
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/message_center/cocoa/popup_controller.h"
#include <memory>
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#import "ui/base/test/cocoa_helper.h"
#include "ui/message_center/public/cpp/notification.h"
using base::ASCIIToUTF16;
namespace message_center {
class PopupControllerTest : public ui::CocoaTest {
};
TEST_F(PopupControllerTest, Creation) {
std::unique_ptr<message_center::Notification> notification(
new message_center::Notification(
message_center::NOTIFICATION_TYPE_SIMPLE, "",
ASCIIToUTF16("Added to circles"),
ASCIIToUTF16("Jonathan and 5 others"), gfx::Image(), base::string16(),
GURL(), message_center::NotifierId(),
message_center::RichNotificationData(), NULL));
base::scoped_nsobject<MCPopupController> controller(
[[MCPopupController alloc] initWithNotification:notification.get()
messageCenter:nil
popupCollection:nil]);
// Add an extra ref count for scoped_nsobject since MCPopupController will
// release itself when it is being closed.
[controller retain];
EXPECT_TRUE([controller window]);
EXPECT_EQ(notification.get(), [controller notification]);
[controller showWindow:nil];
[controller close];
}
} // namespace message_center
...@@ -16,10 +16,6 @@ ...@@ -16,10 +16,6 @@
#include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_paths.h"
#include "ui/gl/test/gl_surface_test_support.h" #include "ui/gl/test/gl_surface_test_support.h"
#if defined(OS_MACOSX)
#include "base/test/mock_chrome_application_mac.h"
#endif
namespace { namespace {
class MessageCenterTestSuite : public base::TestSuite { class MessageCenterTestSuite : public base::TestSuite {
...@@ -28,9 +24,6 @@ class MessageCenterTestSuite : public base::TestSuite { ...@@ -28,9 +24,6 @@ class MessageCenterTestSuite : public base::TestSuite {
protected: protected:
void Initialize() override { void Initialize() override {
#if defined(OS_MACOSX)
mock_cr_app::RegisterMockCrApp();
#endif
gl::GLSurfaceTestSupport::InitializeOneOff(); gl::GLSurfaceTestSupport::InitializeOneOff();
base::TestSuite::Initialize(); base::TestSuite::Initialize();
ui::RegisterPathProvider(); ui::RegisterPathProvider();
......
...@@ -118,21 +118,8 @@ ...@@ -118,21 +118,8 @@
<if expr="is_macosx or is_ios"> <if expr="is_macosx or is_ios">
<structure type="chrome_scaled_image" name="IDR_MENU_HIERARCHY_ARROW" file="mac/menu_hierarchy_arrow.png" /> <structure type="chrome_scaled_image" name="IDR_MENU_HIERARCHY_ARROW" file="mac/menu_hierarchy_arrow.png" />
</if> </if>
<if expr="toolkit_views or is_ios"> <if expr="toolkit_views and not is_macosx">
<if expr="is_win">
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_CLOSE" file="win/notification_close.png"/>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_CLOSE_HOVER" file="win/notification_close_hover.png"/>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_CLOSE_PRESSED" file="win/notification_close_pressed.png"/>
</if>
<if expr="not is_win">
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_CLOSE" file="common/notification_close.png"/>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_CLOSE_HOVER" file="common/notification_close_hover.png"/>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_CLOSE_PRESSED" file="common/notification_close_pressed.png"/>
</if>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_SETTINGS" file="common/notification_settings.png"/> <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_SETTINGS" file="common/notification_settings.png"/>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_SETTINGS_BUTTON_ICON" file="common/notification_settings_button.png"/>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_SETTINGS_BUTTON_ICON_HOVER" file="common/notification_settings_button_hover.png"/>
<structure type="chrome_scaled_image" name="IDR_NOTIFICATION_SETTINGS_BUTTON_ICON_PRESSED" file="common/notification_settings_button_pressed.png"/>
</if> </if>
<if expr="not is_android and not is_ios"> <if expr="not is_android and not is_ios">
<structure type="chrome_scaled_image" name="IDR_NTP_DEFAULT_FAVICON" file="common/ntp_default_favicon.png" /> <structure type="chrome_scaled_image" name="IDR_NTP_DEFAULT_FAVICON" file="common/ntp_default_favicon.png" />
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment