Bug 1170522 - expose whether or not we're in tablet mode to xul/js/css, r=jimm,ted
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Tue, 16 Jun 2015 19:51:29 +0100
changeset 250983 43873ca11c57bfbdb7b18d7d341df0da68612a36
parent 250982 9976683b3e5a4492419fd7b2673acf74a8a6ec8d
child 250984 14d26a6ef7a4bf09439399cea30dbc43c303c964
push id28979
push usercbook@mozilla.com
push dateThu, 02 Jul 2015 13:35:11 +0000
treeherdermozilla-central@cb321bafe1e2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, ted
bugs1170522
milestone42.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 1170522 - expose whether or not we're in tablet mode to xul/js/css, r=jimm,ted
build/win32/mozconfig.vs2013-win64
build/win64/mozconfig.vs2013
toolkit/library/moz.build
widget/moz.build
widget/nsIWindowsUIUtils.idl
widget/nsWidgetsCID.h
widget/windows/WindowsUIUtils.cpp
widget/windows/WindowsUIUtils.h
widget/windows/moz.build
widget/windows/mozwrlbase.h
widget/windows/nsWidgetFactory.cpp
widget/windows/nsWindow.cpp
--- a/build/win32/mozconfig.vs2013-win64
+++ b/build/win32/mozconfig.vs2013-win64
@@ -1,13 +1,13 @@
 _VSPATH="/c/tools/vs2013"
 export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x86/Microsoft.VC120.CRT
 
 ## includes: win8.1 sdk includes, msvc std library, directx sdk for d3d9 ##
-export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
+export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
 
 ## libs: win8.1 sdk x86 (32-bit) libs, msvc (32-bit) std library, msvc atl libs, directx sdk (32-bit) for d3d9  ##
 export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
 export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
 
 ## paths: win8.1 sdk x86 (32-bit) tools, msvc (64-bit compiling 32-bit) build toolchain, moz tools  ##
 export PATH="/c/Program Files (x86)/Windows Kits/8.1/bin/x86:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64_x86:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:/c/mozilla-build/moztools:${PATH}"
 
--- a/build/win64/mozconfig.vs2013
+++ b/build/win64/mozconfig.vs2013
@@ -1,13 +1,13 @@
 _VSPATH="/c/tools/vs2013"
 export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x64/Microsoft.VC120.CRT
 
 ## includes: win8.1 sdk includes, msvc std library, directx sdk for d3d9 ##
-export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
+export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
 
 ## libs: win8.1 sdk x64 (64-bit) libs, msvc (64-bit) std library, msvc atl libs, directx sdk (64-bit) for d3d9  ##
 export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
 export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64
 
 ## paths: win8.1 sdk x64 (64-bit) tools, msvc (64-bit) build toolchain, moz tools  ##
 export PATH="/c/Program Files (x86)/Windows Kits/8.1/bin/x64:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/VC/BIN/x86_amd64:${_VSPATH}/VC/BIN:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:${PATH}"
 
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -27,16 +27,22 @@ def Libxul(name):
     ]
 
     if CONFIG['ACCESSIBILITY']:
         DELAYLOAD_DLLS += ['oleacc.dll']
 
     if CONFIG['MOZ_WEBRTC']:
         DELAYLOAD_DLLS += ['msdmo.dll']
 
+    if CONFIG['OS_ARCH'] == 'WINNT':
+        DELAYLOAD_DLLS += [
+            'api-ms-win-core-winrt-l1-1-0.dll',
+            'api-ms-win-core-winrt-string-l1-1-0.dll',
+        ]
+
     if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
         LOCAL_INCLUDES += [
             '/widget/windows',
             '/xpcom/base',
         ]
         # config/version.mk says $(srcdir)/$(RCINCLUDE), and this needs to
         # be valid in both toolkit/library and toolkit/library/gtest.
         # Eventually, the make backend would do its own path canonicalization
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -21,16 +21,17 @@ if toolkit == 'windows':
         'nsIPrintSettingsWin.idl',
         'nsITaskbarOverlayIconController.idl',
         'nsITaskbarPreview.idl',
         'nsITaskbarPreviewButton.idl',
         'nsITaskbarPreviewController.idl',
         'nsITaskbarProgress.idl',
         'nsITaskbarTabPreview.idl',
         'nsITaskbarWindowPreview.idl',
