12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/touchui/touch_selection_controller_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "grit/ui_resources.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_strings.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/aura/client/cursor_client.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/aura/env.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/aura/window.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/image/image.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/path.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/masked_window_targeter.h"
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_animations.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constants defining the visual attributes of selection handles
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kSelectionHandleLineWidth = 1;
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const SkColor kSelectionHandleLineColor =
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkColorSetRGB(0x42, 0x81, 0xf4);
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
31bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// When a handle is dragged, the drag position reported to the client view is
32bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// offset vertically to represent the cursor position. This constant specifies
33bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// the offset in  pixels above the "O" (see pic below). This is required because
34bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// say if this is zero, that means the drag position we report is the point
35bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// right above the "O" or the bottom most point of the cursor "|". In that case,
36bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// a vertical movement of even one pixel will make the handle jump to the line
37bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// below it. So when the user just starts dragging, the handle will jump to the
38bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// next line if the user makes any vertical movement. It is correct but
39bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// looks/feels weird. So we have this non-zero offset to prevent this jumping.
40bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//
41bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Editing handle widget showing the difference between the position of the
42bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// ET_GESTURE_SCROLL_UPDATE event and the drag position reported to the client:
43bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//                                  _____
44bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//                                 |  |<-|---- Drag position reported to client
45bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//                              _  |  O  |
46bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//          Vertical Padding __|   |   <-|---- ET_GESTURE_SCROLL_UPDATE position
47bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//                             |_  |_____|<--- Editing handle widget
48bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//
49bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//                                 | |
50bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//                                  T
51bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//                          Horizontal Padding
52bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//
53bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochconst int kSelectionHandleVerticalDragOffset = 5;
54bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Padding around the selection handle defining the area that will be included
56bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// in the touch target to make dragging the handle easier (see pic above).
57bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochconst int kSelectionHandleHorizPadding = 10;
58bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochconst int kSelectionHandleVertPadding = 20;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kContextMenuTimoutMs = 200;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kSelectionHandleQuickFadeDurationMs = 50;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Minimum height for selection handle bar. If the bar height is going to be
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// less than this value, handle will not be shown.
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kSelectionHandleBarMinHeight = 5;
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Maximum amount that selection handle bar can stick out of client view's
68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// boundaries.
69a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kSelectionHandleBarBottomAllowance = 3;
70a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a widget to host SelectionHandleView.
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)views::Widget* CreateTouchSelectionPopupWidget(
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::NativeView context,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    views::WidgetDelegate* widget_delegate) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Widget* widget = new views::Widget;
76a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  params.parent = context;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.delegate = widget_delegate;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  widget->Init(params);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return widget;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)gfx::Image* GetHandleImage() {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static gfx::Image* handle_image = NULL;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!handle_image) {
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed(
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IDR_TEXT_SELECTION_HANDLE);
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return handle_image;
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)gfx::Size GetHandleImageSize() {
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetHandleImage()->Size();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Cannot use gfx::UnionRect since it does not work for empty rects.
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochgfx::Rect Union(const gfx::Rect& r1, const gfx::Rect& r2) {
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int rx = std::min(r1.x(), r2.x());
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int ry = std::min(r1.y(), r2.y());
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int rr = std::max(r1.right(), r2.right());
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int rb = std::max(r1.bottom(), r2.bottom());
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return gfx::Rect(rx, ry, rr - rx, rb - ry);
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Convenience methods to convert a |rect| from screen to the |client|'s
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// coordinate system and vice versa.
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Note that this is not quite correct because it does not take into account
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// transforms such as rotation and scaling. This should be in TouchEditable.
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// TODO(varunjain): Fix this.
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochgfx::Rect ConvertFromScreen(ui::TouchEditable* client, const gfx::Rect& rect) {
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Point origin = rect.origin();
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  client->ConvertPointFromScreen(&origin);
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return gfx::Rect(origin, rect.size());
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochgfx::Rect ConvertToScreen(ui::TouchEditable* client, const gfx::Rect& rect) {
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Point origin = rect.origin();
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  client->ConvertPointToScreen(&origin);
122a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return gfx::Rect(origin, rect.size());
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef TouchSelectionControllerImpl::EditingHandleView EditingHandleView;
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TouchHandleWindowTargeter : public wm::MaskedWindowTargeter {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TouchHandleWindowTargeter(aura::Window* window,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            EditingHandleView* handle_view);
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~TouchHandleWindowTargeter() {}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // wm::MaskedWindowTargeter:
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool GetHitTestMask(aura::Window* window,
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              gfx::Path* mask) const OVERRIDE;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EditingHandleView* handle_view_;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TouchHandleWindowTargeter);
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A View that displays the text selection handle.
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TouchSelectionControllerImpl::EditingHandleView
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public views::WidgetDelegateView {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EditingHandleView(TouchSelectionControllerImpl* controller,
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    gfx::NativeView context)
154bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      : controller_(controller),
155bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        drag_offset_(0),
156bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        draw_invisible_(false) {
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    widget_.reset(CreateTouchSelectionPopupWidget(context, this));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    widget_->SetContentsView(this);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    aura::Window* window = widget_->GetNativeWindow();
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new TouchHandleWindowTargeter(window, this)));
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are owned by the TouchSelectionController.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_owned_by_client();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~EditingHandleView() {
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetWidgetVisible(false, false);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from views::WidgetDelegateView:
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool WidgetHasHitTestMask() const OVERRIDE {
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void GetWidgetHitTestMask(gfx::Path* mask) const OVERRIDE {
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gfx::Size image_size = GetHandleImageSize();
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    mask->addRect(SkIntToScalar(0), SkIntToScalar(selection_rect_.height()),
180bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding,
1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        SkIntToScalar(selection_rect_.height() + image_size.height() +
182bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            kSelectionHandleVertPadding));
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void DeleteDelegate() OVERRIDE {
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // We are owned and deleted by TouchSelectionController.
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from views::View:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
191bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (draw_invisible_)
192bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      return;
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gfx::Size image_size = GetHandleImageSize();
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int cursor_pos_x = image_size.width() / 2 - kSelectionHandleLineWidth +
195bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        kSelectionHandleHorizPadding;
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Draw the cursor line.
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    canvas->FillRect(
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        gfx::Rect(cursor_pos_x, 0,
2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                  2 * kSelectionHandleLineWidth + 1, selection_rect_.height()),
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        kSelectionHandleLineColor);
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Draw the handle image.
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    canvas->DrawImageInt(*GetHandleImage()->ToImageSkia(),
2058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        kSelectionHandleHorizPadding, selection_rect_.height());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->SetHandled();
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (event->type()) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case ui::ET_GESTURE_SCROLL_BEGIN:
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        widget_->SetCapture(this);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        controller_->SetDraggingHandle(this);
2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        drag_offset_ = event->y() - selection_rect_.height() +
215bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            kSelectionHandleVerticalDragOffset;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
217bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      case ui::ET_GESTURE_SCROLL_UPDATE: {
218bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        gfx::Point drag_pos(event->location().x(),
219bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch            event->location().y() - drag_offset_);
220bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        controller_->SelectionHandleDragged(drag_pos);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
222bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      }
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case ui::ET_GESTURE_SCROLL_END:
224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case ui::ET_SCROLL_FLING_START:
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        widget_->ReleaseCapture();
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        controller_->SetDraggingHandle(NULL);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE {
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gfx::Size image_size = GetHandleImageSize();
235bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return gfx::Size(image_size.width() + 2 * kSelectionHandleHorizPadding,
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     image_size.height() + selection_rect_.height() +
2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         kSelectionHandleVertPadding);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsWidgetVisible() const {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return widget_->IsVisible();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetWidgetVisible(bool visible, bool quick) {
2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (widget_->IsVisible() == visible)
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    wm::SetWindowVisibilityAnimationDuration(
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        widget_->GetNativeView(),
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            quick ? kSelectionHandleQuickFadeDurationMs : 0));
2518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (visible)
2528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      widget_->Show();
2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    else
2548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      widget_->Hide();
2558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetSelectionRectInScreen(const gfx::Rect& rect) {
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gfx::Size image_size = GetHandleImageSize();
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    selection_rect_ = rect;
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gfx::Rect widget_bounds(
261bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        rect.x() - image_size.width() / 2 - kSelectionHandleHorizPadding,
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        rect.y(),
263bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        image_size.width() + 2 * kSelectionHandleHorizPadding,
264bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        rect.height() + image_size.height() + kSelectionHandleVertPadding);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    widget_->SetBounds(widget_bounds);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point GetScreenPosition() {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return widget_->GetClientAreaBoundsInScreen().origin();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  void SetDrawInvisible(bool draw_invisible) {
273bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (draw_invisible_ == draw_invisible)
274bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      return;
275bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    draw_invisible_ = draw_invisible;
276bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    SchedulePaint();
277bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
278bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Rect& selection_rect() const { return selection_rect_; }
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Widget> widget_;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TouchSelectionControllerImpl* controller_;
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Rect selection_rect_;
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Vertical offset between the scroll event position and the drag position
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // reported to the client view (see the ASCII figure at the top of the file
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // and its description for more details).
289bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  int drag_offset_;
290bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
291bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // If set to true, the handle will not draw anything, hence providing an empty
292bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // widget. We need this because we may want to stop showing the handle while
293bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // it is being dragged. Since it is being dragged, we cannot destroy the
294bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // handle.
295bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  bool draw_invisible_;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(EditingHandleView);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TouchHandleWindowTargeter::TouchHandleWindowTargeter(
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    aura::Window* window,
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EditingHandleView* handle_view)
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : wm::MaskedWindowTargeter(window),
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      handle_view_(handle_view) {
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window,
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               gfx::Path* mask) const {
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Rect& selection_rect = handle_view_->selection_rect();
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Size image_size = GetHandleImageSize();
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mask->addRect(SkIntToScalar(0), SkIntToScalar(selection_rect.height()),
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding,
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SkIntToScalar(selection_rect.height() + image_size.height() +
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    kSelectionHandleVertPadding));
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchSelectionControllerImpl::TouchSelectionControllerImpl(
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::TouchEditable* client_view)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : client_view_(client_view),
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_widget_(NULL),
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      selection_handle_1_(new EditingHandleView(this,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          client_view->GetNativeView())),
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      selection_handle_2_(new EditingHandleView(this,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          client_view->GetNativeView())),
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cursor_handle_(new EditingHandleView(this,
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     client_view->GetNativeView())),
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      context_menu_(NULL),
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dragging_handle_(NULL) {
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_widget_ = Widget::GetTopLevelWidgetForNativeView(
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_view_->GetNativeView());
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (client_widget_)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_widget_->AddObserver(this);
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  aura::Env::GetInstance()->AddPreTargetHandler(this);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchSelectionControllerImpl::~TouchSelectionControllerImpl() {
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HideContextMenu();
339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  aura::Env::GetInstance()->RemovePreTargetHandler(this);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (client_widget_)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_widget_->RemoveObserver(this);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::SelectionChanged() {
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect r1, r2;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_view_->GetSelectionEndPoints(&r1, &r2);
347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect screen_rect_1 = ConvertToScreen(client_view_, r1);
348a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect screen_rect_2 = ConvertToScreen(client_view_, r2);
349a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect client_bounds = client_view_->GetBounds();
350a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (r1.y() < client_bounds.y())
351a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    r1.Inset(0, client_bounds.y() - r1.y(), 0, 0);
352a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (r2.y() < client_bounds.y())
353a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    r2.Inset(0, client_bounds.y() - r2.y(), 0, 0);
354a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect screen_rect_1_clipped = ConvertToScreen(client_view_, r1);
355a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect screen_rect_2_clipped = ConvertToScreen(client_view_, r2);
356a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (screen_rect_1_clipped == selection_end_point_1_clipped_ &&
357a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      screen_rect_2_clipped == selection_end_point_2_clipped_)
3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  selection_end_point_1_ = screen_rect_1;
3618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  selection_end_point_2_ = screen_rect_2;
362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  selection_end_point_1_clipped_ = screen_rect_1_clipped;
363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  selection_end_point_2_clipped_ = screen_rect_2_clipped;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (client_view_->DrawsHandles()) {
366a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    UpdateContextMenu();
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dragging_handle_) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to reposition only the selection handle that is being dragged.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The other handle stays the same. Also, the selection handle being dragged
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // will always be at the end of selection, while the other handle will be at
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the start.
3748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If the new location of this handle is out of client view, its widget
3758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // should not get hidden, since it should still receive touch events.
3768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Hence, we are not using |SetHandleSelectionRect()| method here.
377a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    dragging_handle_->SetSelectionRectInScreen(screen_rect_2_clipped);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
379bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Temporary fix for selection handle going outside a window. On a webpage,
380bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // the page should scroll if the selection handle is dragged outside the
381bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // window. That does not happen currently. So we just hide the handle for
382bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // now.
383bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // TODO(varunjain): Fix this: crbug.com/269003
384a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(r2));
385bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (dragging_handle_ != cursor_handle_.get()) {
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The non-dragging-handle might have recently become visible.
3888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      EditingHandleView* non_dragging_handle = selection_handle_1_.get();
3898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if (dragging_handle_ == selection_handle_1_) {
3908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        non_dragging_handle = selection_handle_2_.get();
3918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // if handle 1 is being dragged, it is corresponding to the end of
3928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // selection and the other handle to the start of selection.
3938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        selection_end_point_1_ = screen_rect_2;
3948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        selection_end_point_2_ = screen_rect_1;
395a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        selection_end_point_1_clipped_ = screen_rect_2_clipped;
396a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        selection_end_point_2_clipped_ = screen_rect_1_clipped;
3978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
398a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      SetHandleSelectionRect(non_dragging_handle, r1, screen_rect_1_clipped);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
401a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    UpdateContextMenu();
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if there is any selection at all.
404a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (screen_rect_1.origin() == screen_rect_2.origin()) {
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      selection_handle_1_->SetWidgetVisible(false, false);
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      selection_handle_2_->SetWidgetVisible(false, false);
407a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      SetHandleSelectionRect(cursor_handle_.get(), r1, screen_rect_1_clipped);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor_handle_->SetWidgetVisible(false, false);
412a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SetHandleSelectionRect(selection_handle_1_.get(), r1,
413a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           screen_rect_1_clipped);
414a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SetHandleSelectionRect(selection_handle_2_.get(), r2,
415a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           screen_rect_2_clipped);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool TouchSelectionControllerImpl::IsHandleDragInProgress() {
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return !!dragging_handle_;
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TouchSelectionControllerImpl::HideHandles(bool quick) {
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  selection_handle_1_->SetWidgetVisible(false, quick);
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  selection_handle_2_->SetWidgetVisible(false, quick);
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor_handle_->SetWidgetVisible(false, quick);
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::SetDraggingHandle(
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EditingHandleView* handle) {
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dragging_handle_ = handle;
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dragging_handle_)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    HideContextMenu();
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StartContextMenuTimer();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchSelectionControllerImpl::SelectionHandleDragged(
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Point& drag_pos) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not want to show the context menu while dragging.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HideContextMenu();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(dragging_handle_);
444bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  gfx::Point drag_pos_in_client = drag_pos;
445bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ConvertPointToClientView(dragging_handle_, &drag_pos_in_client);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dragging_handle_ == cursor_handle_.get()) {
448bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    client_view_->MoveCaretTo(drag_pos_in_client);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find the stationary selection handle.
4538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  gfx::Rect fixed_handle_rect = selection_end_point_1_;
4548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (selection_handle_1_ == dragging_handle_)
4558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    fixed_handle_rect = selection_end_point_2_;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find selection end points in client_view's coordinate system.
4588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  gfx::Point p2 = fixed_handle_rect.origin();
4598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  p2.Offset(0, fixed_handle_rect.height() / 2);
4607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  client_view_->ConvertPointFromScreen(&p2);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Instruct client_view to select the region between p1 and p2. The position
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of |fixed_handle| is the start and that of |dragging_handle| is the end
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of selection.
465bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  client_view_->SelectRect(p2, drag_pos_in_client);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchSelectionControllerImpl::ConvertPointToClientView(
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EditingHandleView* source, gfx::Point* point) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  View::ConvertPointToScreen(source, point);
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_view_->ConvertPointFromScreen(point);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void TouchSelectionControllerImpl::SetHandleSelectionRect(
4758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    EditingHandleView* handle,
4768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const gfx::Rect& rect,
4778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const gfx::Rect& rect_in_screen) {
478a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  handle->SetWidgetVisible(ShouldShowHandleFor(rect), false);
4798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (handle->IsWidgetVisible())
4808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    handle->SetSelectionRectInScreen(rect_in_screen);
4818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
483a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool TouchSelectionControllerImpl::ShouldShowHandleFor(
484a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const gfx::Rect& rect) const {
485a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (rect.height() < kSelectionHandleBarMinHeight)
486a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return false;
487a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect bounds = client_view_->GetBounds();
488a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance);
489a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return bounds.Contains(rect);
490a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
491a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TouchSelectionControllerImpl::IsCommandIdEnabled(int command_id) const {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return client_view_->IsCommandIdEnabled(command_id);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::ExecuteCommand(int command_id,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int event_flags) {
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HideContextMenu();
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_view_->ExecuteCommand(command_id, event_flags);
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::OpenContextMenu() {
5037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Context menu should appear centered on top of the selected region.
5044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const gfx::Rect rect = context_menu_->GetAnchorRect();
5054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const gfx::Point anchor(rect.CenterPoint().x(), rect.y());
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HideContextMenu();
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_view_->OpenContextMenu(anchor);
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::OnMenuClosed(TouchEditingMenuView* menu) {
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (menu == context_menu_)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_menu_ = NULL;
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::OnWidgetClosing(Widget* widget) {
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(client_widget_, widget);
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_widget_ = NULL;
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::OnWidgetBoundsChanged(
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Widget* widget,
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& new_bounds) {
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(client_widget_, widget);
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HideContextMenu();
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SelectionChanged();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
528010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void TouchSelectionControllerImpl::OnKeyEvent(ui::KeyEvent* event) {
529010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  client_view_->DestroyTouchSelection();
530010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
531010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
532010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void TouchSelectionControllerImpl::OnMouseEvent(ui::MouseEvent* event) {
533010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
534010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      client_view_->GetNativeView()->GetRootWindow());
535010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!cursor_client || cursor_client->IsMouseEventsEnabled())
536010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    client_view_->DestroyTouchSelection();
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
539010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void TouchSelectionControllerImpl::OnScrollEvent(ui::ScrollEvent* event) {
540010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  client_view_->DestroyTouchSelection();
541010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
542010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchSelectionControllerImpl::ContextMenuTimerFired() {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get selection end points in client_view's space.
5457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Rect end_rect_1_in_screen;
5467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Rect end_rect_2_in_screen;
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cursor_handle_->IsWidgetVisible()) {
548a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    end_rect_1_in_screen = selection_end_point_1_clipped_;
5497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    end_rect_2_in_screen = end_rect_1_in_screen;
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
551a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    end_rect_1_in_screen = selection_end_point_1_clipped_;
552a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    end_rect_2_in_screen = selection_end_point_2_clipped_;
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Convert from screen to client.
5567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Rect end_rect_1(ConvertFromScreen(client_view_, end_rect_1_in_screen));
5577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Rect end_rect_2(ConvertFromScreen(client_view_, end_rect_2_in_screen));
5587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if selection is completely inside the view, we display the context menu
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in the middle of the end points on the top. Else, we show it above the
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // visible handle. If no handle is visible, we do not show the menu.
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect menu_anchor;
563a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (ShouldShowHandleFor(end_rect_1) &&
564a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      ShouldShowHandleFor(end_rect_2))
5657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    menu_anchor = Union(end_rect_1_in_screen,end_rect_2_in_screen);
566a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  else if (ShouldShowHandleFor(end_rect_1))
5677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    menu_anchor = end_rect_1_in_screen;
568a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  else if (ShouldShowHandleFor(end_rect_2))
5697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    menu_anchor = end_rect_2_in_screen;
5707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  else
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!context_menu_);
5747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  context_menu_ = TouchEditingMenuView::Create(this, menu_anchor,
575010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                               GetHandleImageSize(),
5767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               client_view_->GetNativeView());
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TouchSelectionControllerImpl::StartContextMenuTimer() {
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (context_menu_timer_.IsRunning())
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context_menu_timer_.Start(
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kContextMenuTimoutMs),
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this,
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &TouchSelectionControllerImpl::ContextMenuTimerFired);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
589a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid TouchSelectionControllerImpl::UpdateContextMenu() {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hide context menu to be shown when the timer fires.
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HideContextMenu();
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StartContextMenuTimer();
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchSelectionControllerImpl::HideContextMenu() {
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (context_menu_)
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_menu_->Close();
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context_menu_ = NULL;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_menu_timer_.Stop();
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochgfx::NativeView TouchSelectionControllerImpl::GetCursorHandleNativeView() {
603a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return cursor_handle_->GetWidget()->GetNativeView();
604a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
605a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point TouchSelectionControllerImpl::GetSelectionHandle1Position() {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return selection_handle_1_->GetScreenPosition();
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point TouchSelectionControllerImpl::GetSelectionHandle2Position() {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return selection_handle_2_->GetScreenPosition();
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Point TouchSelectionControllerImpl::GetCursorHandlePosition() {
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cursor_handle_->GetScreenPosition();
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TouchSelectionControllerImpl::IsSelectionHandle1Visible() {
6198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return selection_handle_1_->IsWidgetVisible();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TouchSelectionControllerImpl::IsSelectionHandle2Visible() {
6238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return selection_handle_2_->IsWidgetVisible();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TouchSelectionControllerImpl::IsCursorHandleVisible() {
6278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return cursor_handle_->IsWidgetVisible();
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
631