Bug 1210033 - Add on-screen keyboard diagnostic information to about:support. r=masayuki r=felipe
authorJared Wein <jwein@mozilla.com>
Thu, 08 Oct 2015 11:51:47 -0400
changeset 266924 a6abbca3d2e8af13f08acdc899aba317bbbd2bd2
parent 266923 e0a91b61e9c27928f4fa277fb748b614152ffe96
child 266925 28a0a90ea90a3517bcf38fe362468ac7feb3c94b
push id66331
push userkwierso@gmail.com
push dateThu, 08 Oct 2015 21:35:51 +0000
treeherdermozilla-inbound@1a5167cd7688 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, felipe
bugs1210033
milestone44.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 1210033 - Add on-screen keyboard diagnostic information to about:support. r=masayuki r=felipe
modules/libpref/init/all.js
toolkit/modules/Troubleshoot.jsm
widget/windows/WinIMEHandler.cpp
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3265,16 +3265,21 @@ pref("ui.osk.enabled", true);
 // 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);
+// This pref stores the "reason" that the on-screen keyboard was either
+// shown or not shown when focus is moved to an editable text field. It is
+// used to help debug why the keyboard is either not appearing when expected
+// or appearing when it is not expected.
+pref("ui.osk.debug.keyboardDisplayReason", "");
 
 # 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/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -84,16 +84,20 @@ const PREFS_WHITELIST = [
   "plugins.",
   "print.",
   "privacy.",
   "security.",
   "social.enabled",
   "storage.vacuum.last.",
   "svg.",
   "toolkit.startup.recent_crashes",