+        'nsIWindowsUIUtils.idl',
         'nsIWinTaskbar.idl',
     ]
 elif toolkit == 'cocoa':
     XPIDL_SOURCES += [
         'nsIGfxInfo2.idl',
         'nsIMacDockSupport.idl',
         'nsIMacWebAppUtils.idl',
         'nsIStandaloneNativeMenu.idl',
new file mode 100644
--- /dev/null
+++ b/widget/nsIWindowsUIUtils.idl
@@ -0,0 +1,24 @@
+/* -*- 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 "nsISupports.idl"
+
+
+[scriptable, uuid(aa8a0ecf-96a1-418c-b80e-f24ae18bbedc)]
+interface nsIWindowsUIUtils : nsISupports
+{
+  /**
+   * Whether the OS is currently in tablet mode. Always false on
+   * non-Windows and on versions of Windows before win10
+   */
+  readonly attribute boolean inTabletMode;
+
+  /**
+   * Update the tablet mode state
+   */
+  void updateTabletModeState();
+};
+
--- a/widget/nsWidgetsCID.h
+++ b/widget/nsWidgetsCID.h
@@ -180,8 +180,12 @@
 
 #define NS_GFXINFO_CID \
 { 0xd755a760, 0x9f27, 0x11df, \
 { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66, 0x42, 0x42 } }
 
 #define NS_IMEPICKER_CID \
 { 0x8e5c35ef, 0xb65b, 0x47aa, \
 { 0xbb, 0x90, 0x5b, 0x89, 0x6d, 0x88, 0x24, 0x18 } }
