window_event_dispatcher.cc 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/aura/window_event_dispatcher.h"
  5. #include <stddef.h>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/check_op.h"
  9. #include "base/notreached.h"
  10. #include "base/observer_list.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "base/trace_event/trace_event.h"
  13. #include "build/build_config.h"
  14. #include "ui/aura/client/aura_constants.h"
  15. #include "ui/aura/client/capture_client.h"
  16. #include "ui/aura/client/cursor_client.h"
  17. #include "ui/aura/client/event_client.h"
  18. #include "ui/aura/client/focus_client.h"
  19. #include "ui/aura/client/screen_position_client.h"
  20. #include "ui/aura/env.h"
  21. #include "ui/aura/env_input_state_controller.h"
  22. #include "ui/aura/window_delegate.h"
  23. #include "ui/aura/window_event_dispatcher_observer.h"
  24. #include "ui/aura/window_targeter.h"
  25. #include "ui/aura/window_tracker.h"
  26. #include "ui/aura/window_tree_host.h"
  27. #include "ui/base/hit_test.h"
  28. #include "ui/base/ime/input_method.h"
  29. #include "ui/compositor/compositor.h"
  30. #include "ui/display/screen.h"
  31. #include "ui/events/event.h"
  32. #include "ui/events/event_utils.h"
  33. #include "ui/events/gestures/gesture_recognizer.h"
  34. #include "ui/events/gestures/gesture_types.h"
  35. #include "ui/events/platform/platform_event_source.h"
  36. #include "ui/gfx/geometry/transform.h"
  37. typedef ui::EventDispatchDetails DispatchDetails;
  38. namespace aura {
  39. namespace {
  40. // Returns true if |target| has a non-client (frame) component at |location|,
  41. // in window coordinates.
  42. bool IsNonClientLocation(Window* target, const gfx::Point& location) {
  43. if (!target->delegate())
  44. return false;
  45. int hit_test_code = target->delegate()->GetNonClientComponent(location);
  46. return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE;
  47. }
  48. Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
  49. return consumer ? static_cast<Window*>(consumer) : nullptr;
  50. }
  51. bool IsEventCandidateForHold(const ui::Event& event) {
  52. if (event.type() == ui::ET_TOUCH_MOVED)
  53. return true;
  54. if (event.type() == ui::ET_MOUSE_DRAGGED)
  55. return true;
  56. if (event.type() == ui::ET_MOUSE_EXITED)
  57. return false;
  58. if (event.IsMouseEvent() && (event.flags() & ui::EF_IS_SYNTHESIZED))
  59. return true;
  60. return false;
  61. }
  62. } // namespace
  63. WindowEventDispatcher::ObserverNotifier::ObserverNotifier(
  64. WindowEventDispatcher* dispatcher,
  65. const ui::Event& event)
  66. : dispatcher_(dispatcher) {
  67. for (WindowEventDispatcherObserver& observer :
  68. Env::GetInstance()->window_event_dispatcher_observers()) {
  69. observer.OnWindowEventDispatcherStartedProcessing(dispatcher, event);
  70. }
  71. }
  72. WindowEventDispatcher::ObserverNotifier::~ObserverNotifier() {
  73. for (WindowEventDispatcherObserver& observer :
  74. Env::GetInstance()->window_event_dispatcher_observers()) {
  75. observer.OnWindowEventDispatcherFinishedProcessingEvent(dispatcher_);
  76. }
  77. }
  78. ////////////////////////////////////////////////////////////////////////////////
  79. // WindowEventDispatcher, public:
  80. WindowEventDispatcher::WindowEventDispatcher(WindowTreeHost* host)
  81. : host_(host),
  82. event_targeter_(std::make_unique<WindowTargeter>()) {
  83. Env::GetInstance()->gesture_recognizer()->AddGestureEventHelper(this);
  84. Env::GetInstance()->AddObserver(this);
  85. }
  86. WindowEventDispatcher::~WindowEventDispatcher() {
  87. TRACE_EVENT0("shutdown", "WindowEventDispatcher::Destructor");
  88. Env::GetInstance()->gesture_recognizer()->RemoveGestureEventHelper(this);
  89. Env::GetInstance()->RemoveObserver(this);
  90. }
  91. void WindowEventDispatcher::Shutdown() {
  92. in_shutdown_ = true;
  93. }
  94. ui::EventTargeter* WindowEventDispatcher::GetDefaultEventTargeter() {
  95. return event_targeter_.get();
  96. }
  97. void WindowEventDispatcher::RepostEvent(const ui::LocatedEvent* event) {
  98. DCHECK(event->type() == ui::ET_MOUSE_PRESSED ||
  99. event->type() == ui::ET_GESTURE_TAP_DOWN ||
  100. event->type() == ui::ET_TOUCH_PRESSED);
  101. // We allow for only one outstanding repostable event. This is used
  102. // in exiting context menus. A dropped repost request is allowed.
  103. if (event->type() == ui::ET_MOUSE_PRESSED) {
  104. held_repostable_event_ = std::make_unique<ui::MouseEvent>(
  105. *event->AsMouseEvent(), static_cast<aura::Window*>(event->target()),
  106. window());
  107. } else if (event->type() == ui::ET_TOUCH_PRESSED) {
  108. held_repostable_event_ =
  109. std::make_unique<ui::TouchEvent>(*event->AsTouchEvent());
  110. } else {
  111. DCHECK(event->type() == ui::ET_GESTURE_TAP_DOWN);
  112. held_repostable_event_.reset();
  113. // TODO(rbyers): Reposing of gestures is tricky to get
  114. // right, so it's not yet supported. crbug.com/170987.
  115. }
  116. if (held_repostable_event_) {
  117. base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
  118. FROM_HERE,
  119. base::BindOnce(
  120. base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents),
  121. repost_event_factory_.GetWeakPtr()));
  122. }
  123. }
  124. void WindowEventDispatcher::OnMouseEventsEnableStateChanged(bool enabled) {
  125. // Send entered / exited so that visual state can be updated to match
  126. // mouse events state.
  127. PostSynthesizeMouseMove();
  128. // TODO(mazda): Add code to disable mouse events when |enabled| == false.
  129. }
  130. void WindowEventDispatcher::DispatchCancelModeEvent() {
  131. ui::CancelModeEvent event;
  132. Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow();
  133. if (focused_window && !window()->Contains(focused_window))
  134. focused_window = nullptr;
  135. DispatchDetails details =
  136. DispatchEvent(focused_window ? focused_window : window(), &event);
  137. if (details.dispatcher_destroyed)
  138. return;
  139. }
  140. void WindowEventDispatcher::DispatchGestureEvent(
  141. ui::GestureConsumer* raw_input_consumer,
  142. ui::GestureEvent* event) {
  143. DispatchDetails details = DispatchHeldEvents();
  144. if (details.dispatcher_destroyed)
  145. return;
  146. Window* target = ConsumerToWindow(raw_input_consumer);
  147. if (target) {
  148. event->ConvertLocationToTarget(window(), target);
  149. details = DispatchEvent(target, event);
  150. if (details.dispatcher_destroyed)
  151. return;
  152. }
  153. }
  154. DispatchDetails WindowEventDispatcher::DispatchMouseExitAtPoint(
  155. Window* window,
  156. const gfx::Point& point,
  157. int event_flags) {
  158. ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EventTimeForNow(),
  159. event_flags, ui::EF_NONE);
  160. return DispatchMouseEnterOrExit(window, event, ui::ET_MOUSE_EXITED);
  161. }
  162. void WindowEventDispatcher::ProcessedTouchEvent(
  163. uint32_t unique_event_id,
  164. Window* window,
  165. ui::EventResult result,
  166. bool is_source_touch_event_set_blocking) {
  167. ui::GestureRecognizer::Gestures gestures =
  168. Env::GetInstance()->gesture_recognizer()->AckTouchEvent(
  169. unique_event_id, result, is_source_touch_event_set_blocking, window);
  170. DispatchDetails details = ProcessGestures(window, std::move(gestures));
  171. if (details.dispatcher_destroyed)
  172. return;
  173. }
  174. void WindowEventDispatcher::HoldPointerMoves() {
  175. if (!move_hold_count_) {
  176. // |synthesize_mouse_events_| is explicitly not changed. It is handled and
  177. // reset in ReleasePointerMoves.
  178. held_event_factory_.InvalidateWeakPtrs();
  179. }
  180. ++move_hold_count_;
  181. TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
  182. "ui", "WindowEventDispatcher::HoldPointerMoves", TRACE_ID_LOCAL(this));
  183. }
  184. void WindowEventDispatcher::ReleasePointerMoves() {
  185. --move_hold_count_;
  186. DCHECK_GE(move_hold_count_, 0);
  187. if (!move_hold_count_) {
  188. // HoldPointerMoves cancels the pending synthesized mouse move if any.
  189. // So ReleasePointerMoves should ensure that |synthesize_mouse_move_|
  190. // resets. Otherwise, PostSynthesizeMouseMove is blocked indefintely.
  191. const bool pending_synthesize_mouse_move = synthesize_mouse_move_;
  192. synthesize_mouse_move_ = false;
  193. if (held_move_event_) {
  194. // We don't want to call DispatchHeldEvents directly, because this might
  195. // be called from a deep stack while another event, in which case
  196. // dispatching another one may not be safe/expected. Instead we post a
  197. // task, that we may cancel if HoldPointerMoves is called again before it
  198. // executes.
  199. base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
  200. FROM_HERE,
  201. base::BindOnce(
  202. base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents),
  203. held_event_factory_.GetWeakPtr()));
  204. } else {
  205. if (did_dispatch_held_move_event_callback_)
  206. std::move(did_dispatch_held_move_event_callback_).Run();
  207. if (pending_synthesize_mouse_move) {
  208. // Schedule a synthesized mouse move event when there is no held mouse
  209. // move and we should generate one.
  210. PostSynthesizeMouseMove();
  211. }
  212. }
  213. }
  214. TRACE_EVENT_NESTABLE_ASYNC_END0(
  215. "ui", "WindowEventDispatcher::HoldPointerMoves", TRACE_ID_LOCAL(this));
  216. }
  217. gfx::Point WindowEventDispatcher::GetLastMouseLocationInRoot() const {
  218. gfx::Point location = Env::GetInstance()->last_mouse_location();
  219. ConvertPointFromScreen(&location);
  220. return location;
  221. }
  222. void WindowEventDispatcher::OnHostLostMouseGrab() {
  223. mouse_pressed_handler_ = nullptr;
  224. mouse_moved_handler_ = nullptr;
  225. }
  226. void WindowEventDispatcher::OnCursorMovedToRootLocation(
  227. const gfx::Point& root_location) {
  228. Env::GetInstance()->env_controller()->SetLastMouseLocation(window(),
  229. root_location);
  230. // Synthesize a mouse move in case the cursor's location in root coordinates
  231. // changed but its position in WindowTreeHost coordinates did not.
  232. PostSynthesizeMouseMove();
  233. }
  234. void WindowEventDispatcher::OnPostNotifiedWindowDestroying(Window* window) {
  235. OnWindowHidden(window, WINDOW_DESTROYED);
  236. }
  237. ////////////////////////////////////////////////////////////////////////////////
  238. // WindowEventDispatcher, private:
  239. Window* WindowEventDispatcher::window() {
  240. return host_->window();
  241. }
  242. const Window* WindowEventDispatcher::window() const {
  243. return host_->window();
  244. }
  245. void WindowEventDispatcher::ConvertPointFromScreen(gfx::Point* point) const {
  246. client::ScreenPositionClient* client =
  247. client::GetScreenPositionClient(window());
  248. if (client)
  249. client->ConvertPointFromScreen(window(), point);
  250. }
  251. void WindowEventDispatcher::TransformEventForDeviceScaleFactor(
  252. ui::LocatedEvent* event) {
  253. event->UpdateForRootTransform(
  254. host_->GetInverseRootTransform(),
  255. host_->GetInverseRootTransformForLocalEventCoordinates());
  256. }
  257. void WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) {
  258. // Dispatching events during shutdown can cause crashes (e.g. in Chrome OS
  259. // system tray cleanup). https://crbug.com/874156
  260. if (in_shutdown_)
  261. return;
  262. // The mouse capture is intentionally ignored. Think that a mouse enters
  263. // to a window, the window sets the capture, the mouse exits the window,
  264. // and then it releases the capture. In that case OnMouseExited won't
  265. // be called. So it is natural not to emit OnMouseExited even though
  266. // |window| is the capture window.
  267. gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
  268. if (window->Contains(mouse_moved_handler_) &&
  269. window->ContainsPointInRoot(last_mouse_location)) {
  270. DispatchDetails details =
  271. DispatchMouseExitAtPoint(this->window(), last_mouse_location);
  272. if (details.dispatcher_destroyed)
  273. return;
  274. }
  275. }
  276. ui::EventDispatchDetails WindowEventDispatcher::DispatchMouseEnterOrExit(
  277. Window* target,
  278. const ui::MouseEvent& event,
  279. ui::EventType type) {
  280. Env::GetInstance()->env_controller()->UpdateStateForMouseEvent(window(),
  281. event);
  282. if (!mouse_moved_handler_ || !mouse_moved_handler_->HasTargetHandler() ||
  283. !window()->Contains(mouse_moved_handler_))
  284. return DispatchDetails();
  285. // |event| may be an event in the process of being dispatched to a target (in
  286. // which case its locations will be in the event's target's coordinate
  287. // system), or a synthetic event created in root-window (in which case, the
  288. // event's target will be NULL, and the event will be in the root-window's
  289. // coordinate system.
  290. if (!target)
  291. target = window();
  292. ui::MouseEvent translated_event(event, target, mouse_moved_handler_.get(),
  293. type, event.flags() | ui::EF_IS_SYNTHESIZED);
  294. return DispatchEvent(mouse_moved_handler_, &translated_event);
  295. }
  296. ui::EventDispatchDetails WindowEventDispatcher::ProcessGestures(
  297. Window* target,
  298. ui::GestureRecognizer::Gestures gestures) {
  299. DispatchDetails details;
  300. if (gestures.empty())
  301. return details;
  302. // If a window has been hidden between the touch event and now, the associated
  303. // gestures may not have a valid target.
  304. if (!target)
  305. return details;
  306. for (const auto& event : gestures) {
  307. event->ConvertLocationToTarget(window(), target);
  308. details = DispatchEvent(target, event.get());
  309. if (details.dispatcher_destroyed || details.target_destroyed)
  310. break;
  311. }
  312. return details;
  313. }
  314. void WindowEventDispatcher::OnWindowHidden(Window* invisible,
  315. WindowHiddenReason reason) {
  316. // If the window the mouse was pressed in becomes invisible, it should no
  317. // longer receive mouse events.
  318. if (invisible->Contains(mouse_pressed_handler_))
  319. mouse_pressed_handler_ = nullptr;
  320. if (invisible->Contains(mouse_moved_handler_))
  321. mouse_moved_handler_ = nullptr;
  322. if (invisible->Contains(touchpad_pinch_handler_))
  323. touchpad_pinch_handler_ = nullptr;
  324. // If events are being dispatched from a nested message-loop, and the target
  325. // of the outer loop is hidden or moved to another dispatcher during
  326. // dispatching events in the inner loop, then reset the target for the outer
  327. // loop.
  328. if (invisible->Contains(old_dispatch_target_))
  329. old_dispatch_target_ = nullptr;
  330. // Cleaning up gesture state may end up destroying the hidden window. We use a
  331. // tracker to detect this.
  332. WindowTracker invisible_tracker({invisible});
  333. invisible->CleanupGestureState();
  334. // Do not clear the capture, and the |event_dispatch_target_| if the
  335. // window is moving across hosts, because the target itself is actually still
  336. // visible and clearing them stops further event processing, which can cause
  337. // unexpected behaviors. See crbug.com/157583
  338. if (reason != WINDOW_MOVING) {
  339. // We don't ask |invisible| here, because invisible may have been removed
  340. // from the window hierarchy already by the time this function is called
  341. // (OnWindowDestroyed).
  342. client::CaptureClient* capture_client =
  343. client::GetCaptureClient(host_->window());
  344. Window* capture_window =
  345. capture_client ? capture_client->GetCaptureWindow() : nullptr;
  346. if (!invisible_tracker.Contains(invisible) ||
  347. invisible->Contains(event_dispatch_target_)) {
  348. event_dispatch_target_ = nullptr;
  349. }
  350. // If the ancestor of the capture window is hidden, release the capture.
  351. // Note that this may delete the window so do not use capture_window
  352. // after this.
  353. if (invisible_tracker.Contains(invisible) &&
  354. invisible->Contains(capture_window) && invisible != window()) {
  355. capture_window->ReleaseCapture();
  356. }
  357. }
  358. }
  359. bool WindowEventDispatcher::is_dispatched_held_event(
  360. const ui::Event& event) const {
  361. return dispatching_held_event_ == &event;
  362. }
  363. ////////////////////////////////////////////////////////////////////////////////
  364. // WindowEventDispatcher, aura::client::CaptureDelegate implementation:
  365. void WindowEventDispatcher::UpdateCapture(Window* old_capture,
  366. Window* new_capture) {
  367. // |mouse_moved_handler_| may have been set to a Window in a different root
  368. // (see below). Clear it here to ensure we don't end up referencing a stale
  369. // Window.
  370. if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_))
  371. mouse_moved_handler_ = nullptr;
  372. if (old_capture && old_capture->GetRootWindow() == window() &&
  373. old_capture->delegate()) {
  374. // Send a capture changed event with the most recent mouse screen location.
  375. const gfx::Point location = Env::GetInstance()->last_mouse_location();
  376. ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, location, location,
  377. ui::EventTimeForNow(), 0, 0);
  378. DispatchDetails details = DispatchEvent(old_capture, &event);
  379. if (details.dispatcher_destroyed)
  380. return;
  381. if (!details.target_destroyed)
  382. old_capture->delegate()->OnCaptureLost();
  383. }
  384. if (new_capture) {
  385. // Make all subsequent mouse events go to the capture window. We shouldn't
  386. // need to send an event here as OnCaptureLost() should take care of that.
  387. if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown())
  388. mouse_moved_handler_ = new_capture;
  389. } else {
  390. // Make sure mouse_moved_handler gets updated.
  391. DispatchDetails details = SynthesizeMouseMoveEvent();
  392. if (details.dispatcher_destroyed)
  393. return;
  394. }
  395. mouse_pressed_handler_ = nullptr;
  396. }
  397. void WindowEventDispatcher::OnOtherRootGotCapture() {
  398. // Windows provides the TrackMouseEvents API which allows us to rely on the
  399. // OS to send us the mouse exit events (WM_MOUSELEAVE). Additionally on
  400. // desktop Windows, every top level window could potentially have its own
  401. // root window, in which case this function will get called whenever those
  402. // windows grab mouse capture. Sending mouse exit messages in these cases
  403. // causes subtle bugs like (crbug.com/394672).
  404. #if !BUILDFLAG(IS_WIN)
  405. if (mouse_moved_handler_) {
  406. // Dispatch a mouse exit to reset any state associated with hover. This is
  407. // important when going from no window having capture to a window having
  408. // capture because we do not dispatch ET_MOUSE_CAPTURE_CHANGED in this case.
  409. DispatchDetails details =
  410. DispatchMouseExitAtPoint(nullptr, GetLastMouseLocationInRoot());
  411. if (details.dispatcher_destroyed)
  412. return;
  413. }
  414. #endif
  415. mouse_moved_handler_ = nullptr;
  416. mouse_pressed_handler_ = nullptr;
  417. }
  418. void WindowEventDispatcher::SetNativeCapture() {
  419. host_->SetCapture();
  420. }
  421. void WindowEventDispatcher::ReleaseNativeCapture() {
  422. host_->ReleaseCapture();
  423. }
  424. ////////////////////////////////////////////////////////////////////////////////
  425. // WindowEventDispatcher, ui::EventProcessor implementation:
  426. ui::EventTarget* WindowEventDispatcher::GetRootForEvent(ui::Event* event) {
  427. return window();
  428. }
  429. void WindowEventDispatcher::OnEventProcessingStarted(ui::Event* event) {
  430. // Don't dispatch events during shutdown.
  431. if (in_shutdown_) {
  432. event->SetHandled();
  433. return;
  434. }
  435. if (host_->compositor()) {
  436. event_metrics_monitors_.push_back(
  437. CreateScropedMetricsMonitorForEvent(*event));
  438. }
  439. // The held events are already in |window()|'s coordinate system. So it is
  440. // not necessary to apply the transform to convert from the host's
  441. // coordinate system to |window()|'s coordinate system.
  442. if (event->IsLocatedEvent() && !is_dispatched_held_event(*event))
  443. TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event));
  444. observer_notifiers_.push(std::make_unique<ObserverNotifier>(this, *event));
  445. }
  446. void WindowEventDispatcher::OnEventProcessingFinished(ui::Event* event) {
  447. if (in_shutdown_)
  448. return;
  449. observer_notifiers_.pop();
  450. if (host_->compositor()) {
  451. std::unique_ptr<cc::EventsMetricsManager::ScopedMonitor> monitor =
  452. std::move(event_metrics_monitors_.back());
  453. event_metrics_monitors_.pop_back();
  454. if (event->handled())
  455. monitor->SetSaveMetrics();
  456. }
  457. }
  458. ////////////////////////////////////////////////////////////////////////////////
  459. // WindowEventDispatcher, ui::EventDispatcherDelegate implementation:
  460. bool WindowEventDispatcher::CanDispatchToTarget(ui::EventTarget* target) {
  461. return event_dispatch_target_ == target;
  462. }
  463. ui::EventDispatchDetails WindowEventDispatcher::PreDispatchEvent(
  464. ui::EventTarget* target,
  465. ui::Event* event) {
  466. Window* target_window = static_cast<Window*>(target);
  467. CHECK(window()->Contains(target_window));
  468. WindowTracker target_window_tracker;
  469. target_window_tracker.Add(target_window);
  470. if (!dispatching_held_event_) {
  471. bool can_be_held = IsEventCandidateForHold(*event);
  472. if (!move_hold_count_ || !can_be_held) {
  473. if (can_be_held)
  474. held_move_event_.reset();
  475. DispatchDetails details = DispatchHeldEvents();
  476. if (details.dispatcher_destroyed || details.target_destroyed)
  477. return details;
  478. }
  479. }
  480. if (target_window_tracker.windows().empty()) {
  481. // The event target is destroyed while processing the held event.
  482. DispatchDetails details;
  483. details.target_destroyed = true;
  484. return details;
  485. }
  486. DispatchDetails details;
  487. if (event->IsMouseEvent()) {
  488. details = PreDispatchMouseEvent(target_window, event->AsMouseEvent());
  489. } else if (event->IsScrollEvent()) {
  490. details = PreDispatchLocatedEvent(target_window, event->AsScrollEvent());
  491. } else if (event->IsTouchEvent()) {
  492. details = PreDispatchTouchEvent(target_window, event->AsTouchEvent());
  493. } else if (event->IsKeyEvent()) {
  494. details = PreDispatchKeyEvent(target_window, event->AsKeyEvent());
  495. } else if (event->IsPinchEvent()) {
  496. details = PreDispatchPinchEvent(target_window, event->AsGestureEvent());
  497. }
  498. if (details.dispatcher_destroyed || details.target_destroyed)
  499. return details;
  500. old_dispatch_target_ = event_dispatch_target_;
  501. event_dispatch_target_ = target_window;
  502. return DispatchDetails();
  503. }
  504. ui::EventDispatchDetails WindowEventDispatcher::PostDispatchEvent(
  505. ui::EventTarget* target,
  506. const ui::Event& event) {
  507. DispatchDetails details;
  508. if (!target || target != event_dispatch_target_)
  509. details.target_destroyed = true;
  510. event_dispatch_target_ = old_dispatch_target_;
  511. old_dispatch_target_ = nullptr;
  512. #ifndef NDEBUG
  513. DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_));
  514. #endif
  515. if (event.IsTouchEvent() && !details.target_destroyed) {
  516. // Do not let 'held' touch events contribute to any gestures unless it is
  517. // being dispatched.
  518. if (is_dispatched_held_event(event) || !held_move_event_ ||
  519. !held_move_event_->IsTouchEvent()) {
  520. const ui::TouchEvent& touchevent = *event.AsTouchEvent();
  521. if (!touchevent.synchronous_handling_disabled()) {
  522. Window* window = static_cast<Window*>(target);
  523. ui::GestureRecognizer::Gestures gestures =
  524. Env::GetInstance()->gesture_recognizer()->AckTouchEvent(
  525. touchevent.unique_event_id(), event.result(),
  526. false /* is_source_touch_event_set_blocking */, window);
  527. return ProcessGestures(window, std::move(gestures));
  528. }
  529. }
  530. }
  531. return details;
  532. }
  533. ////////////////////////////////////////////////////////////////////////////////
  534. // WindowEventDispatcher, ui::GestureEventHelper implementation:
  535. bool WindowEventDispatcher::CanDispatchToConsumer(
  536. ui::GestureConsumer* consumer) {
  537. Window* consumer_window = ConsumerToWindow(consumer);
  538. return (consumer_window && consumer_window->GetRootWindow() == window());
  539. }
  540. void WindowEventDispatcher::DispatchSyntheticTouchEvent(ui::TouchEvent* event) {
  541. // The synthetic event's location is based on the last known location of
  542. // the pointer, in dips. OnEventFromSource expects events with co-ordinates
  543. // in raw pixels, so we convert back to raw pixels here.
  544. DCHECK(event->type() == ui::ET_TOUCH_CANCELLED ||
  545. event->type() == ui::ET_TOUCH_PRESSED);
  546. event->UpdateForRootTransform(
  547. host_->GetRootTransform(),
  548. host_->GetRootTransformForLocalEventCoordinates());
  549. DispatchDetails details = OnEventFromSource(event);
  550. if (details.dispatcher_destroyed)
  551. return;
  552. }
  553. ////////////////////////////////////////////////////////////////////////////////
  554. // WindowEventDispatcher, WindowObserver implementation:
  555. void WindowEventDispatcher::OnWindowDestroying(Window* window) {
  556. if (!host_->window()->Contains(window))
  557. return;
  558. SynthesizeMouseMoveAfterChangeToWindow(window);
  559. }
  560. void WindowEventDispatcher::OnWindowDestroyed(Window* window) {
  561. // We observe all windows regardless of what root Window (if any) they're
  562. // attached to.
  563. observation_manager_.RemoveObservation(window);
  564. // In theory this should be cleaned up by other checks, but we are getting
  565. // crashes that seem to indicate otherwise. See https://crbug.com/942552 for
  566. // one case.
  567. if (window == mouse_moved_handler_)
  568. mouse_moved_handler_ = nullptr;
  569. }
  570. void WindowEventDispatcher::OnWindowAddedToRootWindow(Window* attached) {
  571. if (!observation_manager_.IsObservingSource(attached))
  572. observation_manager_.AddObservation(attached);
  573. if (!host_->window()->Contains(attached))
  574. return;
  575. SynthesizeMouseMoveAfterChangeToWindow(attached);
  576. }
  577. void WindowEventDispatcher::OnWindowRemovingFromRootWindow(Window* detached,
  578. Window* new_root) {
  579. if (!host_->window()->Contains(detached))
  580. return;
  581. DCHECK(client::GetCaptureWindow(window()) != window());
  582. DispatchMouseExitToHidingWindow(detached);
  583. SynthesizeMouseMoveAfterChangeToWindow(detached);
  584. // Hiding the window releases capture which can implicitly destroy the window
  585. // so the window may no longer be valid after this call.
  586. OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
  587. }
  588. void WindowEventDispatcher::OnWindowVisibilityChanging(Window* window,
  589. bool visible) {
  590. if (!host_->window()->Contains(window))
  591. return;
  592. DispatchMouseExitToHidingWindow(window);
  593. }
  594. void WindowEventDispatcher::OnWindowVisibilityChanged(Window* window,
  595. bool visible) {
  596. if (!host_->window()->Contains(window))
  597. return;
  598. if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
  599. PostSynthesizeMouseMove();
  600. // Hiding the window releases capture which can implicitly destroy the window
  601. // so the window may no longer be valid after this call.
  602. if (!visible)
  603. OnWindowHidden(window, WINDOW_HIDDEN);
  604. }
  605. void WindowEventDispatcher::OnWindowBoundsChanged(
  606. Window* window,
  607. const gfx::Rect& old_bounds,
  608. const gfx::Rect& new_bounds,
  609. ui::PropertyChangeReason reason) {
  610. if (!host_->window()->Contains(window))
  611. return;
  612. if (window == host_->window()) {
  613. TRACE_EVENT1("ui", "WindowEventDispatcher::OnWindowBoundsChanged(root)",
  614. "size", new_bounds.size().ToString());
  615. DispatchDetails details = DispatchHeldEvents();
  616. if (details.dispatcher_destroyed)
  617. return;
  618. synthesize_mouse_move_ = false;
  619. }
  620. if (window->IsVisible() &&
  621. window->event_targeting_policy() != EventTargetingPolicy::kNone) {
  622. gfx::Rect old_bounds_in_root = old_bounds, new_bounds_in_root = new_bounds;
  623. Window::ConvertRectToTarget(window->parent(), host_->window(),
  624. &old_bounds_in_root);
  625. Window::ConvertRectToTarget(window->parent(), host_->window(),
  626. &new_bounds_in_root);
  627. gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
  628. if ((old_bounds_in_root.Contains(last_mouse_location) !=
  629. new_bounds_in_root.Contains(last_mouse_location)) ||
  630. (new_bounds_in_root.Contains(last_mouse_location) &&
  631. new_bounds_in_root.origin() != old_bounds_in_root.origin())) {
  632. PostSynthesizeMouseMove();
  633. }
  634. }
  635. }
  636. void WindowEventDispatcher::OnWindowTargetTransformChanging(
  637. Window* window,
  638. const gfx::Transform& new_transform) {
  639. window_transforming_ = true;
  640. if (!synthesize_mouse_move_ && host_->window()->Contains(window))
  641. SynthesizeMouseMoveAfterChangeToWindow(window);
  642. }
  643. void WindowEventDispatcher::OnWindowTransformed(
  644. Window* window,
  645. ui::PropertyChangeReason reason) {
  646. // Call SynthesizeMouseMoveAfterChangeToWindow() only if it's the first time
  647. // that OnWindowTransformed() is called after
  648. // OnWindowTargetTransformChanging() (to avoid generating multiple mouse
  649. // events during animation).
  650. if (window_transforming_ && !synthesize_mouse_move_ &&
  651. host_->window()->Contains(window)) {
  652. SynthesizeMouseMoveAfterChangeToWindow(window);
  653. }
  654. window_transforming_ = false;
  655. }
  656. ///////////////////////////////////////////////////////////////////////////////
  657. // WindowEventDispatcher, EnvObserver implementation:
  658. void WindowEventDispatcher::OnWindowInitialized(Window* window) {
  659. observation_manager_.AddObservation(window);
  660. }
  661. ////////////////////////////////////////////////////////////////////////////////
  662. // WindowEventDispatcher, private:
  663. ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() {
  664. if (!held_repostable_event_ && !held_move_event_) {
  665. if (did_dispatch_held_move_event_callback_)
  666. std::move(did_dispatch_held_move_event_callback_).Run();
  667. return DispatchDetails();
  668. }
  669. CHECK(!dispatching_held_event_);
  670. DispatchDetails dispatch_details;
  671. if (held_repostable_event_) {
  672. if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED ||
  673. held_repostable_event_->type() == ui::ET_TOUCH_PRESSED) {
  674. std::unique_ptr<ui::LocatedEvent> event =
  675. std::move(held_repostable_event_);
  676. dispatching_held_event_ = event.get();
  677. dispatch_details = OnEventFromSource(event.get());
  678. } else {
  679. // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
  680. NOTREACHED();
  681. }
  682. if (dispatch_details.dispatcher_destroyed)
  683. return dispatch_details;
  684. }
  685. if (held_move_event_) {
  686. // |held_move_event_| should be cleared here. Some event handler can
  687. // create its own run loop on an event (e.g. WindowMove loop for
  688. // tab-dragging), which means the other move events need to be processed
  689. // before this OnEventFromSource() finishes. See also b/119260190.
  690. std::unique_ptr<ui::LocatedEvent> event = std::move(held_move_event_);
  691. // If a mouse move has been synthesized, the target location is suspect,
  692. // so drop the held mouse event.
  693. if (event->IsTouchEvent() ||
  694. (event->IsMouseEvent() && !synthesize_mouse_move_)) {
  695. dispatching_held_event_ = event.get();
  696. dispatch_details = OnEventFromSource(event.get());
  697. }
  698. }
  699. if (!dispatch_details.dispatcher_destroyed) {
  700. dispatching_held_event_ = nullptr;
  701. for (WindowEventDispatcherObserver& observer :
  702. Env::GetInstance()->window_event_dispatcher_observers()) {
  703. observer.OnWindowEventDispatcherDispatchedHeldEvents(this);
  704. }
  705. if (did_dispatch_held_move_event_callback_)
  706. std::move(did_dispatch_held_move_event_callback_).Run();
  707. }
  708. return dispatch_details;
  709. }
  710. void WindowEventDispatcher::PostSynthesizeMouseMove() {
  711. // No one should care where the real mouse is when this flag is on. So there
  712. // is no need to send a synthetic mouse move here.
  713. if (ui::PlatformEventSource::ShouldIgnoreNativePlatformEvents())
  714. return;
  715. if (synthesize_mouse_move_ || in_shutdown_)
  716. return;
  717. synthesize_mouse_move_ = true;
  718. base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
  719. FROM_HERE,
  720. base::BindOnce(
  721. base::IgnoreResult(&WindowEventDispatcher::SynthesizeMouseMoveEvent),
  722. held_event_factory_.GetWeakPtr()));
  723. }
  724. void WindowEventDispatcher::SynthesizeMouseMoveAfterChangeToWindow(
  725. Window* window) {
  726. if (in_shutdown_)
  727. return;
  728. if (window->IsVisible() &&
  729. window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
  730. PostSynthesizeMouseMove();
  731. }
  732. }
  733. ui::EventDispatchDetails WindowEventDispatcher::SynthesizeMouseMoveEvent() {
  734. DispatchDetails details;
  735. if (!synthesize_mouse_move_ || in_shutdown_)
  736. return details;
  737. synthesize_mouse_move_ = false;
  738. // No need to generate mouse event if the cursor is invisible and not locked.
  739. client::CursorClient* cursor_client =
  740. client::GetCursorClient(host_->window());
  741. if (cursor_client && (!cursor_client->IsMouseEventsEnabled() ||
  742. (!cursor_client->IsCursorVisible() &&
  743. !cursor_client->IsCursorLocked()))) {
  744. return details;
  745. }
  746. // If one of the mouse buttons is currently down, then do not synthesize a
  747. // mouse-move event. In such cases, aura could synthesize a DRAGGED event
  748. // instead of a MOVED event, but in multi-display/multi-host scenarios, the
  749. // DRAGGED event can be synthesized in the incorrect host. So avoid
  750. // synthesizing any events at all.
  751. if (Env::GetInstance()->mouse_button_flags())
  752. return details;
  753. // Do not use GetLastMouseLocationInRoot here because it's not updated when
  754. // the mouse is not over the window or when the window is minimized.
  755. gfx::Point mouse_location =
  756. display::Screen::GetScreen()->GetCursorScreenPoint();
  757. ConvertPointFromScreen(&mouse_location);
  758. if (!window()->bounds().Contains(mouse_location))
  759. return details;
  760. gfx::Point host_mouse_location = mouse_location;
  761. host_->ConvertDIPToPixels(&host_mouse_location);
  762. ui::MouseEvent event(ui::ET_MOUSE_MOVED, host_mouse_location,
  763. host_mouse_location, ui::EventTimeForNow(),
  764. ui::EF_IS_SYNTHESIZED, 0);
  765. return OnEventFromSource(&event);
  766. }
  767. DispatchDetails WindowEventDispatcher::PreDispatchLocatedEvent(
  768. Window* target,
  769. ui::LocatedEvent* event) {
  770. int flags = event->flags();
  771. if (IsNonClientLocation(target, event->location()))
  772. flags |= ui::EF_IS_NON_CLIENT;
  773. event->set_flags(flags);
  774. if (!is_dispatched_held_event(*event) &&
  775. (event->IsMouseEvent() || event->IsScrollEvent()) &&
  776. !(event->flags() & ui::EF_IS_SYNTHESIZED)) {
  777. synthesize_mouse_move_ = false;
  778. }
  779. return DispatchDetails();
  780. }
  781. DispatchDetails WindowEventDispatcher::PreDispatchMouseEvent(
  782. Window* target,
  783. ui::MouseEvent* event) {
  784. client::CursorClient* cursor_client = client::GetCursorClient(window());
  785. // We allow synthesized mouse exit events through even if mouse events are
  786. // disabled. This ensures that hover state, etc on controls like buttons is
  787. // cleared.
  788. if (cursor_client && !cursor_client->IsMouseEventsEnabled() &&
  789. (event->flags() & ui::EF_IS_SYNTHESIZED) &&
  790. (event->type() != ui::ET_MOUSE_EXITED)) {
  791. event->SetHandled();
  792. return DispatchDetails();
  793. }
  794. Env::GetInstance()->env_controller()->UpdateStateForMouseEvent(window(),
  795. *event);
  796. if (IsEventCandidateForHold(*event) && !dispatching_held_event_) {
  797. if (move_hold_count_) {
  798. held_move_event_ =
  799. std::make_unique<ui::MouseEvent>(*event, target, window());
  800. event->SetHandled();
  801. return DispatchDetails();
  802. } else {
  803. // We may have a held event for a period between the time move_hold_count_
  804. // fell to 0 and the DispatchHeldEvents executes. Since we're going to
  805. // dispatch the new event directly below, we can reset the old one.
  806. held_move_event_.reset();
  807. }
  808. }
  809. switch (event->type()) {
  810. case ui::ET_MOUSE_EXITED:
  811. if (!target || target == window()) {
  812. DispatchDetails details =
  813. DispatchMouseEnterOrExit(target, *event, ui::ET_MOUSE_EXITED);
  814. if (details.dispatcher_destroyed) {
  815. event->SetHandled();
  816. return details;
  817. }
  818. mouse_moved_handler_ = nullptr;
  819. }
  820. break;
  821. case ui::ET_MOUSE_MOVED:
  822. // Send an exit to the current |mouse_moved_handler_| and an enter to
  823. // |target|. Take care that both us and |target| aren't destroyed during
  824. // dispatch.
  825. if (target != mouse_moved_handler_) {
  826. aura::Window* old_mouse_moved_handler = mouse_moved_handler_;
  827. WindowTracker live_window;
  828. live_window.Add(target);
  829. DispatchDetails details =
  830. DispatchMouseEnterOrExit(target, *event, ui::ET_MOUSE_EXITED);
  831. // |details| contains information about |mouse_moved_handler_| being
  832. // destroyed which is not our |target|. Return value of this function
  833. // should be about our |target|.
  834. DispatchDetails target_details = details;
  835. target_details.target_destroyed = !live_window.Contains(target);
  836. if (details.dispatcher_destroyed) {
  837. event->SetHandled();
  838. return target_details;
  839. }
  840. // If the |mouse_moved_handler_| changes out from under us, assume a
  841. // nested run loop ran and we don't need to do anything.
  842. if (mouse_moved_handler_ != old_mouse_moved_handler) {
  843. event->SetHandled();
  844. return target_details;
  845. }
  846. if (details.target_destroyed || target_details.target_destroyed) {
  847. mouse_moved_handler_ = nullptr;
  848. event->SetHandled();
  849. return target_details;
  850. }
  851. live_window.Remove(target);
  852. mouse_moved_handler_ = target;
  853. details =
  854. DispatchMouseEnterOrExit(target, *event, ui::ET_MOUSE_ENTERED);
  855. if (details.dispatcher_destroyed || details.target_destroyed) {
  856. event->SetHandled();
  857. return details;
  858. }
  859. }
  860. break;
  861. case ui::ET_MOUSE_PRESSED:
  862. // Don't set the mouse pressed handler for non client mouse down events.
  863. // These are only sent by Windows and are not always followed with non
  864. // client mouse up events which causes subsequent mouse events to be
  865. // sent to the wrong target.
  866. if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
  867. mouse_pressed_handler_ = target;
  868. break;
  869. case ui::ET_MOUSE_RELEASED:
  870. mouse_pressed_handler_ = nullptr;
  871. break;
  872. default:
  873. break;
  874. }
  875. return PreDispatchLocatedEvent(target, event);
  876. }
  877. DispatchDetails WindowEventDispatcher::PreDispatchPinchEvent(
  878. Window* target,
  879. ui::GestureEvent* event) {
  880. if (event->details().device_type() != ui::GestureDeviceType::DEVICE_TOUCHPAD)
  881. return PreDispatchLocatedEvent(target, event);
  882. switch (event->type()) {
  883. case ui::ET_GESTURE_PINCH_BEGIN:
  884. touchpad_pinch_handler_ = target;
  885. break;
  886. case ui::ET_GESTURE_PINCH_END:
  887. touchpad_pinch_handler_ = nullptr;
  888. break;
  889. default:
  890. break;
  891. }
  892. return PreDispatchLocatedEvent(target, event);
  893. }
  894. DispatchDetails WindowEventDispatcher::PreDispatchTouchEvent(
  895. Window* target,
  896. ui::TouchEvent* event) {
  897. if (event->type() == ui::ET_TOUCH_MOVED && move_hold_count_ &&
  898. !dispatching_held_event_) {
  899. held_move_event_ =
  900. std::make_unique<ui::TouchEvent>(*event, target, window());
  901. event->SetHandled();
  902. return DispatchDetails();
  903. }
  904. Env::GetInstance()->env_controller()->UpdateStateForTouchEvent(*event);
  905. ui::TouchEvent root_relative_event(*event);
  906. root_relative_event.set_location_f(event->root_location_f());
  907. Env* env = Env::GetInstance();
  908. if (!env->gesture_recognizer()->ProcessTouchEventPreDispatch(
  909. &root_relative_event, target)) {
  910. // The event is invalid - ignore it.
  911. event->StopPropagation();
  912. event->DisableSynchronousHandling();
  913. for (auto& observer : env->window_event_dispatcher_observers())
  914. observer.OnWindowEventDispatcherIgnoredEvent(this);
  915. return DispatchDetails();
  916. }
  917. // This flag is set depending on the gestures recognized in the call above,
  918. // and needs to propagate with the forwarded event.
  919. event->set_may_cause_scrolling(root_relative_event.may_cause_scrolling());
  920. return PreDispatchLocatedEvent(target, event);
  921. }
  922. DispatchDetails WindowEventDispatcher::PreDispatchKeyEvent(
  923. Window* target,
  924. ui::KeyEvent* event) {
  925. if (skip_ime_ || !host_->has_input_method() ||
  926. (event->flags() & ui::EF_IS_SYNTHESIZED) ||
  927. !host_->ShouldSendKeyEventToIme() ||
  928. target->GetProperty(aura::client::kSkipImeProcessing)) {
  929. return DispatchDetails();
  930. }
  931. // At this point (i.e: EP_PREDISPATCH), event target is still not set, so do
  932. // it explicitly here thus making it possible for InputMethodContext
  933. // implementation to retrieve target window through KeyEvent::target().
  934. // Event::target is reset at WindowTreeHost::DispatchKeyEventPostIME(), just
  935. // after key is processed by InputMethodContext.
  936. ui::Event::DispatcherApi(event).set_target(window());
  937. DispatchDetails details = host_->GetInputMethod()->DispatchKeyEvent(event);
  938. event->StopPropagation();
  939. return details;
  940. }
  941. std::unique_ptr<cc::EventsMetricsManager::ScopedMonitor>
  942. WindowEventDispatcher::CreateScropedMetricsMonitorForEvent(
  943. const ui::Event& event) {
  944. std::unique_ptr<cc::EventMetrics> metrics;
  945. if (event.IsScrollGestureEvent() || event.IsPinchEvent()) {
  946. const auto* gesture = event.AsGestureEvent();
  947. // There are many tests that don't set the device type properly, so if the
  948. // device type is not set, we'll consider it as touchpad/wheel.
  949. ui::ScrollInputType input_type =
  950. gesture->details().device_type() ==
  951. ui::GestureDeviceType::DEVICE_TOUCHSCREEN
  952. ? ui::ScrollInputType::kTouchscreen
  953. : ui::ScrollInputType::kWheel;
  954. if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
  955. metrics = cc::ScrollUpdateEventMetrics::Create(
  956. ui::ET_GESTURE_SCROLL_UPDATE, input_type, /*is_inertial=*/false,
  957. has_seen_gesture_scroll_update_after_begin_
  958. ? cc::ScrollUpdateEventMetrics::ScrollUpdateType::kContinued
  959. : cc::ScrollUpdateEventMetrics::ScrollUpdateType::kStarted,
  960. gesture->details().scroll_y(), gesture->time_stamp());
  961. has_seen_gesture_scroll_update_after_begin_ = true;
  962. } else if (gesture->IsScrollGestureEvent()) {
  963. metrics = cc::ScrollEventMetrics::Create(gesture->type(), input_type,
  964. /*is_inertial=*/false,
  965. gesture->time_stamp());
  966. if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN)
  967. has_seen_gesture_scroll_update_after_begin_ = false;
  968. } else {
  969. DCHECK(gesture->IsPinchEvent());
  970. metrics = cc::PinchEventMetrics::Create(gesture->type(), input_type,
  971. gesture->time_stamp());
  972. }
  973. } else {
  974. metrics = cc::EventMetrics::Create(event.type(), event.time_stamp());
  975. }
  976. cc::EventsMetricsManager::ScopedMonitor::DoneCallback done_callback;
  977. if (metrics) {
  978. // TODO(crbug.com/1278417): The following breakdown has the renderer word
  979. // in its name, so not the best breakdown to use in the browser. Introduce
  980. // and use breakdowns specific to the browser.
  981. metrics->SetDispatchStageTimestamp(
  982. cc::EventMetrics::DispatchStage::kRendererMainStarted);
  983. done_callback = base::BindOnce(
  984. [](std::unique_ptr<cc::EventMetrics> metrics, bool handled) {
  985. // TODO(crbug.com/1278417): The following breakdown has the renderer
  986. // word in its name, so not the best breakdown to use in the
  987. // browser. Introduce and use breakdowns specific to the browser.
  988. metrics->SetDispatchStageTimestamp(
  989. cc::EventMetrics::DispatchStage::kRendererMainFinished);
  990. return handled ? std::move(metrics) : nullptr;
  991. },
  992. std::move(metrics));
  993. }
  994. return host_->compositor()->GetScopedEventMetricsMonitor(
  995. std::move(done_callback));
  996. }
  997. } // namespace aura