+  "ui.osk.enabled",
+  "ui.osk.detect_physical_keyboard",
+  "ui.osk.require_tablet_mode",
+  "ui.osk.debug.keyboardDisplayReason",
   "webgl.",
 ];
 
 // The blacklist, unlike the whitelist, is a list of regular expressions.
 const PREFS_BLACKLIST = [
   /^network[.]proxy[.]/,
   /[.]print_to_filename$/,
   /^print[.]macosx[.]pagesetup/,
--- a/widget/windows/WinIMEHandler.cpp
+++ b/widget/windows/WinIMEHandler.cpp
@@ -24,16 +24,17 @@
 #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";
+const char* kOskDebugReason = "ui.osk.debug.keyboardDisplayReason";
 
 namespace mozilla {
 namespace widget {
 
 /******************************************************************************
  * IMEHandler
  ******************************************************************************/
 
@@ -542,17 +543,17 @@ IMEHandler::MaybeShowOnScreenKeyboard()
   // run on Windows 8 and higher (adjusting the IsWin10OrLater
   // guard above and within MaybeDismissOnScreenKeyboard).
   if (!IsInTabletMode() &&
       Preferences::GetBool(kOskRequireTabletMode, true) &&
       !AutoInvokeOnScreenKeyboardInDesktopMode()) {
     return;
   }
 
- IMEHandler::ShowOnScreenKeyboard();
+  IMEHandler::ShowOnScreenKeyboard();
 }
 
 // static
 void
 IMEHandler::MaybeDismissOnScreenKeyboard()
 {
   if (sPluginHasFocus ||
       !IsWin10OrLater() ||
@@ -585,32 +586,36 @@ IMEHandler::WStringStartsWithCaseInsensi
 // are attached to the machine.
 // Based on IsKeyboardPresentOnSlate() in Chromium's base/win/win_util.cc.
 // static
 bool
 IMEHandler::IsKeyboardPresentOnSlate()
 {
   // This function is only supported for Windows 8 and up.
   if (!IsWin8OrLater()) {
+    Preferences::SetString(kOskDebugReason, L"IKPOS: Requires Win8+.");
     return true;
   }
 
   if (!Preferences::GetBool(kOskDetectPhysicalKeyboard, true)) {
-    // Detection for physical keyboard has been disabled for testing.
+    Preferences::SetString(kOskDebugReason, L"IKPOS: Detection disabled.");
     return false;
   }
 
   // This function should be only invoked for machines with touch screens.
   if ((::GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH)
         != NID_INTEGRATED_TOUCH) {
+    Preferences::SetString(kOskDebugReason,
+                           L"IKPOS: Touch screen not found.");
     return true;
   }
 
   // If the device is docked, the user is treating the device as a PC.
   if (::GetSystemMetrics(SM_SYSTEMDOCKED) != 0) {
+    Preferences::SetString(kOskDebugReason, L"IKPOS: System docked.");
     return true;
   }
 
   // To determine whether a keyboard is present on the device, we do the
   // following:-
   // 1. Check whether the device supports auto rotation. If it does then
   //    it possibly supports flipping from laptop to slate mode. If it
   //    does not support auto rotation, then we assume it is a desktop
@@ -627,50 +632,61 @@ IMEHandler::IsKeyboardPresentOnSlate()
   typedef BOOL (WINAPI* GetAutoRotationState)(PAR_STATE state);
   GetAutoRotationState get_rotation_state =
     reinterpret_cast<GetAutoRotationState>(::GetProcAddress(
       ::GetModuleHandleW(L"user32.dll"), "GetAutoRotationState"));
 
   if (get_rotation_state) {
     AR_STATE auto_rotation_state = AR_ENABLED;
     get_rotation_state(&auto_rotation_state);
-    if ((auto_rotation_state & AR_NOSENSOR) ||
-        (auto_rotation_state & AR_NOT_SUPPORTED)) {
-      // If there is no auto rotation sensor or rotation is not supported in
-      // the current configuration, then we can assume that this is a desktop
-      // or a traditional laptop.
+    // If there is no auto rotation sensor or rotation is not supported in
+    // the current configuration, then we can assume that this is a desktop
+    // or a traditional laptop.
+    if (auto_rotation_state & AR_NOSENSOR) {
+      Preferences::SetString(kOskDebugReason,
+                             L"IKPOS: Rotation sensor not found.");
+      return true;
+    } else if (auto_rotation_state & AR_NOT_SUPPORTED) {
+      Preferences::SetString(kOskDebugReason,
+                             L"IKPOS: Auto-rotation not supported.");
       return true;
     }
   }
 
   // Check if the device is being used as a laptop or a tablet. This can be
   // checked by first checking the role of the device and then the
   // corresponding system metric (SM_CONVERTIBLESLATEMODE). If it is being
   // used as a tablet then we want the OSK to show up.
   typedef POWER_PLATFORM_ROLE (WINAPI* PowerDeterminePlatformRole)();
   PowerDeterminePlatformRole power_determine_platform_role =
     reinterpret_cast<PowerDeterminePlatformRole>(::GetProcAddress(
       ::LoadLibraryW(L"PowrProf.dll"), "PowerDeterminePlatformRole"));
   if (power_determine_platform_role) {
     POWER_PLATFORM_ROLE role = power_determine_platform_role();
     if (((role == PlatformRoleMobile) || (role == PlatformRoleSlate)) &&
          (::GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0)) {
+      if (role == PlatformRoleMobile) {
+        Preferences::SetString(kOskDebugReason, L"IKPOS: PlatformRoleMobile.");
+      } else if (role == PlatformRoleSlate) {
+        Preferences::SetString(kOskDebugReason, L"IKPOS: PlatformRoleSlate.");
+      }
       return false;
     }
   }
 
   const GUID KEYBOARD_CLASS_GUID =
     { 0x4D36E96B, 0xE325,  0x11CE,
       { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } };
 
   // Query for all the keyboard devices.
   HDEVINFO device_info =
     ::SetupDiGetClassDevs(&KEYBOARD_CLASS_GUID, nullptr,
                           nullptr, DIGCF_PRESENT);
   if (device_info == INVALID_HANDLE_VALUE) {
+    Preferences::SetString(kOskDebugReason, L"IKPOS: No keyboard info.");
     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 };
@@ -691,63 +707,85 @@ 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.
+        Preferences::SetString(kOskDebugReason,
+                               L"IKPOS: Keyboard presence confirmed.");
         return true;
       }
     }
   }
+  Preferences::SetString(kOskDebugReason,
+                         L"IKPOS: Lack of keyboard confirmed.");
   return false;
 }
 
 // static
 bool
 IMEHandler::IsInTabletMode()
 {
   nsCOMPtr<nsIWindowsUIUtils>
     uiUtils(do_GetService("@mozilla.org/windows-ui-utils;1"));
   if (NS_WARN_IF(!uiUtils)) {
+    Preferences::SetString(kOskDebugReason,
+                           L"IITM: nsIWindowsUIUtils not available.");
     return false;
   }
   bool isInTabletMode = false;
   uiUtils->GetInTabletMode(&isInTabletMode);
+  if (isInTabletMode) {
+    Preferences::SetString(kOskDebugReason, L"IITM: GetInTabletMode=true.");
+  } else {
+    Preferences::SetString(kOskDebugReason, L"IITM: GetInTabletMode=false.");
+  }
   return isInTabletMode;
 }
 
 // static
 bool
 IMEHandler::AutoInvokeOnScreenKeyboardInDesktopMode()
 {
   nsresult rv;
   nsCOMPtr<nsIWindowsRegKey> regKey
     (do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv));
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    Preferences::SetString(kOskDebugReason, L"AIOSKIDM: "
+                           L"nsIWindowsRegKey not available");
     return false;
   }
   rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
                     NS_LITERAL_STRING("SOFTWARE\\Microsoft\\TabletTip\\1.7"),
                     nsIWindowsRegKey::ACCESS_QUERY_VALUE);
   if (NS_FAILED(rv)) {
+    Preferences::SetString(kOskDebugReason,
+                           L"AIOSKIDM: failed opening regkey.");
     return false;
   }
   // EnableDesktopModeAutoInvoke is an opt-in option from the Windows
   // Settings to "Automatically show the touch keyboard in windowed apps
   // when there's no keyboard attached to your device." If the user has
   // opted-in to this behavior, the tablet-mode requirement is skipped.
   uint32_t value;
   rv = regKey->ReadIntValue(NS_LITERAL_STRING("EnableDesktopModeAutoInvoke"),
                             &value);
   if (NS_FAILED(rv)) {
+    Preferences::SetString(kOskDebugReason,
+                           L"AIOSKIDM: failed reading value of regkey.");
     return false;
   }
+  if (!!value) {
+    Preferences::SetString(kOskDebugReason, L"AIOSKIDM: regkey value=true.");
+  } else {
+    Preferences::SetString(kOskDebugReason, L"AIOSKIDM: regkey value=false.");
+  }
   return !!value;
 }
 
 // Based on DisplayVirtualKeyboard() in Chromium's base/win/win_util.cc.
 // static
 void
 IMEHandler::ShowOnScreenKeyboard()
 {