Bug 750901 - Elm to mc migration work - metro related changes to Windows widget src to support building metro winrt bits (nsWidgetFactory, nsWindowGfx, nsToolkit, WinUtils). Also landing nsIWinMetroUtils.idl. r=bbondy
authorJim Mathies <jmathies@mozilla.com>
Fri, 02 Nov 2012 06:54:44 -0500
changeset 112153 6ac4bb259db3be313d5128a6a96b20d86faf5dd3
parent 112152 b032c4cc9d7dc684bb112424e9d07dd4be8dd046
child 112154 6ca11f4b470cf2c0cb331100eec7189548dc926d
push id23798
push userryanvm@gmail.com
push dateSat, 03 Nov 2012 00:06:35 +0000
treeherdermozilla-central@6134edeea902 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy
bugs750901
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 750901 - Elm to mc migration work - metro related changes to Windows widget src to support building metro winrt bits (nsWidgetFactory, nsWindowGfx, nsToolkit, WinUtils). Also landing nsIWinMetroUtils.idl. r=bbondy
widget/Makefile.in
widget/nsIWinMetroUtils.idl
widget/nsWidgetsCID.h
widget/windows/AudioSession.h
widget/windows/Makefile.in
widget/windows/WinTaskbar.cpp
widget/windows/WinUtils.cpp
widget/windows/WinUtils.h
widget/windows/nsAppShell.cpp
widget/windows/nsAppShell.h
widget/windows/nsClipboard.cpp
widget/windows/nsLookAndFeel.cpp
widget/windows/nsNativeThemeWin.h
widget/windows/nsToolkit.cpp
widget/windows/nsWidgetFactory.cpp
widget/windows/nsWindow.cpp
widget/windows/nsWindowGfx.cpp
widget/windows/nsWindowGfx.h
widget/xpwidgets/nsAppShellSingleton.h
--- a/widget/Makefile.in
+++ b/widget/Makefile.in
@@ -136,16 +136,20 @@ XPIDLSRCS	+= nsIPrintSettingsWin.idl \
 		nsITaskbarPreviewButton.idl \
 		nsITaskbarProgress.idl \
 		nsITaskbarOverlayIconController.idl \
 		nsIJumpListBuilder.idl \
 		nsIJumpListItem.idl \
 		$(NULL)
 endif
 
+ifdef MOZ_METRO
+XPIDLSRCS += nsIWinMetroUtils.idl
+endif
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 XPIDLSRCS +=	nsIMacDockSupport.idl \
 		nsIStandaloneNativeMenu.idl \
 		nsIMacWebAppUtils.idl \
 		$(NULL)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
