Commit 0663980b authored by Mike Wasserman's avatar Mike Wasserman Committed by Commit Bot

ws: Add touch selection controller support for pointer watcher.

Allows ws clients to close touch ui on events outside their windows.

Add a new PointerWatcher plumbing to [Mus]ViewsDelegate.
Wires up watchers to the Mus-only PointerWatcherEventRouter.
(ui/views/mus/* is not allowed as a dependency of ui/views/*)

Destroy the touch selection ui on PointerWatcher mouse events.

Bug: 884394, 887725
Test: Mouse events outside the KSV window close KSV text touch ui.
Change-Id: I0e41da4d03719001191f7d5ab669bcc1805bd63c
Reviewed-on: https://chromium-review.googlesource.com/1232955Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Michael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593001}
parent 4d13de11
......@@ -92,13 +92,12 @@ class UI_BASE_EXPORT TouchEditingControllerDeprecated {
class UI_BASE_EXPORT TouchEditingControllerFactory {
public:
virtual ~TouchEditingControllerFactory() {}
static void SetInstance(TouchEditingControllerFactory* instance);
virtual TouchEditingControllerDeprecated* Create(TouchEditable* client_view)
= 0;
protected:
virtual ~TouchEditingControllerFactory() {}
};
} // namespace ui
......
......@@ -6,6 +6,7 @@
#include "ui/views/mus/ax_remote_host.h"
#include "ui/views/mus/mus_client.h"
#include "ui/views/mus/pointer_watcher_event_router.h"
namespace views {
......@@ -19,4 +20,19 @@ void MusViewsDelegate::NotifyAccessibilityEvent(View* view,
MusClient::Get()->ax_remote_host()->HandleEvent(view, event_type);
}
void MusViewsDelegate::AddPointerWatcher(PointerWatcher* pointer_watcher,
bool wants_moves) {
MusClient::Get()->pointer_watcher_event_router()->AddPointerWatcher(
pointer_watcher, wants_moves);
}
void MusViewsDelegate::RemovePointerWatcher(PointerWatcher* pointer_watcher) {
MusClient::Get()->pointer_watcher_event_router()->RemovePointerWatcher(
pointer_watcher);
}
bool MusViewsDelegate::IsPointerWatcherSupported() const {
return true;
}
} // namespace views
......@@ -20,6 +20,10 @@ class VIEWS_MUS_EXPORT MusViewsDelegate : public ViewsDelegate {
// ViewsDelegate:
void NotifyAccessibilityEvent(View* view,
ax::mojom::Event event_type) override;
void AddPointerWatcher(PointerWatcher* pointer_watcher,
bool wants_moves) override;
void RemovePointerWatcher(PointerWatcher* pointer_watcher) override;
bool IsPointerWatcherSupported() const override;
private:
LayoutProvider layout_provider_;
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Copyright 2018 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/views/touchui/touch_selection_controller_impl.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "ui/aura/client/cursor_client.h"
......@@ -19,6 +18,7 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/path.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/coordinate_conversion.h"
......@@ -74,14 +74,14 @@ const int kSelectionHandleBarBottomAllowance = 3;
// Creates a widget to host SelectionHandleView.
views::Widget* CreateTouchSelectionPopupWidget(
gfx::NativeView context,
gfx::NativeView parent,
views::WidgetDelegate* widget_delegate) {
views::Widget* widget = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.parent = context;
params.parent = parent;
params.delegate = widget_delegate;
widget->Init(params);
return widget;
......@@ -210,17 +210,17 @@ using EditingHandleView = TouchSelectionControllerImpl::EditingHandleView;
// A View that displays the text selection handle.
class TouchSelectionControllerImpl::EditingHandleView
: public views::WidgetDelegateView {
: public WidgetDelegateView {
public:
EditingHandleView(TouchSelectionControllerImpl* controller,
gfx::NativeView context,
gfx::NativeView parent,
bool is_cursor_handle)
: controller_(controller),
image_(GetCenterHandleImage()),
is_cursor_handle_(is_cursor_handle),
draw_invisible_(false),
weak_ptr_factory_(this) {
widget_.reset(CreateTouchSelectionPopupWidget(context, this));
widget_.reset(CreateTouchSelectionPopupWidget(parent, this));
targeter_ = new aura::WindowTargeter();
aura::Window* window = widget_->GetNativeWindow();
......@@ -240,12 +240,12 @@ class TouchSelectionControllerImpl::EditingHandleView
return selection_bound_.type();
}
// Overridden from views::WidgetDelegateView:
// WidgetDelegateView:
void DeleteDelegate() override {
// We are owned and deleted by TouchSelectionControllerImpl.
}
// Overridden from views::View:
// View:
void OnPaint(gfx::Canvas* canvas) override {
if (draw_invisible_)
return;
......@@ -405,23 +405,20 @@ class TouchSelectionControllerImpl::EditingHandleView
TouchSelectionControllerImpl::TouchSelectionControllerImpl(
ui::TouchEditable* client_view)
: client_view_(client_view),
client_widget_(nullptr),
selection_handle_1_(new EditingHandleView(this,
client_view->GetNativeView(),
false)),
selection_handle_2_(new EditingHandleView(this,
client_view->GetNativeView(),
false)),
cursor_handle_(new EditingHandleView(this,
client_view->GetNativeView(),
true)),
command_executed_(false),
dragging_handle_(nullptr) {
selection_handle_1_(
new EditingHandleView(this, client_view->GetNativeView(), false)),
selection_handle_2_(
new EditingHandleView(this, client_view->GetNativeView(), false)),
cursor_handle_(
new EditingHandleView(this, client_view->GetNativeView(), true)) {
selection_start_time_ = base::TimeTicks::Now();
aura::Window* client_window = client_view_->GetNativeView();
client_widget_ = Widget::GetTopLevelWidgetForNativeView(client_window);
// Observe client widget moves and resizes to update the selection handles.
if (client_widget_)
client_widget_->AddObserver(this);
if (ViewsDelegate::GetInstance()->IsPointerWatcherSupported())
ViewsDelegate::GetInstance()->AddPointerWatcher(this, true);
aura::Env::GetInstance()->AddPreTargetHandler(this);
}
......@@ -430,6 +427,8 @@ TouchSelectionControllerImpl::~TouchSelectionControllerImpl() {
command_executed_);
HideQuickMenu();
aura::Env::GetInstance()->RemovePreTargetHandler(this);
if (ViewsDelegate::GetInstance()->IsPointerWatcherSupported())
ViewsDelegate::GetInstance()->RemovePointerWatcher(this);
if (client_widget_)
client_widget_->RemoveObserver(this);
}
......@@ -627,6 +626,18 @@ void TouchSelectionControllerImpl::OnWidgetBoundsChanged(
SelectionChanged();
}
void TouchSelectionControllerImpl::OnPointerEventObserved(
const ui::PointerEvent& event,
const gfx::Point& location_in_screen,
gfx::NativeView target) {
// Disregard CursorClient::IsMouseEventsEnabled, it is disabled for touch
// events in this client, but not re-enabled for mouse events sent elsewhere.
if (event.pointer_details().pointer_type ==
ui::EventPointerType::POINTER_TYPE_MOUSE) {
client_view_->DestroyTouchSelection();
}
}
void TouchSelectionControllerImpl::OnKeyEvent(ui::KeyEvent* event) {
client_view_->DestroyTouchSelection();
}
......@@ -751,11 +762,11 @@ gfx::Rect TouchSelectionControllerImpl::GetExpectedHandleBounds(
return GetSelectionWidgetBounds(bound);
}
views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() {
WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() {
return selection_handle_1_.get();
}
views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() {
WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() {
return selection_handle_2_.get();
}
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Copyright 2018 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.
#ifndef UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
#define UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
#ifndef UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
#define UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
#include "base/macros.h"
#include "base/timer/timer.h"
......@@ -11,6 +11,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/selection_bound.h"
#include "ui/touch_selection/touch_selection_menu_runner.h"
#include "ui/views/pointer_watcher.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/widget_observer.h"
......@@ -29,17 +30,16 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
: public ui::TouchEditingControllerDeprecated,
public ui::TouchSelectionMenuClient,
public WidgetObserver,
public PointerWatcher,
public ui::EventHandler {
public:
class EditingHandleView;
// Use TextSelectionController::create().
explicit TouchSelectionControllerImpl(
ui::TouchEditable* client_view);
// Use ui::TouchEditingControllerFactory::Create() instead.
explicit TouchSelectionControllerImpl(ui::TouchEditable* client_view);
~TouchSelectionControllerImpl() override;
// TextSelectionController.
// ui::TouchEditingControllerDeprecated:
void SelectionChanged() override;
bool IsHandleDragInProgress() override;
void HideHandles(bool quick) override;
......@@ -70,19 +70,22 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
// |bound| should be the clipped version of the selection bound.
bool ShouldShowHandleFor(const gfx::SelectionBound& bound) const;
// Overridden from ui::TouchSelectionMenuClient.
// ui::TouchSelectionMenuClient:
bool IsCommandIdEnabled(int command_id) const override;
void ExecuteCommand(int command_id, int event_flags) override;
void RunContextMenu() override;
// Overridden from WidgetObserver. We will observe the widget backing the
// |client_view_| so that when its moved/resized, we can update the selection
// handles appropriately.
// WidgetObserver:
void OnWidgetClosing(Widget* widget) override;
void OnWidgetBoundsChanged(Widget* widget,
const gfx::Rect& new_bounds) override;
// Overriden from ui::EventHandler.
// PointerWatcher:
void OnPointerEventObserved(const ui::PointerEvent& event,
const gfx::Point& location_in_screen,
gfx::NativeView target) override;
// ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
void OnMouseEvent(ui::MouseEvent* event) override;
void OnScrollEvent(ui::ScrollEvent* event) override;
......@@ -112,15 +115,15 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
bool IsSelectionHandle2Visible();
bool IsCursorHandleVisible();
gfx::Rect GetExpectedHandleBounds(const gfx::SelectionBound& bound);
views::WidgetDelegateView* GetHandle1View();
views::WidgetDelegateView* GetHandle2View();
WidgetDelegateView* GetHandle1View();
WidgetDelegateView* GetHandle2View();
ui::TouchEditable* client_view_;
Widget* client_widget_;
Widget* client_widget_ = nullptr;
std::unique_ptr<EditingHandleView> selection_handle_1_;
std::unique_ptr<EditingHandleView> selection_handle_2_;
std::unique_ptr<EditingHandleView> cursor_handle_;
bool command_executed_;
bool command_executed_ = false;
base::TimeTicks selection_start_time_;
// Timer to trigger quick menu (Quick menu is not shown if the selection
......@@ -129,7 +132,7 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
base::OneShotTimer quick_menu_timer_;
// Pointer to the SelectionHandleView being dragged during a drag session.
EditingHandleView* dragging_handle_;
EditingHandleView* dragging_handle_ = nullptr;
// In cursor mode, the two selection bounds are the same and correspond to
// |cursor_handle_|; otherwise, they correspond to |selection_handle_1_| and
......@@ -148,4 +151,4 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
} // namespace views
#endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
#endif // UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
......@@ -48,8 +48,7 @@ ViewsDelegate* ViewsDelegate::GetInstance() {
void ViewsDelegate::SaveWindowPlacement(const Widget* widget,
const std::string& window_name,
const gfx::Rect& bounds,
ui::WindowShowState show_state) {
}
ui::WindowShowState show_state) {}
bool ViewsDelegate::GetSavedWindowPlacement(
const Widget* widget,
......@@ -66,8 +65,7 @@ void ViewsDelegate::NotifyMenuItemFocused(const base::string16& menu_name,
const base::string16& menu_item_name,
int item_index,
int item_count,
bool has_submenu) {
}
bool has_submenu) {}
ViewsDelegate::ProcessMenuAcceleratorResult
ViewsDelegate::ProcessAcceleratorWhileMenuShowing(
......@@ -98,11 +96,9 @@ NonClientFrameView* ViewsDelegate::CreateDefaultNonClientFrameView(
return nullptr;
}
void ViewsDelegate::AddRef() {
}
void ViewsDelegate::AddRef() {}
void ViewsDelegate::ReleaseRef() {
}
void ViewsDelegate::ReleaseRef() {}
void ViewsDelegate::OnBeforeWidgetInit(
Widget::InitParams* params,
......@@ -140,4 +136,16 @@ bool ViewsDelegate::ShouldMirrorArrowsInRTL() const {
return true;
}
void ViewsDelegate::AddPointerWatcher(PointerWatcher*, bool) {
NOTREACHED();
}
void ViewsDelegate::RemovePointerWatcher(PointerWatcher*) {
NOTREACHED();
}
bool ViewsDelegate::IsPointerWatcherSupported() const {
return false;
}
} // namespace views
......@@ -34,13 +34,14 @@ class Rect;
namespace ui {
class ContextFactory;
class TouchEditingControllerFactory;
}
namespace views {
class NativeWidget;
class NonClientFrameView;
class ViewsTouchEditingControllerFactory;
class PointerWatcher;
class View;
class Widget;
......@@ -206,11 +207,18 @@ class VIEWS_EXPORT ViewsDelegate {
// opens in the opposite direction.
virtual bool ShouldMirrorArrowsInRTL() const;
// Allows lower-level views components to use Mus-only PointerWatcher wiring.
// TODO(crbug.com/887725): Support PointerWatcher without mus, refactor.
virtual void AddPointerWatcher(PointerWatcher* pointer_watcher,
bool wants_moves);
virtual void RemovePointerWatcher(PointerWatcher* pointer_watcher);
virtual bool IsPointerWatcherSupported() const;
protected:
ViewsDelegate();
private:
std::unique_ptr<ViewsTouchEditingControllerFactory>
std::unique_ptr<ui::TouchEditingControllerFactory>
editing_controller_factory_;
#if defined(USE_AURA)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment