diff options
Diffstat (limited to 'win8/metro_driver/chrome_app_view_ash.cc')
-rw-r--r-- | win8/metro_driver/chrome_app_view_ash.cc | 1464 |
1 files changed, 0 insertions, 1464 deletions
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 01f9ba2..0000000 --- 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; -} |