new file mode 100644
--- /dev/null
+++ b/widget/nsIWinMetroUtils.idl
@@ -0,0 +1,122 @@
+/* -*- 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 "nsISupports.idl"
+
+/**
+ * Integration with the "Metro"/"Modern" UI environment in Windows 8.
+ *
+ * Note: browser/metro/base/content/browser-scripts.js contains a stub
+ * implementation of this interface for non-Windows systems, for testing and
+ * development purposes only.
+ */
+[scriptable, uuid(45656788-B111-4317-B054-FFE881A0737E)]
+interface nsIWinMetroUtils : nsISupports
+{
+  /* Fullscreen landscape orientation */
+  const long fullScreenLandscape = 0;
+  /* Larger snapped state */
+  const long filled = 1;
+  /* Smaller snapped state */
+  const long snapped = 2;
+  /* Fullscreen portrait orientation */
+  const long fullScreenPortrait = 3;
+
+  /* return constants for the handPreference property */
+  const long handPreferenceLeft = 0;
+  const long handPreferenceRight = 1;
+
+  /**
+   * Determines the current snapped state.
+   */
+  readonly attribute long snappedState;
+
+  /**
+   * Determine if the current browser is running in the metro immersive
+   * environment.
+   */
+  readonly attribute boolean immersive;
+
+  /**
+   * Determine if the user prefers left handed or right handed input.
+   */
+  readonly attribute long handPreference;
+
+  /**
+   * Attempts to unsnap the application from snapped state to filled state
+   */
+   void unsnap();
+
+  /**
+   * Launches the specified application with the specified arguments and
+   * switches to Desktop mode if in metro mode.
+   */
+   void launchInDesktop(in AString aPath, in AString aArguments); 
+
+  /**
+   * Secondary tiles are a Windows 8 specific feature for pinning new tiles
+   * to the start screen.   Tiles can later be activated whether the browser is
+   * already opened or not. 
+   */
+
+  /**
+   * 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
+   */
+  void pinTileAsync(in AString aTileID,
+                    in AString aShortName,
+                    in AString aDisplayName,
+                    in AString aActivationArgs,
+                    in AString aTileImage,
+                    in AString aSmallTileImage);
+
+  /**
+   * Unpins a tile from the Windows 8 start screen.
+   * 
+   * @param aTileID An existing ID which was previously pinned
+   */
+  void unpinTileAsync(in AString aTileID);
+
+  /**
+   * Determines if a tile is pinned to the Windows 8 start screen.
+   * 
+   * @param aTileID An ID which may have been pinned with pinTileAsync
+   * @return true if the tile is pinned
+   */
+  bool isTilePinned(in AString aTileID);
+
+  /**
+   * Soft keyboard attributes. Used in unison with shown/hidden observer
+   * events sent via FrameworkView.
+   *
+   * keyboardVisible - returns true if the soft keyboard is currently
+   * displayed, false otherwise.
+   * keyboardX, keyboardY, keyboardWidth, keyboardHeight - occlude rect
+   * of the keyboard when displayed in device independent pixels.
+   */
+  readonly attribute boolean keyboardVisible;
+  readonly attribute unsigned long keyboardX;
+  readonly attribute unsigned long keyboardY;
+  readonly attribute unsigned long keyboardWidth;
+  readonly attribute unsigned long keyboardHeight;
+
+  /**
+   * Settings panel links. addSettingsPanelEntry adds an entry to
+   * the settings flyout panel that the user can invoke.
+   *
+   * @param aChromePanelId panel id invoked via nsIBrowserDOMWindow's
+   * ShowPanel api. Example: 'prefs-container'
+   * @param aLabel Localized string label displayed in the settings
+   * flyout panel for this option.
+   */
+  void addSettingsPanelEntry(in AString aChromePanelId, in AString aLabel);
+};
--- a/widget/nsWidgetsCID.h
+++ b/widget/nsWidgetsCID.h
@@ -108,16 +108,20 @@
 
 #define NS_WIN_TASKBAR_CID \
 { 0xb8e5bc54, 0xa22f, 0x4eb2, {0xb0, 0x61, 0x24, 0xcb, 0x6d, 0x19, 0xc1, 0x5f } }
 
 // {73A5946F-608D-454f-9D33-0B8F8C7294B6}
 #define NS_WIN_JUMPLISTBUILDER_CID \
 { 0x73a5946f, 0x608d, 0x454f, { 0x9d, 0x33, 0xb, 0x8f, 0x8c, 0x72, 0x94, 0xb6 } }
 
+// {DE95B8C9-F0E8-4AD5-95A2-06C12F53EC2E}
+#define NS_WIN_METROUTILS_CID \
+{ 0xde95b8c9, 0xf0e8, 0x4ad5, { 0x95, 0xa2, 0x06, 0xc1, 0x2f, 0x53, 0xec, 0x2e }}
+
 // {2B9A1F2C-27CE-45b6-8D4E-755D0E34F8DB}
 #define NS_WIN_JUMPLISTITEM_CID \
 { 0x2b9a1f2c, 0x27ce, 0x45b6, { 0x8d, 0x4e, 0x75, 0x5d, 0x0e, 0x34, 0xf8, 0xdb } }
 
 // {21F1F13B-F75A-42ad-867A-D91AD694447E}
 #define NS_WIN_JUMPLISTSEPARATOR_CID \
 { 0x21f1f13b, 0xf75a, 0x42ad, { 0x86, 0x7a, 0xd9, 0x1a, 0xd6, 0x94, 0x44, 0x7e } }
 
