OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "services/ui/ws/window_manager_state.h" | 5 #include "services/ui/ws/window_manager_state.h" |
6 | 6 |
7 #include "base/memory/weak_ptr.h" | 7 #include "base/memory/weak_ptr.h" |
8 #include "services/shell/public/interfaces/connector.mojom.h" | 8 #include "services/shell/public/interfaces/connector.mojom.h" |
9 #include "services/ui/common/event_matcher_util.h" | 9 #include "services/ui/common/event_matcher_util.h" |
10 #include "services/ui/ws/accelerator.h" | 10 #include "services/ui/ws/accelerator.h" |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 if (event_ack_timer_.IsRunning()) { | 192 if (event_ack_timer_.IsRunning()) { |
193 if (!event_queue_.empty() && !event_queue_.back()->processed_target && | 193 if (!event_queue_.empty() && !event_queue_.back()->processed_target && |
194 EventsCanBeCoalesced(*event_queue_.back()->event, event)) { | 194 EventsCanBeCoalesced(*event_queue_.back()->event, event)) { |
195 event_queue_.back()->event = CoalesceEvents( | 195 event_queue_.back()->event = CoalesceEvents( |
196 std::move(event_queue_.back()->event), ui::Event::Clone(event)); | 196 std::move(event_queue_.back()->event), ui::Event::Clone(event)); |
197 return; | 197 return; |
198 } | 198 } |
199 QueueEvent(event, nullptr); | 199 QueueEvent(event, nullptr); |
200 return; | 200 return; |
201 } | 201 } |
202 event_dispatcher_.ProcessEvent(event); | 202 |
| 203 event_dispatcher_.ProcessEvent(event, |
| 204 EventDispatcher::AcceleratorMatchPhase::ANY); |
203 } | 205 } |
204 | 206 |
205 void WindowManagerState::OnEventAck(mojom::WindowTree* tree, | 207 void WindowManagerState::OnEventAck(mojom::WindowTree* tree, |
206 mojom::EventResult result) { | 208 mojom::EventResult result) { |
207 if (tree_awaiting_input_ack_ != tree) { | 209 if (tree_awaiting_input_ack_ != tree || |
| 210 event_dispatch_phase_ != EventDispatchPhase::TARGET) { |
208 // TODO(sad): The ack must have arrived after the timeout. We should do | 211 // TODO(sad): The ack must have arrived after the timeout. We should do |
209 // something here, and in OnEventAckTimeout(). | 212 // something here, and in OnEventAckTimeout(). |
210 return; | 213 return; |
211 } | 214 } |
212 tree_awaiting_input_ack_ = nullptr; | 215 tree_awaiting_input_ack_ = nullptr; |
213 event_ack_timer_.Stop(); | 216 event_ack_timer_.Stop(); |
214 | 217 |
215 if (result == mojom::EventResult::UNHANDLED && post_target_accelerator_) | 218 if (result == mojom::EventResult::UNHANDLED && post_target_accelerator_) { |
216 OnAccelerator(post_target_accelerator_->id(), *event_awaiting_input_ack_); | 219 OnAccelerator(post_target_accelerator_->id(), *event_awaiting_input_ack_, |
| 220 AcceleratorPhase::POST); |
| 221 } |
217 | 222 |
| 223 event_dispatch_phase_ = EventDispatchPhase::NONE; |
218 ProcessNextEventFromQueue(); | 224 ProcessNextEventFromQueue(); |
219 } | 225 } |
220 | 226 |
| 227 void WindowManagerState::OnAcceleratorAck(mojom::EventResult result) { |
| 228 if (event_dispatch_phase_ != EventDispatchPhase::PRE_TARGET_ACCELERATOR) { |
| 229 // TODO(sad): The ack must have arrived after the timeout. We should do |
| 230 // something here, and in OnEventAckTimeout(). |
| 231 return; |
| 232 } |
| 233 |
| 234 tree_awaiting_input_ack_ = nullptr; |
| 235 event_ack_timer_.Stop(); |
| 236 event_dispatch_phase_ = EventDispatchPhase::NONE; |
| 237 |
| 238 if (result == mojom::EventResult::UNHANDLED) { |
| 239 event_dispatcher_.ProcessEvent( |
| 240 *event_awaiting_input_ack_, |
| 241 EventDispatcher::AcceleratorMatchPhase::POST_ONLY); |
| 242 } else { |
| 243 // We're not going to process the event any further, notify event observers. |
| 244 // We don't do this first to ensure we don't send an event twice to clients. |
| 245 window_server()->SendToEventObservers(*event_awaiting_input_ack_, user_id(), |
| 246 nullptr); |
| 247 ProcessNextEventFromQueue(); |
| 248 } |
| 249 } |
| 250 |
221 const WindowServer* WindowManagerState::window_server() const { | 251 const WindowServer* WindowManagerState::window_server() const { |
222 return window_tree_->window_server(); | 252 return window_tree_->window_server(); |
223 } | 253 } |
224 | 254 |
225 WindowServer* WindowManagerState::window_server() { | 255 WindowServer* WindowManagerState::window_server() { |
226 return window_tree_->window_server(); | 256 return window_tree_->window_server(); |
227 } | 257 } |
228 | 258 |
229 DisplayManager* WindowManagerState::display_manager() { | 259 DisplayManager* WindowManagerState::display_manager() { |
230 return window_tree_->display_manager(); | 260 return window_tree_->display_manager(); |
(...skipping 20 matching lines...) Expand all Loading... |
251 return display_root->root(); | 281 return display_root->root(); |
252 } | 282 } |
253 NOTREACHED(); | 283 NOTREACHED(); |
254 return nullptr; | 284 return nullptr; |
255 } | 285 } |
256 | 286 |
257 void WindowManagerState::OnEventAckTimeout(ClientSpecificId client_id) { | 287 void WindowManagerState::OnEventAckTimeout(ClientSpecificId client_id) { |
258 WindowTree* hung_tree = window_server()->GetTreeWithId(client_id); | 288 WindowTree* hung_tree = window_server()->GetTreeWithId(client_id); |
259 if (hung_tree && !hung_tree->janky()) | 289 if (hung_tree && !hung_tree->janky()) |
260 window_tree_->ClientJankinessChanged(hung_tree); | 290 window_tree_->ClientJankinessChanged(hung_tree); |
261 OnEventAck(tree_awaiting_input_ack_, mojom::EventResult::UNHANDLED); | 291 if (event_dispatch_phase_ == EventDispatchPhase::PRE_TARGET_ACCELERATOR) |
| 292 OnAcceleratorAck(mojom::EventResult::UNHANDLED); |
| 293 else |
| 294 OnEventAck(tree_awaiting_input_ack_, mojom::EventResult::UNHANDLED); |
262 } | 295 } |
263 | 296 |
264 void WindowManagerState::QueueEvent( | 297 void WindowManagerState::QueueEvent( |
265 const ui::Event& event, | 298 const ui::Event& event, |
266 std::unique_ptr<ProcessedEventTarget> processed_event_target) { | 299 std::unique_ptr<ProcessedEventTarget> processed_event_target) { |
267 std::unique_ptr<QueuedEvent> queued_event(new QueuedEvent); | 300 std::unique_ptr<QueuedEvent> queued_event(new QueuedEvent); |
268 queued_event->event = ui::Event::Clone(event); | 301 queued_event->event = ui::Event::Clone(event); |
269 queued_event->processed_target = std::move(processed_event_target); | 302 queued_event->processed_target = std::move(processed_event_target); |
270 event_queue_.push(std::move(queued_event)); | 303 event_queue_.push(std::move(queued_event)); |
271 } | 304 } |
272 | 305 |
273 void WindowManagerState::ProcessNextEventFromQueue() { | 306 void WindowManagerState::ProcessNextEventFromQueue() { |
274 // Loop through |event_queue_| stopping after dispatching the first valid | 307 // Loop through |event_queue_| stopping after dispatching the first valid |
275 // event. | 308 // event. |
276 while (!event_queue_.empty()) { | 309 while (!event_queue_.empty()) { |
277 std::unique_ptr<QueuedEvent> queued_event = std::move(event_queue_.front()); | 310 std::unique_ptr<QueuedEvent> queued_event = std::move(event_queue_.front()); |
278 event_queue_.pop(); | 311 event_queue_.pop(); |
279 if (!queued_event->processed_target) { | 312 if (!queued_event->processed_target) { |
280 event_dispatcher_.ProcessEvent(*queued_event->event); | 313 event_dispatcher_.ProcessEvent( |
| 314 *queued_event->event, EventDispatcher::AcceleratorMatchPhase::ANY); |
281 return; | 315 return; |
282 } | 316 } |
283 if (queued_event->processed_target->IsValid()) { | 317 if (queued_event->processed_target->IsValid()) { |
284 DispatchInputEventToWindowImpl( | 318 DispatchInputEventToWindowImpl( |
285 queued_event->processed_target->window(), | 319 queued_event->processed_target->window(), |
286 queued_event->processed_target->client_id(), *queued_event->event, | 320 queued_event->processed_target->client_id(), *queued_event->event, |
287 queued_event->processed_target->accelerator()); | 321 queued_event->processed_target->accelerator()); |
288 return; | 322 return; |
289 } | 323 } |
290 } | 324 } |
(...skipping 11 matching lines...) Expand all Loading... |
302 DCHECK(event_dispatcher_.mouse_cursor_source_window()); | 336 DCHECK(event_dispatcher_.mouse_cursor_source_window()); |
303 | 337 |
304 int32_t cursor_id = 0; | 338 int32_t cursor_id = 0; |
305 if (event_dispatcher_.GetCurrentMouseCursor(&cursor_id)) { | 339 if (event_dispatcher_.GetCurrentMouseCursor(&cursor_id)) { |
306 WindowManagerDisplayRoot* display_root = | 340 WindowManagerDisplayRoot* display_root = |
307 display_manager()->GetWindowManagerDisplayRoot(target); | 341 display_manager()->GetWindowManagerDisplayRoot(target); |
308 display_root->display()->UpdateNativeCursor(cursor_id); | 342 display_root->display()->UpdateNativeCursor(cursor_id); |
309 } | 343 } |
310 } | 344 } |
311 | 345 |
| 346 event_dispatch_phase_ = EventDispatchPhase::TARGET; |
| 347 |
312 WindowTree* tree = window_server()->GetTreeWithId(client_id); | 348 WindowTree* tree = window_server()->GetTreeWithId(client_id); |
313 | 349 |
314 // TOOD(sad): Adjust this delay, possibly make this dynamic. | 350 ScheduleInputEventTimeout(tree); |
315 const base::TimeDelta max_delay = base::debug::BeingDebugged() | |
316 ? base::TimeDelta::FromDays(1) | |
317 : GetDefaultAckTimerDelay(); | |
318 event_ack_timer_.Start( | |
319 FROM_HERE, max_delay, | |
320 base::Bind(&WindowManagerState::OnEventAckTimeout, | |
321 weak_factory_.GetWeakPtr(), tree->id())); | |
322 | 351 |
323 tree_awaiting_input_ack_ = tree; | |
324 if (accelerator) { | 352 if (accelerator) { |
325 event_awaiting_input_ack_ = ui::Event::Clone(event); | 353 event_awaiting_input_ack_ = ui::Event::Clone(event); |
326 post_target_accelerator_ = accelerator; | 354 post_target_accelerator_ = accelerator; |
327 } | 355 } |
328 | 356 |
329 // Ignore |tree| because it will receive the event via normal dispatch. | 357 // Ignore |tree| because it will receive the event via normal dispatch. |
330 window_server()->SendToEventObservers(event, user_id(), tree); | 358 window_server()->SendToEventObservers(event, user_id(), tree); |
331 | 359 |
332 tree->DispatchInputEvent(target, event); | 360 tree->DispatchInputEvent(target, event); |
333 } | 361 } |
(...skipping 20 matching lines...) Expand all Loading... |
354 LOG(ERROR) << "ServerWindow hierarchy:\n" | 382 LOG(ERROR) << "ServerWindow hierarchy:\n" |
355 << display_root->root()->GetDebugWindowHierarchy(); | 383 << display_root->root()->GetDebugWindowHierarchy(); |
356 } | 384 } |
357 } | 385 } |
358 return true; | 386 return true; |
359 } | 387 } |
360 #endif | 388 #endif |
361 return false; | 389 return false; |
362 } | 390 } |
363 | 391 |
| 392 void WindowManagerState::ScheduleInputEventTimeout(WindowTree* tree) { |
| 393 // TOOD(sad): Adjust this delay, possibly make this dynamic. |
| 394 const base::TimeDelta max_delay = base::debug::BeingDebugged() |
| 395 ? base::TimeDelta::FromDays(1) |
| 396 : GetDefaultAckTimerDelay(); |
| 397 event_ack_timer_.Start(FROM_HERE, max_delay, |
| 398 base::Bind(&WindowManagerState::OnEventAckTimeout, |
| 399 weak_factory_.GetWeakPtr(), tree->id())); |
| 400 |
| 401 tree_awaiting_input_ack_ = tree; |
| 402 } |
| 403 |
364 //////////////////////////////////////////////////////////////////////////////// | 404 //////////////////////////////////////////////////////////////////////////////// |
365 // EventDispatcherDelegate: | 405 // EventDispatcherDelegate: |
366 | 406 |
367 void WindowManagerState::OnAccelerator(uint32_t accelerator_id, | 407 void WindowManagerState::OnAccelerator(uint32_t accelerator_id, |
368 const ui::Event& event) { | 408 const ui::Event& event, |
| 409 AcceleratorPhase phase) { |
369 DCHECK(IsActive()); | 410 DCHECK(IsActive()); |
370 if (HandleDebugAccelerator(accelerator_id)) | 411 if (HandleDebugAccelerator(accelerator_id)) |
371 return; | 412 return; |
372 window_tree_->OnAccelerator(accelerator_id, event); | 413 const bool needs_ack = phase == AcceleratorPhase::PRE; |
| 414 if (needs_ack) { |
| 415 DCHECK_EQ(EventDispatchPhase::NONE, event_dispatch_phase_); |
| 416 event_dispatch_phase_ = EventDispatchPhase::PRE_TARGET_ACCELERATOR; |
| 417 event_awaiting_input_ack_ = ui::Event::Clone(event); |
| 418 ScheduleInputEventTimeout(window_tree_); |
| 419 } |
| 420 window_tree_->OnAccelerator(accelerator_id, event, needs_ack); |
373 } | 421 } |
374 | 422 |
375 void WindowManagerState::SetFocusedWindowFromEventDispatcher( | 423 void WindowManagerState::SetFocusedWindowFromEventDispatcher( |
376 ServerWindow* new_focused_window) { | 424 ServerWindow* new_focused_window) { |
377 DCHECK(IsActive()); | 425 DCHECK(IsActive()); |
378 window_server()->SetFocusedWindow(new_focused_window); | 426 window_server()->SetFocusedWindow(new_focused_window); |
379 } | 427 } |
380 | 428 |
381 ServerWindow* WindowManagerState::GetFocusedWindowForEventDispatcher() { | 429 ServerWindow* WindowManagerState::GetFocusedWindowForEventDispatcher() { |
382 return window_server()->GetFocusedWindow(); | 430 return window_server()->GetFocusedWindow(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 return display_root ? display_root->root() : nullptr; | 524 return display_root ? display_root->root() : nullptr; |
477 } | 525 } |
478 | 526 |
479 void WindowManagerState::OnEventTargetNotFound(const ui::Event& event) { | 527 void WindowManagerState::OnEventTargetNotFound(const ui::Event& event) { |
480 window_server()->SendToEventObservers(event, user_id(), | 528 window_server()->SendToEventObservers(event, user_id(), |
481 nullptr /* ignore_tree */); | 529 nullptr /* ignore_tree */); |
482 } | 530 } |
483 | 531 |
484 } // namespace ws | 532 } // namespace ws |
485 } // namespace ui | 533 } // namespace ui |
OLD | NEW |