Bug 1210033 - Add on-screen keyboard diagnostic information to about:support. r=masayuki r=felipe, a=lizzard
authorJared Wein <jwein@mozilla.com>
Thu, 08 Oct 2015 11:51:47 -0400
changeset 284628 9bc9b8a09107bb1d32ab8743b9d16be03cde8827
parent 284627 fc5c56a6e3188af1c5d501af057424d34fd3ccc0
child 284629 53010930bc01e32fd389c549686ab8a773e0b684
push id8628
push usergijskruitbosch@gmail.com
push dateFri, 23 Oct 2015 18:54:31 +0000
treeherdermozilla-aurora@68f165595f3a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, felipe, lizzard
bugs1210033
milestone43.0a2
Bug 1210033 - Add on-screen keyboard diagnostic information to about:support. r=masayuki r=felipe, a=lizzard
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
@@ -3243,16 +3243,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
@@ -85,16 +85,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()
 {