Reland: Ash: Allow resize along 1 pixel edge inside window content

The mocks call for resize handles to function along a single pixel edge inside the window, overlapping the web content.  Refactored aura::Window::set_hit_test_bounds_inset() into SetHitTestBoundsOverride() to make hover/click events along that border pass through to the non-client area of the window frames.  This also allows windows to be resized when they are flush against the top/left/right edges of the screen.

BUG=117542
TEST=aura_shell_unittests ShelfLayoutManager, manually resize window from left/right/bottom/top edges

Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=126539

Reverted: http://src.chromium.org/viewvc/chrome?view=rev&revision=126544

Review URL: https://chromiumcodereview.appspot.com/9694012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126554 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h
index 9404d2b..dea112c 100644
--- a/ash/launcher/launcher.h
+++ b/ash/launcher/launcher.h
@@ -55,8 +55,7 @@
 
   scoped_ptr<LauncherModel> model_;
 
-  // Widget hosting the view.  May be hidden if we're not using a launcher,
-  // e.g. Aura compact window mode.
+  // Widget hosting the view.
   scoped_ptr<views::Widget> widget_;
 
   aura::Window* window_container_;
diff --git a/ash/wm/frame_painter.cc b/ash/wm/frame_painter.cc
index 9492cfc..f61baad 100644
--- a/ash/wm/frame_painter.cc
+++ b/ash/wm/frame_painter.cc
@@ -28,8 +28,12 @@
 // TODO(jamescook): Border is specified to be a single pixel overlapping
 // the web content and may need to be built into the shadow layers instead.
 const int kBorderThickness = 0;
-// Number of pixels outside the window frame to look for resize events.
-const int kResizeAreaOutsideBounds = 6;
+// Ash windows do not have a traditional visible window frame.  Window content
+// extends to the edge of the window.  We consider a small region outside the
+// window bounds and an even smaller region overlapping the window to be the
+// "non-client" area and use it for resizing.
+const int kResizeOutsideBoundsSize = 6;
+const int kResizeInsideBoundsSize = 1;
 // In the window corners, the resize areas don't actually expand bigger, but the
 // 16 px at the end of each edge triggers diagonal resizing.
 const int kResizeAreaCornerSize = 16;
@@ -137,8 +141,8 @@
       rb.GetImageNamed(IDR_AURA_WINDOW_HEADER_SHADE_RIGHT).ToSkBitmap();
 
   // Ensure we get resize cursors for a few pixels outside our bounds.
-  frame_->GetNativeWindow()->set_hit_test_bounds_inset(
-      -kResizeAreaOutsideBounds);
+  frame_->GetNativeWindow()->SetHitTestBoundsOverride(kResizeOutsideBoundsSize,
+                                                      kResizeInsideBoundsSize);
 }
 
 gfx::Rect FramePainter::GetBoundsForClientView(
@@ -163,13 +167,26 @@
 int FramePainter::NonClientHitTest(views::NonClientFrameView* view,
                                    const gfx::Point& point) {
   gfx::Rect expanded_bounds = view->bounds();
-  expanded_bounds.Inset(-kResizeAreaOutsideBounds, -kResizeAreaOutsideBounds);
+  expanded_bounds.Inset(-kResizeOutsideBoundsSize, -kResizeOutsideBoundsSize);
   if (!expanded_bounds.Contains(point))
     return HTNOWHERE;
 
   // No avatar button.
 
-  // Check the client view first, as it overlaps the window caption area.
+  // Check the frame first, as we allow a small area overlapping the contents
+  // to be used for resize handles.
+  bool can_resize = frame_->widget_delegate() ?
+      frame_->widget_delegate()->CanResize() :
+      false;
+  int frame_component = view->GetHTComponentForFrame(point,
+                                                     kResizeInsideBoundsSize,
+                                                     kResizeInsideBoundsSize,
+                                                     kResizeAreaCornerSize,
+                                                     kResizeAreaCornerSize,
+                                                     can_resize);
+  if (frame_component != HTNOWHERE)
+    return frame_component;
+
   int client_component = frame_->client_view()->NonClientHitTest(point);
   if (client_component != HTNOWHERE)
     return client_component;
@@ -182,18 +199,6 @@
       maximize_button_->GetMirroredBounds().Contains(point))
     return HTMAXBUTTON;
 
-  bool can_resize = frame_->widget_delegate() ?
-      frame_->widget_delegate()->CanResize() :
-      false;
-  int frame_component = view->GetHTComponentForFrame(point,
-                                                     kTopThickness,
-                                                     kBorderThickness,
-                                                     kResizeAreaCornerSize,
-                                                     kResizeAreaCornerSize,
-                                                     can_resize);
-  if (frame_component != HTNOWHERE)
-    return frame_component;
-
   // Caption is a safe default.
   return HTCAPTION;
 }
