mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 04:15:43 +00:00
Bug 750901 - Land widget/windows/winrt/* r=bbondy
This commit is contained in:
parent
b3a0b467c6
commit
942f830344
511
widget/windows/winrt/FrameworkView.cpp
Normal file
511
widget/windows/winrt/FrameworkView.cpp
Normal file
@ -0,0 +1,511 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FrameworkView.h"
|
||||
#include "MetroAppShell.h"
|
||||
#include "MetroWidget.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "MetroApp.h"
|
||||
#include "UIABridgePublic.h"
|
||||
#include "KeyboardLayout.h"
|
||||
|
||||
// generated
|
||||
#include "UIABridge.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::widget::winrt;
|
||||
#ifdef ACCESSIBILITY
|
||||
using namespace mozilla::a11y;
|
||||
#endif
|
||||
using namespace ABI::Windows::ApplicationModel;
|
||||
using namespace ABI::Windows::ApplicationModel::Core;
|
||||
using namespace ABI::Windows::ApplicationModel::Activation;
|
||||
using namespace ABI::Windows::UI::Core;
|
||||
using namespace ABI::Windows::UI::ViewManagement;
|
||||
using namespace ABI::Windows::UI::Input;
|
||||
using namespace ABI::Windows::Devices::Input;
|
||||
using namespace ABI::Windows::System;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
|
||||
/*
|
||||
* Due to issues on older platforms with linking the winrt runtime lib we
|
||||
* can't have ref new winrt variables in the global scope. Everything should
|
||||
* be encapsulated in a class. See toolkit/library/nsDllMain for the details.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
// statics
|
||||
bool FrameworkView::sKeyboardIsVisible = false;
|
||||
Rect FrameworkView::sKeyboardRect;
|
||||
nsTArray<nsString>* sSettingsArray;
|
||||
|
||||
FrameworkView::FrameworkView(MetroApp* aMetroApp) :
|
||||
mDPI(-1.0f),
|
||||
mWidget(nullptr),
|
||||
mShuttingDown(false),
|
||||
mMetroApp(aMetroApp),
|
||||
mWindow(nullptr),
|
||||
mMetroInput(nullptr),
|
||||
mWinVisible(false),
|
||||
mWinActiveState(false)
|
||||
{
|
||||
mPainting = false;
|
||||
memset(&sKeyboardRect, 0, sizeof(Rect));
|
||||
sSettingsArray = new nsTArray<nsString>();
|
||||
LogFunction();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// IFrameworkView impl.
|
||||
|
||||
HRESULT
|
||||
FrameworkView::Initialize(ICoreApplicationView* aAppView)
|
||||
{
|
||||
LogFunction();
|
||||
if (mShuttingDown)
|
||||
return E_FAIL;
|
||||
|
||||
aAppView->add_Activated(Callback<__FITypedEventHandler_2_Windows__CApplicationModel__CCore__CCoreApplicationView_Windows__CApplicationModel__CActivation__CIActivatedEventArgs_t>(
|
||||
this, &FrameworkView::OnActivated).Get(), &mActivated);
|
||||
|
||||
//CoCreateInstance(CLSID_WICImagingFactory, nullptr,
|
||||
// CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&mWicFactory));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::Uninitialize()
|
||||
{
|
||||
LogFunction();
|
||||
mShuttingDown = true;
|
||||
mD2DWindowSurface = nullptr;
|
||||
delete sSettingsArray;
|
||||
sSettingsArray = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::Load(HSTRING aEntryPoint)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::Run()
|
||||
{
|
||||
LogFunction();
|
||||
|
||||
// XPCOM is initialized here. mWidget is also created.
|
||||
mMetroApp->Initialize();
|
||||
|
||||
if (mDeferredActivationEventArgs) {
|
||||
RunStartupArgs(mDeferredActivationEventArgs.Get());
|
||||
mDeferredActivationEventArgs = nullptr;
|
||||
}
|
||||
|
||||
// Activate the window
|
||||
mWindow->Activate();
|
||||
|
||||
UpdateSizeAndPosition();
|
||||
|
||||
MetroUtils::GetViewState(mViewState);
|
||||
|
||||
// Get the metro event dispatcher
|
||||
HRESULT hr = mWindow->get_Dispatcher(&mDispatcher);
|
||||
AssertRetHRESULT(hr, hr);
|
||||
|
||||
// Needs mDispatcher
|
||||
AddEventHandlers();
|
||||
|
||||
// Drop into the main metro event loop
|
||||
mDispatcher->ProcessEvents(ABI::Windows::UI::Core::CoreProcessEventsOption::CoreProcessEventsOption_ProcessUntilQuit);
|
||||
|
||||
Log(L"Exiting FrameworkView::Run()");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::SetWindow(ICoreWindow* aWindow)
|
||||
{
|
||||
LogFunction();
|
||||
|
||||
NS_ASSERTION(!mWindow, "Attempting to set a window on a view that already has a window!");
|
||||
NS_ASSERTION(aWindow, "Attempting to set a null window on a view!");
|
||||
|
||||
mWindow = aWindow;
|
||||
UpdateLogicalDPI();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// FrameworkView impl.
|
||||
|
||||
void
|
||||
FrameworkView::AddEventHandlers() {
|
||||
NS_ASSERTION(mWindow, "SetWindow must be called before AddEventHandlers!");
|
||||
NS_ASSERTION(mWidget, "SetWidget must be called before AddEventHAndlers!");
|
||||
NS_ASSERTION(mDispatcher, "Must have a valid CoreDispatcher before "
|
||||
"calling AddEventHAndlers!");
|
||||
|
||||
mMetroInput = Make<MetroInput>(mWidget.Get(),
|
||||
mWindow.Get(),
|
||||
mDispatcher.Get());
|
||||
|
||||
mWindow->add_VisibilityChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CVisibilityChangedEventArgs>(
|
||||
this, &FrameworkView::OnWindowVisibilityChanged).Get(), &mWindowVisibilityChanged);
|
||||
mWindow->add_Activated(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowActivatedEventArgs_t>(
|
||||
this, &FrameworkView::OnWindowActivated).Get(), &mWindowActivated);
|
||||
mWindow->add_Closed(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CCoreWindowEventArgs_t>(
|
||||
this, &FrameworkView::OnWindowClosed).Get(), &mWindowClosed);
|
||||
mWindow->add_SizeChanged(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t>(
|
||||
this, &FrameworkView::OnWindowSizeChanged).Get(), &mWindowSizeChanged);
|
||||
|
||||
mWindow->add_AutomationProviderRequested(Callback<__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CAutomationProviderRequestedEventArgs_t>(
|
||||
this, &FrameworkView::OnAutomationProviderRequested).Get(), &mAutomationProviderRequested);
|
||||
|
||||
HRESULT hr;
|
||||
ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> dispProps;
|
||||
if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), dispProps.GetAddressOf()))) {
|
||||
hr = dispProps->add_LogicalDpiChanged(Callback<ABI::Windows::Graphics::Display::IDisplayPropertiesEventHandler, FrameworkView>(
|
||||
this, &FrameworkView::OnLogicalDpiChanged).Get(), &mDisplayPropertiesChanged);
|
||||
LogHRESULT(hr);
|
||||
}
|
||||
|
||||
ComPtr<ABI::Windows::UI::ViewManagement::IInputPaneStatics> inputStatic;
|
||||
if (SUCCEEDED(hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), inputStatic.GetAddressOf()))) {
|
||||
ComPtr<ABI::Windows::UI::ViewManagement::IInputPane> inputPane;
|
||||
if (SUCCEEDED(inputStatic->GetForCurrentView(inputPane.GetAddressOf()))) {
|
||||
inputPane->add_Hiding(Callback<__FITypedEventHandler_2_Windows__CUI__CViewManagement__CInputPane_Windows__CUI__CViewManagement__CInputPaneVisibilityEventArgs_t>(
|
||||
this, &FrameworkView::OnSoftkeyboardHidden).Get(), &mSoftKeyboardHidden);
|
||||
inputPane->add_Showing(Callback<__FITypedEventHandler_2_Windows__CUI__CViewManagement__CInputPane_Windows__CUI__CViewManagement__CInputPaneVisibilityEventArgs_t>(
|
||||
this, &FrameworkView::OnSoftkeyboardShown).Get(), &mSoftKeyboardShown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called by MetroApp
|
||||
void
|
||||
FrameworkView::ShutdownXPCOM()
|
||||
{
|
||||
mShuttingDown = true;
|
||||
mWidget = nullptr;
|
||||
ComPtr<IUIABridge> provider;
|
||||
if (mAutomationProvider) {
|
||||
mAutomationProvider.As(&provider);
|
||||
if (provider) {
|
||||
provider->Disconnect();
|
||||
}
|
||||
}
|
||||
mAutomationProvider = nullptr;
|
||||
mMetroInput = nullptr;
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::SetCursor(CoreCursorType aCursorType, DWORD aCustomId)
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(mWindow, "SetWindow must be called before SetCursor!");
|
||||
ComPtr<ABI::Windows::UI::Core::ICoreCursorFactory> factory;
|
||||
AssertHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), factory.GetAddressOf()));
|
||||
ComPtr<ABI::Windows::UI::Core::ICoreCursor> cursor;
|
||||
AssertHRESULT(factory->CreateCursor(aCursorType, aCustomId, cursor.GetAddressOf()));
|
||||
mWindow->put_PointerCursor(cursor.Get());
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::ClearCursor()
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(mWindow, "SetWindow must be called before ClearCursor!");
|
||||
mWindow->put_PointerCursor(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::UpdateLogicalDPI()
|
||||
{
|
||||
ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> dispProps;
|
||||
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(),
|
||||
dispProps.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
FLOAT value;
|
||||
AssertHRESULT(dispProps->get_LogicalDpi(&value));
|
||||
SetDpi(value);
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::GetBounds(nsIntRect &aRect)
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(mWindow, "SetWindow must be called before GetBounds!");
|
||||
Rect msrect;
|
||||
mWindow->get_Bounds(&msrect);
|
||||
nsIntRect mozrect(0, 0, (uint32_t)ceil(msrect.Width),
|
||||
(uint32_t)ceil(msrect.Height));
|
||||
aRect = mozrect;
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::UpdateSizeAndPosition()
|
||||
{
|
||||
if (mShuttingDown)
|
||||
return;
|
||||
|
||||
NS_ASSERTION(mWindow, "SetWindow must be called before UpdateSizeAndPosition!");
|
||||
NS_ASSERTION(mWidget, "SetWidget must be called before UpdateSizeAndPosition!");
|
||||
|
||||
Rect rect;
|
||||
mWindow->get_Bounds(&rect);
|
||||
mWidget->Move(0, 0);
|
||||
mWidget->Resize(0, 0, (uint32_t)ceil(rect.Width),
|
||||
(uint32_t)ceil(rect.Height), true);
|
||||
mWidget->SizeModeChanged();
|
||||
}
|
||||
|
||||
bool
|
||||
FrameworkView::IsEnabled() const
|
||||
{
|
||||
return mWinActiveState;
|
||||
}
|
||||
|
||||
bool
|
||||
FrameworkView::IsVisible() const
|
||||
{
|
||||
// we could check the wnd in MetroWidget for this, but
|
||||
// generally we don't let nsIWidget control visibility
|
||||
// or activation.
|
||||
return mWinVisible;
|
||||
}
|
||||
|
||||
void FrameworkView::SetDpi(float aDpi)
|
||||
{
|
||||
if (aDpi != mDPI) {
|
||||
mDPI = aDpi;
|
||||
// Often a DPI change implies a window size change. In some cases Windows will issues
|
||||
// both a size changed event and a DPI changed event. In this case, the resulting bounds
|
||||
// will not change, and the window resize code will only be executed once.
|
||||
UpdateForWindowSizeChange();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::SetWidget(MetroWidget* aWidget)
|
||||
{
|
||||
NS_ASSERTION(!mWidget, "Attempting to set a widget for a view that already has a widget!");
|
||||
NS_ASSERTION(aWidget, "Attempting to set a null widget for a view!");
|
||||
LogFunction();
|
||||
mWidget = aWidget;
|
||||
mWidget->FindMetroWindow();
|
||||
}
|
||||
|
||||
// This routine is called in the event handler for the view SizeChanged event.
|
||||
void
|
||||
FrameworkView::UpdateForWindowSizeChange()
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(mWindow, "SetWindow must be called before UpdateForWindowSizeChange!");
|
||||
mWindow->get_Bounds(&mWindowBounds);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Event handlers
|
||||
|
||||
void
|
||||
FrameworkView::SendActivationEvent()
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(mWindow, "SetWindow must be called before SendActivationEvent!");
|
||||
mWidget->Activated(mWinActiveState);
|
||||
UpdateSizeAndPosition();
|
||||
EnsureAutomationProviderCreated();
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnWindowVisibilityChanged(ICoreWindow* aWindow,
|
||||
IVisibilityChangedEventArgs* aArgs)
|
||||
{
|
||||
// If we're visible, or we can't determine if we're visible, just store
|
||||
// that we are visible.
|
||||
boolean visible;
|
||||
mWinVisible = FAILED(aArgs->get_Visible(&visible)) || visible;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnActivated(ICoreApplicationView* aApplicationView,
|
||||
IActivatedEventArgs* aArgs)
|
||||
{
|
||||
LogFunction();
|
||||
// If we're on startup, we want to wait for FrameworkView::Run to run because
|
||||
// XPCOM is not initialized yet and and we can't use nsICommandLineRunner
|
||||
|
||||
ApplicationExecutionState state;
|
||||
aArgs->get_PreviousExecutionState(&state);
|
||||
if (state != ApplicationExecutionState::ApplicationExecutionState_Terminated &&
|
||||
state != ApplicationExecutionState::ApplicationExecutionState_ClosedByUser &&
|
||||
state != ApplicationExecutionState::ApplicationExecutionState_NotRunning) {
|
||||
RunStartupArgs(aArgs);
|
||||
} else {
|
||||
mDeferredActivationEventArgs = aArgs;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnSoftkeyboardHidden(IInputPane* aSender,
|
||||
IInputPaneVisibilityEventArgs* aArgs)
|
||||
{
|
||||
LogFunction();
|
||||
if (mShuttingDown)
|
||||
return S_OK;
|
||||
sKeyboardIsVisible = false;
|
||||
memset(&sKeyboardRect, 0, sizeof(Rect));
|
||||
MetroUtils::FireObserver("metro_softkeyboard_hidden");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnSoftkeyboardShown(IInputPane* aSender,
|
||||
IInputPaneVisibilityEventArgs* aArgs)
|
||||
{
|
||||
LogFunction();
|
||||
if (mShuttingDown)
|
||||
return S_OK;
|
||||
sKeyboardIsVisible = true;
|
||||
aSender->get_OccludedRect(&sKeyboardRect);
|
||||
MetroUtils::FireObserver("metro_softkeyboard_shown");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnWindowClosed(ICoreWindow* aSender, ICoreWindowEventArgs* aArgs)
|
||||
{
|
||||
// this doesn't seem very reliable
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::FireViewStateObservers()
|
||||
{
|
||||
ApplicationViewState state;
|
||||
MetroUtils::GetViewState(state);
|
||||
if (state == mViewState) {
|
||||
return;
|
||||
}
|
||||
mViewState = state;
|
||||
nsAutoString name;
|
||||
switch (mViewState) {
|
||||
case ApplicationViewState_FullScreenLandscape:
|
||||
name.AssignLiteral("landscape");
|
||||
break;
|
||||
case ApplicationViewState_Filled:
|
||||
name.AssignLiteral("filled");
|
||||
break;
|
||||
case ApplicationViewState_Snapped:
|
||||
name.AssignLiteral("snapped");
|
||||
break;
|
||||
case ApplicationViewState_FullScreenPortrait:
|
||||
name.AssignLiteral("portrait");
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Unknown view state");
|
||||
return;
|
||||
};
|
||||
MetroUtils::FireObserver("metro_viewstate_changed", name.get());
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnWindowSizeChanged(ICoreWindow* aSender, IWindowSizeChangedEventArgs* aArgs)
|
||||
{
|
||||
LogFunction();
|
||||
UpdateForWindowSizeChange();
|
||||
UpdateSizeAndPosition();
|
||||
FireViewStateObservers();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnWindowActivated(ICoreWindow* aSender, IWindowActivatedEventArgs* aArgs)
|
||||
{
|
||||
LogFunction();
|
||||
if (mShuttingDown || !mWidget)
|
||||
return E_FAIL;
|
||||
CoreWindowActivationState state;
|
||||
aArgs->get_WindowActivationState(&state);
|
||||
mWinActiveState = !(state == CoreWindowActivationState::CoreWindowActivationState_Deactivated);
|
||||
SendActivationEvent();
|
||||
|
||||
// Flush out all remaining events so base widget doesn't process other stuff
|
||||
// earlier which would lead to a white flash of a second at startup.
|
||||
MetroAppShell::ProcessAllNativeEventsPresent();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnLogicalDpiChanged(IInspectable* aSender)
|
||||
{
|
||||
LogFunction();
|
||||
UpdateLogicalDPI();
|
||||
Render();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
FrameworkView::EnsureAutomationProviderCreated()
|
||||
{
|
||||
#ifdef ACCESSIBILITY
|
||||
if (!mWidget || mShuttingDown)
|
||||
return false;
|
||||
|
||||
if (mAutomationProvider) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Accessible *rootAccessible = mWidget->GetRootAccessible();
|
||||
if (rootAccessible) {
|
||||
IInspectable* inspectable;
|
||||
HRESULT hr;
|
||||
AssertRetHRESULT(hr = UIABridge_CreateInstance(&inspectable), hr); // Addref
|
||||
IUIABridge* bridge = nullptr;
|
||||
inspectable->QueryInterface(IID_IUIABridge, (void**)&bridge); // Addref
|
||||
if (bridge) {
|
||||
bridge->Init(this, mWindow.Get(), (ULONG)rootAccessible);
|
||||
mAutomationProvider = inspectable;
|
||||
inspectable->Release();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnAutomationProviderRequested(ICoreWindow* aSender,
|
||||
IAutomationProviderRequestedEventArgs* aArgs)
|
||||
{
|
||||
if (!EnsureAutomationProviderCreated())
|
||||
return E_FAIL;
|
||||
aArgs->put_AutomationProvider(mAutomationProvider.Get());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} } }
|
202
widget/windows/winrt/FrameworkView.h
Normal file
202
widget/windows/winrt/FrameworkView.h
Normal file
@ -0,0 +1,202 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsGUIEvent.h"
|
||||
#include "MetroInput.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "MetroWidget.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
#include <windows.system.h>
|
||||
#include <Windows.ApplicationModel.core.h>
|
||||
#include <Windows.ApplicationModel.h>
|
||||
#include <Windows.Applicationmodel.Activation.h>
|
||||
#include <Windows.ApplicationModel.search.h>
|
||||
#include <windows.ui.core.h>
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
#include <windows.ui.applicationsettings.h>
|
||||
#include <windows.ui.popups.h>
|
||||
#include <windows.graphics.printing.h>
|
||||
#include <windows.graphics.display.h>
|
||||
#include <windows.media.playto.h>
|
||||
#include <d2d1_1.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
class MetroApp;
|
||||
|
||||
class FrameworkView : public Microsoft::WRL::RuntimeClass<ABI::Windows::ApplicationModel::Core::IFrameworkView>
|
||||
{
|
||||
InspectableClass(L"FrameworkView", TrustLevel::BaseTrust)
|
||||
|
||||
typedef mozilla::layers::LayerManager LayerManager;
|
||||
|
||||
typedef ABI::Windows::Foundation::Rect Rect;
|
||||
typedef ABI::Windows::UI::Core::IWindowSizeChangedEventArgs IWindowSizeChangedEventArgs;
|
||||
typedef ABI::Windows::UI::Core::ICoreWindowEventArgs ICoreWindowEventArgs;
|
||||
typedef ABI::Windows::UI::Core::IWindowActivatedEventArgs IWindowActivatedEventArgs;
|
||||
typedef ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs IAutomationProviderRequestedEventArgs;
|
||||
typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow;
|
||||
typedef ABI::Windows::UI::Core::ICoreDispatcher ICoreDispatcher;
|
||||
typedef ABI::Windows::UI::Core::IVisibilityChangedEventArgs IVisibilityChangedEventArgs;
|
||||
typedef ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs IInputPaneVisibilityEventArgs;
|
||||
typedef ABI::Windows::UI::ViewManagement::IInputPane IInputPane;
|
||||
typedef ABI::Windows::UI::ViewManagement::ApplicationViewState ApplicationViewState;
|
||||
typedef ABI::Windows::UI::ApplicationSettings::ISettingsPane ISettingsPane;
|
||||
typedef ABI::Windows::UI::ApplicationSettings::ISettingsPaneCommandsRequestedEventArgs ISettingsPaneCommandsRequestedEventArgs;
|
||||
typedef ABI::Windows::UI::Popups::IUICommand IUICommand;
|
||||
typedef ABI::Windows::ApplicationModel::Activation::ILaunchActivatedEventArgs ILaunchActivatedEventArgs;
|
||||
typedef ABI::Windows::ApplicationModel::Activation::IActivatedEventArgs IActivatedEventArgs;
|
||||
typedef ABI::Windows::ApplicationModel::Activation::ISearchActivatedEventArgs ISearchActivatedEventArgs;
|
||||
typedef ABI::Windows::ApplicationModel::Activation::IFileActivatedEventArgs IFileActivatedEventArgs;
|
||||
typedef ABI::Windows::ApplicationModel::Core::ICoreApplicationView ICoreApplicationView;
|
||||
typedef ABI::Windows::ApplicationModel::DataTransfer::IDataTransferManager IDataTransferManager;
|
||||
typedef ABI::Windows::ApplicationModel::DataTransfer::IDataRequestedEventArgs IDataRequestedEventArgs;
|
||||
typedef ABI::Windows::ApplicationModel::Search::ISearchPane ISearchPane;
|
||||
typedef ABI::Windows::ApplicationModel::Search::ISearchPaneQuerySubmittedEventArgs ISearchPaneQuerySubmittedEventArgs;
|
||||
typedef ABI::Windows::Media::PlayTo::IPlayToManager IPlayToManager;
|
||||
typedef ABI::Windows::Media::PlayTo::IPlayToSourceRequestedEventArgs IPlayToSourceRequestedEventArgs;
|
||||
typedef ABI::Windows::Graphics::Printing::IPrintManager IPrintManager;
|
||||
typedef ABI::Windows::Graphics::Printing::IPrintTaskRequestedEventArgs IPrintTaskRequestedEventArgs;
|
||||
typedef ABI::Windows::Graphics::Printing::IPrintTaskSourceRequestedArgs IPrintTaskSourceRequestedArgs;
|
||||
|
||||
public:
|
||||
FrameworkView(MetroApp* aMetroApp);
|
||||
|
||||
// IFrameworkView Methods
|
||||
STDMETHODIMP Initialize(ICoreApplicationView* aAppView);
|
||||
STDMETHODIMP SetWindow(ICoreWindow* aWindow);
|
||||
STDMETHODIMP Load(HSTRING aEntryPoint);
|
||||
STDMETHODIMP Run();
|
||||
STDMETHODIMP Uninitialize();
|
||||
|
||||
// Public apis for MetroWidget
|
||||
void ShutdownXPCOM();
|
||||
bool Render();
|
||||
bool Render(const nsIntRegion& aInvalidRegion);
|
||||
float GetDPI() { return mDPI; }
|
||||
ICoreWindow* GetCoreWindow() { return mWindow.Get(); }
|
||||
void SetWidget(MetroWidget* aWidget);
|
||||
MetroWidget* GetWidget() { return mWidget.Get(); }
|
||||
void GetBounds(nsIntRect &aRect);
|
||||
void SetCursor(ABI::Windows::UI::Core::CoreCursorType aCursorType, DWORD aCustomId = 0);
|
||||
void ClearCursor();
|
||||
bool IsEnabled() const;
|
||||
bool IsVisible() const;
|
||||
|
||||
// Soft keyboard info for nsIWinMetroUtils
|
||||
static bool IsKeyboardVisible() { return sKeyboardIsVisible; }
|
||||
static ABI::Windows::Foundation::Rect KeyboardVisibleRect() { return sKeyboardRect; }
|
||||
|
||||
// MetroApp apis
|
||||
void SetupContracts();
|
||||
|
||||
// MetroContracts settings panel enumerator entry
|
||||
void AddSetting(ISettingsPaneCommandsRequestedEventArgs* aArgs, uint32_t aId,
|
||||
Microsoft::WRL::Wrappers::HString& aSettingName);
|
||||
protected:
|
||||
// Event Handlers
|
||||
HRESULT OnActivated(ICoreApplicationView* aApplicationView,
|
||||
IActivatedEventArgs* aArgs);
|
||||
HRESULT OnWindowVisibilityChanged(ICoreWindow* aCoreWindow,
|
||||
IVisibilityChangedEventArgs* aArgs);
|
||||
|
||||
HRESULT OnWindowSizeChanged(ICoreWindow* aSender,
|
||||
IWindowSizeChangedEventArgs* aArgs);
|
||||
HRESULT OnWindowClosed(ICoreWindow* aSender,
|
||||
ICoreWindowEventArgs* aArgs);
|
||||
HRESULT OnWindowActivated(ICoreWindow* aSender,
|
||||
IWindowActivatedEventArgs* aArgs);
|
||||
HRESULT OnLogicalDpiChanged(IInspectable* aSender);
|
||||
|
||||
HRESULT OnAutomationProviderRequested(ICoreWindow* aSender,
|
||||
IAutomationProviderRequestedEventArgs* aArgs);
|
||||
|
||||
HRESULT OnSoftkeyboardHidden(IInputPane* aSender,
|
||||
IInputPaneVisibilityEventArgs* aArgs);
|
||||
HRESULT OnSoftkeyboardShown(IInputPane* aSender,
|
||||
IInputPaneVisibilityEventArgs* aArgs);
|
||||
|
||||
HRESULT OnDataShareRequested(IDataTransferManager*, IDataRequestedEventArgs* aArgs);
|
||||
HRESULT OnSearchQuerySubmitted(ISearchPane* aPane, ISearchPaneQuerySubmittedEventArgs* aArgs);
|
||||
HRESULT OnSettingsCommandsRequested(ISettingsPane* aPane, ISettingsPaneCommandsRequestedEventArgs* aArgs);
|
||||
HRESULT OnPlayToSourceRequested(IPlayToManager* aPane, IPlayToSourceRequestedEventArgs* aArgs);
|
||||
HRESULT OnSettingsCommandInvoked(IUICommand* aCommand);
|
||||
HRESULT OnPrintTaskRequested(IPrintManager* aMgr, IPrintTaskRequestedEventArgs* aArgs);
|
||||
HRESULT OnPrintTaskSourceRequested(IPrintTaskSourceRequestedArgs* aArgs);
|
||||
|
||||
protected:
|
||||
void SetDpi(float aDpi);
|
||||
void UpdateSizeAndPosition();
|
||||
void PerformURILoad(Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IUriRuntimeClass>& aURI);
|
||||
void PerformSearch(Microsoft::WRL::Wrappers::HString& aQuery);
|
||||
void PerformURILoadOrSearch(Microsoft::WRL::Wrappers::HString& aString);
|
||||
bool EnsureAutomationProviderCreated();
|
||||
void SearchActivated(Microsoft::WRL::ComPtr<ISearchActivatedEventArgs>& aArgs);
|
||||
void FileActivated(Microsoft::WRL::ComPtr<IFileActivatedEventArgs>& aArgs);
|
||||
void LaunchActivated(Microsoft::WRL::ComPtr<ILaunchActivatedEventArgs>& aArgs);
|
||||
void RunStartupArgs(IActivatedEventArgs* aArgs);
|
||||
void UpdateForWindowSizeChange();
|
||||
void SendActivationEvent();
|
||||
void UpdateLogicalDPI();
|
||||
void FireViewStateObservers();
|
||||
|
||||
// Printing and preview
|
||||
void CreatePrintControl(IPrintDocumentPackageTarget* aDocPackageTarget,
|
||||
D2D1_PRINT_CONTROL_PROPERTIES* aPrintControlProperties);
|
||||
HRESULT ClosePrintControl();
|
||||
void PrintPage(uint32_t aPageNumber, D2D1_RECT_F aImageableArea,
|
||||
D2D1_SIZE_F aPageSize, IStream* aPagePrintTicketStream);
|
||||
void AddEventHandlers();
|
||||
|
||||
private:
|
||||
EventRegistrationToken mActivated;
|
||||
EventRegistrationToken mWindowActivated;
|
||||
EventRegistrationToken mWindowVisibilityChanged;
|
||||
EventRegistrationToken mWindowClosed;
|
||||
EventRegistrationToken mWindowSizeChanged;
|
||||
EventRegistrationToken mSoftKeyboardHidden;
|
||||
EventRegistrationToken mSoftKeyboardShown;
|
||||
EventRegistrationToken mDisplayPropertiesChanged;
|
||||
EventRegistrationToken mAutomationProviderRequested;
|
||||
EventRegistrationToken mDataTransferRequested;
|
||||
EventRegistrationToken mSearchQuerySubmitted;
|
||||
EventRegistrationToken mPlayToRequested;
|
||||
EventRegistrationToken mSettingsPane;
|
||||
EventRegistrationToken mPrintManager;
|
||||
|
||||
private:
|
||||
nsRefPtr<gfxD2DSurface> mD2DWindowSurface;
|
||||
Rect mWindowBounds;
|
||||
float mDPI;
|
||||
bool mShuttingDown;
|
||||
bool mPainting;
|
||||
Microsoft::WRL::ComPtr<IInspectable> mAutomationProvider;
|
||||
Microsoft::WRL::ComPtr<IActivatedEventArgs> mDeferredActivationEventArgs;
|
||||
//Microsoft::WRL::ComPtr<ID2D1PrintControl> mD2DPrintControl;
|
||||
// Private critical section protects D2D device context for on-screen
|
||||
// rendering from that for print/preview in the different thread.
|
||||
//Microsoft::WRL::ComPtr<IWICImagingFactory2> mWicFactory;
|
||||
Microsoft::WRL::ComPtr<MetroApp> mMetroApp;
|
||||
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
||||
Microsoft::WRL::ComPtr<ICoreDispatcher> mDispatcher;
|
||||
Microsoft::WRL::ComPtr<MetroWidget> mWidget;
|
||||
Microsoft::WRL::ComPtr<MetroInput> mMetroInput;
|
||||
static bool sKeyboardIsVisible;
|
||||
static Rect sKeyboardRect;
|
||||
bool mWinVisible;
|
||||
bool mWinActiveState;
|
||||
ApplicationViewState mViewState;
|
||||
};
|
||||
|
||||
} } }
|
76
widget/windows/winrt/FrameworkViewGfx.cpp
Normal file
76
widget/windows/winrt/FrameworkViewGfx.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "FrameworkView.h"
|
||||
#include "MetroWidget.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "nsIWidgetListener.h"
|
||||
|
||||
#include <windows.ui.xaml.media.dxinterop.h>
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
static bool
|
||||
IsRenderMode(gfxWindowsPlatform::RenderMode aRMode)
|
||||
{
|
||||
return gfxWindowsPlatform::GetPlatform()->GetRenderMode() == aRMode;
|
||||
}
|
||||
|
||||
bool
|
||||
FrameworkView::Render()
|
||||
{
|
||||
Rect msrect;
|
||||
mWindow->get_Bounds(&msrect);
|
||||
nsIntRegion region(nsIntRect(0, 0, (uint32_t)ceil(msrect.Width),
|
||||
(uint32_t)ceil(msrect.Height)));
|
||||
return Render(region);
|
||||
}
|
||||
|
||||
bool
|
||||
FrameworkView::Render(const nsIntRegion& aInvalidRegion)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
|
||||
|
||||
if (mShuttingDown || mPainting || !mWidget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we haven't created the layer manager, then create it now.
|
||||
// The swap buffer will be resized automatically by the layer manager.
|
||||
if (!mWidget->mLayerManager) {
|
||||
(void)mWidget->GetLayerManager();
|
||||
if (!mWidget->mLayerManager) {
|
||||
NS_WARNING("mWidget->GetLayerManager() failed!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) ||
|
||||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH32) ||
|
||||
IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_STRETCH24)) {
|
||||
NS_WARNING("Unsupported render mode, can't draw. Needs to be D2D.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mWidget->GetTransparencyMode() != eTransparencyOpaque) {
|
||||
NS_WARNING("transparency modes other than eTransparencyOpaque unsupported, can't draw.");
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoRestore<bool> painting(mPainting);
|
||||
mPainting = true;
|
||||
UpdateForWindowSizeChange();
|
||||
gfxWindowsPlatform::GetPlatform()->UpdateRenderMode();
|
||||
mWidget->Paint(aInvalidRegion);
|
||||
return true;
|
||||
}
|
||||
|
||||
} } }
|
81
widget/windows/winrt/Makefile.in
Normal file
81
widget/windows/winrt/Makefile.in
Normal file
@ -0,0 +1,81 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = widget
|
||||
LIBRARY_NAME = widget_winrt
|
||||
EXPORT_LIBRARY = 1
|
||||
IS_COMPONENT = 1
|
||||
MODULE_NAME = WidgetWinRTModule
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
CPPSRCS = \
|
||||
MetroApp.cpp \
|
||||
MetroWidget.cpp \
|
||||
MetroAppShell.cpp \
|
||||
MetroUtils.cpp \
|
||||
FrameworkView.cpp \
|
||||
FrameworkViewGfx.cpp \
|
||||
nsWinMetroUtils.cpp \
|
||||
MetroInput.cpp \
|
||||
UIABridge.cpp \
|
||||
UIAAccessibilityBridge.cpp \
|
||||
MetroContracts.cpp \
|
||||
nsMetroFilePicker.cpp \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_WIDGET -DMOZ_UNICODE
|
||||
|
||||
ifdef MOZ_ENABLE_D3D9_LAYER
|
||||
DEFINES += -DMOZ_ENABLE_D3D9_LAYER
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_D3D10_LAYER
|
||||
DEFINES += -DMOZ_ENABLE_D3D10_LAYER
|
||||
endif
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I. \
|
||||
-I$(srcdir)/../../xpwidgets \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../ \
|
||||
-I$(topsrcdir)/layout/generic \
|
||||
-I$(topsrcdir)/layout/xul/base/src \
|
||||
-I$(topsrcdir)/toolkit/xre \
|
||||
-I$(topsrcdir)/xpcom/base \
|
||||
$(NULL)
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
MIDL_GENERATED_FILES = \
|
||||
UIABridge_i.c \
|
||||
UIABridge_p.c \
|
||||
dlldata.c \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = components.manifest \
|
||||
$(NULL)
|
||||
EXTRA_COMPONENTS = MetroUIUtils.js \
|
||||
$(NULL)
|
||||
|
||||
GARBAGE += $(MIDL_GENERATED_FILES) done_gen
|
||||
|
||||
do_interfaces_gen: UIABridge.idl
|
||||
$(MIDL) $(srcdir)/UIABridge.idl -I $(srcdir)
|
||||
touch $@
|
||||
|
||||
export:: do_interfaces_gen
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
|
238
widget/windows/winrt/MetroApp.cpp
Normal file
238
widget/windows/winrt/MetroApp.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MetroApp.h"
|
||||
#include "MetroWidget.h"
|
||||
#include "mozilla/widget/AudioSession.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "MetroAppShell.h"
|
||||
#include "nsICommandLineRunner.h"
|
||||
#include "FrameworkView.h"
|
||||
|
||||
using namespace ABI::Windows::ApplicationModel;
|
||||
using namespace ABI::Windows::ApplicationModel::Core;
|
||||
using namespace ABI::Windows::UI::Core;
|
||||
using namespace ABI::Windows::System;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
|
||||
// XXX move
|
||||
#pragma comment(lib, "dwrite.lib")
|
||||
#pragma comment(lib, "d2d1.lib")
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "runtimeobject.lib")
|
||||
|
||||
// Metro specific XRE methods we call from here on an
|
||||
// appropriate thread.
|
||||
extern nsresult XRE_metroStartup();
|
||||
extern void XRE_metroShutdown();
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gWindowsLog;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
ComPtr<FrameworkView> sFrameworkView;
|
||||
ComPtr<MetroApp> sMetroApp;
|
||||
ComPtr<ICoreApplication> sCoreApp;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// IFrameworkViewSource impl.
|
||||
|
||||
// Called after CoreApplication::Run(app)
|
||||
HRESULT
|
||||
MetroApp::CreateView(ABI::Windows::ApplicationModel::Core::IFrameworkView **aViewProvider)
|
||||
{
|
||||
// This entry point is called on the metro main thread, but the thread won't be
|
||||
// recognized as such until after Initialize is called below. XPCOM has not gone
|
||||
// through startup at this point.
|
||||
|
||||
LogFunction();
|
||||
|
||||
sFrameworkView = Make<FrameworkView>(this);
|
||||
*aViewProvider = sFrameworkView.Get();
|
||||
return !sFrameworkView ? E_FAIL : S_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// MetroApp impl.
|
||||
|
||||
// called after FrameworkView::Run() drops into the event dispatch loop
|
||||
void
|
||||
MetroApp::Initialize()
|
||||
{
|
||||
HRESULT hr;
|
||||
LogThread();
|
||||
|
||||
static bool xpcomInit;
|
||||
if (!xpcomInit) {
|
||||
xpcomInit = true;
|
||||
Log(L"XPCOM startup initialization began");
|
||||
nsresult rv = XRE_metroStartup();
|
||||
Log(L"XPCOM startup initialization complete");
|
||||
if (NS_FAILED(rv)) {
|
||||
Log(L"XPCOM startup initialization failed, bailing. rv=%X", rv);
|
||||
CoreExit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sFrameworkView->SetupContracts();
|
||||
|
||||
hr = sCoreApp->add_Suspending(Callback<__FIEventHandler_1_Windows__CApplicationModel__CSuspendingEventArgs_t>(
|
||||
this, &MetroApp::OnSuspending).Get(), &mSuspendEvent);
|
||||
AssertHRESULT(hr);
|
||||
|
||||
hr = sCoreApp->add_Resuming(Callback<__FIEventHandler_1_IInspectable_t>(
|
||||
this, &MetroApp::OnResuming).Get(), &mResumeEvent);
|
||||
AssertHRESULT(hr);
|
||||
|
||||
mozilla::widget::StartAudioSession();
|
||||
}
|
||||
|
||||
// Free all xpcom related resources before calling the xre shutdown call.
|
||||
// Must be called on the metro main thread. Currently called from appshell.
|
||||
void
|
||||
MetroApp::ShutdownXPCOM()
|
||||
{
|
||||
LogThread();
|
||||
|
||||
mozilla::widget::StopAudioSession();
|
||||
|
||||
sCoreApp->remove_Suspending(mSuspendEvent);
|
||||
sCoreApp->remove_Resuming(mResumeEvent);
|
||||
|
||||
MetroApp::GetView()->ShutdownXPCOM();
|
||||
|
||||
// Shut down xpcom
|
||||
XRE_metroShutdown();
|
||||
}
|
||||
|
||||
// Request a shutdown of the application
|
||||
void
|
||||
MetroApp::CoreExit()
|
||||
{
|
||||
HRESULT hr;
|
||||
ComPtr<ICoreApplicationExit> coreExit;
|
||||
HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
|
||||
hr = GetActivationFactory(className.Get(), coreExit.GetAddressOf());
|
||||
NS_ASSERTION(SUCCEEDED(hr), "Activation of ICoreApplicationExit");
|
||||
if (SUCCEEDED(hr)) {
|
||||
coreExit->Exit();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
FrameworkView*
|
||||
MetroApp::GetView()
|
||||
{
|
||||
NS_ASSERTION(sFrameworkView, "view has not been created.");
|
||||
return sFrameworkView.Get();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// MetroApp events
|
||||
|
||||
HRESULT
|
||||
MetroApp::OnSuspending(IInspectable* aSender, ISuspendingEventArgs* aArgs)
|
||||
{
|
||||
LogThread();
|
||||
PostSuspendResumeProcessNotification(true);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MetroApp::OnResuming(IInspectable* aSender, IInspectable* aArgs)
|
||||
{
|
||||
LogThread();
|
||||
PostSuspendResumeProcessNotification(false);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MetroApp::OnAsyncTileCreated(ABI::Windows::Foundation::IAsyncOperation<bool>* aOperation,
|
||||
AsyncStatus aStatus)
|
||||
{
|
||||
Log(L"Async operation status: %d", aStatus);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
MetroApp::SetBaseWidget(MetroWidget* aPtr)
|
||||
{
|
||||
LogThread();
|
||||
NS_ASSERTION(aPtr, "setting null base widget?");
|
||||
aPtr->SetView(sFrameworkView.Get());
|
||||
sFrameworkView->SetWidget(aPtr);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
MetroApp::PostSuspendResumeProcessNotification(const bool aIsSuspend)
|
||||
{
|
||||
static bool isSuspend = false;
|
||||
if (isSuspend == aIsSuspend) {
|
||||
return;
|
||||
}
|
||||
isSuspend = aIsSuspend;
|
||||
MetroUtils::FireObserver(aIsSuspend ? "suspend_process_notification" :
|
||||
"resume_process_notification");
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
MetroApp::PostSleepWakeNotification(const bool aIsSleep)
|
||||
{
|
||||
static bool isSleep = false;
|
||||
if (isSleep == aIsSleep) {
|
||||
return;
|
||||
}
|
||||
isSleep = aIsSleep;
|
||||
MetroUtils::FireObserver(aIsSleep ? "sleep_notification" :
|
||||
"wake_notification");
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
bool
|
||||
XRE_MetroCoreApplicationRun()
|
||||
{
|
||||
HRESULT hr;
|
||||
LogThread();
|
||||
|
||||
using namespace mozilla::widget::winrt;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gWindowsLog) {
|
||||
gWindowsLog = PR_NewLogModule("nsWindow");
|
||||
}
|
||||
#endif
|
||||
|
||||
sMetroApp = Make<MetroApp>();
|
||||
|
||||
HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
|
||||
hr = GetActivationFactory(className.Get(), sCoreApp.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
LogHRESULT(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
sCoreApp->Run(sMetroApp.Get());
|
||||
|
||||
Log(L"Exiting CoreApplication::Run");
|
||||
|
||||
sFrameworkView = nullptr;
|
||||
sCoreApp = nullptr;
|
||||
sMetroApp = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
61
widget/windows/winrt/MetroApp.h
Normal file
61
widget/windows/winrt/MetroApp.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
#include <windows.system.h>
|
||||
#include <windows.ui.core.h>
|
||||
#include <Windows.ApplicationModel.core.h>
|
||||
#include <Windows.ApplicationModel.h>
|
||||
#include <Windows.Applicationmodel.Activation.h>
|
||||
|
||||
class MetroWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
class FrameworkView;
|
||||
|
||||
class MetroApp : public Microsoft::WRL::RuntimeClass<ABI::Windows::ApplicationModel::Core::IFrameworkViewSource>
|
||||
{
|
||||
InspectableClass(L"MetroApp", TrustLevel::BaseTrust)
|
||||
|
||||
typedef ABI::Windows::UI::Core::CoreDispatcherPriority CoreDispatcherPriority;
|
||||
typedef ABI::Windows::ApplicationModel::Activation::LaunchActivatedEventArgs LaunchActivatedEventArgs;
|
||||
typedef ABI::Windows::ApplicationModel::ISuspendingEventArgs ISuspendingEventArgs;
|
||||
typedef ABI::Windows::ApplicationModel::Core::IFrameworkView IFrameworkView;
|
||||
typedef ABI::Windows::ApplicationModel::Core::ICoreApplication ICoreApplication;
|
||||
|
||||
public:
|
||||
// IFrameworkViewSource
|
||||
STDMETHODIMP CreateView(IFrameworkView **viewProvider);
|
||||
|
||||
// ICoreApplication event
|
||||
HRESULT OnSuspending(IInspectable* aSender, ISuspendingEventArgs* aArgs);
|
||||
HRESULT OnResuming(IInspectable* aSender, IInspectable* aArgs);
|
||||
|
||||
// nsIWinMetroUtils tile related async callbacks
|
||||
HRESULT OnAsyncTileCreated(ABI::Windows::Foundation::IAsyncOperation<bool>* aOperation, AsyncStatus aStatus);
|
||||
|
||||
void Initialize();
|
||||
void CoreExit();
|
||||
|
||||
void ShutdownXPCOM();
|
||||
|
||||
// Shared pointers between framework and widget
|
||||
static FrameworkView* GetView();
|
||||
static void SetBaseWidget(MetroWidget* aPtr);
|
||||
static void PostSuspendResumeProcessNotification(bool aIsSuspend);
|
||||
static void PostSleepWakeNotification(bool aIsSuspend);
|
||||
|
||||
private:
|
||||
EventRegistrationToken mSuspendEvent;
|
||||
EventRegistrationToken mResumeEvent;
|
||||
};
|
||||
|
||||
} } }
|
283
widget/windows/winrt/MetroAppShell.cpp
Normal file
283
widget/windows/winrt/MetroAppShell.cpp
Normal file
@ -0,0 +1,283 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MetroAppShell.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/widget/AudioSession.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "MetroApp.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
using namespace mozilla::widget::winrt;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::UI::Core;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
extern ComPtr<MetroApp> sMetroApp;
|
||||
} } }
|
||||
|
||||
const PRUnichar* kMetroAppShellEventId = L"nsAppShell:EventID";
|
||||
static UINT sShellEventMsgID;
|
||||
static ComPtr<ICoreWindowStatic> sCoreStatic;
|
||||
|
||||
MetroAppShell::~MetroAppShell()
|
||||
{
|
||||
if (mEventWnd) {
|
||||
SendMessage(mEventWnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
MetroAppShell::Init()
|
||||
{
|
||||
LogFunction();
|
||||
|
||||
WNDCLASSW wc;
|
||||
HINSTANCE module = GetModuleHandle(NULL);
|
||||
sShellEventMsgID = RegisterWindowMessageW(kMetroAppShellEventId);
|
||||
|
||||
const PRUnichar *const kWindowClass = L"nsAppShell:EventWindowClass";
|
||||
if (!GetClassInfoW(module, kWindowClass, &wc)) {
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = EventWindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = module;
|
||||
wc.hIcon = NULL;
|
||||
wc.hCursor = NULL;
|
||||
wc.hbrBackground = (HBRUSH) NULL;
|
||||
wc.lpszMenuName = (LPCWSTR) NULL;
|
||||
wc.lpszClassName = kWindowClass;
|
||||
RegisterClassW(&wc);
|
||||
}
|
||||
|
||||
mEventWnd = CreateWindowW(kWindowClass, L"nsAppShell:EventWindow",
|
||||
0, 0, 0, 10, 10, NULL, NULL, module, NULL);
|
||||
NS_ENSURE_STATE(mEventWnd);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
observerService->AddObserver(this, "dl-start", false);
|
||||
observerService->AddObserver(this, "dl-done", false);
|
||||
observerService->AddObserver(this, "dl-cancel", false);
|
||||
observerService->AddObserver(this, "dl-failed", false);
|
||||
}
|
||||
|
||||
return nsBaseAppShell::Init();
|
||||
}
|
||||
|
||||
// Called by appstartup->run in xre, which is initiated by a call to
|
||||
// XRE_metroStartup in MetroApp. This call is on the metro main thread.
|
||||
NS_IMETHODIMP
|
||||
MetroAppShell::Run(void)
|
||||
{
|
||||
LogFunction();
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
switch(XRE_GetProcessType()) {
|
||||
case GeckoProcessType_Content:
|
||||
case GeckoProcessType_IPDLUnitTest:
|
||||
mozilla::widget::StartAudioSession();
|
||||
rv = nsBaseAppShell::Run();
|
||||
mozilla::widget::StopAudioSession();
|
||||
break;
|
||||
case GeckoProcessType_Plugin:
|
||||
NS_WARNING("We don't support plugins currently.");
|
||||
// Just exit
|
||||
rv = NS_ERROR_NOT_IMPLEMENTED;
|
||||
break;
|
||||
case GeckoProcessType_Default:
|
||||
// Nothing to do, just return.
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
ProcessNativeEvents(CoreProcessEventsOption eventOption)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (!sCoreStatic) {
|
||||
hr = GetActivationFactory(HStringReference(L"Windows.UI.Core.CoreWindow").Get(), sCoreStatic.GetAddressOf());
|
||||
NS_ASSERTION(SUCCEEDED(hr), "GetActivationFactory failed?");
|
||||
AssertHRESULT(hr);
|
||||
}
|
||||
|
||||
ComPtr<ICoreWindow> window;
|
||||
AssertHRESULT(sCoreStatic->GetForCurrentThread(window.GetAddressOf()));
|
||||
ComPtr<ICoreDispatcher> dispatcher;
|
||||
hr = window->get_Dispatcher(&dispatcher);
|
||||
NS_ASSERTION(SUCCEEDED(hr), "get_Dispatcher failed?");
|
||||
AssertHRESULT(hr);
|
||||
dispatcher->ProcessEvents(eventOption);
|
||||
}
|
||||
|
||||
void
|
||||
MetroAppShell::ProcessOneNativeEventIfPresent()
|
||||
{
|
||||
ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessOneIfPresent);
|
||||
}
|
||||
|
||||
void
|
||||
MetroAppShell::ProcessAllNativeEventsPresent()
|
||||
{
|
||||
ProcessNativeEvents(CoreProcessEventsOption::CoreProcessEventsOption_ProcessAllIfPresent);
|
||||
}
|
||||
|
||||
bool
|
||||
MetroAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
if (mayWait) {
|
||||
if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
||||
WaitMessage();
|
||||
}
|
||||
ProcessOneNativeEventIfPresent();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
||||
ProcessOneNativeEventIfPresent();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Results from a call to appstartup->quit, which fires a final nsAppExitEvent
|
||||
// event which calls us here. This is on the metro main thread. We want to
|
||||
// call xpcom shutdown here, but we need to wait until the runnable that fires
|
||||
// this is off the stack. See NativeEventCallback below.
|
||||
NS_IMETHODIMP
|
||||
MetroAppShell::Exit(void)
|
||||
{
|
||||
LogFunction();
|
||||
mExiting = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MetroAppShell::NativeCallback()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Native callbacks must be on the metro main thread");
|
||||
NativeEventCallback();
|
||||
|
||||
// Handle shutdown after Exit() is called and unwinds.
|
||||
if (mExiting) {
|
||||
// shutdown fires events, don't recurse
|
||||
static bool sShutdown = false;
|
||||
if (sShutdown)
|
||||
return;
|
||||
sShutdown = true;
|
||||
if (sMetroApp) {
|
||||
// This calls XRE_metroShutdown() in xre
|
||||
sMetroApp->ShutdownXPCOM();
|
||||
// This will free the real main thread in CoreApplication::Run()
|
||||
// once winrt cleans up this thread.
|
||||
sMetroApp->CoreExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
LRESULT CALLBACK
|
||||
MetroAppShell::EventWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (uMsg == sShellEventMsgID) {
|
||||
MetroAppShell *as = reinterpret_cast<MetroAppShell *>(lParam);
|
||||
as->NativeCallback();
|
||||
NS_RELEASE(as);
|
||||
return TRUE;
|
||||
}
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
void
|
||||
MetroAppShell::ScheduleNativeEventCallback()
|
||||
{
|
||||
NS_ADDREF_THIS();
|
||||
PostMessage(mEventWnd, sShellEventMsgID, 0, reinterpret_cast<LPARAM>(this));
|
||||
}
|
||||
|
||||
void
|
||||
MetroAppShell::DoProcessMoreGeckoEvents()
|
||||
{
|
||||
ScheduleNativeEventCallback();
|
||||
}
|
||||
|
||||
static HANDLE
|
||||
PowerCreateRequestDyn(REASON_CONTEXT *context)
|
||||
{
|
||||
typedef HANDLE (WINAPI * PowerCreateRequestPtr)(REASON_CONTEXT *context);
|
||||
static HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
static PowerCreateRequestPtr powerCreateRequest =
|
||||
(PowerCreateRequestPtr)GetProcAddress(kernel32, "PowerCreateRequest");
|
||||
if (!powerCreateRequest)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
return powerCreateRequest(context);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
PowerClearRequestDyn(HANDLE powerRequest, POWER_REQUEST_TYPE requestType)
|
||||
{
|
||||
typedef BOOL (WINAPI * PowerClearRequestPtr)(HANDLE powerRequest, POWER_REQUEST_TYPE requestType);
|
||||
static HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
static PowerClearRequestPtr powerClearRequest =
|
||||
(PowerClearRequestPtr)GetProcAddress(kernel32, "PowerClearRequest");
|
||||
if (!powerClearRequest)
|
||||
return FALSE;
|
||||
return powerClearRequest(powerRequest, requestType);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
PowerSetRequestDyn(HANDLE powerRequest, POWER_REQUEST_TYPE requestType)
|
||||
{
|
||||
typedef BOOL (WINAPI * PowerSetRequestPtr)(HANDLE powerRequest, POWER_REQUEST_TYPE requestType);
|
||||
static HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
static PowerSetRequestPtr powerSetRequest =
|
||||
(PowerSetRequestPtr)GetProcAddress(kernel32, "PowerSetRequest");
|
||||
if (!powerSetRequest)
|
||||
return FALSE;
|
||||
return powerSetRequest(powerRequest, requestType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MetroAppShell::Observe(nsISupports *subject, const char *topic,
|
||||
const PRUnichar *data)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(topic);
|
||||
if (!strcmp(topic, "dl-start")) {
|
||||
if (mPowerRequestCount++ == 0) {
|
||||
Log(L"Download started - Disallowing suspend");
|
||||
REASON_CONTEXT context;
|
||||
context.Version = POWER_REQUEST_CONTEXT_VERSION;
|
||||
context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
|
||||
context.Reason.SimpleReasonString = L"downloading";
|
||||
mPowerRequest.own(PowerCreateRequestDyn(&context));
|
||||
PowerSetRequestDyn(mPowerRequest, PowerRequestExecutionRequired);
|
||||
}
|
||||
return NS_OK;
|
||||
} else if (!strcmp(topic, "dl-done") ||
|
||||
!strcmp(topic, "dl-cancel") ||
|
||||
!strcmp(topic, "dl-failed")) {
|
||||
if (--mPowerRequestCount == 0 && mPowerRequest) {
|
||||
Log(L"All downloads ended - Allowing suspend");
|
||||
PowerClearRequestDyn(mPowerRequest, PowerRequestExecutionRequired);
|
||||
mPowerRequest.reset();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsBaseAppShell::Observe(subject, topic, data);
|
||||
}
|
41
widget/windows/winrt/MetroAppShell.h
Normal file
41
widget/windows/winrt/MetroAppShell.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsBaseAppShell.h"
|
||||
#include <windows.h>
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class MetroAppShell : public nsBaseAppShell
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
MetroAppShell() : mEventWnd(NULL), mExiting(false), mPowerRequestCount(0)
|
||||
{}
|
||||
|
||||
nsresult Init();
|
||||
void DoProcessMoreGeckoEvents();
|
||||
void NativeCallback();
|
||||
|
||||
static LRESULT CALLBACK EventWindowProc(HWND, UINT, WPARAM, LPARAM);
|
||||
static void ProcessAllNativeEventsPresent();
|
||||
static void ProcessOneNativeEventIfPresent();
|
||||
|
||||
protected:
|
||||
HWND mEventWnd;
|
||||
bool mExiting;
|
||||
nsAutoHandle mPowerRequest;
|
||||
ULONG mPowerRequestCount;
|
||||
|
||||
NS_IMETHOD Run();
|
||||
NS_IMETHOD Exit();
|
||||
virtual void ScheduleNativeEventCallback();
|
||||
virtual bool ProcessNextNativeEvent(bool mayWait);
|
||||
virtual ~MetroAppShell();
|
||||
};
|
497
widget/windows/winrt/MetroContracts.cpp
Normal file
497
widget/windows/winrt/MetroContracts.cpp
Normal file
@ -0,0 +1,497 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FrameworkView.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "nsICommandLineRunner.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIDOMChromeWindow.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include <wrl/wrappers/corewrappers.h>
|
||||
#include <shellapi.h>
|
||||
#include <DXGIFormat.h>
|
||||
#include <d2d1_1.h>
|
||||
#include <printpreview.h>
|
||||
#include <D3D10.h>
|
||||
#include "MetroUIUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::Foundation::Collections;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
|
||||
// Play to contract
|
||||
using namespace ABI::Windows::Media::PlayTo;
|
||||
|
||||
// Activation contracts
|
||||
using namespace ABI::Windows::ApplicationModel::Activation;
|
||||
using namespace ABI::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace ABI::Windows::ApplicationModel::Search;
|
||||
|
||||
// Settings contract
|
||||
using namespace ABI::Windows::UI::ApplicationSettings;
|
||||
using namespace ABI::Windows::UI::Popups;
|
||||
|
||||
// Print contract
|
||||
using namespace ABI::Windows::Graphics::Printing;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
extern nsTArray<nsString>* sSettingsArray;
|
||||
|
||||
void
|
||||
FrameworkView::SearchActivated(ComPtr<ISearchActivatedEventArgs>& aArgs)
|
||||
{
|
||||
if (!aArgs)
|
||||
return;
|
||||
|
||||
HString data;
|
||||
AssertHRESULT(aArgs->get_QueryText(data.GetAddressOf()));
|
||||
if (WindowsIsStringEmpty(data.Get()))
|
||||
return;
|
||||
|
||||
unsigned int length;
|
||||
Log(L"SearchActivated text=", data.GetRawBuffer(&length));
|
||||
PerformURILoadOrSearch(data);
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::FileActivated(ComPtr<IFileActivatedEventArgs>& aArgs)
|
||||
{
|
||||
if (!aArgs)
|
||||
return;
|
||||
|
||||
ComPtr<IVectorView<ABI::Windows::Storage::IStorageItem*>> list;
|
||||
AssertHRESULT(aArgs->get_Files(list.GetAddressOf()));
|
||||
ComPtr<ABI::Windows::Storage::IStorageItem> item;
|
||||
AssertHRESULT(list->GetAt(0, item.GetAddressOf()));
|
||||
HString filePath;
|
||||
AssertHRESULT(item->get_Path(filePath.GetAddressOf()));
|
||||
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
AssertHRESULT(MetroUtils::CreateUri(filePath, uri));
|
||||
PerformURILoad(uri);
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::LaunchActivated(ComPtr<ILaunchActivatedEventArgs>& aArgs)
|
||||
{
|
||||
if (!aArgs)
|
||||
return;
|
||||
HString data;
|
||||
AssertHRESULT(aArgs->get_Arguments(data.GetAddressOf()));
|
||||
if (WindowsIsStringEmpty(data.Get()))
|
||||
return;
|
||||
|
||||
int argc;
|
||||
unsigned int length;
|
||||
LPWSTR* argv = CommandLineToArgvW(data.GetRawBuffer(&length), &argc);
|
||||
nsCOMPtr<nsICommandLineRunner> cmdLine =
|
||||
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
|
||||
if (!cmdLine) {
|
||||
NS_WARNING("Unable to instantiate command line runner.");
|
||||
return;
|
||||
}
|
||||
|
||||
LPSTR *argvUTF8 = new LPSTR[argc];
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
NS_ConvertUTF16toUTF8 arg(argv[i]);
|
||||
argvUTF8[i] = new char[arg.Length() + 1];
|
||||
strcpy(argvUTF8[i], const_cast<char *>(arg.BeginReading()));
|
||||
Log(L"Launch arg[%d]: '%s'", i, argv[i]);
|
||||
}
|
||||
|
||||
nsresult rv = cmdLine->Init(argc,
|
||||
argvUTF8,
|
||||
nullptr,
|
||||
nsICommandLine::STATE_REMOTE_EXPLICIT);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
cmdLine->Run();
|
||||
} else {
|
||||
NS_WARNING("cmdLine->Init failed.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
delete[] argvUTF8[i];
|
||||
}
|
||||
delete[] argvUTF8;
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::RunStartupArgs(IActivatedEventArgs* aArgs)
|
||||
{
|
||||
ActivationKind kind;
|
||||
if (!aArgs || FAILED(aArgs->get_Kind(&kind)))
|
||||
return;
|
||||
ComPtr<IActivatedEventArgs> args(aArgs);
|
||||
if (kind == ActivationKind::ActivationKind_Protocol) {
|
||||
Log(L"Activation argument kind: Protocol");
|
||||
ComPtr<IProtocolActivatedEventArgs> protoArgs;
|
||||
AssertHRESULT(args.As(&protoArgs));
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
AssertHRESULT(protoArgs->get_Uri(uri.GetAddressOf()));
|
||||
PerformURILoad(uri);
|
||||
} else if (kind == ActivationKind::ActivationKind_Search) {
|
||||
Log(L"Activation argument kind: Search");
|
||||
ComPtr<ISearchActivatedEventArgs> searchArgs;
|
||||
args.As(&searchArgs);
|
||||
SearchActivated(searchArgs);
|
||||
} else if (kind == ActivationKind::ActivationKind_File) {
|
||||
Log(L"Activation argument kind: File");
|
||||
ComPtr<IFileActivatedEventArgs> fileArgs;
|
||||
args.As(&fileArgs);
|
||||
FileActivated(fileArgs);
|
||||
} else if (kind == ActivationKind::ActivationKind_Launch) {
|
||||
Log(L"Activation argument kind: Launch");
|
||||
ComPtr<ILaunchActivatedEventArgs> launchArgs;
|
||||
args.As(&launchArgs);
|
||||
LaunchActivated(launchArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::SetupContracts()
|
||||
{
|
||||
LogFunction();
|
||||
HRESULT hr;
|
||||
|
||||
// Add support for the share charm to indicate that we share data to other apps
|
||||
ComPtr<IDataTransferManagerStatics> transStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager).Get(),
|
||||
transStatics.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
ComPtr<IDataTransferManager> trans;
|
||||
AssertHRESULT(transStatics->GetForCurrentView(trans.GetAddressOf()));
|
||||
trans->add_DataRequested(Callback<__FITypedEventHandler_2_Windows__CApplicationModel__CDataTransfer__CDataTransferManager_Windows__CApplicationModel__CDataTransfer__CDataRequestedEventArgs_t>(
|
||||
this, &FrameworkView::OnDataShareRequested).Get(), &mDataTransferRequested);
|
||||
|
||||
// Add support for the search charm to indicate that you can search using our app.
|
||||
ComPtr<ISearchPaneStatics> searchStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Search_SearchPane).Get(),
|
||||
searchStatics.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
ComPtr<ISearchPane> searchPane;
|
||||
AssertHRESULT(searchStatics->GetForCurrentView(searchPane.GetAddressOf()));
|
||||
searchPane->add_QuerySubmitted(Callback<__FITypedEventHandler_2_Windows__CApplicationModel__CSearch__CSearchPane_Windows__CApplicationModel__CSearch__CSearchPaneQuerySubmittedEventArgs_t>(
|
||||
this, &FrameworkView::OnSearchQuerySubmitted).Get(), &mSearchQuerySubmitted);
|
||||
|
||||
// Add support for the devices play to charm
|
||||
ComPtr<IPlayToManagerStatics> playToStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Media_PlayTo_PlayToManager).Get(),
|
||||
playToStatics.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
ComPtr<IPlayToManager> playTo;
|
||||
AssertHRESULT(playToStatics->GetForCurrentView(playTo.GetAddressOf()));
|
||||
playTo->add_SourceRequested(Callback<__FITypedEventHandler_2_Windows__CMedia__CPlayTo__CPlayToManager_Windows__CMedia__CPlayTo__CPlayToSourceRequestedEventArgs_t>(
|
||||
this, &FrameworkView::OnPlayToSourceRequested).Get(), &mPlayToRequested);
|
||||
|
||||
// Add support for the settings charm
|
||||
ComPtr<ISettingsPaneStatics> settingsPaneStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ApplicationSettings_SettingsPane).Get(),
|
||||
settingsPaneStatics.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
ComPtr<ISettingsPane> settingsPane;
|
||||
AssertHRESULT(settingsPaneStatics->GetForCurrentView(settingsPane.GetAddressOf()));
|
||||
settingsPane->add_CommandsRequested(Callback<__FITypedEventHandler_2_Windows__CUI__CApplicationSettings__CSettingsPane_Windows__CUI__CApplicationSettings__CSettingsPaneCommandsRequestedEventArgs_t>(
|
||||
this, &FrameworkView::OnSettingsCommandsRequested).Get(), &mSettingsPane);
|
||||
|
||||
// Add support for the settings print charm
|
||||
ComPtr<IPrintManagerStatic> printStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Printing_PrintManager).Get(),
|
||||
printStatics.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
ComPtr<IPrintManager> printManager;
|
||||
AssertHRESULT(printStatics->GetForCurrentView(printManager.GetAddressOf()));
|
||||
printManager->add_PrintTaskRequested(Callback<__FITypedEventHandler_2_Windows__CGraphics__CPrinting__CPrintManager_Windows__CGraphics__CPrinting__CPrintTaskRequestedEventArgs_t>(
|
||||
this, &FrameworkView::OnPrintTaskRequested).Get(), &mPrintManager);
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::PerformURILoad(ComPtr<IUriRuntimeClass>& aURI)
|
||||
{
|
||||
LogFunction();
|
||||
if (!aURI)
|
||||
return;
|
||||
|
||||
HString data;
|
||||
AssertHRESULT(aURI->get_AbsoluteUri(data.GetAddressOf()));
|
||||
if (WindowsIsStringEmpty(data.Get()))
|
||||
return;
|
||||
|
||||
unsigned int length;
|
||||
Log(L"PerformURILoad uri=%s", data.GetRawBuffer(&length));
|
||||
|
||||
nsCOMPtr<nsICommandLineRunner> cmdLine =
|
||||
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
|
||||
if (!cmdLine) {
|
||||
NS_WARNING("Unable to instantiate command line runner.");
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString utf8data(NS_ConvertUTF16toUTF8(data.GetRawBuffer(&length)));
|
||||
const char *argv[] = { "metrobrowser",
|
||||
"-url",
|
||||
utf8data.BeginReading() };
|
||||
nsresult rv = cmdLine->Init(ArrayLength(argv),
|
||||
const_cast<char **>(argv), nullptr,
|
||||
nsICommandLine::STATE_REMOTE_EXPLICIT);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("cmdLine->Init failed.");
|
||||
return;
|
||||
}
|
||||
cmdLine->Run();
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::PerformSearch(HString& aQuery)
|
||||
{
|
||||
LogFunction();
|
||||
|
||||
nsCOMPtr<nsICommandLineRunner> cmdLine =
|
||||
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
|
||||
if (!cmdLine) {
|
||||
NS_WARNING("Unable to instantiate command line runner.");
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString parameter;
|
||||
parameter.AppendLiteral("\"");
|
||||
unsigned int length;
|
||||
parameter.Append(NS_ConvertUTF16toUTF8(aQuery.GetRawBuffer(&length)));
|
||||
parameter.AppendLiteral("\"");
|
||||
|
||||
const char *argv[] = { "metrobrowser",
|
||||
"-search",
|
||||
parameter.BeginReading() };
|
||||
nsresult rv = cmdLine->Init(ArrayLength(argv),
|
||||
const_cast<char **>(argv), nullptr,
|
||||
nsICommandLine::STATE_REMOTE_EXPLICIT);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("cmdLine->Init failed.");
|
||||
return;
|
||||
}
|
||||
cmdLine->Run();
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::PerformURILoadOrSearch(HString& aString)
|
||||
{
|
||||
LogFunction();
|
||||
|
||||
if (WindowsIsStringEmpty(aString.Get())) {
|
||||
Log(L"Emptry string passed to PerformURILoadOrSearch");
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a URI then devert to load the URI directly
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
MetroUtils::CreateUri(aString.Get(), uri);
|
||||
if (uri) {
|
||||
PerformURILoad(uri);
|
||||
} else {
|
||||
PerformSearch(aString);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnDataShareRequested(IDataTransferManager* aDTM,
|
||||
IDataRequestedEventArgs* aArg)
|
||||
{
|
||||
// Only share pages that contain a title and a URI
|
||||
nsCOMPtr<nsIMetroUIUtils> metroUIUtils = do_CreateInstance("@mozilla.org/metro-ui-utils;1");
|
||||
if (!metroUIUtils)
|
||||
return E_FAIL;
|
||||
|
||||
nsString url, title;
|
||||
nsresult rv = metroUIUtils->GetCurrentPageURI(url);
|
||||
nsresult rv2 = metroUIUtils->GetCurrentPageTitle(title);
|
||||
if (NS_FAILED(rv) || NS_FAILED(rv2)) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Get the package to share and initialize it
|
||||
HRESULT hr;
|
||||
ComPtr<IDataRequest> request;
|
||||
AssertRetHRESULT(hr = aArg->get_Request(request.GetAddressOf()), hr);
|
||||
ComPtr<IDataPackage> dataPackage;
|
||||
AssertRetHRESULT(hr = request->get_Data(dataPackage.GetAddressOf()), hr);
|
||||
ComPtr<IDataPackagePropertySet> props;
|
||||
AssertRetHRESULT(hr = dataPackage->get_Properties(props.GetAddressOf()), hr);
|
||||
props->put_ApplicationName(HStringReference(L"Firefox").Get());
|
||||
props->put_Title(HStringReference(title.BeginReading()).Get());
|
||||
props->put_Description(HStringReference(url.BeginReading()).Get());
|
||||
|
||||
// Only add a URI to the package when there is no selected content.
|
||||
// This is because most programs treat URIs as highest priority to generate
|
||||
// their own preview, but we only want the selected content to show up.
|
||||
bool hasSelectedContent = false;
|
||||
metroUIUtils->GetHasSelectedContent(&hasSelectedContent);
|
||||
if (!hasSelectedContent) {
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
AssertRetHRESULT(hr = MetroUtils::CreateUri(HStringReference(url.BeginReading()).Get(), uri), hr);
|
||||
AssertRetHRESULT(hr = dataPackage->SetUri(uri.Get()), hr);
|
||||
}
|
||||
|
||||
// Add whatever content metroUIUtils wants us to for the text sharing
|
||||
nsString shareText;
|
||||
if (NS_SUCCEEDED(metroUIUtils->GetShareText(shareText))) {
|
||||
AssertRetHRESULT(hr = dataPackage->SetText(HStringReference(shareText.BeginReading()).Get()) ,hr);
|
||||
}
|
||||
|
||||
// Add whatever content metroUIUtils wants us to for the HTML sharing
|
||||
nsString shareHTML;
|
||||
if (NS_SUCCEEDED(metroUIUtils->GetShareHTML(shareHTML))) {
|
||||
// The sharing format needs some special headers, so pass it through Windows
|
||||
ComPtr<IHtmlFormatHelperStatics> htmlFormatHelper;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_HtmlFormatHelper).Get(),
|
||||
htmlFormatHelper.GetAddressOf());
|
||||
AssertRetHRESULT(hr, hr);
|
||||
HSTRING fixedHTML;
|
||||
htmlFormatHelper->CreateHtmlFormat(HStringReference(shareHTML.BeginReading()).Get(), &fixedHTML);
|
||||
|
||||
// And now add the fixed HTML to the data package
|
||||
AssertRetHRESULT(hr = dataPackage->SetHtmlFormat(fixedHTML), hr);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnSearchQuerySubmitted(ISearchPane* aPane,
|
||||
ISearchPaneQuerySubmittedEventArgs* aArgs)
|
||||
{
|
||||
LogFunction();
|
||||
HString aQuery;
|
||||
aArgs->get_QueryText(aQuery.GetAddressOf());
|
||||
PerformURILoadOrSearch(aQuery);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnSettingsCommandInvoked(IUICommand* aCommand)
|
||||
{
|
||||
LogFunction();
|
||||
HRESULT hr;
|
||||
uint32_t id;
|
||||
ComPtr<IPropertyValue> prop;
|
||||
AssertRetHRESULT(hr = aCommand->get_Id((IInspectable**)prop.GetAddressOf()), hr);
|
||||
AssertRetHRESULT(hr = prop->GetUInt32(&id), hr);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
NS_ConvertASCIItoUTF16 idStr(nsPrintfCString("%lu", id));
|
||||
obs->NotifyObservers(nullptr, "metro-settings-entry-selected", idStr.BeginReading());
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::AddSetting(ISettingsPaneCommandsRequestedEventArgs* aArgs,
|
||||
uint32_t aId, HString& aSettingName)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
ComPtr<ABI::Windows::UI::ApplicationSettings::ISettingsPaneCommandsRequest> request;
|
||||
AssertHRESULT(aArgs->get_Request(request.GetAddressOf()));
|
||||
|
||||
// ApplicationCommands - vector that holds SettingsCommand to be invoked
|
||||
ComPtr<IVector<ABI::Windows::UI::ApplicationSettings::SettingsCommand*>> list;
|
||||
AssertHRESULT(request->get_ApplicationCommands(list.GetAddressOf()));
|
||||
|
||||
ComPtr<IUICommand> command;
|
||||
ComPtr<ISettingsCommandFactory> factory;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ApplicationSettings_SettingsCommand).Get(),
|
||||
factory.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
|
||||
// Create the IInspectable string property that identifies this command
|
||||
ComPtr<IInspectable> prop;
|
||||
ComPtr<IPropertyValueStatics> propStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(),
|
||||
propStatics.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
hr = propStatics->CreateUInt32(aId, prop.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
|
||||
// Create the command
|
||||
hr = factory->CreateSettingsCommand(prop.Get(), aSettingName.Get(),
|
||||
Callback<ABI::Windows::UI::Popups::IUICommandInvokedHandler>(
|
||||
this, &FrameworkView::OnSettingsCommandInvoked).Get(), command.GetAddressOf());
|
||||
AssertHRESULT(hr);
|
||||
|
||||
// Add it to the list
|
||||
hr = list->Append(command.Get());
|
||||
AssertHRESULT(hr);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnSettingsCommandsRequested(ISettingsPane* aPane,
|
||||
ISettingsPaneCommandsRequestedEventArgs* aArgs)
|
||||
{
|
||||
if (!sSettingsArray)
|
||||
return E_FAIL;
|
||||
if (!sSettingsArray->Length())
|
||||
return S_OK;
|
||||
for (uint32_t i = 0; i < sSettingsArray->Length(); i++) {
|
||||
HString label;
|
||||
label.Set(sSettingsArray->ElementAt(i).BeginReading());
|
||||
AddSetting(aArgs, i, label);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnPlayToSourceRequested(IPlayToManager* aPlayToManager,
|
||||
IPlayToSourceRequestedEventArgs* aArgs)
|
||||
{
|
||||
// TODO: Implement PlayTo, find the element on the page and then do something similar to this:
|
||||
// PlayToReceiver::Dispatcher.Helper.BeginInvoke(
|
||||
// mMediaElement = ref new Windows::UI::Xaml::Controls::MediaElement();
|
||||
// mMediaElement->Source = ref new Uri("http://www.youtube.com/watch?v=2U0NFgoNI7s");
|
||||
// aArgs->SourceRequest->SetSource(mMediaElement->PlayToSource);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnPrintTaskSourceRequested(IPrintTaskSourceRequestedArgs* aArgs)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::OnPrintTaskRequested(IPrintManager* aPrintManager,
|
||||
IPrintTaskRequestedEventArgs* aArgs)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FrameworkView::CreatePrintControl(IPrintDocumentPackageTarget* docPackageTarget,
|
||||
D2D1_PRINT_CONTROL_PROPERTIES* printControlProperties)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT
|
||||
FrameworkView::ClosePrintControl()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Print out one page, with the given print ticket.
|
||||
// This sample has only one page and we ignore pageNumber below.
|
||||
void FrameworkView::PrintPage(uint32_t pageNumber,
|
||||
D2D1_RECT_F imageableArea,
|
||||
D2D1_SIZE_F pageSize,
|
||||
IStream* pagePrintTicketStream)
|
||||
{
|
||||
}
|
||||
|
||||
} } }
|
1677
widget/windows/winrt/MetroInput.cpp
Normal file
1677
widget/windows/winrt/MetroInput.cpp
Normal file
File diff suppressed because it is too large
Load Diff
280
widget/windows/winrt/MetroInput.h
Normal file
280
widget/windows/winrt/MetroInput.h
Normal file
@ -0,0 +1,280 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// Moz headers (alphabetical)
|
||||
#include "keyboardlayout.h" // mModifierKeyState
|
||||
#include "nsBaseHashtable.h" // mTouches
|
||||
#include "nsGUIEvent.h" // mTouchEvent (nsTouchEvent)
|
||||
#include "nsHashKeys.h" // type of key for mTouches
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
// System headers (alphabetical)
|
||||
#include <EventToken.h> // EventRegistrationToken
|
||||
#include <stdint.h> // uint32_t
|
||||
#include <wrl\client.h> // Microsoft::WRL::ComPtr class
|
||||
#include <wrl\implements.h> // Microsoft::WRL::InspectableClass macro
|
||||
|
||||
// Moz forward declarations
|
||||
class MetroWidget;
|
||||
class nsIDOMTouch;
|
||||
enum nsEventStatus;
|
||||
class nsGUIEvent;
|
||||
struct nsIntPoint;
|
||||
|
||||
// Windows forward declarations
|
||||
namespace ABI {
|
||||
namespace Windows {
|
||||
namespace Devices {
|
||||
namespace Input {
|
||||
enum PointerDeviceType;
|
||||
}
|
||||
};
|
||||
namespace Foundation {
|
||||
struct Point;
|
||||
};
|
||||
namespace UI {
|
||||
namespace Core {
|
||||
struct CorePhysicalKeyStatus;
|
||||
struct ICoreWindow;
|
||||
struct ICoreDispatcher;
|
||||
struct IAcceleratorKeyEventArgs;
|
||||
struct IKeyEventArgs;
|
||||
struct IPointerEventArgs;
|
||||
};
|
||||
namespace Input {
|
||||
struct IEdgeGesture;
|
||||
struct IEdgeGestureEventArgs;
|
||||
struct IGestureRecognizer;
|
||||
struct IManipulationCompletedEventArgs;
|
||||
struct IManipulationStartedEventArgs;
|
||||
struct IManipulationUpdatedEventArgs;
|
||||
struct IPointerPoint;
|
||||
struct IRightTappedEventArgs;
|
||||
struct ITappedEventArgs;
|
||||
struct ManipulationDelta;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
class MetroInput : public Microsoft::WRL::RuntimeClass<IInspectable>
|
||||
{
|
||||
InspectableClass(L"MetroInput", BaseTrust);
|
||||
|
||||
private:
|
||||
// Devices
|
||||
typedef ABI::Windows::Devices::Input::PointerDeviceType PointerDeviceType;
|
||||
|
||||
// Foundation
|
||||
typedef ABI::Windows::Foundation::Point Point;
|
||||
|
||||
// UI::Core
|
||||
typedef ABI::Windows::UI::Core::CorePhysicalKeyStatus CorePhysicalKeyStatus;
|
||||
typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow;
|
||||
typedef ABI::Windows::UI::Core::IAcceleratorKeyEventArgs \
|
||||
IAcceleratorKeyEventArgs;
|
||||
typedef ABI::Windows::UI::Core::ICoreDispatcher ICoreDispatcher;
|
||||
typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs;
|
||||
typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs;
|
||||
|
||||
// UI::Input
|
||||
typedef ABI::Windows::UI::Input::IEdgeGesture IEdgeGesture;
|
||||
typedef ABI::Windows::UI::Input::IEdgeGestureEventArgs IEdgeGestureEventArgs;
|
||||
typedef ABI::Windows::UI::Input::IGestureRecognizer IGestureRecognizer;
|
||||
typedef ABI::Windows::UI::Input::IManipulationCompletedEventArgs \
|
||||
IManipulationCompletedEventArgs;
|
||||
typedef ABI::Windows::UI::Input::IManipulationStartedEventArgs \
|
||||
IManipulationStartedEventArgs;
|
||||
typedef ABI::Windows::UI::Input::IManipulationUpdatedEventArgs \
|
||||
IManipulationUpdatedEventArgs;
|
||||
typedef ABI::Windows::UI::Input::IPointerPoint IPointerPoint;
|
||||
typedef ABI::Windows::UI::Input::IRightTappedEventArgs IRightTappedEventArgs;
|
||||
typedef ABI::Windows::UI::Input::ITappedEventArgs ITappedEventArgs;
|
||||
typedef ABI::Windows::UI::Input::ManipulationDelta ManipulationDelta;
|
||||
|
||||
public:
|
||||
MetroInput(MetroWidget* aWidget,
|
||||
ICoreWindow* aWindow,
|
||||
ICoreDispatcher* aDispatcher);
|
||||
virtual ~MetroInput();
|
||||
|
||||
// This event is received from our CoreDispatcher. All keyboard and
|
||||
// character events are handled in this function. See function
|
||||
// definition for more info.
|
||||
HRESULT OnAcceleratorKeyActivated(ICoreDispatcher* aSender,
|
||||
IAcceleratorKeyEventArgs* aArgs);
|
||||
|
||||
// These input events are received from our window. These are basic
|
||||
// pointer and keyboard press events. MetroInput responds to them
|
||||
// by sending gecko events and forwarding these input events to its
|
||||
// GestureRecognizer to be processed into more complex input events
|
||||
// (tap, rightTap, rotate, etc)
|
||||
HRESULT OnPointerWheelChanged(ICoreWindow* aSender,
|
||||
IPointerEventArgs* aArgs);
|
||||
HRESULT OnPointerPressed(ICoreWindow* aSender,
|
||||
IPointerEventArgs* aArgs);
|
||||
HRESULT OnPointerReleased(ICoreWindow* aSender,
|
||||
IPointerEventArgs* aArgs);
|
||||
HRESULT OnPointerMoved(ICoreWindow* aSender,
|
||||
IPointerEventArgs* aArgs);
|
||||
HRESULT OnPointerEntered(ICoreWindow* aSender,
|
||||
IPointerEventArgs* aArgs);
|
||||
HRESULT OnPointerExited(ICoreWindow* aSender,
|
||||
IPointerEventArgs* aArgs);
|
||||
|
||||
// The Edge gesture event is special. It does not come from our window
|
||||
// or from our GestureRecognizer.
|
||||
HRESULT OnEdgeGestureCompleted(IEdgeGesture* aSender,
|
||||
IEdgeGestureEventArgs* aArgs);
|
||||
|
||||
// These events are raised by our GestureRecognizer in response to input
|
||||
// events that we forward to it. The ManipulationStarted,
|
||||
// ManipulationUpdated, and ManipulationEnded events are sent during
|
||||
// complex input gestures including pinch, swipe, and rotate. Note that
|
||||
// all three gestures can occur simultaneously.
|
||||
HRESULT OnManipulationStarted(IGestureRecognizer* aSender,
|
||||
IManipulationStartedEventArgs* aArgs);
|
||||
HRESULT OnManipulationUpdated(IGestureRecognizer* aSender,
|
||||
IManipulationUpdatedEventArgs* aArgs);
|
||||
HRESULT OnManipulationCompleted(IGestureRecognizer* aSender,
|
||||
IManipulationCompletedEventArgs* aArgs);
|
||||
HRESULT OnTapped(IGestureRecognizer* aSender, ITappedEventArgs* aArgs);
|
||||
HRESULT OnRightTapped(IGestureRecognizer* aSender,
|
||||
IRightTappedEventArgs* aArgs);
|
||||
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
||||
Microsoft::WRL::ComPtr<MetroWidget> mWidget;
|
||||
Microsoft::WRL::ComPtr<ICoreDispatcher> mDispatcher;
|
||||
Microsoft::WRL::ComPtr<IGestureRecognizer> mGestureRecognizer;
|
||||
|
||||
ModifierKeyState mModifierKeyState;
|
||||
|
||||
// Initialization/Uninitialization helpers
|
||||
void RegisterInputEvents();
|
||||
void UnregisterInputEvents();
|
||||
|
||||
// Event processing helpers. See function definitions for more info.
|
||||
void OnKeyDown(uint32_t aVKey,
|
||||
CorePhysicalKeyStatus const& aKeyStatus);
|
||||
void OnKeyUp(uint32_t aVKey,
|
||||
CorePhysicalKeyStatus const& aKeyStatus);
|
||||
void OnCharacterReceived(uint32_t aVKey,
|
||||
CorePhysicalKeyStatus const& aKeyStatus);
|
||||
void OnPointerNonTouch(IPointerPoint* aPoint);
|
||||
void InitGeckoMouseEventFromPointerPoint(nsMouseEvent& aEvent,
|
||||
IPointerPoint* aPoint);
|
||||
void ProcessManipulationDelta(ManipulationDelta const& aDelta,
|
||||
Point const& aPosition,
|
||||
uint32_t aMagEventType,
|
||||
uint32_t aRotEventType);
|
||||
|
||||
void DispatchEventIgnoreStatus(nsGUIEvent *aEvent);
|
||||
static nsEventStatus sThrowawayStatus;
|
||||
|
||||
// The W3C spec states that "whether preventDefault has been called" should
|
||||
// be tracked on a per-touchpoint basis, but it also states that touchstart
|
||||
// and touchmove events can contain multiple changed points. At the time of
|
||||
// this writing, W3C touch events are in the process of being abandoned in
|
||||
// favor of W3C pointer events, so it is unlikely that this ambiguity will
|
||||
// be resolved. Additionally, nsPresShell tracks "whether preventDefault
|
||||
// has been called" on a per-touch-session basis. We will follow a similar
|
||||
// approach here.
|
||||
//
|
||||
// Specifically:
|
||||
// If preventDefault is called on the FIRST touchstart event of a touch
|
||||
// session, then no default actions associated with any touchstart,
|
||||
// touchmove, or touchend events will be taken. This means that no
|
||||
// mousedowns, mousemoves, mouseups, clicks, swipes, rotations,
|
||||
// magnifications, etc will be dispatched during this touch session;
|
||||
// only touchstart, touchmove, and touchend.
|
||||
//
|
||||
// If preventDefault is called on the FIRST touchmove event of a touch
|
||||
// session, then no default actions associated with the _touchmove_ events
|
||||
// will be dispatched. However, it is still possible that additional
|
||||
// events will be generated based on the touchstart and touchend events.
|
||||
// For example, a set of mousemove, mousedown, and mouseup events might
|
||||
// be sent if a tap is detected.
|
||||
bool mTouchStartDefaultPrevented;
|
||||
bool mTouchMoveDefaultPrevented;
|
||||
bool mIsFirstTouchMove;
|
||||
|
||||
// In the old Win32 way of doing things, we would receive a WM_TOUCH event
|
||||
// that told us the state of every touchpoint on the touch surface. If
|
||||
// multiple touchpoints had moved since the last update we would learn
|
||||
// about all their movement simultaneously.
|
||||
//
|
||||
// In the new WinRT way of doing things, we receive a separate
|
||||
// PointerPressed/PointerMoved/PointerReleased event for each touchpoint
|
||||
// that has changed.
|
||||
//
|
||||
// When we learn of touch input, we dispatch gecko events in response.
|
||||
// With the new WinRT way of doing things, we would end up sending many
|
||||
// more gecko events than we would using the Win32 mechanism. E.g.,
|
||||
// for 5 active touchpoints, we would be sending 5 times as many gecko
|
||||
// events. This caused performance to visibly degrade on modestly-powered
|
||||
// machines. In response, we no longer send touch events immediately
|
||||
// upon receiving PointerPressed or PointerMoved. Instead, we store
|
||||
// the updated touchpoint info and record the fact that the touchpoint
|
||||
// has changed. If ever we try to update a touchpoint has already
|
||||
// changed, we dispatch a touch event containing all the changed touches.
|
||||
nsEventStatus mTouchEventStatus;
|
||||
nsTouchEvent mTouchEvent;
|
||||
void DispatchPendingTouchEvent();
|
||||
void DispatchPendingTouchEvent(nsEventStatus& status);
|
||||
nsBaseHashtable<nsUint32HashKey,
|
||||
nsCOMPtr<nsIDOMTouch>,
|
||||
nsCOMPtr<nsIDOMTouch> > mTouches;
|
||||
|
||||
// When a key press is received, we convert the Windows virtual key
|
||||
// into a gecko virtual key to send in a gecko event.
|
||||
//
|
||||
// Source:
|
||||
// http://msdn.microsoft.com
|
||||
// /en-us/library/windows/apps/windows.system.virtualkey.aspx
|
||||
static uint32_t sVirtualKeyMap[255];
|
||||
static bool sIsVirtualKeyMapInitialized;
|
||||
static void InitializeVirtualKeyMap();
|
||||
static uint32_t GetMozKeyCode(uint32_t aKey);
|
||||
|
||||
// These registration tokens are set when we register ourselves to receive
|
||||
// events from our window. We must hold on to them for the entire duration
|
||||
// that we want to receive these events. When we are done, we must
|
||||
// unregister ourself with the window using these tokens.
|
||||
EventRegistrationToken mTokenPointerPressed;
|
||||
EventRegistrationToken mTokenPointerReleased;
|
||||
EventRegistrationToken mTokenPointerMoved;
|
||||
EventRegistrationToken mTokenPointerEntered;
|
||||
EventRegistrationToken mTokenPointerExited;
|
||||
EventRegistrationToken mTokenPointerWheelChanged;
|
||||
|
||||
// This registration token is set when we register ourselves to handle
|
||||
// the `AcceleratorKeyActivated` event received from our CoreDispatcher.
|
||||
// When we are done, we must unregister ourselves with the CoreDispatcher
|
||||
// using this token.
|
||||
EventRegistrationToken mTokenAcceleratorKeyActivated;
|
||||
|
||||
// When we register ourselves to handle the edge gesture, we receive a
|
||||
// token. When we unregister ourselves, we must use the token we received.
|
||||
EventRegistrationToken mTokenEdgeGesture;
|
||||
|
||||
// These registration tokens are set when we register ourselves to receive
|
||||
// events from our GestureRecognizer. It's probably not a huge deal if we
|
||||
// don't unregister ourselves with our GestureRecognizer before destroying
|
||||
// the GestureRecognizer, but it can't hurt.
|
||||
EventRegistrationToken mTokenManipulationStarted;
|
||||
EventRegistrationToken mTokenManipulationUpdated;
|
||||
EventRegistrationToken mTokenManipulationCompleted;
|
||||
EventRegistrationToken mTokenTapped;
|
||||
EventRegistrationToken mTokenRightTapped;
|
||||
};
|
||||
|
||||
} } }
|
181
widget/windows/winrt/MetroUIUtils.js
Normal file
181
widget/windows/winrt/MetroUIUtils.js
Normal file
@ -0,0 +1,181 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function MetroUIUtils() {
|
||||
}
|
||||
|
||||
const URLElements = {
|
||||
"a": "href",
|
||||
"applet": ["archive", "code", "codebase"],
|
||||
"area": "href",
|
||||
"audio": "src",
|
||||
"base": "href",
|
||||
"blockquote": ["cite"],
|
||||
"body": "background",
|
||||
"button": "formaction",
|
||||
"command": "icon",
|
||||
"del": ["cite"],
|
||||
"embed": "src",
|
||||
"form": "action",
|
||||
"frame": ["longdesc", "src"],
|
||||
"iframe": ["longdesc", "src"],
|
||||
"img": ["longdesc", "src"],
|
||||
"input": ["formaction", "src"],
|
||||
"ins": ["cite"],
|
||||
"link": "href",
|
||||
"object": ["archive", "codebase", "data"],
|
||||
"q": ["cite"],
|
||||
"script": "src",
|
||||
"source": "src",
|
||||
};
|
||||
|
||||
MetroUIUtils.prototype = {
|
||||
classID : Components.ID("e4626085-17f7-4068-a225-66c1acc0485c"),
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIMetroUIUtils]),
|
||||
/**
|
||||
* Loads the specified panel in the browser.
|
||||
* @ param aPanelId The identifier of the pane to load
|
||||
*/
|
||||
showPanel: function(aPanelId) {
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browserWin.PanelUI.show(aPanelId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if the browser has selected content
|
||||
*/
|
||||
get hasSelectedContent() {
|
||||
try {
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let tabBrowser = browserWin.getBrowser();
|
||||
if (!browserWin || !tabBrowser || !tabBrowser.contentWindow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let sel = tabBrowser.contentWindow.getSelection();
|
||||
return sel && sel.toString();
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtains the current page title
|
||||
*/
|
||||
get currentPageTitle() {
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (!browserWin || !browserWin.content || !browserWin.content.document) {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
return browserWin.content.document.title || "";
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtains the current page URI
|
||||
*/
|
||||
get currentPageURI() {
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (!browserWin || !browserWin.content || !browserWin.content.document) {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
return browserWin.content.document.URL || "";
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines the text that should be shared
|
||||
*/
|
||||
get shareText() {
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let tabBrowser = browserWin.getBrowser();
|
||||
if (browserWin && tabBrowser && tabBrowser.contentWindow) {
|
||||
return tabBrowser.contentWindow.getSelection() || "";
|
||||
}
|
||||
else if (browserWin && browserWin.content && browserWin.document) {
|
||||
return browserWin.content.document.URL ||
|
||||
browserWin.content.document.title || "";
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces the node's attribute value to be a fully qualified URL
|
||||
*/
|
||||
_expandAttribute : function(ioService, doc, node, attrName) {
|
||||
let attrValue = node.getAttribute(attrName);
|
||||
if (!attrValue)
|
||||
return;
|
||||
|
||||
try {
|
||||
let uri = ioService.newURI(attrValue, null, doc.baseURIObject);
|
||||
node.setAttribute(attrName, uri.spec);
|
||||
} catch (e) {
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Replaces all attribute values in 'n' which contain URLs recursiely
|
||||
* to fully qualified URLs.
|
||||
*/
|
||||
_expandURLs: function(doc, n) {
|
||||
let ioService = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
for (let i = 0; i < n.children.length; i++) {
|
||||
let child = n.children[i];
|
||||
let childTagName = child.tagName.toLowerCase();
|
||||
|
||||
// Iterate through all known tags which can contain URLs. A tag either
|
||||
// contains a single attribute name or an array of attribute names.
|
||||
for (let tagName in URLElements) {
|
||||
if (tagName === childTagName) {
|
||||
if (URLElements[tagName] instanceof Array) {
|
||||
URLElements[tagName].forEach(function(attrName) {
|
||||
this._expandAttribute(ioService ,doc, child, attrName);
|
||||
}, this);
|
||||
} else {
|
||||
this._expandAttribute(ioService ,doc, child, URLElements[tagName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._expandURLs(doc, child);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines the HTML that should be shared
|
||||
*/
|
||||
get shareHTML() {
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let tabBrowser = browserWin.getBrowser();
|
||||
let sel;
|
||||
if (browserWin && tabBrowser && tabBrowser.contentWindow &&
|
||||
(sel = tabBrowser.contentWindow.getSelection()) && sel.rangeCount) {
|
||||
let div = tabBrowser.contentWindow.document.createElement("DIV");
|
||||
for (let i = 0; i < sel.rangeCount; i++) {
|
||||
let contents = sel.getRangeAt(i).cloneContents(true);
|
||||
div.appendChild(contents);
|
||||
}
|
||||
this._expandURLs(tabBrowser.contentWindow.document, div);
|
||||
return div.outerHTML;
|
||||
}
|
||||
else if (browserWin && browserWin.content && browserWin.document) {
|
||||
return browserWin.content.document.URL ||
|
||||
browserWin.content.document.title || "";
|
||||
}
|
||||
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
var component = [MetroUIUtils];
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(component);
|
144
widget/windows/winrt/MetroUtils.cpp
Normal file
144
widget/windows/winrt/MetroUtils.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
// so we can get logging even in release builds
|
||||
#define FORCE_PR_LOG 1
|
||||
#endif
|
||||
|
||||
#include "MetroUtils.h"
|
||||
#include <windows.h>
|
||||
#include "nsICommandLineRunner.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMChromeWindow.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsIURI.h"
|
||||
#include "prlog.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#include <wrl/wrappers/corewrappers.h>
|
||||
#include <windows.ui.applicationsettings.h>
|
||||
|
||||
using namespace ABI::Windows::UI::ApplicationSettings;
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::UI::ViewManagement;
|
||||
|
||||
// File-scoped statics (unnamed namespace)
|
||||
namespace {
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* metroWidgetLog = PR_NewLogModule("MetroWidget");
|
||||
#endif
|
||||
};
|
||||
|
||||
void Log(const wchar_t *fmt, ...)
|
||||
{
|
||||
va_list a = NULL;
|
||||
wchar_t szDebugString[1024];
|
||||
if(!lstrlenW(fmt))
|
||||
return;
|
||||
va_start(a,fmt);
|
||||
vswprintf(szDebugString, 1024, fmt, a);
|
||||
va_end(a);
|
||||
if(!lstrlenW(szDebugString))
|
||||
return;
|
||||
|
||||
// MSVC, including remote debug sessions
|
||||
OutputDebugStringW(szDebugString);
|
||||
OutputDebugStringW(L"\n");
|
||||
|
||||
// desktop console
|
||||
wprintf(L"%s\n", szDebugString);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
NS_ASSERTION(metroWidgetLog, "Called MetroUtils Log() but MetroWidget "
|
||||
"log module doesn't exist!");
|
||||
int len = wcslen(szDebugString);
|
||||
if (len) {
|
||||
char* utf8 = new char[len+1];
|
||||
memset(utf8, 0, sizeof(utf8));
|
||||
if (WideCharToMultiByte(CP_ACP, 0, szDebugString,
|
||||
-1, utf8, len+1, NULL,
|
||||
NULL) > 0) {
|
||||
PR_LOG(metroWidgetLog, PR_LOG_ALWAYS, (utf8));
|
||||
}
|
||||
delete[] utf8;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
MetroUtils::FireObserver(const char* aMessage, const PRUnichar* aData)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
return observerService->NotifyObservers(nullptr, aMessage, aData);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
HRESULT MetroUtils::CreateUri(HSTRING aUriStr, ComPtr<IUriRuntimeClass>& aUriOut)
|
||||
{
|
||||
HRESULT hr;
|
||||
ComPtr<IUriRuntimeClassFactory> uriFactory;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
|
||||
AssertRetHRESULT(hr, hr);
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
return uriFactory->CreateUri(aUriStr, &aUriOut);
|
||||
}
|
||||
|
||||
HRESULT MetroUtils::CreateUri(HString& aHString, ComPtr<IUriRuntimeClass>& aUriOut)
|
||||
{
|
||||
return MetroUtils::CreateUri(aHString.Get(), aUriOut);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MetroUtils::GetViewState(ApplicationViewState& aState)
|
||||
{
|
||||
HRESULT hr;
|
||||
ComPtr<IApplicationViewStatics> appViewStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
|
||||
appViewStatics.GetAddressOf());
|
||||
AssertRetHRESULT(hr, hr);
|
||||
hr = appViewStatics->get_Value(&aState);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MetroUtils::TryUnsnap(bool* aResult)
|
||||
{
|
||||
HRESULT hr;
|
||||
ComPtr<IApplicationViewStatics> appViewStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
|
||||
appViewStatics.GetAddressOf());
|
||||
AssertRetHRESULT(hr, hr);
|
||||
boolean success = false;
|
||||
hr = appViewStatics->TryUnsnap(&success);
|
||||
if (aResult)
|
||||
*aResult = success;
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
MetroUtils::ShowSettingsFlyout()
|
||||
{
|
||||
ComPtr<ISettingsPaneStatics> settingsPaneStatics;
|
||||
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ApplicationSettings_SettingsPane).Get(),
|
||||
settingsPaneStatics.GetAddressOf());
|
||||
if (SUCCEEDED(hr)) {
|
||||
settingsPaneStatics->Show();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
92
widget/windows/winrt/MetroUtils.h
Normal file
92
widget/windows/winrt/MetroUtils.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
|
||||
void Log(const wchar_t *fmt, ...);
|
||||
|
||||
#define WIDEN2(x) L ## x
|
||||
#define WIDEN(x) WIDEN2(x)
|
||||
#define __WFUNCTION__ WIDEN(__FUNCTION__)
|
||||
|
||||
#define LogFunction() Log(__WFUNCTION__)
|
||||
#define LogThread() Log(L"%s: IsMainThread:%d ThreadId:%X", __WFUNCTION__, NS_IsMainThread(), GetCurrentThreadId())
|
||||
#define LogThis() Log(L"[%X] %s", this, __WFUNCTION__)
|
||||
#define LogException(e) Log(L"%s Exception:%s", __WFUNCTION__, e->ToString()->Data())
|
||||
#define LogHRESULT(hr) Log(L"%s hr=%X", __WFUNCTION__, hr)
|
||||
|
||||
// HRESULT checkers, these warn on failure in debug builds
|
||||
#ifdef DEBUG
|
||||
#define DebugLogHR(hr) LogHRESULT(hr)
|
||||
#else
|
||||
#define DebugLogHR(hr)
|
||||
#endif
|
||||
#define AssertHRESULT(hr) \
|
||||
if (FAILED(hr)) { \
|
||||
DebugLogHR(hr); \
|
||||
return; \
|
||||
}
|
||||
#define AssertRetHRESULT(hr, res) \
|
||||
if (FAILED(hr)) { \
|
||||
DebugLogHR(hr); \
|
||||
return res; \
|
||||
}
|
||||
|
||||
// MS Point helpers
|
||||
#define POINT_CEIL_X(position) (uint32_t)ceil(position.X)
|
||||
#define POINT_CEIL_Y(position) (uint32_t)ceil(position.Y)
|
||||
|
||||
class nsIBrowserDOMWindow;
|
||||
class nsIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
template<unsigned int size, typename T>
|
||||
HRESULT ActivateGenericInstance(wchar_t const (&RuntimeClassName)[size], Microsoft::WRL::ComPtr<T>& aOutObject) {
|
||||
Microsoft::WRL::ComPtr<IActivationFactory> factory;
|
||||
HRESULT hr = ABI::Windows::Foundation::GetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClassName).Get(),
|
||||
factory.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
Microsoft::WRL::ComPtr<IInspectable> inspect;
|
||||
hr = factory->ActivateInstance(inspect.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
return inspect.As(&aOutObject);
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
class MetroUtils
|
||||
{
|
||||
typedef ABI::Windows::Foundation::IUriRuntimeClass IUriRuntimeClass;
|
||||
typedef Microsoft::WRL::Wrappers::HString HString;
|
||||
typedef ABI::Windows::UI::ViewManagement::ApplicationViewState ApplicationViewState;
|
||||
|
||||
public:
|
||||
static nsresult FireObserver(const char* aMessage, const PRUnichar* aData = nullptr);
|
||||
|
||||
static HRESULT CreateUri(HSTRING aUriStr, Microsoft::WRL::ComPtr<IUriRuntimeClass>& aUriOut);
|
||||
static HRESULT CreateUri(HString& aHString, Microsoft::WRL::ComPtr<IUriRuntimeClass>& aUriOut);
|
||||
static HRESULT GetViewState(ApplicationViewState& aState);
|
||||
static HRESULT TryUnsnap(bool* aResult = nullptr);
|
||||
static HRESULT ShowSettingsFlyout();
|
||||
|
||||
private:
|
||||
static nsresult GetBrowserDOMWindow(nsCOMPtr<nsIBrowserDOMWindow> &aBWin);
|
||||
static nsresult GetMostRecentWindow(const PRUnichar* aType, nsIDOMWindow** aWindow);
|
||||
};
|
1159
widget/windows/winrt/MetroWidget.cpp
Normal file
1159
widget/windows/winrt/MetroWidget.cpp
Normal file
File diff suppressed because it is too large
Load Diff
200
widget/windows/winrt/MetroWidget.h
Normal file
200
widget/windows/winrt/MetroWidget.h
Normal file
@ -0,0 +1,200 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsdefs.h"
|
||||
#include "prlog.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "nsWindowBase.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWindowDbg.h"
|
||||
#include "WindowHook.h"
|
||||
#include "TaskbarWindowPreview.h"
|
||||
#include "nsIdleService.h"
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "mozilla/a11y/Accessible.h"
|
||||
#endif
|
||||
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
#include <windows.system.h>
|
||||
#include <windows.ui.core.h>
|
||||
#include <Windows.ApplicationModel.core.h>
|
||||
#include <Windows.ApplicationModel.h>
|
||||
#include <Windows.Applicationmodel.Activation.h>
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
class FrameworkView;
|
||||
|
||||
} } }
|
||||
|
||||
class MetroWidget : public nsWindowBase
|
||||
{
|
||||
typedef mozilla::widget::WindowHook WindowHook;
|
||||
typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview;
|
||||
typedef ABI::Windows::UI::Input::IPointerPoint IPointerPoint;
|
||||
typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs;
|
||||
typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs;
|
||||
typedef ABI::Windows::UI::Core::ICharacterReceivedEventArgs ICharacterReceivedEventArgs;
|
||||
typedef mozilla::widget::winrt::FrameworkView FrameworkView;
|
||||
|
||||
static LRESULT CALLBACK
|
||||
StaticWindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParan, LPARAM aLParam);
|
||||
LRESULT WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParan, LPARAM aLParam);
|
||||
|
||||
public:
|
||||
MetroWidget();
|
||||
virtual ~MetroWidget();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsWindowBase
|
||||
virtual void InitEvent(nsGUIEvent& aEvent, nsIntPoint* aPoint = nullptr) MOZ_OVERRIDE;
|
||||
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
|
||||
|
||||
// nsIWidget interface
|
||||
NS_IMETHOD Create(nsIWidget *aParent,
|
||||
nsNativeWidget aNativeParent,
|
||||
const nsIntRect &aRect,
|
||||
nsDeviceContext *aContext,
|
||||
nsWidgetInitData *aInitData = nullptr);
|
||||
NS_IMETHOD Destroy();
|
||||
NS_IMETHOD SetParent(nsIWidget *aNewParent);
|
||||
NS_IMETHOD Show(bool bState);
|
||||
NS_IMETHOD IsVisible(bool & aState);
|
||||
NS_IMETHOD IsEnabled(bool *aState);
|
||||
NS_IMETHOD GetBounds(nsIntRect &aRect);
|
||||
NS_IMETHOD GetScreenBounds(nsIntRect &aRect);
|
||||
NS_IMETHOD GetClientBounds(nsIntRect &aRect);
|
||||
NS_IMETHOD Invalidate(bool aEraseBackground = false,
|
||||
bool aUpdateNCArea = false,
|
||||
bool aIncludeChildren = false);
|
||||
NS_IMETHOD Invalidate(const nsIntRect & aRect);
|
||||
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
|
||||
NS_IMETHOD ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY);
|
||||
NS_IMETHOD Move(double aX, double aY);
|
||||
NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint);
|
||||
NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint);
|
||||
NS_IMETHOD SetFocus(bool aRaise);
|
||||
NS_IMETHOD Enable(bool aState);
|
||||
NS_IMETHOD SetCursor(nsCursor aCursor);
|
||||
NS_IMETHOD SetTitle(const nsAString& aTitle);
|
||||
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener,
|
||||
bool aDoCapture);
|
||||
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
|
||||
virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
|
||||
int32_t aNativeKeyCode,
|
||||
uint32_t aModifierFlags,
|
||||
const nsAString& aCharacters,
|
||||
const nsAString& aUnmodifiedCharacters);
|
||||
virtual nsresult SynthesizeNativeMouseEvent(nsIntPoint aPoint,
|
||||
uint32_t aNativeMessage,
|
||||
uint32_t aModifierFlags);
|
||||
virtual nsresult SynthesizeNativeMouseScrollEvent(nsIntPoint aPoint,
|
||||
uint32_t aNativeMessage,
|
||||
double aDeltaX,
|
||||
double aDeltaY,
|
||||
double aDeltaZ,
|
||||
uint32_t aModifierFlags,
|
||||
uint32_t aAdditionalFlags);
|
||||
virtual bool HasPendingInputEvent();
|
||||
float GetDPI();
|
||||
virtual bool IsVisible() const;
|
||||
virtual bool IsEnabled() const;
|
||||
virtual LayerManager* GetLayerManager(PLayersChild* aShadowManager = nullptr,
|
||||
LayersBackend aBackendHint = mozilla::layers::LAYERS_NONE,
|
||||
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
|
||||
bool* aAllowRetaining = nullptr);
|
||||
|
||||
// IME related interfaces
|
||||
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
|
||||
const InputContextAction& aAction);
|
||||
NS_IMETHOD_(nsIWidget::InputContext) GetInputContext();
|
||||
NS_IMETHOD ResetInputState();
|
||||
NS_IMETHOD CancelIMEComposition();
|
||||
NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState);
|
||||
NS_IMETHOD OnIMEFocusChange(bool aFocus);
|
||||
NS_IMETHOD OnIMETextChange(uint32_t aStart, uint32_t aOldEnd, uint32_t aNewEnd);
|
||||
NS_IMETHOD OnIMESelectionChange(void);
|
||||
|
||||
// FrameworkView helpers
|
||||
void SizeModeChanged();
|
||||
void Activated(bool aActiveated);
|
||||
void Paint(const nsIntRegion& aInvalidRegion);
|
||||
|
||||
MetroWidget* MetroWidget::GetTopLevelWindow(bool aStopOnDialogOrPopup) { return this; }
|
||||
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
|
||||
virtual void* GetNativeData(uint32_t aDataType);
|
||||
virtual void FreeNativeData(void * data, uint32_t aDataType);
|
||||
virtual nsIntPoint WidgetToScreenOffset();
|
||||
|
||||
void UserActivity();
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
mozilla::a11y::Accessible* DispatchAccessibleEvent(uint32_t aEventType);
|
||||
mozilla::a11y::Accessible* GetRootAccessible();
|
||||
#endif // ACCESSIBILITY
|
||||
|
||||
// needed for current nsIFilePicker
|
||||
void PickerOpen();
|
||||
void PickerClosed();
|
||||
bool DestroyCalled() { return false; }
|
||||
void SuppressBlurEvents(bool aSuppress);
|
||||
bool BlurEventsSuppressed();
|
||||
|
||||
// needed for nsITaskbarWindowPreview
|
||||
bool HasTaskbarIconBeenCreated() { return false; }
|
||||
void SetHasTaskbarIconBeenCreated(bool created = true) { }
|
||||
already_AddRefed<nsITaskbarWindowPreview> GetTaskbarPreview() { return nullptr; }
|
||||
void SetTaskbarPreview(nsITaskbarWindowPreview *preview) { }
|
||||
WindowHook& GetWindowHook() { return mWindowHook; }
|
||||
|
||||
void SetView(FrameworkView* aView);
|
||||
void FindMetroWindow();
|
||||
virtual void SetTransparencyMode(nsTransparencyMode aMode);
|
||||
virtual nsTransparencyMode GetTransparencyMode();
|
||||
|
||||
protected:
|
||||
friend class FrameworkView;
|
||||
|
||||
struct OleInitializeWrapper {
|
||||
HRESULT const hr;
|
||||
|
||||
OleInitializeWrapper()
|
||||
: hr(::OleInitialize(NULL))
|
||||
{
|
||||
}
|
||||
|
||||
~OleInitializeWrapper() {
|
||||
if (SUCCEEDED(hr)) {
|
||||
::OleFlushClipboard();
|
||||
::OleUninitialize();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void SetSubclass();
|
||||
void RemoveSubclass();
|
||||
nsIWidgetListener* GetPaintListener();
|
||||
|
||||
OleInitializeWrapper mOleInitializeWrapper;
|
||||
WindowHook mWindowHook;
|
||||
Microsoft::WRL::ComPtr<FrameworkView> mView;
|
||||
nsTransparencyMode mTransparencyMode;
|
||||
nsIntRegion mInvalidatedRegion;
|
||||
nsCOMPtr<nsIdleService> mIdleService;
|
||||
HWND mWnd;
|
||||
WNDPROC mMetroWndProc;
|
||||
nsIWidget::InputContext mInputContext;
|
||||
};
|
146
widget/windows/winrt/UIAAccessibilityBridge.cpp
Normal file
146
widget/windows/winrt/UIAAccessibilityBridge.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#if defined(ACCESSIBILITY)
|
||||
|
||||
#include "UIAAccessibilityBridge.h"
|
||||
#include "MetroUtils.h"
|
||||
|
||||
#include <OAIdl.h>
|
||||
|
||||
#include "nsIAccessibleEvent.h"
|
||||
#include "nsIAccessibleEditableText.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
// generated
|
||||
#include "UIABridge.h"
|
||||
|
||||
#include <wrl/implements.h>
|
||||
|
||||
//#define DEBUG_BRIDGE
|
||||
#if !defined(DEBUG_BRIDGE)
|
||||
#undef LogThread
|
||||
#undef LogFunction
|
||||
#undef Log
|
||||
#define LogThread()
|
||||
#define LogFunction()
|
||||
#define Log(...)
|
||||
#endif
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(AccessibilityBridge, nsIObserver)
|
||||
|
||||
nsresult
|
||||
AccessibilityBridge::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
nsCOMPtr<nsIAccessibleEvent> ev = do_QueryInterface(aSubject);
|
||||
if (!ev) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t eventType = 0;
|
||||
ev->GetEventType(&eventType);
|
||||
|
||||
switch (eventType) {
|
||||
case nsIAccessibleEvent::EVENT_FOCUS:
|
||||
Log(L"EVENT_FOCUS");
|
||||
{
|
||||
nsCOMPtr<nsIAccessible> item;
|
||||
ev->GetAccessible(getter_AddRefs(item));
|
||||
Accessible* access = (Accessible*)item.get();
|
||||
Log(L"Focus element flags: %d %d %d",
|
||||
((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0),
|
||||
((access->NativeState() & mozilla::a11y::states::FOCUSABLE) > 0),
|
||||
((access->NativeState() & mozilla::a11y::states::READONLY) > 0)
|
||||
);
|
||||
bool focusable = (((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0) &&
|
||||
((access->NativeState() & mozilla::a11y::states::READONLY) == 0));
|
||||
|
||||
if (focusable) {
|
||||
Log(L"focus item can be focused");
|
||||
// we have a text input
|
||||
Microsoft::WRL::ComPtr<IUIAElement> bridgePtr;
|
||||
mBridge.As(&bridgePtr);
|
||||
if (bridgePtr) {
|
||||
#if defined(x86_64)
|
||||
bridgePtr->SetFocusInternal((__int64)item.get());
|
||||
#else
|
||||
bridgePtr->SetFocusInternal((__int32)item.get());
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
Log(L"focus item can't have focus");
|
||||
Microsoft::WRL::ComPtr<IUIAElement> bridgePtr;
|
||||
mBridge.As(&bridgePtr);
|
||||
if (bridgePtr) {
|
||||
bridgePtr->ClearFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case nsIAccessibleEvent::EVENT_SHOW:
|
||||
Log(L"EVENT_SHOW");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_HIDE:
|
||||
Log(L"EVENT_HIDE");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_STATE_CHANGE:
|
||||
Log(L"EVENT_STATE_CHANGE");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_SELECTION:
|
||||
Log(L"EVENT_SELECTION");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_SELECTION_ADD:
|
||||
Log(L"EVENT_SELECTION_ADD");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_SELECTION_REMOVE:
|
||||
Log(L"EVENT_SELECTION_REMOVE");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_SELECTION_WITHIN:
|
||||
Log(L"EVENT_SELECTION_WITHIN");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
|
||||
Log(L"EVENT_TEXT_CARET_MOVED");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_TEXT_CHANGED:
|
||||
Log(L"EVENT_TEXT_CHANGED");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
|
||||
Log(L"EVENT_TEXT_INSERTED");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_TEXT_REMOVED:
|
||||
Log(L"EVENT_TEXT_REMOVED");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_TEXT_UPDATED:
|
||||
Log(L"EVENT_TEXT_UPDATED");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
|
||||
Log(L"EVENT_TEXT_SELECTION_CHANGED");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_SECTION_CHANGED:
|
||||
Log(L"EVENT_SECTION_CHANGED");
|
||||
break;
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
|
||||
Log(L"EVENT_WINDOW_ACTIVATE");
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif // ACCESSIBILITY
|
80
widget/windows/winrt/UIAAccessibilityBridge.h
Normal file
80
widget/windows/winrt/UIAAccessibilityBridge.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(ACCESSIBILITY)
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozilla/a11y/Accessible.h"
|
||||
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
// Connects to our accessibility framework to receive
|
||||
// events and query the dom.
|
||||
class AccessibilityBridge : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
AccessibilityBridge() {}
|
||||
|
||||
~AccessibilityBridge() {
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
bool Init(IUnknown* aBridge, mozilla::a11y::Accessible* aPtr) {
|
||||
mAccess = aPtr;
|
||||
mBridge = aBridge;
|
||||
return Connect();
|
||||
}
|
||||
|
||||
bool Connect() {
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
rv = observerService->AddObserver(this, "accessible-event", false);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Connected() {
|
||||
return mAccess ? true : false;
|
||||
}
|
||||
|
||||
void Disconnect() {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to get observersvc on shutdown.");
|
||||
return;
|
||||
}
|
||||
observerService->RemoveObserver(this, "accessible-event");
|
||||
mAccess = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<mozilla::a11y::Accessible> mAccess;
|
||||
Microsoft::WRL::ComPtr<IUnknown> mBridge;
|
||||
};
|
||||
|
||||
} } }
|
||||
|
||||
#endif // ACCESSIBILITY
|
722
widget/windows/winrt/UIABridge.cpp
Normal file
722
widget/windows/winrt/UIABridge.cpp
Normal file
@ -0,0 +1,722 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "UIABridge.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "UIABridgePrivate.h"
|
||||
|
||||
#include <wrl.h>
|
||||
#include <OAIdl.h>
|
||||
#include <windows.graphics.display.h>
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
using namespace mozilla::a11y;
|
||||
#endif
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::UI;
|
||||
using namespace ABI::Windows::UI::Core;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::System;
|
||||
|
||||
//#define DEBUG_BRIDGE
|
||||
#if !defined(DEBUG_BRIDGE)
|
||||
#undef LogThread
|
||||
#undef LogFunction
|
||||
#undef Log
|
||||
#define LogThread()
|
||||
#define LogFunction()
|
||||
#define Log(...)
|
||||
#endif
|
||||
|
||||
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
|
||||
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
|
||||
MIDL_DEFINE_GUID(IID, IID_IUIABridge,0x343159D8,0xB1E9,0x4464,0x82,0xFC,0xB1,0x2C,0x7A,0x47,0x3C,0xF1);
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
#define ProviderOptions_UseClientCoordinates (ProviderOptions)0x100
|
||||
|
||||
static int gIDIndex = 2;
|
||||
static ComPtr<IUIABridge> gProviderRoot = nullptr;
|
||||
static ComPtr<IUIAElement> gElement = nullptr;
|
||||
|
||||
HRESULT
|
||||
UIABridge_CreateInstance(IInspectable **retVal)
|
||||
{
|
||||
LogFunction();
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
*retVal = nullptr;
|
||||
ComPtr<UIABridge> spProvider = Make<UIABridge>();
|
||||
if (spProvider != nullptr &&
|
||||
SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(retVal))) &&
|
||||
SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gProviderRoot)))) {
|
||||
return S_OK;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement_CreateInstance(IRawElementProviderFragmentRoot* aRoot)
|
||||
{
|
||||
LogFunction();
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
ComPtr<UIATextElement> spProvider = Make<UIATextElement>();
|
||||
if (spProvider != nullptr &&
|
||||
SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gElement)))) {
|
||||
spProvider->SetIndexID(gIDIndex++);
|
||||
return S_OK;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// IUIABridge
|
||||
|
||||
#if defined(x86_64)
|
||||
HRESULT
|
||||
UIABridge::Init(IInspectable* view, IInspectable* window, __int64 inner)
|
||||
#else
|
||||
HRESULT
|
||||
UIABridge::Init(IInspectable* view, IInspectable* window, __int32 inner)
|
||||
#endif
|
||||
{
|
||||
LogFunction();
|
||||
NS_ASSERTION(view, "invalid framework view pointer");
|
||||
NS_ASSERTION(window, "invalid window pointer");
|
||||
NS_ASSERTION(inner, "invalid Accessible pointer");
|
||||
|
||||
#if defined(ACCESSIBILITY)
|
||||
window->QueryInterface(IID_PPV_ARGS(&mWindow));
|
||||
|
||||
if (FAILED(UIATextElement_CreateInstance(this)))
|
||||
return E_FAIL;
|
||||
|
||||
// init AccessibilityBridge and connect to accessibility
|
||||
mBridge = new AccessibilityBridge();
|
||||
if (!mBridge->Init(CastToUnknown(), (Accessible*)inner))
|
||||
return E_FAIL;
|
||||
|
||||
mConnected = true;
|
||||
return S_OK;
|
||||
#endif
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::CheckFocus(int x, int y)
|
||||
{
|
||||
LogFunction();
|
||||
VARIANT_BOOL val = VARIANT_FALSE;
|
||||
gElement->CheckFocus(x, y);
|
||||
gElement->HasFocus(&val);
|
||||
mHasFocus = (val == VARIANT_TRUE);
|
||||
UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::ClearFocus()
|
||||
{
|
||||
LogFunction();
|
||||
mHasFocus = false;
|
||||
gElement->ClearFocus();
|
||||
UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::HasFocus(VARIANT_BOOL * hasFocus)
|
||||
{
|
||||
LogFunction();
|
||||
*hasFocus = mHasFocus ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::Disconnect()
|
||||
{
|
||||
LogFunction();
|
||||
#if defined(ACCESSIBILITY)
|
||||
mBridge->Disconnect();
|
||||
mBridge = nullptr;
|
||||
#endif
|
||||
mConnected = false;
|
||||
mWindow = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IUIAElement
|
||||
|
||||
#if defined(x86_64)
|
||||
HRESULT
|
||||
UIABridge::SetFocusInternal(__int64 aAccessible)
|
||||
#else
|
||||
HRESULT
|
||||
UIABridge::SetFocusInternal(__int32 aAccessible)
|
||||
#endif
|
||||
{
|
||||
LogFunction();
|
||||
mHasFocus = true;
|
||||
ComPtr<IUIAElement> doc;
|
||||
gElement.As(&doc);
|
||||
if (doc)
|
||||
doc->SetFocusInternal(aAccessible);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
UIABridge::Connected()
|
||||
{
|
||||
#if defined(ACCESSIBILITY)
|
||||
return !(!mConnected || !mBridge->Connected());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// IRawElementProviderFragmentRoot
|
||||
|
||||
HRESULT
|
||||
UIABridge::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment ** retVal)
|
||||
{
|
||||
LogFunction();
|
||||
*retVal = nullptr;
|
||||
if (!Connected()) {
|
||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||
}
|
||||
gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::GetFocus(IRawElementProviderFragment ** retVal)
|
||||
{
|
||||
LogFunction();
|
||||
if (!Connected()) {
|
||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||
}
|
||||
if (!mHasFocus)
|
||||
return S_OK;
|
||||
|
||||
gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IRawElementProviderFragment
|
||||
|
||||
HRESULT
|
||||
UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal)
|
||||
{
|
||||
LogFunction();
|
||||
if (!Connected()) {
|
||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||
}
|
||||
*retVal = nullptr;
|
||||
switch(direction) {
|
||||
case NavigateDirection_Parent:
|
||||
break;
|
||||
case NavigateDirection_NextSibling:
|
||||
break;
|
||||
case NavigateDirection_PreviousSibling:
|
||||
break;
|
||||
case NavigateDirection_FirstChild:
|
||||
gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
break;
|
||||
case NavigateDirection_LastChild:
|
||||
gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
break;
|
||||
}
|
||||
|
||||
// For the other directions (parent, next, previous) the default of nullptr is correct
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::GetRuntimeId(SAFEARRAY ** retVal)
|
||||
{
|
||||
if (!Connected()) {
|
||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||
}
|
||||
|
||||
int runtimeId[2] = { UiaAppendRuntimeId, 1 }; // always 1
|
||||
*retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId));
|
||||
if (*retVal != nullptr) {
|
||||
for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) {
|
||||
SafeArrayPutElement(*retVal, &index, &runtimeId[index]);
|
||||
}
|
||||
} else {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::get_BoundingRectangle(UiaRect * retVal)
|
||||
{
|
||||
LogFunction();
|
||||
if (!Connected() || !mWindow) {
|
||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||
}
|
||||
|
||||
// physical pixel value = (DIP x DPI) / 96
|
||||
FLOAT dpi;
|
||||
HRESULT hr;
|
||||
ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> dispProps;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), dispProps.GetAddressOf());
|
||||
AssertRetHRESULT(hr, hr);
|
||||
AssertRetHRESULT(hr = dispProps->get_LogicalDpi(&dpi), hr);
|
||||
|
||||
Rect bounds;
|
||||
mWindow->get_Bounds(&bounds);
|
||||
retVal->left = ((bounds.X * dpi) / 96.0);
|
||||
retVal->top = ((bounds.Y * dpi) / 96.0);
|
||||
retVal->width = ((bounds.Width * dpi) / 96.0);
|
||||
retVal->height = ((bounds.Height * dpi) / 96.0);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal)
|
||||
{
|
||||
if (!Connected()) {
|
||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||
}
|
||||
// doesn't apply according to msdn.
|
||||
*retVal = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::SetFocus()
|
||||
{
|
||||
LogFunction();
|
||||
if (!Connected()) {
|
||||
return UIA_E_ELEMENTNOTAVAILABLE;
|
||||
}
|
||||
UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal)
|
||||
{
|
||||
// we are the fragment root. Our children return us for this call.
|
||||
return QueryInterface(IID_PPV_ARGS(retVal));
|
||||
}
|
||||
|
||||
// IRawElementProviderSimple
|
||||
|
||||
HRESULT
|
||||
UIABridge::get_ProviderOptions(ProviderOptions * pRetVal)
|
||||
{
|
||||
if (!Connected()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
*pRetVal = ProviderOptions_ServerSideProvider |
|
||||
ProviderOptions_UseComThreading |
|
||||
ProviderOptions_UseClientCoordinates;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
Log(L"UIABridge::GetPatternProvider=%d", patternId);
|
||||
|
||||
// The root window doesn't support any specific pattern
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
pRetVal->vt = VT_EMPTY;
|
||||
|
||||
// native hwnd
|
||||
if (idProp == 30020) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Log(L"UIABridge::GetPropertyValue: idProp=%d", idProp);
|
||||
|
||||
if (!Connected()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
switch (idProp) {
|
||||
case UIA_AutomationIdPropertyId:
|
||||
pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge0001");
|
||||
pRetVal->vt = VT_BSTR;
|
||||
break;
|
||||
|
||||
case UIA_ControlTypePropertyId:
|
||||
pRetVal->vt = VT_I4;
|
||||
pRetVal->lVal = UIA_WindowControlTypeId;
|
||||
break;
|
||||
|
||||
case UIA_IsKeyboardFocusablePropertyId:
|
||||
case UIA_IsContentElementPropertyId:
|
||||
case UIA_IsControlElementPropertyId:
|
||||
case UIA_IsEnabledPropertyId:
|
||||
pRetVal->boolVal = VARIANT_TRUE;
|
||||
pRetVal->vt = VT_BOOL;
|
||||
break;
|
||||
|
||||
case UIA_HasKeyboardFocusPropertyId:
|
||||
pRetVal->vt = VT_BOOL;
|
||||
pRetVal->boolVal = mHasFocus ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
break;
|
||||
|
||||
case UIA_NamePropertyId:
|
||||
pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge");
|
||||
pRetVal->vt = VT_BSTR;
|
||||
break;
|
||||
|
||||
case UIA_IsPasswordPropertyId:
|
||||
pRetVal->vt = VT_BOOL;
|
||||
pRetVal->boolVal = VARIANT_FALSE;
|
||||
break;
|
||||
|
||||
case UIA_NativeWindowHandlePropertyId:
|
||||
break;
|
||||
|
||||
default:
|
||||
Log(L"UIABridge: Unhandled property");
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIABridge::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal)
|
||||
{
|
||||
// We only have this in the root bridge - this is our parent ICoreWindow.
|
||||
*ppRetVal = nullptr;
|
||||
if (mWindow != nullptr) {
|
||||
IInspectable *pHostAsInspectable = nullptr;
|
||||
if (SUCCEEDED(mWindow->get_AutomationHostProvider(&pHostAsInspectable))) {
|
||||
pHostAsInspectable->QueryInterface(ppRetVal);
|
||||
pHostAsInspectable->Release();
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Element
|
||||
|
||||
#if defined(x86_64)
|
||||
HRESULT
|
||||
UIATextElement::SetFocusInternal(__int64 aAccessible)
|
||||
#else
|
||||
HRESULT
|
||||
UIATextElement::SetFocusInternal(__int32 aAccessible)
|
||||
#endif
|
||||
{
|
||||
LogFunction();
|
||||
#if defined(ACCESSIBILITY)
|
||||
nsCOMPtr<nsIAccessible> item = (nsIAccessible*)aAccessible;
|
||||
NS_ASSERTION(item, "Bad accessible pointer");
|
||||
if (item) {
|
||||
int32_t docX = 0, docY = 0, docWidth = 0, docHeight = 0;
|
||||
item->GetBounds(&docX, &docY, &docWidth, &docHeight);
|
||||
mBounds.X = (float)docX;
|
||||
mBounds.Y = (float)docY;
|
||||
mBounds.Width = (float)docWidth;
|
||||
mBounds.Height = (float)docHeight;
|
||||
SetFocus();
|
||||
}
|
||||
return S_OK;
|
||||
#endif
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static bool
|
||||
RectContains(const Rect& rect, int x, int y)
|
||||
{
|
||||
return ((x >= rect.X && x <= (rect.X + rect.Width) &&
|
||||
(y >= rect.Y && y <= (rect.Y + rect.Height))));
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::CheckFocus(int x, int y)
|
||||
{
|
||||
LogFunction();
|
||||
if (RectContains(mBounds, x, y))
|
||||
return S_OK;
|
||||
Log(L"UIATextElement::CheckFocus CLEAR!");
|
||||
mHasFocus = false;
|
||||
UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::ClearFocus()
|
||||
{
|
||||
LogFunction();
|
||||
mHasFocus = false;
|
||||
UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::HasFocus(VARIANT_BOOL * hasFocus)
|
||||
{
|
||||
LogFunction();
|
||||
*hasFocus = mHasFocus ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IRawElementProviderFragment
|
||||
|
||||
HRESULT
|
||||
UIATextElement::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal)
|
||||
{
|
||||
LogFunction();
|
||||
|
||||
*retVal = nullptr;
|
||||
switch(direction) {
|
||||
case NavigateDirection_Parent:
|
||||
gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
break;
|
||||
case NavigateDirection_NextSibling:
|
||||
break;
|
||||
case NavigateDirection_PreviousSibling:
|
||||
break;
|
||||
case NavigateDirection_FirstChild:
|
||||
break;
|
||||
case NavigateDirection_LastChild:
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::GetRuntimeId(SAFEARRAY ** retVal)
|
||||
{
|
||||
int runtimeId[2] = { UiaAppendRuntimeId, mIndexID };
|
||||
*retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId));
|
||||
if (*retVal != nullptr) {
|
||||
for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) {
|
||||
SafeArrayPutElement(*retVal, &index, &runtimeId[index]);
|
||||
}
|
||||
} else {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::get_BoundingRectangle(UiaRect * retVal)
|
||||
{
|
||||
LogFunction();
|
||||
retVal->left = mBounds.X;
|
||||
retVal->top = mBounds.Y;
|
||||
retVal->width = mBounds.Width;
|
||||
retVal->height = mBounds.Height;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal)
|
||||
{
|
||||
*retVal = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::SetFocus()
|
||||
{
|
||||
LogFunction();
|
||||
mHasFocus = true;
|
||||
UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal)
|
||||
{
|
||||
return gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal));
|
||||
}
|
||||
|
||||
// IRawElementProviderSimple
|
||||
|
||||
HRESULT
|
||||
UIATextElement::get_ProviderOptions(ProviderOptions * pRetVal)
|
||||
{
|
||||
*pRetVal = ProviderOptions_ServerSideProvider |
|
||||
ProviderOptions_UseComThreading |
|
||||
ProviderOptions_UseClientCoordinates;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
Log(L"UIATextElement::GetPatternProvider=%d", patternId);
|
||||
|
||||
// UIA_ValuePatternId - 10002
|
||||
// UIA_TextPatternId - 10014
|
||||
// UIA_TextChildPatternId - 10029
|
||||
|
||||
*ppRetVal = nullptr;
|
||||
if (patternId == UIA_TextPatternId) {
|
||||
Log(L"** TextPattern requested from element.");
|
||||
*ppRetVal = static_cast<ITextProvider*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
} else if (patternId == UIA_ValuePatternId) {
|
||||
Log(L"** ValuePattern requested from element.");
|
||||
*ppRetVal = static_cast<IValueProvider*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
pRetVal->vt = VT_EMPTY;
|
||||
|
||||
// native hwnd
|
||||
if (idProp == 30020) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Log(L"UIATextElement::GetPropertyValue: idProp=%d", idProp);
|
||||
|
||||
switch (idProp) {
|
||||
case UIA_AutomationIdPropertyId:
|
||||
pRetVal->bstrVal = SysAllocString(L"MozillaDocument0001");
|
||||
pRetVal->vt = VT_BSTR;
|
||||
break;
|
||||
|
||||
case UIA_ControlTypePropertyId:
|
||||
pRetVal->vt = VT_I4;
|
||||
pRetVal->lVal = UIA_DocumentControlTypeId;
|
||||
break;
|
||||
|
||||
case UIA_IsTextPatternAvailablePropertyId:
|
||||
case UIA_IsKeyboardFocusablePropertyId:
|
||||
case UIA_IsContentElementPropertyId:
|
||||
case UIA_IsControlElementPropertyId:
|
||||
case UIA_IsEnabledPropertyId:
|
||||
pRetVal->boolVal = VARIANT_TRUE;
|
||||
pRetVal->vt = VT_BOOL;
|
||||
break;
|
||||
|
||||
case UIA_LocalizedControlTypePropertyId:
|
||||
case UIA_LabeledByPropertyId:
|
||||
break;
|
||||
|
||||
case UIA_HasKeyboardFocusPropertyId:
|
||||
pRetVal->vt = VT_BOOL;
|
||||
pRetVal->boolVal = mHasFocus ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
break;
|
||||
|
||||
case UIA_NamePropertyId:
|
||||
pRetVal->bstrVal = SysAllocString(L"MozillaDocument");
|
||||
pRetVal->vt = VT_BSTR;
|
||||
break;
|
||||
|
||||
case UIA_IsPasswordPropertyId:
|
||||
pRetVal->vt = VT_BOOL;
|
||||
pRetVal->boolVal = VARIANT_FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
Log(L"UIATextElement: Unhandled property");
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal)
|
||||
{
|
||||
*ppRetVal = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// ITextProvider
|
||||
|
||||
HRESULT
|
||||
UIATextElement::GetSelection(SAFEARRAY * *pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::GetVisibleRanges(SAFEARRAY * *pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::get_DocumentRange(ITextRangeProvider **pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UIATextElement::get_SupportedTextSelection(SupportedTextSelection *pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// IValueProvider
|
||||
|
||||
IFACEMETHODIMP
|
||||
UIATextElement::SetValue(LPCWSTR val)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP
|
||||
UIATextElement::get_Value(BSTR *pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP
|
||||
UIATextElement::get_IsReadOnly(BOOL *pRetVal)
|
||||
{
|
||||
LogFunction();
|
||||
*pRetVal = FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} } }
|
31
widget/windows/winrt/UIABridge.idl
Normal file
31
widget/windows/winrt/UIABridge.idl
Normal file
@ -0,0 +1,31 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#define DO_NO_IMPORTS 1
|
||||
|
||||
import "oaidl.idl";
|
||||
import "oleacc.idl";
|
||||
import "Inspectable.idl";
|
||||
|
||||
[uuid(343159D8-B1E9-4464-82FC-B12C7A473CF1)]
|
||||
interface IUIABridge : IInspectable {
|
||||
#if defined(x86_64)
|
||||
HRESULT Init([in] IInspectable* view, [in] IInspectable* window, [in] __int64 inner);
|
||||
#else
|
||||
HRESULT Init([in] IInspectable* view, [in] IInspectable* window, [in] __int32 inner);
|
||||
#endif
|
||||
HRESULT Disconnect();
|
||||
};
|
||||
|
||||
[uuid(2153B284-F946-4209-908D-AB8AA1FED09C)]
|
||||
interface IUIAElement : IInspectable {
|
||||
#if defined(x86_64)
|
||||
HRESULT SetFocusInternal([in] __int64 accessible);
|
||||
#else
|
||||
HRESULT SetFocusInternal([in] __int32 accessible);
|
||||
#endif
|
||||
HRESULT CheckFocus([in] int X, [in] int y);
|
||||
HRESULT ClearFocus();
|
||||
HRESULT HasFocus([out, retval] VARIANT_BOOL * hasFocus);
|
||||
};
|
157
widget/windows/winrt/UIABridgePrivate.h
Normal file
157
widget/windows/winrt/UIABridgePrivate.h
Normal file
@ -0,0 +1,157 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.system.h>
|
||||
#include <windows.ui.core.h>
|
||||
#include <UIAutomation.h>
|
||||
#include <UIAutomationCore.h>
|
||||
#include <UIAutomationCoreApi.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include "UIAAccessibilityBridge.h"
|
||||
|
||||
// generated
|
||||
#include "UIABridge.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
// represents the root window to UIA
|
||||
[uuid("D3EDD951-0715-4501-A8E5-25D97EF35D5A")]
|
||||
class UIABridge : public RuntimeClass<RuntimeClassFlags<RuntimeClassType::WinRtClassicComMix>,
|
||||
IUIABridge,
|
||||
IUIAElement,
|
||||
IRawElementProviderSimple,
|
||||
IRawElementProviderFragment,
|
||||
IRawElementProviderFragmentRoot>
|
||||
{
|
||||
typedef ABI::Windows::UI::Core::ICoreWindow ICoreWindow;
|
||||
|
||||
InspectableClass(L"IUIABridge", BaseTrust);
|
||||
|
||||
public:
|
||||
UIABridge() :
|
||||
mConnected(false),
|
||||
mHasFocus(false)
|
||||
{}
|
||||
|
||||
// IUIABridge
|
||||
#if defined(x86_64)
|
||||
IFACEMETHODIMP Init(IInspectable* view, IInspectable* window, __int64 inner);
|
||||
#else
|
||||
IFACEMETHODIMP Init(IInspectable* view, IInspectable* window, __int32 inner);
|
||||
#endif
|
||||
IFACEMETHODIMP Disconnect();
|
||||
|
||||
// IUIAElement
|
||||
#if defined(x86_64)
|
||||
IFACEMETHODIMP SetFocusInternal(__int64 aAccessible);
|
||||
#else
|
||||
IFACEMETHODIMP SetFocusInternal(__int32 aAccessible);
|
||||
#endif
|
||||
IFACEMETHODIMP CheckFocus(int x, int y);
|
||||
IFACEMETHODIMP ClearFocus();
|
||||
IFACEMETHODIMP HasFocus(VARIANT_BOOL * hasFocus);
|
||||
|
||||
// IRawElementProviderFragmentRoot
|
||||
IFACEMETHODIMP ElementProviderFromPoint(double x, double y, IRawElementProviderFragment ** retVal);
|
||||
IFACEMETHODIMP GetFocus(IRawElementProviderFragment ** retVal);
|
||||
|
||||
// IRawElementProviderFragment
|
||||
IFACEMETHODIMP Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal);
|
||||
IFACEMETHODIMP GetRuntimeId(SAFEARRAY ** retVal);
|
||||
IFACEMETHODIMP get_BoundingRectangle(UiaRect * retVal);
|
||||
IFACEMETHODIMP GetEmbeddedFragmentRoots(SAFEARRAY ** retVal);
|
||||
IFACEMETHODIMP SetFocus();
|
||||
IFACEMETHODIMP get_FragmentRoot(IRawElementProviderFragmentRoot * * retVal);
|
||||
|
||||
// IRawElementProviderSimple
|
||||
IFACEMETHODIMP get_ProviderOptions(ProviderOptions * retVal);
|
||||
IFACEMETHODIMP GetPatternProvider(PATTERNID iid, IUnknown * * retVal);
|
||||
IFACEMETHODIMP GetPropertyValue(PROPERTYID idProp, VARIANT * retVal );
|
||||
IFACEMETHODIMP get_HostRawElementProvider(IRawElementProviderSimple ** retVal);
|
||||
|
||||
protected:
|
||||
bool Connected();
|
||||
|
||||
private:
|
||||
bool mConnected;
|
||||
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
||||
#if defined(ACCESSIBILITY)
|
||||
nsRefPtr<AccessibilityBridge> mBridge;
|
||||
#endif
|
||||
bool mHasFocus;
|
||||
};
|
||||
|
||||
[uuid("4438135F-F624-43DE-A417-275CE7A1A0CD")]
|
||||
class UIATextElement : public RuntimeClass<RuntimeClassFlags<RuntimeClassType::WinRtClassicComMix>,
|
||||
IUIAElement,
|
||||
IRawElementProviderSimple,
|
||||
IRawElementProviderFragment,
|
||||
ITextProvider,
|
||||
IValueProvider >
|
||||
{
|
||||
typedef ABI::Windows::Foundation::Rect Rect;
|
||||
|
||||
InspectableClass(L"UIATextElement", BaseTrust);
|
||||
|
||||
public:
|
||||
UIATextElement() :
|
||||
mHasFocus(false)
|
||||
{}
|
||||
|
||||
// IUIAElement
|
||||
#if defined(x86_64)
|
||||
IFACEMETHODIMP SetFocusInternal(__int64 aAccessible);
|
||||
#else
|
||||
IFACEMETHODIMP SetFocusInternal(__int32 aAccessible);
|
||||
#endif
|
||||
IFACEMETHODIMP CheckFocus(int x, int y);
|
||||
IFACEMETHODIMP ClearFocus();
|
||||
IFACEMETHODIMP HasFocus(VARIANT_BOOL * hasFocus);
|
||||
|
||||
// IRawElementProviderFragment
|
||||
IFACEMETHODIMP Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal);
|
||||
IFACEMETHODIMP GetRuntimeId(SAFEARRAY ** retVal);
|
||||
IFACEMETHODIMP get_BoundingRectangle(UiaRect * retVal);
|
||||
IFACEMETHODIMP GetEmbeddedFragmentRoots(SAFEARRAY ** retVal);
|
||||
IFACEMETHODIMP SetFocus();
|
||||
IFACEMETHODIMP get_FragmentRoot(IRawElementProviderFragmentRoot * * retVal);
|
||||
|
||||
// IRawElementProviderSimple
|
||||
IFACEMETHODIMP get_ProviderOptions(ProviderOptions * retVal);
|
||||
IFACEMETHODIMP GetPatternProvider(PATTERNID iid, IUnknown * * retVal);
|
||||
IFACEMETHODIMP GetPropertyValue(PROPERTYID idProp, VARIANT * retVal );
|
||||
IFACEMETHODIMP get_HostRawElementProvider(IRawElementProviderSimple ** retVal);
|
||||
|
||||
// ITextProvider
|
||||
IFACEMETHODIMP GetSelection(SAFEARRAY * *pRetVal);
|
||||
IFACEMETHODIMP GetVisibleRanges(SAFEARRAY * *pRetVal);
|
||||
IFACEMETHODIMP RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal);
|
||||
IFACEMETHODIMP RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal);
|
||||
IFACEMETHODIMP get_DocumentRange(ITextRangeProvider **pRetVal);
|
||||
IFACEMETHODIMP get_SupportedTextSelection(SupportedTextSelection *pRetVal);
|
||||
|
||||
// IValueProvider
|
||||
IFACEMETHODIMP SetValue(LPCWSTR val);
|
||||
IFACEMETHODIMP get_Value(BSTR *pRetVal);
|
||||
IFACEMETHODIMP get_IsReadOnly(BOOL *pRetVal);
|
||||
|
||||
void SetIndexID(int id) {
|
||||
mIndexID = id;
|
||||
}
|
||||
|
||||
private:
|
||||
int mIndexID;
|
||||
Rect mBounds;
|
||||
bool mHasFocus;
|
||||
};
|
||||
|
||||
} } }
|
19
widget/windows/winrt/UIABridgePublic.h
Normal file
19
widget/windows/winrt/UIABridgePublic.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.system.h>
|
||||
#include <windows.ui.core.h>
|
||||
#include <UIAutomation.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
|
||||
// Factory function for UIABridge
|
||||
HRESULT UIABridge_CreateInstance(IInspectable **retVal);
|
||||
|
||||
} } }
|
3
widget/windows/winrt/components.manifest
Normal file
3
widget/windows/winrt/components.manifest
Normal file
@ -0,0 +1,3 @@
|
||||
# MetroUIUtils.js
|
||||
component {e4626085-17f7-4068-a225-66c1acc0485c} MetroUIUtils.js
|
||||
contract @mozilla.org/metro-ui-utils;1 {e4626085-17f7-4068-a225-66c1acc0485c}
|
77
widget/windows/winrt/mozwrlbase.h
Normal file
77
widget/windows/winrt/mozwrlbase.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Includes <wrl.h> and it's children. Defines imports needed by
|
||||
* corewrappers.h in the case where windows.h has already been
|
||||
* included w/WINVER < 0x600. Also ups WINVER/_WIN32_WINNT prior
|
||||
* to including wrl.h. Mozilla's build currently has WINVER set to
|
||||
* 0x502 for XP support.
|
||||
*/
|
||||
|
||||
#if _WIN32_WINNT < 0x600
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
ReleaseSRWLockExclusive(
|
||||
_Inout_ PSRWLOCK SRWLock
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
ReleaseSRWLockShared(
|
||||
_Inout_ PSRWLOCK SRWLock
|
||||
);
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
InitializeCriticalSectionEx(
|
||||
_Out_ LPCRITICAL_SECTION lpCriticalSection,
|
||||
_In_ DWORD dwSpinCount,
|
||||
_In_ DWORD Flags
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
InitializeSRWLock(
|
||||
_Out_ PSRWLOCK SRWLock
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
AcquireSRWLockExclusive(
|
||||
_Inout_ PSRWLOCK SRWLock
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
WINAPI
|
||||
TryAcquireSRWLockExclusive(
|
||||
_Inout_ PSRWLOCK SRWLock
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
WINAPI
|
||||
TryAcquireSRWLockShared(
|
||||
_Inout_ PSRWLOCK SRWLock
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
AcquireSRWLockShared(
|
||||
_Inout_ PSRWLOCK SRWLock
|
||||
);
|
||||
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
#define WINVER 0x600
|
||||
#define _WIN32_WINNT 0x600
|
||||
|
||||
#endif // _WIN32_WINNT < 0x600
|
||||
|
||||
#include <wrl.h>
|
483
widget/windows/winrt/nsMetroFilePicker.cpp
Normal file
483
widget/windows/winrt/nsMetroFilePicker.cpp
Normal file
@ -0,0 +1,483 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsMetroFilePicker.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "MetroUtils.h"
|
||||
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
#include <windows.storage.search.h>
|
||||
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::Foundation::Collections;
|
||||
using namespace ABI::Windows::Storage;
|
||||
using namespace ABI::Windows::Storage::Pickers;
|
||||
using namespace ABI::Windows::Storage::Streams;
|
||||
using namespace ABI::Windows::UI;
|
||||
using namespace ABI::Windows::UI::ViewManagement;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace mozilla::widget::winrt;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsIFilePicker
|
||||
|
||||
nsMetroFilePicker::nsMetroFilePicker()
|
||||
{
|
||||
}
|
||||
|
||||
nsMetroFilePicker::~nsMetroFilePicker()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMetroFilePicker, nsIFilePicker)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::Init(nsIDOMWindow *parent, const nsAString& title, int16_t mode)
|
||||
{
|
||||
mMode = mode;
|
||||
HRESULT hr;
|
||||
switch(mMode) {
|
||||
case nsIFilePicker::modeOpen:
|
||||
case nsIFilePicker::modeOpenMultiple:
|
||||
hr = ActivateGenericInstance(RuntimeClass_Windows_Storage_Pickers_FileOpenPicker, mFileOpenPicker);
|
||||
AssertRetHRESULT(hr, NS_ERROR_UNEXPECTED);
|
||||
return NS_OK;
|
||||
case nsIFilePicker::modeSave:
|
||||
hr = ActivateGenericInstance(RuntimeClass_Windows_Storage_Pickers_FileSavePicker, mFileSavePicker);
|
||||
AssertRetHRESULT(hr, NS_ERROR_UNEXPECTED);
|
||||
return NS_OK;
|
||||
default:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::Show(int16_t *aReturnVal)
|
||||
{
|
||||
// Metro file picker only offers an async variant which calls back to the
|
||||
// UI thread, which is the main thread. We therefore can't call it
|
||||
// synchronously from the main thread.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HRESULT nsMetroFilePicker::OnPickSingleFile(IAsyncOperation<StorageFile*>* aFile,
|
||||
AsyncStatus aStatus)
|
||||
{
|
||||
if (aStatus != ABI::Windows::Foundation::AsyncStatus::Completed) {
|
||||
if (mCallback)
|
||||
mCallback->Done(nsIFilePicker::returnCancel);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
ComPtr<IStorageFile> file;
|
||||
hr = aFile->GetResults(file.GetAddressOf());
|
||||
// When the user cancels hr == S_OK and file is NULL
|
||||
if (FAILED(hr) || !file) {
|
||||
if (mCallback)
|
||||
mCallback->Done(nsIFilePicker::returnCancel);
|
||||
return S_OK;
|
||||
}
|
||||
ComPtr<IStorageItem> storageItem;
|
||||
hr = file.As(&storageItem);
|
||||
if (FAILED(hr)) {
|
||||
if (mCallback)
|
||||
mCallback->Done(nsIFilePicker::returnCancel);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HSTRING path;
|
||||
if (FAILED(storageItem->get_Path(&path))) {
|
||||
if (mCallback)
|
||||
mCallback->Done(nsIFilePicker::returnCancel);
|
||||
return S_OK;
|
||||
}
|
||||
WindowsDuplicateString(path, mFilePath.GetAddressOf());
|
||||
WindowsDeleteString(path);
|
||||
|
||||
if (mCallback) {
|
||||
mCallback->Done(nsIFilePicker::returnOK);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT nsMetroFilePicker::OnPickMultipleFiles(IAsyncOperation<IVectorView<StorageFile*>*>* aFileList,
|
||||
AsyncStatus aStatus)
|
||||
{
|
||||
if (aStatus != ABI::Windows::Foundation::AsyncStatus::Completed) {
|
||||
if (mCallback)
|
||||
mCallback->Done(nsIFilePicker::returnCancel);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
ComPtr<IVectorView<StorageFile*>> view;
|
||||
hr = aFileList->GetResults(view.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
if (mCallback)
|
||||
mCallback->Done(nsIFilePicker::returnCancel);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
unsigned int length;
|
||||
view->get_Size(&length);
|
||||
for (unsigned int idx = 0; idx < length; idx++) {
|
||||
ComPtr<IStorageFile> file;
|
||||
hr = view->GetAt(idx, file.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ComPtr<IStorageItem> storageItem;
|
||||
hr = file.As(&storageItem);
|
||||
if (FAILED(hr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HSTRING path;
|
||||
if (SUCCEEDED(storageItem->get_Path(&path))) {
|
||||
nsCOMPtr<nsILocalFile> file =
|
||||
do_CreateInstance("@mozilla.org/file/local;1");
|
||||
unsigned int tmp;
|
||||
if (NS_SUCCEEDED(file->InitWithPath(
|
||||
nsAutoString(WindowsGetStringRawBuffer(path, &tmp))))) {
|
||||
mFiles.AppendObject(file);
|
||||
}
|
||||
}
|
||||
WindowsDeleteString(path);
|
||||
}
|
||||
|
||||
if (mCallback) {
|
||||
mCallback->Done(nsIFilePicker::returnOK);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::Open(nsIFilePickerShownCallback *aCallback)
|
||||
{
|
||||
HRESULT hr;
|
||||
// Capture a reference to the callback which we'll also pass into the
|
||||
// closure to ensure it's not freed.
|
||||
mCallback = aCallback;
|
||||
|
||||
// The filepicker cannot open when in snapped view, try to unsnapp
|
||||
// before showing the filepicker.
|
||||
ApplicationViewState viewState;
|
||||
MetroUtils::GetViewState(viewState);
|
||||
if (viewState == ApplicationViewState::ApplicationViewState_Snapped) {
|
||||
bool unsnapped = SUCCEEDED(MetroUtils::TryUnsnap());
|
||||
NS_ENSURE_TRUE(unsnapped, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
switch(mMode) {
|
||||
case nsIFilePicker::modeOpen: {
|
||||
NS_ENSURE_ARG_POINTER(mFileOpenPicker);
|
||||
|
||||
// Initiate the file picker operation
|
||||
ComPtr<IAsyncOperation<StorageFile*>> asyncOperation;
|
||||
hr = mFileOpenPicker->PickSingleFileAsync(asyncOperation.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
|
||||
// Subscribe to the completed event
|
||||
ComPtr<IAsyncOperationCompletedHandler<StorageFile*>>
|
||||
completedHandler(Callback<IAsyncOperationCompletedHandler<StorageFile*>>(
|
||||
this, &nsMetroFilePicker::OnPickSingleFile));
|
||||
hr = asyncOperation->put_Completed(completedHandler.Get());
|
||||
AssertRetHRESULT(hr, NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIFilePicker::modeOpenMultiple: {
|
||||
NS_ENSURE_ARG_POINTER(mFileOpenPicker);
|
||||
|
||||
typedef IVectorView<StorageFile*> StorageTemplate;
|
||||
typedef IAsyncOperation<StorageTemplate*> AsyncCallbackTemplate;
|
||||
typedef IAsyncOperationCompletedHandler<StorageTemplate*> HandlerTemplate;
|
||||
|
||||
// Initiate the file picker operation
|
||||
ComPtr<AsyncCallbackTemplate> asyncOperation;
|
||||
hr = mFileOpenPicker->PickMultipleFilesAsync(asyncOperation.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
|
||||
// Subscribe to the completed event
|
||||
ComPtr<HandlerTemplate> completedHandler(Callback<HandlerTemplate>(
|
||||
this, &nsMetroFilePicker::OnPickMultipleFiles));
|
||||
hr = asyncOperation->put_Completed(completedHandler.Get());
|
||||
AssertRetHRESULT(hr, NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIFilePicker::modeSave: {
|
||||
NS_ENSURE_ARG_POINTER(mFileSavePicker);
|
||||
|
||||
// Set the default file name
|
||||
mFileSavePicker->put_SuggestedFileName(HStringReference(mDefaultFilename.BeginReading()).Get());
|
||||
|
||||
// Set the default file extension
|
||||
if (mDefaultExtension.Length() > 0) {
|
||||
nsAutoString defaultFileExtension(mDefaultExtension);
|
||||
|
||||
// Touch up the extansion format platform hands us.
|
||||
if (defaultFileExtension[0] == L'*') {
|
||||
defaultFileExtension.Cut(0, 1);
|
||||
} else if (defaultFileExtension[0] != L'.') {
|
||||
defaultFileExtension.Insert(L".", 0);
|
||||
}
|
||||
|
||||
// Sometimes the default file extension is not passed in correctly,
|
||||
// so we purposfully ignore failures here.
|
||||
HString ext;
|
||||
ext.Set(defaultFileExtension.BeginReading());
|
||||
hr = mFileSavePicker->put_DefaultFileExtension(ext.Get());
|
||||
NS_ASSERTION(SUCCEEDED(hr), "put_DefaultFileExtension failed, bad format for extension?");
|
||||
|
||||
// Due to a bug in the WinRT file picker, the first file extension in the
|
||||
// list is always used when saving a file. So we explicitly make sure the
|
||||
// default extension is the first one in the list here.
|
||||
if (mFirstTitle.Get()) {
|
||||
ComPtr<IMap<HSTRING, IVector<HSTRING>*>> map;
|
||||
mFileSavePicker->get_FileTypeChoices(map.GetAddressOf());
|
||||
if (map) {
|
||||
boolean found = false;
|
||||
unsigned int index;
|
||||
map->HasKey(mFirstTitle.Get(), &found);
|
||||
if (found) {
|
||||
ComPtr<IVector<HSTRING>> list;
|
||||
if (SUCCEEDED(map->Lookup(mFirstTitle.Get(), list.GetAddressOf()))) {
|
||||
HString ext;
|
||||
ext.Set(defaultFileExtension.get());
|
||||
found = false;
|
||||
list->IndexOf(HStringReference(defaultFileExtension.get()).Get(), &index, &found);
|
||||
if (found) {
|
||||
list->RemoveAt(index);
|
||||
list->InsertAt(0, HStringReference(defaultFileExtension.get()).Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch the async show operation
|
||||
ComPtr<IAsyncOperation<StorageFile*>> asyncOperation;
|
||||
hr = mFileSavePicker->PickSaveFileAsync(asyncOperation.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
|
||||
// Subscribe to the completed event
|
||||
ComPtr<IAsyncOperationCompletedHandler<StorageFile*>>
|
||||
completedHandler(Callback<IAsyncOperationCompletedHandler<StorageFile*>>(
|
||||
this, &nsMetroFilePicker::OnPickSingleFile));
|
||||
hr = asyncOperation->put_Completed(completedHandler.Get());
|
||||
AssertRetHRESULT(hr, NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
case modeGetFolder:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
default:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::GetFile(nsIFile **aFile)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFile);
|
||||
*aFile = nullptr;
|
||||
|
||||
if (WindowsIsStringEmpty(mFilePath.Get()))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
|
||||
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
|
||||
unsigned int length;
|
||||
file->InitWithPath(nsAutoString(mFilePath.GetRawBuffer(&length)));
|
||||
NS_ADDREF(*aFile = file);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::GetFileURL(nsIURI **aFileURL)
|
||||
{
|
||||
*aFileURL = nullptr;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = GetFile(getter_AddRefs(file));
|
||||
if (!file)
|
||||
return rv;
|
||||
|
||||
return NS_NewFileURI(aFileURL, file);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFiles);
|
||||
return NS_NewArrayEnumerator(aFiles, mFiles);
|
||||
}
|
||||
|
||||
// Set the filter index
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::GetFilterIndex(int32_t *aFilterIndex)
|
||||
{
|
||||
// No associated concept with a Metro file picker
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::SetFilterIndex(int32_t aFilterIndex)
|
||||
{
|
||||
// No associated concept with a Metro file picker
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// AFACT, it's up to use to supply the implementation of a vector list.
|
||||
class MozHStringVector : public RuntimeClass<IVector<HSTRING>> {
|
||||
InspectableClass(L"MozHStringVector", TrustLevel::BaseTrust)
|
||||
~MozHStringVector() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
// See IVector_impl in windows.foundation.collections.h
|
||||
public:
|
||||
STDMETHOD(GetAt)(unsigned aIndex, HSTRING* aString) {
|
||||
if (aIndex >= mList.Length()) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
return WindowsDuplicateString(mList[aIndex], aString);
|
||||
}
|
||||
|
||||
STDMETHOD(get_Size)(unsigned int* aLength) {
|
||||
if (!aLength) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*aLength = mList.Length();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHOD(Append)(HSTRING aString) {
|
||||
HSTRING str;
|
||||
if (FAILED(WindowsDuplicateString(aString, &str))) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
mList.AppendElement(str);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHOD(Clear)() {
|
||||
int length = mList.Length();
|
||||
for (int idx = 0; idx < length; idx++)
|
||||
WindowsDeleteString(mList[idx]);
|
||||
mList.Clear();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// interfaces picker code doesn't seem to need
|
||||
STDMETHOD(GetView)(IVectorView<HSTRING> **aView) { return E_NOTIMPL; }
|
||||
STDMETHOD(IndexOf)(HSTRING aValue, unsigned *aIndex, boolean *found) { return E_NOTIMPL; }
|
||||
STDMETHOD(SetAt)(unsigned aIndex, HSTRING aString) { return E_NOTIMPL; }
|
||||
STDMETHOD(InsertAt)(unsigned aIndex, HSTRING aString) { return E_NOTIMPL; }
|
||||
STDMETHOD(RemoveAt)(unsigned aIndex) { return E_NOTIMPL; }
|
||||
STDMETHOD(RemoveAtEnd)() { return E_NOTIMPL; }
|
||||
|
||||
private:
|
||||
nsTArray<HSTRING> mList;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsMetroFilePicker::ParseFiltersIntoVector(ComPtr<IVector<HSTRING>>& aVector,
|
||||
const nsAString& aFilter,
|
||||
bool aAllowAll)
|
||||
{
|
||||
const PRUnichar *beg = aFilter.BeginReading();
|
||||
const PRUnichar *end = aFilter.EndReading();
|
||||
for (const PRUnichar *cur = beg, *fileTypeStart = beg; cur <= end; ++cur) {
|
||||
// Start of a a filetype, example: *.png
|
||||
if (cur == end || PRUnichar(' ') == *cur) {
|
||||
int32_t startPos = fileTypeStart - beg;
|
||||
int32_t endPos = cur - fileTypeStart - (cur == end ? 0 : 1);
|
||||
const nsAString& fileType = Substring(aFilter,
|
||||
startPos,
|
||||
endPos);
|
||||
// There is no way to say show all files in Metro save file picker, so
|
||||
// just use .data if * or *.* is specified.
|
||||
if (fileType.IsEmpty() ||
|
||||
fileType.Equals(L"*") ||
|
||||
fileType.Equals(L"*.*")) {
|
||||
HString str;
|
||||
if (aAllowAll) {
|
||||
str.Set(L"*");
|
||||
aVector->Append(str.Get());
|
||||
} else {
|
||||
str.Set(L".data");
|
||||
aVector->Append(str.Get());
|
||||
}
|
||||
} else {
|
||||
nsAutoString filter(fileType);
|
||||
if (filter[0] == L'*') {
|
||||
filter.Cut(0, 1);
|
||||
} else if (filter[0] != L'.') {
|
||||
filter.Insert(L".", 0);
|
||||
}
|
||||
HString str;
|
||||
str.Set(filter.BeginReading());
|
||||
aVector->Append(str.Get());
|
||||
}
|
||||
|
||||
fileTypeStart = cur + 1;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMetroFilePicker::AppendFilter(const nsAString& aTitle,
|
||||
const nsAString& aFilter)
|
||||
{
|
||||
HRESULT hr;
|
||||
switch(mMode) {
|
||||
case nsIFilePicker::modeOpen:
|
||||
case nsIFilePicker::modeOpenMultiple: {
|
||||
NS_ENSURE_ARG_POINTER(mFileOpenPicker);
|
||||
ComPtr<IVector<HSTRING>> list;
|
||||
mFileOpenPicker->get_FileTypeFilter(list.GetAddressOf());
|
||||
nsresult rv = ParseFiltersIntoVector(list, aFilter, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
case nsIFilePicker::modeSave: {
|
||||
NS_ENSURE_ARG_POINTER(mFileSavePicker);
|
||||
|
||||
ComPtr<IMap<HSTRING,IVector<HSTRING>*>> map;
|
||||
hr = mFileSavePicker->get_FileTypeChoices(map.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
|
||||
HString key;
|
||||
key.Set(aTitle.BeginReading());
|
||||
|
||||
ComPtr<IVector<HSTRING>> saveTypes;
|
||||
saveTypes = Make<MozHStringVector>();
|
||||
nsresult rv = ParseFiltersIntoVector(saveTypes, aFilter, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (WindowsIsStringEmpty(mFirstTitle.Get())) {
|
||||
mFirstTitle.Set(key.Get());
|
||||
}
|
||||
|
||||
boolean replaced;
|
||||
map->Insert(key.Get(), saveTypes.Get(), &replaced);
|
||||
}
|
||||
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
70
widget/windows/winrt/nsMetroFilePicker.h
Normal file
70
widget/windows/winrt/nsMetroFilePicker.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsMetroFilePicker_h__
|
||||
#define nsMetroFilePicker_h__
|
||||
|
||||
#include "../nsFilePicker.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILocalFile.h"
|
||||
|
||||
#include "mozwrlbase.h"
|
||||
|
||||
#include <windows.system.h>
|
||||
#include <windows.ui.core.h>
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.storage.pickers.h>
|
||||
#include <windows.storage.fileproperties.h>
|
||||
|
||||
/**
|
||||
* Metro file picker
|
||||
*/
|
||||
|
||||
class nsMetroFilePicker :
|
||||
public nsBaseWinFilePicker
|
||||
{
|
||||
typedef Microsoft::WRL::Wrappers::HString HString;
|
||||
typedef ABI::Windows::Storage::StorageFile StorageFile;
|
||||
typedef ABI::Windows::Foundation::AsyncStatus AsyncStatus;
|
||||
|
||||
public:
|
||||
nsMetroFilePicker();
|
||||
virtual ~nsMetroFilePicker();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFilePicker (less what's in nsBaseFilePicker)
|
||||
NS_IMETHOD GetFilterIndex(int32_t *aFilterIndex);
|
||||
NS_IMETHOD SetFilterIndex(int32_t aFilterIndex);
|
||||
NS_IMETHOD GetFile(nsIFile * *aFile);
|
||||
NS_IMETHOD GetFileURL(nsIURI * *aFileURL);
|
||||
NS_IMETHOD GetFiles(nsISimpleEnumerator **aFiles);
|
||||
NS_IMETHOD Show(int16_t *aReturnVal);
|
||||
NS_IMETHOD Open(nsIFilePickerShownCallback *aCallback);
|
||||
NS_IMETHOD AppendFilter(const nsAString& aTitle, const nsAString& aFilter);
|
||||
NS_IMETHOD Init(nsIDOMWindow *parent, const nsAString& title,
|
||||
int16_t mode);
|
||||
|
||||
// Async callbacks
|
||||
HRESULT OnPickSingleFile(ABI::Windows::Foundation::IAsyncOperation<StorageFile*>* aFile, AsyncStatus aStatus);
|
||||
HRESULT OnPickMultipleFiles(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Foundation::Collections::IVectorView<StorageFile*>*>* aFileList, AsyncStatus aStatus);
|
||||
|
||||
private:
|
||||
void InitNative(nsIWidget*, const nsAString&, int16_t) {};
|
||||
nsresult ParseFiltersIntoVector(Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVector<HSTRING>>& aVector,
|
||||
const nsAString& aFilter,
|
||||
bool aAllowAll);
|
||||
int16_t mMode;
|
||||
nsCOMArray<nsILocalFile> mFiles;
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Pickers::IFileOpenPicker> mFileOpenPicker;
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Pickers::IFileSavePicker> mFileSavePicker;
|
||||
HString mFilePath;
|
||||
HString mFirstTitle;
|
||||
nsRefPtr<nsIFilePickerShownCallback> mCallback;
|
||||
};
|
||||
|
||||
#endif // nsMetroFilePicker_h__
|
320
widget/windows/winrt/nsWinMetroUtils.cpp
Normal file
320
widget/windows/winrt/nsWinMetroUtils.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsWinMetroUtils.h"
|
||||
#include "MetroUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "FrameworkView.h"
|
||||
#include "MetroApp.h"
|
||||
|
||||
#include <shldisp.h>
|
||||
#include <shellapi.h>
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
#include <windows.ui.startscreen.h>
|
||||
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::UI::StartScreen;
|
||||
using namespace ABI::Windows::UI::ViewManagement;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace mozilla::widget::winrt;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
namespace winrt {
|
||||
extern ComPtr<MetroApp> sMetroApp;
|
||||
extern nsTArray<nsString>* sSettingsArray;
|
||||
} } }
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsWinMetroUtils, nsIWinMetroUtils)
|
||||
|
||||
nsWinMetroUtils::nsWinMetroUtils()
|
||||
{
|
||||
}
|
||||
|
||||
nsWinMetroUtils::~nsWinMetroUtils()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins a new tile to the Windows 8 start screen.
|
||||
*
|
||||
* @param aTileID An ID which can later be used to remove the tile
|
||||
* @param aShortName A short name for the tile
|
||||
* @param aDiplayName The name that will be displayed on the tile
|
||||
* @param aActivationArgs The arguments to pass to the browser upon
|
||||
* activation of the tile
|
||||
* @param aTileImage An image for the normal tile view
|
||||
* @param aSmallTileImage An image for the small tile view
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::PinTileAsync(const nsAString &aTileID,
|
||||
const nsAString &aShortName,
|
||||
const nsAString &aDisplayName,
|
||||
const nsAString &aActivationArgs,
|
||||
const nsAString &aTileImage,
|
||||
const nsAString &aSmallTileImage)
|
||||
{
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
NS_WARNING("PinTileAsync can't be called on the desktop.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
HRESULT hr;
|
||||
|
||||
HString logoStr, smallLogoStr, displayName, shortName;
|
||||
|
||||
logoStr.Set(aTileImage.BeginReading());
|
||||
smallLogoStr.Set(aSmallTileImage.BeginReading());
|
||||
displayName.Set(aDisplayName.BeginReading());
|
||||
shortName.Set(aShortName.BeginReading());
|
||||
|
||||
ComPtr<IUriRuntimeClass> logo, smallLogo;
|
||||
AssertRetHRESULT(MetroUtils::CreateUri(logoStr, logo), NS_ERROR_FAILURE);
|
||||
AssertRetHRESULT(MetroUtils::CreateUri(smallLogoStr, smallLogo), NS_ERROR_FAILURE);
|
||||
|
||||
HString tileActivationArgumentsStr, tileIdStr;
|
||||
tileActivationArgumentsStr.Set(aActivationArgs.BeginReading());
|
||||
tileIdStr.Set(aTileID.BeginReading());
|
||||
|
||||
ComPtr<ISecondaryTileFactory> tileFactory;
|
||||
ComPtr<ISecondaryTile> secondaryTile;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_StartScreen_SecondaryTile).Get(),
|
||||
tileFactory.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
hr = tileFactory->CreateWithId(tileIdStr.Get(), secondaryTile.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
|
||||
secondaryTile->put_Logo(logo.Get());
|
||||
secondaryTile->put_SmallLogo(smallLogo.Get());
|
||||
secondaryTile->put_DisplayName(displayName.Get());
|
||||
secondaryTile->put_ShortName(shortName.Get());
|
||||
secondaryTile->put_Arguments(tileActivationArgumentsStr.Get());
|
||||
secondaryTile->put_TileOptions(TileOptions::TileOptions_ShowNameOnLogo);
|
||||
secondaryTile->put_ForegroundText(ForegroundText::ForegroundText_Dark);
|
||||
|
||||
// The tile is created and we can now attempt to pin the tile.
|
||||
ComPtr<IAsyncOperationCompletedHandler<bool>> callback(Callback<IAsyncOperationCompletedHandler<bool>>(
|
||||
sMetroApp.Get(), &MetroApp::OnAsyncTileCreated));
|
||||
ComPtr<IAsyncOperation<bool>> operation;
|
||||
AssertRetHRESULT(secondaryTile->RequestCreateAsync(operation.GetAddressOf()), NS_ERROR_FAILURE);
|
||||
operation->put_Completed(callback.Get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpins a tile from the Windows 8 start screen.
|
||||
*
|
||||
* @param aTileID An existing ID which was previously pinned
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::UnpinTileAsync(const nsAString &aTileID)
|
||||
{
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
NS_WARNING("UnpinTileAsync can't be called on the desktop.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
HRESULT hr;
|
||||
HString tileIdStr;
|
||||
tileIdStr.Set(aTileID.BeginReading());
|
||||
|
||||
ComPtr<ISecondaryTileFactory> tileFactory;
|
||||
ComPtr<ISecondaryTile> secondaryTile;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_StartScreen_SecondaryTile).Get(),
|
||||
tileFactory.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
hr = tileFactory->CreateWithId(tileIdStr.Get(), secondaryTile.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
|
||||
// Attempt to unpin the tile
|
||||
ComPtr<IAsyncOperationCompletedHandler<bool>> callback(Callback<IAsyncOperationCompletedHandler<bool>>(
|
||||
sMetroApp.Get(), &MetroApp::OnAsyncTileCreated));
|
||||
ComPtr<IAsyncOperation<bool>> operation;
|
||||
AssertRetHRESULT(secondaryTile->RequestDeleteAsync(operation.GetAddressOf()), NS_ERROR_FAILURE);
|
||||
operation->put_Completed(callback.Get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a tile is pinned to the Windows 8 start screen.
|
||||
*
|
||||
* @param aTileID An ID which may have been pinned with pinTileAsync
|
||||
* @param aIsPinned Out parameter for determining if the tile is pinned or not
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::IsTilePinned(const nsAString &aTileID, bool *aIsPinned)
|
||||
{
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
NS_WARNING("IsTilePinned can't be called on the desktop.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ENSURE_ARG_POINTER(aIsPinned);
|
||||
|
||||
HRESULT hr;
|
||||
HString tileIdStr;
|
||||
tileIdStr.Set(aTileID.BeginReading());
|
||||
|
||||
ComPtr<ISecondaryTileStatics> tileStatics;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_StartScreen_SecondaryTile).Get(),
|
||||
tileStatics.GetAddressOf());
|
||||
AssertRetHRESULT(hr, NS_ERROR_FAILURE);
|
||||
boolean result = false;
|
||||
tileStatics->Exists(tileIdStr.Get(), &result);
|
||||
*aIsPinned = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the specified application with the specified arguments and
|
||||
* switches to Desktop mode if in metro mode.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::LaunchInDesktop(const nsAString &aPath, const nsAString &aArguments)
|
||||
{
|
||||
SHELLEXECUTEINFOW sinfo;
|
||||
memset(&sinfo, 0, sizeof(SHELLEXECUTEINFOW));
|
||||
sinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
|
||||
// Per the Metro style enabled desktop browser, for some reason,
|
||||
// SEE_MASK_FLAG_LOG_USAGE is needed to change from immersive mode
|
||||
// to desktop.
|
||||
sinfo.fMask = SEE_MASK_FLAG_LOG_USAGE;
|
||||
sinfo.hwnd = NULL;
|
||||
sinfo.lpFile = aPath.BeginReading();
|
||||
sinfo.lpParameters = aArguments.BeginReading();
|
||||
sinfo.lpVerb = L"open";
|
||||
sinfo.nShow = SW_SHOWNORMAL;
|
||||
|
||||
if (!ShellExecuteEx(&sinfo)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetSnappedState(int32_t *aSnappedState)
|
||||
{
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
NS_WARNING("GetSnappedState can't be called on the desktop.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ENSURE_ARG_POINTER(aSnappedState);
|
||||
ApplicationViewState viewState;
|
||||
AssertRetHRESULT(MetroUtils::GetViewState(viewState), NS_ERROR_UNEXPECTED);
|
||||
*aSnappedState = (int32_t) viewState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::Unsnap()
|
||||
{
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
NS_WARNING("Unsnap can't be called on the desktop.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
HRESULT hr = MetroUtils::TryUnsnap();
|
||||
return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::ShowSettingsFlyout()
|
||||
{
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
NS_WARNING("Settings flyout can't be shown on the desktop.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
HRESULT hr = MetroUtils::ShowSettingsFlyout();
|
||||
return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetImmersive(bool *aImersive)
|
||||
{
|
||||
*aImersive =
|
||||
XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetHandPreference(int32_t *aHandPreference)
|
||||
{
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
*aHandPreference = nsIWinMetroUtils::handPreferenceRight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<IUISettings> uiSettings;
|
||||
AssertRetHRESULT(ActivateGenericInstance(RuntimeClass_Windows_UI_ViewManagement_UISettings, uiSettings), NS_ERROR_UNEXPECTED);
|
||||
|
||||
HandPreference value;
|
||||
uiSettings->get_HandPreference(&value);
|
||||
if (value == HandPreference::HandPreference_LeftHanded)
|
||||
*aHandPreference = nsIWinMetroUtils::handPreferenceLeft;
|
||||
else
|
||||
*aHandPreference = nsIWinMetroUtils::handPreferenceRight;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetKeyboardVisible(bool *aImersive)
|
||||
{
|
||||
*aImersive = mozilla::widget::winrt::FrameworkView::IsKeyboardVisible();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetKeyboardX(uint32_t *aX)
|
||||
{
|
||||
*aX = (uint32_t)floor(mozilla::widget::winrt::FrameworkView::KeyboardVisibleRect().X);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetKeyboardY(uint32_t *aY)
|
||||
{
|
||||
*aY = (uint32_t)floor(mozilla::widget::winrt::FrameworkView::KeyboardVisibleRect().Y);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetKeyboardWidth(uint32_t *aWidth)
|
||||
{
|
||||
*aWidth = (uint32_t)ceil(mozilla::widget::winrt::FrameworkView::KeyboardVisibleRect().Width);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::GetKeyboardHeight(uint32_t *aHeight)
|
||||
{
|
||||
*aHeight = (uint32_t)ceil(mozilla::widget::winrt::FrameworkView::KeyboardVisibleRect().Height);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::AddSettingsPanelEntry(const nsAString& aLabel, uint32_t *aId)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aId);
|
||||
if (!sSettingsArray)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
*aId = sSettingsArray->Length();
|
||||
sSettingsArray->AppendElement(nsString(aLabel));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::SwapMouseButton(bool aValue, bool *aOriginalValue)
|
||||
{
|
||||
*aOriginalValue = ::SwapMouseButton(aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // widget
|
||||
} // mozilla
|
25
widget/windows/winrt/nsWinMetroUtils.h
Normal file
25
widget/windows/winrt/nsWinMetroUtils.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsIWinMetroUtils.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class nsWinMetroUtils : public nsIWinMetroUtils
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWINMETROUTILS
|
||||
|
||||
nsWinMetroUtils();
|
||||
virtual ~nsWinMetroUtils();
|
||||
};
|
||||
|
||||
} // widget
|
||||
} // mozilla
|
Loading…
Reference in New Issue
Block a user