// Copyright 2016 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 "content/browser/renderer_host/render_widget_host_view_event_handler.h"

#include "base/command_line.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "components/viz/common/features.h"
#include "content/browser/renderer_host/hit_test_debug_key_event_observer.h"
#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_switches_internal.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/common/content_features.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/scoped_keyboard_hook.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/web_input_event.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/touch_selection/touch_selection_controller.h"

#if defined(OS_WIN)
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/common/context_menu_params.h"
#include "ui/aura/window_tree_host.h"
#include "ui/display/screen.h"
#endif  // defined(OS_WIN)

namespace {

// In mouse lock mode, we need to prevent the (invisible) cursor from hitting
// the border of the view, in order to get valid movement information. However,
// forcing the cursor back to the center of the view after each mouse move
// doesn't work well. It reduces the frequency of useful mouse move messages
// significantly. Therefore, we move the cursor to the center of the view only
// if it approaches the border. |kMouseLockBorderPercentage| specifies the width
// of the border area, in percentage of the corresponding dimension.
const int kMouseLockBorderPercentage = 15;

#if defined(OS_WIN)
// A callback function for EnumThreadWindows to enumerate and dismiss
// any owned popup windows.
BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
  const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);

  if (::IsWindowVisible(window)) {
    const HWND owner = ::GetWindow(window, GW_OWNER);
    if (toplevel_hwnd == owner) {
      ::PostMessageW(window, WM_CANCELMODE, 0, 0);
    }
  }

  return TRUE;
}
#endif  // defined(OS_WIN)

bool IsFractionalScaleFactor(float scale_factor) {
  return (scale_factor - static_cast<int>(scale_factor)) > 0;
}

// We don't mark these as handled so that they're sent back to the
// DefWindowProc so it can generate WM_APPCOMMAND as necessary.
bool ShouldGenerateAppCommand(const ui::MouseEvent* event) {
#if defined(OS_WIN)
  switch (event->native_event().message) {
    case WM_XBUTTONUP:
      return !base::FeatureList::IsEnabled(features::kExtendedMouseButtons);
    case WM_NCXBUTTONUP:
      return true;
  }
#endif
  return false;
}

// Reset unchanged touch points to StateStationary for touchmove and
// touchcancel.
void MarkUnchangedTouchPointsAsStationary(blink::WebTouchEvent* event,
                                          int changed_touch_id) {
  if (event->GetType() == blink::WebInputEvent::kTouchMove ||
      event->GetType() == blink::WebInputEvent::kTouchCancel) {
    for (size_t i = 0; i < event->touches_length; ++i) {
      if (event->touches[i].id != changed_touch_id)
        event->touches[i].state = blink::WebTouchPoint::kStateStationary;
    }
  }
}

bool NeedsInputGrab(content::RenderWidgetHostViewBase* view) {
  if (!view)
    return false;
  return view->GetWidgetType() == content::WidgetType::kPopup;
}

}  // namespace

