summaryrefslogtreecommitdiffstats
path: root/win8/metro_driver
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-19 18:16:33 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-19 18:16:33 +0000
commit1554ee3d5b704b0bd4a9e10733175704464a8784 (patch)
treea39271bf17f97d07f116eeca981fad0ca19f0ff0 /win8/metro_driver
parentf98641a635dc64f18f5a526fb0dcdcb7047b1e5e (diff)
downloadchromium_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
Diffstat (limited to 'win8/metro_driver')
-rw-r--r--win8/metro_driver/chrome_app_view_ash.cc272
-rw-r--r--win8/metro_driver/chrome_app_view_ash.h24
2 files changed, 192 insertions, 104 deletions
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(&timestamp_);
@@ -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_;