Bug 1192573 - Require tablet-mode (Win10+) to show the on-screen keyboard. r=masayuki, a=sledru
authorJared Wein <jwein@mozilla.com>
Thu, 13 Aug 2015 14:23:54 -0400
changeset 288767 90b30784881791352d87eeaa5c98d51b11275dee
parent 288766 a40a4eae93ea5d962bf4a744aa33e6644c388f2a
child 288768 76f8cfa41d910eddda686f07aaac7221dbc5c15a
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, sledru
bugs1192573
milestone42.0a2
Bug 1192573 - Require tablet-mode (Win10+) to show the on-screen keyboard. r=masayuki, a=sledru
modules/libpref/init/all.js
widget/windows/WinIMEHandler.cpp
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3229,16 +3229,19 @@ pref("ui.osk.enabled", false);
 #else
 pref("ui.osk.enabled", true);
 #endif
 // Only show the on-screen keyboard if there are no physical keyboards attached
 // to the device.
 pref("ui.osk.detect_physical_keyboard", true);
 // Path to TabTip.exe on local machine. Cached for performance reasons.
 pref("ui.osk.on_screen_keyboard_path", "");
+// Only show the on-screen keyboard when Windows is in Tablet mode. Setting
+// this pref to false will allow the OSK to show in regular non-tablet mode.
+pref("ui.osk.require_tablet_mode", true);
 
 # XP_WIN
 #endif
 
 #ifdef XP_MACOSX
 // Mac specific preference defaults
 pref("browser.drag_out_of_frame_style", 1);
 pref("ui.key.saveLink.shift", false); // true = shift, false = meta
--- a/widget/windows/WinIMEHandler.cpp
+++ b/widget/windows/WinIMEHandler.cpp
@@ -11,26 +11,28 @@
 
 #ifdef NS_ENABLE_TSF
 #include "TSFTextStore.h"
 #endif // #ifdef NS_ENABLE_TSF
 
 #include "nsLookAndFeel.h"
 #include "nsWindow.h"
 #include "WinUtils.h"
+#include "nsIWindowsUIUtils.h"
 
 #include "shellapi.h"
 #include "Shlobj.h"
 #include "PowrProf.h"
 #include "Setupapi.h"
 #include "cfgmgr32.h"
 
 const char* kOskPathPrefName = "ui.osk.on_screen_keyboard_path";
 const char* kOskEnabled = "ui.osk.enabled";
 const char* kOskDetectPhysicalKeyboard = "ui.osk.detect_physical_keyboard";
