Commit dd3c80b4 authored by Ella Ge's avatar Ella Ge Committed by Commit Bot

Use WM_INPUT when pointerlock request unadjusted movement

This CL adds support for pointerlock unadjusted movement on Windows
behind flag. The api is added at crrev.com/c/1764943 behind flag.
(design doc:
https://docs.google.com/document/d/1vvnthXjzfZXiAx7ih-mVhGc_YJ8-_rtlAhIn8i6_6nM/)

When entering pointer lock, if is requesting unadjusted movement, use
|RegisterRawInputDevices| to listen to WM_INPUT messages, and set the
|use_wm_input_| to true. When unlock, remove mouse as raw input device
are reset the bit.

When |use_wm_input_| is true(in lock and unadjusted movement mode),
convert WM_INPUT messages into ET_MOUSE_MOVED events as they are
representing mouse movements.
The move/drag events from WM_MOUSE are suppressed.

Since WM_INPUT messages do not have coordinates, use current mouse
positions as the event coordinates so that there is no jump when
switching between normal events and raw movement events.

This CL adds a field movement_ in ui::MouseEvent to store the raw mouse
movement info from the mouse raw input event. This field only valid if
the event has EF_RAW_MOVEMENT flag set.




Bug: 982379
Change-Id: Ia6e5969717917bbefc0579b5ed587a68df4b26ce
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1769518
Commit-Queue: Ella Ge <eirage@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarNavid Zolghadr <nzolghadr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699577}
parent b52dc379
...@@ -45,6 +45,13 @@ class MockPointerLockWebContentsDelegate : public WebContentsDelegate { ...@@ -45,6 +45,13 @@ class MockPointerLockWebContentsDelegate : public WebContentsDelegate {
}; };
#ifdef USE_AURA #ifdef USE_AURA
class ScopedEnableUnadjustedMouseEventsForTesting
: public aura::ScopedEnableUnadjustedMouseEvents {
public:
explicit ScopedEnableUnadjustedMouseEventsForTesting() {}
~ScopedEnableUnadjustedMouseEventsForTesting() override {}
};
class MockPointerLockRenderWidgetHostView : public RenderWidgetHostViewAura { class MockPointerLockRenderWidgetHostView : public RenderWidgetHostViewAura {
public: public:
MockPointerLockRenderWidgetHostView(RenderWidgetHost* host, MockPointerLockRenderWidgetHostView(RenderWidgetHost* host,
...@@ -59,14 +66,16 @@ class MockPointerLockRenderWidgetHostView : public RenderWidgetHostViewAura { ...@@ -59,14 +66,16 @@ class MockPointerLockRenderWidgetHostView : public RenderWidgetHostViewAura {
bool LockMouse(bool request_unadjusted_movement) override { bool LockMouse(bool request_unadjusted_movement) override {
event_handler()->mouse_locked_ = true; event_handler()->mouse_locked_ = true;
event_handler()->mouse_locked_unadjusted_movement_ = event_handler()->mouse_locked_unadjusted_movement_ =
request_unadjusted_movement; request_unadjusted_movement
? std::make_unique<ScopedEnableUnadjustedMouseEventsForTesting>()
: nullptr;
return true; return true;
} }
void UnlockMouse() override { void UnlockMouse() override {
host_->LostMouseLock(); host_->LostMouseLock();
event_handler()->mouse_locked_ = false; event_handler()->mouse_locked_ = false;
event_handler()->mouse_locked_unadjusted_movement_ = false; event_handler()->mouse_locked_unadjusted_movement_.reset();
} }
bool IsMouseLocked() override { return event_handler()->mouse_locked(); } bool IsMouseLocked() override { return event_handler()->mouse_locked(); }
......
...@@ -350,6 +350,13 @@ class MockWindowEventTarget : public ui::WindowEventTarget { ...@@ -350,6 +350,13 @@ class MockWindowEventTarget : public ui::WindowEventTarget {
return S_OK; return S_OK;
} }
LRESULT HandleInputMessage(unsigned int message,
WPARAM w_param,
LPARAM l_param,
bool* handled) override {
return S_OK;
}
LRESULT HandleScrollMessage(unsigned int message, LRESULT HandleScrollMessage(unsigned int message,
WPARAM w_param, WPARAM w_param,
LPARAM l_param, LPARAM l_param,
......
...@@ -395,6 +395,19 @@ LRESULT LegacyRenderWidgetHostHWND::OnTouch(UINT message, ...@@ -395,6 +395,19 @@ LRESULT LegacyRenderWidgetHostHWND::OnTouch(UINT message,
return ret; return ret;
} }
LRESULT LegacyRenderWidgetHostHWND::OnInput(UINT message,
WPARAM w_param,
LPARAM l_param) {
LRESULT ret = 0;
if (GetWindowEventTarget(GetParent())) {
bool msg_handled = false;
ret = GetWindowEventTarget(GetParent())
->HandleInputMessage(message, w_param, l_param, &msg_handled);
SetMsgHandled(msg_handled);
}
return ret;
}
LRESULT LegacyRenderWidgetHostHWND::OnScroll(UINT message, LRESULT LegacyRenderWidgetHostHWND::OnScroll(UINT message,
WPARAM w_param, WPARAM w_param,
LPARAM l_param) { LPARAM l_param) {
......
...@@ -83,6 +83,7 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND ...@@ -83,6 +83,7 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
MESSAGE_HANDLER_EX(WM_PAINT, OnPaint) MESSAGE_HANDLER_EX(WM_PAINT, OnPaint)
MESSAGE_HANDLER_EX(WM_NCPAINT, OnNCPaint) MESSAGE_HANDLER_EX(WM_NCPAINT, OnNCPaint)
MESSAGE_HANDLER_EX(WM_ERASEBKGND, OnEraseBkGnd) MESSAGE_HANDLER_EX(WM_ERASEBKGND, OnEraseBkGnd)
MESSAGE_HANDLER_EX(WM_INPUT, OnInput)
MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange) MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseLeave) MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseLeave)
MESSAGE_HANDLER_EX(WM_MOUSEACTIVATE, OnMouseActivate) MESSAGE_HANDLER_EX(WM_MOUSEACTIVATE, OnMouseActivate)
...@@ -146,6 +147,7 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND ...@@ -146,6 +147,7 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
LRESULT OnEraseBkGnd(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnEraseBkGnd(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnInput(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnKeyboardRange(UINT message, WPARAM w_param, LPARAM l_param, LRESULT OnKeyboardRange(UINT message, WPARAM w_param, LPARAM l_param,
BOOL& handled); BOOL& handled);
LRESULT OnMouseLeave(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnMouseLeave(UINT message, WPARAM w_param, LPARAM l_param);
......
...@@ -1733,7 +1733,8 @@ void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) { ...@@ -1733,7 +1733,8 @@ void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) { void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
#if defined(OS_WIN) #if defined(OS_WIN)
if (event->type() == ui::ET_MOUSE_MOVED) { if (event->type() == ui::ET_MOUSE_MOVED) {
if (event->location() == last_mouse_move_location_) { if (event->location() == last_mouse_move_location_ &&
event->movement().IsZero()) {
event->SetHandled(); event->SetHandled();
return; return;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "ui/aura/scoped_keyboard_hook.h" #include "ui/aura/scoped_keyboard_hook.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_delegate.h" #include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_client.h"
#include "ui/events/blink/blink_event_util.h" #include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/web_input_event.h" #include "ui/events/blink/web_input_event.h"
...@@ -116,7 +117,6 @@ RenderWidgetHostViewEventHandler::RenderWidgetHostViewEventHandler( ...@@ -116,7 +117,6 @@ RenderWidgetHostViewEventHandler::RenderWidgetHostViewEventHandler(
Delegate* delegate) Delegate* delegate)
: accept_return_character_(false), : accept_return_character_(false),
mouse_locked_(false), mouse_locked_(false),
mouse_locked_unadjusted_movement_(false),
pinch_zoom_enabled_(content::IsPinchToZoomEnabled()), pinch_zoom_enabled_(content::IsPinchToZoomEnabled()),
set_focus_on_mouse_down_or_key_event_(false), set_focus_on_mouse_down_or_key_event_(false),
enable_consolidated_movement_( enable_consolidated_movement_(
...@@ -132,7 +132,9 @@ RenderWidgetHostViewEventHandler::RenderWidgetHostViewEventHandler( ...@@ -132,7 +132,9 @@ RenderWidgetHostViewEventHandler::RenderWidgetHostViewEventHandler(
? std::make_unique<HitTestDebugKeyEventObserver>(host) ? std::make_unique<HitTestDebugKeyEventObserver>(host)
: nullptr) {} : nullptr) {}
RenderWidgetHostViewEventHandler::~RenderWidgetHostViewEventHandler() {} RenderWidgetHostViewEventHandler::~RenderWidgetHostViewEventHandler() {
DCHECK(!mouse_locked_);
}
void RenderWidgetHostViewEventHandler::SetPopupChild( void RenderWidgetHostViewEventHandler::SetPopupChild(
RenderWidgetHostViewBase* popup_child_host_view, RenderWidgetHostViewBase* popup_child_host_view,
...@@ -169,12 +171,15 @@ bool RenderWidgetHostViewEventHandler::LockMouse( ...@@ -169,12 +171,15 @@ bool RenderWidgetHostViewEventHandler::LockMouse(
if (mouse_locked_) if (mouse_locked_)
return true; return true;
if (request_unadjusted_movement) { if (request_unadjusted_movement && window_->GetHost()) {
NOTIMPLEMENTED(); mouse_locked_unadjusted_movement_ =
return false; window_->GetHost()->RequestUnadjustedMovement();
if (!mouse_locked_unadjusted_movement_)
return false;
} }
mouse_locked_ = true; mouse_locked_ = true;
#if !defined(OS_WIN) #if !defined(OS_WIN)
window_->SetCapture(); window_->SetCapture();
#else #else
...@@ -202,7 +207,7 @@ void RenderWidgetHostViewEventHandler::UnlockMouse() { ...@@ -202,7 +207,7 @@ void RenderWidgetHostViewEventHandler::UnlockMouse() {
return; return;
mouse_locked_ = false; mouse_locked_ = false;
mouse_locked_unadjusted_movement_ = false; mouse_locked_unadjusted_movement_.reset();
if (window_->HasCapture()) if (window_->HasCapture())
window_->ReleaseCapture(); window_->ReleaseCapture();
...@@ -802,10 +807,12 @@ void RenderWidgetHostViewEventHandler::ModifyEventMovementAndCoords( ...@@ -802,10 +807,12 @@ void RenderWidgetHostViewEventHandler::ModifyEventMovementAndCoords(
// movement_x/y are integer. In order not to lose fractional part, we need // 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)". // to keep the movement calculation as "floor(cur_pos) - floor(last_pos)".
// Remove the floor here when movement_x/y is changed to double. // Remove the floor here when movement_x/y is changed to double.
event->movement_x = gfx::ToFlooredInt(event->PositionInScreen().x) - if (!(ui_mouse_event.flags() & ui::EF_UNADJUSTED_MOUSE)) {
gfx::ToFlooredInt(global_mouse_position_.x()); event->movement_x = gfx::ToFlooredInt(event->PositionInScreen().x) -
event->movement_y = gfx::ToFlooredInt(event->PositionInScreen().y) - gfx::ToFlooredInt(global_mouse_position_.x());
gfx::ToFlooredInt(global_mouse_position_.y()); event->movement_y = gfx::ToFlooredInt(event->PositionInScreen().y) -
gfx::ToFlooredInt(global_mouse_position_.y());
}
global_mouse_position_.SetPoint(event->PositionInScreen().x, global_mouse_position_.SetPoint(event->PositionInScreen().x,
event->PositionInScreen().y); event->PositionInScreen().y);
...@@ -913,6 +920,11 @@ void RenderWidgetHostViewEventHandler::SetKeyboardFocus() { ...@@ -913,6 +920,11 @@ void RenderWidgetHostViewEventHandler::SetKeyboardFocus() {
bool RenderWidgetHostViewEventHandler::ShouldMoveToCenter( bool RenderWidgetHostViewEventHandler::ShouldMoveToCenter(
gfx::PointF mouse_screen_position) { gfx::PointF mouse_screen_position) {
// Do not need to move to center in unadjusted movement mode as
// the movement value are directly from OS.
if (mouse_locked_unadjusted_movement_)
return false;
gfx::Rect rect = window_->bounds(); gfx::Rect rect = window_->bounds();
rect = delegate_->ConvertRectToScreen(rect); rect = delegate_->ConvertRectToScreen(rect);
float border_x = rect.width() * kMouseLockBorderPercentage / 100.0; float border_x = rect.width() * kMouseLockBorderPercentage / 100.0;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h" #include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
#include "ui/aura/scoped_enable_unadjusted_mouse_events.h"
#include "ui/aura/scoped_keyboard_hook.h" #include "ui/aura/scoped_keyboard_hook.h"
#include "ui/aura/window_tracker.h" #include "ui/aura/window_tracker.h"
#include "ui/events/event_handler.h" #include "ui/events/event_handler.h"
...@@ -259,9 +260,12 @@ class CONTENT_EXPORT RenderWidgetHostViewEventHandler ...@@ -259,9 +260,12 @@ class CONTENT_EXPORT RenderWidgetHostViewEventHandler
// locked. // locked.
bool mouse_locked_; bool mouse_locked_;
// True if mouse is locked and we are reporting the unadjusted movement // Use to track whether pointer lock is in the unadjusted movement mode and
// value (without mouse accelerations) from OS, i.e. WM_INPUT on Windows. // mousemoves are using unadjusted movement value (without mouse
bool mouse_locked_unadjusted_movement_; // accelerations) from OS, i.e. WM_INPUT on Windows. Deactivates raw input
// mode when destroyed.
std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
mouse_locked_unadjusted_movement_;
// Whether pinch-to-zoom should be enabled and pinch events forwarded to the // Whether pinch-to-zoom should be enabled and pinch events forwarded to the
// renderer. // renderer.
......
...@@ -36,6 +36,7 @@ jumbo_component("aura") { ...@@ -36,6 +36,7 @@ jumbo_component("aura") {
"input_state_lookup_win.h", "input_state_lookup_win.h",
"layout_manager.h", "layout_manager.h",
"null_window_targeter.h", "null_window_targeter.h",
"scoped_enable_unadjusted_mouse_events.h",
"scoped_keyboard_hook.h", "scoped_keyboard_hook.h",
"scoped_simple_keyboard_hook.h", "scoped_simple_keyboard_hook.h",
"scoped_window_targeter.h", "scoped_window_targeter.h",
......
// Copyright 2019 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.
#ifndef UI_AURA_SCOPED_ENABLE_UNADJUSTED_MOUSE_EVENTS_H_
#define UI_AURA_SCOPED_ENABLE_UNADJUSTED_MOUSE_EVENTS_H_
#include "ui/aura/aura_export.h"
namespace aura {
// Scoping class that ensures correctly exit unadjusted mouse input. Start using
// unadjusted mouse events (i.e. WM_INPUT on Windows) when this is constructed.
// Destroying an instance of this class will exit the unadjusted mouse event
// mode.
class AURA_EXPORT ScopedEnableUnadjustedMouseEvents {
public:
virtual ~ScopedEnableUnadjustedMouseEvents() = default;
protected:
ScopedEnableUnadjustedMouseEvents() = default;
};
} // namespace aura
#endif // UI_AURA_SCOPED_ENABLE_UNADJUSTED_MOUSE_EVENTS_H_
...@@ -344,6 +344,12 @@ void WindowTreeHost::SetNativeWindowOcclusionState( ...@@ -344,6 +344,12 @@ void WindowTreeHost::SetNativeWindowOcclusionState(
} }
} }
std::unique_ptr<ScopedEnableUnadjustedMouseEvents>
WindowTreeHost::RequestUnadjustedMovement() {
NOTIMPLEMENTED();
return nullptr;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// WindowTreeHost, protected: // WindowTreeHost, protected:
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/frame_sink_id.h"
#include "ui/aura/aura_export.h" #include "ui/aura/aura_export.h"
#include "ui/aura/scoped_enable_unadjusted_mouse_events.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor.h"
#include "ui/base/ime/input_method_delegate.h" #include "ui/base/ime/input_method_delegate.h"
...@@ -241,6 +242,13 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, ...@@ -241,6 +242,13 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
return occlusion_state_; return occlusion_state_;
} }
// Requests using unadjusted movement mouse events, i.e. WM_INPUT on Windows.
// Returns a ScopedEnableUnadjustedMouseEvents instance which stops using
// unadjusted mouse events when destroyed, returns nullptr if unadjusted mouse
// event is not not implemented or failed.
virtual std::unique_ptr<ScopedEnableUnadjustedMouseEvents>
RequestUnadjustedMovement();
bool holding_pointer_moves() const { return holding_pointer_moves_; } bool holding_pointer_moves() const { return holding_pointer_moves_; }
protected: protected:
......
...@@ -65,6 +65,17 @@ class UI_BASE_EXPORT WindowEventTarget { ...@@ -65,6 +65,17 @@ class UI_BASE_EXPORT WindowEventTarget {
LPARAM l_param, LPARAM l_param,
bool* handled) = 0; bool* handled) = 0;
// Handles WM_INPUT events.
// The |message| parameter identifies the message.
// The |w_param| and |l_param| values are as per MSDN docs.
// The |handled| parameter is an output parameter which when set to false
// indicates that the message should be DefProc'ed.
// Returns the result of processing the message.
virtual LRESULT HandleInputMessage(unsigned int message,
WPARAM w_param,
LPARAM l_param,
bool* handled) = 0;
// Handles scroll messages like WM_VSCROLL and WM_HSCROLL. // Handles scroll messages like WM_VSCROLL and WM_HSCROLL.
// The |message| parameter identifies the scroll message. // The |message| parameter identifies the scroll message.
// The |w_param| and |l_param| values are dependent on the type of scroll. // The |w_param| and |l_param| values are dependent on the type of scroll.
......
...@@ -257,6 +257,11 @@ blink::WebMouseEvent MakeWebMouseEvent(const MouseEvent& event) { ...@@ -257,6 +257,11 @@ blink::WebMouseEvent MakeWebMouseEvent(const MouseEvent& event) {
// Replace the event's coordinate fields with translated position data from // Replace the event's coordinate fields with translated position data from
// |event|. // |event|.
webkit_event.SetPositionInWidget(event.x(), event.y()); webkit_event.SetPositionInWidget(event.x(), event.y());
if (event.flags() & ui::EF_UNADJUSTED_MOUSE) {
webkit_event.movement_x = event.movement().x();
webkit_event.movement_y = event.movement().y();
webkit_event.is_raw_movement_event = true;
}
#if defined(OS_WIN) #if defined(OS_WIN)
if (event.native_event().message && event.type() != ET_MOUSE_EXITED) if (event.native_event().message && event.type() != ET_MOUSE_EXITED)
......
...@@ -550,4 +550,18 @@ TEST(WebInputEventTest, MouseLeaveScreenCoordinate) { ...@@ -550,4 +550,18 @@ TEST(WebInputEventTest, MouseLeaveScreenCoordinate) {
} }
#endif #endif
TEST(WebInputEventTest, MouseMoveUnadjustedMovement) {
gfx::PointF cursor_pos(123, 456);
gfx::Vector2dF movement(-12, 34);
ui::MouseEvent event(ET_MOUSE_MOVED, cursor_pos, cursor_pos,
base::TimeTicks(), 0, 0);
MouseEvent::DispatcherApi(&event).set_movement(movement);
blink::WebMouseEvent web_event = MakeWebMouseEvent(event);
ASSERT_TRUE(web_event.is_raw_movement_event);
ASSERT_EQ(web_event.movement_x, movement.x());
ASSERT_EQ(web_event.movement_y, movement.y());
}
} // namespace ui } // namespace ui
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
#include "ui/events/gesture_event_details.h" #include "ui/events/gesture_event_details.h"
#include "ui/events/gestures/gesture_types.h" #include "ui/events/gestures/gesture_types.h"
...@@ -485,6 +486,22 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent { ...@@ -485,6 +486,22 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
MouseEvent(const MouseEvent& copy); MouseEvent(const MouseEvent& copy);
~MouseEvent() override; ~MouseEvent() override;
class DispatcherApi {
public:
explicit DispatcherApi(MouseEvent* event) : event_(event) {}
// TODO(eirage): convert this to builder pattern.
void set_movement(const gfx::Vector2dF& movement) {
event_->movement_ = movement;
event_->set_flags(event_->flags() | EF_UNADJUSTED_MOUSE);
}
private:
MouseEvent* event_;
DISALLOW_COPY_AND_ASSIGN(DispatcherApi);
};
// Conveniences to quickly test what button is down // Conveniences to quickly test what button is down
bool IsOnlyLeftMouseButton() const { bool IsOnlyLeftMouseButton() const {
return button_flags() == EF_LEFT_MOUSE_BUTTON; return button_flags() == EF_LEFT_MOUSE_BUTTON;
...@@ -543,6 +560,8 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent { ...@@ -543,6 +560,8 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
// Updates the button that changed. // Updates the button that changed.
void set_changed_button_flags(int flags) { changed_button_flags_ = flags; } void set_changed_button_flags(int flags) { changed_button_flags_ = flags; }
const gfx::Vector2dF& movement() const { return movement_; }
const PointerDetails& pointer_details() const { return pointer_details_; } const PointerDetails& pointer_details() const { return pointer_details_; }
private: private:
...@@ -559,6 +578,12 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent { ...@@ -559,6 +578,12 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
// See description above getter for details. // See description above getter for details.
int changed_button_flags_; int changed_button_flags_;
// Raw mouse movement value reported from mouse hardware. The value of this is
// platform dependent and may change depending upon the hardware connected to
// the device. This field is only set if the flag EF_UNADJUSTED_MOUSE is
// present.
gfx::Vector2dF movement_;
// The most recent user-generated MouseEvent, used to detect double clicks. // The most recent user-generated MouseEvent, used to detect double clicks.
static MouseEvent* last_click_event_; static MouseEvent* last_click_event_;
......
...@@ -149,6 +149,9 @@ enum MouseEventFlags { ...@@ -149,6 +149,9 @@ enum MouseEventFlags {
EF_SCROLL_BY_PAGE = 1 << 22, // Indicates this mouse event is generated EF_SCROLL_BY_PAGE = 1 << 22, // Indicates this mouse event is generated
// when users is requesting to scroll by // when users is requesting to scroll by
// pages. // pages.
EF_UNADJUSTED_MOUSE = 1 << 23, // Indicates this mouse event is unadjusted
// mouse events that has unadjusted movement
// delta, i.e. is from WM_INPUT on Windows.
}; };
// Result of dispatching an event. // Result of dispatching an event.
......
...@@ -575,6 +575,7 @@ jumbo_component("views") { ...@@ -575,6 +575,7 @@ jumbo_component("views") {
"win/hwnd_message_handler_delegate.h", "win/hwnd_message_handler_delegate.h",
"win/hwnd_util.h", "win/hwnd_util.h",
"win/pen_event_processor.h", "win/pen_event_processor.h",
"win/scoped_enable_unadjusted_mouse_events_win.h",
"win/scoped_fullscreen_visibility.h", "win/scoped_fullscreen_visibility.h",
] ]
sources += [ sources += [
...@@ -583,6 +584,7 @@ jumbo_component("views") { ...@@ -583,6 +584,7 @@ jumbo_component("views") {
"win/hwnd_message_handler.cc", "win/hwnd_message_handler.cc",
"win/hwnd_util_aurawin.cc", "win/hwnd_util_aurawin.cc",
"win/pen_event_processor.cc", "win/pen_event_processor.cc",
"win/scoped_enable_unadjusted_mouse_events_win.cc",
"win/scoped_fullscreen_visibility.cc", "win/scoped_fullscreen_visibility.cc",
] ]
libs = [ libs = [
......
...@@ -626,6 +626,11 @@ void DesktopWindowTreeHostWin::MoveCursorToScreenLocationInPixels( ...@@ -626,6 +626,11 @@ void DesktopWindowTreeHostWin::MoveCursorToScreenLocationInPixels(
::SetCursorPos(cursor_location.x, cursor_location.y); ::SetCursorPos(cursor_location.x, cursor_location.y);
} }
std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
DesktopWindowTreeHostWin::RequestUnadjustedMovement() {
return message_handler_->RegisterUnadjustedMouseEvent();
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostWin, wm::AnimationHost implementation: // DesktopWindowTreeHostWin, wm::AnimationHost implementation:
...@@ -903,6 +908,7 @@ bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) { ...@@ -903,6 +908,7 @@ bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
// with the event. // with the event.
if (window()->occlusion_state() == aura::Window::OcclusionState::OCCLUDED) if (window()->occlusion_state() == aura::Window::OcclusionState::OCCLUDED)
UMA_HISTOGRAM_BOOLEAN("OccludedWindowMouseEvents", true); UMA_HISTOGRAM_BOOLEAN("OccludedWindowMouseEvents", true);
SendEventToSink(event); SendEventToSink(event);
return event->handled(); return event->handled();
} }
......
...@@ -141,6 +141,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin ...@@ -141,6 +141,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
void OnCursorVisibilityChangedNative(bool show) override; void OnCursorVisibilityChangedNative(bool show) override;
void MoveCursorToScreenLocationInPixels( void MoveCursorToScreenLocationInPixels(
const gfx::Point& location_in_pixels) override; const gfx::Point& location_in_pixels) override;
std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
RequestUnadjustedMovement() override;
// Overridden from aura::client::AnimationHost // Overridden from aura::client::AnimationHost
void SetHostTransitionOffsets( void SetHostTransitionOffsets(
......
...@@ -320,6 +320,22 @@ void RecordDeltaBetweenTimeNowAndPerformanceCountHistogram( ...@@ -320,6 +320,22 @@ void RecordDeltaBetweenTimeNowAndPerformanceCountHistogram(
} }
} }
int GetFlagsFromRawInputMessage(RAWINPUT* input) {
int flags = ui::EF_NONE;
if (input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN)
flags |= ui::EF_LEFT_MOUSE_BUTTON;
if (input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN)
flags |= ui::EF_RIGHT_MOUSE_BUTTON;
if (input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN)
flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
if (input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN)
flags |= ui::EF_BACK_MOUSE_BUTTON;
if (input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN)
flags |= ui::EF_FORWARD_MOUSE_BUTTON;
return ui::GetModifiersFromKeyState() | flags;
}
constexpr auto kTouchDownContextResetTimeout = constexpr auto kTouchDownContextResetTimeout =
base::TimeDelta::FromMilliseconds(500); base::TimeDelta::FromMilliseconds(500);
...@@ -993,6 +1009,18 @@ bool HWNDMessageHandler::HasChildRenderingWindow() { ...@@ -993,6 +1009,18 @@ bool HWNDMessageHandler::HasChildRenderingWindow() {
hwnd()); hwnd());
} }
std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
HWNDMessageHandler::RegisterUnadjustedMouseEvent() {
if (!base::FeatureList::IsEnabled(::features::kPointerLockOptions))
return nullptr;
std::unique_ptr<ScopedEnableUnadjustedMouseEventsWin> scoped_enable =
ScopedEnableUnadjustedMouseEventsWin::StartMonitor(this);
DCHECK(using_wm_input_);
return scoped_enable;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// HWNDMessageHandler, gfx::WindowImpl overrides: // HWNDMessageHandler, gfx::WindowImpl overrides:
...@@ -1131,6 +1159,16 @@ LRESULT HWNDMessageHandler::HandlePointerMessage(unsigned int message, ...@@ -1131,6 +1159,16 @@ LRESULT HWNDMessageHandler::HandlePointerMessage(unsigned int message,
return ret; return ret;
} }
LRESULT HWNDMessageHandler::HandleInputMessage(unsigned int message,
WPARAM w_param,
LPARAM l_param,
bool* handled) {
base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
LRESULT ret = OnInputEvent(message, w_param, l_param);
*handled = !ref.get() || msg_handled_;
return ret;
}
LRESULT HWNDMessageHandler::HandleScrollMessage(unsigned int message, LRESULT HWNDMessageHandler::HandleScrollMessage(unsigned int message,
WPARAM w_param, WPARAM w_param,
LPARAM l_param, LPARAM l_param,
...@@ -2023,6 +2061,54 @@ LRESULT HWNDMessageHandler::OnPointerEvent(UINT message, ...@@ -2023,6 +2061,54 @@ LRESULT HWNDMessageHandler::OnPointerEvent(UINT message,
return -1; return -1;
} }
LRESULT HWNDMessageHandler::OnInputEvent(UINT message,
WPARAM w_param,
LPARAM l_param) {
if (!using_wm_input_)
return -1;
HRAWINPUT input_handle = reinterpret_cast<HRAWINPUT>(l_param);
// Get the size of the input record.
UINT size = 0;
UINT result = ::GetRawInputData(input_handle, RID_INPUT, nullptr, &size,
sizeof(RAWINPUTHEADER));
if (result == static_cast<UINT>(-1)) {
PLOG(ERROR) << "GetRawInputData() failed";
return 0;
}
DCHECK_EQ(0u, result);
// Retrieve the input record.
uint8_t buffer[size];
RAWINPUT* input = reinterpret_cast<RAWINPUT*>(&buffer);
result = ::GetRawInputData(input_handle, RID_INPUT, &buffer, &size,
sizeof(RAWINPUTHEADER));
if (result == static_cast<UINT>(-1)) {
PLOG(ERROR) << "GetRawInputData() failed";
return 0;
}
DCHECK_EQ(size, result);
if (input->header.dwType == RIM_TYPEMOUSE &&
input->data.mouse.usButtonFlags != RI_MOUSE_WHEEL) {
POINT cursor_pos = {0};
::GetCursorPos(&cursor_pos);
ScreenToClient(hwnd(), &cursor_pos);
ui::MouseEvent event(
ui::ET_MOUSE_MOVED, gfx::PointF(cursor_pos.x, cursor_pos.y),
gfx::PointF(cursor_pos.x, cursor_pos.y), ui::EventTimeForNow(),
GetFlagsFromRawInputMessage(input), 0);
if (!(input->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)) {
ui::MouseEvent::DispatcherApi(&event).set_movement(
gfx::Vector2dF(input->data.mouse.lLastX, input->data.mouse.lLastY));
}
delegate_->HandleMouseEvent(&event);
}
return ::DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
}
void HWNDMessageHandler::OnMove(const gfx::Point& point) { void HWNDMessageHandler::OnMove(const gfx::Point& point) {
delegate_->HandleMove(); delegate_->HandleMove();
SetMsgHandled(FALSE); SetMsgHandled(FALSE);
...@@ -2973,6 +3059,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message, ...@@ -2973,6 +3059,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
: 1; : 1;
} }
// Suppress |ET_MOUSE_MOVED| and |ET_MOUSE_DRAGGED| events from WM_MOUSE*
// messages when using WM_INPUT.
if (using_wm_input_ && (event.type() == ui::ET_MOUSE_MOVED ||
event.type() == ui::ET_MOUSE_DRAGGED)) {
return 0;
}
// There are cases where the code handling the message destroys the window, // There are cases where the code handling the message destroys the window,
// so use the weak ptr to check if destruction occured or not. // so use the weak ptr to check if destruction occured or not.
base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr()); base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "ui/gfx/win/window_impl.h" #include "ui/gfx/win/window_impl.h"
#include "ui/views/views_export.h" #include "ui/views/views_export.h"
#include "ui/views/win/pen_event_processor.h" #include "ui/views/win/pen_event_processor.h"
#include "ui/views/win/scoped_enable_unadjusted_mouse_events_win.h"
#include "ui/views/window/window_resize_utils.h" #include "ui/views/window/window_resize_utils.h"
namespace gfx { namespace gfx {
...@@ -188,6 +189,13 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl, ...@@ -188,6 +189,13 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
} }
bool is_translucent() const { return is_translucent_; } bool is_translucent() const { return is_translucent_; }
std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
RegisterUnadjustedMouseEvent();
void set_using_wm_input(bool using_wm_input) {
using_wm_input_ = using_wm_input;
}
bool using_wm_input() { return using_wm_input_; }
private: private:
friend class ::views::test::DesktopWindowTreeHostWinTestApi; friend class ::views::test::DesktopWindowTreeHostWinTestApi;
...@@ -224,6 +232,10 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl, ...@@ -224,6 +232,10 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
WPARAM w_param, WPARAM w_param,
LPARAM l_param, LPARAM l_param,
bool* handled) override; bool* handled) override;
LRESULT HandleInputMessage(unsigned int message,
WPARAM w_param,
LPARAM l_param,
bool* handled) override;
LRESULT HandleScrollMessage(unsigned int message, LRESULT HandleScrollMessage(unsigned int message,
WPARAM w_param, WPARAM w_param,
LPARAM l_param, LPARAM l_param,
...@@ -382,6 +394,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl, ...@@ -382,6 +394,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
CR_MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent) CR_MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent)
CR_MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent) CR_MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent)
CR_MESSAGE_HANDLER_EX(WM_INPUT, OnInputEvent)
// IME Events. // IME Events.
CR_MESSAGE_HANDLER_EX(WM_IME_SETCONTEXT, OnImeMessages) CR_MESSAGE_HANDLER_EX(WM_IME_SETCONTEXT, OnImeMessages)
CR_MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeMessages) CR_MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeMessages)
...@@ -471,6 +484,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl, ...@@ -471,6 +484,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param);
void OnInitMenu(HMENU menu); void OnInitMenu(HMENU menu);
LRESULT OnInputEvent(UINT message, WPARAM w_param, LPARAM l_param);
void OnInputLangChange(DWORD character_set, HKL input_language_id); void OnInputLangChange(DWORD character_set, HKL input_language_id);
LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param);
void OnKillFocus(HWND focused_window); void OnKillFocus(HWND focused_window);
...@@ -767,6 +781,9 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl, ...@@ -767,6 +781,9 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// True if user is in remote session. // True if user is in remote session.
bool is_remote_session_; bool is_remote_session_;
// True if is handling mouse WM_INPUT messages.
bool using_wm_input_ = false;
// This is a map of the HMONITOR to full screeen window instance. It is safe // This is a map of the HMONITOR to full screeen window instance. It is safe
// to keep a raw pointer to the HWNDMessageHandler instance as we track the // to keep a raw pointer to the HWNDMessageHandler instance as we track the
// window destruction and ensure that the map is cleaned up. // window destruction and ensure that the map is cleaned up.
......
// Copyright 2019 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 "ui/views/win/scoped_enable_unadjusted_mouse_events_win.h"
#include "ui/views/win/hwnd_message_handler.h"
namespace views {
namespace {
// From the HID Usage Tables specification.
constexpr USHORT kGenericDesktopPage = 1;
constexpr USHORT kMouseUsage = 2;
std::unique_ptr<RAWINPUTDEVICE> GetRawInputDevices(HWND hwnd, DWORD flags) {
std::unique_ptr<RAWINPUTDEVICE> device = std::make_unique<RAWINPUTDEVICE>();
device->dwFlags = flags;
device->usUsagePage = kGenericDesktopPage;
device->usUsage = kMouseUsage;
device->hwndTarget = hwnd;
return device;
}
} // namespace
ScopedEnableUnadjustedMouseEventsWin::ScopedEnableUnadjustedMouseEventsWin(
HWNDMessageHandler* owner)
: owner_(owner) {}
ScopedEnableUnadjustedMouseEventsWin::~ScopedEnableUnadjustedMouseEventsWin() {
// Stop receiving raw input.
std::unique_ptr<RAWINPUTDEVICE> device(GetRawInputDevices(0, RIDEV_REMOVE));
if (!RegisterRawInputDevices(device.get(), 1, sizeof(*device)))
PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE ";
DCHECK(owner_->using_wm_input());
owner_->set_using_wm_input(false);
}
// static
std::unique_ptr<ScopedEnableUnadjustedMouseEventsWin>
ScopedEnableUnadjustedMouseEventsWin::StartMonitor(HWNDMessageHandler* owner) {
std::unique_ptr<RAWINPUTDEVICE> device(
GetRawInputDevices(owner->hwnd(), RIDEV_INPUTSINK));
if (!RegisterRawInputDevices(device.get(), 1, sizeof(*device))) {
PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK ";
return nullptr;
}
DCHECK(!owner->using_wm_input());
owner->set_using_wm_input(true);
return std::make_unique<ScopedEnableUnadjustedMouseEventsWin>(owner);
}
} // namespace views
// Copyright 2019 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.
#ifndef UI_VIEWS_WIN_SCOPED_ENABLE_UNADJUSTED_MOUSE_EVENTS_WIN_H_
#define UI_VIEWS_WIN_SCOPED_ENABLE_UNADJUSTED_MOUSE_EVENTS_WIN_H_
#include <memory>
#include "base/macros.h"
#include "ui/aura/scoped_enable_unadjusted_mouse_events.h"
namespace views {
class HWNDMessageHandler;
// This class handles register and unregister unadjusted mouse events on
// windows. Destroying an instance of this class will unregister unadjusted
// mouse events and stops handling mouse WM_INPUT messages.
class ScopedEnableUnadjustedMouseEventsWin
: public aura::ScopedEnableUnadjustedMouseEvents {
public:
explicit ScopedEnableUnadjustedMouseEventsWin(HWNDMessageHandler* owner);
~ScopedEnableUnadjustedMouseEventsWin() override;
// Register to receive raw mouse input. If success, creates a new
// ScopedEnableUnadjustedMouseEventsWin instance.
static std::unique_ptr<ScopedEnableUnadjustedMouseEventsWin> StartMonitor(
HWNDMessageHandler* owner);
HWNDMessageHandler* owner_;
DISALLOW_COPY_AND_ASSIGN(ScopedEnableUnadjustedMouseEventsWin);
};
} // namespace views
#endif // UI_VIEWS_WIN_SCOPED_ENABLE_UNADJUSTED_MOUSE_EVENTS_WIN_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment