summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-09 23:57:45 +0000
committerdimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-09 23:57:45 +0000
commit45190c6ec9e3cde4e15bfb9962f56eb673cbcb5e (patch)
treeda0e293699912d223ca14f871cecb310ab6f76c7
parentaedcee6b23ff2d833c0cf57cec4fdc6547d2e77b (diff)
downloadchromium_src-45190c6ec9e3cde4e15bfb9962f56eb673cbcb5e.zip
chromium_src-45190c6ec9e3cde4e15bfb9962f56eb673cbcb5e.tar.gz
chromium_src-45190c6ec9e3cde4e15bfb9962f56eb673cbcb5e.tar.bz2
Enable rearrangement of Panels on Mac by dragging.
TEST=PanelBrowserTest.DragPanels Review URL: http://codereview.chromium.org/7857002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100537 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/panels/panel_browser_window_cocoa.h1
-rw-r--r--chrome/browser/ui/panels/panel_browser_window_cocoa.mm52
-rw-r--r--chrome/browser/ui/panels/panel_browser_window_cocoa_unittest.mm50
-rw-r--r--chrome/browser/ui/panels/panel_browsertest.cc8
-rw-r--r--chrome/browser/ui/panels/panel_titlebar_view_cocoa.h25
-rw-r--r--chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm116
-rw-r--r--chrome/browser/ui/panels/panel_window_controller_cocoa.h26
-rw-r--r--chrome/browser/ui/panels/panel_window_controller_cocoa.mm75
-rw-r--r--chrome/common/chrome_notification_types.h5
9 files changed, 332 insertions, 26 deletions
diff --git a/chrome/browser/ui/panels/panel_browser_window_cocoa.h b/chrome/browser/ui/panels/panel_browser_window_cocoa.h
index 6c33f92..558ad65 100644
--- a/chrome/browser/ui/panels/panel_browser_window_cocoa.h
+++ b/chrome/browser/ui/panels/panel_browser_window_cocoa.h
@@ -66,6 +66,7 @@ class PanelBrowserWindowCocoa : public NativePanel {
private:
friend class PanelBrowserWindowCocoaTest;
+ friend class NativePanelTestingCocoa;
FRIEND_TEST_ALL_PREFIXES(PanelBrowserWindowCocoaTest, CreateClose);
FRIEND_TEST_ALL_PREFIXES(PanelBrowserWindowCocoaTest, NativeBounds);
FRIEND_TEST_ALL_PREFIXES(PanelBrowserWindowCocoaTest, TitlebarViewCreate);
diff --git a/chrome/browser/ui/panels/panel_browser_window_cocoa.mm b/chrome/browser/ui/panels/panel_browser_window_cocoa.mm
index 68f3879..f335ee3 100644
--- a/chrome/browser/ui/panels/panel_browser_window_cocoa.mm
+++ b/chrome/browser/ui/panels/panel_browser_window_cocoa.mm
@@ -10,6 +10,7 @@
#import "chrome/browser/ui/cocoa/browser_window_utils.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_manager.h"
+#import "chrome/browser/ui/panels/panel_titlebar_view_cocoa.h"
#import "chrome/browser/ui/panels/panel_window_controller_cocoa.h"
#include "content/common/native_web_keyboard_event.h"
@@ -86,7 +87,7 @@ gfx::Rect PanelBrowserWindowCocoa::GetPanelBounds() const {
void PanelBrowserWindowCocoa::SetPanelBounds(const gfx::Rect& bounds) {
bounds_ = bounds;
NSRect frame = ConvertCoordinatesToCocoa(bounds);
- [[controller_ window] setFrame:frame display:YES animate:YES];
+ [controller_ setPanelFrame:frame];
}
void PanelBrowserWindowCocoa::OnPanelExpansionStateChanged(
@@ -202,6 +203,7 @@ void PanelBrowserWindowCocoa::didCloseNativeWindow() {
panel_->manager()->Remove(panel_.get());
controller_ = NULL;
}
+
gfx::Size PanelBrowserWindowCocoa::GetNonClientAreaExtent() const {
NOTIMPLEMENTED();
return gfx::Size();
@@ -217,9 +219,53 @@ void PanelBrowserWindowCocoa::SetRestoredHeight(int height) {
}
// NativePanelTesting implementation.
+class NativePanelTestingCocoa : public NativePanelTesting {
+ public:
+ NativePanelTestingCocoa(NativePanel* native_panel);
+ virtual ~NativePanelTestingCocoa() { }
+ // Overridden from NativePanelTesting
+ virtual void PressLeftMouseButtonTitlebar(const gfx::Point& point) OVERRIDE;
+ virtual void ReleaseMouseButtonTitlebar() OVERRIDE;
+ virtual void DragTitlebar(int delta_x, int delta_y) OVERRIDE;
+ virtual void CancelDragTitlebar() OVERRIDE;
+ virtual void FinishDragTitlebar() OVERRIDE;
+ private:
+ PanelTitlebarViewCocoa* titlebar();
+ // Weak, assumed always to outlive this test API object.
+ PanelBrowserWindowCocoa* native_panel_window_;
+};
// static
NativePanelTesting* NativePanelTesting::Create(NativePanel* native_panel) {
- NOTIMPLEMENTED();
- return NULL;
+ return new NativePanelTestingCocoa(native_panel);
}
+
+NativePanelTestingCocoa::NativePanelTestingCocoa(NativePanel* native_panel)
+ : native_panel_window_(static_cast<PanelBrowserWindowCocoa*>(native_panel)) {
+}
+
+PanelTitlebarViewCocoa* NativePanelTestingCocoa::titlebar() {
+ return [native_panel_window_->controller_ titlebarView];
+}
+
+void NativePanelTestingCocoa::PressLeftMouseButtonTitlebar(
+ const gfx::Point& point) {
+ [titlebar() pressLeftMouseButtonTitlebar];
+}
+
+void NativePanelTestingCocoa::ReleaseMouseButtonTitlebar() {
+ [titlebar() releaseLeftMouseButtonTitlebar];
+}
+
+void NativePanelTestingCocoa::DragTitlebar(int delta_x, int delta_y) {
+ [titlebar() dragTitlebarDeltaX:delta_x deltaY:delta_y];
+}
+
+void NativePanelTestingCocoa::CancelDragTitlebar() {
+ [titlebar() cancelDragTitlebar];
+}
+
+void NativePanelTestingCocoa::FinishDragTitlebar() {
+ [titlebar() finishDragTitlebar];
+}
+
diff --git a/chrome/browser/ui/panels/panel_browser_window_cocoa_unittest.mm b/chrome/browser/ui/panels/panel_browser_window_cocoa_unittest.mm
index db957ad..814f448 100644
--- a/chrome/browser/ui/panels/panel_browser_window_cocoa_unittest.mm
+++ b/chrome/browser/ui/panels/panel_browser_window_cocoa_unittest.mm
@@ -29,12 +29,23 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
+class PanelAnimatedBoundsObserver :
+ public ui_test_utils::WindowedNotificationObserver {
+ public:
+ PanelAnimatedBoundsObserver(Panel* panel)
+ : ui_test_utils::WindowedNotificationObserver(
+ chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
+ Source<Panel>(panel)) { }
+ virtual ~PanelAnimatedBoundsObserver() { }
+};
+
// Main test class.
class PanelBrowserWindowCocoaTest : public CocoaProfileTest {
public:
virtual void SetUp() {
CocoaProfileTest::SetUp();
CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnablePanels);
+ [PanelWindowControllerCocoa enableBoundsAnimationNotifications];
}
Panel* CreateTestPanel(const std::string& panel_name) {
@@ -185,21 +196,29 @@ TEST_F(PanelBrowserWindowCocoaTest, NativeBounds) {
EXPECT_EQ(bounds1.origin.y, bounds2.origin.y);
EXPECT_EQ(bounds2.origin.y, bounds3.origin.y);
- // After panel2 is closed, panel3 should take its place.
- ClosePanelAndWait(panel2->browser());
- bounds3 = [[native_window3->controller_ window] frame];
- EXPECT_EQ(bounds2.origin.x, bounds3.origin.x);
- EXPECT_EQ(bounds2.origin.y, bounds3.origin.y);
- EXPECT_EQ(bounds2.size.width, bounds3.size.width);
- EXPECT_EQ(bounds2.size.height, bounds3.size.height);
+ {
+ // After panel2 is closed, panel3 should take its place.
+ PanelAnimatedBoundsObserver bounds_observer(panel3);
+ ClosePanelAndWait(panel2->browser());
+ bounds_observer.Wait();
+ bounds3 = [[native_window3->controller_ window] frame];
+ EXPECT_EQ(bounds2.origin.x, bounds3.origin.x);
+ EXPECT_EQ(bounds2.origin.y, bounds3.origin.y);
+ EXPECT_EQ(bounds2.size.width, bounds3.size.width);
+ EXPECT_EQ(bounds2.size.height, bounds3.size.height);
+ }
- // After panel1 is closed, panel3 should take its place.
- ClosePanelAndWait(panel1->browser());
- bounds3 = [[native_window3->controller_ window] frame];
- EXPECT_EQ(bounds1.origin.x, bounds3.origin.x);
- EXPECT_EQ(bounds1.origin.y, bounds3.origin.y);
- EXPECT_EQ(bounds1.size.width, bounds3.size.width);
- EXPECT_EQ(bounds1.size.height, bounds3.size.height);
+ {
+ // After panel1 is closed, panel3 should take its place.
+ PanelAnimatedBoundsObserver bounds_observer(panel3);
+ ClosePanelAndWait(panel1->browser());
+ bounds_observer.Wait();
+ bounds3 = [[native_window3->controller_ window] frame];
+ EXPECT_EQ(bounds1.origin.x, bounds3.origin.x);
+ EXPECT_EQ(bounds1.origin.y, bounds3.origin.y);
+ EXPECT_EQ(bounds1.size.width, bounds3.size.width);
+ EXPECT_EQ(bounds1.size.height, bounds3.size.height);
+ }
ClosePanelAndWait(panel3->browser());
}
@@ -241,7 +260,10 @@ TEST_F(PanelBrowserWindowCocoaTest, TitlebarViewSizing) {
bounds.set_y(bounds.y() - kDelta);
bounds.set_width(bounds.width() + kDelta);
bounds.set_height(bounds.height() + kDelta);
+
+ PanelAnimatedBoundsObserver bounds_observer(panel);
native_window->SetPanelBounds(bounds);
+ bounds_observer.Wait();
// Verify the panel resized.
NSRect window_frame = [[native_window->controller_ window] frame];
diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc
index 5d59ffd..ec4661a 100644
--- a/chrome/browser/ui/panels/panel_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browsertest.cc
@@ -326,13 +326,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreatePanelOnOverflow) {
TestCreatePanelOnOverflow();
}
-#if defined(TOOLKIT_GTK) || defined(OS_WIN)
-#define MAYBE_DragPanels DragPanels
-#else
-#define MAYBE_DragPanels DISABLED_DragPanels
-#endif
-
-IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DragPanels) {
+IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DragPanels) {
static const int max_panels = 3;
static const int zero_delta = 0;
static const int small_delta = 10;
diff --git a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h
index 30c8728..23d9ccb 100644
--- a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h
+++ b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h
@@ -24,6 +24,15 @@
// differently based on being key window) so it appears easier to simply overlay
// the standard titlebar.
+// When Drag is cancelled by hitting ESC key, we may still receive
+// the mouseDragged events but should ignore them until the mouse button is
+// released. Use these simple states to track this condition.
+enum PanelDragState {
+ PANEL_DRAG_CAN_START, // Mouse key went down, drag may be started.
+ PANEL_DRAG_IN_PROGRESS,
+ PANEL_DRAG_SUPPRESSED // Ignore drag events until PANEL_DRAG_CAN_START.
+};
+
@interface PanelTitlebarViewCocoa : BackgroundGradientView {
@private
IBOutlet PanelWindowControllerCocoa* controller_;
@@ -32,6 +41,7 @@
NSButton* closeButton_; // Created explicitly, not from NIB. Weak, destroyed
// when view is destroyed, as a subview.
ScopedCrTrackingArea closeButtonTrackingArea_;
+ PanelDragState dragState_;
}
// Callback from Close button.
@@ -51,6 +61,13 @@
// We need to respond to main window changes so we can update our look.
- (void)didChangeMainWindow:(NSNotification*)notification;
+// Helpers to control title drag operation, called from more then one place.
+// TODO(dimich): replace BOOL parameter that we have to explicitly specify at
+// callsites with an enum defined in PanelManager.
+- (void)startDrag;
+- (void)endDrag:(BOOL)cancelled;
+- (void)dragWithDeltaX:(int)deltaX;
+
@end // @interface PanelTitlebarView
// Methods which are either only for testing, or only public for testing.
@@ -61,6 +78,14 @@
// Simulates click on a close button. Used to test panel closing.
- (void)simulateCloseButtonClick;
+// NativePanelTesting support.
+- (void)pressLeftMouseButtonTitlebar;
+- (void)releaseLeftMouseButtonTitlebar;
+- (void)dragTitlebarDeltaX:(double)delta_x
+ deltaY:(double)delta_y;
+- (void)cancelDragTitlebar;
+- (void)finishDragTitlebar;
+
@end // @interface PanelTitlebarViewCocoa(TestingAPI)
#endif // CHROME_BROWSER_UI_PANELS_PANEL_TITLEBAR_VIEW_COCOA_H_
diff --git a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
index 0de95a1..9b3447f 100644
--- a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
+++ b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
@@ -4,9 +4,11 @@
#import "chrome/browser/ui/panels/panel_titlebar_view_cocoa.h"
+#include <Carbon/Carbon.h> // kVK_Escape
#import <Cocoa/Cocoa.h>
#include "base/logging.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
#include "chrome/browser/themes/theme_service.h"
#import "chrome/browser/ui/cocoa/hover_image_button.h"
#import "chrome/browser/ui/cocoa/themed_window.h"
@@ -19,10 +21,24 @@
const int kRoundedCornerSize = 6;
const int kCloseButtonLeftPadding = 8;
+// Used to implement TestingAPI
+static NSEvent* MakeMouseEvent(NSEventType type, NSPoint point) {
+ return [NSEvent mouseEventWithType:type
+ location:point
+ modifierFlags:0
+ timestamp:0
+ windowNumber:0
+ context:nil
+ eventNumber:0
+ clickCount:0
+ pressure:0.0];
+}
+
@implementation PanelTitlebarViewCocoa
- (id)initWithFrame:(NSRect)frame {
if ((self = [super initWithFrame:frame])) {
+ dragState_ = PANEL_DRAG_SUPPRESSED;
// Create standard OSX Close Button.
closeButton_ = [NSWindow standardWindowButton:NSWindowCloseButton
forStyleMask:NSClosableWindowMask];
@@ -158,6 +174,10 @@ const int kCloseButtonLeftPadding = 8;
return NO;
}
+- (BOOL)acceptsFirstMouse:(NSEvent*)event {
+ return YES;
+}
+
- (void)mouseEntered:(NSEvent*)event {
[[closeButton_ cell] setHighlighted:YES];
}
@@ -170,6 +190,77 @@ const int kCloseButtonLeftPadding = 8;
[self setNeedsDisplay:YES];
}
+- (void)mouseDown:(NSEvent*)event {
+ dragState_ = PANEL_DRAG_CAN_START;
+}
+
+- (void)mouseDragged:(NSEvent*)event {
+ // In addition to events needed to control the drag operation, fetch the right
+ // mouse click events and key down events and ignore them, to prevent their
+ // accumulation in the queue and "playing out" when the mouse is released.
+ const NSUInteger mask =
+ NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSKeyUpMask |
+ NSRightMouseDownMask | NSKeyDownMask ;
+ BOOL keepGoing = YES;
+
+ while (keepGoing) {
+ base::mac::ScopedNSAutoreleasePool autorelease_pool;
+
+ NSEvent* event = [NSApp nextEventMatchingMask:mask
+ untilDate:[NSDate distantFuture]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+
+ switch ([event type]) {
+ case NSLeftMouseDragged:
+ if (dragState_ == PANEL_DRAG_CAN_START)
+ [self startDrag];
+ [self dragWithDeltaX:[event deltaX]];
+ break;
+
+ case NSKeyUp:
+ if ([event keyCode] == kVK_Escape) {
+ [self endDrag:YES];
+ keepGoing = NO;
+ }
+ break;
+
+ case NSLeftMouseUp:
+ [self endDrag:NO];
+ keepGoing = NO;
+ break;
+
+ case NSRightMouseDownMask:
+ break;
+
+ default:
+ // Dequeue and ignore other mouse and key events so the Chrome context
+ // menu does not come after right click on a page during Panel
+ // rearrangement, or the keystrokes are not 'accumulated' and entered
+ // at once when the drag ends.
+ break;
+ }
+ }
+}
+
+- (void)startDrag {
+ DCHECK(dragState_ == PANEL_DRAG_CAN_START);
+ dragState_ = PANEL_DRAG_IN_PROGRESS;
+ [controller_ startDrag];
+}
+
+- (void)endDrag:(BOOL)cancelled {
+ if (dragState_ == PANEL_DRAG_IN_PROGRESS)
+ [controller_ endDrag:cancelled];
+ dragState_ = PANEL_DRAG_SUPPRESSED;
+}
+
+- (void)dragWithDeltaX:(int)deltaX {
+ if (dragState_ != PANEL_DRAG_IN_PROGRESS)
+ return;
+ [controller_ dragWithDeltaX:deltaX];
+}
+
// (Private/TestingAPI)
- (PanelWindowControllerCocoa*)controller {
return controller_;
@@ -179,5 +270,30 @@ const int kCloseButtonLeftPadding = 8;
[[closeButton_ cell] performClick:closeButton_];
}
+- (void)pressLeftMouseButtonTitlebar {
+ NSEvent* event = MakeMouseEvent(NSLeftMouseDown, NSZeroPoint);
+ [self mouseDown:event];
+}
+
+- (void)releaseLeftMouseButtonTitlebar {
+ NSEvent* event = MakeMouseEvent(NSLeftMouseUp, NSZeroPoint);
+ [self mouseUp:event];
+}
+
+- (void)dragTitlebarDeltaX:(double)delta_x
+ deltaY:(double)delta_y {
+ if (dragState_ == PANEL_DRAG_CAN_START)
+ [self startDrag];
+ [self dragWithDeltaX:delta_x];
+}
+
+- (void)cancelDragTitlebar {
+ [self endDrag:YES];
+}
+
+- (void)finishDragTitlebar {
+ [self endDrag:NO];
+}
+
@end
diff --git a/chrome/browser/ui/panels/panel_window_controller_cocoa.h b/chrome/browser/ui/panels/panel_window_controller_cocoa.h
index 4e01e29a..4e83335 100644
--- a/chrome/browser/ui/panels/panel_window_controller_cocoa.h
+++ b/chrome/browser/ui/panels/panel_window_controller_cocoa.h
@@ -14,6 +14,7 @@
#import "base/mac/cocoa_protocols.h"
#include "base/memory/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
+#import "base/memory/scoped_nsobject.h"
#import "chrome/browser/ui/cocoa/browser_command_executor.h"
#import "chrome/browser/ui/cocoa/themed_window.h"
@@ -27,6 +28,9 @@ class PanelBrowserWindowCocoa;
IBOutlet PanelTitlebarViewCocoa* titlebar_view_;
scoped_ptr<PanelBrowserWindowCocoa> windowShim_;
scoped_nsobject<NSString> pendingWindowTitle_;
+ NSViewAnimation* boundsAnimation_; // Lifetime controlled manually, needs
+ // more then just |release| to terminate.
+ BOOL animateOnBoundsChange_;
}
// Load the browser window nib and do any Cocoa-specific initialization.
@@ -60,6 +64,16 @@ class PanelBrowserWindowCocoa;
// native window at the end.
- (void)closePanel;
+// Uses nonblocking animation for moving the Panels. It's especially
+// important in case of dragging a Panel when other Panels should 'slide out',
+// indicating the potential drop slot.
+- (void)setPanelFrame:(NSRect)frame;
+
+// Used by PanelTitlebarViewCocoa when user rearranges the Panels by dragging.
+- (void)startDrag;
+- (void)endDrag:(BOOL)cancelled;
+- (void)dragWithDeltaX:(int)deltaX;
+
// Accessor for titlebar view.
- (PanelTitlebarViewCocoa*)titlebarView;
@@ -71,6 +85,18 @@ class PanelBrowserWindowCocoa;
// Invokes the settings menu when the settings button is pressed.
- (void)runSettingsMenu:(NSView*)button;
+// NSAnimationDelegate method, invoked when bounds animation is finished.
+- (void)animationDidEnd:(NSAnimation*)animation;
+// Terminates current bounds animation, if any.
+- (void)terminateBoundsAnimation;
+
@end // @interface PanelWindowController
+// Methods which are either only for testing, or only public for testing.
+@interface PanelWindowControllerCocoa(TestingAPI)
+
++ (void)enableBoundsAnimationNotifications;
+
+@end // @interface PanelWindowControllerCocoa(TestingAPI)
+
#endif // CHROME_BROWSER_UI_PANELS_PANEL_WINDOW_CONTROLLER_COCOA_H_
diff --git a/chrome/browser/ui/panels/panel_window_controller_cocoa.mm b/chrome/browser/ui/panels/panel_window_controller_cocoa.mm
index b87f0e7..965ec6e 100644
--- a/chrome/browser/ui/panels/panel_window_controller_cocoa.mm
+++ b/chrome/browser/ui/panels/panel_window_controller_cocoa.mm
@@ -22,12 +22,16 @@
#import "chrome/browser/ui/cocoa/menu_controller.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_browser_window_cocoa.h"
+#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/panels/panel_settings_menu_model.h"
#import "chrome/browser/ui/panels/panel_titlebar_view_cocoa.h"
#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
+#include "chrome/common/chrome_notification_types.h"
#include "content/browser/tab_contents/tab_contents.h"
+#include "content/common/notification_service.h"
const int kMinimumWindowSize = 1;
+const double kBoundsChangeAnimationDuration = 0.25;
// Replicate specific 10.6 SDK declarations for building with prior SDKs.
#if !defined(MAC_OS_X_VERSION_10_6) || \
@@ -39,13 +43,18 @@ enum {
#endif // MAC_OS_X_VERSION_10_6
+// In UNIT_TESTS, this is set to YES to wait on nonblocking animations.
+static BOOL g_reportAnimationStatus = NO;
+
@implementation PanelWindowControllerCocoa
- (id)initWithBrowserWindow:(PanelBrowserWindowCocoa*)window {
NSString* nibpath =
[base::mac::MainAppBundle() pathForResource:@"Panel" ofType:@"nib"];
- if ((self = [super initWithWindowNibPath:nibpath owner:self]))
+ if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
windowShim_.reset(window);
+ animateOnBoundsChange_ = YES;
+ }
return self;
}
@@ -259,7 +268,8 @@ enum {
// signal), window will be unconditionally closed. Clean up.
- (void)windowWillClose:(NSNotification*)notification {
DCHECK(windowShim_->browser()->tabstrip_model()->empty());
-
+ // Avoid callbacks from a nonblocking animation in progress, if any.
+ [self terminateBoundsAnimation];
windowShim_->didCloseNativeWindow();
[self autorelease];
}
@@ -279,4 +289,65 @@ enum {
forView:button];
}
+- (void)startDrag {
+ animateOnBoundsChange_ = NO;
+ windowShim_->panel()->manager()->StartDragging(windowShim_->panel());
+}
+
+- (void)endDrag:(BOOL)cancelled {
+ animateOnBoundsChange_ = YES;
+ windowShim_->panel()->manager()->EndDragging(cancelled);
+}
+
+- (void)dragWithDeltaX:(int)deltaX {
+ windowShim_->panel()->manager()->Drag(deltaX);
+}
+
+- (void)setPanelFrame:(NSRect)frame {
+ if (!animateOnBoundsChange_) {
+ [[self window] setFrame:frame display:YES animate:NO];
+ return;
+ }
+
+ NSDictionary *windowResize = [NSDictionary dictionaryWithObjectsAndKeys:
+ [self window], NSViewAnimationTargetKey,
+ [NSValue valueWithRect:frame], NSViewAnimationEndFrameKey, nil];
+
+ NSArray *animations = [NSArray arrayWithObjects:windowResize, nil];
+
+ // Terminate previous animation, if it is still playing.
+ [self terminateBoundsAnimation];
+ boundsAnimation_ =
+ [[NSViewAnimation alloc] initWithViewAnimations:animations];
+ [boundsAnimation_ setDelegate:self];
+
+ [boundsAnimation_ setAnimationBlockingMode: NSAnimationNonblocking];
+ [boundsAnimation_ setDuration: kBoundsChangeAnimationDuration];
+ [boundsAnimation_ startAnimation];
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation {
+ if (!g_reportAnimationStatus)
+ return;
+
+ NotificationService::current()->Notify(
+ chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
+ Source<Panel>(windowShim_->panel()),
+ NotificationService::NoDetails());
+}
+
+- (void)terminateBoundsAnimation {
+ if (!boundsAnimation_)
+ return;
+ [boundsAnimation_ stopAnimation];
+ [boundsAnimation_ setDelegate:nil];
+ [boundsAnimation_ release];
+}
+
+// TestingAPI interface implementation
+
++ (void)enableBoundsAnimationNotifications {
+ g_reportAnimationStatus = YES;
+}
+
@end
diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h
index 60f62ea..bdecc9b 100644
--- a/chrome/common/chrome_notification_types.h
+++ b/chrome/common/chrome_notification_types.h
@@ -894,6 +894,11 @@ enum NotificationType {
// enable/disable status.
NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
+ // Panels Notifications. The Panels are small browser windows near the bottom
+ // of the screen.
+ // Sent when all nonblocking bounds animations are finished across panels.
+ NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
+
// Note:-
// Currently only Content and Chrome define and use notifications.
// Custom notifications not belonging to Content and Chrome should start