Index: win8/metro_driver/chrome_app_view.cc |
diff --git a/win8/metro_driver/chrome_app_view.cc b/win8/metro_driver/chrome_app_view.cc |
deleted file mode 100644 |
index 051f37f776c82ecad85687b3d44b813e78d4a09b..0000000000000000000000000000000000000000 |
--- a/win8/metro_driver/chrome_app_view.cc |
+++ /dev/null |
@@ -1,1216 +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.h" |
- |
-#include <corewindow.h> |
-#include <windows.applicationModel.datatransfer.h> |
-#include <windows.foundation.h> |
- |
-#include <algorithm> |
- |
-#include "base/bind.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/win/metro.h" |
-// This include allows to send WM_SYSCOMMANDs to chrome. |
-#include "chrome/app/chrome_command_ids.h" |
-#include "ui/base/ui_base_switches.h" |
-#include "ui/gfx/native_widget_types.h" |
-#include "ui/metro_viewer/metro_viewer_messages.h" |
-#include "win8/metro_driver/metro_driver.h" |
-#include "win8/metro_driver/winrt_utils.h" |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winapp::Core::CoreApplicationView*, |
- winapp::Activation::IActivatedEventArgs*> ActivatedHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::WindowSizeChangedEventArgs*> SizeChangedHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Input::EdgeGesture*, |
- winui::Input::EdgeGestureEventArgs*> EdgeEventHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winapp::DataTransfer::DataTransferManager*, |
- winapp::DataTransfer::DataRequestedEventArgs*> ShareDataRequestedHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::ViewManagement::InputPane*, |
- winui::ViewManagement::InputPaneVisibilityEventArgs*> |
- InputPaneEventHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::PointerEventArgs*> PointerEventHandler; |
- |
-typedef winfoundtn::ITypedEventHandler< |
- winui::Core::CoreWindow*, |
- winui::Core::KeyEventArgs*> KeyEventHandler; |
- |
-struct Globals globals; |
- |
-// TODO(ananta) |
-// Remove this once we consolidate metro driver with chrome. |
-const wchar_t kMetroGetCurrentTabInfoMessage[] = |
- L"CHROME_METRO_GET_CURRENT_TAB_INFO"; |
- |
-static const int kFlipWindowsHotKeyId = 0x0000baba; |
- |
-static const int kAnimateWindowTimeoutMs = 200; |
- |
-static const int kCheckOSKDelayMs = 300; |
- |
-const wchar_t kOSKClassName[] = L"IPTip_Main_Window"; |
- |
-static const int kOSKAdjustmentOffset = 20; |
- |
-const wchar_t kChromeSubclassWindowProp[] = L"MetroChromeWindowProc"; |
- |
-namespace { |
- |
-enum Modifier { |
- NONE, |
- SHIFT = 1, |
- CONTROL = 2, |
- ALT = 4 |
-}; |
- |
-// Helper function to send keystrokes via the SendInput function. |
-// Params: |
-// mnemonic_char: The keystroke to be sent. |
-// modifiers: Combination with Alt, Ctrl, Shift, etc. |
-// extended: whether this is an extended key. |
-// unicode: whether this is a unicode key. |
-void SendMnemonic(WORD mnemonic_char, Modifier modifiers, bool extended, |
- bool unicode) { |
- INPUT keys[4] = {0}; // 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); |
- |
- if (extended) |
- keys[key_count].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; |
- if (unicode) |
- keys[key_count].ki.dwFlags |= KEYEVENTF_UNICODE; |
- 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); |
- } |
- } |
-} |
- |
-// Helper function to Exit metro chrome cleanly. If we are in the foreground |
-// then we try and exit by sending an Alt+F4 key combination to the core |
-// window which ensures that the chrome application tile does not show up in |
-// the running metro apps list on the top left corner. We have seen cases |
-// where this does work. To workaround that we invoke the |
-// ICoreApplicationExit::Exit function in a background delayed task which |
-// ensures that chrome exits. |
-void MetroExit(bool send_alt_f4_mnemonic) { |
- if (send_alt_f4_mnemonic && globals.view && |
- globals.view->core_window_hwnd() == ::GetForegroundWindow()) { |
- DVLOG(1) << "We are in the foreground. Exiting via Alt F4"; |
- SendMnemonic(VK_F4, ALT, false, false); |
- DWORD core_window_process_id = 0; |
- DWORD core_window_thread_id = GetWindowThreadProcessId( |
- globals.view->core_window_hwnd(), &core_window_process_id); |
- if (core_window_thread_id != ::GetCurrentThreadId()) { |
- globals.appview_task_runner->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&MetroExit, false), |
- base::TimeDelta::FromMilliseconds(100)); |
- } |
- } else { |
- globals.app_exit->Exit(); |
- } |
-} |
- |
-void AdjustToFitWindow(HWND hwnd, int flags) { |
- RECT rect = {0}; |
- ::GetWindowRect(globals.view->core_window_hwnd() , &rect); |
- int cx = rect.right - rect.left; |
- int cy = rect.bottom - rect.top; |
- |
- ::SetWindowPos(hwnd, HWND_TOP, |
- rect.left, rect.top, cx, cy, |
- SWP_NOZORDER | flags); |
-} |
- |
-LRESULT CALLBACK ChromeWindowProc(HWND window, |
- UINT message, |
- WPARAM wp, |
- LPARAM lp) { |
- if (message == WM_SETCURSOR) { |
- // Override the WM_SETCURSOR message to avoid showing the resize cursor |
- // as the mouse moves to the edge of the screen. |
- switch (LOWORD(lp)) { |
- case HTBOTTOM: |
- case HTBOTTOMLEFT: |
- case HTBOTTOMRIGHT: |
- case HTLEFT: |
- case HTRIGHT: |
- case HTTOP: |
- case HTTOPLEFT: |
- case HTTOPRIGHT: |
- lp = MAKELPARAM(HTCLIENT, HIWORD(lp)); |
- break; |
- default: |
- break; |
- } |
- } |
- |
- WNDPROC old_proc = reinterpret_cast<WNDPROC>( |
- ::GetProp(window, kChromeSubclassWindowProp)); |
- DCHECK(old_proc); |
- return CallWindowProc(old_proc, window, message, wp, lp); |
-} |
- |
-void AdjustFrameWindowStyleForMetro(HWND hwnd) { |
- DVLOG(1) << __FUNCTION__; |
- // Ajust the frame so the live preview works and the frame buttons dissapear. |
- ::SetWindowLong(hwnd, GWL_STYLE, |
- WS_POPUP | (::GetWindowLong(hwnd, GWL_STYLE) & |
- ~(WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU))); |
- ::SetWindowLong(hwnd, GWL_EXSTYLE, |
- ::GetWindowLong(hwnd, GWL_EXSTYLE) & ~(WS_EX_DLGMODALFRAME | |
- WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); |
- |
- // Subclass the wndproc of the frame window, if it's not already there. |
- if (::GetProp(hwnd, kChromeSubclassWindowProp) == NULL) { |
- WNDPROC old_chrome_proc = |
- reinterpret_cast<WNDPROC>(::SetWindowLongPtr( |
- hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(ChromeWindowProc))); |
- ::SetProp(hwnd, kChromeSubclassWindowProp, old_chrome_proc); |
- } |
- AdjustToFitWindow(hwnd, SWP_FRAMECHANGED | SWP_NOACTIVATE); |
-} |
- |
-void SetFrameWindowInternal(HWND hwnd) { |
- DVLOG(1) << __FUNCTION__ << ", hwnd=" << LONG_PTR(hwnd); |
- |
- HWND current_top_frame = |
- !globals.host_windows.empty() ? globals.host_windows.front().first : NULL; |
- if (hwnd != current_top_frame && IsWindow(current_top_frame)) { |
- DVLOG(1) << "Hiding current top window, hwnd=" |
- << LONG_PTR(current_top_frame); |
- ::ShowWindow(current_top_frame, SW_HIDE); |
- } |
- |
- // Visible frame windows always need to be at the head of the list. |
- // Check if the window being shown already exists in our global list. |
- // If no then add it at the head of the list. |
- // If yes, retrieve the osk window scrolled state, remove the window from the |
- // list and readd it at the head. |
- std::list<std::pair<HWND, bool> >::iterator index = |
- std::find_if(globals.host_windows.begin(), globals.host_windows.end(), |
- [hwnd](std::pair<HWND, bool>& item) { |
- return (item.first == hwnd); |
- }); |
- |
- bool window_scrolled_state = false; |
- bool new_window = (index == globals.host_windows.end()); |
- if (!new_window) { |
- window_scrolled_state = index->second; |
- globals.host_windows.erase(index); |
- } |
- |
- globals.host_windows.push_front(std::make_pair(hwnd, window_scrolled_state)); |
- |
- if (new_window) { |
- AdjustFrameWindowStyleForMetro(hwnd); |
- } else { |
- DVLOG(1) << "Adjusting new top window to core window size"; |
- AdjustToFitWindow(hwnd, 0); |
- } |
- if (globals.view->GetViewState() == |
- winui::ViewManagement::ApplicationViewState_Snapped) { |
- DVLOG(1) << "Enabling Metro snap state on new window: " << hwnd; |
- ::PostMessageW(hwnd, WM_SYSCOMMAND, IDC_METRO_SNAP_ENABLE, 0); |
- } |
-} |
- |
-void CloseFrameWindowInternal(HWND hwnd) { |
- DVLOG(1) << __FUNCTION__ << ", hwnd=" << LONG_PTR(hwnd); |
- |
- globals.host_windows.remove_if([hwnd](std::pair<HWND, bool>& item) { |
- return (item.first == hwnd); |
- }); |
- |
- if (globals.host_windows.size() > 0) { |
- DVLOG(1) << "Making new top frame window visible:" |
- << reinterpret_cast<int>(globals.host_windows.front().first); |
- AdjustToFitWindow(globals.host_windows.front().first, SWP_SHOWWINDOW); |
- } else { |
- // time to quit |
- DVLOG(1) << "Last host window closed. Calling Exit()."; |
- MetroExit(true); |
- } |
-} |
- |
-void FlipFrameWindowsInternal() { |
- DVLOG(1) << __FUNCTION__; |
- // Get the first window in the frame windows queue and push it to the end. |
- // Metroize the next window in the queue. |
- if (globals.host_windows.size() > 1) { |
- std::pair<HWND, bool> current_top_window = globals.host_windows.front(); |
- globals.host_windows.pop_front(); |
- |
- DVLOG(1) << "Making new top frame window visible:" |
- << reinterpret_cast<int>(globals.host_windows.front().first); |
- |
- AdjustToFitWindow(globals.host_windows.front().first, SWP_SHOWWINDOW); |
- |
- DVLOG(1) << "Hiding current top window:" |
- << reinterpret_cast<int>(current_top_window.first); |
- AnimateWindow(current_top_window.first, kAnimateWindowTimeoutMs, |
- AW_HIDE | AW_HOR_POSITIVE | AW_SLIDE); |
- |
- globals.host_windows.push_back(current_top_window); |
- } |
-} |
- |
-} // namespace |
- |
-void ChromeAppView::DisplayNotification( |
- const ToastNotificationHandler::DesktopNotification& notification) { |
- DVLOG(1) << __FUNCTION__; |
- |
- if (IsValidNotification(notification.id)) { |
- NOTREACHED() << "Duplicate notification id passed in."; |
- return; |
- } |
- |
- base::AutoLock lock(notification_lock_); |
- |
- ToastNotificationHandler* notification_handler = |
- new ToastNotificationHandler; |
- |
- notification_map_[notification.id].reset(notification_handler); |
- notification_handler->DisplayNotification(notification); |
-} |
- |
-void ChromeAppView::CancelNotification(const std::string& notification) { |
- DVLOG(1) << __FUNCTION__; |
- |
- base::AutoLock lock(notification_lock_); |
- |
- NotificationMap::iterator index = notification_map_.find(notification); |
- if (index == notification_map_.end()) { |
- NOTREACHED() << "Invalid notification:" << notification.c_str(); |
- return; |
- } |
- |
- scoped_ptr<ToastNotificationHandler> notification_handler( |
- index->second.release()); |
- |
- notification_map_.erase(index); |
- |
- notification_handler->CancelNotification(); |
-} |
- |
-// Returns true if the notification passed in is valid. |
-bool ChromeAppView::IsValidNotification(const std::string& notification) { |
- DVLOG(1) << __FUNCTION__; |
- |
- base::AutoLock lock(notification_lock_); |
- return notification_map_.find(notification) != notification_map_.end(); |
-} |
- |
-void ChromeAppView::ShowDialogBox( |
- const MetroDialogBox::DialogBoxInfo& dialog_box_info) { |
- VLOG(1) << __FUNCTION__; |
- dialog_box_.Show(dialog_box_info); |
-} |
- |
-void ChromeAppView::DismissDialogBox() { |
- VLOG(1) << __FUNCTION__; |
- dialog_box_.Dismiss(); |
-} |
- |
-// static |
-HRESULT ChromeAppView::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 ChromeAppView::SetFullscreen(bool fullscreen) { |
- VLOG(1) << __FUNCTION__; |
- |
- if (osk_offset_adjustment_) { |
- VLOG(1) << "Scrolling the window down by: " |
- << osk_offset_adjustment_; |
- |
- ::ScrollWindowEx(globals.host_windows.front().first, |
- 0, |
- osk_offset_adjustment_, |
- NULL, |
- NULL, |
- NULL, |
- NULL, |
- SW_INVALIDATE | SW_SCROLLCHILDREN); |
- osk_offset_adjustment_ = 0; |
- } |
-} |
- |
-winui::ViewManagement::ApplicationViewState ChromeAppView::GetViewState() { |
- winui::ViewManagement::ApplicationViewState view_state = |
- winui::ViewManagement::ApplicationViewState_FullScreenLandscape; |
- app_view_->get_Value(&view_state); |
- return view_state; |
-} |
- |
-void UnsnapHelper() { |
- ChromeAppView::Unsnap(); |
-} |
- |
-extern "C" __declspec(dllexport) |
-void MetroUnsnap() { |
- DVLOG(1) << __FUNCTION__; |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind(&UnsnapHelper)); |
-} |
- |
-extern "C" __declspec(dllexport) |
-HWND GetRootWindow() { |
- DVLOG(1) << __FUNCTION__; |
- return globals.view->core_window_hwnd(); |
-} |
- |
-extern "C" __declspec(dllexport) |
-void SetFrameWindow(HWND hwnd) { |
- DVLOG(1) << __FUNCTION__ << ", hwnd=" << LONG_PTR(hwnd); |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind(&SetFrameWindowInternal, hwnd)); |
-} |
- |
-// TODO(ananta) |
-// Handle frame window close by deleting it from the window list and making the |
-// next guy visible. |
-extern "C" __declspec(dllexport) |
- void CloseFrameWindow(HWND hwnd) { |
- DVLOG(1) << __FUNCTION__ << ", hwnd=" << LONG_PTR(hwnd); |
- |
- // This is a hack to ensure that the BrowserViewLayout code layout happens |
- // just at the right time to hide the switcher button if it is visible. |
- globals.appview_task_runner->PostDelayedTask( |
- FROM_HERE, base::Bind(&CloseFrameWindowInternal, hwnd), |
- base::TimeDelta::FromMilliseconds(50)); |
-} |
- |
-// Returns the initial url. This returns a valid url only if we were launched |
-// into metro via a url navigation. |
-extern "C" __declspec(dllexport) |
-const wchar_t* GetInitialUrl() { |
- DVLOG(1) << __FUNCTION__; |
- bool was_initial_activation = globals.is_initial_activation; |
- globals.is_initial_activation = false; |
- if (!was_initial_activation || globals.navigation_url.empty()) |
- return L""; |
- |
- const wchar_t* initial_url = globals.navigation_url.c_str(); |
- DVLOG(1) << initial_url; |
- return initial_url; |
-} |
- |
-// Returns the initial search string. This returns a valid url only if we were |
-// launched into metro via the search charm |
-extern "C" __declspec(dllexport) |
-const wchar_t* GetInitialSearchString() { |
- DVLOG(1) << __FUNCTION__; |
- bool was_initial_activation = globals.is_initial_activation; |
- globals.is_initial_activation = false; |
- if (!was_initial_activation || globals.search_string.empty()) |
- return L""; |
- |
- const wchar_t* initial_search_string = globals.search_string.c_str(); |
- DVLOG(1) << initial_search_string; |
- return initial_search_string; |
-} |
- |
-// Returns the launch type. |
-extern "C" __declspec(dllexport) |
-base::win::MetroLaunchType GetLaunchType( |
- base::win::MetroPreviousExecutionState* previous_state) { |
- if (previous_state) { |
- *previous_state = static_cast<base::win::MetroPreviousExecutionState>( |
- globals.previous_state); |
- } |
- return static_cast<base::win::MetroLaunchType>( |
- globals.initial_activation_kind); |
-} |
- |
-extern "C" __declspec(dllexport) |
-void FlipFrameWindows() { |
- DVLOG(1) << __FUNCTION__; |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind(&FlipFrameWindowsInternal)); |
-} |
- |
-extern "C" __declspec(dllexport) |
-void DisplayNotification(const char* origin_url, const char* icon_url, |
- const wchar_t* title, const wchar_t* body, |
- const wchar_t* display_source, |
- const char* notification_id, |
- base::win::MetroNotificationClickedHandler handler, |
- const wchar_t* handler_context) { |
- // TODO(ananta) |
- // Needs implementation. |
- DVLOG(1) << __FUNCTION__; |
- |
- ToastNotificationHandler::DesktopNotification notification(origin_url, |
- icon_url, |
- title, |
- body, |
- display_source, |
- notification_id, |
- handler, |
- handler_context); |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppView::DisplayNotification, |
- globals.view, notification)); |
-} |
- |
-extern "C" __declspec(dllexport) |
-bool CancelNotification(const char* notification_id) { |
- // TODO(ananta) |
- // Needs implementation. |
- DVLOG(1) << __FUNCTION__; |
- |
- if (!globals.view->IsValidNotification(notification_id)) { |
- NOTREACHED() << "Invalid notification id :" << notification_id; |
- return false; |
- } |
- |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind(&ChromeAppView::CancelNotification, |
- globals.view, std::string(notification_id))); |
- return true; |
-} |
- |
-// Returns command line switches if any to be used by metro chrome. |
-extern "C" __declspec(dllexport) |
-const wchar_t* GetMetroCommandLineSwitches() { |
- DVLOG(1) << __FUNCTION__; |
- // The metro_command_line_switches field should be filled up once. |
- // ideally in ChromeAppView::Activate. |
- return globals.metro_command_line_switches.c_str(); |
-} |
- |
-// Provides functionality to display a metro style dialog box with two buttons. |
-// Only one dialog box can be displayed at any given time. |
-extern "C" __declspec(dllexport) |
-void ShowDialogBox( |
- const wchar_t* title, |
- const wchar_t* content, |
- const wchar_t* button1_label, |
- const wchar_t* button2_label, |
- base::win::MetroDialogButtonPressedHandler button1_handler, |
- base::win::MetroDialogButtonPressedHandler button2_handler) { |
- VLOG(1) << __FUNCTION__; |
- |
- DCHECK(title); |
- DCHECK(content); |
- DCHECK(button1_label); |
- DCHECK(button2_label); |
- DCHECK(button1_handler); |
- DCHECK(button2_handler); |
- |
- MetroDialogBox::DialogBoxInfo dialog_box_info; |
- dialog_box_info.title = title; |
- dialog_box_info.content = content; |
- dialog_box_info.button1_label = button1_label; |
- dialog_box_info.button2_label = button2_label; |
- dialog_box_info.button1_handler = button1_handler; |
- dialog_box_info.button2_handler = button2_handler; |
- |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind( |
- &ChromeAppView::ShowDialogBox, globals.view, dialog_box_info)); |
-} |
- |
-// Provides functionality to dismiss the previously displayed metro style |
-// dialog box. |
-extern "C" __declspec(dllexport) |
-void DismissDialogBox() { |
- VLOG(1) << __FUNCTION__; |
- |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind( |
- &ChromeAppView::DismissDialogBox, |
- globals.view)); |
-} |
- |
-extern "C" __declspec(dllexport) |
-void SetFullscreen(bool fullscreen) { |
- VLOG(1) << __FUNCTION__; |
- |
- globals.appview_task_runner->PostTask( |
- FROM_HERE, base::Bind( |
- &ChromeAppView::SetFullscreen, |
- globals.view, fullscreen)); |
-} |
- |
-template <typename ContainerT> |
-void CloseSecondaryWindows(ContainerT& windows) { |
- DVLOG(1) << "Closing secondary windows", windows.size(); |
- std::for_each(windows.begin(), windows.end(), [](HWND hwnd) { |
- ::PostMessageW(hwnd, WM_CLOSE, 0, 0); |
- }); |
- windows.clear(); |
-} |
- |
-void EndChromeSession() { |
- DVLOG(1) << "Sending chrome WM_ENDSESSION window message."; |
- ::SendMessage(globals.host_windows.front().first, WM_ENDSESSION, FALSE, |
- ENDSESSION_CLOSEAPP); |
-} |
- |
-DWORD WINAPI HostMainThreadProc(void*) { |
- // Test feature - devs have requested the ability to easily add metro-chrome |
- // command line arguments. This is hard since shortcut arguments are ignored, |
- // by Metro, so we instead read them directly from the pinned taskbar |
- // shortcut. This may call Coinitialize and there is tell of badness |
- // occurring if CoInitialize is called on a metro thread. |
- globals.metro_command_line_switches = |
- winrt_utils::ReadArgumentsFromPinnedTaskbarShortcut(); |
- |
- globals.g_core_proc = |
- reinterpret_cast<WNDPROC>(::SetWindowLongPtr( |
- globals.view->core_window_hwnd(), GWLP_WNDPROC, |
- reinterpret_cast<LONG_PTR>(ChromeAppView::CoreWindowProc))); |
- DWORD exit_code = globals.host_main(globals.host_context); |
- |
- DVLOG(1) << "host thread done, exit_code=" << exit_code; |
- MetroExit(true); |
- return exit_code; |
-} |
- |
-ChromeAppView::ChromeAppView() |
- : osk_visible_notification_received_(false), |
- osk_offset_adjustment_(0), |
- core_window_hwnd_(NULL) { |
- globals.previous_state = |
- winapp::Activation::ApplicationExecutionState_NotRunning; |
-} |
- |
-ChromeAppView::~ChromeAppView() { |
- DVLOG(1) << __FUNCTION__; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppView::Initialize(winapp::Core::ICoreApplicationView* view) { |
- view_ = view; |
- DVLOG(1) << __FUNCTION__; |
- |
- HRESULT hr = view_->add_Activated(mswr::Callback<ActivatedHandler>( |
- this, &ChromeAppView::OnActivate).Get(), |
- &activated_token_); |
- CheckHR(hr); |
- return hr; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppView::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); |
- |
- hr = url_launch_handler_.Initialize(); |
- CheckHR(hr, "Failed to initialize url launch handler."); |
- // Register for size notifications. |
- hr = window_->add_SizeChanged(mswr::Callback<SizeChangedHandler>( |
- this, &ChromeAppView::OnSizeChanged).Get(), |
- &sizechange_token_); |
- CheckHR(hr); |
- |
- // Register for edge gesture notifications. |
- mswr::ComPtr<winui::Input::IEdgeGestureStatics> edge_gesture_statics; |
- hr = winrt_utils::CreateActivationFactory( |
- RuntimeClass_Windows_UI_Input_EdgeGesture, |
- edge_gesture_statics.GetAddressOf()); |
- CheckHR(hr, "Failed to activate IEdgeGestureStatics."); |
- |
- 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, &ChromeAppView::OnEdgeGestureCompleted).Get(), |
- &edgeevent_token_); |
- CheckHR(hr); |
- |
- // Register for share notifications. |
- mswr::ComPtr<winapp::DataTransfer::IDataTransferManagerStatics> |
- data_mgr_statics; |
- hr = winrt_utils::CreateActivationFactory( |
- RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager, |
- data_mgr_statics.GetAddressOf()); |
- CheckHR(hr, "Failed to activate IDataTransferManagerStatics."); |
- |
- mswr::ComPtr<winapp::DataTransfer::IDataTransferManager> data_transfer_mgr; |
- hr = data_mgr_statics->GetForCurrentView(&data_transfer_mgr); |
- CheckHR(hr, "Failed to get IDataTransferManager for current view."); |
- |
- hr = data_transfer_mgr->add_DataRequested( |
- mswr::Callback<ShareDataRequestedHandler>( |
- this, &ChromeAppView::OnShareDataRequested).Get(), |
- &share_data_requested_token_); |
- CheckHR(hr); |
- |
- // TODO(ananta) |
- // The documented InputPane notifications don't fire on Windows 8 in metro |
- // chrome. Uncomment this once we figure out why they don't fire. |
- // RegisterInputPaneNotifications(); |
- hr = winrt_utils::CreateActivationFactory( |
- RuntimeClass_Windows_UI_ViewManagement_ApplicationView, |
- app_view_.GetAddressOf()); |
- CheckHR(hr); |
- |
- DVLOG(1) << "Created appview instance."; |
- |
- hr = devices_handler_.Initialize(window); |
- // Don't check or return the failure here, we need to let the app |
- // initialization succeed. Even if we won't be able to access devices |
- // we still want to allow the app to start. |
- LOG_IF(ERROR, FAILED(hr)) << "Failed to initialize devices handler."; |
- return S_OK; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppView::Load(HSTRING entryPoint) { |
- DVLOG(1) << __FUNCTION__; |
- return S_OK; |
-} |
- |
-void RunMessageLoop(winui::Core::ICoreDispatcher* dispatcher) { |
- // We're entering a nested message loop, let's allow dispatching |
- // tasks while we're in there. |
- base::MessageLoop::current()->SetNestableTasksAllowed(true); |
- |
- // Enter main core message loop. There are several ways to exit it |
- // Nicely: |
- // 1 - User action like ALT-F4. |
- // 2 - Calling ICoreApplicationExit::Exit(). |
- // 3- Posting WM_CLOSE to the core window. |
- HRESULT hr = dispatcher->ProcessEvents( |
- winui::Core::CoreProcessEventsOption |
- ::CoreProcessEventsOption_ProcessUntilQuit); |
- |
- // Wind down the thread's chrome message loop. |
- base::MessageLoop::current()->QuitWhenIdle(); |
-} |
- |
-void ChromeAppView::CheckForOSKActivation() { |
- // Hack for checking if the OSK was displayed while we are in the foreground. |
- // The input pane notifications which are supposed to fire when the OSK is |
- // shown and hidden don't seem to be firing in Windows 8 metro for us. |
- // The current hack is supposed to workaround that issue till we figure it |
- // out. Logic is to find the OSK window and see if we are the foreground |
- // process. If yes then fire the notification once for when the OSK is shown |
- // and once for when it is hidden. |
- // TODO(ananta) |
- // Take this out when the documented input pane notification issues are |
- // addressed. |
- HWND osk = ::FindWindow(kOSKClassName, NULL); |
- if (::IsWindow(osk)) { |
- HWND foreground_window = ::GetForegroundWindow(); |
- if (globals.host_windows.size() > 0 && |
- foreground_window == globals.host_windows.front().first) { |
- RECT osk_rect = {0}; |
- ::GetWindowRect(osk, &osk_rect); |
- |
- if (::IsWindowVisible(osk) && ::IsWindowEnabled(osk)) { |
- if (!globals.view->osk_visible_notification_received()) { |
- DVLOG(1) << "Found KB window while we are in the forground."; |
- HandleInputPaneVisible(osk_rect); |
- } |
- } else if (osk_visible_notification_received()) { |
- DVLOG(1) << "KB window hidden while we are in the foreground."; |
- HandleInputPaneHidden(osk_rect); |
- } |
- } |
- } |
- base::MessageLoop::current()->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&ChromeAppView::CheckForOSKActivation, base::Unretained(this)), |
- base::TimeDelta::FromMilliseconds(kCheckOSKDelayMs)); |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppView::Run() { |
- DVLOG(1) << __FUNCTION__; |
- mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher; |
- HRESULT hr = window_->get_Dispatcher(&dispatcher); |
- CheckHR(hr, "Dispatcher failed."); |
- |
- hr = window_->Activate(); |
- if (SUCCEEDED(hr)) { |
- // TODO(cpu): Draw something here. |
- } else { |
- DVLOG(1) << "Activate failed, hr=" << hr; |
- } |
- |
- // Create a message loop to allow message passing into this thread. |
- base::MessageLoopForUI msg_loop; |
- |
- // Announce our message loop task runner to the world. |
- globals.appview_task_runner = msg_loop.task_runner(); |
- |
- // And post the task that'll do the inner Metro message pumping to it. |
- msg_loop.PostTask(FROM_HERE, base::Bind(&RunMessageLoop, dispatcher.Get())); |
- |
- // Post the recurring task which checks for OSK activation in metro chrome. |
- // Please refer to the comments in the CheckForOSKActivation function for why |
- // this is needed. |
- // TODO(ananta) |
- // Take this out when the documented OSK notifications start working. |
- msg_loop.PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&ChromeAppView::CheckForOSKActivation, |
- base::Unretained(this)), |
- base::TimeDelta::FromMilliseconds(kCheckOSKDelayMs)); |
- |
- msg_loop.Run(); |
- |
- globals.appview_task_runner = NULL; |
- |
- DVLOG(0) << "ProcessEvents done, hr=" << hr; |
- |
- // We join here with chrome's main thread so that the chrome is not killed |
- // while a critical operation is still in progress. Now, if there are host |
- // windows active it is possible we end up stuck on the wait below therefore |
- // we tell chrome to close its windows. |
- if (!globals.host_windows.empty()) { |
- DVLOG(1) << "Chrome still has windows open!"; |
- EndChromeSession(); |
- } |
- DWORD wr = ::WaitForSingleObject(globals.host_thread, INFINITE); |
- if (wr != WAIT_OBJECT_0) { |
- DVLOG(1) << "Waiting for host thread failed : " << wr; |
- } |
- |
- DVLOG(1) << "Host thread exited"; |
- |
- ::CloseHandle(globals.host_thread); |
- globals.host_thread = NULL; |
- return hr; |
-} |
- |
-IFACEMETHODIMP |
-ChromeAppView::Uninitialize() { |
- DVLOG(1) << __FUNCTION__; |
- window_ = nullptr; |
- view_ = nullptr; |
- base::AutoLock lock(notification_lock_); |
- notification_map_.clear(); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppView::RegisterInputPaneNotifications() { |
- DVLOG(1) << __FUNCTION__; |
- |
- mswr::ComPtr<winui::ViewManagement::IInputPaneStatics> |
- input_pane_statics; |
- HRESULT hr = winrt_utils::CreateActivationFactory( |
- RuntimeClass_Windows_UI_ViewManagement_InputPane, |
- input_pane_statics.GetAddressOf()); |
- CheckHR(hr); |
- |
- hr = input_pane_statics->GetForCurrentView(&input_pane_); |
- CheckHR(hr); |
- DVLOG(1) << "Got input pane."; |
- |
- hr = input_pane_->add_Showing( |
- mswr::Callback<InputPaneEventHandler>( |
- this, &ChromeAppView::OnInputPaneVisible).Get(), |
- &input_pane_visible_token_); |
- CheckHR(hr); |
- |
- DVLOG(1) << "Added showing event handler for input pane", |
- input_pane_visible_token_.value; |
- |
- hr = input_pane_->add_Hiding( |
- mswr::Callback<InputPaneEventHandler>( |
- this, &ChromeAppView::OnInputPaneHiding).Get(), |
- &input_pane_hiding_token_); |
- CheckHR(hr); |
- |
- DVLOG(1) << "Added hiding event handler for input pane, value=" |
- << input_pane_hiding_token_.value; |
- return hr; |
-} |
- |
-HRESULT ChromeAppView::OnActivate(winapp::Core::ICoreApplicationView*, |
- winapp::Activation::IActivatedEventArgs* args) { |
- DVLOG(1) << __FUNCTION__; |
- |
- args->get_PreviousExecutionState(&globals.previous_state); |
- DVLOG(1) << "Previous Execution State: " << globals.previous_state; |
- |
- window_->Activate(); |
- url_launch_handler_.Activate(args); |
- |
- if (globals.previous_state == |
- winapp::Activation::ApplicationExecutionState_Running && |
- globals.host_thread) { |
- DVLOG(1) << "Already running. Skipping rest of OnActivate."; |
- return S_OK; |
- } |
- |
- if (!globals.host_thread) { |
- DWORD chrome_ui_thread_id = 0; |
- globals.host_thread = |
- ::CreateThread(NULL, 0, HostMainThreadProc, NULL, 0, |
- &chrome_ui_thread_id); |
- |
- if (!globals.host_thread) { |
- NOTREACHED() << "thread creation failed."; |
- return E_UNEXPECTED; |
- } |
- } |
- |
- if (RegisterHotKey(core_window_hwnd_, kFlipWindowsHotKeyId, |
- MOD_CONTROL, VK_F12)) { |
- DVLOG(1) << "Registered flip window hotkey."; |
- } else { |
- VPLOG(1) << "Failed to register flip window hotkey."; |
- } |
- HRESULT hr = settings_handler_.Initialize(); |
- CheckHR(hr,"Failed to initialize settings handler."); |
- return hr; |
-} |
- |
-// We subclass the core window for moving the associated chrome window when the |
-// core window is moved around, typically in the snap view operation. The |
-// size changes are handled in the documented size changed event. |
-LRESULT CALLBACK ChromeAppView::CoreWindowProc( |
- HWND window, UINT message, WPARAM wp, LPARAM lp) { |
- |
- static const UINT kBrowserClosingMessage = |
- ::RegisterWindowMessage(L"DefaultBrowserClosing"); |
- |
- if (message == WM_WINDOWPOSCHANGED) { |
- WINDOWPOS* pos = reinterpret_cast<WINDOWPOS*>(lp); |
- if (!(pos->flags & SWP_NOMOVE)) { |
- DVLOG(1) << "WM_WINDOWPOSCHANGED. Moving the chrome window."; |
- globals.view->OnPositionChanged(pos->x, pos->y); |
- } |
- } else if (message == WM_HOTKEY && wp == kFlipWindowsHotKeyId) { |
- FlipFrameWindows(); |
- } else if (message == kBrowserClosingMessage) { |
- DVLOG(1) << "Received DefaultBrowserClosing window message."; |
- // Ensure that the view is uninitialized. The kBrowserClosingMessage |
- // means that the app is going to be terminated, i.e. the proper |
- // uninitialization sequence does not occur. |
- globals.view->Uninitialize(); |
- if (!globals.host_windows.empty()) { |
- EndChromeSession(); |
- } |
- } |
- return CallWindowProc(globals.g_core_proc, window, message, wp, lp); |
-} |
- |
-HRESULT ChromeAppView::OnSizeChanged(winui::Core::ICoreWindow* sender, |
- winui::Core::IWindowSizeChangedEventArgs* args) { |
- if (!globals.host_windows.size()) { |
- return S_OK; |
- } |
- |
- winfoundtn::Size size; |
- args->get_Size(&size); |
- |
- int cx = static_cast<int>(size.Width); |
- int cy = static_cast<int>(size.Height); |
- |
- if (!::SetWindowPos(globals.host_windows.front().first, NULL, 0, 0, cx, cy, |
- SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED)) { |
- DVLOG(1) << "SetWindowPos failed."; |
- } |
- DVLOG(1) << "size changed cx=" << cx; |
- DVLOG(1) << "size changed cy=" << cy; |
- |
- winui::ViewManagement::ApplicationViewState view_state = |
- winui::ViewManagement::ApplicationViewState_FullScreenLandscape; |
- app_view_->get_Value(&view_state); |
- |
- HWND top_level_frame = globals.host_windows.front().first; |
- if (view_state == winui::ViewManagement::ApplicationViewState_Snapped) { |
- DVLOG(1) << "Enabling metro snap mode."; |
- ::PostMessageW(top_level_frame, WM_SYSCOMMAND, IDC_METRO_SNAP_ENABLE, 0); |
- } else { |
- ::PostMessageW(top_level_frame, WM_SYSCOMMAND, IDC_METRO_SNAP_DISABLE, 0); |
- } |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppView::OnPositionChanged(int x, int y) { |
- DVLOG(1) << __FUNCTION__; |
- |
- ::SetWindowPos(globals.host_windows.front().first, NULL, x, y, 0, 0, |
- SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSIZE); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppView::OnEdgeGestureCompleted( |
- winui::Input::IEdgeGesture* gesture, |
- winui::Input::IEdgeGestureEventArgs* args) { |
- DVLOG(1) << "edge gesture completed."; |
- |
- winui::ViewManagement::ApplicationViewState view_state = |
- winui::ViewManagement::ApplicationViewState_FullScreenLandscape; |
- app_view_->get_Value(&view_state); |
- // We don't want fullscreen chrome unless we are fullscreen metro. |
- if ((view_state == winui::ViewManagement::ApplicationViewState_Filled) || |
- (view_state == winui::ViewManagement::ApplicationViewState_Snapped)) { |
- DVLOG(1) << "No full screen in snapped view state:" << view_state; |
- return S_OK; |
- } |
- |
- // Deactivate anything pending, e.g., the wrench or a context menu. |
- BOOL success = ::ReleaseCapture(); |
- DCHECK(success) << "Couldn't ReleaseCapture() before going full screen"; |
- |
- DVLOG(1) << "Going full screen."; |
- ::PostMessageW(globals.host_windows.front().first, WM_SYSCOMMAND, |
- IDC_FULLSCREEN, 0); |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppView::OnShareDataRequested( |
- winapp::DataTransfer::IDataTransferManager* data_transfer_mgr, |
- winapp::DataTransfer::IDataRequestedEventArgs* event_args) { |
- |
- DVLOG(1) << "Share data requested."; |
- |
- // The current tab info is retrieved from Chrome via a registered window |
- // message. |
- |
- static const UINT get_current_tab_info = |
- RegisterWindowMessage(kMetroGetCurrentTabInfoMessage); |
- |
- static const int kGetTabInfoTimeoutMs = 1000; |
- |
- mswr::ComPtr<winapp::DataTransfer::IDataRequest> data_request; |
- HRESULT hr = event_args->get_Request(&data_request); |
- CheckHR(hr); |
- |
- mswr::ComPtr<winapp::DataTransfer::IDataPackage> data_package; |
- hr = data_request->get_Data(&data_package); |
- CheckHR(hr); |
- |
- base::win::CurrentTabInfo current_tab_info; |
- current_tab_info.title = NULL; |
- current_tab_info.url = NULL; |
- |
- DWORD_PTR result = 0; |
- |
- if (!SendMessageTimeout(globals.host_windows.front().first, |
- get_current_tab_info, |
- reinterpret_cast<WPARAM>(¤t_tab_info), |
- 0, |
- SMTO_ABORTIFHUNG, |
- kGetTabInfoTimeoutMs, |
- &result)) { |
- VPLOG(1) << "Failed to retrieve tab info from chrome."; |
- return E_FAIL; |
- } |
- |
- if (!current_tab_info.title || !current_tab_info.url) { |
- DVLOG(1) << "Failed to retrieve tab info from chrome."; |
- return E_FAIL; |
- } |
- |
- base::string16 current_title(current_tab_info.title); |
- base::string16 current_url(current_tab_info.url); |
- |
- LocalFree(current_tab_info.title); |
- LocalFree(current_tab_info.url); |
- |
- mswr::ComPtr<winapp::DataTransfer::IDataPackagePropertySet> data_properties; |
- hr = data_package->get_Properties(&data_properties); |
- |
- mswrw::HString title; |
- title.Attach(MakeHString(current_title)); |
- data_properties->put_Title(title.Get()); |
- |
- mswr::ComPtr<winfoundtn::IUriRuntimeClassFactory> uri_factory; |
- hr = winrt_utils::CreateActivationFactory( |
- RuntimeClass_Windows_Foundation_Uri, |
- uri_factory.GetAddressOf()); |
- CheckHR(hr); |
- |
- mswrw::HString url; |
- url.Attach(MakeHString(current_url)); |
- mswr::ComPtr<winfoundtn::IUriRuntimeClass> uri; |
- hr = uri_factory->CreateUri(url.Get(), &uri); |
- CheckHR(hr); |
- |
- hr = data_package->SetUri(uri.Get()); |
- CheckHR(hr); |
- |
- return S_OK; |
-} |
- |
-void ChromeAppView::HandleInputPaneVisible(const RECT& osk_rect) { |
- DCHECK(!osk_visible_notification_received_); |
- |
- DVLOG(1) << __FUNCTION__; |
- DVLOG(1) << "OSK width:" << osk_rect.right - osk_rect.left; |
- DVLOG(1) << "OSK height:" << osk_rect.bottom - osk_rect.top; |
- |
- globals.host_windows.front().second = false; |
- |
- POINT cursor_pos = {0}; |
- GetCursorPos(&cursor_pos); |
- |
- osk_offset_adjustment_ = 0; |
- |
- if (::PtInRect(&osk_rect, cursor_pos)) { |
- DVLOG(1) << "OSK covering focus point."; |
- int osk_height = osk_rect.bottom - osk_rect.top; |
- |
- osk_offset_adjustment_ = osk_height + kOSKAdjustmentOffset; |
- |
- DVLOG(1) << "Scrolling window by offset: " << osk_offset_adjustment_; |
- ::ScrollWindowEx(globals.host_windows.front().first, |
- 0, |
- -osk_offset_adjustment_, |
- NULL, |
- NULL, |
- NULL, |
- NULL, |
- SW_INVALIDATE | SW_SCROLLCHILDREN); |
- |
- globals.host_windows.front().second = true; |
- } |
- osk_visible_notification_received_ = true; |
-} |
- |
-void ChromeAppView::HandleInputPaneHidden(const RECT& osk_rect) { |
- DCHECK(osk_visible_notification_received_); |
- DVLOG(1) << __FUNCTION__; |
- DVLOG(1) << "OSK width:" << osk_rect.right - osk_rect.left; |
- DVLOG(1) << "OSK height:" << osk_rect.bottom - osk_rect.top; |
- osk_visible_notification_received_ = false; |
- if (globals.host_windows.front().second == true) { |
- |
- if (osk_offset_adjustment_) { |
- DVLOG(1) << "Restoring scrolled window offset: " |
- << osk_offset_adjustment_; |
- |
- ::ScrollWindowEx(globals.host_windows.front().first, |
- 0, |
- osk_offset_adjustment_, |
- NULL, |
- NULL, |
- NULL, |
- NULL, |
- SW_INVALIDATE | SW_SCROLLCHILDREN); |
- } |
- |
- globals.host_windows.front().second = false; |
- } |
-} |
- |
-HRESULT ChromeAppView::OnInputPaneVisible( |
- winui::ViewManagement::IInputPane* input_pane, |
- winui::ViewManagement::IInputPaneVisibilityEventArgs* event_args) { |
- DVLOG(1) << __FUNCTION__; |
- return S_OK; |
-} |
- |
-HRESULT ChromeAppView::OnInputPaneHiding( |
- winui::ViewManagement::IInputPane* input_pane, |
- winui::ViewManagement::IInputPaneVisibilityEventArgs* event_args) { |
- DVLOG(1) << __FUNCTION__; |
- return S_OK; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-ChromeAppViewFactory::ChromeAppViewFactory( |
- winapp::Core::ICoreApplication* icore_app, |
- LPTHREAD_START_ROUTINE host_main, |
- void* host_context) { |
- globals.host_main = host_main; |
- globals.host_context = host_context; |
- 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) { |
- globals.view = mswr::Make<ChromeAppView>().Detach(); |
- *view = globals.view; |
- return (*view) ? S_OK : E_OUTOFMEMORY; |
-} |