--- a/widget/windows/AudioSession.h
+++ b/widget/windows/AudioSession.h
@@ -1,14 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; 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 "nsAutoPtr.h"
+#include "nsString.h"
+
 namespace mozilla {
 namespace widget {
 
 // Start the audio session in the current process
 nsresult StartAudioSession();
 
 // Pass the information necessary to start an audio session in another process
 nsresult GetAudioSessionData(nsID& aID,
--- a/widget/windows/Makefile.in
+++ b/widget/windows/Makefile.in
@@ -13,16 +13,20 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= widget
 LIBRARY_NAME	= widget_windows
 EXPORT_LIBRARY	= 1
 IS_COMPONENT	= 1
 RESFILE		= widget.res
 MODULE_NAME	= nsWidgetWinModule
 LIBXUL_LIBRARY = 1
 
+ifdef MOZ_METRO
+DIRS = winrt
+endif
+
 CPPSRCS = \
   nsWindow.cpp \
   nsWindowGfx.cpp \
   nsWindowDbg.cpp \
   nsAppShell.cpp \
   nsToolkit.cpp \
   nsFilePicker.cpp \
   nsScreenWin.cpp  \
--- a/widget/windows/WinTaskbar.cpp
+++ b/widget/windows/WinTaskbar.cpp
@@ -235,16 +235,21 @@ WinTaskbar::~WinTaskbar() {
     NS_RELEASE(mTaskbar);
     ::CoUninitialize();
   }
 }
 
 // static
 bool
 WinTaskbar::GetAppUserModelID(nsAString & aDefaultGroupId) {
+  // For win8 metro builds, we can't set this. The value is static
+  // for the app.
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
+    return false;
+  }
   // If marked as such in prefs, use a hash of the profile path for the id
   // instead of the install path hash setup by the installer.
   bool useProfile =
     Preferences::GetBool("taskbar.grouping.useprofile", false);
   if (useProfile) {
     nsCOMPtr<nsIFile> profileDir;
     NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
                            getter_AddRefs(profileDir));
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -895,10 +895,49 @@ WinUtils::GetShellItemPath(IShellItem* a
   LPWSTR str = NULL;
   if (FAILED(aItem->GetDisplayName(SIGDN_FILESYSPATH, &str)))
     return false;
   aResultString.Assign(str);
   CoTaskMemFree(str);
   return !aResultString.IsEmpty();
 }
 
+/* static */
+nsIntRegion
+WinUtils::ConvertHRGNToRegion(HRGN aRgn)
+{
+  NS_ASSERTION(aRgn, "Don't pass NULL region here");
+
+  nsIntRegion rgn;
+
+  DWORD size = ::GetRegionData(aRgn, 0, NULL);
+  nsAutoTArray<PRUint8,100> buffer;
+  if (!buffer.SetLength(size))
+    return rgn;
+
+  RGNDATA* data = reinterpret_cast<RGNDATA*>(buffer.Elements());
+  if (!::GetRegionData(aRgn, size, data))
+    return rgn;
+
+  if (data->rdh.nCount > MAX_RECTS_IN_REGION) {
+    rgn = ToIntRect(data->rdh.rcBound);
+    return rgn;
+  }
+
+  RECT* rects = reinterpret_cast<RECT*>(data->Buffer);
+  for (PRUint32 i = 0; i < data->rdh.nCount; ++i) {
+    RECT* r = rects + i;
+    rgn.Or(rgn, ToIntRect(*r));
+  }
+
+  return rgn;
+}
+
+nsIntRect
+WinUtils::ToIntRect(const RECT& aRect)
+{
+  return nsIntRect(aRect.left, aRect.top,
+                   aRect.right - aRect.left,
+                   aRect.bottom - aRect.top);
+}
+
 } // namespace widget
 } // namespace mozilla
--- a/widget/windows/WinUtils.h
+++ b/widget/windows/WinUtils.h
@@ -6,16 +6,18 @@
 #ifndef mozilla_widget_WinUtils_h__
 #define mozilla_widget_WinUtils_h__
 
 #include "nscore.h"
 #include <windows.h>
 #include <shobjidl.h>
 #include "nsAutoPtr.h"
 #include "nsString.h"
+#include "nsRegion.h"
+#include "nsRect.h"
 
 #include "nsThreadUtils.h"
 #include "nsICryptoHash.h"
 #include "nsIFaviconService.h" 
 #include "nsIDownloader.h"
 
 #include "mozilla/Attributes.h"
 
@@ -197,16 +199,32 @@ public:
    *
    * aItem  the shell item containing the path.
    * aResultString  the resulting string path.
    * returns  true if a path was retreived.
    */
   static bool GetShellItemPath(IShellItem* aItem,
                                nsString& aResultString);
 