namespace content {

RenderWidgetHostViewEventHandler::Delegate::Delegate()
    : selection_controller_client_(nullptr),
      selection_controller_(nullptr),
      overscroll_controller_(nullptr) {}

RenderWidgetHostViewEventHandler::Delegate::~Delegate() {}

RenderWidgetHostViewEventHandler::RenderWidgetHostViewEventHandler(
    RenderWidgetHostImpl* host,
    RenderWidgetHostViewBase* host_view,
    Delegate* delegate)
    : accept_return_character_(false),
      disable_input_event_router_for_testing_(false),
      mouse_locked_(false),
      pinch_zoom_enabled_(content::IsPinchToZoomEnabled()),
      set_focus_on_mouse_down_or_key_event_(false),
      synthetic_move_sent_(false),
      host_(host),
      host_view_(host_view),
      popup_child_host_view_(nullptr),
      popup_child_event_handler_(nullptr),
      delegate_(delegate),
      window_(nullptr),
      mouse_wheel_phase_handler_(host_view),
      debug_observer_(features::IsVizHitTestingDebugEnabled()
                          ? std::make_unique<HitTestDebugKeyEventObserver>(host)
                          : nullptr) {}

RenderWidgetHostViewEventHandler::~RenderWidgetHostViewEventHandler() {}

void RenderWidgetHostViewEventHandler::SetPopupChild(
    RenderWidgetHostViewBase* popup_child_host_view,
    ui::EventHandler* popup_child_event_handler) {
  popup_child_host_view_ = popup_child_host_view;
  popup_child_event_handler_ = popup_child_event_handler;
}

void RenderWidgetHostViewEventHandler::TrackHost(
    aura::Window* reference_window) {
  if (!reference_window)
    return;
  DCHECK(!host_tracker_);
  host_tracker_.reset(new aura::WindowTracker);
  host_tracker_->Add(reference_window);
}

#if defined(OS_WIN)
void RenderWidgetHostViewEventHandler::UpdateMouseLockRegion() {
  RECT window_rect =
      display::Screen::GetScreen()
          ->DIPToScreenRectInWindow(window_, window_->GetBoundsInScreen())
          .ToRECT();
  ::ClipCursor(&window_rect);
}
#endif

bool RenderWidgetHostViewEventHandler::LockMouse() {
  aura::Window* root_window = window_->GetRootWindow();
  if (!root_window)
    return false;

  if (mouse_locked_)
    return true;

  mouse_locked_ = true;
#if !defined(OS_WIN)
  window_->SetCapture();
#else
  UpdateMouseLockRegion();
#endif
  aura::client::CursorClient* cursor_client =
      aura::client::GetCursorClient(root_window);
  if (cursor_client) {
    cursor_client->HideCursor();
    cursor_client->LockCursor();
  }

  if (ShouldMoveToCenter()) {
    MoveCursorToCenter();
  }
  delegate_->SetTooltipsEnabled(false);
  return true;
}

void RenderWidgetHostViewEventHandler::UnlockMouse() {
  delegate_->SetTooltipsEnabled(true);

  aura::Window* root_window = window_->GetRootWindow();
  if (!mouse_locked_ || !root_window)
    return;

  mouse_locked_ = false;

  if (window_->HasCapture())
    window_->ReleaseCapture();

#if defined(OS_WIN)
  ::ClipCursor(NULL);
#endif

  // Ensure that the global mouse position is updated here to its original
  // value. If we don't do this then the synthesized mouse move which is posted
  // after the cursor is moved ends up getting a large movement delta which is
  // not what sites expect. The delta is computed in the
  // ModifyEventMovementAndCoords function.
  global_mouse_position_ = unlocked_global_mouse_position_;
  window_->MoveCursorTo(gfx::ToFlooredPoint(unlocked_mouse_position_));

  aura::client::CursorClient* cursor_client =
      aura::client::GetCursorClient(root_window);
  if (cursor_client) {
    cursor_client->UnlockCursor();
    cursor_client->ShowCursor();
  }
  host_->LostMouseLock();
}

bool RenderWidgetHostViewEventHandler::LockKeyboard(
    base::Optional<base::flat_set<ui::DomCode>> codes) {
  aura::Window* root_window = window_->GetRootWindow();
  if (!root_window)
    return false;

  // Remove existing hook, if registered.
  UnlockKeyboard();
  scoped_keyboard_hook_ = root_window->CaptureSystemKeyEvents(std::move(codes));

  return IsKeyboardLocked();
}

void RenderWidgetHostViewEventHandler::UnlockKeyboard() {
  scoped_keyboard_hook_.reset();
}

bool RenderWidgetHostViewEventHandler::IsKeyboardLocked() const {
  return scoped_keyboard_hook_ != nullptr;
}

void RenderWidgetHostViewEventHandler::OnKeyEvent(ui::KeyEvent* event) {
  TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnKeyEvent");

  if (NeedsInputGrab(popup_child_host_view_)) {
    popup_child_event_handler_->OnKeyEvent(event);
    if (event->handled())
      return;
  }

  bool mark_event_as_handled = true;
  // We need to handle the Escape key for Pepper Flash.
  if (host_view_->is_fullscreen() && event->key_code() == ui::VKEY_ESCAPE) {
    // Focus the window we were created from.
    if (host_tracker_.get() && !host_tracker_->windows().empty()) {
      aura::Window* host = *(host_tracker_->windows().begin());
      aura::client::FocusClient* client = aura::client::GetFocusClient(host);
      if (client) {
        // Calling host->Focus() may delete |this|. We create a local observer
        // for that. In that case we exit without further access to any members.
        auto local_tracker = std::move(host_tracker_);
        local_tracker->Add(window_);
        host->Focus();
        if (!local_tracker->Contains(window_)) {
          event->SetHandled();
          return;
        }
      }
    }
    delegate_->Shutdown();
    host_tracker_.reset();
  } else {
    if (event->key_code() == ui::VKEY_RETURN) {
      // Do not forward return key release events if no press event was handled.
      if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
        return;
      // Accept return key character events between press and release events.
      accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
    }

    // Call SetKeyboardFocus() for not only ET_KEY_PRESSED but also
    // ET_KEY_RELEASED. If a user closed the hotdog menu with ESC key press,
    // we need to notify focus to Blink on ET_KEY_RELEASED for ESC key.
    SetKeyboardFocus();
    // We don't have to communicate with an input method here.
    NativeWebKeyboardEvent webkit_event(*event);

    // If the key has been reserved as part of the active KeyboardLock request,
    // then we want to mark it as such so it is not intercepted by the browser.
    if (IsKeyLocked(*event))
      webkit_event.skip_in_browser = true;

    delegate_->ForwardKeyboardEventWithLatencyInfo(
        webkit_event, *event->latency(), event, &mark_event_as_handled);
  }
  if (mark_event_as_handled)
    event->SetHandled();
}

void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) {
  TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnMouseEvent");

  // CrOS will send a mouse exit event to update hover state when mouse is
  // hidden which we want to filter out in renderer. crbug.com/723535.
  if (event->flags() & ui::EF_CURSOR_HIDE)
    return;

  ForwardMouseEventToParent(event);
  // TODO(mgiuca): Return if event->handled() returns true. This currently
  // breaks drop-down lists which means something is incorrectly setting
  // event->handled to true (http://crbug.com/577983).

  if (mouse_locked_) {
    HandleMouseEventWhileLocked(event);
    return;
  }

  // As the overscroll is handled during scroll events from the trackpad, the
  // RWHVA window is transformed by the overscroll controller. This transform
  // triggers a synthetic mouse-move event to be generated (by the aura
  // RootWindow). Also, with a touchscreen, we may get a synthetic mouse-move
  // caused by a pointer grab. But these events interfere with the overscroll
  // gesture. So, ignore such synthetic mouse-move events if an overscroll
  // gesture is in progress.
  OverscrollController* overscroll_controller =
      delegate_->overscroll_controller();
  if (overscroll_controller &&
      overscroll_controller->overscroll_mode() != OVERSCROLL_NONE &&
      event->flags() & ui::EF_IS_SYNTHESIZED &&
      (event->type() == ui::ET_MOUSE_ENTERED ||
       event->type() == ui::ET_MOUSE_EXITED ||
       event->type() == ui::ET_MOUSE_MOVED)) {
    event->StopPropagation();
    return;
  }

  if (event->type() == ui::ET_MOUSEWHEEL) {
#if defined(OS_WIN)
    // We get mouse wheel/scroll messages even if we are not in the foreground.
    // So here we check if we have any owned popup windows in the foreground and
    // dismiss them.
    aura::WindowTreeHost* host = window_->GetHost();
    if (host) {
      HWND parent = host->GetAcceleratedWidget();
      HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
      EnumThreadWindows(GetCurrentThreadId(), DismissOwnedPopups,
                        reinterpret_cast<LPARAM>(toplevel_hwnd));
    }
#endif
    blink::WebMouseWheelEvent mouse_wheel_event =
        ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent());

    if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
      bool should_route_event = ShouldRouteEvent(event);
      // End the touchpad scrolling sequence (if such exists) before handling
      // a ui::ET_MOUSEWHEEL event.
      mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded();

      mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
          mouse_wheel_event, should_route_event);
      if (should_route_event) {
        host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
            host_view_, &mouse_wheel_event, *event->latency());
      } else {
        ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
      }
    }
  } else {
    bool is_selection_popup = NeedsInputGrab(popup_child_host_view_);
    if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
        !(event->flags() & ui::EF_FROM_TOUCH)) {
      // Confirm existing composition text on mouse press, to make sure
      // the input caret won't be moved with an ongoing composition text.
      if (event->type() == ui::ET_MOUSE_PRESSED)
        FinishImeCompositionSession();

      blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(*event);
      ModifyEventMovementAndCoords(*event, &mouse_event);
      if (ShouldRouteEvent(event)) {
        host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
            host_view_, &mouse_event, *event->latency());
      } else {
        ProcessMouseEvent(mouse_event, *event->latency());
      }

      // Ensure that we get keyboard focus on mouse down as a plugin window may
      // have grabbed keyboard focus.
      if (event->type() == ui::ET_MOUSE_PRESSED)
        SetKeyboardFocus();
    }
  }

  switch (event->type()) {
    case ui::ET_MOUSE_PRESSED:
      window_->SetCapture();
      break;
    case ui::ET_MOUSE_RELEASED:
      if (!delegate_->NeedsMouseCapture())
        window_->ReleaseCapture();
      break;
    default:
      break;
  }

  if (!ShouldGenerateAppCommand(event))
    event->SetHandled();
}

