Index: win8/metro_driver/chrome_app_view_ash.cc |
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc |
deleted file mode 100644 |
index 01f9ba23441acf29317b8a110734e74ef6b40038..0000000000000000000000000000000000000000 |
--- a/win8/metro_driver/chrome_app_view_ash.cc |
+++ /dev/null |
@@ -1,1464 +0,0 @@ |
-// Copyright (c) 2012 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 "win8/metro_driver/stdafx.h" |
-#include "win8/metro_driver/chrome_app_view_ash.h" |
- |
-#include <corewindow.h> |
-#include <shellapi.h> |
-#include <stdint.h> |
-#include <windows.foundation.h> |
- |
-#include "base/bind.h" |
-#include "base/command_line.h" |
-#include "base/files/file_path.h" |
-#include "base/macros.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/path_service.h" |
-#include "base/single_thread_task_runner.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/gesture_detection/motion_event.h" |
-#include "ui/events/win/system_event_state_lookup.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" |
-#include "win8/metro_driver/ime/input_source.h" |
-#include "win8/metro_driver/ime/text_service.h" |
-#include "win8/metro_driver/metro_driver.h" |
-#include "win8/metro_driver/winrt_utils.h" |
-#include "win8/viewer/metro_viewer_constants.h" |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winapp::Core::CoreApplicationView*, |
- winapp::Activation::IActivatedEventArgs*> ActivatedHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::PointerEventArgs*> PointerEventHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::KeyEventArgs*> KeyEventHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreDispatcher*, |
- winui::Core::AcceleratorKeyEventArgs*> AcceleratorKeyEventHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::CharacterReceivedEventArgs*> CharEventHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::WindowActivatedEventArgs*> WindowActivatedHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::WindowSizeChangedEventArgs*> SizeChangedHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Input::EdgeGesture*, |
- winui::Input::EdgeGestureEventArgs*> EdgeEventHandler; |
- |
-// This function is exported by chrome.exe. |
-typedef int (__cdecl *BreakpadExceptionHandler)(EXCEPTION_POINTERS* info); |
- |
-// Global information used across the metro driver. |
-struct Globals { |
- winapp::Activation::ApplicationExecutionState previous_state; |
- winapp::Core::ICoreApplicationExit* app_exit; |
- BreakpadExceptionHandler breakpad_exception_handler; |
-} globals; |
- |
-extern float GetModernUIScale(); |
- |
-namespace { |
- |
-enum KeyModifier { |
- NONE, |
- SHIFT = 1, |
- CONTROL = 2, |
- ALT = 4 |
-}; |
- |
-const int kChromeChannelPollTimerMs = 100; |
- |
-// Helper function to send keystrokes via the SendInput function. |
-// mnemonic_char: The keystroke to be sent. |
-// modifiers: Combination with Alt, Ctrl, Shift, etc. |
-void SendKeySequence( |
- WORD mnemonic_char, KeyModifier modifiers) { |
- INPUT keys[4] = {}; // Keyboard events |
- int key_count = 0; // Number of generated events |
- |
- if (modifiers & SHIFT) { |
- keys[key_count].type = INPUT_KEYBOARD; |
- keys[key_count].ki.wVk = VK_SHIFT; |
- keys[key_count].ki.wScan = MapVirtualKey(VK_SHIFT, 0); |
- key_count++; |
- } |
- |
- if (modifiers & CONTROL) { |
- keys[key_count].type = INPUT_KEYBOARD; |
- keys[key_count].ki.wVk = VK_CONTROL; |
- keys[key_count].ki.wScan = MapVirtualKey(VK_CONTROL, 0); |
- key_count++; |
- } |
- |
- if (modifiers & ALT) { |
- keys[key_count].type = INPUT_KEYBOARD; |
- keys[key_count].ki.wVk = VK_MENU; |
- keys[key_count].ki.wScan = MapVirtualKey(VK_MENU, 0); |
- key_count++; |
- } |
- |
- keys[key_count].type = INPUT_KEYBOARD; |
- keys[key_count].ki.wVk = mnemonic_char; |
- keys[key_count].ki.wScan = MapVirtualKey(mnemonic_char, 0); |
- key_count++; |
- |
- bool should_sleep = key_count > 1; |
- |
- // Send key downs. |
- for (int i = 0; i < key_count; i++) { |
- SendInput(1, &keys[ i ], sizeof(keys[0])); |
- keys[i].ki.dwFlags |= KEYEVENTF_KEYUP; |
- if (should_sleep) |
- Sleep(10); |
- } |
- |
- // Now send key ups in reverse order. |
- for (int i = key_count; i; i--) { |
- SendInput(1, &keys[ i - 1 ], sizeof(keys[0])); |
- if (should_sleep) |
- Sleep(10); |
- } |
-} |
- |
-class ChromeChannelListener : public IPC::Listener { |
- public: |
- ChromeChannelListener(base::MessageLoop* ui_loop, ChromeAppViewAsh* app_view) |
- : ui_task_runner_(ui_loop->task_runner()), app_view_(app_view) {} |
- |
- bool OnMessageReceived(const IPC::Message& message) override { |
- IPC_BEGIN_MESSAGE_MAP(ChromeChannelListener, message) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ActivateDesktop, |
- OnActivateDesktop) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MetroExit, OnMetroExit) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_OpenURLOnDesktop, |
- OnOpenURLOnDesktop) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursor, OnSetCursor) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplayFileOpen, |
- OnDisplayFileOpenDialog) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplayFileSaveAs, |
- OnDisplayFileSaveAsDialog) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplaySelectFolder, |
- OnDisplayFolderPicker) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPos, OnSetCursorPos) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCancelComposition, |
- OnImeCancelComposition) |
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextInputClientUpdated, |
- OnImeTextInputClientChanged) |
- IPC_MESSAGE_UNHANDLED(__debugbreak()) |
- IPC_END_MESSAGE_MAP() |
- return true; |
- } |
- |
- void OnChannelError() override { |
- DVLOG(1) << "Channel error. Exiting."; |
- ui_task_runner_->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_task_runner_->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_), |
- TERMINATE_USING_PROCESS_EXIT), |
- base::TimeDelta::FromMilliseconds(100)); |
- } |
- |
- private: |
- void OnActivateDesktop(const base::FilePath& shortcut, bool ash_exit) { |
- ui_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppViewAsh::OnActivateDesktop, |
- base::Unretained(app_view_), shortcut, ash_exit)); |
- } |
- |
- void OnMetroExit() { |
- ui_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_), |
- TERMINATE_USING_KEY_SEQUENCE)); |
- } |
- |
- void OnOpenURLOnDesktop(const base::FilePath& shortcut, |
- const base::string16& url) { |
- ui_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppViewAsh::OnOpenURLOnDesktop, |
- base::Unretained(app_view_), shortcut, url)); |
- } |
- |
- void OnSetCursor(int64_t cursor) { |
- ui_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&ChromeAppViewAsh::OnSetCursor, base::Unretained(app_view_), |
- reinterpret_cast<HCURSOR>(cursor))); |
- } |
- |
- void OnDisplayFileOpenDialog(const base::string16& title, |
- const base::string16& filter, |
- const base::FilePath& default_path, |
- bool allow_multiple_files) { |
- ui_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppViewAsh::OnDisplayFileOpenDialog, |
- base::Unretained(app_view_), title, filter, |
- default_path, allow_multiple_files)); |
- } |
- |
- void OnDisplayFileSaveAsDialog( |
- const MetroViewerHostMsg_SaveAsDialogParams& params) { |
- ui_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppViewAsh::OnDisplayFileSaveAsDialog, |
- base::Unretained(app_view_), params)); |
- } |
- |
- void OnDisplayFolderPicker(const base::string16& title) { |
- ui_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppViewAsh::OnDisplayFolderPicker, |
- base::Unretained(app_view_), title)); |
- } |
- |
- void OnSetCursorPos(int x, int y) { |
- VLOG(1) << "In IPC OnSetCursorPos: " << x << ", " << y; |
- ui_task_runner_->PostTask(FROM_HERE, |
- base::Bind(&ChromeAppViewAsh::OnSetCursorPos, |
- base::Unretained(app_view_), x, y)); |
- } |
- |
- void OnImeCancelComposition() { |
- ui_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppViewAsh::OnImeCancelComposition, |
- base::Unretained(app_view_))); |
- } |
- |
- void OnImeTextInputClientChanged( |
- const std::vector<int32_t>& input_scopes, |
- const std::vector<metro_viewer::CharacterBounds>& character_bounds) { |
- ui_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppViewAsh::OnImeUpdateTextInputClient, |
- base::Unretained(app_view_), input_scopes, |
- character_bounds)); |
- } |
- |
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
- ChromeAppViewAsh* app_view_; |
-}; |
- |
-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. |
- dispatcher->ProcessEvents( |
- winui::Core::CoreProcessEventsOption |
- ::CoreProcessEventsOption_ProcessUntilQuit); |
- |
- // Wind down the thread's chrome message loop. |
- base::MessageLoop::current()->QuitWhenIdle(); |
-} |
- |
-// Helper to return the state of the shift/control/alt keys. |
-uint32_t GetKeyboardEventFlags() { |
- uint32_t flags = 0; |
- if (ui::win::IsShiftPressed()) |
- flags |= ui::EF_SHIFT_DOWN; |
- if (ui::win::IsCtrlPressed()) |
- flags |= ui::EF_CONTROL_DOWN; |
- if (ui::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 --connect-to-metro-viewer "; |
- 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 ChromeAppViewAsh::PointerInfoHandler { |
- public: |
- PointerInfoHandler(float metro_dpi_scale, float win32_dpi_scale) |
- : x_(0), |
- y_(0), |
- wheel_delta_(0), |
- pointer_id_(0), |
- update_kind_(winui::Input::PointerUpdateKind_Other), |
- timestamp_(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_); |
- if (FAILED(hr)) |
- return hr; |
- |
- winfoundtn::Point point; |
- hr = pointer_point_->get_Position(&point); |
- if (FAILED(hr)) |
- return hr; |
- |
- mswr::ComPtr<winui::Input::IPointerPointProperties> properties; |
- hr = pointer_point_->get_Properties(&properties); |
- if (FAILED(hr)) |
- return hr; |
- |
- hr = properties->get_PointerUpdateKind(&update_kind_); |
- if (FAILED(hr)) |
- return hr; |
- |
- hr = properties->get_MouseWheelDelta(&wheel_delta_); |
- if (FAILED(hr)) |
- return hr; |
- |
- 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::ScaleToCeiledPoint(dip_point_metro, metro_dpi_scale_); |
- gfx::Point dip_point_win32 = |
- gfx::ScaleToCeiledPoint(scaled_point_metro, 1.0 / win32_dpi_scale_); |
- x_ = dip_point_win32.x(); |
- y_ = dip_point_win32.y(); |
- |
- pointer_point_->get_Timestamp(×tamp_); |
- 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::MotionEvent::MAX_TOUCH_POINT_COUNT; |
- |
- 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; |
- } |
- |
- bool IsType(windevs::Input::PointerDeviceType type) const { |
- mswr::ComPtr<windevs::Input::IPointerDevice> pointer_device; |
- CheckHR(pointer_point_->get_PointerDevice(&pointer_device)); |
- windevs::Input::PointerDeviceType device_type; |
- CheckHR(pointer_device->get_PointerDeviceType(&device_type)); |
- return (device_type == type); |
- } |
- |
- bool IsMouse() const { |
- return IsType(windevs::Input::PointerDeviceType_Mouse); |
- } |
- |
- bool IsTouch() const { |
- return IsType(windevs::Input::PointerDeviceType_Touch); |
- } |
- |
- int32_t wheel_delta() const { return wheel_delta_; } |
- |
- // Identifies the button that changed. |
- ui::EventFlags changed_button() const { |
- switch (update_kind_) { |
- case winui::Input::PointerUpdateKind_LeftButtonPressed: |
- return ui::EF_LEFT_MOUSE_BUTTON; |
- case winui::Input::PointerUpdateKind_LeftButtonReleased: |
- return ui::EF_LEFT_MOUSE_BUTTON; |
- case winui::Input::PointerUpdateKind_RightButtonPressed: |
- return ui::EF_RIGHT_MOUSE_BUTTON; |
- case winui::Input::PointerUpdateKind_RightButtonReleased: |
- return ui::EF_RIGHT_MOUSE_BUTTON; |
- case winui::Input::PointerUpdateKind_MiddleButtonPressed: |
- return ui::EF_MIDDLE_MOUSE_BUTTON; |
- case winui::Input::PointerUpdateKind_MiddleButtonReleased: |
- return ui::EF_MIDDLE_MOUSE_BUTTON; |
- default: |
- return ui::EF_NONE; |
- } |
- } |
- |
- uint32_t mouse_down_flags() const { return mouse_down_flags_; } |
- |
- int x() const { return x_; } |
- int y() const { return y_; } |
- |
- uint32_t pointer_id() const { return pointer_id_; } |
- |
- uint64_t 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_; |
- int wheel_delta_; |
- uint32_t pointer_id_; |
- winui::Input::PointerUpdateKind update_kind_; |
- mswr::ComPtr<winui::Input::IPointerPoint> pointer_point_; |
- uint64_t timestamp_; |
- |
- // Bitmask of ui::EventFlags corresponding to the buttons that are currently |
- // down. |
- uint32_t mouse_down_flags_; |
- |
- // Set to true for a horizontal wheel message. |
- boolean is_horizontal_wheel_; |
- |
- // 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_; |
- |
- DISALLOW_COPY_AND_ASSIGN(PointerInfoHandler); |
-}; |
- |
-ChromeAppViewAsh::ChromeAppViewAsh() |
- : mouse_down_flags_(ui::EF_NONE), |
- ui_channel_(nullptr), |
- core_window_hwnd_(NULL), |
- metro_dpi_scale_(0), |
- win32_dpi_scale_(0), |
- last_cursor_(NULL), |
- channel_listener_(NULL) { |
- DVLOG(1) << __FUNCTION__; |
- globals.previous_state = |
- winapp::Activation::ApplicationExecutionState_NotRunning; |
-} |
- |
-ChromeAppViewAsh::~ChromeAppViewAsh() { |
- DVLOG(1) << __FUNCTION__; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppViewAsh::Initialize(winapp::Core::ICoreApplicationView* view) { |
- view_ = view; |
- DVLOG(1) << __FUNCTION__; |
- HRESULT hr = view_->add_Activated(mswr::Callback<ActivatedHandler>( |
- this, &ChromeAppViewAsh::OnActivate).Get(), |
- &activated_token_); |
- CheckHR(hr); |
- return hr; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppViewAsh::SetWindow(winui::Core::ICoreWindow* window) { |
- window_ = window; |
- DVLOG(1) << __FUNCTION__; |
- |
- // Retrieve the native window handle via the interop layer. |
- mswr::ComPtr<ICoreWindowInterop> interop; |
- HRESULT hr = window->QueryInterface(interop.GetAddressOf()); |
- CheckHR(hr); |
- hr = interop->get_WindowHandle(&core_window_hwnd_); |
- CheckHR(hr); |
- |
- text_service_ = metro_driver::CreateTextService(this, core_window_hwnd_); |
- |
- hr = window_->add_SizeChanged(mswr::Callback<SizeChangedHandler>( |
- this, &ChromeAppViewAsh::OnSizeChanged).Get(), |
- &sizechange_token_); |
- CheckHR(hr); |
- |
- // Register for pointer and keyboard notifications. We forward |
- // them to the browser process via IPC. |
- hr = window_->add_PointerMoved(mswr::Callback<PointerEventHandler>( |
- this, &ChromeAppViewAsh::OnPointerMoved).Get(), |
- &pointermoved_token_); |
- CheckHR(hr); |
- |
- hr = window_->add_PointerPressed(mswr::Callback<PointerEventHandler>( |
- this, &ChromeAppViewAsh::OnPointerPressed).Get(), |
- &pointerpressed_token_); |
- CheckHR(hr); |
- |
- hr = window_->add_PointerReleased(mswr::Callback<PointerEventHandler>( |
- this, &ChromeAppViewAsh::OnPointerReleased).Get(), |
- &pointerreleased_token_); |
- CheckHR(hr); |
- |
- hr = window_->add_KeyDown(mswr::Callback<KeyEventHandler>( |
- this, &ChromeAppViewAsh::OnKeyDown).Get(), |
- &keydown_token_); |
- CheckHR(hr); |
- |
- hr = window_->add_KeyUp(mswr::Callback<KeyEventHandler>( |
- this, &ChromeAppViewAsh::OnKeyUp).Get(), |
- &keyup_token_); |
- CheckHR(hr); |
- |
- mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher; |
- hr = window_->get_Dispatcher(dispatcher.GetAddressOf()); |
- CheckHR(hr, "Get Dispatcher failed."); |
- |
- mswr::ComPtr<winui::Core::ICoreAcceleratorKeys> accelerator_keys; |
- hr = dispatcher.CopyTo(__uuidof(winui::Core::ICoreAcceleratorKeys), |
- reinterpret_cast<void**>( |
- accelerator_keys.GetAddressOf())); |
- CheckHR(hr, "QI for ICoreAcceleratorKeys failed."); |
- hr = accelerator_keys->add_AcceleratorKeyActivated( |
- mswr::Callback<AcceleratorKeyEventHandler>( |
- this, &ChromeAppViewAsh::OnAcceleratorKeyDown).Get(), |
- &accel_keydown_token_); |
- CheckHR(hr); |
- |
- hr = window_->add_PointerWheelChanged(mswr::Callback<PointerEventHandler>( |
- this, &ChromeAppViewAsh::OnWheel).Get(), |
- &wheel_token_); |
- CheckHR(hr); |
- |
- hr = window_->add_CharacterReceived(mswr::Callback<CharEventHandler>( |
- this, &ChromeAppViewAsh::OnCharacterReceived).Get(), |
- &character_received_token_); |
- CheckHR(hr); |
- |
- hr = window_->add_Activated(mswr::Callback<WindowActivatedHandler>( |
- this, &ChromeAppViewAsh::OnWindowActivated).Get(), |
- &window_activated_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; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppViewAsh::Run() { |
- DVLOG(1) << __FUNCTION__; |
- mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher; |
- HRESULT hr = window_->get_Dispatcher(dispatcher.GetAddressOf()); |
- CheckHR(hr, "Dispatcher failed."); |
- |
- // Create the IPC channel IO thread. It needs to out-live the ChannelProxy. |
- io_thread_.reset(new base::Thread("metro_IO_thread")); |
- base::Thread::Options options; |
- options.message_loop_type = base::MessageLoop::TYPE_IO; |
- io_thread_->StartWithOptions(options); |
- |
- ChromeChannelListener ui_channel_listener(&ui_loop_, this); |
- channel_listener_ = &ui_channel_listener; |
- |
- // We can't do anything until the Chrome browser IPC channel is initialized. |
- // Lazy initialization in a timer. |
- ui_loop_.PostDelayedTask(FROM_HERE, |
- base::Bind(base::IgnoreResult(&ChromeAppViewAsh::StartChromeOSMode), |
- base::Unretained(this)), |
- base::TimeDelta::FromMilliseconds(kChromeChannelPollTimerMs)); |
- |
- // Post the task that'll do the inner Metro message pumping to it. |
- ui_loop_.PostTask(FROM_HERE, base::Bind(&RunMessageLoop, dispatcher.Get())); |
- ui_loop_.Run(); |
- |
- io_thread_.reset(NULL); |
- ui_channel_.reset(NULL); |
- channel_listener_ = NULL; |
- |
- DVLOG(0) << "ProcessEvents done, hr=" << hr; |
- return hr; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppViewAsh::Uninitialize() { |
- DVLOG(1) << __FUNCTION__; |
- metro_driver::RemoveImePopupObserver(this); |
- input_source_.reset(); |
- text_service_.reset(); |
- window_ = nullptr; |
- view_ = nullptr; |
- core_window_hwnd_ = NULL; |
- return S_OK; |
-} |
- |
-// static |
-HRESULT ChromeAppViewAsh::Unsnap() { |
- mswr::ComPtr<winui::ViewManagement::IApplicationViewStatics> view_statics; |
- HRESULT hr = winrt_utils::CreateActivationFactory( |
- RuntimeClass_Windows_UI_ViewManagement_ApplicationView, |
- view_statics.GetAddressOf()); |
- CheckHR(hr); |
- |
- winui::ViewManagement::ApplicationViewState state = |
- winui::ViewManagement::ApplicationViewState_FullScreenLandscape; |
- hr = view_statics->get_Value(&state); |
- CheckHR(hr); |
- |
- if (state == winui::ViewManagement::ApplicationViewState_Snapped) { |
- boolean success = FALSE; |
- hr = view_statics->TryUnsnap(&success); |
- |
- if (FAILED(hr) || !success) { |
- LOG(ERROR) << "Failed to unsnap. Error 0x" << hr; |
- if (SUCCEEDED(hr)) |
- hr = E_UNEXPECTED; |
- } |
- } |
- return hr; |
-} |
- |
-void ChromeAppViewAsh::OnActivateDesktop(const base::FilePath& file_path, |
- bool ash_exit) { |
- DVLOG(1) << "ChannelAppViewAsh::OnActivateDesktop\n"; |
- |
- 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(). |
- OnMetroExit(TERMINATE_USING_KEY_SEQUENCE); |
- } |
- |
- // We are just executing delegate_execute here without parameters. Assumption |
- // here is that this process will be reused by shell when asking for |
- // IExecuteCommand interface. |
- |
- // TODO(shrikant): Consolidate ShellExecuteEx with SEE_MASK_FLAG_LOG_USAGE |
- // and place it metro.h or similar accessible file from all code code paths |
- // using this function. |
- SHELLEXECUTEINFO sei = { sizeof(sei) }; |
- sei.fMask = SEE_MASK_FLAG_LOG_USAGE; |
- sei.nShow = SW_SHOWNORMAL; |
- sei.lpFile = file_path.value().c_str(); |
- sei.lpParameters = NULL; |
- if (!ash_exit) |
- sei.fMask |= SEE_MASK_NOCLOSEPROCESS; |
- ::ShellExecuteExW(&sei); |
- if (!ash_exit) { |
- ::TerminateProcess(sei.hProcess, 0); |
- ::CloseHandle(sei.hProcess); |
- } |
-} |
- |
-void ChromeAppViewAsh::OnOpenURLOnDesktop(const base::FilePath& shortcut, |
- const base::string16& url) { |
- base::FilePath::StringType file = shortcut.value(); |
- SHELLEXECUTEINFO sei = { sizeof(sei) }; |
- sei.fMask = SEE_MASK_FLAG_LOG_USAGE; |
- sei.nShow = SW_SHOWNORMAL; |
- sei.lpFile = file.c_str(); |
- sei.lpDirectory = L""; |
- sei.lpParameters = url.c_str(); |
- ShellExecuteEx(&sei); |
-} |
- |
-void ChromeAppViewAsh::OnSetCursor(HCURSOR cursor) { |
- ::SetCursor(cursor); |
- last_cursor_ = cursor; |
-} |
- |
-void ChromeAppViewAsh::OnDisplayFileOpenDialog( |
- const base::string16& title, |
- const base::string16& filter, |
- const base::FilePath& default_path, |
- bool allow_multiple_files) { |
- DVLOG(1) << __FUNCTION__; |
- |
- // The OpenFilePickerSession instance is deleted when we receive a |
- // callback from the OpenFilePickerSession class about the completion of the |
- // operation. |
- FilePickerSessionBase* file_picker_ = |
- new OpenFilePickerSession(this, |
- title, |
- filter, |
- default_path, |
- allow_multiple_files); |
- file_picker_->Run(); |
-} |
- |
-void ChromeAppViewAsh::OnDisplayFileSaveAsDialog( |
- const MetroViewerHostMsg_SaveAsDialogParams& params) { |
- DVLOG(1) << __FUNCTION__; |
- |
- // The SaveFilePickerSession instance is deleted when we receive a |
- // callback from the SaveFilePickerSession class about the completion of the |
- // operation. |
- FilePickerSessionBase* file_picker_ = |
- new SaveFilePickerSession(this, params); |
- file_picker_->Run(); |
-} |
- |
-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 |
- // operation. |
- FilePickerSessionBase* file_picker_ = new FolderPickerSession(this, title); |
- file_picker_->Run(); |
-} |
- |
-void ChromeAppViewAsh::OnSetCursorPos(int x, int y) { |
- if (ui_channel_) { |
- ::SetCursorPos(x, y); |
- DVLOG(1) << "In UI OnSetCursorPos: " << x << ", " << y; |
- ui_channel_->Send(new MetroViewerHostMsg_SetCursorPosAck()); |
- // Generate a fake mouse move which matches the SetCursor coordinates as |
- // the browser expects to receive a mouse move for these coordinates. |
- // It is not clear why we don't receive a real mouse move in response to |
- // the SetCursorPos calll above. |
- ui_channel_->Send(new MetroViewerHostMsg_MouseMoved(x, y, 0)); |
- } |
-} |
- |
-void ChromeAppViewAsh::OnOpenFileCompleted( |
- OpenFilePickerSession* open_file_picker, |
- bool success) { |
- DVLOG(1) << __FUNCTION__; |
- DVLOG(1) << "Success: " << success; |
- if (ui_channel_) { |
- if (open_file_picker->allow_multi_select()) { |
- ui_channel_->Send(new MetroViewerHostMsg_MultiFileOpenDone( |
- success, open_file_picker->filenames())); |
- } else { |
- ui_channel_->Send(new MetroViewerHostMsg_FileOpenDone( |
- success, base::FilePath(open_file_picker->result()))); |
- } |
- } |
- delete open_file_picker; |
-} |
- |
-void ChromeAppViewAsh::OnSaveFileCompleted( |
- SaveFilePickerSession* save_file_picker, |
- bool success) { |
- DVLOG(1) << __FUNCTION__; |
- DVLOG(1) << "Success: " << success; |
- if (ui_channel_) { |
- ui_channel_->Send(new MetroViewerHostMsg_FileSaveAsDone( |
- success, |
- base::FilePath(save_file_picker->result()), |
- save_file_picker->filter_index())); |
- } |
- delete save_file_picker; |
-} |
- |
-void ChromeAppViewAsh::OnFolderPickerCompleted( |
- FolderPickerSession* folder_picker, |
- bool success) { |
- DVLOG(1) << __FUNCTION__; |
- DVLOG(1) << "Success: " << success; |
- if (ui_channel_) { |
- ui_channel_->Send(new MetroViewerHostMsg_SelectFolderDone( |
- success, |
- base::FilePath(folder_picker->result()))); |
- } |
- delete folder_picker; |
-} |
- |
-void ChromeAppViewAsh::OnImeCancelComposition() { |
- if (!text_service_) |
- return; |
- text_service_->CancelComposition(); |
-} |
- |
-void ChromeAppViewAsh::OnImeUpdateTextInputClient( |
- const std::vector<int32_t>& input_scopes, |
- const std::vector<metro_viewer::CharacterBounds>& character_bounds) { |
- if (!text_service_) |
- return; |
- text_service_->OnDocumentChanged(input_scopes, character_bounds); |
-} |
- |
-void ChromeAppViewAsh::OnImePopupChanged(ImePopupObserver::EventType event) { |
- if (!ui_channel_) |
- return; |
- switch (event) { |
- case ImePopupObserver::kPopupShown: |
- ui_channel_->Send(new MetroViewerHostMsg_ImeCandidatePopupChanged(true)); |
- return; |
- case ImePopupObserver::kPopupHidden: |
- ui_channel_->Send(new MetroViewerHostMsg_ImeCandidatePopupChanged(false)); |
- return; |
- case ImePopupObserver::kPopupUpdated: |
- // TODO(kochi): Support this event for W3C IME API proposal. |
- // See crbug.com/238585. |
- return; |
- default: |
- NOTREACHED() << "unknown event type: " << event; |
- return; |
- } |
-} |
- |
-// 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(); |
- |
- HWND core_window = core_window_hwnd(); |
- ::PostMessage(core_window, WM_CLOSE, 0, 0); |
- |
- globals.app_exit->Exit(); |
- } |
-} |
- |
-void ChromeAppViewAsh::OnInputSourceChanged() { |
- if (!input_source_) |
- return; |
- |
- DCHECK(ui_channel_); |
- |
- LANGID langid = 0; |
- bool is_ime = false; |
- if (!input_source_->GetActiveSource(&langid, &is_ime)) { |
- LOG(ERROR) << "GetActiveSource failed"; |
- return; |
- } |
- ui_channel_->Send(new MetroViewerHostMsg_ImeInputSourceChanged(langid, |
- is_ime)); |
-} |
- |
-void ChromeAppViewAsh::OnCompositionChanged( |
- const base::string16& text, |
- int32_t selection_start, |
- int32_t selection_end, |
- const std::vector<metro_viewer::UnderlineInfo>& underlines) { |
- ui_channel_->Send(new MetroViewerHostMsg_ImeCompositionChanged( |
- text, selection_start, selection_end, underlines)); |
-} |
- |
-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_t flags, |
- ui::EventFlags changed_button, |
- bool is_horizontal_wheel) { |
- if (!ui_channel_) |
- return; |
- MetroViewerHostMsg_MouseButtonParams params; |
- params.x = static_cast<int32_t>(x); |
- params.y = static_cast<int32_t>(y); |
- params.extra = static_cast<int32_t>(extra); |
- params.event_type = event_type; |
- params.flags = static_cast<int32_t>(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_t 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) { |
- DVLOG(1) << __FUNCTION__; |
- // Note: If doing more work in this function, you migth need to call |
- // get_PreviousExecutionState() and skip the work if the result is |
- // ApplicationExecutionState_Running and globals.previous_state is too. |
- args->get_PreviousExecutionState(&globals.previous_state); |
- DVLOG(1) << "Previous Execution State: " << globals.previous_state; |
- |
- winapp::Activation::ActivationKind activation_kind; |
- CheckHR(args->get_Kind(&activation_kind)); |
- DVLOG(1) << "Activation kind: " << activation_kind; |
- |
- if (activation_kind == winapp::Activation::ActivationKind_Search) |
- HandleSearchRequest(args); |
- else if (activation_kind == winapp::Activation::ActivationKind_Protocol) |
- HandleProtocolRequest(args); |
- else |
- LaunchChromeBrowserProcess(NULL, args); |
- // We call ICoreWindow::Activate after the handling for the search/protocol |
- // requests because Chrome can be launched to handle a search request which |
- // in turn launches the chrome browser process in desktop mode via |
- // ShellExecute. If we call ICoreWindow::Activate before this, then |
- // Windows kills the metro chrome process when it calls ShellExecute. Seems |
- // to be a bug. |
- window_->Activate(); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, |
- winui::Core::IPointerEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
- HRESULT hr = pointer.Init(args); |
- if (FAILED(hr)) |
- return hr; |
- |
- if (pointer.IsMouse()) { |
- // If the mouse was moved towards the charms or the OS specific section, |
- // the cursor may change from what the browser last set. Restore it here. |
- if (::GetCursor() != last_cursor_) |
- SetCursor(last_cursor_); |
- |
- GenerateMouseEventFromMoveIfNecessary(pointer); |
- ui_channel_->Send(new MetroViewerHostMsg_MouseMoved( |
- pointer.x(), |
- pointer.y(), |
- mouse_down_flags_ | GetKeyboardEventFlags())); |
- } else { |
- DCHECK(pointer.IsTouch()); |
- ui_channel_->Send(new MetroViewerHostMsg_TouchMoved(pointer.x(), |
- pointer.y(), |
- pointer.timestamp(), |
- pointer.pointer_id())); |
- } |
- return S_OK; |
-} |
- |
-// NOTE: From experimentation, it seems like Metro only sends a PointerPressed |
-// 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. Intermediary |
-// presses and releases are tracked in OnPointMoved(). |
-HRESULT ChromeAppViewAsh::OnPointerPressed( |
- winui::Core::ICoreWindow* sender, |
- winui::Core::IPointerEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
- HRESULT hr = pointer.Init(args); |
- if (FAILED(hr)) |
- return hr; |
- |
- if (pointer.IsMouse()) { |
- 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(), |
- pointer.y(), |
- pointer.timestamp(), |
- pointer.pointer_id())); |
- } |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnPointerReleased( |
- winui::Core::ICoreWindow* sender, |
- winui::Core::IPointerEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
- HRESULT hr = pointer.Init(args); |
- if (FAILED(hr)) |
- return hr; |
- |
- if (pointer.IsMouse()) { |
- mouse_down_flags_ = ui::EF_NONE; |
- SendMouseButton(pointer.x(), pointer.y(), 0, ui::ET_MOUSE_RELEASED, |
- static_cast<uint32_t>(pointer.changed_button()) | |
- GetKeyboardEventFlags(), |
- pointer.changed_button(), pointer.is_horizontal_wheel()); |
- } else { |
- DCHECK(pointer.IsTouch()); |
- ui_channel_->Send(new MetroViewerHostMsg_TouchUp(pointer.x(), |
- pointer.y(), |
- pointer.timestamp(), |
- pointer.pointer_id())); |
- } |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnWheel( |
- winui::Core::ICoreWindow* sender, |
- winui::Core::IPointerEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
- HRESULT hr = pointer.Init(args); |
- if (FAILED(hr)) |
- return hr; |
- DCHECK(pointer.IsMouse()); |
- SendMouseButton(pointer.x(), pointer.y(), pointer.wheel_delta(), |
- ui::ET_MOUSEWHEEL, GetKeyboardEventFlags(), ui::EF_NONE, |
- pointer.is_horizontal_wheel()); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnKeyDown( |
- winui::Core::ICoreWindow* sender, |
- winui::Core::IKeyEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- winsys::VirtualKey virtual_key; |
- HRESULT hr = args->get_VirtualKey(&virtual_key); |
- if (FAILED(hr)) |
- return hr; |
- winui::Core::CorePhysicalKeyStatus status; |
- hr = args->get_KeyStatus(&status); |
- if (FAILED(hr)) |
- return hr; |
- |
- ui_channel_->Send(new MetroViewerHostMsg_KeyDown(virtual_key, |
- status.RepeatCount, |
- status.ScanCode, |
- GetKeyboardEventFlags())); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnKeyUp( |
- winui::Core::ICoreWindow* sender, |
- winui::Core::IKeyEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- winsys::VirtualKey virtual_key; |
- HRESULT hr = args->get_VirtualKey(&virtual_key); |
- if (FAILED(hr)) |
- return hr; |
- winui::Core::CorePhysicalKeyStatus status; |
- hr = args->get_KeyStatus(&status); |
- if (FAILED(hr)) |
- return hr; |
- |
- ui_channel_->Send(new MetroViewerHostMsg_KeyUp(virtual_key, |
- status.RepeatCount, |
- status.ScanCode, |
- GetKeyboardEventFlags())); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown( |
- winui::Core::ICoreDispatcher* sender, |
- winui::Core::IAcceleratorKeyEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- winsys::VirtualKey virtual_key; |
- HRESULT hr = args->get_VirtualKey(&virtual_key); |
- if (FAILED(hr)) |
- return hr; |
- winui::Core::CorePhysicalKeyStatus status; |
- hr = args->get_KeyStatus(&status); |
- if (FAILED(hr)) |
- return hr; |
- |
- winui::Core::CoreAcceleratorKeyEventType event_type; |
- hr = args->get_EventType(&event_type); |
- if (FAILED(hr)) |
- return hr; |
- |
- uint32_t keyboard_flags = GetKeyboardEventFlags(); |
- |
- switch (event_type) { |
- case winui::Core::CoreAcceleratorKeyEventType_SystemCharacter: |
- ui_channel_->Send(new MetroViewerHostMsg_Character(virtual_key, |
- status.RepeatCount, |
- status.ScanCode, |
- keyboard_flags)); |
- 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; |
- // Don't send the EF_ALT_DOWN modifier along with the IPC message for |
- // the Alt or F10 key. The accelerator for VKEY_MENU is registered |
- // without modifiers in Chrome for historical reasons. Not sending the |
- // EF_ALT_DOWN modifier ensures that the accelerator is processed |
- // correctly. |
- if (virtual_key == winsys::VirtualKey_Menu) |
- keyboard_flags &= ~ui::EF_ALT_DOWN; |
- ui_channel_->Send(new MetroViewerHostMsg_KeyDown(virtual_key, |
- status.RepeatCount, |
- status.ScanCode, |
- keyboard_flags)); |
- break; |
- |
- case winui::Core::CoreAcceleratorKeyEventType_SystemKeyUp: |
- ui_channel_->Send(new MetroViewerHostMsg_KeyUp(virtual_key, |
- status.RepeatCount, |
- status.ScanCode, |
- keyboard_flags)); |
- break; |
- |
- default: |
- break; |
- } |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnCharacterReceived( |
- winui::Core::ICoreWindow* sender, |
- winui::Core::ICharacterReceivedEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- unsigned int char_code = 0; |
- HRESULT hr = args->get_KeyCode(&char_code); |
- if (FAILED(hr)) |
- return hr; |
- |
- winui::Core::CorePhysicalKeyStatus status; |
- hr = args->get_KeyStatus(&status); |
- if (FAILED(hr)) |
- return hr; |
- |
- ui_channel_->Send(new MetroViewerHostMsg_Character(char_code, |
- status.RepeatCount, |
- status.ScanCode, |
- GetKeyboardEventFlags())); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnWindowActivated( |
- winui::Core::ICoreWindow* sender, |
- winui::Core::IWindowActivatedEventArgs* args) { |
- if (!ui_channel_) |
- return S_OK; |
- |
- if (args) { |
- winui::Core::CoreWindowActivationState state; |
- HRESULT hr = args->get_WindowActivationState(&state); |
- if (FAILED(hr)) |
- return hr; |
- |
- // Treat both full activation (Ash was reopened from the Start Screen or |
- // from any other Metro entry point in Windows) and pointer activation |
- // (user clicked back in Ash after using another app on another monitor) |
- // the same. |
- if (state == winui::Core::CoreWindowActivationState_CodeActivated || |
- state == winui::Core::CoreWindowActivationState_PointerActivated) { |
- ui_channel_->Send(new MetroViewerHostMsg_WindowActivated(false)); |
- } |
- } else { |
- // On Windows 7, we force a repaint when the window is activated. |
- ui_channel_->Send(new MetroViewerHostMsg_WindowActivated(true)); |
- } |
- if (text_service_) |
- text_service_->OnWindowActivated(); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::HandleSearchRequest( |
- winapp::Activation::IActivatedEventArgs* args) { |
- mswr::ComPtr<winapp::Activation::ISearchActivatedEventArgs> search_args; |
- CheckHR(args->QueryInterface( |
- winapp::Activation::IID_ISearchActivatedEventArgs, &search_args)); |
- |
- if (!ui_channel_) { |
- DVLOG(1) << "Launched to handle search request"; |
- LaunchChromeBrowserProcess(L"--windows8-search", args); |
- } |
- |
- mswrw::HString search_string; |
- CheckHR(search_args->get_QueryText(search_string.GetAddressOf())); |
- base::string16 search_text(MakeStdWString(search_string.Get())); |
- |
- ui_loop_.PostTask(FROM_HERE, |
- base::Bind(&ChromeAppViewAsh::OnSearchRequest, |
- base::Unretained(this), |
- search_text)); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::HandleProtocolRequest( |
- winapp::Activation::IActivatedEventArgs* args) { |
- DVLOG(1) << __FUNCTION__; |
- if (!ui_channel_) |
- DVLOG(1) << "Launched to handle url request"; |
- |
- mswr::ComPtr<winapp::Activation::IProtocolActivatedEventArgs> |
- protocol_args; |
- CheckHR(args->QueryInterface( |
- winapp::Activation::IID_IProtocolActivatedEventArgs, |
- &protocol_args)); |
- |
- mswr::ComPtr<winfoundtn::IUriRuntimeClass> uri; |
- protocol_args->get_Uri(&uri); |
- mswrw::HString url; |
- uri->get_AbsoluteUri(url.GetAddressOf()); |
- base::string16 actual_url(MakeStdWString(url.Get())); |
- DVLOG(1) << "Received url request: " << actual_url; |
- |
- ui_loop_.PostTask(FROM_HERE, |
- base::Bind(&ChromeAppViewAsh::OnNavigateToUrl, |
- base::Unretained(this), |
- actual_url)); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppViewAsh::OnEdgeGestureCompleted( |
- winui::Input::IEdgeGesture* gesture, |
- winui::Input::IEdgeGestureEventArgs* args) { |
- if (ui_channel_) |
- ui_channel_->Send(new MetroViewerHostMsg_EdgeGesture()); |
- return S_OK; |
-} |
- |
-void ChromeAppViewAsh::OnSearchRequest(const base::string16& search_string) { |
- if (ui_channel_) |
- ui_channel_->Send(new MetroViewerHostMsg_SearchRequest(search_string)); |
-} |
- |
-void ChromeAppViewAsh::OnNavigateToUrl(const base::string16& url) { |
- if (ui_channel_) |
- ui_channel_->Send(new MetroViewerHostMsg_OpenURL(url)); |
-} |
- |
-HRESULT ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow* sender, |
- winui::Core::IWindowSizeChangedEventArgs* args) { |
- if (!window_ || !ui_channel_) { |
- return S_OK; |
- } |
- |
- // 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_t cx = static_cast<uint32_t>(rect.right - rect.left); |
- uint32_t cy = static_cast<uint32_t>(rect.bottom - rect.top); |
- |
- DVLOG(1) << "Window size changed: width=" << cx << ", height=" << cy; |
- ui_channel_->Send(new MetroViewerHostMsg_WindowSizeChanged(cx, cy)); |
- return S_OK; |
-} |
- |
-void ChromeAppViewAsh::StartChromeOSMode() { |
- static int ms_elapsed = 0; |
- |
- if (!IPC::Channel::IsNamedServerInitialized( |
- win8::kMetroViewerIPCChannelName) && ms_elapsed < 10000) { |
- ms_elapsed += 100; |
- ui_loop_.PostDelayedTask(FROM_HERE, |
- base::Bind(base::IgnoreResult(&ChromeAppViewAsh::StartChromeOSMode), |
- base::Unretained(this)), |
- base::TimeDelta::FromMilliseconds(kChromeChannelPollTimerMs)); |
- return; |
- } |
- |
- if (!IPC::Channel::IsNamedServerInitialized( |
- win8::kMetroViewerIPCChannelName)) { |
- DVLOG(1) << "Failed to connect to chrome channel : " |
- << win8::kMetroViewerIPCChannelName; |
- DVLOG(1) << "Exiting. Elapsed time :" << ms_elapsed; |
- PostMessage(core_window_hwnd_, WM_CLOSE, 0, 0); |
- return; |
- } |
- |
- DVLOG(1) << "Found channel : " << win8::kMetroViewerIPCChannelName; |
- |
- DCHECK(channel_listener_); |
- |
- // In Aura mode we create an IPC channel to the browser, then ask it to |
- // connect to us. |
- ui_channel_ = |
- IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName, |
- IPC::Channel::MODE_NAMED_CLIENT, |
- channel_listener_, |
- io_thread_->task_runner()); |
- DVLOG(1) << "Created channel proxy"; |
- |
- // 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_), |
- win32_dpi_scale_)); |
- DVLOG(1) << "ICoreWindow sent " << core_window_hwnd_; |
- |
- // Send an initial size message so that the Ash root window host gets sized |
- // correctly. |
- RECT rect = {0}; |
- ::GetWindowRect(core_window_hwnd_, &rect); |
- ui_channel_->Send( |
- new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left, |
- rect.bottom - rect.top)); |
- |
- input_source_ = metro_driver::InputSource::Create(); |
- if (input_source_) { |
- input_source_->AddObserver(this); |
- // Send an initial input source. |
- OnInputSourceChanged(); |
- } |
- |
- // Start receiving IME popup window notifications. |
- metro_driver::AddImePopupObserver(this); |
- |
- DVLOG(1) << "Channel setup complete"; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-ChromeAppViewFactory::ChromeAppViewFactory( |
- 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)); |
- globals.app_exit = app_exit.Detach(); |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppViewFactory::CreateView(winapp::Core::IFrameworkView** view) { |
- *view = mswr::Make<ChromeAppViewAsh>().Detach(); |
- return (*view) ? S_OK : E_OUTOFMEMORY; |
-} |