summaryrefslogtreecommitdiffstats
path: root/base/win
diff options
context:
space:
mode:
authorananta <ananta@chromium.org>2014-10-20 17:14:46 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-21 00:15:14 +0000
commit74ca738f038557de0e53fd91a8d15774da36f85a (patch)
tree126e1659c2cae49feec43a069e90277bffd1e2fc /base/win
parent800a6c7f0e5524b5d9fec10d3c9a4b39f0428a4c (diff)
downloadchromium_src-74ca738f038557de0e53fd91a8d15774da36f85a.zip
chromium_src-74ca738f038557de0e53fd91a8d15774da36f85a.tar.gz
chromium_src-74ca738f038557de0e53fd91a8d15774da36f85a.tar.bz2
The DisplayVirtualKeyboard function on Windows 8 and beyond should not be displaying the OSK if a physical keyboard is attached to the machine.
Added a function IsKeyboardPresent locally to win_util.cc which uses the setup API's to enumerate keyboard devices and check for the common ones like ACPI\PNP and HID\VID. This function returns true if the number of keyboards is greater than 1. This is a hacky approach and is being done for lack of a good way to determine the presence of a keyboard. The documented methods don't work well. BUG=335735 Review URL: https://codereview.chromium.org/644783005 Cr-Commit-Position: refs/heads/master@{#300383}
Diffstat (limited to 'base/win')
-rw-r--r--base/win/win_util.cc62
1 files changed, 62 insertions, 0 deletions
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index 69e14e4..a53f30a 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -5,6 +5,7 @@
#include "base/win/win_util.h"
#include <aclapi.h>
+#include <cfgmgr32.h>
#include <lm.h>
#include <powrprof.h>
#include <shellapi.h>
@@ -14,6 +15,7 @@
#include <propkey.h>
#include <propvarutil.h>
#include <sddl.h>
+#include <setupapi.h>
#include <signal.h>
#include <stdlib.h>
@@ -53,6 +55,63 @@ const wchar_t kWindows8OSKRegPath[] =
L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}"
L"\\LocalServer32";
+// Returns true if a physical keyboard is detected on Windows 8 and up.
+// Uses the Setup APIs to enumerate the attached keyboards and returns true
+// if the keyboard count is more than 1. While this will work in most cases
+// it won't work if there are devices which expose keyboard interfaces which
+// are attached to the machine.
+bool IsKeyboardPresentOnSlate() {
+ // This function is only supported for Windows 8 and up.
+ DCHECK(base::win::GetVersion() >= base::win::VERSION_WIN8);
+
+ // This function should be only invoked for machines with touch screens.
+ if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH)
+ != NID_INTEGRATED_TOUCH) {
+ return true;
+ }
+
+ 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, NULL, NULL, DIGCF_PRESENT);
+ if (device_info == INVALID_HANDLE_VALUE)
+ 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.
+ int keyboard_count = 0;
+ for (DWORD i = 0;; ++i) {
+ SP_DEVINFO_DATA device_info_data = { 0 };
+ device_info_data.cbSize = sizeof(device_info_data);
+ if (!SetupDiEnumDeviceInfo(device_info, i, &device_info_data))
+ break;
+ // Get the device ID.
+ wchar_t device_id[MAX_DEVICE_ID_LEN];
+ CONFIGRET status = CM_Get_Device_ID(device_info_data.DevInst,
+ device_id,
+ MAX_DEVICE_ID_LEN,
+ 0);
+ if (status == CR_SUCCESS) {
+ // To reduce the scope of the hack we only look for PNP and HID
+ // keyboards.
+ if (StartsWith(L"ACPI\\PNP", device_id, false) ||
+ StartsWith(L"HID\\VID", device_id, false)) {
+ keyboard_count++;
+ }
+ }
+ }
+ // On a Windows machine, the API's always report 1 keyboard at least
+ // regardless of whether the machine has a keyboard attached or not.
+ // The heuristic we are using is to check the count and return true
+ // if the API's report more than one keyboard. Please note that this
+ // will break for non keyboard devices which expose a keyboard PDO.
+ return keyboard_count > 1;
+}
+
} // namespace
namespace base {
@@ -252,6 +311,9 @@ bool DisplayVirtualKeyboard() {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return false;
+ if (IsKeyboardPresentOnSlate())
+ return false;
+
static base::LazyInstance<string16>::Leaky osk_path =
LAZY_INSTANCE_INITIALIZER;