void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) {
  TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnScrollEvent");
  bool should_route_event = ShouldRouteEvent(event);
  if (event->type() == ui::ET_SCROLL) {
#if !defined(OS_WIN)
    // TODO(ananta)
    // Investigate if this is true for Windows 8 Metro ASH as well.
    if (event->finger_count() != 2)
      return;
#endif
    blink::WebMouseWheelEvent mouse_wheel_event =
        ui::MakeWebMouseWheelEvent(*event);
    mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
        mouse_wheel_event, should_route_event);

    base::Optional<blink::WebGestureEvent> maybe_synthetic_fling_cancel;
    if (mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseBegan) {
      maybe_synthetic_fling_cancel =
          ui::MakeWebGestureEventFlingCancel(mouse_wheel_event);
    }

    if (should_route_event) {
      if (maybe_synthetic_fling_cancel) {
        host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
            host_view_, &*maybe_synthetic_fling_cancel,
            ui::LatencyInfo(ui::SourceEventType::WHEEL));
      }
      host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
          host_view_, &mouse_wheel_event, *event->latency());
    } else {
      if (maybe_synthetic_fling_cancel) {
        host_->ForwardGestureEvent(*maybe_synthetic_fling_cancel);
      }
      host_->ForwardWheelEventWithLatencyInfo(mouse_wheel_event,
                                              *event->latency());
    }
  } else if (event->type() == ui::ET_SCROLL_FLING_START ||
             event->type() == ui::ET_SCROLL_FLING_CANCEL) {
    blink::WebGestureEvent gesture_event = ui::MakeWebGestureEvent(*event);
    if (should_route_event) {
      host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
          host_view_, &gesture_event,
          ui::LatencyInfo(ui::SourceEventType::WHEEL));
    } else {
      host_->ForwardGestureEvent(gesture_event);
    }
    if (event->type() == ui::ET_SCROLL_FLING_START) {
      RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
      // The user has lifted their fingers.
      mouse_wheel_phase_handler_.ResetTouchpadScrollSequence();
    } else if (event->type() == ui::ET_SCROLL_FLING_CANCEL) {
      // The user has put their fingers down.
      DCHECK_EQ(blink::kWebGestureDeviceTouchpad, gesture_event.SourceDevice());
      mouse_wheel_phase_handler_.TouchpadScrollingMayBegin();
    }
  }

  event->SetHandled();
}

void RenderWidgetHostViewEventHandler::OnTouchEvent(ui::TouchEvent* event) {
  TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnTouchEvent");

  bool had_no_pointer = !pointer_state_.GetPointerCount();

  // Update the touch event first.
  if (!pointer_state_.OnTouch(*event)) {
    event->StopPropagation();
    return;
  }

  blink::WebTouchEvent touch_event;
  bool handled =
      delegate_->selection_controller()->WillHandleTouchEvent(pointer_state_);
  if (handled) {
    event->SetHandled();
  } else {
    touch_event = ui::CreateWebTouchEventFromMotionEvent(
        pointer_state_, event->may_cause_scrolling(), event->hovering());
  }
  pointer_state_.CleanupRemovedTouchPoints(*event);

  if (handled)
    return;

  if (had_no_pointer)
    delegate_->selection_controller_client()->OnTouchDown();
  if (!pointer_state_.GetPointerCount())
    delegate_->selection_controller_client()->OnTouchUp();

  // It is important to always mark events as being handled asynchronously when
  // they are forwarded. This ensures that the current event does not get
  // processed by the gesture recognizer before events currently awaiting
  // dispatch in the touch queue.
  event->DisableSynchronousHandling();

  // Set unchanged touch point to StateStationary for touchmove and
  // touchcancel to make sure only send one ack per WebTouchEvent.
  MarkUnchangedTouchPointsAsStationary(&touch_event,
                                       event->pointer_details().id);
  if (ShouldRouteEvent(event)) {
    host_->delegate()->GetInputEventRouter()->RouteTouchEvent(
        host_view_, &touch_event, *event->latency());
  } else {
    ProcessTouchEvent(touch_event, *event->latency());
  }
}

