x11_panel_resizer.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1// Copyright 2014 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 "chrome/browser/ui/views/panels/x11_panel_resizer.h"
6
7#include "chrome/browser/ui/panels/panel.h"
8#include "chrome/browser/ui/panels/panel_manager.h"
9#include "ui/aura/window.h"
10#include "ui/aura/window_delegate.h"
11#include "ui/base/hit_test.h"
12#include "ui/events/event.h"
13#include "ui/events/event_utils.h"
14#include "ui/views/view.h"
15
16namespace {
17
18// Returns true if the window can be resized via |component|.
19bool IsWindowBorder(int component) {
20  return component == HTBOTTOM ||
21      component == HTBOTTOMLEFT ||
22      component == HTBOTTOMRIGHT ||
23      component == HTLEFT ||
24      component == HTRIGHT ||
25      component == HTTOP ||
26      component == HTTOPLEFT ||
27      component == HTTOPRIGHT;
28}
29
30}  // namespace
31
32X11PanelResizer::X11PanelResizer(Panel* panel, aura::Window* window)
33    : panel_(panel),
34      window_(window),
35      resize_state_(NOT_RESIZING),
36      resize_component_(HTNOWHERE) {
37}
38
39X11PanelResizer::~X11PanelResizer() {
40  StopResizing(NULL, true);
41}
42
43void X11PanelResizer::OnMousePressed(ui::MouseEvent* event) {
44  if (resize_state_ != NOT_RESIZING ||
45      event->type() != ui::ET_MOUSE_PRESSED ||
46      !event->IsLeftMouseButton() ||
47      !event->native_event()) {
48    return;
49  }
50
51  int component = window_->delegate()->GetNonClientComponent(event->location());
52  if (!IsWindowBorder(component))
53    return;
54
55  // Set capture so that we get notified of all subsequent events.
56  window_->SetCapture();
57
58  resize_state_ = RESIZE_CAN_START;
59  initial_press_location_in_screen_ = ui::EventSystemLocationFromNative(
60      event->native_event());
61  resize_component_ = component;
62  event->StopPropagation();
63}
64
65void X11PanelResizer::OnMouseDragged(ui::MouseEvent* event) {
66  if (resize_state_ != RESIZE_CAN_START &&
67      resize_state_ != RESIZE_IN_PROGRESS) {
68    return;
69  }
70
71  if (!event->native_event())
72    return;
73
74  // Get the location in screen coordinates from the XEvent because converting
75  // the mouse location to screen coordinates using ScreenPositionClient returns
76  // an incorrect location while the panel is moving. See crbug.com/353393 for
77  // more details.
78  // TODO: Fix conversion to screen coordinates.
79  gfx::Point location_in_screen = ui::EventSystemLocationFromNative(
80      event->native_event());
81  if (resize_state_ == RESIZE_CAN_START) {
82    gfx::Vector2d delta =
83        location_in_screen - initial_press_location_in_screen_;
84    if (views::View::ExceededDragThreshold(delta)) {
85      resize_state_ = RESIZE_IN_PROGRESS;
86      panel_->manager()->StartResizingByMouse(panel_, location_in_screen,
87                                              resize_component_);
88    }
89  }
90
91  if (resize_state_ == RESIZE_IN_PROGRESS)
92    panel_->manager()->ResizeByMouse(location_in_screen);
93
94  event->StopPropagation();
95}
96
97void X11PanelResizer::StopResizing(ui::MouseEvent* event, bool canceled) {
98  if (resize_state_ == NOT_RESIZING)
99    return;
100
101  if (resize_state_ == RESIZE_IN_PROGRESS) {
102    panel_->manager()->EndResizingByMouse(canceled);
103    window_->ReleaseCapture();
104  }
105  if (event)
106    event->StopPropagation();
107  resize_state_ = NOT_RESIZING;
108}
109
110void X11PanelResizer::OnMouseEvent(ui::MouseEvent* event) {
111  switch (event->type()) {
112    case ui::ET_MOUSE_PRESSED:
113      OnMousePressed(event);
114      break;
115    case ui::ET_MOUSE_DRAGGED:
116      OnMouseDragged(event);
117      break;
118    case ui::ET_MOUSE_RELEASED:
119      StopResizing(event, false);
120      break;
121    case ui::ET_MOUSE_CAPTURE_CHANGED:
122      StopResizing(event, true);
123      break;
124    default:
125      break;
126  }
127}
128