+const char* kOskRequireTabletMode = "ui.osk.require_tablet_mode";
 
 namespace mozilla {
 namespace widget {
 
 /******************************************************************************
  * IMEHandler
  ******************************************************************************/
 
@@ -520,29 +522,54 @@ IMEHandler::SetInputScopeForIMM32(nsWind
                     nullptr, nullptr);
   }
 }
 
 // static
 void
 IMEHandler::MaybeShowOnScreenKeyboard()
 {
-  if (sPluginHasFocus) {
+  if (sPluginHasFocus ||
+      !IsWin10OrLater() ||
+      !Preferences::GetBool(kOskEnabled, true) ||
+      sShowingOnScreenKeyboard ||
+      IMEHandler::IsKeyboardPresentOnSlate()) {
     return;
   }
-  IMEHandler::ShowOnScreenKeyboard();
+
+  if (Preferences::GetBool(kOskRequireTabletMode, true)) {
+    // Tablet Mode is only supported on Windows 10 and higher.
+    // When touch-event detection within IME is better supported
+    // this check may be removed, and ShowOnScreenKeyboard can
+    // run on Windows 8 and higher (adjusting the IsWin10OrLater
+    // guard above and within MaybeDismissOnScreenKeyboard).
+    nsCOMPtr<nsIWindowsUIUtils>
+      uiUtils(do_GetService("@mozilla.org/windows-ui-utils;1"));
+    if (uiUtils) {
+      bool isInTabletMode = false;
+      uiUtils->GetInTabletMode(&isInTabletMode);
+      if (!isInTabletMode) {
+        return;
+      }
+    }
+  }
+
+ IMEHandler::ShowOnScreenKeyboard();
 }
 
 // static
 void
 IMEHandler::MaybeDismissOnScreenKeyboard()
 {
-  if (sPluginHasFocus) {
+  if (sPluginHasFocus ||
+      !IsWin10OrLater() ||
+      !sShowingOnScreenKeyboard) {
     return;
   }
+
   IMEHandler::DismissOnScreenKeyboard();
 }
 
 // static
 bool
 IMEHandler::WStringStartsWithCaseInsensitive(const std::wstring& aHaystack,
                                              const std::wstring& aNeedle)
 {
@@ -634,23 +661,22 @@ IMEHandler::IsKeyboardPresentOnSlate()
       return false;
     }
   }
 
   const GUID KEYBOARD_CLASS_GUID =
     { 0x4D36E96B, 0xE325,  0x11CE,
       { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } };
 
-  bool result = false;
   // Query for all the keyboard devices.
   HDEVINFO device_info =
     ::SetupDiGetClassDevs(&KEYBOARD_CLASS_GUID, nullptr,
                           nullptr, DIGCF_PRESENT);
   if (device_info == INVALID_HANDLE_VALUE) {
-    return result;
+    return false;
   }
 
   // Enumerate all keyboards and look for ACPI\PNP and HID\VID devices. If
   // the count is more than 1 we assume that a keyboard is present. This is
   // under the assumption that there will always be one keyboard device.
   for (DWORD i = 0;; ++i) {
     SP_DEVINFO_DATA device_info_data = { 0 };
     device_info_data.cbSize = sizeof(device_info_data);
@@ -670,35 +696,28 @@ IMEHandler::IsKeyboardPresentOnSlate()
       if (IMEHandler::WStringStartsWithCaseInsensitive(device_id,
                                                        L"ACPI") ||
           IMEHandler::WStringStartsWithCaseInsensitive(device_id,
                                                        L"HID\\VID")) {
         // The heuristic we are using is to check the count of keyboards and
         // return true if the API's report one or more keyboards. Please note
         // that this will break for non keyboard devices which expose a
         // keyboard PDO.
-        result = true;
+        return true;
       }
     }
   }
-  return result;
+  return false;
 }
 
 // Based on DisplayVirtualKeyboard() in Chromium's base/win/win_util.cc.
 // static
 void
 IMEHandler::ShowOnScreenKeyboard()
 {
-  if (!IsWin8OrLater() ||
-      !Preferences::GetBool(kOskEnabled, true) ||
-      sShowingOnScreenKeyboard ||
-      IMEHandler::IsKeyboardPresentOnSlate()) {
-    return;
-  }
-
   nsAutoString cachedPath;
   nsresult result = Preferences::GetString(kOskPathPrefName, &cachedPath);
   if (NS_FAILED(result) || cachedPath.IsEmpty()) {
     wchar_t path[MAX_PATH];
     // The path to TabTip.exe is defined at the following registry key.
     // This is pulled out of the 64-bit registry hive directly.
     const wchar_t kRegKeyName[] =
       L"Software\\Classes\\CLSID\\"
@@ -769,21 +788,16 @@ IMEHandler::ShowOnScreenKeyboard()
   sShowingOnScreenKeyboard = true;
 }
 
 // Based on DismissVirtualKeyboard() in Chromium's base/win/win_util.cc.
 // static
 void
 IMEHandler::DismissOnScreenKeyboard()
 {
-  if (!IsWin8OrLater() ||
-      !sShowingOnScreenKeyboard) {
-    return;
-  }
-
   sShowingOnScreenKeyboard = false;
 
   // Dismiss the virtual keyboard by generating the ESC keystroke
   // programmatically.
   const wchar_t kOSKClassName[] = L"IPTip_Main_Window";
   HWND osk = ::FindWindowW(kOSKClassName, nullptr);
   if (::IsWindow(osk) && ::IsWindowEnabled(osk)) {
     ::PostMessage(osk, WM_SYSCOMMAND, SC_CLOSE, 0);