summaryrefslogtreecommitdiffstats
path: root/chromium/win8/metro_driver/chrome_app_view_ash.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/win8/metro_driver/chrome_app_view_ash.cc')
-rw-r--r--chromium/win8/metro_driver/chrome_app_view_ash.cc498
1 files changed, 319 insertions, 179 deletions
diff --git a/chromium/win8/metro_driver/chrome_app_view_ash.cc b/chromium/win8/metro_driver/chrome_app_view_ash.cc
index c1a8f4cd573..fd193853d3c 100644
--- a/chromium/win8/metro_driver/chrome_app_view_ash.cc
+++ b/chromium/win8/metro_driver/chrome_app_view_ash.cc
@@ -17,11 +17,14 @@
#include "base/threading/thread.h"
#include "base/win/metro.h"
#include "base/win/win_util.h"
+#include "base/win/windows_version.h"
#include "chrome/common/chrome_switches.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_sender.h"
#include "ui/events/gestures/gesture_sequence.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/win/dpi.h"
#include "ui/metro_viewer/metro_viewer_messages.h"
#include "win8/metro_driver/file_picker_ash.h"
#include "win8/metro_driver/ime/ime_popup_monitor.h"
@@ -73,6 +76,8 @@ struct Globals {
BreakpadExceptionHandler breakpad_exception_handler;
} globals;
+extern float GetModernUIScale();
+
namespace {
enum KeyModifier {
@@ -85,7 +90,7 @@ enum KeyModifier {
// Helper function to send keystrokes via the SendInput function.
// mnemonic_char: The keystroke to be sent.
// modifiers: Combination with Alt, Ctrl, Shift, etc.
-void SendMnemonic(
+void SendKeySequence(
WORD mnemonic_char, KeyModifier modifiers) {
INPUT keys[4] = {0}; // Keyboard events
int key_count = 0; // Number of generated events
@@ -134,19 +139,6 @@ void SendMnemonic(
}
}
-// Helper function to Exit metro chrome cleanly. If we are in the foreground
-// then we try and exit by sending an Alt+F4 key combination to the core
-// window which ensures that the chrome application tile does not show up in
-// the running metro apps list on the top left corner.
-void MetroExit(HWND core_window) {
- if ((core_window != NULL) && (core_window == ::GetForegroundWindow())) {
- DVLOG(1) << "We are in the foreground. Exiting via Alt F4";
- SendMnemonic(VK_F4, ALT);
- } else {
- globals.app_exit->Exit();
- }
-}
-
class ChromeChannelListener : public IPC::Listener {
public:
ChromeChannelListener(base::MessageLoop* ui_loop, ChromeAppViewAsh* app_view)
@@ -179,11 +171,15 @@ class ChromeChannelListener : public IPC::Listener {
virtual void OnChannelError() OVERRIDE {
DVLOG(1) << "Channel error. Exiting.";
- MetroExit(app_view_->core_window_hwnd());
+ ui_proxy_->PostTask(FROM_HERE,
+ base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_),
+ TERMINATE_USING_KEY_SEQUENCE));
+
// In early Windows 8 versions the code above sometimes fails so we call
// it a second time with a NULL window which just calls Exit().
ui_proxy_->PostDelayedTask(FROM_HERE,
- base::Bind(&MetroExit, HWND(NULL)),
+ base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_),
+ TERMINATE_USING_PROCESS_EXIT),
base::TimeDelta::FromMilliseconds(100));
}
@@ -196,11 +192,13 @@ class ChromeChannelListener : public IPC::Listener {
}
void OnMetroExit() {
- MetroExit(app_view_->core_window_hwnd());
+ ui_proxy_->PostTask(FROM_HERE,
+ base::Bind(&ChromeAppViewAsh::OnMetroExit,
+ base::Unretained(app_view_), TERMINATE_USING_KEY_SEQUENCE));
}
void OnOpenURLOnDesktop(const base::FilePath& shortcut,
- const string16& url) {
+ const base::string16& url) {
ui_proxy_->PostTask(FROM_HERE,
base::Bind(&ChromeAppViewAsh::OnOpenURLOnDesktop,
base::Unretained(app_view_),
@@ -214,8 +212,8 @@ class ChromeChannelListener : public IPC::Listener {
reinterpret_cast<HCURSOR>(cursor)));
}
- void OnDisplayFileOpenDialog(const string16& title,
- const string16& filter,
+ void OnDisplayFileOpenDialog(const base::string16& title,
+ const base::string16& filter,
const base::FilePath& default_path,
bool allow_multiple_files) {
ui_proxy_->PostTask(FROM_HERE,
@@ -236,7 +234,7 @@ class ChromeChannelListener : public IPC::Listener {
params));
}
- void OnDisplayFolderPicker(const string16& title) {
+ void OnDisplayFolderPicker(const base::string16& title) {
ui_proxy_->PostTask(
FROM_HERE,
base::Bind(&ChromeAppViewAsh::OnDisplayFolderPicker,
@@ -279,22 +277,104 @@ bool WaitForChromeIPCConnection(const std::string& channel_name) {
int ms_elapsed = 0;
while (!IPC::Channel::IsNamedServerInitialized(channel_name) &&
ms_elapsed < 10000) {
- ms_elapsed += 500;
- Sleep(500);
+ ms_elapsed += 100;
+ Sleep(100);
}
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());
+ base::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;
+
+ base::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()
+ PointerInfoHandler(float metro_dpi_scale, float win32_dpi_scale)
: x_(0),
y_(0),
wheel_delta_(0),
update_kind_(winui::Input::PointerUpdateKind_Other),
timestamp_(0),
- pointer_id_(0) {}
+ pointer_id_(0),
+ mouse_down_flags_(0),
+ is_horizontal_wheel_(0),
+ metro_dpi_scale_(metro_dpi_scale),
+ win32_dpi_scale_(win32_dpi_scale) {}
HRESULT Init(winui::Core::IPointerEventArgs* args) {
HRESULT hr = args->get_CurrentPoint(&pointer_point_);
@@ -318,13 +398,50 @@ class PointerInfoHandler {
hr = properties->get_MouseWheelDelta(&wheel_delta_);
if (FAILED(hr))
return hr;
- x_ = point.X;
- y_ = point.Y;
+
+ is_horizontal_wheel_ = 0;
+ properties->get_IsHorizontalMouseWheel(&is_horizontal_wheel_);
+
+ // The input coordinates are in DIP based on the metro scale factor.
+ // We want to convert it to DIP based on the win32 scale factor.
+ // We scale the point by the metro scale factor and then scale down
+ // via the win32 scale factor which achieves the needful.
+ gfx::Point dip_point_metro(point.X, point.Y);
+ gfx::Point scaled_point_metro =
+ gfx::ToCeiledPoint(gfx::ScalePoint(dip_point_metro, metro_dpi_scale_));
+ gfx::Point dip_point_win32 =
+ gfx::ToCeiledPoint(gfx::ScalePoint(scaled_point_metro,
+ 1.0 / win32_dpi_scale_));
+ x_ = dip_point_win32.x();
+ y_ = dip_point_win32.y();
+
pointer_point_->get_Timestamp(&timestamp_);
pointer_point_->get_PointerId(&pointer_id_);
// 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;
}
@@ -348,7 +465,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;
@@ -364,9 +482,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_; }
@@ -376,6 +496,10 @@ class PointerInfoHandler {
uint64 timestamp() const { return timestamp_; }
+ winui::Input::PointerUpdateKind update_kind() const { return update_kind_; }
+
+ bool is_horizontal_wheel() const { return !!is_horizontal_wheel_; }
+
private:
int x_;
int y_;
@@ -384,90 +508,29 @@ 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);
+ // Bitmask of ui::EventFlags corresponding to the buttons that are currently
+ // down.
+ uint32 mouse_down_flags_;
- // Wind down the thread's chrome message loop.
- base::MessageLoop::current()->Quit();
-}
+ // Set to true for a horizontal wheel message.
+ boolean is_horizontal_wheel_;
-// 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;
+ // The metro device scale factor as reported by the winrt interfaces.
+ float metro_dpi_scale_;
+ // The win32 dpi scale which is queried via GetDeviceCaps. Please refer to
+ // ui/gfx/win/dpi.cc for more information.
+ float win32_dpi_scale_;
- 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
+ DISALLOW_COPY_AND_ASSIGN(PointerInfoHandler);
+};
ChromeAppViewAsh::ChromeAppViewAsh()
: mouse_down_flags_(ui::EF_NONE),
ui_channel_(nullptr),
core_window_hwnd_(NULL),
- ui_loop_(base::MessageLoop::TYPE_UI) {
+ metro_dpi_scale_(0),
+ win32_dpi_scale_(0) {
DVLOG(1) << __FUNCTION__;
globals.previous_state =
winapp::Activation::ApplicationExecutionState_NotRunning;
@@ -535,7 +598,7 @@ ChromeAppViewAsh::SetWindow(winui::Core::ICoreWindow* window) {
CheckHR(hr);
mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher;
- hr = window_->get_Dispatcher(&dispatcher);
+ hr = window_->get_Dispatcher(dispatcher.GetAddressOf());
CheckHR(hr, "Get Dispatcher failed.");
mswr::ComPtr<winui::Core::ICoreAcceleratorKeys> accelerator_keys;
@@ -564,31 +627,44 @@ ChromeAppViewAsh::SetWindow(winui::Core::ICoreWindow* window) {
&window_activated_token_);
CheckHR(hr);
- // Register for edge gesture notifications.
- mswr::ComPtr<winui::Input::IEdgeGestureStatics> edge_gesture_statics;
- hr = winrt_utils::CreateActivationFactory(
- RuntimeClass_Windows_UI_Input_EdgeGesture,
- edge_gesture_statics.GetAddressOf());
- CheckHR(hr);
-
- mswr::ComPtr<winui::Input::IEdgeGesture> edge_gesture;
- hr = edge_gesture_statics->GetForCurrentView(&edge_gesture);
- CheckHR(hr);
-
- hr = edge_gesture->add_Completed(mswr::Callback<EdgeEventHandler>(
- this, &ChromeAppViewAsh::OnEdgeGestureCompleted).Get(),
- &edgeevent_token_);
- CheckHR(hr);
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ // Register for edge gesture notifications only for Windows 8 and above.
+ mswr::ComPtr<winui::Input::IEdgeGestureStatics> edge_gesture_statics;
+ hr = winrt_utils::CreateActivationFactory(
+ RuntimeClass_Windows_UI_Input_EdgeGesture,
+ edge_gesture_statics.GetAddressOf());
+ CheckHR(hr);
+
+ mswr::ComPtr<winui::Input::IEdgeGesture> edge_gesture;
+ hr = edge_gesture_statics->GetForCurrentView(&edge_gesture);
+ CheckHR(hr);
+
+ hr = edge_gesture->add_Completed(mswr::Callback<EdgeEventHandler>(
+ this, &ChromeAppViewAsh::OnEdgeGestureCompleted).Get(),
+ &edgeevent_token_);
+ CheckHR(hr);
+ }
// By initializing the direct 3D swap chain with the corewindow
// we can now directly blit to it from the browser process.
direct3d_helper_.Initialize(window);
DVLOG(1) << "Initialized Direct3D.";
+
+ // On Windows 8+ the WinRT interface IDisplayProperties which we use to get
+ // device scale factor does not return the correct values in metro mode.
+ // To workaround this we retrieve the device scale factor via the win32 way
+ // and scale input coordinates accordingly to pass them in DIP to chrome.
+ // TODO(ananta). Investigate and fix.
+ metro_dpi_scale_ = GetModernUIScale();
+ win32_dpi_scale_ = gfx::GetDPIScale();
+ DVLOG(1) << "Metro Scale is " << metro_dpi_scale_;
+ DVLOG(1) << "Win32 Scale is " << win32_dpi_scale_;
return S_OK;
}
IFACEMETHODIMP
ChromeAppViewAsh::Load(HSTRING entryPoint) {
+ // On Win7 |entryPoint| is NULL.
DVLOG(1) << __FUNCTION__;
return S_OK;
}
@@ -597,7 +673,7 @@ IFACEMETHODIMP
ChromeAppViewAsh::Run() {
DVLOG(1) << __FUNCTION__;
mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher;
- HRESULT hr = window_->get_Dispatcher(&dispatcher);
+ HRESULT hr = window_->get_Dispatcher(dispatcher.GetAddressOf());
CheckHR(hr, "Dispatcher failed.");
hr = window_->Activate();
@@ -618,16 +694,17 @@ ChromeAppViewAsh::Run() {
// In Aura mode we create an IPC channel to the browser, then ask it to
// connect to us.
ChromeChannelListener ui_channel_listener(&ui_loop_, this);
- IPC::ChannelProxy ui_channel(win8::kMetroViewerIPCChannelName,
- IPC::Channel::MODE_NAMED_CLIENT,
- &ui_channel_listener,
- io_thread.message_loop_proxy());
- ui_channel_ = &ui_channel;
+ scoped_ptr<IPC::ChannelProxy> channel =
+ IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName,
+ IPC::Channel::MODE_NAMED_CLIENT,
+ &ui_channel_listener,
+ io_thread.message_loop_proxy());
+ ui_channel_ = channel.get();
// Upon receipt of the MetroViewerHostMsg_SetTargetSurface message the
// browser will use D3D from the browser process to present to our Window.
ui_channel_->Send(new MetroViewerHostMsg_SetTargetSurface(
- gfx::NativeViewId(core_window_hwnd_)));
+ gfx::NativeViewId(core_window_hwnd_), win32_dpi_scale_));
DVLOG(1) << "ICoreWindow sent " << core_window_hwnd_;
// Send an initial size message so that the Ash root window host gets sized
@@ -701,7 +778,7 @@ void ChromeAppViewAsh::OnActivateDesktop(const base::FilePath& file_path,
if (ash_exit) {
// As we are the top level window, the exiting is done async so we manage
// to execute the entire function including the final Send().
- MetroExit(core_window_hwnd());
+ OnMetroExit(TERMINATE_USING_KEY_SEQUENCE);
}
// We are just executing delegate_execute here without parameters. Assumption
@@ -726,7 +803,7 @@ void ChromeAppViewAsh::OnActivateDesktop(const base::FilePath& file_path,
}
void ChromeAppViewAsh::OnOpenURLOnDesktop(const base::FilePath& shortcut,
- const string16& url) {
+ const base::string16& url) {
base::FilePath::StringType file = shortcut.value();
SHELLEXECUTEINFO sei = { sizeof(sei) };
sei.fMask = SEE_MASK_FLAG_LOG_USAGE;
@@ -742,8 +819,8 @@ void ChromeAppViewAsh::OnSetCursor(HCURSOR cursor) {
}
void ChromeAppViewAsh::OnDisplayFileOpenDialog(
- const string16& title,
- const string16& filter,
+ const base::string16& title,
+ const base::string16& filter,
const base::FilePath& default_path,
bool allow_multiple_files) {
DVLOG(1) << __FUNCTION__;
@@ -772,7 +849,7 @@ void ChromeAppViewAsh::OnDisplayFileSaveAsDialog(
file_picker_->Run();
}
-void ChromeAppViewAsh::OnDisplayFolderPicker(const string16& title) {
+void ChromeAppViewAsh::OnDisplayFolderPicker(const base::string16& title) {
DVLOG(1) << __FUNCTION__;
// The FolderPickerSession instance is deleted when we receive a
// callback from the FolderPickerSession class about the completion of the
@@ -872,6 +949,30 @@ void ChromeAppViewAsh::OnImePopupChanged(ImePopupObserver::EventType event) {
}
}
+// Function to Exit metro chrome cleanly. If we are in the foreground
+// then we try and exit by sending an Alt+F4 key combination to the core
+// window which ensures that the chrome application tile does not show up in
+// the running metro apps list on the top left corner.
+void ChromeAppViewAsh::OnMetroExit(MetroTerminateMethod method) {
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ HWND core_window = core_window_hwnd();
+ if (method == TERMINATE_USING_KEY_SEQUENCE && core_window != NULL &&
+ core_window == ::GetForegroundWindow()) {
+ DVLOG(1) << "We are in the foreground. Exiting via Alt F4";
+ SendKeySequence(VK_F4, ALT);
+ if (ui_channel_)
+ ui_channel_->Close();
+ } else {
+ globals.app_exit->Exit();
+ }
+ } else {
+ if (ui_channel_)
+ ui_channel_->Close();
+
+ globals.app_exit->Exit();
+ }
+}
+
void ChromeAppViewAsh::OnInputSourceChanged() {
if (!input_source_)
return;
@@ -887,7 +988,7 @@ void ChromeAppViewAsh::OnInputSourceChanged() {
}
void ChromeAppViewAsh::OnCompositionChanged(
- const string16& text,
+ const base::string16& text,
int32 selection_start,
int32 selection_end,
const std::vector<metro_viewer::UnderlineInfo>& underlines) {
@@ -895,10 +996,54 @@ void ChromeAppViewAsh::OnCompositionChanged(
text, selection_start, selection_end, underlines));
}
-void ChromeAppViewAsh::OnTextCommitted(const string16& text) {
+void ChromeAppViewAsh::OnTextCommitted(const base::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,
+ bool is_horizontal_wheel) {
+ 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;
+ params.is_horizontal_wheel = is_horizontal_wheel;
+ 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(), pointer.is_horizontal_wheel());
+}
+
HRESULT ChromeAppViewAsh::OnActivate(
winapp::Core::ICoreApplicationView*,
winapp::Activation::IActivatedEventArgs* args) {
@@ -931,12 +1076,13 @@ HRESULT ChromeAppViewAsh::OnActivate(
HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender,
winui::Core::IPointerEventArgs* args) {
- PointerInfoHandler pointer;
+ PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_);
HRESULT hr = pointer.Init(args);
if (FAILED(hr))
return hr;
if (pointer.IsMouse()) {
+ GenerateMouseEventFromMoveIfNecessary(pointer);
ui_channel_->Send(new MetroViewerHostMsg_MouseMoved(
pointer.x(),
pointer.y(),
@@ -955,25 +1101,21 @@ 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) {
- PointerInfoHandler pointer;
+ PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_);
HRESULT hr = pointer.Init(args);
if (FAILED(hr))
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(), pointer.is_horizontal_wheel());
} else {
DCHECK(pointer.IsTouch());
ui_channel_->Send(new MetroViewerHostMsg_TouchDown(pointer.x(),
@@ -987,21 +1129,18 @@ HRESULT ChromeAppViewAsh::OnPointerPressed(
HRESULT ChromeAppViewAsh::OnPointerReleased(
winui::Core::ICoreWindow* sender,
winui::Core::IPointerEventArgs* args) {
- PointerInfoHandler pointer;
+ PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_);
HRESULT hr = pointer.Init(args);
if (FAILED(hr))
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(),
+ pointer.is_horizontal_wheel());
} else {
DCHECK(pointer.IsTouch());
ui_channel_->Send(new MetroViewerHostMsg_TouchUp(pointer.x(),
@@ -1015,15 +1154,14 @@ HRESULT ChromeAppViewAsh::OnPointerReleased(
HRESULT ChromeAppViewAsh::OnWheel(
winui::Core::ICoreWindow* sender,
winui::Core::IPointerEventArgs* args) {
- PointerInfoHandler pointer;
+ PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_);
HRESULT hr = pointer.Init(args);
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,
+ pointer.is_horizontal_wheel());
return S_OK;
}
@@ -1093,6 +1231,13 @@ HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown(
break;
case winui::Core::CoreAcceleratorKeyEventType_SystemKeyDown:
+ // Don't send the Alt + F4 combination to Chrome as this is intended to
+ // shut the metro environment down. Reason we check for Control here is
+ // Windows does not shutdown metro if Ctrl is pressed along with Alt F4.
+ // Other key combinations with Alt F4 shutdown metro.
+ if ((virtual_key == VK_F4) && ((keyboard_flags & ui::EF_ALT_DOWN) &&
+ !(keyboard_flags & ui::EF_CONTROL_DOWN)))
+ return S_OK;
ui_channel_->Send(new MetroViewerHostMsg_KeyDown(virtual_key,
status.RepeatCount,
status.ScanCode,
@@ -1165,7 +1310,7 @@ HRESULT ChromeAppViewAsh::HandleSearchRequest(
mswrw::HString search_string;
CheckHR(search_args->get_QueryText(search_string.GetAddressOf()));
- string16 search_text(MakeStdWString(search_string.Get()));
+ base::string16 search_text(MakeStdWString(search_string.Get()));
ui_loop_.PostTask(FROM_HERE,
base::Bind(&ChromeAppViewAsh::OnSearchRequest,
@@ -1190,7 +1335,7 @@ HRESULT ChromeAppViewAsh::HandleProtocolRequest(
protocol_args->get_Uri(&uri);
mswrw::HString url;
uri->get_AbsoluteUri(url.GetAddressOf());
- string16 actual_url(MakeStdWString(url.Get()));
+ base::string16 actual_url(MakeStdWString(url.Get()));
DVLOG(1) << "Received url request: " << actual_url;
ui_loop_.PostTask(FROM_HERE,
@@ -1203,20 +1348,16 @@ HRESULT ChromeAppViewAsh::HandleProtocolRequest(
HRESULT ChromeAppViewAsh::OnEdgeGestureCompleted(
winui::Input::IEdgeGesture* gesture,
winui::Input::IEdgeGestureEventArgs* args) {
- // Swipe from edge gesture (and win+z) is equivalent to pressing F11.
- // TODO(cpu): Make this cleaner for m33.
- ui_channel_->Send(new MetroViewerHostMsg_KeyDown(VK_F11, 1, 0, 0));
- ::Sleep(15);
- ui_channel_->Send(new MetroViewerHostMsg_KeyUp(VK_F11, 1, 0, 0));
+ ui_channel_->Send(new MetroViewerHostMsg_EdgeGesture());
return S_OK;
}
-void ChromeAppViewAsh::OnSearchRequest(const string16& search_string) {
+void ChromeAppViewAsh::OnSearchRequest(const base::string16& search_string) {
DCHECK(ui_channel_);
ui_channel_->Send(new MetroViewerHostMsg_SearchRequest(search_string));
}
-void ChromeAppViewAsh::OnNavigateToUrl(const string16& url) {
+void ChromeAppViewAsh::OnNavigateToUrl(const base::string16& url) {
DCHECK(ui_channel_);
ui_channel_->Send(new MetroViewerHostMsg_OpenURL(url));
}
@@ -1227,13 +1368,14 @@ HRESULT ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow* sender,
return S_OK;
}
- winfoundtn::Size size;
- HRESULT hr = args->get_Size(&size);
- if (FAILED(hr))
- return hr;
+ // winui::Core::IWindowSizeChangedEventArgs args->Size appears to return
+ // scaled values under HiDPI. We will instead use GetWindowRect() which
+ // should always return values in Pixels.
+ RECT rect = {0};
+ ::GetWindowRect(core_window_hwnd_, &rect);
- uint32 cx = static_cast<uint32>(size.Width);
- uint32 cy = static_cast<uint32>(size.Height);
+ uint32 cx = static_cast<uint32>(rect.right - rect.left);
+ uint32 cy = static_cast<uint32>(rect.bottom - rect.top);
DVLOG(1) << "Window size changed: width=" << cx << ", height=" << cy;
ui_channel_->Send(new MetroViewerHostMsg_WindowSizeChanged(cx, cy));
@@ -1243,9 +1385,7 @@ HRESULT ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow* sender,
///////////////////////////////////////////////////////////////////////////////
ChromeAppViewFactory::ChromeAppViewFactory(
- winapp::Core::ICoreApplication* icore_app,
- LPTHREAD_START_ROUTINE host_main,
- void* host_context) {
+ winapp::Core::ICoreApplication* icore_app) {
mswr::ComPtr<winapp::Core::ICoreApplication> core_app(icore_app);
mswr::ComPtr<winapp::Core::ICoreApplicationExit> app_exit;
CheckHR(core_app.As(&app_exit));