| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |  | 
| 2 // Use of this source code is governed by a BSD-style license that can be |  | 
| 3 // found in the LICENSE file. |  | 
| 4 |  | 
| 5 #include "ui/aura_shell/toplevel_window_event_filter.h" |  | 
| 6 |  | 
| 7 #include "ui/aura/client/aura_constants.h" |  | 
| 8 #include "ui/aura/cursor.h" |  | 
| 9 #include "ui/aura/event.h" |  | 
| 10 #include "ui/aura/root_window.h" |  | 
| 11 #include "ui/aura/window.h" |  | 
| 12 #include "ui/aura/window_delegate.h" |  | 
| 13 #include "ui/aura_shell/window_util.h" |  | 
| 14 #include "ui/base/hit_test.h" |  | 
| 15 #include "ui/base/ui_base_types.h" |  | 
| 16 |  | 
| 17 namespace aura_shell { |  | 
| 18 |  | 
| 19 namespace { |  | 
| 20 |  | 
| 21 // Identifies the types of bounds change operations performed by a drag to a |  | 
| 22 // particular window component. |  | 
| 23 const int kBoundsChange_None = 0; |  | 
| 24 const int kBoundsChange_Repositions = 1; |  | 
| 25 const int kBoundsChange_Resizes = 2; |  | 
| 26 |  | 
| 27 int GetBoundsChangeForWindowComponent(int window_component) { |  | 
| 28   int bounds_change = kBoundsChange_None; |  | 
| 29   switch (window_component) { |  | 
| 30     case HTTOPLEFT: |  | 
| 31     case HTTOP: |  | 
| 32     case HTTOPRIGHT: |  | 
| 33     case HTLEFT: |  | 
| 34     case HTBOTTOMLEFT: |  | 
| 35       bounds_change |= kBoundsChange_Repositions | kBoundsChange_Resizes; |  | 
| 36       break; |  | 
| 37     case HTCAPTION: |  | 
| 38       bounds_change |= kBoundsChange_Repositions; |  | 
| 39       break; |  | 
| 40     case HTRIGHT: |  | 
| 41     case HTBOTTOMRIGHT: |  | 
| 42     case HTBOTTOM: |  | 
| 43     case HTGROWBOX: |  | 
| 44       bounds_change |= kBoundsChange_Resizes; |  | 
| 45       break; |  | 
| 46     default: |  | 
| 47       break; |  | 
| 48   } |  | 
| 49   return bounds_change; |  | 
| 50 } |  | 
| 51 |  | 
| 52 // Possible directions for changing bounds. |  | 
| 53 |  | 
| 54 const int kBoundsChangeDirection_None = 0; |  | 
| 55 const int kBoundsChangeDirection_Horizontal = 1; |  | 
| 56 const int kBoundsChangeDirection_Vertical = 2; |  | 
| 57 |  | 
| 58 int GetPositionChangeDirectionForWindowComponent(int window_component) { |  | 
| 59   int pos_change_direction = kBoundsChangeDirection_None; |  | 
| 60   switch (window_component) { |  | 
| 61     case HTTOPLEFT: |  | 
| 62     case HTBOTTOMRIGHT: |  | 
| 63     case HTGROWBOX: |  | 
| 64     case HTCAPTION: |  | 
| 65       pos_change_direction |= |  | 
| 66           kBoundsChangeDirection_Horizontal | kBoundsChangeDirection_Vertical; |  | 
| 67       break; |  | 
| 68     case HTTOP: |  | 
| 69     case HTTOPRIGHT: |  | 
| 70     case HTBOTTOM: |  | 
| 71       pos_change_direction |= kBoundsChangeDirection_Vertical; |  | 
| 72       break; |  | 
| 73     case HTBOTTOMLEFT: |  | 
| 74     case HTRIGHT: |  | 
| 75     case HTLEFT: |  | 
| 76       pos_change_direction |= kBoundsChangeDirection_Horizontal; |  | 
| 77       break; |  | 
| 78     default: |  | 
| 79       break; |  | 
| 80   } |  | 
| 81   return pos_change_direction; |  | 
| 82 } |  | 
| 83 |  | 
| 84 int GetSizeChangeDirectionForWindowComponent(int window_component) { |  | 
| 85   int size_change_direction = kBoundsChangeDirection_None; |  | 
| 86   switch (window_component) { |  | 
| 87     case HTTOPLEFT: |  | 
| 88     case HTTOPRIGHT: |  | 
| 89     case HTBOTTOMLEFT: |  | 
| 90     case HTBOTTOMRIGHT: |  | 
| 91     case HTGROWBOX: |  | 
| 92     case HTCAPTION: |  | 
| 93       size_change_direction |= |  | 
| 94           kBoundsChangeDirection_Horizontal | kBoundsChangeDirection_Vertical; |  | 
| 95       break; |  | 
| 96     case HTTOP: |  | 
| 97     case HTBOTTOM: |  | 
| 98       size_change_direction |= kBoundsChangeDirection_Vertical; |  | 
| 99       break; |  | 
| 100     case HTRIGHT: |  | 
| 101     case HTLEFT: |  | 
| 102       size_change_direction |= kBoundsChangeDirection_Horizontal; |  | 
| 103       break; |  | 
| 104     default: |  | 
| 105       break; |  | 
| 106   } |  | 
| 107   return size_change_direction; |  | 
| 108 } |  | 
| 109 |  | 
| 110 // Returns true for resize components along the right edge, where a drag in |  | 
| 111 // positive x will make the window larger. |  | 
| 112 bool IsRightEdge(int window_component) { |  | 
| 113   return window_component == HTTOPRIGHT || |  | 
| 114       window_component == HTRIGHT || |  | 
| 115       window_component == HTBOTTOMRIGHT || |  | 
| 116       window_component == HTGROWBOX; |  | 
| 117 } |  | 
| 118 |  | 
| 119 // Returns true for resize components in along the bottom edge, where a drag |  | 
| 120 // in positive y will make the window larger. |  | 
| 121 bool IsBottomEdge(int window_component) { |  | 
| 122   return window_component == HTBOTTOMLEFT || |  | 
| 123       window_component == HTBOTTOM || |  | 
| 124       window_component == HTBOTTOMRIGHT || |  | 
| 125       window_component == HTGROWBOX; |  | 
| 126 } |  | 
| 127 |  | 
| 128 void ToggleMaximizedState(aura::Window* window) { |  | 
| 129   window->SetIntProperty(aura::client::kShowStateKey, |  | 
| 130                          IsWindowMaximized(window) ? |  | 
| 131                              ui::SHOW_STATE_NORMAL : ui::SHOW_STATE_MAXIMIZED); |  | 
| 132 } |  | 
| 133 |  | 
| 134 }  // namespace |  | 
| 135 |  | 
| 136 ToplevelWindowEventFilter::ToplevelWindowEventFilter(aura::Window* owner) |  | 
| 137     : EventFilter(owner), |  | 
| 138       window_component_(HTNOWHERE) { |  | 
| 139 } |  | 
| 140 |  | 
| 141 ToplevelWindowEventFilter::~ToplevelWindowEventFilter() { |  | 
| 142 } |  | 
| 143 |  | 
| 144 bool ToplevelWindowEventFilter::PreHandleKeyEvent(aura::Window* target, |  | 
| 145                                                   aura::KeyEvent* event) { |  | 
| 146   return false; |  | 
| 147 } |  | 
| 148 |  | 
| 149 bool ToplevelWindowEventFilter::PreHandleMouseEvent(aura::Window* target, |  | 
| 150                                                     aura::MouseEvent* event) { |  | 
| 151   // Process EventFilters implementation first so that it processes |  | 
| 152   // activation/focus first. |  | 
| 153   switch (event->type()) { |  | 
| 154     case ui::ET_MOUSE_MOVED: |  | 
| 155       UpdateWindowComponentForEvent(target, event); |  | 
| 156       break; |  | 
| 157     case ui::ET_MOUSE_PRESSED: |  | 
| 158       // We also update the current window component here because for the |  | 
| 159       // mouse-drag-release-press case, where the mouse is released and |  | 
| 160       // pressed without mouse move event. |  | 
| 161       UpdateWindowComponentForEvent(target, event); |  | 
| 162       if (window_component_ == HTCAPTION && |  | 
| 163           event->flags() & ui::EF_IS_DOUBLE_CLICK) { |  | 
| 164         ToggleMaximizedState(target); |  | 
| 165       } |  | 
| 166       UpdateLocationFromEvent(target, event); |  | 
| 167       return GetBoundsChangeForWindowComponent(window_component_) != |  | 
| 168           kBoundsChange_None; |  | 
| 169     case ui::ET_MOUSE_DRAGGED: |  | 
| 170       return HandleDrag(target, event); |  | 
| 171     case ui::ET_MOUSE_RELEASED: |  | 
| 172       window_component_ = HTNOWHERE; |  | 
| 173       break; |  | 
| 174     default: |  | 
| 175       break; |  | 
| 176   } |  | 
| 177   return false; |  | 
| 178 } |  | 
| 179 |  | 
| 180 ui::TouchStatus ToplevelWindowEventFilter::PreHandleTouchEvent( |  | 
| 181     aura::Window* target, |  | 
| 182     aura::TouchEvent* event) { |  | 
| 183   // Process EventFilters implementation first so that it processes |  | 
| 184   // activation/focus first. |  | 
| 185   // TODO(sad): Allow resizing/maximizing etc. from touch? |  | 
| 186   UpdateWindowComponentForEvent(target, event); |  | 
| 187   int bounds_change = GetBoundsChangeForWindowComponent(window_component_); |  | 
| 188   if (bounds_change == kBoundsChange_None) |  | 
| 189     return ui::TOUCH_STATUS_UNKNOWN; |  | 
| 190 |  | 
| 191   // Handle touch move by simulate mouse drag with single touch. |  | 
| 192   switch (event->type()) { |  | 
| 193     case ui::ET_TOUCH_PRESSED: |  | 
| 194       UpdateLocationFromEvent(target, event); |  | 
| 195       pressed_touch_ids_.insert(event->touch_id()); |  | 
| 196       if (pressed_touch_ids_.size() == 1) |  | 
| 197         return ui::TOUCH_STATUS_START; |  | 
| 198       break; |  | 
| 199     case ui::ET_TOUCH_MOVED: |  | 
| 200       if (pressed_touch_ids_.size() == 1) { |  | 
| 201         if (HandleDrag(target, event)) |  | 
| 202           return ui::TOUCH_STATUS_CONTINUE; |  | 
| 203       } |  | 
| 204       break; |  | 
| 205     case ui::ET_TOUCH_RELEASED: |  | 
| 206       pressed_touch_ids_.erase(event->touch_id()); |  | 
| 207       if (pressed_touch_ids_.empty()) { |  | 
| 208         window_component_ = HTNOWHERE; |  | 
| 209         return ui::TOUCH_STATUS_END; |  | 
| 210       } |  | 
| 211       break; |  | 
| 212     default: |  | 
| 213       break; |  | 
| 214   } |  | 
| 215   return ui::TOUCH_STATUS_UNKNOWN; |  | 
| 216 } |  | 
| 217 |  | 
| 218 void ToplevelWindowEventFilter::MoveWindowToFront(aura::Window* target) { |  | 
| 219   aura::Window* parent = target->parent(); |  | 
| 220   aura::Window* child = target; |  | 
| 221   while (parent) { |  | 
| 222     parent->StackChildAtTop(child); |  | 
| 223     if (parent == owner()) |  | 
| 224       break; |  | 
| 225     parent = parent->parent(); |  | 
| 226     child = child->parent(); |  | 
| 227   } |  | 
| 228 } |  | 
| 229 |  | 
| 230 bool ToplevelWindowEventFilter::HandleDrag(aura::Window* target, |  | 
| 231                                            aura::LocatedEvent* event) { |  | 
| 232   // This function only be triggered to move window |  | 
| 233   // by mouse drag or touch move event. |  | 
| 234   DCHECK(event->type() == ui::ET_MOUSE_DRAGGED || |  | 
| 235          event->type() == ui::ET_TOUCH_MOVED); |  | 
| 236 |  | 
| 237   int bounds_change = GetBoundsChangeForWindowComponent(window_component_); |  | 
| 238   if (bounds_change == kBoundsChange_None) |  | 
| 239     return false; |  | 
| 240 |  | 
| 241   // Only a normal/default window can be moved/resized. |  | 
| 242   if (target->GetIntProperty(aura::client::kShowStateKey) != |  | 
| 243           ui::SHOW_STATE_NORMAL && |  | 
| 244       target->GetIntProperty(aura::client::kShowStateKey) != |  | 
| 245           ui::SHOW_STATE_DEFAULT) |  | 
| 246     return false; |  | 
| 247 |  | 
| 248   // Dragging a window moves the local coordinate frame, so do arithmetic |  | 
| 249   // in the parent coordinate frame. |  | 
| 250   gfx::Point event_location_in_parent(event->location()); |  | 
| 251   aura::Window::ConvertPointToWindow(target, target->parent(), |  | 
| 252                                      &event_location_in_parent); |  | 
| 253   int delta_x = event_location_in_parent.x() - mouse_down_offset_in_parent_.x(); |  | 
| 254   int delta_y = event_location_in_parent.y() - mouse_down_offset_in_parent_.y(); |  | 
| 255 |  | 
| 256   // The minimize size constraint may limit how much we change the window |  | 
| 257   // position.  For example, dragging the left edge to the right should stop |  | 
| 258   // repositioning the window when the minimize size is reached. |  | 
| 259   gfx::Size size = GetSizeForDrag(bounds_change, target, &delta_x, &delta_y); |  | 
| 260   gfx::Point origin = GetOriginForDrag(bounds_change, delta_x, delta_y); |  | 
| 261 |  | 
| 262   target->SetBounds(gfx::Rect(origin, size)); |  | 
| 263   return true; |  | 
| 264 } |  | 
| 265 |  | 
| 266 void ToplevelWindowEventFilter::UpdateLocationFromEvent( |  | 
| 267     aura::Window* target, |  | 
| 268     aura::LocatedEvent* event) { |  | 
| 269   mouse_down_bounds_ = target->bounds(); |  | 
| 270   mouse_down_offset_in_parent_ = event->location(); |  | 
| 271   aura::Window::ConvertPointToWindow(target, target->parent(), |  | 
| 272                                      &mouse_down_offset_in_parent_); |  | 
| 273 } |  | 
| 274 |  | 
| 275 void ToplevelWindowEventFilter::UpdateWindowComponentForEvent( |  | 
| 276     aura::Window* target, |  | 
| 277     aura::LocatedEvent* event) { |  | 
| 278   window_component_ = |  | 
| 279       target->delegate()->GetNonClientComponent(event->location()); |  | 
| 280 } |  | 
| 281 |  | 
| 282 gfx::Point ToplevelWindowEventFilter::GetOriginForDrag( |  | 
| 283     int bounds_change, |  | 
| 284     int delta_x, |  | 
| 285     int delta_y) const { |  | 
| 286   gfx::Point origin = mouse_down_bounds_.origin(); |  | 
| 287   if (bounds_change & kBoundsChange_Repositions) { |  | 
| 288     int pos_change_direction = |  | 
| 289         GetPositionChangeDirectionForWindowComponent(window_component_); |  | 
| 290     if (pos_change_direction & kBoundsChangeDirection_Horizontal) |  | 
| 291       origin.Offset(delta_x, 0); |  | 
| 292     if (pos_change_direction & kBoundsChangeDirection_Vertical) |  | 
| 293       origin.Offset(0, delta_y); |  | 
| 294   } |  | 
| 295   return origin; |  | 
| 296 } |  | 
| 297 |  | 
| 298 gfx::Size ToplevelWindowEventFilter::GetSizeForDrag( |  | 
| 299     int bounds_change, |  | 
| 300     aura::Window* target, |  | 
| 301     int* delta_x, |  | 
| 302     int* delta_y) const { |  | 
| 303   gfx::Size size = mouse_down_bounds_.size(); |  | 
| 304   if (bounds_change & kBoundsChange_Resizes) { |  | 
| 305     gfx::Size min_size = target->delegate()->GetMinimumSize(); |  | 
| 306     int size_change_direction = |  | 
| 307         GetSizeChangeDirectionForWindowComponent(window_component_); |  | 
| 308     size.SetSize( |  | 
| 309       GetWidthForDrag(size_change_direction, min_size.width(), delta_x), |  | 
| 310       GetHeightForDrag(size_change_direction, min_size.height(), delta_y)); |  | 
| 311   } |  | 
| 312   return size; |  | 
| 313 } |  | 
| 314 |  | 
| 315 int ToplevelWindowEventFilter::GetWidthForDrag(int size_change_direction, |  | 
| 316                                                int min_width, |  | 
| 317                                                int* delta_x) const { |  | 
| 318   int width = mouse_down_bounds_.width(); |  | 
| 319   if (size_change_direction & kBoundsChangeDirection_Horizontal) { |  | 
| 320     // Along the right edge, positive delta_x increases the window size. |  | 
| 321     int x_multiplier = IsRightEdge(window_component_) ? 1 : -1; |  | 
| 322     width += x_multiplier * (*delta_x); |  | 
| 323 |  | 
| 324     // Ensure we don't shrink past the minimum width and clamp delta_x |  | 
| 325     // for the window origin computation. |  | 
| 326     if (width < min_width) { |  | 
| 327       width = min_width; |  | 
| 328       *delta_x = -x_multiplier * (mouse_down_bounds_.width() - min_width); |  | 
| 329     } |  | 
| 330   } |  | 
| 331   return width; |  | 
| 332 } |  | 
| 333 |  | 
| 334 int ToplevelWindowEventFilter::GetHeightForDrag(int size_change_direction, |  | 
| 335                                                 int min_height, |  | 
| 336                                                 int* delta_y) const { |  | 
| 337   int height = mouse_down_bounds_.height(); |  | 
| 338   if (size_change_direction & kBoundsChangeDirection_Vertical) { |  | 
| 339     // Along the bottom edge, positive delta_y increases the window size. |  | 
| 340     int y_multiplier = IsBottomEdge(window_component_) ? 1 : -1; |  | 
| 341     height += y_multiplier * (*delta_y); |  | 
| 342 |  | 
| 343     // Ensure we don't shrink past the minimum height and clamp delta_y |  | 
| 344     // for the window origin computation. |  | 
| 345     if (height < min_height) { |  | 
| 346       height = min_height; |  | 
| 347       *delta_y = -y_multiplier * (mouse_down_bounds_.height() - min_height); |  | 
| 348     } |  | 
| 349   } |  | 
| 350   return height; |  | 
| 351 } |  | 
| 352 |  | 
| 353 }  // namespace aura |  | 
| OLD | NEW | 
|---|