| 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 |