Rename PanelMouseWatcherGtk into PanelMouseWatcherTimer. Added implementation of gfx::Point GetCursorScreenPoint() on Mac.

Review URL: http://codereview.chromium.org/7981012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102173 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/ui/panels/native_panel.h b/chrome/browser/ui/panels/native_panel.h
index d25ae21..08d82e4 100644
--- a/chrome/browser/ui/panels/native_panel.h
+++ b/chrome/browser/ui/panels/native_panel.h
@@ -87,6 +87,7 @@
 class NativePanelTesting {
  public:
   static NativePanelTesting* Create(NativePanel* native_panel);
+  // TODO(dimich) Remove this method, there is PanelMouseWatcher::GetInstance().
   static PanelMouseWatcher* GetPanelMouseWatcherInstance();
 
   // clang gives error on delete if the destructor is not virtual.
diff --git a/chrome/browser/ui/panels/panel_browser_window_cocoa.mm b/chrome/browser/ui/panels/panel_browser_window_cocoa.mm
index a2a90cc..5afc84e 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"
+#include "chrome/browser/ui/panels/panel_mouse_watcher.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"
@@ -58,6 +59,9 @@
 }
 
 PanelBrowserWindowCocoa::~PanelBrowserWindowCocoa() {
+  PanelMouseWatcher* watcher = PanelMouseWatcher::GetInstance();
+  if (watcher->IsSubscribed(this))
+    watcher->RemoveSubscriber(this);
 }
 
 bool PanelBrowserWindowCocoa::isClosed() {
@@ -109,13 +113,15 @@
   int height;  // New height of the Panel in screen coordinates.
   switch (expansion_state) {
     case Panel::EXPANDED:
+      PanelMouseWatcher::GetInstance()->RemoveSubscriber(this);
       height = restored_height_;
       break;
     case Panel::TITLE_ONLY:
       height = [controller_ titlebarHeightInScreenCoordinates];
       break;
     case Panel::MINIMIZED:
-      height = 3;  // TODO(dimich) merge with GTK patch which defines it better.
+      PanelMouseWatcher::GetInstance()->AddSubscriber(this);
+      height = PanelManager::minimized_panel_height();
       break;
     default:
       NOTREACHED();
@@ -133,10 +139,11 @@
   SetPanelBounds(bounds);
 }
 
+// Coordinates are in gfx coordinate system (screen, with 0,0 at the top left).
 bool PanelBrowserWindowCocoa::ShouldBringUpPanelTitlebar(int mouse_x,
                                                          int mouse_y) const {
-  NOTIMPLEMENTED();
-  return false;
+  return bounds_.x() <= mouse_x && mouse_x <= bounds_.right() &&
+      mouse_y >= bounds_.y();
 }
 
 void PanelBrowserWindowCocoa::ClosePanel() {
@@ -300,7 +307,7 @@
 
 // static
 PanelMouseWatcher* NativePanelTesting::GetPanelMouseWatcherInstance() {
-  return NULL;
+  return PanelMouseWatcher::GetInstance();
 }
 
 NativePanelTestingCocoa::NativePanelTestingCocoa(NativePanel* native_panel)
@@ -332,12 +339,13 @@
   [titlebar() finishDragTitlebar];
 }
 
+// TODO(dimich) this method is platform-independent. Reuse it.
 void NativePanelTestingCocoa::SetMousePositionForMinimizeRestore(
     const gfx::Point& hover_point) {
-  NOTIMPLEMENTED();
+  PanelMouseWatcher::GetInstance()->HandleMouseMovement(hover_point);
+  MessageLoopForUI::current()->RunAllPending();
 }
 
 int NativePanelTestingCocoa::TitleOnlyHeight() const {
-  NOTIMPLEMENTED();
-  return -1;
+  return [native_panel_window_->controller_ titlebarHeightInScreeenCoordinates];
 }
diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc
index aa80b2e4..cd37946 100644
--- a/chrome/browser/ui/panels/panel_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browsertest.cc
@@ -306,6 +306,12 @@
   }
 
   void TestMinimizeRestore() {
+    // This constant is used to generate a point 'sufficiently higher then
+    // top edge of the panel'. On some platforms (Mac) we extend hover area
+    // a bit above the minimized panel as well, so it takes significant
+    // distance to 'move mouse out' of the hover-sensitive area.
+    const int kFarEnoughFromHoverArea = 153;
+
     std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
     std::vector<gfx::Rect> test_begin_bounds = GetAllPanelsBounds();
     std::vector<gfx::Rect> expected_bounds = test_begin_bounds;
@@ -367,7 +373,8 @@
       CheckExpansionStates(titlebar_exposed_states);
 
       // Hover mouse above the panel. Verify all panels are minimized.
-      hover_point.set_y(panels[index]->GetRestoredBounds().y() - 10);
+      hover_point.set_y(
+          panels[index]->GetRestoredBounds().y() - kFarEnoughFromHoverArea);
       native_panels_testing[index]->SetMousePositionForMinimizeRestore(
           hover_point);
       CheckPanelBounds(panels, minimized_bounds);
@@ -391,7 +398,8 @@
       CheckExpansionStates(titlebar_exposed_states);
 
       // Hover mouse above panel.  Verify all panels are minimized.
-      hover_point.set_y(panels[index]->GetRestoredBounds().y() - 10);
+      hover_point.set_y(
+          panels[index]->GetRestoredBounds().y() - kFarEnoughFromHoverArea);
       native_panels_testing[index]->SetMousePositionForMinimizeRestore(
           hover_point);
       CheckPanelBounds(panels, minimized_bounds);
@@ -816,7 +824,7 @@
   panel->Close();
 }
 