void RenderWidgetHostViewEventHandler::OnGestureEvent(ui::GestureEvent* event) {
  TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnGestureEvent");

  if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
       event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
       event->type() == ui::ET_GESTURE_PINCH_END) &&
      !pinch_zoom_enabled_) {
    event->SetHandled();
    return;
  }

  HandleGestureForTouchSelection(event);
  if (event->handled())
    return;

  // Confirm existing composition text on TAP gesture, to make sure the input
  // caret won't be moved with an ongoing composition text.
  if (event->type() == ui::ET_GESTURE_TAP)
    FinishImeCompositionSession();

  blink::WebGestureEvent gesture = ui::MakeWebGestureEvent(*event);
  if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
    // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
    // event to stop any in-progress flings.
    blink::WebGestureEvent fling_cancel = gesture;
    fling_cancel.SetType(blink::WebInputEvent::kGestureFlingCancel);
    fling_cancel.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
    if (ShouldRouteEvent(event)) {
      host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
          host_view_, &fling_cancel,
          ui::LatencyInfo(ui::SourceEventType::TOUCH));
    } else {
      host_->ForwardGestureEvent(fling_cancel);
    }
  }

  if (gesture.GetType() != blink::WebInputEvent::kUndefined) {
    if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
      // If there is a current scroll going on and a new scroll that isn't
      // wheel based send a synthetic wheel event with kPhaseEnded to cancel
      // the current scroll.
      mouse_wheel_phase_handler_.DispatchPendingWheelEndEvent();
      mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded();
    } else if (event->type() == ui::ET_SCROLL_FLING_START) {
      RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
    }

    if (event->type() == ui::ET_GESTURE_SCROLL_END ||
        event->type() == ui::ET_SCROLL_FLING_START) {
      // Scrolling with touchscreen has finished. Make sure that the next wheel
      // event will have phase = |kPhaseBegan|. This is for maintaining the
      // correct phase info when some of the wheel events get ignored while a
      // touchscreen scroll is going on.
      mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
      mouse_wheel_phase_handler_.ResetTouchpadScrollSequence();
    }

    if (ShouldRouteEvent(event)) {
      host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
          host_view_, &gesture, *event->latency());
    } else {
      host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
    }
  }

  // If a gesture is not processed by the webpage, then WebKit processes it
  // (e.g. generates synthetic mouse events).
  event->SetHandled();
}

void RenderWidgetHostViewEventHandler::GestureEventAck(
    const blink::WebGestureEvent& event,
    InputEventAckState ack_result) {
  mouse_wheel_phase_handler_.GestureEventAck(event, ack_result);
}

bool RenderWidgetHostViewEventHandler::CanRendererHandleEvent(
    const ui::MouseEvent* event,
    bool mouse_locked,
    bool selection_popup) const {
  if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
    return false;

  if (event->type() == ui::ET_MOUSE_EXITED) {
    if (mouse_locked || selection_popup)
      return false;
#if defined(OS_WIN) || defined(OS_LINUX)
    // Don't forward the mouse leave message which is received when the context
    // menu is displayed by the page. This confuses the page and causes state
    // changes.
    if (host_->delegate() && host_->delegate()->IsShowingContextMenuOnPage())
      return false;
#endif
    return true;
  }

#if defined(OS_WIN)
  // Renderer cannot handle WM_XBUTTON or NC events.
  switch (event->native_event().message) {
    case WM_XBUTTONDOWN:
    case WM_XBUTTONUP:
    case WM_XBUTTONDBLCLK:
      return base::FeatureList::IsEnabled(features::kExtendedMouseButtons);
    case WM_NCMOUSELEAVE:
    case WM_NCMOUSEMOVE:
    case WM_NCLBUTTONDOWN:
    case WM_NCLBUTTONUP:
    case WM_NCLBUTTONDBLCLK:
    case WM_NCRBUTTONDOWN:
    case WM_NCRBUTTONUP:
    case WM_NCRBUTTONDBLCLK:
    case WM_NCMBUTTONDOWN:
    case WM_NCMBUTTONUP:
    case WM_NCMBUTTONDBLCLK:
    case WM_NCXBUTTONDOWN:
    case WM_NCXBUTTONUP:
    case WM_NCXBUTTONDBLCLK:
      return false;
    default:
      break;
  }
#elif defined(USE_X11)
  if (!base::FeatureList::IsEnabled(features::kExtendedMouseButtons)) {
    // Renderer only supports standard mouse buttons, so ignore programmable
    // buttons.
    switch (event->type()) {
      case ui::ET_MOUSE_PRESSED:
      case ui::ET_MOUSE_RELEASED: {
        const int kAllowedButtons = ui::EF_LEFT_MOUSE_BUTTON |
                                    ui::EF_MIDDLE_MOUSE_BUTTON |
                                    ui::EF_RIGHT_MOUSE_BUTTON;
        return (event->flags() & kAllowedButtons) != 0;
      }
      default:
        break;
    }
  }
#endif
  return true;
}

