OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/win/win_util.h" | 5 #include "base/win/win_util.h" |
6 | 6 |
7 #include <aclapi.h> | 7 #include <aclapi.h> |
8 #include <cfgmgr32.h> | 8 #include <cfgmgr32.h> |
9 #include <lm.h> | 9 #include <lm.h> |
10 #include <powrprof.h> | 10 #include <powrprof.h> |
11 #include <shellapi.h> | 11 #include <shellapi.h> |
12 #include <shlobj.h> | 12 #include <shlobj.h> |
13 #include <shobjidl.h> // Must be before propkey. | 13 #include <shobjidl.h> // Must be before propkey. |
14 #include <initguid.h> | 14 #include <initguid.h> |
| 15 #include <inspectable.h> |
15 #include <propkey.h> | 16 #include <propkey.h> |
16 #include <propvarutil.h> | 17 #include <propvarutil.h> |
17 #include <psapi.h> | 18 #include <psapi.h> |
| 19 #include <roapi.h> |
18 #include <sddl.h> | 20 #include <sddl.h> |
19 #include <setupapi.h> | 21 #include <setupapi.h> |
20 #include <signal.h> | 22 #include <signal.h> |
21 #include <stddef.h> | 23 #include <stddef.h> |
22 #include <stdlib.h> | 24 #include <stdlib.h> |
| 25 #include <uiviewsettingsinterop.h> |
| 26 #include <windows.ui.viewmanagement.h> |
| 27 #include <winstring.h> |
| 28 #include <wrl/wrappers/corewrappers.h> |
23 | 29 |
24 #include "base/base_switches.h" | 30 #include "base/base_switches.h" |
25 #include "base/command_line.h" | 31 #include "base/command_line.h" |
26 #include "base/lazy_instance.h" | 32 #include "base/lazy_instance.h" |
27 #include "base/logging.h" | 33 #include "base/logging.h" |
28 #include "base/macros.h" | 34 #include "base/macros.h" |
29 #include "base/memory/scoped_ptr.h" | 35 #include "base/memory/scoped_ptr.h" |
30 #include "base/strings/string_util.h" | 36 #include "base/strings/string_util.h" |
31 #include "base/strings/stringprintf.h" | 37 #include "base/strings/stringprintf.h" |
32 #include "base/strings/utf_string_conversions.h" | 38 #include "base/strings/utf_string_conversions.h" |
33 #include "base/threading/thread_restrictions.h" | 39 #include "base/threading/thread_restrictions.h" |
34 #include "base/win/registry.h" | 40 #include "base/win/registry.h" |
35 #include "base/win/scoped_co_mem.h" | 41 #include "base/win/scoped_co_mem.h" |
| 42 #include "base/win/scoped_comptr.h" |
36 #include "base/win/scoped_handle.h" | 43 #include "base/win/scoped_handle.h" |
37 #include "base/win/scoped_propvariant.h" | 44 #include "base/win/scoped_propvariant.h" |
38 #include "base/win/windows_version.h" | 45 #include "base/win/windows_version.h" |
39 | 46 |
40 namespace base { | 47 namespace base { |
41 namespace win { | 48 namespace win { |
42 | 49 |
43 namespace { | 50 namespace { |
44 | 51 |
45 // Sets the value of |property_key| to |property_value| in |property_store|. | 52 // Sets the value of |property_key| to |property_value| in |property_store|. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 const wchar_t kWindows8OSKRegPath[] = | 107 const wchar_t kWindows8OSKRegPath[] = |
101 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" | 108 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" |
102 L"\\LocalServer32"; | 109 L"\\LocalServer32"; |
103 | 110 |
104 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx | 111 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx |
105 // API for that. | 112 // API for that. |
106 POWER_PLATFORM_ROLE GetPlatformRole() { | 113 POWER_PLATFORM_ROLE GetPlatformRole() { |
107 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); | 114 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); |
108 } | 115 } |
109 | 116 |
| 117 // Uses the Windows 10 WRL API's to query the current system state. The API's |
| 118 // we are using in the function below are supported in Win32 apps as per msdn. |
| 119 // It looks like the API implementation is buggy at least on Surface 4 causing |
| 120 // it to always return UserInteractionMode_Touch which as per documentation |
| 121 // indicates tablet mode. |
| 122 bool IsWindows10TabletDevice() { |
| 123 if (GetVersion() < VERSION_WIN10) |
| 124 return false; |
| 125 |
| 126 using RoGetActivationFactoryFunction = decltype(&RoGetActivationFactory); |
| 127 using WindowsCreateStringFunction = decltype(&WindowsCreateString); |
| 128 |
| 129 static RoGetActivationFactoryFunction get_factory = nullptr; |
| 130 static WindowsCreateStringFunction create_string = nullptr; |
| 131 |
| 132 if (!get_factory) { |
| 133 DCHECK_EQ(create_string, static_cast<WindowsCreateStringFunction>( |
| 134 nullptr)); |
| 135 |
| 136 HMODULE combase_dll = ::LoadLibrary(L"combase.dll"); |
| 137 if (!combase_dll) |
| 138 return false; |
| 139 |
| 140 get_factory = reinterpret_cast<RoGetActivationFactoryFunction>( |
| 141 ::GetProcAddress(combase_dll, "RoGetActivationFactory")); |
| 142 if (!get_factory) { |
| 143 CHECK(false); |
| 144 return false; |
| 145 } |
| 146 |
| 147 create_string = reinterpret_cast<WindowsCreateStringFunction>( |
| 148 ::GetProcAddress(combase_dll, "WindowsCreateString")); |
| 149 if (!create_string) { |
| 150 CHECK(false); |
| 151 return false; |
| 152 } |
| 153 } |
| 154 |
| 155 HRESULT hr = E_FAIL; |
| 156 // This HSTRING is allocated on the heap and is leaked. |
| 157 static HSTRING view_settings_guid = NULL; |
| 158 if (!view_settings_guid) { |
| 159 hr = create_string( |
| 160 RuntimeClass_Windows_UI_ViewManagement_UIViewSettings, |
| 161 static_cast<UINT32>( |
| 162 wcslen(RuntimeClass_Windows_UI_ViewManagement_UIViewSettings)), |
| 163 &view_settings_guid); |
| 164 if (FAILED(hr)) |
| 165 return false; |
| 166 } |
| 167 |
| 168 base::win::ScopedComPtr<IUIViewSettingsInterop> view_settings_interop; |
| 169 hr = get_factory(view_settings_guid, |
| 170 __uuidof(IUIViewSettingsInterop), |
| 171 view_settings_interop.ReceiveVoid()); |
| 172 if (FAILED(hr)) |
| 173 return false; |
| 174 |
| 175 base::win::ScopedComPtr<ABI::Windows::UI::ViewManagement::IUIViewSettings> |
| 176 view_settings; |
| 177 // TODO(ananta) |
| 178 // Avoid using GetForegroundWindow here and pass in the HWND of the window |
| 179 // intiating the request to display the keyboard. |
| 180 hr = view_settings_interop->GetForWindow( |
| 181 ::GetForegroundWindow(), |
| 182 __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings), |
| 183 view_settings.ReceiveVoid()); |
| 184 if (FAILED(hr)) |
| 185 return false; |
| 186 |
| 187 ABI::Windows::UI::ViewManagement::UserInteractionMode mode = |
| 188 ABI::Windows::UI::ViewManagement::UserInteractionMode_Mouse; |
| 189 view_settings->get_UserInteractionMode(&mode); |
| 190 return mode == ABI::Windows::UI::ViewManagement::UserInteractionMode_Touch; |
| 191 } |
| 192 |
110 } // namespace | 193 } // namespace |
111 | 194 |
112 // Returns true if a physical keyboard is detected on Windows 8 and up. | 195 // Returns true if a physical keyboard is detected on Windows 8 and up. |
113 // Uses the Setup APIs to enumerate the attached keyboards and returns true | 196 // Uses the Setup APIs to enumerate the attached keyboards and returns true |
114 // if the keyboard count is 1 or more.. While this will work in most cases | 197 // if the keyboard count is 1 or more.. While this will work in most cases |
115 // it won't work if there are devices which expose keyboard interfaces which | 198 // it won't work if there are devices which expose keyboard interfaces which |
116 // are attached to the machine. | 199 // are attached to the machine. |
117 bool IsKeyboardPresentOnSlate(std::string* reason) { | 200 bool IsKeyboardPresentOnSlate(std::string* reason) { |
118 bool result = false; | 201 bool result = false; |
119 | 202 |
(...skipping 14 matching lines...) Expand all Loading... |
134 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) | 217 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) |
135 != NID_INTEGRATED_TOUCH) { | 218 != NID_INTEGRATED_TOUCH) { |
136 if (reason) { | 219 if (reason) { |
137 *reason += "NID_INTEGRATED_TOUCH\n"; | 220 *reason += "NID_INTEGRATED_TOUCH\n"; |
138 result = true; | 221 result = true; |
139 } else { | 222 } else { |
140 return true; | 223 return true; |
141 } | 224 } |
142 } | 225 } |
143 | 226 |
| 227 // If it is a tablet device we assume that there is no keyboard attached. |
144 if (IsTabletDevice(reason)) { | 228 if (IsTabletDevice(reason)) { |
145 if (reason) | 229 if (reason) |
146 *reason += "Tablet device.\n"; | 230 *reason += "Tablet device.\n"; |
147 return true; | 231 return false; |
148 } else { | 232 } else { |
149 if (reason) { | 233 if (reason) { |
150 *reason += "Not a tablet device"; | 234 *reason += "Not a tablet device"; |
151 result = true; | 235 result = true; |
152 } else { | 236 } else { |
153 return true; | 237 return true; |
154 } | 238 } |
155 } | 239 } |
156 | 240 |
157 // To determine whether a keyboard is present on the device, we do the | 241 // To determine whether a keyboard is present on the device, we do the |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 signal(SIGABRT, ForceCrashOnSigAbort); | 468 signal(SIGABRT, ForceCrashOnSigAbort); |
385 } | 469 } |
386 | 470 |
387 bool IsTabletDevice(std::string* reason) { | 471 bool IsTabletDevice(std::string* reason) { |
388 if (GetVersion() < VERSION_WIN8) { | 472 if (GetVersion() < VERSION_WIN8) { |
389 if (reason) | 473 if (reason) |
390 *reason = "Tablet device detection not supported below Windows 8\n"; | 474 *reason = "Tablet device detection not supported below Windows 8\n"; |
391 return false; | 475 return false; |
392 } | 476 } |
393 | 477 |
| 478 if (IsWindows10TabletDevice()) |
| 479 return true; |
| 480 |
394 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { | 481 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { |
395 if (reason) { | 482 if (reason) { |
396 *reason += "Device does not support touch.\n"; | 483 *reason += "Device does not support touch.\n"; |
397 } else { | 484 } else { |
398 return false; | 485 return false; |
399 } | 486 } |
400 } | 487 } |
401 | 488 |
402 // If the device is docked, the user is treating the device as a PC. | 489 // If the device is docked, the user is treating the device as a PC. |
403 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { | 490 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { |
404 if (reason) { | 491 if (reason) { |
405 *reason += "SM_SYSTEMDOCKED\n"; | 492 *reason += "SM_SYSTEMDOCKED\n"; |
406 } else { | 493 } else { |
407 return false; | 494 return false; |
408 } | 495 } |
409 } | 496 } |
410 | 497 |
411 // PlatformRoleSlate was added in Windows 8+. | 498 // PlatformRoleSlate was added in Windows 8+. |
412 POWER_PLATFORM_ROLE role = GetPlatformRole(); | 499 POWER_PLATFORM_ROLE role = GetPlatformRole(); |
413 bool mobile_power_profile = (role == PlatformRoleMobile); | 500 bool mobile_power_profile = (role == PlatformRoleMobile); |
414 bool slate_power_profile = (role == PlatformRoleSlate); | 501 bool slate_power_profile = (role == PlatformRoleSlate); |
415 | 502 |
416 bool is_tablet = false; | 503 bool is_tablet = false; |
417 | 504 bool is_tablet_pc = false; |
418 if (mobile_power_profile || slate_power_profile) { | 505 if (mobile_power_profile || slate_power_profile) { |
| 506 is_tablet_pc = !GetSystemMetrics(SM_TABLETPC); |
419 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); | 507 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); |
420 if (!is_tablet) { | 508 if (!is_tablet) { |
421 if (reason) { | 509 if (reason) { |
422 *reason += "Not in slate mode.\n"; | 510 *reason += "Not in slate mode.\n"; |
423 } else { | 511 } else { |
424 return false; | 512 return false; |
425 } | 513 } |
426 } else { | 514 } else { |
427 if (reason) { | 515 if (reason) { |
428 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : | 516 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : |
429 "PlatformRoleSlate\n"; | 517 "PlatformRoleSlate\n"; |
430 } | 518 } |
431 } | 519 } |
432 } else { | 520 } else { |
433 if (reason) | 521 if (reason) |
434 *reason += "Device role is not mobile or slate.\n"; | 522 *reason += "Device role is not mobile or slate.\n"; |
435 } | 523 } |
436 return is_tablet; | 524 return is_tablet && is_tablet_pc; |
437 } | 525 } |
438 | 526 |
439 bool DisplayVirtualKeyboard() { | 527 bool DisplayVirtualKeyboard() { |
440 if (GetVersion() < VERSION_WIN8) | 528 if (GetVersion() < VERSION_WIN8) |
441 return false; | 529 return false; |
442 | 530 |
443 if (IsKeyboardPresentOnSlate(nullptr)) | 531 if (IsKeyboardPresentOnSlate(nullptr)) |
444 return false; | 532 return false; |
445 | 533 |
446 static LazyInstance<string16>::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; | 534 static LazyInstance<string16>::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 snapshot->resize(num_modules + 8, NULL); | 689 snapshot->resize(num_modules + 8, NULL); |
602 } | 690 } |
603 } while (--retries_remaining); | 691 } while (--retries_remaining); |
604 | 692 |
605 DLOG(ERROR) << "Failed to enumerate modules."; | 693 DLOG(ERROR) << "Failed to enumerate modules."; |
606 return false; | 694 return false; |
607 } | 695 } |
608 | 696 |
609 } // namespace win | 697 } // namespace win |
610 } // namespace base | 698 } // namespace base |
OLD | NEW |