Bug 750901 - Land widget/windows/winrt/* r=bbondy

This commit is contained in:
Jim Mathies 2013-02-12 14:51:25 -06:00
parent b3a0b467c6
commit 942f830344
28 changed files with 7856 additions and 0 deletions

View 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;
}
} } }

View 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;
};
} } }

View 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;
}
} } }

View 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)

View 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;
}

View 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;
};
} } }

View 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);
}

View 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();
};

View 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)
{
}
} } }

File diff suppressed because it is too large Load Diff

View 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;
};
} } }

View 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);

View 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;
}

View 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);
};

File diff suppressed because it is too large Load Diff

View 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;
};

View 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

View 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

View 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;
}
} } }

View 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);
};

View 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;
};
} } }

View 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);
} } }

View 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}

View 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>

View 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;
}

View 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__

View 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

View 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