| Index: components/mus/ws/event_dispatcher.cc
|
| diff --git a/components/mus/ws/event_dispatcher.cc b/components/mus/ws/event_dispatcher.cc
|
| deleted file mode 100644
|
| index 23874c3abc406cfdfa651e788b5891cc81a43ff3..0000000000000000000000000000000000000000
|
| --- a/components/mus/ws/event_dispatcher.cc
|
| +++ /dev/null
|
| @@ -1,559 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "components/mus/ws/event_dispatcher.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/time/time.h"
|
| -#include "components/mus/ws/accelerator.h"
|
| -#include "components/mus/ws/display.h"
|
| -#include "components/mus/ws/event_dispatcher_delegate.h"
|
| -#include "components/mus/ws/server_window.h"
|
| -#include "components/mus/ws/server_window_delegate.h"
|
| -#include "components/mus/ws/window_coordinate_conversions.h"
|
| -#include "components/mus/ws/window_finder.h"
|
| -#include "ui/events/event_utils.h"
|
| -#include "ui/gfx/geometry/point.h"
|
| -#include "ui/gfx/geometry/point_conversions.h"
|
| -
|
| -namespace mus {
|
| -namespace ws {
|
| -
|
| -using Entry = std::pair<uint32_t, std::unique_ptr<Accelerator>>;
|
| -
|
| -namespace {
|
| -
|
| -bool IsOnlyOneMouseButtonDown(int flags) {
|
| - const uint32_t button_only_flags =
|
| - flags & (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON |
|
| - ui::EF_RIGHT_MOUSE_BUTTON);
|
| - return button_only_flags == ui::EF_LEFT_MOUSE_BUTTON ||
|
| - button_only_flags == ui::EF_MIDDLE_MOUSE_BUTTON ||
|
| - button_only_flags == ui::EF_RIGHT_MOUSE_BUTTON;
|
| -}
|
| -
|
| -bool IsLocationInNonclientArea(const ServerWindow* target,
|
| - const gfx::Point& location) {
|
| - if (!target->parent())
|
| - return false;
|
| -
|
| - gfx::Rect client_area(target->bounds().size());
|
| - client_area.Inset(target->client_area());
|
| - if (client_area.Contains(location))
|
| - return false;
|
| -
|
| - for (const auto& rect : target->additional_client_areas()) {
|
| - if (rect.Contains(location))
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -uint32_t PointerId(const ui::LocatedEvent& event) {
|
| - if (event.IsPointerEvent())
|
| - return event.AsPointerEvent()->pointer_id();
|
| - if (event.IsMouseWheelEvent())
|
| - return ui::PointerEvent::kMousePointerId;
|
| -
|
| - NOTREACHED();
|
| - return 0;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
|
| - : delegate_(delegate),
|
| - capture_window_(nullptr),
|
| - capture_window_client_id_(kInvalidClientId),
|
| - modal_window_controller_(this),
|
| - mouse_button_down_(false),
|
| - mouse_cursor_source_window_(nullptr),
|
| - mouse_cursor_in_non_client_area_(false) {}
|
| -
|
| -EventDispatcher::~EventDispatcher() {
|
| - if (capture_window_) {
|
| - UnobserveWindow(capture_window_);
|
| - capture_window_ = nullptr;
|
| - capture_window_client_id_ = kInvalidClientId;
|
| - }
|
| - for (const auto& pair : pointer_targets_) {
|
| - if (pair.second.window)
|
| - UnobserveWindow(pair.second.window);
|
| - }
|
| - pointer_targets_.clear();
|
| -}
|
| -
|
| -void EventDispatcher::Reset() {
|
| - if (capture_window_) {
|
| - CancelPointerEventsToTarget(capture_window_);
|
| - DCHECK(capture_window_ == nullptr);
|
| - }
|
| -
|
| - while (!pointer_targets_.empty())
|
| - StopTrackingPointer(pointer_targets_.begin()->first);
|
| -
|
| - mouse_button_down_ = false;
|
| -}
|
| -
|
| -void EventDispatcher::SetMousePointerScreenLocation(
|
| - const gfx::Point& screen_location) {
|
| - DCHECK(pointer_targets_.empty());
|
| - mouse_pointer_last_location_ = screen_location;
|
| - UpdateCursorProviderByLastKnownLocation();
|
| - // Write our initial location back to our shared screen coordinate. This
|
| - // shouldn't cause problems because we already read the cursor before we
|
| - // process any events in views during window construction.
|
| - delegate_->OnMouseCursorLocationChanged(screen_location);
|
| -}
|
| -
|
| -bool EventDispatcher::GetCurrentMouseCursor(int32_t* cursor_out) {
|
| - if (!mouse_cursor_source_window_)
|
| - return false;
|
| -
|
| - *cursor_out = mouse_cursor_in_non_client_area_
|
| - ? mouse_cursor_source_window_->non_client_cursor()
|
| - : mouse_cursor_source_window_->cursor();
|
| - return true;
|
| -}
|
| -
|
| -bool EventDispatcher::SetCaptureWindow(ServerWindow* window,
|
| - ClientSpecificId client_id) {
|
| - if (!window)
|
| - client_id = kInvalidClientId;
|
| -
|
| - if (window == capture_window_ && client_id == capture_window_client_id_)
|
| - return true;
|
| -
|
| - // A window that is blocked by a modal window cannot gain capture.
|
| - if (window && modal_window_controller_.IsWindowBlocked(window))
|
| - return false;
|
| -
|
| - if (capture_window_) {
|
| - // Stop observing old capture window. |pointer_targets_| are cleared on
|
| - // initial setting of a capture window.
|
| - delegate_->OnServerWindowCaptureLost(capture_window_);
|
| - UnobserveWindow(capture_window_);
|
| - } else {
|
| - // Cancel implicit capture to all other windows.
|
| - for (const auto& pair : pointer_targets_) {
|
| - ServerWindow* target = pair.second.window;
|
| - if (!target)
|
| - continue;
|
| - UnobserveWindow(target);
|
| - if (target == window)
|
| - continue;
|
| -
|
| - ui::EventType event_type = pair.second.is_mouse_event
|
| - ? ui::ET_POINTER_EXITED
|
| - : ui::ET_POINTER_CANCELLED;
|
| - ui::EventPointerType pointer_type =
|
| - pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE
|
| - : ui::EventPointerType::POINTER_TYPE_TOUCH;
|
| - // TODO(jonross): Track previous location in PointerTarget for sending
|
| - // cancels.
|
| - ui::PointerEvent event(
|
| - event_type, gfx::Point(), gfx::Point(), ui::EF_NONE, pair.first,
|
| - ui::PointerDetails(pointer_type), ui::EventTimeForNow());
|
| - DispatchToPointerTarget(pair.second, event);
|
| - }
|
| - pointer_targets_.clear();
|
| - }
|
| -
|
| - // Set the capture before changing native capture; otherwise, the callback
|
| - // from native platform might try to set the capture again.
|
| - bool had_capture_window = capture_window_ != nullptr;
|
| - capture_window_ = window;
|
| - capture_window_client_id_ = client_id;
|
| -
|
| - // Begin tracking the capture window if it is not yet being observed.
|
| - if (window) {
|
| - ObserveWindow(window);
|
| - // TODO(sky): this conditional is problematic for the case of capture moving
|
| - // to a different display.
|
| - if (!had_capture_window)
|
| - delegate_->SetNativeCapture(window);
|
| - } else {
|
| - delegate_->ReleaseNativeCapture();
|
| - if (!mouse_button_down_)
|
| - UpdateCursorProviderByLastKnownLocation();
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void EventDispatcher::AddSystemModalWindow(ServerWindow* window) {
|
| - modal_window_controller_.AddSystemModalWindow(window);
|
| -}
|
| -
|
| -void EventDispatcher::ReleaseCaptureBlockedByModalWindow(
|
| - const ServerWindow* modal_window) {
|
| - if (!capture_window_)
|
| - return;
|
| -
|
| - if (modal_window_controller_.IsWindowBlockedBy(capture_window_,
|
| - modal_window)) {
|
| - SetCaptureWindow(nullptr, kInvalidClientId);
|
| - }
|
| -}
|
| -
|
| -void EventDispatcher::ReleaseCaptureBlockedByAnyModalWindow() {
|
| - if (!capture_window_)
|
| - return;
|
| -
|
| - if (modal_window_controller_.IsWindowBlocked(capture_window_))
|
| - SetCaptureWindow(nullptr, kInvalidClientId);
|
| -}
|
| -
|
| -void EventDispatcher::UpdateNonClientAreaForCurrentWindow() {
|
| - if (mouse_cursor_source_window_) {
|
| - gfx::Point location = mouse_pointer_last_location_;
|
| - ServerWindow* target = FindDeepestVisibleWindowForEvents(&location);
|
| - if (target == mouse_cursor_source_window_) {
|
| - mouse_cursor_in_non_client_area_ =
|
| - mouse_cursor_source_window_
|
| - ? IsLocationInNonclientArea(mouse_cursor_source_window_, location)
|
| - : false;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void EventDispatcher::UpdateCursorProviderByLastKnownLocation() {
|
| - if (!mouse_button_down_) {
|
| - gfx::Point location = mouse_pointer_last_location_;
|
| - mouse_cursor_source_window_ = FindDeepestVisibleWindowForEvents(&location);
|
| -
|
| - mouse_cursor_in_non_client_area_ =
|
| - mouse_cursor_source_window_
|
| - ? IsLocationInNonclientArea(mouse_cursor_source_window_, location)
|
| - : false;
|
| - }
|
| -}
|
| -
|
| -bool EventDispatcher::AddAccelerator(uint32_t id,
|
| - mojom::EventMatcherPtr event_matcher) {
|
| - std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher));
|
| - // If an accelerator with the same id or matcher already exists, then abort.
|
| - for (const auto& pair : accelerators_) {
|
| - if (pair.first == id || accelerator->EqualEventMatcher(pair.second.get()))
|
| - return false;
|
| - }
|
| - accelerators_.insert(Entry(id, std::move(accelerator)));
|
| - return true;
|
| -}
|
| -
|
| -void EventDispatcher::RemoveAccelerator(uint32_t id) {
|
| - auto it = accelerators_.find(id);
|
| - // Clients may pass bogus ids.
|
| - if (it != accelerators_.end())
|
| - accelerators_.erase(it);
|
| -}
|
| -
|
| -void EventDispatcher::ProcessEvent(const ui::Event& event) {
|
| - if (event.IsKeyEvent()) {
|
| - const ui::KeyEvent* key_event = event.AsKeyEvent();
|
| - if (event.type() == ui::ET_KEY_PRESSED && !key_event->is_char()) {
|
| - Accelerator* pre_target =
|
| - FindAccelerator(*key_event, ui::mojom::AcceleratorPhase::PRE_TARGET);
|
| - if (pre_target) {
|
| - delegate_->OnAccelerator(pre_target->id(), event);
|
| - return;
|
| - }
|
| - }
|
| - ProcessKeyEvent(*key_event);
|
| - return;
|
| - }
|
| -
|
| - if (event.IsPointerEvent() || event.IsMouseWheelEvent()) {
|
| - ProcessLocatedEvent(*event.AsLocatedEvent());
|
| - return;
|
| - }
|
| -
|
| - NOTREACHED();
|
| -}
|
| -
|
| -void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event) {
|
| - Accelerator* post_target =
|
| - FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET);
|
| - ServerWindow* focused_window =
|
| - delegate_->GetFocusedWindowForEventDispatcher();
|
| - if (focused_window) {
|
| - // Assume key events are for the client area.
|
| - const bool in_nonclient_area = false;
|
| - const ClientSpecificId client_id =
|
| - delegate_->GetEventTargetClientId(focused_window, in_nonclient_area);
|
| - delegate_->DispatchInputEventToWindow(focused_window, client_id, event,
|
| - post_target);
|
| - return;
|
| - }
|
| - delegate_->OnEventTargetNotFound(event);
|
| - if (post_target)
|
| - delegate_->OnAccelerator(post_target->id(), event);
|
| -}
|
| -
|
| -void EventDispatcher::ProcessLocatedEvent(const ui::LocatedEvent& event) {
|
| - DCHECK(event.IsPointerEvent() || event.IsMouseWheelEvent());
|
| - const bool is_mouse_event =
|
| - event.IsMousePointerEvent() || event.IsMouseWheelEvent();
|
| -
|
| - if (is_mouse_event) {
|
| - mouse_pointer_last_location_ = event.location();
|
| - delegate_->OnMouseCursorLocationChanged(event.root_location());
|
| - }
|
| -
|
| - // Release capture on pointer up. For mouse we only release if there are
|
| - // no buttons down.
|
| - const bool is_pointer_going_up =
|
| - (event.type() == ui::ET_POINTER_UP ||
|
| - event.type() == ui::ET_POINTER_CANCELLED) &&
|
| - (!is_mouse_event || IsOnlyOneMouseButtonDown(event.flags()));
|
| -
|
| - // Update mouse down state upon events which change it.
|
| - if (is_mouse_event) {
|
| - if (event.type() == ui::ET_POINTER_DOWN)
|
| - mouse_button_down_ = true;
|
| - else if (is_pointer_going_up)
|
| - mouse_button_down_ = false;
|
| - }
|
| -
|
| - if (capture_window_) {
|
| - mouse_cursor_source_window_ = capture_window_;
|
| - DispatchToClient(capture_window_, capture_window_client_id_, event);
|
| - return;
|
| - }
|
| -
|
| - const int32_t pointer_id = PointerId(event);
|
| - if (!IsTrackingPointer(pointer_id) ||
|
| - !pointer_targets_[pointer_id].is_pointer_down) {
|
| - const bool any_pointers_down = AreAnyPointersDown();
|
| - UpdateTargetForPointer(pointer_id, event);
|
| - if (is_mouse_event)
|
| - mouse_cursor_source_window_ = pointer_targets_[pointer_id].window;
|
| -
|
| - PointerTarget& pointer_target = pointer_targets_[pointer_id];
|
| - if (pointer_target.is_pointer_down) {
|
| - if (is_mouse_event)
|
| - mouse_cursor_source_window_ = pointer_target.window;
|
| - if (!any_pointers_down) {
|
| - delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window);
|
| - delegate_->SetNativeCapture(pointer_target.window);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // When we release the mouse button, we want the cursor to be sourced from
|
| - // the window under the mouse pointer, even though we're sending the button
|
| - // up event to the window that had implicit capture. We have to set this
|
| - // before we perform dispatch because the Delegate is going to read this
|
| - // information from us.
|
| - if (is_pointer_going_up && is_mouse_event)
|
| - UpdateCursorProviderByLastKnownLocation();
|
| -
|
| - DispatchToPointerTarget(pointer_targets_[pointer_id], event);
|
| -
|
| - if (is_pointer_going_up) {
|
| - if (is_mouse_event)
|
| - pointer_targets_[pointer_id].is_pointer_down = false;
|
| - else
|
| - StopTrackingPointer(pointer_id);
|
| - if (!AreAnyPointersDown())
|
| - delegate_->ReleaseNativeCapture();
|
| - }
|
| -}
|
| -
|
| -void EventDispatcher::StartTrackingPointer(
|
| - int32_t pointer_id,
|
| - const PointerTarget& pointer_target) {
|
| - DCHECK(!IsTrackingPointer(pointer_id));
|
| - ObserveWindow(pointer_target.window);
|
| - pointer_targets_[pointer_id] = pointer_target;
|
| -}
|
| -
|
| -void EventDispatcher::StopTrackingPointer(int32_t pointer_id) {
|
| - DCHECK(IsTrackingPointer(pointer_id));
|
| - ServerWindow* window = pointer_targets_[pointer_id].window;
|
| - pointer_targets_.erase(pointer_id);
|
| - if (window)
|
| - UnobserveWindow(window);
|
| -}
|
| -
|
| -void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id,
|
| - const ui::LocatedEvent& event) {
|
| - if (!IsTrackingPointer(pointer_id)) {
|
| - StartTrackingPointer(pointer_id, PointerTargetForEvent(event));
|
| - return;
|
| - }
|
| -
|
| - const PointerTarget pointer_target = PointerTargetForEvent(event);
|
| - if (pointer_target.window == pointer_targets_[pointer_id].window &&
|
| - pointer_target.in_nonclient_area ==
|
| - pointer_targets_[pointer_id].in_nonclient_area) {
|
| - // The targets are the same, only set the down state to true if necessary.
|
| - // Down going to up is handled by ProcessLocatedEvent().
|
| - if (pointer_target.is_pointer_down)
|
| - pointer_targets_[pointer_id].is_pointer_down = true;
|
| - return;
|
| - }
|
| -
|
| - // The targets are changing. Send an exit if appropriate.
|
| - if (event.IsMousePointerEvent()) {
|
| - ui::PointerEvent exit_event(
|
| - ui::ET_POINTER_EXITED, event.location(), event.root_location(),
|
| - event.flags(), ui::PointerEvent::kMousePointerId,
|
| - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE),
|
| - event.time_stamp());
|
| - DispatchToPointerTarget(pointer_targets_[pointer_id], exit_event);
|
| - }
|
| -
|
| - // Technically we're updating in place, but calling start then stop makes for
|
| - // simpler code.
|
| - StopTrackingPointer(pointer_id);
|
| - StartTrackingPointer(pointer_id, pointer_target);
|
| -}
|
| -
|
| -EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent(
|
| - const ui::LocatedEvent& event) {
|
| - PointerTarget pointer_target;
|
| - gfx::Point location(event.location());
|
| - ServerWindow* target_window = FindDeepestVisibleWindowForEvents(&location);
|
| - pointer_target.window =
|
| - modal_window_controller_.GetTargetForWindow(target_window);
|
| - pointer_target.is_mouse_event = event.IsMousePointerEvent();
|
| - pointer_target.in_nonclient_area =
|
| - target_window != pointer_target.window ||
|
| - IsLocationInNonclientArea(pointer_target.window, location);
|
| - pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN;
|
| - return pointer_target;
|
| -}
|
| -
|
| -bool EventDispatcher::AreAnyPointersDown() const {
|
| - for (const auto& pair : pointer_targets_) {
|
| - if (pair.second.is_pointer_down)
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -void EventDispatcher::DispatchToPointerTarget(const PointerTarget& target,
|
| - const ui::LocatedEvent& event) {
|
| - if (!target.window) {
|
| - delegate_->OnEventTargetNotFound(event);
|
| - return;
|
| - }
|
| -
|
| - if (target.is_mouse_event)
|
| - mouse_cursor_in_non_client_area_ = target.in_nonclient_area;
|
| -
|
| - DispatchToClient(target.window, delegate_->GetEventTargetClientId(
|
| - target.window, target.in_nonclient_area),
|
| - event);
|
| -}
|
| -
|
| -void EventDispatcher::DispatchToClient(ServerWindow* window,
|
| - ClientSpecificId client_id,
|
| - const ui::LocatedEvent& event) {
|
| - gfx::Point location(event.location());
|
| - gfx::Transform transform(GetTransformToWindow(window));
|
| - transform.TransformPoint(&location);
|
| - std::unique_ptr<ui::Event> clone = ui::Event::Clone(event);
|
| - clone->AsLocatedEvent()->set_location(location);
|
| - // TODO(jonross): add post-target accelerator support once accelerators
|
| - // support pointer events.
|
| - delegate_->DispatchInputEventToWindow(window, client_id, *clone, nullptr);
|
| -}
|
| -
|
| -void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) {
|
| - if (capture_window_ == window) {
|
| - UnobserveWindow(window);
|
| - capture_window_ = nullptr;
|
| - capture_window_client_id_ = kInvalidClientId;
|
| - mouse_button_down_ = false;
|
| - // A window only cares to be informed that it lost capture if it explicitly
|
| - // requested capture. A window can lose capture if another window gains
|
| - // explicit capture.
|
| - delegate_->OnServerWindowCaptureLost(window);
|
| - delegate_->ReleaseNativeCapture();
|
| - UpdateCursorProviderByLastKnownLocation();
|
| - return;
|
| - }
|
| -
|
| - for (auto& pair : pointer_targets_) {
|
| - if (pair.second.window == window) {
|
| - UnobserveWindow(window);
|
| - pair.second.window = nullptr;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void EventDispatcher::ObserveWindow(ServerWindow* window) {
|
| - auto res = observed_windows_.insert(std::make_pair(window, 0u));
|
| - res.first->second++;
|
| - if (res.second)
|
| - window->AddObserver(this);
|
| -}
|
| -
|
| -void EventDispatcher::UnobserveWindow(ServerWindow* window) {
|
| - auto it = observed_windows_.find(window);
|
| - DCHECK(it != observed_windows_.end());
|
| - DCHECK_LT(0u, it->second);
|
| - it->second--;
|
| - if (!it->second) {
|
| - window->RemoveObserver(this);
|
| - observed_windows_.erase(it);
|
| - }
|
| -}
|
| -
|
| -Accelerator* EventDispatcher::FindAccelerator(
|
| - const ui::KeyEvent& event,
|
| - const ui::mojom::AcceleratorPhase phase) {
|
| - for (const auto& pair : accelerators_) {
|
| - if (pair.second->MatchesEvent(event, phase)) {
|
| - return pair.second.get();
|
| - }
|
| - }
|
| - return nullptr;
|
| -}
|
| -
|
| -ServerWindow* EventDispatcher::FindDeepestVisibleWindowForEvents(
|
| - gfx::Point* location) {
|
| - ServerWindow* root = delegate_->GetRootWindowContaining(*location);
|
| - if (!root)
|
| - return nullptr;
|
| -
|
| - return mus::ws::FindDeepestVisibleWindowForEvents(root, location);
|
| -}
|
| -
|
| -void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window,
|
| - ServerWindow* new_parent,
|
| - ServerWindow* old_parent) {
|
| - // TODO(sky): moving to a different root likely needs to transfer capture.
|
| - // TODO(sky): this isn't quite right, I think the logic should be (assuming
|
| - // moving in same root and still drawn):
|
| - // . if there is capture and window is still in the same root, continue
|
| - // sending to it.
|
| - // . if there isn't capture, then reevaluate each of the pointer targets
|
| - // sending exit as necessary.
|
| - // http://crbug.com/613646 .
|
| - if (!new_parent || !new_parent->IsDrawn() ||
|
| - new_parent->GetRoot() != old_parent->GetRoot()) {
|
| - CancelPointerEventsToTarget(window);
|
| - }
|
| -}
|
| -
|
| -void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) {
|
| - CancelPointerEventsToTarget(window);
|
| -}
|
| -
|
| -void EventDispatcher::OnWindowDestroyed(ServerWindow* window) {
|
| - CancelPointerEventsToTarget(window);
|
| -
|
| - if (mouse_cursor_source_window_ == window)
|
| - mouse_cursor_source_window_ = nullptr;
|
| -}
|
| -
|
| -} // namespace ws
|
| -} // namespace mus
|
|
|