Bug 1170522 - Expose whether or not we're in tablet mode to xul/js/css. r=jimm, r=ted, a=lmandel
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Tue, 16 Jun 2015 19:51:29 +0100
changeset 281577 e7738a202ad3c1d963fce3cb974b210b85fe58ba
parent 281576 57564319395c624948cb43cdaf4b06c61f196d9b
child 281578 c809ee45fa5227d1dd13ff75ea57c1b7e5ec7a10
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, ted, lmandel
bugs1170522
milestone41.0a2
Bug 1170522 - Expose whether or not we're in tablet mode to xul/js/css. r=jimm, r=ted, a=lmandel
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"
@@ -4650,16 +4652,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`