void RenderWidgetHostViewEventHandler::FinishImeCompositionSession() {
  // RenderWidgetHostViewAura keeps track of existing composition texts. The
  // call to finish composition text should be made through the RWHVA itself
  // otherwise the following call to cancel composition will lead to an extra
  // IPC for finishing the ongoing composition (see https://crbug.com/723024).
  host_view_->GetTextInputClient()->ConfirmCompositionText();
  host_view_->ImeCancelComposition();
}

void RenderWidgetHostViewEventHandler::ForwardMouseEventToParent(
    ui::MouseEvent* event) {
  // Needed to propagate mouse event to |window_->parent()->delegate()|, but
  // note that it might be something other than a WebContentsViewAura instance.
  // TODO(pkotwicz): Find a better way of doing this.
  // In fullscreen mode which is typically used by flash, don't forward
  // the mouse events to the parent. The renderer and the plugin process
  // handle these events.
  if (host_view_->is_fullscreen())
    return;

  if (event->flags() & ui::EF_FROM_TOUCH)
    return;

  if (!window_->parent() || !window_->parent()->delegate())
    return;

  // Take a copy of |event|, to avoid ConvertLocationToTarget mutating the
  // event.
  std::unique_ptr<ui::Event> event_copy = ui::Event::Clone(*event);
  ui::MouseEvent* mouse_event = static_cast<ui::MouseEvent*>(event_copy.get());
  mouse_event->ConvertLocationToTarget(window_, window_->parent());
  window_->parent()->delegate()->OnMouseEvent(mouse_event);
  if (mouse_event->handled())
    event->SetHandled();
}

void RenderWidgetHostViewEventHandler::HandleGestureForTouchSelection(
    ui::GestureEvent* event) {
  switch (event->type()) {
    case ui::ET_GESTURE_LONG_PRESS:
      delegate_->selection_controller()->HandleLongPressEvent(
          event->time_stamp(), event->location_f());
      break;
    case ui::ET_GESTURE_TAP:
      delegate_->selection_controller()->HandleTapEvent(
          event->location_f(), event->details().tap_count());
      break;
    case ui::ET_GESTURE_SCROLL_BEGIN:
      delegate_->selection_controller_client()->OnScrollStarted();
      break;
    case ui::ET_GESTURE_SCROLL_END:
      delegate_->selection_controller_client()->OnScrollCompleted();
      break;
    default:
      break;
  }
}

