| Index: services/ui/ws/window_manager_state.cc
|
| diff --git a/services/ui/ws/window_manager_state.cc b/services/ui/ws/window_manager_state.cc
|
| index e70ec273f45bd0b83ed66b38ea2b59155672ffdf..4f4d2eeee12330265cfb8169edd7f5c00a0d6dc0 100644
|
| --- a/services/ui/ws/window_manager_state.cc
|
| +++ b/services/ui/ws/window_manager_state.cc
|
| @@ -199,12 +199,15 @@ void WindowManagerState::ProcessEvent(const ui::Event& event) {
|
| QueueEvent(event, nullptr);
|
| return;
|
| }
|
| - event_dispatcher_.ProcessEvent(event);
|
| +
|
| + event_dispatcher_.ProcessEvent(event,
|
| + EventDispatcher::AcceleratorMatchPhase::ANY);
|
| }
|
|
|
| void WindowManagerState::OnEventAck(mojom::WindowTree* tree,
|
| mojom::EventResult result) {
|
| - if (tree_awaiting_input_ack_ != tree) {
|
| + if (tree_awaiting_input_ack_ != tree ||
|
| + event_dispatch_phase_ != EventDispatchPhase::TARGET) {
|
| // TODO(sad): The ack must have arrived after the timeout. We should do
|
| // something here, and in OnEventAckTimeout().
|
| return;
|
| @@ -212,12 +215,39 @@ void WindowManagerState::OnEventAck(mojom::WindowTree* tree,
|
| tree_awaiting_input_ack_ = nullptr;
|
| event_ack_timer_.Stop();
|
|
|
| - if (result == mojom::EventResult::UNHANDLED && post_target_accelerator_)
|
| - OnAccelerator(post_target_accelerator_->id(), *event_awaiting_input_ack_);
|
| + if (result == mojom::EventResult::UNHANDLED && post_target_accelerator_) {
|
| + OnAccelerator(post_target_accelerator_->id(), *event_awaiting_input_ack_,
|
| + AcceleratorPhase::POST);
|
| + }
|
|
|
| + event_dispatch_phase_ = EventDispatchPhase::NONE;
|
| ProcessNextEventFromQueue();
|
| }
|
|
|
| +void WindowManagerState::OnAcceleratorAck(mojom::EventResult result) {
|
| + if (event_dispatch_phase_ != EventDispatchPhase::PRE_TARGET_ACCELERATOR) {
|
| + // TODO(sad): The ack must have arrived after the timeout. We should do
|
| + // something here, and in OnEventAckTimeout().
|
| + return;
|
| + }
|
| +
|
| + tree_awaiting_input_ack_ = nullptr;
|
| + event_ack_timer_.Stop();
|
| + event_dispatch_phase_ = EventDispatchPhase::NONE;
|
| +
|
| + if (result == mojom::EventResult::UNHANDLED) {
|
| + event_dispatcher_.ProcessEvent(
|
| + *event_awaiting_input_ack_,
|
| + EventDispatcher::AcceleratorMatchPhase::POST_ONLY);
|
| + } else {
|
| + // We're not going to process the event any further, notify event observers.
|
| + // We don't do this first to ensure we don't send an event twice to clients.
|
| + window_server()->SendToEventObservers(*event_awaiting_input_ack_, user_id(),
|
| + nullptr);
|
| + ProcessNextEventFromQueue();
|
| + }
|
| +}
|
| +
|
| const WindowServer* WindowManagerState::window_server() const {
|
| return window_tree_->window_server();
|
| }
|
| @@ -258,7 +288,10 @@ void WindowManagerState::OnEventAckTimeout(ClientSpecificId client_id) {
|
| WindowTree* hung_tree = window_server()->GetTreeWithId(client_id);
|
| if (hung_tree && !hung_tree->janky())
|
| window_tree_->ClientJankinessChanged(hung_tree);
|
| - OnEventAck(tree_awaiting_input_ack_, mojom::EventResult::UNHANDLED);
|
| + if (event_dispatch_phase_ == EventDispatchPhase::PRE_TARGET_ACCELERATOR)
|
| + OnAcceleratorAck(mojom::EventResult::UNHANDLED);
|
| + else
|
| + OnEventAck(tree_awaiting_input_ack_, mojom::EventResult::UNHANDLED);
|
| }
|
|
|
| void WindowManagerState::QueueEvent(
|
| @@ -277,7 +310,8 @@ void WindowManagerState::ProcessNextEventFromQueue() {
|
| std::unique_ptr<QueuedEvent> queued_event = std::move(event_queue_.front());
|
| event_queue_.pop();
|
| if (!queued_event->processed_target) {
|
| - event_dispatcher_.ProcessEvent(*queued_event->event);
|
| + event_dispatcher_.ProcessEvent(
|
| + *queued_event->event, EventDispatcher::AcceleratorMatchPhase::ANY);
|
| return;
|
| }
|
| if (queued_event->processed_target->IsValid()) {
|
| @@ -309,18 +343,12 @@ void WindowManagerState::DispatchInputEventToWindowImpl(
|
| }
|
| }
|
|
|
| + event_dispatch_phase_ = EventDispatchPhase::TARGET;
|
| +
|
| WindowTree* tree = window_server()->GetTreeWithId(client_id);
|
|
|
| - // TOOD(sad): Adjust this delay, possibly make this dynamic.
|
| - const base::TimeDelta max_delay = base::debug::BeingDebugged()
|
| - ? base::TimeDelta::FromDays(1)
|
| - : GetDefaultAckTimerDelay();
|
| - event_ack_timer_.Start(
|
| - FROM_HERE, max_delay,
|
| - base::Bind(&WindowManagerState::OnEventAckTimeout,
|
| - weak_factory_.GetWeakPtr(), tree->id()));
|
| + ScheduleInputEventTimeout(tree);
|
|
|
| - tree_awaiting_input_ack_ = tree;
|
| if (accelerator) {
|
| event_awaiting_input_ack_ = ui::Event::Clone(event);
|
| post_target_accelerator_ = accelerator;
|
| @@ -361,15 +389,35 @@ bool WindowManagerState::HandleDebugAccelerator(uint32_t accelerator_id) {
|
| return false;
|
| }
|
|
|
| +void WindowManagerState::ScheduleInputEventTimeout(WindowTree* tree) {
|
| + // TOOD(sad): Adjust this delay, possibly make this dynamic.
|
| + const base::TimeDelta max_delay = base::debug::BeingDebugged()
|
| + ? base::TimeDelta::FromDays(1)
|
| + : GetDefaultAckTimerDelay();
|
| + event_ack_timer_.Start(FROM_HERE, max_delay,
|
| + base::Bind(&WindowManagerState::OnEventAckTimeout,
|
| + weak_factory_.GetWeakPtr(), tree->id()));
|
| +
|
| + tree_awaiting_input_ack_ = tree;
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // EventDispatcherDelegate:
|
|
|
| void WindowManagerState::OnAccelerator(uint32_t accelerator_id,
|
| - const ui::Event& event) {
|
| + const ui::Event& event,
|
| + AcceleratorPhase phase) {
|
| DCHECK(IsActive());
|
| if (HandleDebugAccelerator(accelerator_id))
|
| return;
|
| - window_tree_->OnAccelerator(accelerator_id, event);
|
| + const bool needs_ack = phase == AcceleratorPhase::PRE;
|
| + if (needs_ack) {
|
| + DCHECK_EQ(EventDispatchPhase::NONE, event_dispatch_phase_);
|
| + event_dispatch_phase_ = EventDispatchPhase::PRE_TARGET_ACCELERATOR;
|
| + event_awaiting_input_ack_ = ui::Event::Clone(event);
|
| + ScheduleInputEventTimeout(window_tree_);
|
| + }
|
| + window_tree_->OnAccelerator(accelerator_id, event, needs_ack);
|
| }
|
|
|
| void WindowManagerState::SetFocusedWindowFromEventDispatcher(
|
|
|