Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/mus/ws/event_dispatcher.h" | 5 #include "components/mus/ws/event_dispatcher.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/time/time.h" | |
| 9 #include "cc/surfaces/surface_hittest.h" | 10 #include "cc/surfaces/surface_hittest.h" |
| 10 #include "components/mus/surfaces/surfaces_state.h" | 11 #include "components/mus/surfaces/surfaces_state.h" |
| 11 #include "components/mus/ws/event_dispatcher_delegate.h" | 12 #include "components/mus/ws/event_dispatcher_delegate.h" |
| 12 #include "components/mus/ws/server_window.h" | 13 #include "components/mus/ws/server_window.h" |
| 13 #include "components/mus/ws/server_window_delegate.h" | 14 #include "components/mus/ws/server_window_delegate.h" |
| 14 #include "components/mus/ws/window_coordinate_conversions.h" | 15 #include "components/mus/ws/window_coordinate_conversions.h" |
| 15 #include "components/mus/ws/window_finder.h" | 16 #include "components/mus/ws/window_finder.h" |
| 16 #include "components/mus/ws/window_tree_host_impl.h" | 17 #include "components/mus/ws/window_tree_host_impl.h" |
| 17 #include "mojo/converters/geometry/geometry_type_converters.h" | 18 #include "mojo/converters/geometry/geometry_type_converters.h" |
| 18 #include "ui/gfx/geometry/point.h" | 19 #include "ui/gfx/geometry/point.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 mojom::KeyboardCode keyboard_code_; | 151 mojom::KeyboardCode keyboard_code_; |
| 151 mojom::PointerKind pointer_kind_; | 152 mojom::PointerKind pointer_kind_; |
| 152 gfx::RectF pointer_region_; | 153 gfx::RectF pointer_region_; |
| 153 }; | 154 }; |
| 154 | 155 |
| 155 //////////////////////////////////////////////////////////////////////////////// | 156 //////////////////////////////////////////////////////////////////////////////// |
| 156 | 157 |
| 157 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) | 158 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) |
| 158 : delegate_(delegate), | 159 : delegate_(delegate), |
| 159 root_(nullptr), | 160 root_(nullptr), |
| 161 capture_window_(nullptr), | |
| 162 capture_window_in_nonclient_area_(false), | |
| 160 mouse_button_down_(false), | 163 mouse_button_down_(false), |
| 161 mouse_cursor_source_window_(nullptr) {} | 164 mouse_cursor_source_window_(nullptr) {} |
| 162 | 165 |
| 163 EventDispatcher::~EventDispatcher() { | 166 EventDispatcher::~EventDispatcher() { |
| 164 std::set<ServerWindow*> pointer_targets; | 167 std::set<ServerWindow*> pointer_targets; |
| 168 if (capture_window_) { | |
| 169 pointer_targets.insert(capture_window_); | |
| 170 capture_window_->RemoveObserver(this); | |
| 171 capture_window_ = nullptr; | |
| 172 } | |
| 165 for (const auto& pair : pointer_targets_) { | 173 for (const auto& pair : pointer_targets_) { |
| 166 if (pair.second.window && | 174 if (pair.second.window && |
| 167 pointer_targets.insert(pair.second.window).second) { | 175 pointer_targets.insert(pair.second.window).second) { |
| 168 pair.second.window->RemoveObserver(this); | 176 pair.second.window->RemoveObserver(this); |
| 169 } | 177 } |
| 170 } | 178 } |
| 179 pointer_targets_.clear(); | |
| 180 } | |
| 181 | |
| 182 void EventDispatcher::SetCaptureWindow(ServerWindow* window, | |
| 183 bool in_nonclient_area) { | |
| 184 if (window == capture_window_) | |
| 185 return; | |
| 186 | |
| 187 if (capture_window_) { | |
| 188 // Stop observing old capture window. |pointer_targets_| are cleared on | |
| 189 // intial setting of a capture window. | |
| 190 delegate_->OnLostCapture(capture_window_); | |
| 191 capture_window_->RemoveObserver(this); | |
| 192 } else { | |
| 193 // Cancel implicit capture to all other windows. | |
| 194 std::set<ServerWindow*> unobserved_windows; | |
| 195 for (const auto& pair : pointer_targets_) { | |
| 196 ServerWindow* target = pair.second.window; | |
| 197 if (!target) | |
| 198 continue; | |
| 199 if (unobserved_windows.insert(target).second) | |
| 200 target->RemoveObserver(this); | |
| 201 if (target == window) | |
| 202 continue; | |
| 203 mojom::EventPtr cancel_event = mojom::Event::New(); | |
| 204 cancel_event->action = mojom::EventType::POINTER_CANCEL; | |
| 205 cancel_event->flags = mojom::kEventFlagNone; | |
| 206 cancel_event->time_stamp = base::TimeTicks::Now().ToInternalValue(); | |
| 207 cancel_event->pointer_data = mojom::PointerData::New(); | |
| 208 // TODO(jonross): Track previous location in PointerTarget for sending | |
| 209 // cancels | |
| 210 cancel_event->pointer_data->location = mojom::LocationData::New(); | |
| 211 cancel_event->pointer_data->pointer_id = pair.first; | |
| 212 DispatchToPointerTarget(pair.second, std::move(cancel_event)); | |
| 213 } | |
| 214 pointer_targets_.clear(); | |
| 215 } | |
| 216 | |
| 217 // Begin tracking the capture window if it is not yet being observed. | |
| 218 if (window) { | |
| 219 window->AddObserver(this); | |
| 220 delegate_->SetCapture(window); | |
| 221 } else { | |
| 222 delegate_->ReleaseCapture(capture_window_); | |
| 223 if (!mouse_button_down_) | |
| 224 UpdateCursorProviderByLastKnownLocation(); | |
| 225 } | |
| 226 | |
| 227 capture_window_ = window; | |
| 228 capture_window_in_nonclient_area_ = in_nonclient_area; | |
| 171 } | 229 } |
| 172 | 230 |
| 173 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { | 231 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { |
| 174 if (!mouse_button_down_) { | 232 if (!mouse_button_down_) { |
| 175 gfx::Point location = mouse_pointer_last_location_; | 233 gfx::Point location = mouse_pointer_last_location_; |
| 176 mouse_cursor_source_window_ = | 234 mouse_cursor_source_window_ = |
| 177 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); | 235 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); |
| 178 } | 236 } |
| 179 } | 237 } |
| 180 | 238 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 std::move(event)); | 288 std::move(event)); |
| 231 } | 289 } |
| 232 | 290 |
| 233 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { | 291 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { |
| 234 const bool is_mouse_event = event->pointer_data && | 292 const bool is_mouse_event = event->pointer_data && |
| 235 event->pointer_data->kind == mojom::PointerKind::MOUSE; | 293 event->pointer_data->kind == mojom::PointerKind::MOUSE; |
| 236 | 294 |
| 237 if (is_mouse_event) | 295 if (is_mouse_event) |
| 238 mouse_pointer_last_location_ = EventLocationToPoint(*event); | 296 mouse_pointer_last_location_ = EventLocationToPoint(*event); |
| 239 | 297 |
| 298 // Release capture on pointer up. For mouse we only release if there are | |
| 299 // no buttons down. | |
| 300 const bool is_pointer_going_up = | |
| 301 (event->action == mojom::EventType::POINTER_UP || | |
| 302 event->action == mojom::EventType::POINTER_CANCEL) && | |
| 303 (event->pointer_data->kind != mojom::PointerKind::MOUSE || | |
| 304 IsOnlyOneMouseButtonDown(event->flags)); | |
| 305 | |
| 306 // Update mouse down state upon events which change it. | |
| 307 if (is_mouse_event) { | |
| 308 if (event->action == mojom::EventType::POINTER_DOWN) | |
| 309 mouse_button_down_ = true; | |
| 310 else if (is_pointer_going_up) | |
| 311 mouse_button_down_ = false; | |
| 312 } | |
| 313 | |
| 314 if (capture_window_) { | |
| 315 mouse_cursor_source_window_ = capture_window_; | |
| 316 PointerTarget pointer_target; | |
| 317 pointer_target.window = capture_window_; | |
| 318 pointer_target.in_nonclient_area = capture_window_in_nonclient_area_; | |
| 319 DispatchToPointerTarget(pointer_target, std::move(event)); | |
| 320 return; | |
| 321 } | |
| 322 | |
| 240 const int32_t pointer_id = event->pointer_data->pointer_id; | 323 const int32_t pointer_id = event->pointer_data->pointer_id; |
| 241 if (!IsTrackingPointer(pointer_id) || | 324 if (!IsTrackingPointer(pointer_id) || |
|
sky
2016/02/10 17:38:22
Shouldn't we SetCapture and ReleaseCapture in here
jonross
2016/02/10 19:45:49
Right now DisplayManager is doing its own version
sky
2016/02/10 20:06:32
Yes please as otherwise things are in a bit of wei
jonross
2016/02/10 22:51:01
Done.
| |
| 242 !pointer_targets_[pointer_id].is_pointer_down) { | 325 !pointer_targets_[pointer_id].is_pointer_down) { |
| 243 const bool any_pointers_down = AreAnyPointersDown(); | 326 const bool any_pointers_down = AreAnyPointersDown(); |
| 244 UpdateTargetForPointer(*event); | 327 UpdateTargetForPointer(*event); |
| 245 if (is_mouse_event) | 328 if (is_mouse_event) |
| 246 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; | 329 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; |
| 247 | 330 |
| 248 PointerTarget& pointer_target = pointer_targets_[pointer_id]; | 331 PointerTarget& pointer_target = pointer_targets_[pointer_id]; |
| 249 if (pointer_target.is_pointer_down) { | 332 if (pointer_target.is_pointer_down) { |
| 250 if (is_mouse_event) { | 333 if (is_mouse_event) |
| 251 mouse_button_down_ = true; | |
| 252 mouse_cursor_source_window_ = pointer_target.window; | 334 mouse_cursor_source_window_ = pointer_target.window; |
| 253 } | |
| 254 if (!any_pointers_down) | 335 if (!any_pointers_down) |
| 255 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); | 336 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); |
| 256 } | 337 } |
| 257 } | 338 } |
| 258 | 339 |
| 259 // Release capture on pointer up. For mouse we only release if there are | 340 // When we release the mouse button, we want the cursor to be sourced from |
| 260 // no buttons down. | 341 // the window under the mouse pointer, even though we're sending the button |
| 261 const bool is_pointer_going_up = | 342 // up event to the window that had implicit capture. We have to set this |
| 262 (event->action == mojom::EventType::POINTER_UP || | 343 // before we perform dispatch because the Delegate is going to read this |
| 263 event->action == mojom::EventType::POINTER_CANCEL) && | 344 // information from us. |
| 264 (event->pointer_data->kind != mojom::PointerKind::MOUSE || | 345 if (is_pointer_going_up && is_mouse_event) |
| 265 IsOnlyOneMouseButtonDown(event->flags)); | 346 UpdateCursorProviderByLastKnownLocation(); |
| 266 | |
| 267 if (is_pointer_going_up && is_mouse_event) { | |
| 268 // When we release the mouse button, we want the cursor to be sourced from | |
| 269 // the window under the mouse pointer, even though we're sending the button | |
| 270 // up event to the window that had implicit capture. We have to set this | |
| 271 // before we perform dispatch because the Delegate is going to read this | |
| 272 // information from us. | |
| 273 mouse_button_down_ = false; | |
| 274 gfx::Point location(EventLocationToPoint(*event)); | |
| 275 mouse_cursor_source_window_ = | |
| 276 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); | |
| 277 } | |
| 278 | 347 |
| 279 DispatchToPointerTarget(pointer_targets_[pointer_id], std::move(event)); | 348 DispatchToPointerTarget(pointer_targets_[pointer_id], std::move(event)); |
| 280 | 349 |
| 281 if (is_pointer_going_up) { | 350 if (is_pointer_going_up) { |
| 282 if (is_mouse_event) | 351 if (is_mouse_event) |
| 283 pointer_targets_[pointer_id].is_pointer_down = false; | 352 pointer_targets_[pointer_id].is_pointer_down = false; |
| 284 else | 353 else |
| 285 StopTrackingPointer(pointer_id); | 354 StopTrackingPointer(pointer_id); |
| 286 } | 355 } |
| 287 } | 356 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 transform.TransformPoint(&location); | 442 transform.TransformPoint(&location); |
| 374 event->pointer_data->location->x = location.x(); | 443 event->pointer_data->location->x = location.x(); |
| 375 event->pointer_data->location->y = location.y(); | 444 event->pointer_data->location->y = location.y(); |
| 376 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, | 445 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, |
| 377 std::move(event)); | 446 std::move(event)); |
| 378 } | 447 } |
| 379 | 448 |
| 380 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { | 449 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { |
| 381 window->RemoveObserver(this); | 450 window->RemoveObserver(this); |
| 382 | 451 |
| 452 if (capture_window_ == window) { | |
| 453 capture_window_ = nullptr; | |
| 454 // A window only cares to be informed that it lost capture if it explicitly | |
| 455 // requested capture. A window can lose capture if another window gains | |
| 456 // explicit capture. | |
| 457 delegate_->OnLostCapture(window); | |
|
sky
2016/02/10 17:38:22
AFAICT you won't release native capture here. By t
jonross
2016/02/10 19:45:49
Correct.
DisplayManagerDelegate::OnLostCapture()
| |
| 458 mouse_button_down_ = false; | |
| 459 UpdateCursorProviderByLastKnownLocation(); | |
| 460 return; | |
| 461 } | |
| 462 | |
| 383 for (auto& pair : pointer_targets_) { | 463 for (auto& pair : pointer_targets_) { |
| 384 if (pair.second.window == window) | 464 if (pair.second.window == window) |
| 385 pair.second.window = nullptr; | 465 pair.second.window = nullptr; |
| 386 } | 466 } |
| 387 } | 467 } |
| 388 | 468 |
| 389 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { | 469 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { |
| 390 for (const auto& pair : pointer_targets_) { | 470 for (const auto& pair : pointer_targets_) { |
| 391 if (pair.second.window == window) | 471 if (pair.second.window == window) |
| 392 return true; | 472 return true; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 418 | 498 |
| 419 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { | 499 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { |
| 420 CancelPointerEventsToTarget(window); | 500 CancelPointerEventsToTarget(window); |
| 421 | 501 |
| 422 if (mouse_cursor_source_window_ == window) | 502 if (mouse_cursor_source_window_ == window) |
| 423 mouse_cursor_source_window_ = nullptr; | 503 mouse_cursor_source_window_ = nullptr; |
| 424 } | 504 } |
| 425 | 505 |
| 426 } // namespace ws | 506 } // namespace ws |
| 427 } // namespace mus | 507 } // namespace mus |
| OLD | NEW |