void RenderWidgetHostViewEventHandler::HandleMouseEventWhileLocked(
    ui::MouseEvent* event) {
  aura::client::CursorClient* cursor_client =
      aura::client::GetCursorClient(window_->GetRootWindow());

  DCHECK(!cursor_client || !cursor_client->IsCursorVisible());

  if (event->type() == ui::ET_MOUSEWHEEL) {
    blink::WebMouseWheelEvent mouse_wheel_event =
        ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent());
    if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
      if (ShouldRouteEvent(event)) {
        host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
            host_view_, &mouse_wheel_event, *event->latency());
      } else {
        ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
      }
    }
  } else {
    gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());

    // If we receive non client mouse messages while we are in the locked state
    // it probably means that the mouse left the borders of our window and
    // needs to be moved back to the center.
    if (event->flags() & ui::EF_IS_NON_CLIENT) {
      // TODO(jonross): ideally this would not be done for mus
      // (crbug.com/621412)
      MoveCursorToCenter();
      return;
    }

    blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(*event);

    bool is_move_to_center_event =
        (event->type() == ui::ET_MOUSE_MOVED ||
         event->type() == ui::ET_MOUSE_DRAGGED) &&
        mouse_event.PositionInWidget().x == center.x() &&
        mouse_event.PositionInWidget().y == center.y();

    // For fractional scale factors, the conversion from pixels to dip and
    // vice versa could result in off by 1 or 2 errors which hurts us because
    // we want to avoid sending the artificial move to center event to the
    // renderer. Sending the move to center to the renderer cause the cursor
    // to bounce around the center of the screen leading to the lock operation
    // not working correctly.
    // Workaround is to treat a mouse move or drag event off by at most 2 px
    // from the center as a move to center event.
    if (synthetic_move_sent_ &&
        IsFractionalScaleFactor(host_view_->current_device_scale_factor())) {
      if (event->type() == ui::ET_MOUSE_MOVED ||
          event->type() == ui::ET_MOUSE_DRAGGED) {
        if ((std::abs(mouse_event.PositionInWidget().x - center.x()) <= 2) &&
            (std::abs(mouse_event.PositionInWidget().y - center.y()) <= 2)) {
          is_move_to_center_event = true;
        }
      }
    }

    ModifyEventMovementAndCoords(*event, &mouse_event);

    bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
    if (should_not_forward) {
      synthetic_move_sent_ = false;
    } else {
      // Check if the mouse has reached the border and needs to be centered.
      if (ShouldMoveToCenter())
        MoveCursorToCenter();
      bool is_selection_popup = NeedsInputGrab(popup_child_host_view_);
      // Forward event to renderer.
      if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
          !(event->flags() & ui::EF_FROM_TOUCH)) {
        if (ShouldRouteEvent(event)) {
          host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
              host_view_, &mouse_event, *event->latency());
        } else {
          ProcessMouseEvent(mouse_event, *event->latency());
        }
        // Ensure that we get keyboard focus on mouse down as a plugin window
        // may have grabbed keyboard focus.
        if (event->type() == ui::ET_MOUSE_PRESSED)
          SetKeyboardFocus();
      }
    }
  }
  if (!ShouldGenerateAppCommand(event))
    event->SetHandled();
}

void RenderWidgetHostViewEventHandler::ModifyEventMovementAndCoords(
    const ui::MouseEvent& ui_mouse_event,
    blink::WebMouseEvent* event) {
  // If the mouse has just entered, we must report zero movementX/Y. Hence we
  // reset any global_mouse_position set previously.
  if (ui_mouse_event.type() == ui::ET_MOUSE_ENTERED ||
      ui_mouse_event.type() == ui::ET_MOUSE_EXITED) {
    global_mouse_position_.SetPoint(event->PositionInScreen().x,
                                    event->PositionInScreen().y);
  }

  // Movement is computed by taking the difference of the new cursor position
  // and the previous. Under mouse lock the cursor will be warped back to the
  // center so that we are not limited by clipping boundaries.
  // We do not measure movement as the delta from cursor to center because
  // we may receive more mouse movement events before our warp has taken
  // effect.
  // TODO(crbug.com/802067): We store event coordinates as pointF but
  // movement_x/y are integer. In order not to lose fractional part, we need
  // to keep the movement calculation as "floor(cur_pos) - floor(last_pos)".
  // Remove the floor here when movement_x/y is changed to double.
  event->movement_x = gfx::ToFlooredInt(event->PositionInScreen().x) -
                      gfx::ToFlooredInt(global_mouse_position_.x());
  event->movement_y = gfx::ToFlooredInt(event->PositionInScreen().y) -
                      gfx::ToFlooredInt(global_mouse_position_.y());

  global_mouse_position_.SetPoint(event->PositionInScreen().x,
                                  event->PositionInScreen().y);

  // Under mouse lock, coordinates of mouse are locked to what they were when
  // mouse lock was entered.
  if (mouse_locked_) {
    event->SetPositionInWidget(unlocked_mouse_position_.x(),
                               unlocked_mouse_position_.y());
    event->SetPositionInScreen(unlocked_global_mouse_position_.x(),
                               unlocked_global_mouse_position_.y());
  } else {
    unlocked_mouse_position_.SetPoint(event->PositionInWidget().x,
                                      event->PositionInWidget().y);
    unlocked_global_mouse_position_.SetPoint(event->PositionInScreen().x,
                                             event->PositionInScreen().y);
  }
}