+  /**
+   * ConvertHRGNToRegion converts a Windows HRGN to an nsIntRegion.
+   *
+   * aRgn the HRGN to convert.
+   * returns the nsIntRegion.
+   */
+  static nsIntRegion ConvertHRGNToRegion(HRGN aRgn);
+
+  /**
+   * ToIntRect converts a Windows RECT to a nsIntRect.
+   *
+   * aRect the RECT to convert.
+   * returns the nsIntRect.
+   */
+  static nsIntRect ToIntRect(const RECT& aRect);
+
 private:
   typedef HRESULT (WINAPI * SHCreateItemFromParsingNamePtr)(PCWSTR pszPath,
                                                             IBindCtx *pbc,
                                                             REFIID riid,
                                                             void **ppv);
   static SHCreateItemFromParsingNamePtr sCreateItemFromParsingName;
 
   /**
--- a/widget/windows/nsAppShell.cpp
+++ b/widget/windows/nsAppShell.cpp
@@ -17,22 +17,19 @@
 
 // For skidmark code
 #include <windows.h> 
 #include <tlhelp32.h> 
 
 const PRUnichar* kAppShellEventId = L"nsAppShell:EventID";
 const PRUnichar* kTaskbarButtonEventId = L"TaskbarButtonCreated";
 
-// The maximum time we allow before forcing a native event callback
-#define NATIVE_EVENT_STARVATION_LIMIT mozilla::TimeDuration::FromSeconds(1)
-
 static UINT sMsgId;
 
-static UINT sTaskbarButtonCreatedMsg;
+UINT sTaskbarButtonCreatedMsg;
 
 /* static */
 UINT nsAppShell::GetTaskbarButtonCreatedMessage() {
 	return sTaskbarButtonCreatedMsg;
 }
 
 namespace mozilla {
 namespace crashreporter {
@@ -236,16 +233,22 @@ nsAppShell::Run(void)
   // Don't forget to null this out!
   sLoadedModules = nullptr;
 
   return rv;
 }
 
 #endif
 
+NS_IMETHODIMP
+nsAppShell::Exit(void)
+{
+  return nsBaseAppShell::Exit();
+}
+
 void
 nsAppShell::DoProcessMoreGeckoEvents()
 {
   // Called by nsBaseAppShell's NativeEventCallback() after it has finished
   // processing pending gecko events and there are still gecko events pending
   // for the thread. (This can happen if NS_ProcessPendingEvents reached it's
   // starvation timeout limit.) The default behavior in nsBaseAppShell is to
   // call ScheduleNativeEventCallback to post a follow up native event callback
--- a/widget/windows/nsAppShell.h
+++ b/widget/windows/nsAppShell.h
@@ -5,16 +5,19 @@
 
 #ifndef nsAppShell_h__
 #define nsAppShell_h__
 
 #include "nsBaseAppShell.h"
 #include <windows.h>
 #include "mozilla/TimeStamp.h"
 
+// The maximum time we allow before forcing a native event callback
+#define NATIVE_EVENT_STARVATION_LIMIT mozilla::TimeDuration::FromSeconds(1)
+
 /**
  * Native Win32 Application shell wrapper
  */
 class nsAppShell : public nsBaseAppShell
 {
 public:
   nsAppShell() :
     mEventWnd(NULL),
@@ -26,16 +29,17 @@ public:
   void DoProcessMoreGeckoEvents();
 
   static UINT GetTaskbarButtonCreatedMessage();
 
 protected:
 #if defined(_MSC_VER) && defined(_M_IX86)
   NS_IMETHOD Run();
 #endif
+  NS_IMETHOD Exit();
   virtual void ScheduleNativeEventCallback();
   virtual bool ProcessNextNativeEvent(bool mayWait);
   virtual ~nsAppShell();
 
   static LRESULT CALLBACK EventWindowProc(HWND, UINT, WPARAM, LPARAM);
 
 protected:
   HWND mEventWnd;
--- a/widget/windows/nsClipboard.cpp
+++ b/widget/windows/nsClipboard.cpp
@@ -267,18 +267,20 @@ nsresult nsClipboard::GetGlobalData(HGLO
       data[allocSize] = data[allocSize + 1] = '\0';     // null terminate for safety
 
       GlobalUnlock(aHGBL);
       *aData = data;
       *aLen = allocSize;
 
       result = NS_OK;
     }
-  } 
-  else {
+  } else {
+#ifdef MOZ_METRO
+    return result;
+#endif
     // We really shouldn't ever get here
     // but just in case
     *aData = nullptr;
     *aLen  = 0;
     LPVOID lpMsgBuf;
 
     FormatMessageW( 
         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
@@ -296,22 +298,22 @@ nsresult nsClipboard::GetGlobalData(HGLO
     // Free the buffer.
     LocalFree( lpMsgBuf );    
   }
 
   return result;
 }
 
 //-------------------------------------------------------------------------
-nsresult nsClipboard::GetNativeDataOffClipboard(nsIWidget * aWindow, UINT /*aIndex*/, UINT aFormat, void ** aData, uint32_t * aLen)
+nsresult nsClipboard::GetNativeDataOffClipboard(nsIWidget * aWidget, UINT /*aIndex*/, UINT aFormat, void ** aData, uint32_t * aLen)
 {
   HGLOBAL   hglb; 
   nsresult  result = NS_ERROR_FAILURE;
 
-  HWND nativeWin = nullptr;//(HWND)aWindow->GetNativeData(NS_NATIVE_WINDOW);
+  HWND nativeWin = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
   if (::OpenClipboard(nativeWin)) { 
     hglb = ::GetClipboardData(aFormat); 
     result = GetGlobalData(hglb, aData, aLen);
     ::CloseClipboard();
   }
   return result;
 }
 
--- a/widget/windows/nsLookAndFeel.cpp
+++ b/widget/windows/nsLookAndFeel.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; 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 "nsLookAndFeel.h"
 #include <windows.h>
 #include <shellapi.h>
-#include "nsWindow.h"
 #include "nsStyleConsts.h"
 #include "nsUXThemeData.h"
 #include "nsUXThemeConstants.h"
 #include "gfxFont.h"
 #include "WinUtils.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla::widget;
--- a/widget/windows/nsNativeThemeWin.h
+++ b/widget/windows/nsNativeThemeWin.h
@@ -99,11 +99,8 @@ protected:
                        HBRUSH defaultBack);
 
   uint32_t GetWidgetNativeDrawingFlags(uint8_t aWidgetType);
 
   int32_t StandardGetState(nsIFrame* aFrame, uint8_t aWidgetType, bool wantFocused);
 
   bool IsMenuActive(nsIFrame* aFrame, uint8_t aWidgetType);
 };
-
-// Creator function
-extern NS_METHOD NS_NewNativeThemeWin(nsISupports *aOuter, REFNSIID aIID, void **aResult);
--- a/widget/windows/nsToolkit.cpp
+++ b/widget/windows/nsToolkit.cpp
@@ -22,17 +22,19 @@
 
 nsToolkit* nsToolkit::gToolkit = nullptr;
 HINSTANCE nsToolkit::mDllInstance = 0;
 static const unsigned long kD3DUsageDelay = 5000;
 
 static void
 StartAllowingD3D9(nsITimer *aTimer, void *aClosure)
 {
-  nsWindow::StartAllowingD3D9(true);
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
+    nsWindow::StartAllowingD3D9(true);
+  }
 }
 
 MouseTrailer*       nsToolkit::gMouseTrailer;
 
 //-------------------------------------------------------------------------
 //
 // constructor
 //
