summaryrefslogtreecommitdiffstats
path: root/win8/metro_driver/chrome_app_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'win8/metro_driver/chrome_app_view.cc')
-rw-r--r--win8/metro_driver/chrome_app_view.cc1059
1 files changed, 0 insertions, 1059 deletions
diff --git a/win8/metro_driver/chrome_app_view.cc b/win8/metro_driver/chrome_app_view.cc
deleted file mode 100644
index 7d5580e..0000000
--- a/win8/metro_driver/chrome_app_view.cc
+++ /dev/null
@@ -1,1059 +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 <algorithm>
-#include <windows.applicationModel.datatransfer.h>
-#include <windows.foundation.h>
-
-#include "base/bind.h"
-#include "base/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 "win8/metro_driver/winrt_utils.h"
-#include "ui/base/ui_base_switches.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;
-
-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;
-
-namespace {
-
-void AdjustToFitWindow(HWND hwnd, int flags) {
- RECT rect = {0};
- ::GetWindowRect(globals.core_window, &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);
-}
-
-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));
- 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);
- }
-
- // If chrome opens a url in a foreground tab, it may call SetFrameWindow
- // again. Ensure that we don't have dups.
- globals.host_windows.remove_if([hwnd](std::pair<HWND, bool>& item) {
- return (item.first == hwnd);
- });
-
- globals.host_windows.push_front(std::make_pair(hwnd, false));
-
- AdjustFrameWindowStyleForMetro(hwnd);
-}
-
-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().";
- globals.app_exit->Exit();
- }
-}
-
-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
-
-HRESULT ChromeAppView::TileRequestCreateDone(
- winfoundtn::IAsyncOperation<bool>* async,
- AsyncStatus status) {
- if (status == Completed) {
- unsigned char result;
- CheckHR(async->GetResults(&result));
- DVLOG(1) << __FUNCTION__ << " result " << static_cast<int>(result);
- } else {
- LOG(ERROR) << __FUNCTION__ << " Unexpected async status " << status;
- }
-
- return S_OK;
-}
-
-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;
- }
-}
-
-void UnsnapHelper() {
- ChromeAppView::Unsnap();
-}
-
-extern "C" __declspec(dllexport)
-void MetroUnsnap() {
- DVLOG(1) << __FUNCTION__;
- globals.appview_msg_loop->PostTask(
- FROM_HERE, base::Bind(&UnsnapHelper));
-}
-
-extern "C" __declspec(dllexport)
-HWND GetRootWindow() {
- DVLOG(1) << __FUNCTION__;
- return globals.core_window;
-}
-
-extern "C" __declspec(dllexport)
-void SetFrameWindow(HWND hwnd) {
- DVLOG(1) << __FUNCTION__ << ", hwnd=" << LONG_PTR(hwnd);
- globals.appview_msg_loop->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_msg_loop->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_msg_loop->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) {
- // TODO(ananta)
- // Needs implementation.
- DVLOG(1) << __FUNCTION__;
-
- ToastNotificationHandler::DesktopNotification notification(origin_url,
- icon_url,
- title,
- body,
- display_source,
- notification_id);
- globals.appview_msg_loop->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_msg_loop->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_msg_loop->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_msg_loop->PostTask(
- FROM_HERE, base::Bind(
- &ChromeAppView::DismissDialogBox,
- globals.view));
-}
-
-extern "C" __declspec(dllexport)
-void SetFullscreen(bool fullscreen) {
- VLOG(1) << __FUNCTION__;
-
- globals.appview_msg_loop->PostTask(
- FROM_HERE, base::Bind(
- &ChromeAppView::SetFullscreen,
- globals.view, fullscreen));
-}
-
-BOOL CALLBACK CoreWindowFinder(HWND hwnd, LPARAM) {
- char classname[128];
- if (::GetClassNameA(hwnd, classname, ARRAYSIZE(classname))) {
- if (lstrcmpiA("Windows.UI.Core.CoreWindow", classname) == 0) {
- globals.core_window = hwnd;
- return FALSE;
- }
- }
- return TRUE;
-}
-
-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>(
- ::SetWindowLong(globals.core_window, GWL_WNDPROC,
- reinterpret_cast<long>(ChromeAppView::CoreWindowProc)));
- DWORD exit_code = globals.host_main(globals.host_context);
- DVLOG(1) << "host thread done, exit_code=" << exit_code;
- globals.app_exit->Exit();
- return exit_code;
-}
-
-ChromeAppView::ChromeAppView()
- : osk_visible_notification_received_(false),
- osk_offset_adjustment_(0) {
- globals.previous_state =
- winapp::Activation::ApplicationExecutionState_NotRunning;
-}
-
-ChromeAppView::~ChromeAppView() {
- DVLOG(1) << __FUNCTION__;
-}
-
-IFACEMETHODIMP
-ChromeAppView::Initialize(winapp::Core::ICoreApplicationView* view) {
- view_ = view;
- DVLOG(1) << __FUNCTION__;
- globals.main_thread_id = ::GetCurrentThreadId();
-
- 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__;
-
- HRESULT 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.
- 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.
- MessageLoop::current()->Quit();
-}
-
-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 notifcation 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);
- }
- }
- }
- MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&ChromeAppView::CheckForOSKActivation,
- base::Unretained(this)),
- base::TimeDelta::FromMilliseconds(kCheckOSKDelayMs));
-}
-
-IFACEMETHODIMP
-ChromeAppView::Run() {
- DVLOG(1) << __FUNCTION__ << ", hwnd=" << LONG_PTR(window_.Get());
- 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.
- MessageLoop msg_loop(MessageLoop::TYPE_UI);
-
- // Announce our message loop to the world.
- globals.appview_msg_loop = msg_loop.message_loop_proxy();
-
- // 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_msg_loop = 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;
- }
- ::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;
- }
-
- do {
- ::Sleep(10);
- ::EnumThreadWindows(globals.main_thread_id, &CoreWindowFinder, 0);
- } while (globals.core_window == NULL);
-
- DVLOG(1) << "CoreWindow found: " << std::hex << globals.core_window;
-
- if (!globals.host_thread) {
- globals.host_thread =
- ::CreateThread(NULL, 0, HostMainThreadProc, NULL, 0, NULL);
-
- if (!globals.host_thread) {
- NOTREACHED() << "thread creation failed.";
- return E_UNEXPECTED;
- }
- }
-
- if (RegisterHotKey(globals.core_window, 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>(&current_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;
- }
-
- string16 current_title(current_tab_info.title);
- 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;
-}