diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-19 18:16:33 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-19 18:16:33 +0000 |
commit | 1554ee3d5b704b0bd4a9e10733175704464a8784 (patch) | |
tree | a39271bf17f97d07f116eeca981fad0ca19f0ff0 | |
parent | f98641a635dc64f18f5a526fb0dcdcb7047b1e5e (diff) | |
download | chromium_src-1554ee3d5b704b0bd4a9e10733175704464a8784.zip chromium_src-1554ee3d5b704b0bd4a9e10733175704464a8784.tar.gz chromium_src-1554ee3d5b704b0bd4a9e10733175704464a8784.tar.bz2 |
Fixes mouse events in metro
This patch fixes two things not handled correctly:
. PointerPress/PointerRelease is only sent for the first button down
and the last button released. Intermediary presses and releases need
to be handled in OnPointerMoved.
. The changed flags (eg what button was pressed/released) wasn't being
passed in. This patch adds it.
BUG=none
TEST=none
R=ananta@chromium.org
Review URL: https://codereview.chromium.org/101193005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241884 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ui/aura/remote_root_window_host_win.cc | 23 | ||||
-rw-r--r-- | ui/aura/remote_root_window_host_win.h | 8 | ||||
-rw-r--r-- | ui/metro_viewer/metro_viewer_messages.h | 20 | ||||
-rw-r--r-- | win8/metro_driver/chrome_app_view_ash.cc | 272 | ||||
-rw-r--r-- | win8/metro_driver/chrome_app_view_ash.h | 24 |
5 files changed, 219 insertions, 128 deletions
diff --git a/ui/aura/remote_root_window_host_win.cc b/ui/aura/remote_root_window_host_win.cc index 8e78046..8373a31 100644 --- a/ui/aura/remote_root_window_host_win.cc +++ b/ui/aura/remote_root_window_host_win.cc @@ -492,20 +492,17 @@ void RemoteRootWindowHostWin::OnMouseMoved(int32 x, int32 y, int32 flags) { } void RemoteRootWindowHostWin::OnMouseButton( - int32 x, - int32 y, - int32 extra, - ui::EventType type, - ui::EventFlags flags) { - gfx::Point location(x, y); - // TODO: this needs to pass in changed flags. - ui::MouseEvent mouse_event(type, location, location, flags, 0); - - SetEventFlags(flags | key_event_flags()); - if (type == ui::ET_MOUSEWHEEL) { - ui::MouseWheelEvent wheel_event(mouse_event, 0, extra); + const MetroViewerHostMsg_MouseButtonParams& params) { + gfx::Point location(params.x, params.y); + ui::MouseEvent mouse_event(params.event_type, location, location, + static_cast<int>(params.flags), + static_cast<int>(params.changed_button)); + + SetEventFlags(params.flags | key_event_flags()); + if (params.event_type == ui::ET_MOUSEWHEEL) { + ui::MouseWheelEvent wheel_event(mouse_event, 0, params.extra); delegate_->OnHostMouseEvent(&wheel_event); - } else if (type == ui::ET_MOUSE_PRESSED) { + } else if (params.event_type == ui::ET_MOUSE_PRESSED) { // TODO(shrikant): Ideally modify code in event.cc by adding automatic // tracking of double clicks in synthetic MouseEvent constructor code. // Non-synthetic MouseEvent constructor code does automatically track diff --git a/ui/aura/remote_root_window_host_win.h b/ui/aura/remote_root_window_host_win.h index 41774e2..a295109 100644 --- a/ui/aura/remote_root_window_host_win.h +++ b/ui/aura/remote_root_window_host_win.h @@ -17,6 +17,8 @@ #include "ui/gfx/native_widget_types.h" #include "ui/metro_viewer/ime_types.h" +struct MetroViewerHostMsg_MouseButtonParams; + namespace base { class FilePath; } @@ -162,11 +164,7 @@ class AURA_EXPORT RemoteRootWindowHostWin // IPC message handing methods: void OnMouseMoved(int32 x, int32 y, int32 flags); - void OnMouseButton(int32 x, - int32 y, - int32 extra, - ui::EventType type, - ui::EventFlags flags); + void OnMouseButton(const MetroViewerHostMsg_MouseButtonParams& params); void OnKeyDown(uint32 vkey, uint32 repeat_count, uint32 scan_code, diff --git a/ui/metro_viewer/metro_viewer_messages.h b/ui/metro_viewer/metro_viewer_messages.h index b68c052..de213cb 100644 --- a/ui/metro_viewer/metro_viewer_messages.h +++ b/ui/metro_viewer/metro_viewer_messages.h @@ -17,6 +17,18 @@ IPC_ENUM_TRAITS(ui::EventType) IPC_ENUM_TRAITS(ui::EventFlags) +// Contains the parameters sent for a mousebutton message. +IPC_STRUCT_BEGIN(MetroViewerHostMsg_MouseButtonParams) + + IPC_STRUCT_MEMBER(int32, x) + IPC_STRUCT_MEMBER(int32, y) + IPC_STRUCT_MEMBER(int32, extra) + IPC_STRUCT_MEMBER(ui::EventType, event_type) + IPC_STRUCT_MEMBER(uint32, flags) + IPC_STRUCT_MEMBER(ui::EventFlags, changed_button) + +IPC_STRUCT_END() + // Messages sent from the viewer to the browser: // Inform the browser of the surface to target for compositing. @@ -28,12 +40,8 @@ IPC_MESSAGE_CONTROL3(MetroViewerHostMsg_MouseMoved, int32, /* y-coordinate */ int32 /* flags */) // Informs the brower that a mouse button was pressed. -IPC_MESSAGE_CONTROL5(MetroViewerHostMsg_MouseButton, - int32, /* x-coordinate */ - int32, /* y-coordinate */ - int32, /* extra */ - ui::EventType, /* event type */ - ui::EventFlags /* event flags */) +IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_MouseButton, + MetroViewerHostMsg_MouseButtonParams) // Informs the browser that a key was pressed. IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_KeyDown, uint32, /* virtual key */ diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc index 8b64251..08673de 100644 --- a/win8/metro_driver/chrome_app_view_ash.cc +++ b/win8/metro_driver/chrome_app_view_ash.cc @@ -280,8 +280,85 @@ bool WaitForChromeIPCConnection(const std::string& channel_name) { return IPC::Channel::IsNamedServerInitialized(channel_name); } +void RunMessageLoop(winui::Core::ICoreDispatcher* dispatcher) { + // We're entering a nested message loop, let's allow dispatching + // tasks while we're in there. + base::MessageLoop::current()->SetNestableTasksAllowed(true); + + // Enter main core message loop. There are several ways to exit it + // Nicely: + // 1 - User action like ALT-F4. + // 2 - Calling ICoreApplicationExit::Exit(). + // 3- Posting WM_CLOSE to the core window. + HRESULT hr = dispatcher->ProcessEvents( + winui::Core::CoreProcessEventsOption + ::CoreProcessEventsOption_ProcessUntilQuit); + + // Wind down the thread's chrome message loop. + base::MessageLoop::current()->Quit(); +} + +// Helper to return the state of the shift/control/alt keys. +uint32 GetKeyboardEventFlags() { + uint32 flags = 0; + if (base::win::IsShiftPressed()) + flags |= ui::EF_SHIFT_DOWN; + if (base::win::IsCtrlPressed()) + flags |= ui::EF_CONTROL_DOWN; + if (base::win::IsAltPressed()) + flags |= ui::EF_ALT_DOWN; + return flags; +} + +bool LaunchChromeBrowserProcess(const wchar_t* additional_parameters, + winapp::Activation::IActivatedEventArgs* args) { + if (args) { + DVLOG(1) << __FUNCTION__ << ":" << ::GetCommandLineW(); + winapp::Activation::ActivationKind activation_kind; + CheckHR(args->get_Kind(&activation_kind)); + + DVLOG(1) << __FUNCTION__ << ", activation_kind=" << activation_kind; + + if (activation_kind == winapp::Activation::ActivationKind_Launch) { + mswr::ComPtr<winapp::Activation::ILaunchActivatedEventArgs> launch_args; + if (args->QueryInterface( + winapp::Activation::IID_ILaunchActivatedEventArgs, + &launch_args) == S_OK) { + DVLOG(1) << "Activate: ActivationKind_Launch"; + mswrw::HString launch_args_str; + launch_args->get_Arguments(launch_args_str.GetAddressOf()); + string16 actual_launch_args(MakeStdWString(launch_args_str.Get())); + if (actual_launch_args == win8::kMetroViewerConnectVerb) { + DVLOG(1) << __FUNCTION__ << "Not launching chrome server"; + return true; + } + } + } + } + + DVLOG(1) << "Launching chrome server"; + base::FilePath chrome_exe_path; + + if (!PathService::Get(base::FILE_EXE, &chrome_exe_path)) + return false; + + string16 parameters = L"--silent-launch --viewer-connect "; + if (additional_parameters) + parameters += additional_parameters; + + SHELLEXECUTEINFO sei = { sizeof(sei) }; + sei.nShow = SW_SHOWNORMAL; + sei.lpFile = chrome_exe_path.value().c_str(); + sei.lpDirectory = L""; + sei.lpParameters = parameters.c_str(); + ::ShellExecuteEx(&sei); + return true; +} + +} // namespace + // This class helps decoding the pointer properties of an event. -class PointerInfoHandler { +class ChromeAppViewAsh::PointerInfoHandler { public: PointerInfoHandler() : x_(0), @@ -289,7 +366,8 @@ class PointerInfoHandler { wheel_delta_(0), update_kind_(winui::Input::PointerUpdateKind_Other), timestamp_(0), - pointer_id_(0) {} + pointer_id_(0), + mouse_down_flags_(0) {} HRESULT Init(winui::Core::IPointerEventArgs* args) { HRESULT hr = args->get_CurrentPoint(&pointer_point_); @@ -313,6 +391,7 @@ class PointerInfoHandler { hr = properties->get_MouseWheelDelta(&wheel_delta_); if (FAILED(hr)) return hr; + x_ = point.X; y_ = point.Y; pointer_point_->get_Timestamp(×tamp_); @@ -320,6 +399,28 @@ class PointerInfoHandler { // Map the OS touch event id to a range allowed by the gesture recognizer. if (IsTouch()) pointer_id_ %= ui::GestureSequence::kMaxGesturePoints; + + boolean left_button_state; + hr = properties->get_IsLeftButtonPressed(&left_button_state); + if (FAILED(hr)) + return hr; + if (left_button_state) + mouse_down_flags_ |= ui::EF_LEFT_MOUSE_BUTTON; + + boolean right_button_state; + hr = properties->get_IsRightButtonPressed(&right_button_state); + if (FAILED(hr)) + return hr; + if (right_button_state) + mouse_down_flags_ |= ui::EF_RIGHT_MOUSE_BUTTON; + + boolean middle_button_state; + hr = properties->get_IsMiddleButtonPressed(&middle_button_state); + if (FAILED(hr)) + return hr; + if (middle_button_state) + mouse_down_flags_ |= ui::EF_MIDDLE_MOUSE_BUTTON; + return S_OK; } @@ -343,7 +444,8 @@ class PointerInfoHandler { return wheel_delta_; } - ui::EventFlags flags() { + // Identifies the button that changed. + ui::EventFlags changed_button() const { switch (update_kind_) { case winui::Input::PointerUpdateKind_LeftButtonPressed: return ui::EF_LEFT_MOUSE_BUTTON; @@ -359,9 +461,11 @@ class PointerInfoHandler { return ui::EF_MIDDLE_MOUSE_BUTTON; default: return ui::EF_NONE; - }; + } } + uint32 mouse_down_flags() const { return mouse_down_flags_; } + int x() const { return x_; } int y() const { return y_; } @@ -371,6 +475,8 @@ class PointerInfoHandler { uint64 timestamp() const { return timestamp_; } + winui::Input::PointerUpdateKind update_kind() const { return update_kind_; } + private: int x_; int y_; @@ -379,84 +485,13 @@ class PointerInfoHandler { winui::Input::PointerUpdateKind update_kind_; mswr::ComPtr<winui::Input::IPointerPoint> pointer_point_; uint64 timestamp_; -}; - -void RunMessageLoop(winui::Core::ICoreDispatcher* dispatcher) { - // We're entering a nested message loop, let's allow dispatching - // tasks while we're in there. - base::MessageLoop::current()->SetNestableTasksAllowed(true); - - // Enter main core message loop. There are several ways to exit it - // Nicely: - // 1 - User action like ALT-F4. - // 2 - Calling ICoreApplicationExit::Exit(). - // 3- Posting WM_CLOSE to the core window. - HRESULT hr = dispatcher->ProcessEvents( - winui::Core::CoreProcessEventsOption - ::CoreProcessEventsOption_ProcessUntilQuit); - - // Wind down the thread's chrome message loop. - base::MessageLoop::current()->Quit(); -} - -// Helper to return the state of the shift/control/alt keys. -uint32 GetKeyboardEventFlags() { - uint32 flags = 0; - if (base::win::IsShiftPressed()) - flags |= ui::EF_SHIFT_DOWN; - if (base::win::IsCtrlPressed()) - flags |= ui::EF_CONTROL_DOWN; - if (base::win::IsAltPressed()) - flags |= ui::EF_ALT_DOWN; - return flags; -} - -bool LaunchChromeBrowserProcess(const wchar_t* additional_parameters, - winapp::Activation::IActivatedEventArgs* args) { - if (args) { - DVLOG(1) << __FUNCTION__ << ":" << ::GetCommandLineW(); - winapp::Activation::ActivationKind activation_kind; - CheckHR(args->get_Kind(&activation_kind)); - - DVLOG(1) << __FUNCTION__ << ", activation_kind=" << activation_kind; - - if (activation_kind == winapp::Activation::ActivationKind_Launch) { - mswr::ComPtr<winapp::Activation::ILaunchActivatedEventArgs> launch_args; - if (args->QueryInterface( - winapp::Activation::IID_ILaunchActivatedEventArgs, - &launch_args) == S_OK) { - DVLOG(1) << "Activate: ActivationKind_Launch"; - mswrw::HString launch_args_str; - launch_args->get_Arguments(launch_args_str.GetAddressOf()); - string16 actual_launch_args(MakeStdWString(launch_args_str.Get())); - if (actual_launch_args == win8::kMetroViewerConnectVerb) { - DVLOG(1) << __FUNCTION__ << "Not launching chrome server"; - return true; - } - } - } - } - DVLOG(1) << "Launching chrome server"; - base::FilePath chrome_exe_path; - - if (!PathService::Get(base::FILE_EXE, &chrome_exe_path)) - return false; + // Bitmask of ui::EventFlags corresponding to the buttons that are currently + // down. + uint32 mouse_down_flags_; - string16 parameters = L"--silent-launch --viewer-connect "; - if (additional_parameters) - parameters += additional_parameters; - - SHELLEXECUTEINFO sei = { sizeof(sei) }; - sei.nShow = SW_SHOWNORMAL; - sei.lpFile = chrome_exe_path.value().c_str(); - sei.lpDirectory = L""; - sei.lpParameters = parameters.c_str(); - ::ShellExecuteEx(&sei); - return true; -} - -} // namespace + DISALLOW_COPY_AND_ASSIGN(PointerInfoHandler); +}; ChromeAppViewAsh::ChromeAppViewAsh() : mouse_down_flags_(ui::EF_NONE), @@ -894,6 +929,48 @@ void ChromeAppViewAsh::OnTextCommitted(const string16& text) { ui_channel_->Send(new MetroViewerHostMsg_ImeTextCommitted(text)); } +void ChromeAppViewAsh::SendMouseButton(int x, + int y, + int extra, + ui::EventType event_type, + uint32 flags, + ui::EventFlags changed_button) { + MetroViewerHostMsg_MouseButtonParams params; + params.x = static_cast<int32>(x); + params.y = static_cast<int32>(y); + params.extra = static_cast<int32>(extra); + params.event_type = event_type; + params.flags = static_cast<int32>(flags); + params.changed_button = changed_button; + ui_channel_->Send(new MetroViewerHostMsg_MouseButton(params)); +} + +void ChromeAppViewAsh::GenerateMouseEventFromMoveIfNecessary( + const PointerInfoHandler& pointer) { + ui::EventType event_type; + // For aura we want the flags to include the button that was released, thus + // we or the old and new. + uint32 mouse_down_flags = pointer.mouse_down_flags() | mouse_down_flags_; + mouse_down_flags_ = pointer.mouse_down_flags(); + switch (pointer.update_kind()) { + case winui::Input::PointerUpdateKind_LeftButtonPressed: + case winui::Input::PointerUpdateKind_RightButtonPressed: + case winui::Input::PointerUpdateKind_MiddleButtonPressed: + event_type = ui::ET_MOUSE_PRESSED; + break; + case winui::Input::PointerUpdateKind_LeftButtonReleased: + case winui::Input::PointerUpdateKind_RightButtonReleased: + case winui::Input::PointerUpdateKind_MiddleButtonReleased: + event_type = ui::ET_MOUSE_RELEASED; + break; + default: + return; + } + SendMouseButton(pointer.x(), pointer.y(), 0, event_type, + mouse_down_flags | GetKeyboardEventFlags(), + pointer.changed_button()); +} + HRESULT ChromeAppViewAsh::OnActivate( winapp::Core::ICoreApplicationView*, winapp::Activation::IActivatedEventArgs* args) { @@ -932,6 +1009,7 @@ HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, return hr; if (pointer.IsMouse()) { + GenerateMouseEventFromMoveIfNecessary(pointer); ui_channel_->Send(new MetroViewerHostMsg_MouseMoved( pointer.x(), pointer.y(), @@ -950,7 +1028,8 @@ HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, // event for the first button pressed and the last button released in a sequence // of mouse events. // For example, a sequence of LEFT_DOWN, RIGHT_DOWN, LEFT_UP, RIGHT_UP results -// only in PointerPressed(LEFT)/PointerReleased(RIGHT) events. +// only in PointerPressed(LEFT)/PointerReleased(RIGHT) events. Intermediary +// presses and releases are tracked in OnPointMoved(). HRESULT ChromeAppViewAsh::OnPointerPressed( winui::Core::ICoreWindow* sender, winui::Core::IPointerEventArgs* args) { @@ -960,15 +1039,10 @@ HRESULT ChromeAppViewAsh::OnPointerPressed( return hr; if (pointer.IsMouse()) { - // TODO: this is wrong, more than one pointer may be down at a time. - mouse_down_flags_ = pointer.flags(); - ui_channel_->Send(new MetroViewerHostMsg_MouseButton( - pointer.x(), - pointer.y(), - 0, - ui::ET_MOUSE_PRESSED, - static_cast<ui::EventFlags>( - mouse_down_flags_ | GetKeyboardEventFlags()))); + mouse_down_flags_ = pointer.mouse_down_flags(); + SendMouseButton(pointer.x(), pointer.y(), 0, ui::ET_MOUSE_PRESSED, + mouse_down_flags_ | GetKeyboardEventFlags(), + pointer.changed_button()); } else { DCHECK(pointer.IsTouch()); ui_channel_->Send(new MetroViewerHostMsg_TouchDown(pointer.x(), @@ -988,15 +1062,11 @@ HRESULT ChromeAppViewAsh::OnPointerReleased( return hr; if (pointer.IsMouse()) { - // TODO: this is wrong, more than one pointer may be down at a time. mouse_down_flags_ = ui::EF_NONE; - ui_channel_->Send(new MetroViewerHostMsg_MouseButton( - pointer.x(), - pointer.y(), - 0, - ui::ET_MOUSE_RELEASED, - static_cast<ui::EventFlags>( - pointer.flags() | GetKeyboardEventFlags()))); + SendMouseButton(pointer.x(), pointer.y(), 0, ui::ET_MOUSE_RELEASED, + static_cast<uint32>(pointer.changed_button()) | + GetKeyboardEventFlags(), + pointer.changed_button()); } else { DCHECK(pointer.IsTouch()); ui_channel_->Send(new MetroViewerHostMsg_TouchUp(pointer.x(), @@ -1015,10 +1085,8 @@ HRESULT ChromeAppViewAsh::OnWheel( if (FAILED(hr)) return hr; DCHECK(pointer.IsMouse()); - ui_channel_->Send(new MetroViewerHostMsg_MouseButton(pointer.x(), pointer.y(), - pointer.wheel_delta(), - ui::ET_MOUSEWHEEL, - ui::EF_NONE)); + SendMouseButton(pointer.x(), pointer.y(), pointer.wheel_delta(), + ui::ET_MOUSEWHEEL, ui::EF_NONE, ui::EF_NONE); return S_OK; } diff --git a/win8/metro_driver/chrome_app_view_ash.h b/win8/metro_driver/chrome_app_view_ash.h index f657792..4b439c2 100644 --- a/win8/metro_driver/chrome_app_view_ash.h +++ b/win8/metro_driver/chrome_app_view_ash.h @@ -107,6 +107,8 @@ class ChromeAppViewAsh private: + class PointerInfoHandler; + // ImePopupObserver overrides. virtual void OnImePopupChanged(ImePopupObserver::EventType event) OVERRIDE; @@ -121,6 +123,23 @@ class ChromeAppViewAsh const std::vector<metro_viewer::UnderlineInfo>& underlines) OVERRIDE; virtual void OnTextCommitted(const string16& text) OVERRIDE; + // Convenience for sending a MetroViewerHostMsg_MouseButton with the specified + // parameters. + void SendMouseButton(int x, + int y, + int extra, + ui::EventType event_type, + uint32 flags, + ui::EventFlags changed_button); + + // Win8 only generates a mouse press for the initial button that goes down and + // a release when the last button is released. Any intermediary presses (or + // releases) do not result in a new press/release event. Instead a move is + // generated with the winui::Input::PointerUpdateKind identifying what + // changed. This function generates the necessary intermediary events (as + // necessary). + void GenerateMouseEventFromMoveIfNecessary(const PointerInfoHandler& pointer); + HRESULT OnActivate(winapp::Core::ICoreApplicationView* view, winapp::Activation::IActivatedEventArgs* args); @@ -185,8 +204,9 @@ class ChromeAppViewAsh EventRegistrationToken edgeevent_token_; // Keep state about which button is currently down, if any, as PointerMoved - // events do not contain that state, but Ash's MouseEvents need it. - ui::EventFlags mouse_down_flags_; + // events do not contain that state, but Ash's MouseEvents need it. Value is + // as a bitmask of ui::EventFlags. + uint32 mouse_down_flags_; // Set the D3D swap chain and nothing else. metro_driver::Direct3DHelper direct3d_helper_; |