@@ -42,21 +44,23 @@ nsToolkit::nsToolkit()
     MOZ_COUNT_CTOR(nsToolkit);
 
 #if defined(MOZ_STATIC_COMPONENT_LIBS)
     nsToolkit::Startup(GetModuleHandle(NULL));
 #endif
 
     gMouseTrailer = &mMouseTrailer;
 
-    mD3D9Timer = do_CreateInstance("@mozilla.org/timer;1");
-    mD3D9Timer->InitWithFuncCallback(::StartAllowingD3D9,
-                                     NULL,
-                                     kD3DUsageDelay,
-                                     nsITimer::TYPE_ONE_SHOT);
+    if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
+      mD3D9Timer = do_CreateInstance("@mozilla.org/timer;1");
+      mD3D9Timer->InitWithFuncCallback(::StartAllowingD3D9,
+                                       NULL,
+                                       kD3DUsageDelay,
+                                       nsITimer::TYPE_ONE_SHOT);
+    }
 }
 
 
 //-------------------------------------------------------------------------
 //
 // destructor
 //
 //-------------------------------------------------------------------------
@@ -78,18 +82,20 @@ nsToolkit::Shutdown()
 {
     delete gToolkit;
     gToolkit = nullptr;
 }
 
 void
 nsToolkit::StartAllowingD3D9()
 {
-  nsToolkit::GetToolkit()->mD3D9Timer->Cancel();
-  nsWindow::StartAllowingD3D9(false);
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
+    nsToolkit::GetToolkit()->mD3D9Timer->Cancel();
+    nsWindow::StartAllowingD3D9(false);
+  }
 }
 
 //-------------------------------------------------------------------------
 //
 // Return the nsToolkit for the current thread.  If a toolkit does not
 // yet exist, then one will be created...
 //
 //-------------------------------------------------------------------------
--- a/widget/windows/nsWidgetFactory.cpp
+++ b/widget/windows/nsWidgetFactory.cpp
@@ -3,124 +3,200 @@
  * 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 "nsIFactory.h"
 #include "nsISupports.h"
 #include "nsdefs.h"
 #include "nsWidgetsCID.h"
-
 #include "nsAppShell.h"
 #include "nsAppShellSingleton.h"
-#include "nsFilePicker.h"
 #include "mozilla/ModuleUtils.h"
 #include "nsIServiceManager.h"
 #include "nsIdleServiceWin.h"
 #include "nsLookAndFeel.h"
-#include "nsNativeThemeWin.h"
 #include "nsScreenManagerWin.h"
 #include "nsSound.h"
-#include "nsWindow.h"
 #include "WinMouseScrollHandler.h"
-#include "WinTaskbar.h"
-#include "JumpListBuilder.h"
-#include "JumpListItem.h"
 #include "GfxInfo.h"
 #include "nsToolkit.h"
 
-// Drag & Drop, Clipboard
+// Modules that switch out based on the environment
+#include "nsXULAppAPI.h"
+// Desktop
+#include "nsFilePicker.h" // needs to be included before other shobjidl.h includes
+#include "nsNativeThemeWin.h"
+#include "nsWindow.h"
+// Content processes
+#include "nsFilePickerProxy.h"
+// Metro
+#ifdef MOZ_METRO
+#include "winrt/MetroAppShell.h"
+#include "winrt/MetroWidget.h"
+#include "winrt/nsMetroFilePicker.h"
+#include "winrt/nsWinMetroUtils.h"
+#endif
 
+// Drag & Drop, Clipboard
 #include "nsClipboardHelper.h"
