michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "FrameworkView.h" michael@0: #include "MetroAppShell.h" michael@0: #include "MetroWidget.h" michael@0: #include "mozilla/AutoRestore.h" michael@0: #include "MetroUtils.h" michael@0: #include "MetroApp.h" michael@0: #include "UIABridgePublic.h" michael@0: #include "KeyboardLayout.h" michael@0: michael@0: // generated michael@0: #include "UIABridge.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::widget::winrt; michael@0: #ifdef ACCESSIBILITY michael@0: using namespace mozilla::a11y; michael@0: #endif michael@0: using namespace ABI::Windows::ApplicationModel; michael@0: using namespace ABI::Windows::ApplicationModel::Core; michael@0: using namespace ABI::Windows::ApplicationModel::Activation; michael@0: using namespace ABI::Windows::UI::Core; michael@0: using namespace ABI::Windows::UI::ViewManagement; michael@0: using namespace ABI::Windows::UI::Input; michael@0: using namespace ABI::Windows::Devices::Input; michael@0: using namespace ABI::Windows::System; michael@0: using namespace ABI::Windows::Foundation; michael@0: using namespace Microsoft::WRL; michael@0: using namespace Microsoft::WRL::Wrappers; michael@0: michael@0: namespace mozilla { michael@0: namespace widget { michael@0: namespace winrt { michael@0: michael@0: // statics michael@0: bool FrameworkView::sKeyboardIsVisible = false; michael@0: Rect FrameworkView::sKeyboardRect; michael@0: HSTRING FrameworkView::sActivationURI = NULL; michael@0: ApplicationExecutionState FrameworkView::sPreviousExecutionState; michael@0: nsTArray* sSettingsArray; michael@0: michael@0: FrameworkView::FrameworkView(MetroApp* aMetroApp) : michael@0: mDPI(-1.0f), michael@0: mWidget(nullptr), michael@0: mShuttingDown(false), michael@0: mMetroApp(aMetroApp), michael@0: mWindow(nullptr), michael@0: mMetroInput(nullptr), michael@0: mWinVisible(false), michael@0: mWinActiveState(false) michael@0: { michael@0: mActivated.value = 0; michael@0: mWindowActivated.value = 0; michael@0: mWindowVisibilityChanged.value = 0; michael@0: mWindowSizeChanged.value = 0; michael@0: mSoftKeyboardHidden.value = 0; michael@0: mSoftKeyboardShown.value = 0; michael@0: mDisplayPropertiesChanged.value = 0; michael@0: mAutomationProviderRequested.value = 0; michael@0: mDataTransferRequested.value = 0; michael@0: mSearchQuerySubmitted.value = 0; michael@0: mPlayToRequested.value = 0; michael@0: mSettingsPane.value = 0; michael@0: mPrintManager.value = 0; michael@0: memset(&sKeyboardRect, 0, sizeof(Rect)); michael@0: sSettingsArray = new nsTArray(); michael@0: LogFunction(); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////// michael@0: // IFrameworkView impl. michael@0: michael@0: HRESULT michael@0: FrameworkView::Initialize(ICoreApplicationView* aAppView) michael@0: { michael@0: LogFunction(); michael@0: if (mShuttingDown) michael@0: return E_FAIL; michael@0: michael@0: aAppView->add_Activated(Callback<__FITypedEventHandler_2_Windows__CApplicationModel__CCore__CCoreApplicationView_Windows__CApplicationModel__CActivation__CIActivatedEventArgs_t>( michael@0: this, &FrameworkView::OnActivated).Get(), &mActivated); michael@0: michael@0: //CoCreateInstance(CLSID_WICImagingFactory, nullptr, michael@0: // CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&mWicFactory)); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::Uninitialize() michael@0: { michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::Load(HSTRING aEntryPoint) michael@0: { michael@0: return S_OK; michael@0: } michael@0: michael@0: // called by winrt on startup michael@0: HRESULT michael@0: FrameworkView::Run() michael@0: { michael@0: LogFunction(); michael@0: michael@0: // Initialize XPCOM, create mWidget and go! We get a michael@0: // callback in MetroAppShell::Run, in which we kick michael@0: // off normal browser execution / event dispatching. michael@0: mMetroApp->Run(); michael@0: michael@0: // Gecko is completely shut down at this point. michael@0: WinUtils::Log("Exiting FrameworkView::Run()"); michael@0: michael@0: WindowsDeleteString(sActivationURI); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::ActivateView() michael@0: { michael@0: LogFunction(); michael@0: michael@0: UpdateWidgetSizeAndPosition(); michael@0: michael@0: nsIntRegion region(nsIntRect(0, 0, mWindowBounds.width, mWindowBounds.height)); michael@0: mWidget->Paint(region); michael@0: michael@0: // Activate the window, this kills the splash screen michael@0: mWindow->Activate(); michael@0: michael@0: ProcessLaunchArguments(); michael@0: AddEventHandlers(); michael@0: SetupContracts(); michael@0: michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::SetWindow(ICoreWindow* aWindow) michael@0: { michael@0: LogFunction(); michael@0: michael@0: NS_ASSERTION(!mWindow, "Attempting to set a window on a view that already has a window!"); michael@0: NS_ASSERTION(aWindow, "Attempting to set a null window on a view!"); michael@0: michael@0: mWindow = aWindow; michael@0: UpdateLogicalDPI(); michael@0: return S_OK; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////// michael@0: // FrameworkView impl. michael@0: michael@0: void michael@0: FrameworkView::AddEventHandlers() { michael@0: NS_ASSERTION(mWindow, "SetWindow must be called before AddEventHandlers!"); michael@0: NS_ASSERTION(mWidget, "SetWidget must be called before AddEventHAndlers!"); michael@0: michael@0: mMetroInput = Make(mWidget.Get(), michael@0: mWindow.Get()); michael@0: michael@0: mWindow->add_VisibilityChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs>( michael@0: this, &FrameworkView::OnWindowVisibilityChanged).Get(), &mWindowVisibilityChanged); michael@0: mWindow->add_Activated(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowActivatedEventArgs_t>( michael@0: this, &FrameworkView::OnWindowActivated).Get(), &mWindowActivated); michael@0: mWindow->add_SizeChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t>( michael@0: this, &FrameworkView::OnWindowSizeChanged).Get(), &mWindowSizeChanged); michael@0: michael@0: mWindow->add_AutomationProviderRequested(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CAutomationProviderRequestedEventArgs_t>( michael@0: this, &FrameworkView::OnAutomationProviderRequested).Get(), &mAutomationProviderRequested); michael@0: michael@0: HRESULT hr; michael@0: ComPtr dispProps; michael@0: if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), dispProps.GetAddressOf()))) { michael@0: hr = dispProps->add_LogicalDpiChanged(Callback( michael@0: this, &FrameworkView::OnLogicalDpiChanged).Get(), &mDisplayPropertiesChanged); michael@0: LogHRESULT(hr); michael@0: } michael@0: michael@0: ComPtr inputStatic; michael@0: if (SUCCEEDED(hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), inputStatic.GetAddressOf()))) { michael@0: ComPtr inputPane; michael@0: if (SUCCEEDED(inputStatic->GetForCurrentView(inputPane.GetAddressOf()))) { michael@0: inputPane->add_Hiding(Callback<__FITypedEventHandler_2_Windows__CUI__CViewManagement__CInputPane_Windows__CUI__CViewManagement__CInputPaneVisibilityEventArgs_t>( michael@0: this, &FrameworkView::OnSoftkeyboardHidden).Get(), &mSoftKeyboardHidden); michael@0: inputPane->add_Showing(Callback<__FITypedEventHandler_2_Windows__CUI__CViewManagement__CInputPane_Windows__CUI__CViewManagement__CInputPaneVisibilityEventArgs_t>( michael@0: this, &FrameworkView::OnSoftkeyboardShown).Get(), &mSoftKeyboardShown); michael@0: } michael@0: } michael@0: } michael@0: michael@0: // Called by MetroApp michael@0: void michael@0: FrameworkView::Shutdown() michael@0: { michael@0: LogFunction(); michael@0: mShuttingDown = true; michael@0: michael@0: if (mWindow && mWindowVisibilityChanged.value) { michael@0: mWindow->remove_VisibilityChanged(mWindowVisibilityChanged); michael@0: mWindow->remove_Activated(mWindowActivated); michael@0: mWindow->remove_Closed(mWindowClosed); michael@0: mWindow->remove_SizeChanged(mWindowSizeChanged); michael@0: mWindow->remove_AutomationProviderRequested(mAutomationProviderRequested); michael@0: } michael@0: michael@0: ComPtr dispProps; michael@0: if (mDisplayPropertiesChanged.value && michael@0: SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), dispProps.GetAddressOf()))) { michael@0: dispProps->remove_LogicalDpiChanged(mDisplayPropertiesChanged); michael@0: } michael@0: michael@0: ComPtr inputStatic; michael@0: if (mSoftKeyboardHidden.value && michael@0: SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), inputStatic.GetAddressOf()))) { michael@0: ComPtr inputPane; michael@0: if (SUCCEEDED(inputStatic->GetForCurrentView(inputPane.GetAddressOf()))) { michael@0: inputPane->remove_Hiding(mSoftKeyboardHidden); michael@0: inputPane->remove_Showing(mSoftKeyboardShown); michael@0: } michael@0: } michael@0: michael@0: if (mAutomationProvider) { michael@0: ComPtr provider; michael@0: mAutomationProvider.As(&provider); michael@0: if (provider) { michael@0: provider->Disconnect(); michael@0: } michael@0: } michael@0: mAutomationProvider = nullptr; michael@0: michael@0: mMetroInput = nullptr; michael@0: delete sSettingsArray; michael@0: sSettingsArray = nullptr; michael@0: mWidget = nullptr; michael@0: mMetroApp = nullptr; michael@0: mWindow = nullptr; michael@0: } michael@0: michael@0: void michael@0: FrameworkView::SetCursor(CoreCursorType aCursorType, DWORD aCustomId) michael@0: { michael@0: if (mShuttingDown) { michael@0: return; michael@0: } michael@0: NS_ASSERTION(mWindow, "SetWindow must be called before SetCursor!"); michael@0: ComPtr factory; michael@0: AssertHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), factory.GetAddressOf())); michael@0: ComPtr cursor; michael@0: AssertHRESULT(factory->CreateCursor(aCursorType, aCustomId, cursor.GetAddressOf())); michael@0: mWindow->put_PointerCursor(cursor.Get()); michael@0: } michael@0: michael@0: void michael@0: FrameworkView::ClearCursor() michael@0: { michael@0: if (mShuttingDown) { michael@0: return; michael@0: } michael@0: NS_ASSERTION(mWindow, "SetWindow must be called before ClearCursor!"); michael@0: mWindow->put_PointerCursor(nullptr); michael@0: } michael@0: michael@0: void michael@0: FrameworkView::UpdateLogicalDPI() michael@0: { michael@0: ComPtr dispProps; michael@0: HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), michael@0: dispProps.GetAddressOf()); michael@0: AssertHRESULT(hr); michael@0: FLOAT value; michael@0: AssertHRESULT(dispProps->get_LogicalDpi(&value)); michael@0: SetDpi(value); michael@0: } michael@0: michael@0: void michael@0: FrameworkView::GetBounds(nsIntRect &aRect) michael@0: { michael@0: // May be called by compositor thread michael@0: if (mShuttingDown) { michael@0: return; michael@0: } michael@0: aRect = mWindowBounds; michael@0: } michael@0: michael@0: void michael@0: FrameworkView::UpdateWidgetSizeAndPosition() michael@0: { michael@0: if (mShuttingDown) michael@0: return; michael@0: michael@0: NS_ASSERTION(mWindow, "SetWindow must be called before UpdateWidgetSizeAndPosition!"); michael@0: NS_ASSERTION(mWidget, "SetWidget must be called before UpdateWidgetSizeAndPosition!"); michael@0: michael@0: UpdateBounds(); michael@0: mWidget->Move(0, 0); michael@0: mWidget->Resize(0, 0, mWindowBounds.width, mWindowBounds.height, true); michael@0: mWidget->SizeModeChanged(); michael@0: } michael@0: michael@0: bool michael@0: FrameworkView::IsEnabled() const michael@0: { michael@0: return mWinActiveState; michael@0: } michael@0: michael@0: bool michael@0: FrameworkView::IsVisible() const michael@0: { michael@0: // we could check the wnd in MetroWidget for this, but michael@0: // generally we don't let nsIWidget control visibility michael@0: // or activation. michael@0: return mWinVisible; michael@0: } michael@0: michael@0: void FrameworkView::SetDpi(float aDpi) michael@0: { michael@0: if (aDpi != mDPI) { michael@0: LogFunction(); michael@0: michael@0: mDPI = aDpi; michael@0: michael@0: // notify the widget that dpi has changed michael@0: if (mWidget) { michael@0: mWidget->ChangedDPI(); michael@0: UpdateBounds(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: FrameworkView::UpdateBounds() michael@0: { michael@0: if (!mWidget) michael@0: return; michael@0: michael@0: RECT winRect; michael@0: GetClientRect(mWidget->GetICoreWindowHWND(), &winRect); michael@0: michael@0: mWindowBounds = nsIntRect(winRect.left, michael@0: winRect.top, michael@0: winRect.right - winRect.left, michael@0: winRect.bottom - winRect.top); michael@0: } michael@0: michael@0: void michael@0: FrameworkView::SetWidget(MetroWidget* aWidget) michael@0: { michael@0: NS_ASSERTION(!mWidget, "Attempting to set a widget for a view that already has a widget!"); michael@0: NS_ASSERTION(aWidget, "Attempting to set a null widget for a view!"); michael@0: LogFunction(); michael@0: mWidget = aWidget; michael@0: mWidget->FindMetroWindow(); michael@0: UpdateBounds(); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////// michael@0: // Event handlers michael@0: michael@0: void michael@0: FrameworkView::SendActivationEvent() michael@0: { michael@0: if (mShuttingDown) { michael@0: return; michael@0: } michael@0: NS_ASSERTION(mWindow, "SetWindow must be called before SendActivationEvent!"); michael@0: mWidget->Activated(mWinActiveState); michael@0: if (mWinActiveState) { michael@0: UpdateWidgetSizeAndPosition(); michael@0: } michael@0: EnsureAutomationProviderCreated(); michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnWindowVisibilityChanged(ICoreWindow* aWindow, michael@0: IVisibilityChangedEventArgs* aArgs) michael@0: { michael@0: // If we're visible, or we can't determine if we're visible, just store michael@0: // that we are visible. michael@0: boolean visible; michael@0: mWinVisible = FAILED(aArgs->get_Visible(&visible)) || visible; michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnActivated(ICoreApplicationView* aApplicationView, michael@0: IActivatedEventArgs* aArgs) michael@0: { michael@0: LogFunction(); michael@0: michael@0: if (mShuttingDown) { michael@0: return S_OK; michael@0: } michael@0: michael@0: aArgs->get_PreviousExecutionState(&sPreviousExecutionState); michael@0: bool startup = sPreviousExecutionState == ApplicationExecutionState::ApplicationExecutionState_Terminated || michael@0: sPreviousExecutionState == ApplicationExecutionState::ApplicationExecutionState_ClosedByUser || michael@0: sPreviousExecutionState == ApplicationExecutionState::ApplicationExecutionState_NotRunning; michael@0: ProcessActivationArgs(aArgs, startup); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnSoftkeyboardHidden(IInputPane* aSender, michael@0: IInputPaneVisibilityEventArgs* aArgs) michael@0: { michael@0: LogFunction(); michael@0: sKeyboardIsVisible = false; michael@0: memset(&sKeyboardRect, 0, sizeof(Rect)); michael@0: MetroUtils::FireObserver("metro_softkeyboard_hidden"); michael@0: aArgs->put_EnsuredFocusedElementInView(true); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnSoftkeyboardShown(IInputPane* aSender, michael@0: IInputPaneVisibilityEventArgs* aArgs) michael@0: { michael@0: LogFunction(); michael@0: sKeyboardIsVisible = true; michael@0: aSender->get_OccludedRect(&sKeyboardRect); michael@0: MetroUtils::FireObserver("metro_softkeyboard_shown"); michael@0: aArgs->put_EnsuredFocusedElementInView(true); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnWindowSizeChanged(ICoreWindow* aSender, IWindowSizeChangedEventArgs* aArgs) michael@0: { michael@0: LogFunction(); michael@0: UpdateWidgetSizeAndPosition(); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnWindowActivated(ICoreWindow* aSender, IWindowActivatedEventArgs* aArgs) michael@0: { michael@0: LogFunction(); michael@0: if (!mWidget) { michael@0: return S_OK; michael@0: } michael@0: CoreWindowActivationState state; michael@0: aArgs->get_WindowActivationState(&state); michael@0: mWinActiveState = !(state == CoreWindowActivationState::CoreWindowActivationState_Deactivated); michael@0: SendActivationEvent(); michael@0: return S_OK; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnLogicalDpiChanged(IInspectable* aSender) michael@0: { michael@0: LogFunction(); michael@0: UpdateLogicalDPI(); michael@0: if (mWidget) { michael@0: mWidget->Invalidate(); michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: bool michael@0: FrameworkView::EnsureAutomationProviderCreated() michael@0: { michael@0: #ifdef ACCESSIBILITY michael@0: if (!mWidget || mShuttingDown) michael@0: return false; michael@0: michael@0: if (mAutomationProvider) { michael@0: return true; michael@0: } michael@0: michael@0: Accessible *rootAccessible = mWidget->GetRootAccessible(); michael@0: if (rootAccessible) { michael@0: IInspectable* inspectable; michael@0: HRESULT hr; michael@0: AssertRetHRESULT(hr = UIABridge_CreateInstance(&inspectable), hr); // Addref michael@0: IUIABridge* bridge = nullptr; michael@0: inspectable->QueryInterface(IID_IUIABridge, (void**)&bridge); // Addref michael@0: if (bridge) { michael@0: bridge->Init(this, mWindow.Get(), (ULONG)rootAccessible); michael@0: mAutomationProvider = inspectable; michael@0: inspectable->Release(); michael@0: return true; michael@0: } michael@0: } michael@0: #endif michael@0: return false; michael@0: } michael@0: michael@0: HRESULT michael@0: FrameworkView::OnAutomationProviderRequested(ICoreWindow* aSender, michael@0: IAutomationProviderRequestedEventArgs* aArgs) michael@0: { michael@0: LogFunction(); michael@0: if (!EnsureAutomationProviderCreated()) michael@0: return E_FAIL; michael@0: HRESULT hr = aArgs->put_AutomationProvider(mAutomationProvider.Get()); michael@0: if (FAILED(hr)) { michael@0: WinUtils::Log("put failed? %X", hr); michael@0: } michael@0: return S_OK; michael@0: } michael@0: michael@0: } } }