-#if defined(TOOLKIT_GTK)
+#if defined(TOOLKIT_GTK) || defined(OS_MACOSX)
 #define MAYBE_MinimizeRestore MinimizeRestore
 #else
 #define MAYBE_MinimizeRestore DISABLED_MinimizeRestore
diff --git a/chrome/browser/ui/panels/panel_mouse_watcher.cc b/chrome/browser/ui/panels/panel_mouse_watcher.cc
index bf1f4378..77e5f5b 100644
--- a/chrome/browser/ui/panels/panel_mouse_watcher.cc
+++ b/chrome/browser/ui/panels/panel_mouse_watcher.cc
@@ -11,6 +11,7 @@
 }
 
 PanelMouseWatcher::~PanelMouseWatcher() {
+  DCHECK(subscribers_.size() == 0);
 }
 
 void PanelMouseWatcher::AddSubscriber(NativePanel* native_panel) {
diff --git a/chrome/browser/ui/panels/panel_mouse_watcher_gtk.cc b/chrome/browser/ui/panels/panel_mouse_watcher_gtk.cc
deleted file mode 100644
index 9ae6002..0000000
--- a/chrome/browser/ui/panels/panel_mouse_watcher_gtk.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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.
-
-// #include "chrome/browser/ui/panels/panel_mouse_watcher_gtk.h"
-
-#include "base/memory/singleton.h"
-#include "base/time.h"
-#include "base/timer.h"
-#include "chrome/browser/ui/panels/panel_manager.h"
-#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
-#include "ui/gfx/screen.h"
-
-// A timer based implementation of PanelMouseWatcher.  Currently used on Gtk
-// but could be used on any platform.
-class PanelMouseWatcherGtk : public PanelMouseWatcher {
- public:
-  // Returns the singleton instance.
-  static PanelMouseWatcherGtk* GetInstance();
-
-  virtual ~PanelMouseWatcherGtk();
-
- protected:
-  virtual void Start();
-  virtual void Stop();
-
- private:
-  // Specifies the rate at which we want to sample the mouse position.
-  static const int kMousePollingIntervalMs = 250;
-
-  PanelMouseWatcherGtk();
-  friend struct DefaultSingletonTraits<PanelMouseWatcherGtk>;
-
-  // Timer callback function.
-  void DoWork();
-  friend class base::RepeatingTimer<PanelMouseWatcherGtk>;
-
-  // Timer used to track mouse movements.  Gtk does not provide an easy way of
-  // tracking mouse movements across applications.  So we use a timer to
-  // accomplish the same.  This could also be more efficient as you end up
-  // getting a lot of notifications when tracking mouse movements.
-  base::RepeatingTimer<PanelMouseWatcherGtk> timer_;
-
-  DISALLOW_COPY_AND_ASSIGN(PanelMouseWatcherGtk);
-};
-
-// static
-PanelMouseWatcher* PanelMouseWatcher::GetInstance() {
-  return PanelMouseWatcherGtk::GetInstance();
-}
-
-// static
-PanelMouseWatcherGtk* PanelMouseWatcherGtk::GetInstance() {
-  return Singleton<PanelMouseWatcherGtk>::get();
-}
-
-PanelMouseWatcherGtk::PanelMouseWatcherGtk() : PanelMouseWatcher() {
-}
-
-PanelMouseWatcherGtk::~PanelMouseWatcherGtk() {
-}
-
-void PanelMouseWatcherGtk::Start() {
-  DCHECK(!timer_.IsRunning());
-  timer_.Start(FROM_HERE,
-               base::TimeDelta::FromMilliseconds(kMousePollingIntervalMs),
-               this, &PanelMouseWatcherGtk::DoWork);
-}
-
-void PanelMouseWatcherGtk::Stop() {
-  DCHECK(timer_.IsRunning());
-  timer_.Stop();
-}
-
-void PanelMouseWatcherGtk::DoWork() {
-  HandleMouseMovement(gfx::Screen::GetCursorScreenPoint());
-}
diff --git a/chrome/browser/ui/panels/panel_mouse_watcher_timer.cc b/chrome/browser/ui/panels/panel_mouse_watcher_timer.cc
new file mode 100644
index 0000000..089d3e9
--- /dev/null
+++ b/chrome/browser/ui/panels/panel_mouse_watcher_timer.cc
@@ -0,0 +1,76 @@
+// 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.
+
+#include "base/memory/singleton.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "chrome/browser/ui/panels/panel_manager.h"
+#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
+#include "ui/gfx/screen.h"
+
+// A timer based implementation of PanelMouseWatcher.  Currently used for Gtk
+// and Mac panels implementations.
+class PanelMouseWatcherTimer : public PanelMouseWatcher {
+ public:
+  // Returns the singleton instance.
+  static PanelMouseWatcherTimer* GetInstance();
+
+  virtual ~PanelMouseWatcherTimer();
+
+ protected:
+  virtual void Start();
+  virtual void Stop();
+
+ private:
+  // Specifies the rate at which we want to sample the mouse position.
+  static const int kMousePollingIntervalMs = 250;
+
+  PanelMouseWatcherTimer();
+  friend struct DefaultSingletonTraits<PanelMouseWatcherTimer>;
+
+  // Timer callback function.
+  void DoWork();
+  friend class base::RepeatingTimer<PanelMouseWatcherTimer>;
+
+  // Timer used to track mouse movements. Some OSes do not provide an easy way
+  // of tracking mouse movements across applications.  So we use a timer to
+  // accomplish the same.  This could also be more efficient as you end up
+  // getting a lot of notifications when tracking mouse movements.
+  base::RepeatingTimer<PanelMouseWatcherTimer> timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(PanelMouseWatcherTimer);
+};
+
+// static
+PanelMouseWatcher* PanelMouseWatcher::GetInstance() {
+  return PanelMouseWatcherTimer::GetInstance();
+}
+
+// static
+PanelMouseWatcherTimer* PanelMouseWatcherTimer::GetInstance() {
+  return Singleton<PanelMouseWatcherTimer>::get();
+}
+
+PanelMouseWatcherTimer::PanelMouseWatcherTimer() : PanelMouseWatcher() {
+}
+
+PanelMouseWatcherTimer::~PanelMouseWatcherTimer() {
+  DCHECK(!timer_.IsRunning());
+}
+
+void PanelMouseWatcherTimer::Start() {
+  DCHECK(!timer_.IsRunning());
+  timer_.Start(FROM_HERE,
+               base::TimeDelta::FromMilliseconds(kMousePollingIntervalMs),
+               this, &PanelMouseWatcherTimer::DoWork);
+}
+
+void PanelMouseWatcherTimer::Stop() {
+  DCHECK(timer_.IsRunning());
+  timer_.Stop();
+}
+
+void PanelMouseWatcherTimer::DoWork() {
+  HandleMouseMovement(gfx::Screen::GetCursorScreenPoint());
+}
diff --git a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
index 08fdc1b..7483b5e 100644
--- a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
+++ b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
@@ -24,7 +24,9 @@
 const int kCloseButtonLeftPadding = 8;
 
 // Used to implement TestingAPI
-static NSEvent* MakeMouseEvent(NSEventType type, NSPoint point) {
+static NSEvent* MakeMouseEvent(NSEventType type,
+                               NSPoint point,
+                               int clickCount) {
   return [NSEvent mouseEventWithType:type
                             location:point
                        modifierFlags:0
@@ -32,7 +34,7 @@
                         windowNumber:0
                              context:nil
                          eventNumber:0
-                          clickCount:0
+                          clickCount:clickCount
                             pressure:0.0];
 }
 
@@ -347,12 +349,12 @@
 }
 
 - (void)pressLeftMouseButtonTitlebar {
-  NSEvent* event = MakeMouseEvent(NSLeftMouseDown, NSZeroPoint);
+  NSEvent* event = MakeMouseEvent(NSLeftMouseDown, NSZeroPoint, 0);
   [self mouseDown:event];
 }
 
 - (void)releaseLeftMouseButtonTitlebar {
-  NSEvent* event = MakeMouseEvent(NSLeftMouseUp, NSZeroPoint);
+  NSEvent* event = MakeMouseEvent(NSLeftMouseUp, NSZeroPoint, 1);
   [self mouseUp:event];
 }
 
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5b58dc4c..99b84b6 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3058,7 +3058,7 @@
         'browser/ui/panels/panel_manager.h',
         'browser/ui/panels/panel_mouse_watcher.cc',
         'browser/ui/panels/panel_mouse_watcher.h',
-        'browser/ui/panels/panel_mouse_watcher_gtk.cc',
+        'browser/ui/panels/panel_mouse_watcher_timer.cc',
         'browser/ui/panels/panel_mouse_watcher_win.cc',
         'browser/ui/panels/panel_mouse_watcher_win.h',
         'browser/ui/panels/panel_settings_menu_model.cc',
@@ -4752,7 +4752,7 @@
                 ['exclude', '^browser/ui/gtk/omnibox/omnibox_popup_view_gtk.h'],
                 ['exclude', '^browser/ui/panels/panel_browser_window_gtk.cc'],
                 ['exclude', '^browser/ui/panels/panel_browser_window_gtk.h'],
-                ['exclude', '^browser/ui/panels/panel_mouse_watcher_gtk.cc'],
+                ['exclude', '^browser/ui/panels/panel_mouse_watcher_timer.cc'],
               ],
             }],
             # Exclude these toolkit_views specific files again.
diff --git a/ui/gfx/screen_mac.mm b/ui/gfx/screen_mac.mm
new file mode 100644
index 0000000..b38344a
--- /dev/null
+++ b/ui/gfx/screen_mac.mm
@@ -0,0 +1,20 @@
+// 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.
+
+#include "ui/gfx/screen.h"
+
+#import <Cocoa/Cocoa.h>
+
+namespace gfx {
+
+// static
+gfx::Point Screen::GetCursorScreenPoint() {
+  NSPoint mouseLocation  = [NSEvent mouseLocation];
+  // Flip coordinates to gfx (0,0 in top-left corner) using primary screen.
+  NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
+  mouseLocation.y = NSMaxY([screen frame]) - mouseLocation.y;
+  return gfx::Point(mouseLocation.x, mouseLocation.y);
+}
+
+}  // namespace gfx
diff --git a/ui/ui.gyp b/ui/ui.gyp
index ce8f495..dffa9b7 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -277,6 +277,7 @@
         'gfx/screen.h',
         'gfx/screen_aura.cc',
         'gfx/screen_gtk.cc',
+        'gfx/screen_mac.mm',
         'gfx/screen_wayland.cc',
         'gfx/screen_win.cc',
         'gfx/scoped_cg_context_save_gstate_mac.h',