-
 #include "nsClipboard.h"
 #include "nsBidiKeyboard.h"
 #include "nsDragService.h"
 #include "nsTransferable.h"
 #include "nsHTMLFormatConverter.h"
 
+#include "WinTaskbar.h"
+#include "JumpListBuilder.h"
+#include "JumpListItem.h"
+
 #ifdef NS_PRINTING
 #include "nsDeviceContextSpecWin.h"
 #include "nsPrintOptionsWin.h"
 #include "nsPrintSession.h"
 #endif
 
 using namespace mozilla::widget;
 
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
-NS_GENERIC_FACTORY_CONSTRUCTOR(ChildWindow)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
+static nsresult
+WindowConstructor(nsISupports *aOuter, REFNSIID aIID,
+                  void **aResult)
+{
+  *aResult = nullptr;
+  if (aOuter != nullptr) {
+    return NS_ERROR_NO_AGGREGATION;
+  }
+  nsCOMPtr<nsIWidget> widget;
+
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
+#ifdef MOZ_METRO
+    widget = new MetroWidget;
+#else
+    NS_RUNTIMEABORT("build does not support metro.");
+#endif
+  } else {
+    widget = new nsWindow;
+  }
+
+  return widget->QueryInterface(aIID, aResult);
+}
+
+static nsresult
+ChildWindowConstructor(nsISupports *aOuter, REFNSIID aIID,
+                       void **aResult)
+{
+  *aResult = nullptr;
+  if (aOuter != nullptr) {
+    return NS_ERROR_NO_AGGREGATION;
+  }
+  nsCOMPtr<nsIWidget> widget;
+
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
+    return NS_NOINTERFACE;
+  } else {
+    widget = new ChildWindow;
+  }
+
+  return widget->QueryInterface(aIID, aResult);
+}
+
+static nsresult
+FilePickerConstructor(nsISupports *aOuter, REFNSIID aIID,
+                      void **aResult)
+{
+  *aResult = nullptr;
+  if (aOuter != nullptr) {
+    return NS_ERROR_NO_AGGREGATION;
+  }
+  nsCOMPtr<nsIFilePicker> picker;
+
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    picker = new nsFilePickerProxy();
+  } else {
+    if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
+#ifdef MOZ_METRO
+      picker = new nsMetroFilePicker;
+#else
+      NS_RUNTIMEABORT("build does not support metro.");
+#endif
+    } else {
+      picker = new nsFilePicker;
+    }
+  }
+  return picker->QueryInterface(aIID, aResult);
+}
+
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerWin)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceWin, nsIdleServiceWin::GetInstance)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
-
 NS_GENERIC_FACTORY_CONSTRUCTOR(WinTaskbar)
 NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListBuilder)
 NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListItem)
 NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListSeparator)
 NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListLink)
 NS_GENERIC_FACTORY_CONSTRUCTOR(JumpListShortcut)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
+#ifdef MOZ_METRO
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsWinMetroUtils)
+#endif
+#ifdef NS_PRINTING
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsWin, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsPrinterEnumeratorWin)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecWin)
+#endif
 
 namespace mozilla {
 namespace widget {
 // This constructor should really be shared with all platforms.
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init);
 }
 }
 
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
-
-#ifdef NS_PRINTING
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsWin, Init)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsPrinterEnumeratorWin)
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecWin)
-#endif
-
 NS_DEFINE_NAMED_CID(NS_WINDOW_CID);
 NS_DEFINE_NAMED_CID(NS_CHILD_CID);
 NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
 NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
 NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
 NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID);
 NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
 NS_DEFINE_NAMED_CID(NS_SOUND_CID);
 NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
-
 NS_DEFINE_NAMED_CID(NS_WIN_TASKBAR_CID);
 NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTBUILDER_CID);
 NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTITEM_CID);
 NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTSEPARATOR_CID);
 NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTLINK_CID);
 NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTSHORTCUT_CID);
-
+#ifdef MOZ_METRO
+NS_DEFINE_NAMED_CID(NS_WIN_METROUTILS_CID);
+#endif
 NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_BIDIKEYBOARD_CID);
-
 #ifdef NS_PRINTING
 NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_PRINTER_ENUMERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID);
 NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID);
 #endif
 
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
-  { &kNS_WINDOW_CID, false, NULL, nsWindowConstructor },
+  { &kNS_WINDOW_CID, false, NULL, WindowConstructor },
   { &kNS_CHILD_CID, false, NULL, ChildWindowConstructor },
-  { &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor },
+  { &kNS_FILEPICKER_CID, false, NULL, FilePickerConstructor },
   { &kNS_APPSHELL_CID, false, NULL, nsAppShellConstructor },
   { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerWinConstructor },
   { &kNS_GFXINFO_CID, false, NULL, GfxInfoConstructor },
   { &kNS_THEMERENDERER_CID, false, NULL, NS_NewNativeTheme },
   { &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceWinConstructor },
   { &kNS_CLIPBOARD_CID, false, NULL, nsClipboardConstructor },
   { &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor },
   { &kNS_SOUND_CID, false, NULL, nsSoundConstructor },
