diff options
author | ananta <ananta@chromium.org> | 2014-10-20 17:14:46 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-21 00:15:14 +0000 |
commit | 74ca738f038557de0e53fd91a8d15774da36f85a (patch) | |
tree | 126e1659c2cae49feec43a069e90277bffd1e2fc /base/win | |
parent | 800a6c7f0e5524b5d9fec10d3c9a4b39f0428a4c (diff) | |
download | chromium_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.cc | 62 |
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; |