void RenderWidgetHostViewEventHandler::MoveCursorToCenter() {
#if defined(OS_WIN)
  // TODO(crbug.com/781182): Set the global position when move cursor to center.
  // This is a workaround for a bug from Windows update 16299, and should be remove
  // once the bug is fixed in OS.
  gfx::PointF center_in_screen(window_->GetBoundsInScreen().CenterPoint());
  global_mouse_position_ = center_in_screen;
#else
  synthetic_move_sent_ = true;
#endif

  gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
  window_->MoveCursorTo(center);
}

void RenderWidgetHostViewEventHandler::SetKeyboardFocus() {
#if defined(OS_WIN)
  if (window_ && window_->delegate()->CanFocus()) {
    aura::WindowTreeHost* host = window_->GetHost();
    if (host) {
      gfx::AcceleratedWidget hwnd = host->GetAcceleratedWidget();
      if (!(::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE))
        ::SetFocus(hwnd);
    }
  }
#endif
  // TODO(wjmaclean): can host_ ever be null?
  if (host_ && set_focus_on_mouse_down_or_key_event_) {
    set_focus_on_mouse_down_or_key_event_ = false;
    host_->Focus();
  }
}

bool RenderWidgetHostViewEventHandler::ShouldMoveToCenter() {
  gfx::Rect rect = window_->bounds();
  rect = delegate_->ConvertRectToScreen(rect);
  float border_x = rect.width() * kMouseLockBorderPercentage / 100.0;
  float border_y = rect.height() * kMouseLockBorderPercentage / 100.0;

  return global_mouse_position_.x() < rect.x() + border_x ||
         global_mouse_position_.x() > rect.right() - border_x ||
         global_mouse_position_.y() < rect.y() + border_y ||
         global_mouse_position_.y() > rect.bottom() - border_y;
}

bool RenderWidgetHostViewEventHandler::ShouldRouteEvent(
    const ui::Event* event) const {
  // We should route an event in two cases:
  // 1) Mouse events are routed only if cross-process frames are possible.
  // 2) Touch events are always routed. In the absence of a BrowserPlugin
  //    we expect the routing to always send the event to this view. If
  //    one or more BrowserPlugins are present, then the event may be targeted
  //    to one of them, or this view. This allows GuestViews to have access to
  //    them while still forcing pinch-zoom to be handled by the top-level
  //    frame. TODO(wjmaclean): At present, this doesn't work for OOPIF, but
  //    it should be a simple extension to modify RenderWidgetHostViewChildFrame
  //    in a similar manner to RenderWidgetHostViewGuest.
  bool result = host_->delegate() && host_->delegate()->GetInputEventRouter() &&
                !disable_input_event_router_for_testing_;

  // Do not route events that are currently targeted to page popups such as
  // <select> element drop-downs, since these cannot contain cross-process
  // frames.
  if (host_->delegate() && !host_->delegate()->IsWidgetForMainFrame(host_))
    return false;

  return result;
}

void RenderWidgetHostViewEventHandler::ProcessMouseEvent(
    const blink::WebMouseEvent& event,
    const ui::LatencyInfo& latency) {
  host_->ForwardMouseEventWithLatencyInfo(event, latency);
}

void RenderWidgetHostViewEventHandler::ProcessMouseWheelEvent(
    const blink::WebMouseWheelEvent& event,
    const ui::LatencyInfo& latency) {
  host_->ForwardWheelEventWithLatencyInfo(event, latency);
}

void RenderWidgetHostViewEventHandler::ProcessTouchEvent(
    const blink::WebTouchEvent& event,
    const ui::LatencyInfo& latency) {
  host_->ForwardTouchEventWithLatencyInfo(event, latency);
}

bool RenderWidgetHostViewEventHandler::IsKeyLocked(const ui::KeyEvent& event) {
  // Note: We never consider 'ESC' to be locked as we don't want to prevent it
  // from being handled by the browser.  Doing so would have adverse effects
  // such as the user being unable to exit fullscreen mode.
  if (!IsKeyboardLocked() || event.code() == ui::DomCode::ESCAPE)
    return false;

  return scoped_keyboard_hook_->IsKeyLocked(event.code());
}

}  // namespace content