@@ -129,16 +205,19 @@ static const mozilla::Module::CIDEntry k
   { &kNS_WIN_TASKBAR_CID, false, NULL, WinTaskbarConstructor },
   { &kNS_WIN_JUMPLISTBUILDER_CID, false, NULL, JumpListBuilderConstructor },
   { &kNS_WIN_JUMPLISTITEM_CID, false, NULL, JumpListItemConstructor },
   { &kNS_WIN_JUMPLISTSEPARATOR_CID, false, NULL, JumpListSeparatorConstructor },
   { &kNS_WIN_JUMPLISTLINK_CID, false, NULL, JumpListLinkConstructor },
   { &kNS_WIN_JUMPLISTSHORTCUT_CID, false, NULL, JumpListShortcutConstructor },
   { &kNS_DRAGSERVICE_CID, false, NULL, nsDragServiceConstructor },
   { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor },
+#ifdef MOZ_METRO
+  { &kNS_WIN_METROUTILS_CID, false, NULL, nsWinMetroUtilsConstructor },
+#endif
 #ifdef NS_PRINTING
   { &kNS_PRINTSETTINGSSERVICE_CID, false, NULL, nsPrintOptionsWinConstructor },
   { &kNS_PRINTER_ENUMERATOR_CID, false, NULL, nsPrinterEnumeratorWinConstructor },
   { &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor },
   { &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecWinConstructor },
 #endif
   { NULL }
 };
@@ -160,16 +239,19 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/windows-taskbar;1", &kNS_WIN_TASKBAR_CID },
   { "@mozilla.org/windows-jumplistbuilder;1", &kNS_WIN_JUMPLISTBUILDER_CID },
   { "@mozilla.org/windows-jumplistitem;1", &kNS_WIN_JUMPLISTITEM_CID },
   { "@mozilla.org/windows-jumplistseparator;1", &kNS_WIN_JUMPLISTSEPARATOR_CID },
   { "@mozilla.org/windows-jumplistlink;1", &kNS_WIN_JUMPLISTLINK_CID },
   { "@mozilla.org/windows-jumplistshortcut;1", &kNS_WIN_JUMPLISTSHORTCUT_CID },
   { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID },
   { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID },
