Commit acb5a6e0 authored by Mike Wasserman's avatar Mike Wasserman Committed by Commit Bot

mash: Make TouchSelectionControllerClientAura use ui::EventObserver

Close touch selection ui in Mash on events outside the browser window.
(global pre-target handlers are not supported in window service clients)
This follows and refines the new pattern in TouchSelectionControllerImpl.

Bug: 896973, 884394
Test: Text touch selection ui hides as expected in Views and Content.
Change-Id: Iedba63a7ce5d5f70f9763cf540d26ee69cee5f28
Reviewed-on: https://chromium-review.googlesource.com/c/1292274
Commit-Queue: Michael Wasserman <msw@chromium.org>
Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602084}
parent bdc6f771
......@@ -16,6 +16,7 @@
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/events/event_observer.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/strings/grit/ui_strings.h"
......@@ -47,79 +48,59 @@ gfx::Rect ConvertRectToScreen(aura::Window* window, const gfx::RectF& rect) {
} // namespace
// A pre-target event handler for aura::Env which deactivates touch selection on
// mouse and keyboard events.
class TouchSelectionControllerClientAura::EnvPreTargetHandler
: public ui::EventHandler {
// An aura::Env event observer that hides touch selection ui on mouse and
// keyboard events, including those targeting windows outside the client.
class TouchSelectionControllerClientAura::EnvEventObserver
: public ui::EventObserver {
public:
EnvPreTargetHandler(ui::TouchSelectionController* selection_controller,
aura::Window* window);
~EnvPreTargetHandler() override;
EnvEventObserver(ui::TouchSelectionController* selection_controller,
aura::Window* window)
: selection_controller_(selection_controller), window_(window) {
// Observe certain event types sent to any event target, to hide this ui.
aura::Env* env = aura::Env::GetInstance();
std::set<ui::EventType> types = {ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_MOVED,
ui::ET_KEY_PRESSED, ui::ET_MOUSEWHEEL};
env->AddEventObserver(this, env, types);
}
~EnvEventObserver() override {
aura::Env::GetInstance()->RemoveEventObserver(this);
}
private:
// EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
void OnMouseEvent(ui::MouseEvent* event) override;
void OnScrollEvent(ui::ScrollEvent* event) override;
// ui::EventObserver:
void OnEvent(const ui::Event& event) override {
DCHECK_NE(ui::TouchSelectionController::INACTIVE,
selection_controller_->active_status());
if (event.IsMouseEvent()) {
// Check IsMouseEventsEnabled, except on Mus, where it's disabled on touch
// events in this client, but not re-enabled on mouse events elsewhere.
auto* cursor = aura::client::GetCursorClient(window_->GetRootWindow());
if (cursor && !cursor->IsMouseEventsEnabled() &&
aura::Env::GetInstance()->mode() != aura::Env::Mode::MUS) {
return;
}
// Windows OS unhandled WM_POINTER* may be redispatched as WM_MOUSE*.
// Avoid adjusting the handles on synthesized events or events generated
// from touch as this can clear an active selection generated by the pen.
if ((event.flags() & (ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH)) ||
event.AsMouseEvent()->pointer_details().pointer_type ==
ui::EventPointerType::POINTER_TYPE_PEN) {
return;
}
}
selection_controller_->HideAndDisallowShowingAutomatically();
}
ui::TouchSelectionController* selection_controller_;
aura::Window* window_;
DISALLOW_COPY_AND_ASSIGN(EnvPreTargetHandler);
DISALLOW_COPY_AND_ASSIGN(EnvEventObserver);
};
TouchSelectionControllerClientAura::EnvPreTargetHandler::EnvPreTargetHandler(
ui::TouchSelectionController* selection_controller,
aura::Window* window)
: selection_controller_(selection_controller), window_(window) {
aura::Env::GetInstance()->AddPreTargetHandler(this);
}
TouchSelectionControllerClientAura::EnvPreTargetHandler::
~EnvPreTargetHandler() {
aura::Env::GetInstance()->RemovePreTargetHandler(this);
}
void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnKeyEvent(
ui::KeyEvent* event) {
DCHECK_NE(ui::TouchSelectionController::INACTIVE,
selection_controller_->active_status());
selection_controller_->HideAndDisallowShowingAutomatically();
}
void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent(
ui::MouseEvent* event) {
DCHECK_NE(ui::TouchSelectionController::INACTIVE,
selection_controller_->active_status());
// Avoid adjusting the handles on synthesized or events
// generated from touch as this can clear an active selection
// generated by the pen.
if (event->flags() & (ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH))
return;
// Don't hide handles for pen input.
if (event->pointer_details().pointer_type ==
ui::EventPointerType::POINTER_TYPE_PEN)
return;
// If mouse events are not enabled, this mouse event is synthesized from a
// touch event in which case we don't want to deactivate touch selection.
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(window_->GetRootWindow());
if (!cursor_client || cursor_client->IsMouseEventsEnabled())
selection_controller_->HideAndDisallowShowingAutomatically();
}
void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnScrollEvent(
ui::ScrollEvent* event) {
DCHECK_NE(ui::TouchSelectionController::INACTIVE,
selection_controller_->active_status());
selection_controller_->HideAndDisallowShowingAutomatically();
}
TouchSelectionControllerClientAura::TouchSelectionControllerClientAura(
RenderWidgetHostViewAura* rwhva)
: rwhva_(rwhva),
......@@ -382,12 +363,12 @@ void TouchSelectionControllerClientAura::OnSelectionEvent(
FALLTHROUGH;
case ui::INSERTION_HANDLE_SHOWN:
UpdateQuickMenu();
env_pre_target_handler_.reset(new EnvPreTargetHandler(
rwhva_->selection_controller(), rwhva_->GetNativeView()));
env_event_observer_ = std::make_unique<EnvEventObserver>(
rwhva_->selection_controller(), rwhva_->GetNativeView());
break;
case ui::SELECTION_HANDLES_CLEARED:
case ui::INSERTION_HANDLE_CLEARED:
env_pre_target_handler_.reset();
env_event_observer_.reset();
quick_menu_requested_ = false;
UpdateQuickMenu();
break;
......
......@@ -70,7 +70,7 @@ class CONTENT_EXPORT TouchSelectionControllerClientAura
private:
friend class TestTouchSelectionControllerClientAura;
class EnvPreTargetHandler;
class EnvEventObserver;
bool IsQuickMenuAvailable() const;
void ShowQuickMenu();
......@@ -133,9 +133,8 @@ class CONTENT_EXPORT TouchSelectionControllerClientAura
bool show_quick_menu_immediately_for_test_;
// A pre-target event handler for aura::Env which deactivates touch selection
// on mouse and keyboard events.
std::unique_ptr<EnvPreTargetHandler> env_pre_target_handler_;
// An event observer that deactivates touch selection on certain input events.
std::unique_ptr<EnvEventObserver> env_event_observer_;
DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerClientAura);
};
......
......@@ -418,7 +418,7 @@ TouchSelectionControllerImpl::TouchSelectionControllerImpl(
if (client_widget_)
client_widget_->AddObserver(this);
// Observe certain event types sent to other event targets, to hide this ui.
// Observe certain event types sent to any event target, to hide this ui.
aura::Env* env = aura::Env::GetInstance();
std::set<ui::EventType> types = {ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_MOVED,
ui::ET_KEY_PRESSED, ui::ET_MOUSEWHEEL};
......@@ -628,22 +628,27 @@ void TouchSelectionControllerImpl::OnWidgetBoundsChanged(
}
void TouchSelectionControllerImpl::OnEvent(const ui::Event& event) {
if (event.IsKeyEvent() || event.IsScrollEvent()) {
client_view_->DestroyTouchSelection();
return;
}
if (event.IsMouseEvent()) {
aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
// Check IsMouseEventsEnabled, except on Mus, where it's disabled on touch
// events in this client, but not re-enabled on mouse events elsewhere.
auto* cursor = aura::client::GetCursorClient(
client_view_->GetNativeView()->GetRootWindow());
// Disregard IsMouseEventsEnabled on Mus, it is disabled on touch events in
// this client, but not re-enabled when mouse events are sent elsewhere.
if ((cursor_client && cursor_client->IsMouseEventsEnabled()) ||
aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS) {
client_view_->DestroyTouchSelection();
if (cursor && !cursor->IsMouseEventsEnabled() &&
aura::Env::GetInstance()->mode() != aura::Env::Mode::MUS) {
return;
}
// Windows OS unhandled WM_POINTER* may be redispatched as WM_MOUSE*.
// Avoid adjusting the handles on synthesized events or events generated
// from touch as this can clear an active selection generated by the pen.
if ((event.flags() & (ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH)) ||
event.AsMouseEvent()->pointer_details().pointer_type ==
ui::EventPointerType::POINTER_TYPE_PEN) {
return;
}
return;
}
client_view_->DestroyTouchSelection();
}
void TouchSelectionControllerImpl::QuickMenuTimerFired() {
......
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