diff --git a/ash/wm/frame_painter.h b/ash/wm/frame_painter.h
index 2cf474d..5be8ca14 100644
--- a/ash/wm/frame_painter.h
+++ b/ash/wm/frame_painter.h
@@ -27,7 +27,8 @@
 namespace ash {
 
 // Helper class for painting window frames.  Exists to share code between
-// various implementations of views::NonClientFrameView.
+// various implementations of views::NonClientFrameView.  Canonical source of
+// layout constants for Ash window frames.
 class ASH_EXPORT FramePainter {
  public:
   FramePainter();
diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc
index eca4c40c..fff8c19e 100644
--- a/ash/wm/shelf_layout_manager.cc
+++ b/ash/wm/shelf_layout_manager.cc
@@ -26,6 +26,9 @@
 
 }  // namespace
 
+// static
+const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2;
+
 ////////////////////////////////////////////////////////////////////////////////
 // ShelfLayoutManager, public:
 
@@ -144,7 +147,8 @@
       available_bounds.width(),
       launcher_bounds.height());
   if (visible)
-    target_bounds->work_area_insets = gfx::Insets(0, 0, max_height_, 0);
+    target_bounds->work_area_insets = gfx::Insets(
+        0, 0, max_height_ + kWorkspaceAreaBottomInset, 0);
 }
 
 void ShelfLayoutManager::OnImplicitAnimationsCompleted() {
diff --git a/ash/wm/shelf_layout_manager.h b/ash/wm/shelf_layout_manager.h
index 8d69cc6..5c4b6dd 100644
--- a/ash/wm/shelf_layout_manager.h
+++ b/ash/wm/shelf_layout_manager.h
@@ -30,6 +30,14 @@
 class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager,
                                       public ui::ImplicitAnimationObserver {
  public:
+  // We reserve a small area at the bottom of the workspace area to ensure that
+  // the bottom-of-window resize handle can be hit.
+  // TODO(jamescook): Some day we may want the workspace area to be an even
+  // multiple of the size of the grid (currently 8 pixels), which will require
+  // removing this and finding a way for hover and click events to pass through
+  // the invisible parts of the launcher.
+  static const int kWorkspaceAreaBottomInset;
+
   ShelfLayoutManager(views::Widget* launcher, views::Widget* status);
   virtual ~ShelfLayoutManager();
 
diff --git a/ash/wm/shelf_layout_manager_unittest.cc b/ash/wm/shelf_layout_manager_unittest.cc
index fbf924d..bfedd5a 100644
--- a/ash/wm/shelf_layout_manager_unittest.cc
+++ b/ash/wm/shelf_layout_manager_unittest.cc
@@ -54,7 +54,8 @@
   const ash::ScreenAsh* screen = Shell::GetInstance()->screen();
   ASSERT_TRUE(screen);
   // Bottom inset should be the max of widget heights.
-  EXPECT_EQ(shelf->max_height(), screen->work_area_insets().bottom());
+  EXPECT_EQ(shelf->max_height() + ShelfLayoutManager::kWorkspaceAreaBottomInset,
+            screen->work_area_insets().bottom());
 
   // Hide the shelf.
   shelf->SetVisible(false);
@@ -76,7 +77,8 @@
   StepWidgetLayerAnimatorToEnd(shelf->launcher());
   StepWidgetLayerAnimatorToEnd(shelf->status());
   EXPECT_TRUE(shelf->visible());
-  EXPECT_EQ(shelf->max_height(), screen->work_area_insets().bottom());
+  EXPECT_EQ(shelf->max_height() + ShelfLayoutManager::kWorkspaceAreaBottomInset,
+            screen->work_area_insets().bottom());
 
   // Make sure the bounds of the two widgets changed.
   gfx::Rect launcher_bounds(shelf->launcher()->GetNativeView()->bounds());