| 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" |
| 11 #include "services/ui/ws/display_manager.h" | 11 #include "services/ui/ws/display_manager.h" |
| 12 #include "services/ui/ws/platform_display.h" | 12 #include "services/ui/ws/platform_display.h" |
| 13 #include "services/ui/ws/server_window.h" | 13 #include "services/ui/ws/server_window.h" |
| 14 #include "services/ui/ws/user_display_manager.h" | 14 #include "services/ui/ws/user_display_manager.h" |
| 15 #include "services/ui/ws/user_id_tracker.h" | 15 #include "services/ui/ws/user_id_tracker.h" |
| 16 #include "services/ui/ws/window_manager_display_root.h" | 16 #include "services/ui/ws/window_manager_display_root.h" |
| 17 #include "services/ui/ws/window_server.h" | 17 #include "services/ui/ws/window_server.h" |
| 18 #include "services/ui/ws/window_tree.h" | 18 #include "services/ui/ws/window_tree.h" |
| 19 #include "ui/events/event.h" | 19 #include "ui/events/event.h" |
| 20 | 20 |
| 21 namespace ui { | 21 namespace ui { |
| 22 namespace ws { | 22 namespace ws { |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 // Debug accelerator IDs start far above the highest valid Windows command ID | |
| 26 // (0xDFFF) and Chrome's highest IDC command ID. | |
| 27 const uint32_t kPrintWindowsDebugAcceleratorId = 1u << 31; | |
| 28 | |
| 29 base::TimeDelta GetDefaultAckTimerDelay() { | 25 base::TimeDelta GetDefaultAckTimerDelay() { |
| 30 #if defined(NDEBUG) | 26 #if defined(NDEBUG) |
| 31 return base::TimeDelta::FromMilliseconds(100); | 27 return base::TimeDelta::FromMilliseconds(100); |
| 32 #else | 28 #else |
| 33 return base::TimeDelta::FromMilliseconds(1000); | 29 return base::TimeDelta::FromMilliseconds(1000); |
| 34 #endif | 30 #endif |
| 35 } | 31 } |
| 36 | 32 |
| 37 bool EventsCanBeCoalesced(const ui::Event& one, const ui::Event& two) { | 33 bool EventsCanBeCoalesced(const ui::Event& one, const ui::Event& two) { |
| 38 if (one.type() != two.type() || one.flags() != two.flags()) | 34 if (one.type() != two.type() || one.flags() != two.flags()) |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 if (!event_queue_.empty() && !event_queue_.back()->processed_target && | 189 if (!event_queue_.empty() && !event_queue_.back()->processed_target && |
| 194 EventsCanBeCoalesced(*event_queue_.back()->event, event)) { | 190 EventsCanBeCoalesced(*event_queue_.back()->event, event)) { |
| 195 event_queue_.back()->event = CoalesceEvents( | 191 event_queue_.back()->event = CoalesceEvents( |
| 196 std::move(event_queue_.back()->event), ui::Event::Clone(event)); | 192 std::move(event_queue_.back()->event), ui::Event::Clone(event)); |
| 197 return; | 193 return; |
| 198 } | 194 } |
| 199 QueueEvent(event, nullptr); | 195 QueueEvent(event, nullptr); |
| 200 return; | 196 return; |
| 201 } | 197 } |
| 202 | 198 |
| 203 event_dispatcher_.ProcessEvent(event, | 199 ProcessEventImpl(event); |
| 204 EventDispatcher::AcceleratorMatchPhase::ANY); | |
| 205 } | 200 } |
| 206 | 201 |
| 207 void WindowManagerState::OnEventAck(mojom::WindowTree* tree, | 202 void WindowManagerState::OnEventAck(mojom::WindowTree* tree, |
| 208 mojom::EventResult result) { | 203 mojom::EventResult result) { |
| 209 if (tree_awaiting_input_ack_ != tree || | 204 if (tree_awaiting_input_ack_ != tree || |
| 210 event_dispatch_phase_ != EventDispatchPhase::TARGET) { | 205 event_dispatch_phase_ != EventDispatchPhase::TARGET) { |
| 211 // TODO(sad): The ack must have arrived after the timeout. We should do | 206 // TODO(sad): The ack must have arrived after the timeout. We should do |
| 212 // something here, and in OnEventAckTimeout(). | 207 // something here, and in OnEventAckTimeout(). |
| 213 return; | 208 return; |
| 214 } | 209 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 void WindowManagerState::OnEventAckTimeout(ClientSpecificId client_id) { | 285 void WindowManagerState::OnEventAckTimeout(ClientSpecificId client_id) { |
| 291 WindowTree* hung_tree = window_server()->GetTreeWithId(client_id); | 286 WindowTree* hung_tree = window_server()->GetTreeWithId(client_id); |
| 292 if (hung_tree && !hung_tree->janky()) | 287 if (hung_tree && !hung_tree->janky()) |
| 293 window_tree_->ClientJankinessChanged(hung_tree); | 288 window_tree_->ClientJankinessChanged(hung_tree); |
| 294 if (event_dispatch_phase_ == EventDispatchPhase::PRE_TARGET_ACCELERATOR) | 289 if (event_dispatch_phase_ == EventDispatchPhase::PRE_TARGET_ACCELERATOR) |
| 295 OnAcceleratorAck(mojom::EventResult::UNHANDLED); | 290 OnAcceleratorAck(mojom::EventResult::UNHANDLED); |
| 296 else | 291 else |
| 297 OnEventAck(tree_awaiting_input_ack_, mojom::EventResult::UNHANDLED); | 292 OnEventAck(tree_awaiting_input_ack_, mojom::EventResult::UNHANDLED); |
| 298 } | 293 } |
| 299 | 294 |
| 295 void WindowManagerState::ProcessEventImpl(const ui::Event& event) { |
| 296 // Debug accelerators are always checked and don't interfere with processing. |
| 297 ProcessDebugAccelerator(event); |
| 298 event_dispatcher_.ProcessEvent(event, |
| 299 EventDispatcher::AcceleratorMatchPhase::ANY); |
| 300 } |
| 301 |
| 300 void WindowManagerState::QueueEvent( | 302 void WindowManagerState::QueueEvent( |
| 301 const ui::Event& event, | 303 const ui::Event& event, |
| 302 std::unique_ptr<ProcessedEventTarget> processed_event_target) { | 304 std::unique_ptr<ProcessedEventTarget> processed_event_target) { |
| 303 std::unique_ptr<QueuedEvent> queued_event(new QueuedEvent); | 305 std::unique_ptr<QueuedEvent> queued_event(new QueuedEvent); |
| 304 queued_event->event = ui::Event::Clone(event); | 306 queued_event->event = ui::Event::Clone(event); |
| 305 queued_event->processed_target = std::move(processed_event_target); | 307 queued_event->processed_target = std::move(processed_event_target); |
| 306 event_queue_.push(std::move(queued_event)); | 308 event_queue_.push(std::move(queued_event)); |
| 307 } | 309 } |
| 308 | 310 |
| 309 void WindowManagerState::ProcessNextEventFromQueue() { | 311 void WindowManagerState::ProcessNextEventFromQueue() { |
| 310 // Loop through |event_queue_| stopping after dispatching the first valid | 312 // Loop through |event_queue_| stopping after dispatching the first valid |
| 311 // event. | 313 // event. |
| 312 while (!event_queue_.empty()) { | 314 while (!event_queue_.empty()) { |
| 313 std::unique_ptr<QueuedEvent> queued_event = std::move(event_queue_.front()); | 315 std::unique_ptr<QueuedEvent> queued_event = std::move(event_queue_.front()); |
| 314 event_queue_.pop(); | 316 event_queue_.pop(); |
| 315 if (!queued_event->processed_target) { | 317 if (!queued_event->processed_target) { |
| 316 event_dispatcher_.ProcessEvent( | 318 ProcessEventImpl(*queued_event->event); |
| 317 *queued_event->event, EventDispatcher::AcceleratorMatchPhase::ANY); | |
| 318 return; | 319 return; |
| 319 } | 320 } |
| 320 if (queued_event->processed_target->IsValid()) { | 321 if (queued_event->processed_target->IsValid()) { |
| 321 DispatchInputEventToWindowImpl( | 322 DispatchInputEventToWindowImpl( |
| 322 queued_event->processed_target->window(), | 323 queued_event->processed_target->window(), |
| 323 queued_event->processed_target->client_id(), *queued_event->event, | 324 queued_event->processed_target->client_id(), *queued_event->event, |
| 324 queued_event->processed_target->accelerator()); | 325 queued_event->processed_target->accelerator()); |
| 325 return; | 326 return; |
| 326 } | 327 } |
| 327 } | 328 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 357 post_target_accelerator_ = accelerator; | 358 post_target_accelerator_ = accelerator; |
| 358 } | 359 } |
| 359 | 360 |
| 360 // Ignore |tree| because it will receive the event via normal dispatch. | 361 // Ignore |tree| because it will receive the event via normal dispatch. |
| 361 window_server()->SendToEventObservers(event, user_id(), tree); | 362 window_server()->SendToEventObservers(event, user_id(), tree); |
| 362 | 363 |
| 363 tree->DispatchInputEvent(target, event); | 364 tree->DispatchInputEvent(target, event); |
| 364 } | 365 } |
| 365 | 366 |
| 366 void WindowManagerState::AddDebugAccelerators() { | 367 void WindowManagerState::AddDebugAccelerators() { |
| 367 // Always register the accelerators, even if they only work in debug, so that | 368 const DebugAccelerator accelerator = { |
| 368 // keyboard behavior is the same in release and debug builds. | 369 DebugAcceleratorType::PRINT_WINDOWS, ui::VKEY_S, |
| 369 mojom::EventMatcherPtr matcher = CreateKeyMatcher( | 370 ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN}; |
| 370 ui::mojom::KeyboardCode::S, ui::mojom::kEventFlagControlDown | | 371 debug_accelerators_.push_back(accelerator); |
| 371 ui::mojom::kEventFlagAltDown | | |
| 372 ui::mojom::kEventFlagShiftDown); | |
| 373 event_dispatcher_.AddAccelerator(kPrintWindowsDebugAcceleratorId, | |
| 374 std::move(matcher)); | |
| 375 } | 372 } |
| 376 | 373 |
| 377 bool WindowManagerState::HandleDebugAccelerator(uint32_t accelerator_id) { | 374 void WindowManagerState::ProcessDebugAccelerator(const ui::Event& event) { |
| 375 if (event.type() != ui::ET_KEY_PRESSED) |
| 376 return; |
| 377 |
| 378 const ui::KeyEvent& key_event = *event.AsKeyEvent(); |
| 379 for (const DebugAccelerator& accelerator : debug_accelerators_) { |
| 380 if (accelerator.key_code == key_event.key_code() && |
| 381 accelerator.event_flags == key_event.flags()) { |
| 382 HandleDebugAccelerator(accelerator.type); |
| 383 break; |
| 384 } |
| 385 } |
| 386 } |
| 387 |
| 388 void WindowManagerState::HandleDebugAccelerator(DebugAcceleratorType type) { |
| 378 #if !defined(NDEBUG) | 389 #if !defined(NDEBUG) |
| 379 if (accelerator_id == kPrintWindowsDebugAcceleratorId) { | 390 // Error so it will be collected in system logs. |
| 380 // Error so it will be collected in system logs. | 391 for (Display* display : display_manager()->displays()) { |
| 381 for (Display* display : display_manager()->displays()) { | 392 WindowManagerDisplayRoot* display_root = |
| 382 WindowManagerDisplayRoot* display_root = | 393 display->GetWindowManagerDisplayRootForUser(user_id()); |
| 383 display->GetWindowManagerDisplayRootForUser(user_id()); | 394 if (display_root) { |
| 384 if (display_root) { | 395 LOG(ERROR) << "ServerWindow hierarchy:\n" |
| 385 LOG(ERROR) << "ServerWindow hierarchy:\n" | 396 << display_root->root()->GetDebugWindowHierarchy(); |
| 386 << display_root->root()->GetDebugWindowHierarchy(); | |
| 387 } | |
| 388 } | 397 } |
| 389 return true; | |
| 390 } | 398 } |
| 391 #endif | 399 #endif |
| 392 return false; | |
| 393 } | 400 } |
| 394 | 401 |
| 395 void WindowManagerState::ScheduleInputEventTimeout(WindowTree* tree) { | 402 void WindowManagerState::ScheduleInputEventTimeout(WindowTree* tree) { |
| 396 // TOOD(sad): Adjust this delay, possibly make this dynamic. | 403 // TOOD(sad): Adjust this delay, possibly make this dynamic. |
| 397 const base::TimeDelta max_delay = base::debug::BeingDebugged() | 404 const base::TimeDelta max_delay = base::debug::BeingDebugged() |
| 398 ? base::TimeDelta::FromDays(1) | 405 ? base::TimeDelta::FromDays(1) |
| 399 : GetDefaultAckTimerDelay(); | 406 : GetDefaultAckTimerDelay(); |
| 400 event_ack_timer_.Start(FROM_HERE, max_delay, | 407 event_ack_timer_.Start(FROM_HERE, max_delay, |
| 401 base::Bind(&WindowManagerState::OnEventAckTimeout, | 408 base::Bind(&WindowManagerState::OnEventAckTimeout, |
| 402 weak_factory_.GetWeakPtr(), tree->id())); | 409 weak_factory_.GetWeakPtr(), tree->id())); |
| 403 | 410 |
| 404 tree_awaiting_input_ack_ = tree; | 411 tree_awaiting_input_ack_ = tree; |
| 405 } | 412 } |
| 406 | 413 |
| 407 //////////////////////////////////////////////////////////////////////////////// | 414 //////////////////////////////////////////////////////////////////////////////// |
| 408 // EventDispatcherDelegate: | 415 // EventDispatcherDelegate: |
| 409 | 416 |
| 410 void WindowManagerState::OnAccelerator(uint32_t accelerator_id, | 417 void WindowManagerState::OnAccelerator(uint32_t accelerator_id, |
| 411 const ui::Event& event, | 418 const ui::Event& event, |
| 412 AcceleratorPhase phase) { | 419 AcceleratorPhase phase) { |
| 413 DCHECK(IsActive()); | 420 DCHECK(IsActive()); |
| 414 if (HandleDebugAccelerator(accelerator_id)) | |
| 415 return; | |
| 416 const bool needs_ack = phase == AcceleratorPhase::PRE; | 421 const bool needs_ack = phase == AcceleratorPhase::PRE; |
| 417 if (needs_ack) { | 422 if (needs_ack) { |
| 418 DCHECK_EQ(EventDispatchPhase::NONE, event_dispatch_phase_); | 423 DCHECK_EQ(EventDispatchPhase::NONE, event_dispatch_phase_); |
| 419 event_dispatch_phase_ = EventDispatchPhase::PRE_TARGET_ACCELERATOR; | 424 event_dispatch_phase_ = EventDispatchPhase::PRE_TARGET_ACCELERATOR; |
| 420 event_awaiting_input_ack_ = ui::Event::Clone(event); | 425 event_awaiting_input_ack_ = ui::Event::Clone(event); |
| 421 ScheduleInputEventTimeout(window_tree_); | 426 ScheduleInputEventTimeout(window_tree_); |
| 422 } | 427 } |
| 423 window_tree_->OnAccelerator(accelerator_id, event, needs_ack); | 428 window_tree_->OnAccelerator(accelerator_id, event, needs_ack); |
| 424 } | 429 } |
| 425 | 430 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 return display_root ? display_root->root() : nullptr; | 534 return display_root ? display_root->root() : nullptr; |
| 530 } | 535 } |
| 531 | 536 |
| 532 void WindowManagerState::OnEventTargetNotFound(const ui::Event& event) { | 537 void WindowManagerState::OnEventTargetNotFound(const ui::Event& event) { |
| 533 window_server()->SendToEventObservers(event, user_id(), | 538 window_server()->SendToEventObservers(event, user_id(), |
| 534 nullptr /* ignore_tree */); | 539 nullptr /* ignore_tree */); |
| 535 } | 540 } |
| 536 | 541 |
| 537 } // namespace ws | 542 } // namespace ws |
| 538 } // namespace ui | 543 } // namespace ui |
| OLD | NEW |