+#ifdef MOZ_METRO
+  { "@mozilla.org/windows-metroutils;1", &kNS_WIN_METROUTILS_CID },
+#endif
 #ifdef NS_PRINTING
   { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
   { "@mozilla.org/gfx/printerenumerator;1", &kNS_PRINTER_ENUMERATOR_CID },
   { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
   { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
 #endif
   { NULL }
 };
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -1948,17 +1948,17 @@ nsWindow::ResetLayout()
 
   // If hidden, just send the frame changed event for now.
   if (!mIsVisible)
     return;
 
   // Send a gecko size event to trigger reflow.
   RECT clientRc = {0};
   GetClientRect(mWnd, &clientRc);
-  nsIntRect evRect(nsWindowGfx::ToIntRect(clientRc));
+  nsIntRect evRect(WinUtils::ToIntRect(clientRc));
   OnResize(evRect);
 
   // Invalidate and update
   Invalidate();
 }
 
 // Internally track the caption status via a window property. Required
 // due to our internal handling of WM_NCACTIVATE when custom client
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -100,46 +100,16 @@ static IconMetrics sIconMetrics[] = {
  **************************************************************/
 
 static bool
 IsRenderMode(gfxWindowsPlatform::RenderMode rmode)
 {
   return gfxWindowsPlatform::GetPlatform()->GetRenderMode() == rmode;
 }
 
-nsIntRegion
-nsWindowGfx::ConvertHRGNToRegion(HRGN aRgn)
-{
-  NS_ASSERTION(aRgn, "Don't pass NULL region here");
-
-  nsIntRegion rgn;
-
-  DWORD size = ::GetRegionData(aRgn, 0, NULL);
-  nsAutoTArray<uint8_t,100> buffer;
-  if (!buffer.SetLength(size))
-    return rgn;
-
-  RGNDATA* data = reinterpret_cast<RGNDATA*>(buffer.Elements());
-  if (!::GetRegionData(aRgn, size, data))
-    return rgn;
-
-  if (data->rdh.nCount > MAX_RECTS_IN_REGION) {
-    rgn = ToIntRect(data->rdh.rcBound);
-    return rgn;
-  }
-
-  RECT* rects = reinterpret_cast<RECT*>(data->Buffer);
-  for (uint32_t i = 0; i < data->rdh.nCount; ++i) {
-    RECT* r = rects + i;
-    rgn.Or(rgn, ToIntRect(*r));
-  }
-
-  return rgn;
-}
-
 /**************************************************************
  **************************************************************
  **
  ** BLOCK: nsWindow impl.
  **
  ** Paint related nsWindow methods.
  **
  **************************************************************
@@ -147,32 +117,32 @@ nsWindowGfx::ConvertHRGNToRegion(HRGN aR
 
 // GetRegionToPaint returns the invalidated region that needs to be painted
 nsIntRegion nsWindow::GetRegionToPaint(bool aForceFullRepaint,
                                        PAINTSTRUCT ps, HDC aDC)
 {
   if (aForceFullRepaint) {
     RECT paintRect;
     ::GetClientRect(mWnd, &paintRect);
-    return nsIntRegion(nsWindowGfx::ToIntRect(paintRect));
+    return nsIntRegion(WinUtils::ToIntRect(paintRect));
   }
 
   HRGN paintRgn = ::CreateRectRgn(0, 0, 0, 0);
   if (paintRgn != NULL) {
     int result = GetRandomRgn(aDC, paintRgn, SYSRGN);
     if (result == 1) {
       POINT pt = {0,0};
       ::MapWindowPoints(NULL, mWnd, &pt, 1);
       ::OffsetRgn(paintRgn, pt.x, pt.y);
     }
-    nsIntRegion rgn(nsWindowGfx::ConvertHRGNToRegion(paintRgn));
+    nsIntRegion rgn(WinUtils::ConvertHRGNToRegion(paintRgn));
     ::DeleteObject(paintRgn);
     return rgn;
   }
-  return nsIntRegion(nsWindowGfx::ToIntRect(ps.rcPaint));
+  return nsIntRegion(WinUtils::ToIntRect(ps.rcPaint));
 }
 
 #define WORDSSIZE(x) ((x).width * (x).height)
 static bool
 EnsureSharedSurfaceSize(gfxIntSize size)
 {
   gfxIntSize screenSize;
   screenSize.height = GetSystemMetrics(SM_CYSCREEN);
--- a/widget/windows/nsWindowGfx.h
+++ b/widget/windows/nsWindowGfx.h
@@ -15,24 +15,16 @@
 
 // This isn't ideal, we should figure out how to export
 // the #defines here; need this to figure out if we have
 // the DirectDraw surface or not.
 #include "cairo-features.h"
 
 class nsWindowGfx {
 public:
-  static nsIntRect ToIntRect(const RECT& aRect)
-  {
-    return nsIntRect(aRect.left, aRect.top,
-                     aRect.right - aRect.left, aRect.bottom - aRect.top);
-  }
-
-  static nsIntRegion ConvertHRGNToRegion(HRGN aRgn);
-
   enum IconSizeType {
     kSmallIcon,
     kRegularIcon
   };
   static gfxIntSize GetIconMetrics(IconSizeType aSizeType);
   static nsresult CreateIcon(imgIContainer *aContainer, bool aIsCursor, uint32_t aHotspotX, uint32_t aHotspotY, gfxIntSize aScaledSize, HICON *aIcon);
 
 private:
--- a/widget/xpwidgets/nsAppShellSingleton.h
+++ b/widget/xpwidgets/nsAppShellSingleton.h
@@ -22,29 +22,51 @@
  * The nsAppShellShutdown function is designed to be used as a module
  * destructor.  If you already have a module destructor, then call
  * nsAppShellShutdown from your module destructor.
  *
  * The nsAppShellConstructor function is designed to be used as a factory
  * method for the nsAppShell class.
  */
 
-static nsAppShell *sAppShell;
+#include "nsXULAppAPI.h"
+#if defined(MOZ_METRO) && defined(XP_WIN)
+#include "winrt/MetroAppShell.h"
+#endif
+
+static nsIAppShell *sAppShell;
 
 static nsresult
 nsAppShellInit()
 {
   NS_ASSERTION(!sAppShell, "already initialized");
 
+#if !defined(MOZ_METRO) || !defined(XP_WIN)
   sAppShell = new nsAppShell();
+#else
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
+    sAppShell = new MetroAppShell();
+  } else {
+    sAppShell = new nsAppShell();
+  }
+#endif
   if (!sAppShell)
     return NS_ERROR_OUT_OF_MEMORY;
   NS_ADDREF(sAppShell);
 
-  nsresult rv = sAppShell->Init();
+  nsresult rv;
+#if !defined(MOZ_METRO) || !defined(XP_WIN)
+  rv = static_cast<nsAppShell*>(sAppShell)->Init();
+#else
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
+    rv = static_cast<MetroAppShell*>(sAppShell)->Init();
+  } else {
+    rv = static_cast<nsAppShell*>(sAppShell)->Init();
+  }
+#endif
   if (NS_FAILED(rv)) {
     NS_RELEASE(sAppShell);
     return rv;
   }
 
   return NS_OK;
 }