From d15bcae0ad81850478cbb5e8218da8ae134d820d Mon Sep 17 00:00:00 2001 From: Scott Violet Date: Fri, 22 Jun 2018 20:43:31 +0000 Subject: [PATCH] chromeos: adds support for sending CANCEL_MODE events And this also changes ws2 to only stop cancelable events. To do otherwise triggers a CHECK in Event. BUG=837686 TEST=covered by tests Change-Id: I6bc3d8b6a02eda1ecf7b7aecec6729a9ef7b1a2e Reviewed-on: https://chromium-review.googlesource.com/1111268 Commit-Queue: Scott Violet Reviewed-by: Tom Sepez Reviewed-by: Michael Wasserman Cr-Commit-Position: refs/heads/master@{#569751} --- services/ui/ws2/event_test_utils.cc | 5 ++ services/ui/ws2/server_window.cc | 11 +-- services/ui/ws2/window_tree_unittest.cc | 14 ++++ ui/events/event.cc | 92 ++++--------------------- ui/events/event.h | 4 +- ui/events/event_utils.cc | 67 ++++++++++++++++++ ui/events/event_utils.h | 3 + ui/events/mojo/event_constants.mojom | 1 + ui/events/mojo/event_struct_traits.cc | 9 ++- 9 files changed, 121 insertions(+), 85 deletions(-) diff --git a/services/ui/ws2/event_test_utils.cc b/services/ui/ws2/event_test_utils.cc index 57f5660291bee..f2d2558148740 100644 --- a/services/ui/ws2/event_test_utils.cc +++ b/services/ui/ws2/event_test_utils.cc @@ -14,7 +14,12 @@ namespace ws2 { std::string EventToEventType(const Event* event) { if (!event) return ""; + + // TODO(sky): convert to using EventTypeName() is ui/events.h. switch (event->type()) { + case ET_CANCEL_MODE: + return "CANCEL_MODE"; + case ET_KEY_PRESSED: return "KEY_PRESSED"; diff --git a/services/ui/ws2/server_window.cc b/services/ui/ws2/server_window.cc index dd85823aef185..1c8df27a0c87d 100644 --- a/services/ui/ws2/server_window.cc +++ b/services/ui/ws2/server_window.cc @@ -172,7 +172,8 @@ class ServerWindowEventHandler : public ui::EventHandler { // The event was forwarded to the remote client. We don't want it handled // locally too. - event->StopPropagation(); + if (event->cancelable()) + event->StopPropagation(); } protected: @@ -215,7 +216,8 @@ class ServerWindowEventHandler : public ui::EventHandler { // for a client intercepting events. if (server_window_->DoesOwnerInterceptEvents()) { server_window_->owning_window_tree()->SendEventToClient(window(), *event); - event->StopPropagation(); + if (event->cancelable()) + event->StopPropagation(); return true; } return false; @@ -325,7 +327,8 @@ class TopLevelEventHandler : public ServerWindowEventHandler { if (wm::CaptureController::Get()->GetCaptureWindow()) { if (server_window()->capture_owner()) { server_window()->capture_owner()->SendEventToClient(window(), *event); - event->StopPropagation(); + if (event->cancelable()) + event->StopPropagation(); return; } return; @@ -363,7 +366,7 @@ class TopLevelEventHandler : public ServerWindowEventHandler { } } server_window()->owning_window_tree()->SendEventToClient(window(), *event); - if (stop_propagation) + if (stop_propagation && event->cancelable()) event->StopPropagation(); } diff --git a/services/ui/ws2/window_tree_unittest.cc b/services/ui/ws2/window_tree_unittest.cc index cd5e3942f9877..5990590d3e597 100644 --- a/services/ui/ws2/window_tree_unittest.cc +++ b/services/ui/ws2/window_tree_unittest.cc @@ -1475,6 +1475,20 @@ TEST(WindowTreeTest2, CancelMoveLoop) { SingleChangeToDescription(*setup.changes())); } +TEST(WindowTreeTest2, CancelMode) { + WindowServiceTestSetup setup; + aura::Window* top_level = + setup.window_tree_test_helper()->NewTopLevelWindow(); + ASSERT_TRUE(top_level); + top_level->Show(); + EXPECT_TRUE(setup.window_tree_test_helper()->SetFocus(top_level)); + // Dispatch a CancelEvent. This should go to the |top_level| as it has focus. + setup.root()->GetHost()->dispatcher()->DispatchCancelModeEvent(); + EXPECT_EQ("CANCEL_MODE", + EventToEventType( + setup.window_tree_client()->PopInputEvent().event.get())); +} + TEST(WindowTreeTest2, PerformDragDrop) { WindowServiceTestSetup setup; aura::Window* top_level = diff --git a/ui/events/event.cc b/ui/events/event.cc index c43486324a4f4..bcc2da1f7552b 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc @@ -40,71 +40,21 @@ namespace ui { namespace { -const char* EventTypeName(EventType type) { - if (type >= ET_LAST) - return ""; - -#define CASE_TYPE(t) \ - case t: \ - return #t - switch (type) { - CASE_TYPE(ET_UNKNOWN); - CASE_TYPE(ET_MOUSE_PRESSED); - CASE_TYPE(ET_MOUSE_DRAGGED); - CASE_TYPE(ET_MOUSE_RELEASED); - CASE_TYPE(ET_MOUSE_MOVED); - CASE_TYPE(ET_MOUSE_ENTERED); - CASE_TYPE(ET_MOUSE_EXITED); - CASE_TYPE(ET_KEY_PRESSED); - CASE_TYPE(ET_KEY_RELEASED); - CASE_TYPE(ET_MOUSEWHEEL); - CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED); - CASE_TYPE(ET_TOUCH_RELEASED); - CASE_TYPE(ET_TOUCH_PRESSED); - CASE_TYPE(ET_TOUCH_MOVED); - CASE_TYPE(ET_TOUCH_CANCELLED); - CASE_TYPE(ET_DROP_TARGET_EVENT); - CASE_TYPE(ET_POINTER_DOWN); - CASE_TYPE(ET_POINTER_MOVED); - CASE_TYPE(ET_POINTER_UP); - CASE_TYPE(ET_POINTER_CANCELLED); - CASE_TYPE(ET_POINTER_ENTERED); - CASE_TYPE(ET_POINTER_EXITED); - CASE_TYPE(ET_POINTER_WHEEL_CHANGED); - CASE_TYPE(ET_POINTER_CAPTURE_CHANGED); - CASE_TYPE(ET_GESTURE_SCROLL_BEGIN); - CASE_TYPE(ET_GESTURE_SCROLL_END); - CASE_TYPE(ET_GESTURE_SCROLL_UPDATE); - CASE_TYPE(ET_GESTURE_SHOW_PRESS); - CASE_TYPE(ET_GESTURE_TAP); - CASE_TYPE(ET_GESTURE_TAP_DOWN); - CASE_TYPE(ET_GESTURE_TAP_CANCEL); - CASE_TYPE(ET_GESTURE_BEGIN); - CASE_TYPE(ET_GESTURE_END); - CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP); - CASE_TYPE(ET_GESTURE_PINCH_BEGIN); - CASE_TYPE(ET_GESTURE_PINCH_END); - CASE_TYPE(ET_GESTURE_PINCH_UPDATE); - CASE_TYPE(ET_GESTURE_LONG_PRESS); - CASE_TYPE(ET_GESTURE_LONG_TAP); - CASE_TYPE(ET_GESTURE_SWIPE); - CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED); - CASE_TYPE(ET_GESTURE_DOUBLE_TAP); - CASE_TYPE(ET_SCROLL); - CASE_TYPE(ET_SCROLL_FLING_START); - CASE_TYPE(ET_SCROLL_FLING_CANCEL); - CASE_TYPE(ET_CANCEL_MODE); - CASE_TYPE(ET_UMA_DATA); - case ET_LAST: - NOTREACHED(); - return ""; - // Don't include default, so that we get an error when new type is added. - } -#undef CASE_TYPE +#if defined(USE_X11) +bool X11EventHasNonStandardState(const PlatformEvent& event) { + const unsigned int kAllStateMask = + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask | + Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | + LockMask | ControlMask | AnyModifier; - NOTREACHED(); - return ""; + return event && (event->xkey.state & ~kAllStateMask) != 0; } +#endif + +constexpr int kChangedButtonFlagMask = + ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | + ui::EF_RIGHT_MOUSE_BUTTON | ui::EF_BACK_MOUSE_BUTTON | + ui::EF_FORWARD_MOUSE_BUTTON; SourceEventType EventTypeToLatencySourceEventType(EventType type) { switch (type) { @@ -179,22 +129,6 @@ SourceEventType EventTypeToLatencySourceEventType(EventType type) { return SourceEventType::UNKNOWN; } -#if defined(USE_X11) -bool X11EventHasNonStandardState(const PlatformEvent& event) { - const unsigned int kAllStateMask = - Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask | - Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | - LockMask | ControlMask | AnyModifier; - - return event && (event->xkey.state & ~kAllStateMask) != 0; -} -#endif - -constexpr int kChangedButtonFlagMask = - ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | - ui::EF_RIGHT_MOUSE_BUTTON | ui::EF_BACK_MOUSE_BUTTON | - ui::EF_FORWARD_MOUSE_BUTTON; - } // namespace //////////////////////////////////////////////////////////////////////////////// diff --git a/ui/events/event.h b/ui/events/event.h index aabf5a90defa0..ef40f4f144dc2 100644 --- a/ui/events/event.h +++ b/ui/events/event.h @@ -83,7 +83,9 @@ class EVENTS_EXPORT Event { const base::TimeTicks time_stamp() const { return time_stamp_; } int flags() const { return flags_; } - // Returns a name for the event, typically used in logging/debugging. + // Returns a name for the event, typically used in logging/debugging. This is + // a convenience for EventTypeName(type()) (EventTypeName() is in + // event_utils). const char* GetName() const; // This is only intended to be used externally by classes that are modifying diff --git a/ui/events/event_utils.cc b/ui/events/event_utils.cc index d1f799633eccd..bf689ae2a8b9c 100644 --- a/ui/events/event_utils.cc +++ b/ui/events/event_utils.cc @@ -154,4 +154,71 @@ void ConvertEventLocationToTargetWindowLocation( located_event->set_root_location_f(location_in_pixel_in_host); } +const char* EventTypeName(EventType type) { + if (type >= ET_LAST) + return ""; + +#define CASE_TYPE(t) \ + case t: \ + return #t + + switch (type) { + CASE_TYPE(ET_UNKNOWN); + CASE_TYPE(ET_MOUSE_PRESSED); + CASE_TYPE(ET_MOUSE_DRAGGED); + CASE_TYPE(ET_MOUSE_RELEASED); + CASE_TYPE(ET_MOUSE_MOVED); + CASE_TYPE(ET_MOUSE_ENTERED); + CASE_TYPE(ET_MOUSE_EXITED); + CASE_TYPE(ET_KEY_PRESSED); + CASE_TYPE(ET_KEY_RELEASED); + CASE_TYPE(ET_MOUSEWHEEL); + CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED); + CASE_TYPE(ET_TOUCH_RELEASED); + CASE_TYPE(ET_TOUCH_PRESSED); + CASE_TYPE(ET_TOUCH_MOVED); + CASE_TYPE(ET_TOUCH_CANCELLED); + CASE_TYPE(ET_DROP_TARGET_EVENT); + CASE_TYPE(ET_POINTER_DOWN); + CASE_TYPE(ET_POINTER_MOVED); + CASE_TYPE(ET_POINTER_UP); + CASE_TYPE(ET_POINTER_CANCELLED); + CASE_TYPE(ET_POINTER_ENTERED); + CASE_TYPE(ET_POINTER_EXITED); + CASE_TYPE(ET_POINTER_WHEEL_CHANGED); + CASE_TYPE(ET_POINTER_CAPTURE_CHANGED); + CASE_TYPE(ET_GESTURE_SCROLL_BEGIN); + CASE_TYPE(ET_GESTURE_SCROLL_END); + CASE_TYPE(ET_GESTURE_SCROLL_UPDATE); + CASE_TYPE(ET_GESTURE_SHOW_PRESS); + CASE_TYPE(ET_GESTURE_TAP); + CASE_TYPE(ET_GESTURE_TAP_DOWN); + CASE_TYPE(ET_GESTURE_TAP_CANCEL); + CASE_TYPE(ET_GESTURE_BEGIN); + CASE_TYPE(ET_GESTURE_END); + CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP); + CASE_TYPE(ET_GESTURE_PINCH_BEGIN); + CASE_TYPE(ET_GESTURE_PINCH_END); + CASE_TYPE(ET_GESTURE_PINCH_UPDATE); + CASE_TYPE(ET_GESTURE_LONG_PRESS); + CASE_TYPE(ET_GESTURE_LONG_TAP); + CASE_TYPE(ET_GESTURE_SWIPE); + CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED); + CASE_TYPE(ET_GESTURE_DOUBLE_TAP); + CASE_TYPE(ET_SCROLL); + CASE_TYPE(ET_SCROLL_FLING_START); + CASE_TYPE(ET_SCROLL_FLING_CANCEL); + CASE_TYPE(ET_CANCEL_MODE); + CASE_TYPE(ET_UMA_DATA); + case ET_LAST: + NOTREACHED(); + return ""; + // Don't include default, so that we get an error when new type is added. + } +#undef CASE_TYPE + + NOTREACHED(); + return ""; +} + } // namespace ui diff --git a/ui/events/event_utils.h b/ui/events/event_utils.h index 4c0f44a0bf35e..ccf0706bd0c6d 100644 --- a/ui/events/event_utils.h +++ b/ui/events/event_utils.h @@ -187,6 +187,9 @@ EVENTS_EXPORT void ConvertEventLocationToTargetWindowLocation( const gfx::Point& current_window_origin, ui::LocatedEvent* located_event); +// Returns a string description of an event type. Useful for debugging. +EVENTS_EXPORT const char* EventTypeName(EventType type); + } // namespace ui #endif // UI_EVENTS_EVENT_UTILS_H_ diff --git a/ui/events/mojo/event_constants.mojom b/ui/events/mojo/event_constants.mojom index d346e18230a87..c7bd18fd4a282 100644 --- a/ui/events/mojo/event_constants.mojom +++ b/ui/events/mojo/event_constants.mojom @@ -28,6 +28,7 @@ enum EventType { SCROLL, SCROLL_FLING_START, SCROLL_FLING_CANCEL, + CANCEL_MODE, }; // This mirrors ui::EventFlags diff --git a/ui/events/mojo/event_struct_traits.cc b/ui/events/mojo/event_struct_traits.cc index 8423dc59a7ec9..e2663f6d3264c 100644 --- a/ui/events/mojo/event_struct_traits.cc +++ b/ui/events/mojo/event_struct_traits.cc @@ -6,6 +6,7 @@ #include "mojo/public/cpp/base/time_mojom_traits.h" #include "ui/events/event.h" +#include "ui/events/event_utils.h" #include "ui/events/gesture_event_details.h" #include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/mojo/event_constants.mojom.h" @@ -159,8 +160,11 @@ ui::mojom::EventType TypeConverter::Read( scroll_data->momentum_phase); break; } + case ui::mojom::EventType::CANCEL_MODE: + *out = std::make_unique(); + break; case ui::mojom::EventType::UNKNOWN: NOTREACHED() << "Using unknown event types closes connections"; return false;