+
+#define NS_WINDOWS_UIUTILS_CID \
+{ 0xe04a55e8, 0xfee3, 0x4ea2, \
+  { 0xa9, 0x8b, 0x41, 0xd2, 0x62, 0x1a, 0xdc, 0x3c } }
new file mode 100644
--- /dev/null
+++ b/widget/windows/WindowsUIUtils.cpp
@@ -0,0 +1,174 @@
+/* -*- 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 <windows.h>
+#include "mozwrlbase.h"
+#include "nsServiceManagerUtils.h"
+
+#include "WindowsUIUtils.h"
+
+#include "nsIObserverService.h"
+#include "nsIBaseWindow.h"
+#include "nsIDocshell.h"
+#include "nsIAppShellService.h"
+#include "nsAppShellCID.h"
+#include "nsIXULWindow.h"
+#include "mozilla/Services.h"
+#include "mozilla/WindowsVersion.h"
+#include "nsString.h"
+#include "nsIWidget.h"
+
+#include <windows.ui.viewmanagement.h>
+
+#pragma comment(lib, "runtimeobject.lib")
+
+using namespace mozilla;
+using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::ViewManagement;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+
+/* All of this is win10 stuff and we're compiling against win81 headers
+ * for now, so we may need to do some legwork: */
+#ifndef UserInteractionMode
+namespace ABI {
+  namespace Windows {
+    namespace UI {
+      namespace ViewManagement {
+        enum UserInteractionMode {
+          UserInteractionMode_Mouse = 0,
+          UserInteractionMode_Touch = 1
+        };
+      }
+    }
+  }
+}
+
+#endif
+
+#ifndef RuntimeClass_Windows_UI_ViewManagement_UIViewSettings
+#define RuntimeClass_Windows_UI_ViewManagement_UIViewSettings L"Windows.UI.ViewManagement.UIViewSettings"
+#endif
+
+#ifndef IUIViewSettings
+namespace ABI {
+  namespace Windows {
+    namespace UI {
+      namespace ViewManagement {
+        interface IUIViewSettings;
+        MIDL_INTERFACE("C63657F6-8850-470D-88F8-455E16EA2C26")
+          IUIViewSettings : public IInspectable
+          {
+            public:
+              virtual HRESULT STDMETHODCALLTYPE get_UserInteractionMode(UserInteractionMode *value) = 0;
+          };
+
+        extern const __declspec(selectany) IID & IID_IUIViewSettings = __uuidof(IUIViewSettings);
+      }
+    }
+  }
+}
+#endif
+
+#ifndef IUIViewSettingsInterop
+
+typedef interface IUIViewSettingsInterop IUIViewSettingsInterop;
+
+MIDL_INTERFACE("3694dbf9-8f68-44be-8ff5-195c98ede8a6")
+IUIViewSettingsInterop : public IInspectable
+{
+public:
+  virtual HRESULT STDMETHODCALLTYPE GetForWindow(HWND hwnd, REFIID riid, void **ppv) = 0;
+};
+#endif
+
+WindowsUIUtils::WindowsUIUtils() :
+  mInTabletMode(eTabletModeUnknown)
+{
+}
+
+WindowsUIUtils::~WindowsUIUtils()
+{
+}
+
+/*
+ * Implement the nsISupports methods...
+ */
+NS_IMPL_ISUPPORTS(WindowsUIUtils,
+                  nsIWindowsUIUtils)
+
+NS_IMETHODIMP
+WindowsUIUtils::GetInTabletMode(bool* aResult)
+{
+  if (mInTabletMode == eTabletModeUnknown) {
+    UpdateTabletModeState();
+  }
+  *aResult = mInTabletMode == eTabletModeOn;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+WindowsUIUtils::UpdateTabletModeState()
+{
+  if (!IsWin10OrLater()) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
+  nsCOMPtr<nsIXULWindow> hiddenWindow;
+
+  nsresult rv = appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIDocShell> docShell;
+  rv = hiddenWindow->GetDocShell(getter_AddRefs(docShell));
+  if (NS_FAILED(rv) || !docShell) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
+
+  if (!baseWindow)
+    return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIWidget> widget;
+  baseWindow->GetMainWidget(getter_AddRefs(widget));
+
+  if (!widget)
+    return NS_ERROR_FAILURE;
+
+  HWND winPtr = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
+  ComPtr<IUIViewSettingsInterop> uiViewSettingsInterop;
+
+  HRESULT hr = GetActivationFactory(
+      HStringReference(RuntimeClass_Windows_UI_ViewManagement_UIViewSettings).Get(),
+      &uiViewSettingsInterop);
+  if (SUCCEEDED(hr)) {
+    ComPtr<IUIViewSettings> uiViewSettings;
+    hr = uiViewSettingsInterop->GetForWindow(winPtr, IID_PPV_ARGS(&uiViewSettings));
+    if (SUCCEEDED(hr)) {
+      UserInteractionMode mode;
+      hr = uiViewSettings->get_UserInteractionMode(&mode);
+      if (SUCCEEDED(hr)) {
+        TabletModeState oldTabletModeState = mInTabletMode;
+        mInTabletMode = (mode == UserInteractionMode_Touch) ? eTabletModeOn : eTabletModeOff;
+        if (mInTabletMode != oldTabletModeState) {
+          nsCOMPtr<nsIObserverService> observerService =
+            mozilla::services::GetObserverService();
+          NS_NAMED_LITERAL_STRING(tabletMode, "tablet-mode");
+          NS_NAMED_LITERAL_STRING(normalMode, "normal-mode");
+          observerService->NotifyObservers(nullptr, "tablet-mode-change",
+            ((mInTabletMode == eTabletModeOn) ? tabletMode.get() : normalMode.get()));
+        }
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/widget/windows/WindowsUIUtils.h
@@ -0,0 +1,29 @@
+/* -*- 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/. */
+
+#ifndef mozilla_widget_WindowsUIUtils_h__
+#define mozilla_widget_WindowsUIUtils_h__
+
+#include "nsIWindowsUIUtils.h"
+
+enum TabletModeState {
+  eTabletModeUnknown = 0,
+  eTabletModeOff,
+  eTabletModeOn
+};
+
+class WindowsUIUtils final : public nsIWindowsUIUtils {
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIWINDOWSUIUTILS
+
+  WindowsUIUtils();
+protected:
+  ~WindowsUIUtils();
+
+  TabletModeState mInTabletMode;
+};
+
+#endif // mozilla_widget_WindowsUIUtils_h__
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -58,16 +58,17 @@ UNIFIED_SOURCES += [
 ]
 
 # The following files cannot be built in unified mode because of name clashes.
 SOURCES += [
     'JumpListBuilder.cpp',
     'nsBidiKeyboard.cpp',
     'nsFilePicker.cpp',
     'nsWidgetFactory.cpp',
+    'WindowsUIUtils.cpp',
     'WinMouseScrollHandler.cpp',
 ]
 
 if CONFIG['MOZ_CRASHREPORTER']:
     UNIFIED_SOURCES += [
         'LSPAnnotator.cpp',
     ]
 
new file mode 100644
--- /dev/null
+++ b/widget/windows/mozwrlbase.h
@@ -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>
--- a/widget/windows/nsWidgetFactory.cpp
+++ b/widget/windows/nsWidgetFactory.cpp
@@ -39,16 +39,18 @@
 #include "nsDragService.h"
 #include "nsTransferable.h"
 #include "nsHTMLFormatConverter.h"
 
 #include "WinTaskbar.h"
 #include "JumpListBuilder.h"
 #include "JumpListItem.h"
 
+#include "WindowsUIUtils.h"
+
 #ifdef NS_PRINTING
 #include "nsDeviceContextSpecWin.h"
 #include "nsPrintOptionsWin.h"
 #include "nsPrintSession.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::widget;
@@ -107,16 +109,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboa
 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(WindowsUIUtils)
 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)
@@ -145,16 +148,17 @@ 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);
+NS_DEFINE_NAMED_CID(NS_WINDOWS_UIUTILS_CID);
 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
@@ -177,16 +181,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor },
   { &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor },
   { &kNS_WIN_TASKBAR_CID, false, nullptr, WinTaskbarConstructor },
   { &kNS_WIN_JUMPLISTBUILDER_CID, false, nullptr, JumpListBuilderConstructor },
   { &kNS_WIN_JUMPLISTITEM_CID, false, nullptr, JumpListItemConstructor },
   { &kNS_WIN_JUMPLISTSEPARATOR_CID, false, nullptr, JumpListSeparatorConstructor },
   { &kNS_WIN_JUMPLISTLINK_CID, false, nullptr, JumpListLinkConstructor },
   { &kNS_WIN_JUMPLISTSHORTCUT_CID, false, nullptr, JumpListShortcutConstructor },
+  { &kNS_WINDOWS_UIUTILS_CID, false, nullptr, WindowsUIUtilsConstructor },
   { &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY },
   { &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor },
 #ifdef NS_PRINTING
   { &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintOptionsWinConstructor },
   { &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorWinConstructor },
   { &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor },
   { &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecWinConstructor },
 #endif
@@ -209,16 +214,17 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
   { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
   { "@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/windows-ui-utils;1", &kNS_WINDOWS_UIUTILS_CID },
   { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::MAIN_PROCESS_ONLY },
   { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID },
 #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
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -156,16 +156,18 @@
 #if !defined(WINABLEAPI)
 #include <winable.h>
 #endif // !defined(WINABLEAPI)
 #endif // defined(ACCESSIBILITY)
 
 #include "nsIWinTaskbar.h"
 #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
 
+#include "nsIWindowsUIUtils.h"
+
 #include "nsWindowDefs.h"
 
 #include "nsCrashOnException.h"
 #include "nsIXULRuntime.h"
 
 #include "nsIContent.h"
 
 #include "mozilla/HangMonitor.h"
@@ -4651,16 +4653,30 @@ nsWindow::ProcessMessage(UINT msg, WPARA
       nsCOMPtr<nsIFontEnumerator> fontEnum = do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv);
       if (NS_SUCCEEDED(rv)) {
         fontEnum->UpdateFontList(&didChange);
         ForceFontUpdate();
       } //if (NS_SUCCEEDED(rv))
     }
     break;
 
+    case WM_SETTINGCHANGE:
+    {
+      if (IsWin10OrLater() && mWindowType == eWindowType_invisible && lParam) {
+        auto lParamString = reinterpret_cast<const wchar_t*>(lParam);
+        if (!wcscmp(lParamString, L"UserInteractionMode")) {
+          nsCOMPtr<nsIWindowsUIUtils> uiUtils(do_GetService("@mozilla.org/windows-ui-utils;1"));
+          if (uiUtils) {
+            uiUtils->UpdateTabletModeState();
+          }
+        }
+      }
+    }
+    break;
+
     case WM_NCCALCSIZE:
     {
       if (mCustomNonClient) {
         // If `wParam` is `FALSE`, `lParam` points to a `RECT` that contains
         // the proposed window rectangle for our window.  During our
         // processing of the `WM_NCCALCSIZE` message, we are expected to
         // modify the `RECT` that `lParam` points to, so that its value upon
         // our return is the new client area.  We must return 0 if `wParam`