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> |
| 18 #include <psapi.h> |
| 19 #include <roapi.h> |
17 #include <sddl.h> | 20 #include <sddl.h> |
18 #include <setupapi.h> | 21 #include <setupapi.h> |
19 #include <signal.h> | 22 #include <signal.h> |
20 #include <stddef.h> | 23 #include <stddef.h> |
21 #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> |
22 | 29 |
23 #include "base/base_switches.h" | 30 #include "base/base_switches.h" |
24 #include "base/command_line.h" | 31 #include "base/command_line.h" |
25 #include "base/lazy_instance.h" | 32 #include "base/lazy_instance.h" |
26 #include "base/logging.h" | 33 #include "base/logging.h" |
27 #include "base/macros.h" | 34 #include "base/macros.h" |
28 #include "base/memory/scoped_ptr.h" | 35 #include "base/memory/scoped_ptr.h" |
29 #include "base/strings/string_util.h" | 36 #include "base/strings/string_util.h" |
30 #include "base/strings/stringprintf.h" | 37 #include "base/strings/stringprintf.h" |
31 #include "base/strings/utf_string_conversions.h" | 38 #include "base/strings/utf_string_conversions.h" |
32 #include "base/threading/thread_restrictions.h" | 39 #include "base/threading/thread_restrictions.h" |
33 #include "base/win/registry.h" | 40 #include "base/win/registry.h" |
34 #include "base/win/scoped_co_mem.h" | 41 #include "base/win/scoped_co_mem.h" |
| 42 #include "base/win/scoped_comptr.h" |
35 #include "base/win/scoped_handle.h" | 43 #include "base/win/scoped_handle.h" |
36 #include "base/win/scoped_propvariant.h" | 44 #include "base/win/scoped_propvariant.h" |
37 #include "base/win/windows_version.h" | 45 #include "base/win/windows_version.h" |
38 | 46 |
39 namespace base { | 47 namespace base { |
40 namespace win { | 48 namespace win { |
41 | 49 |
42 namespace { | 50 namespace { |
43 | 51 |
44 // 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... |
99 const wchar_t kWindows8OSKRegPath[] = | 107 const wchar_t kWindows8OSKRegPath[] = |
100 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" | 108 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" |
101 L"\\LocalServer32"; | 109 L"\\LocalServer32"; |
102 | 110 |
103 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx | 111 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx |
104 // API for that. | 112 // API for that. |
105 POWER_PLATFORM_ROLE GetPlatformRole() { | 113 POWER_PLATFORM_ROLE GetPlatformRole() { |
106 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); | 114 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); |
107 } | 115 } |
108 | 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 |
109 } // namespace | 193 } // namespace |
110 | 194 |
111 // 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. |
112 // 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 |
113 // 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 |
114 // 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 |
115 // are attached to the machine. | 199 // are attached to the machine. |
116 bool IsKeyboardPresentOnSlate(std::string* reason) { | 200 bool IsKeyboardPresentOnSlate(std::string* reason) { |
117 bool result = false; | 201 bool result = false; |
118 | 202 |
(...skipping 14 matching lines...) Expand all Loading... |
133 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) | 217 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) |
134 != NID_INTEGRATED_TOUCH) { | 218 != NID_INTEGRATED_TOUCH) { |
135 if (reason) { | 219 if (reason) { |
136 *reason += "NID_INTEGRATED_TOUCH\n"; | 220 *reason += "NID_INTEGRATED_TOUCH\n"; |
137 result = true; | 221 result = true; |
138 } else { | 222 } else { |
139 return true; | 223 return true; |
140 } | 224 } |
141 } | 225 } |
142 | 226 |
| 227 // If it is a tablet device we assume that there is no keyboard attached. |
143 if (IsTabletDevice(reason)) { | 228 if (IsTabletDevice(reason)) { |
144 if (reason) | 229 if (reason) |
145 *reason += "Tablet device.\n"; | 230 *reason += "Tablet device.\n"; |
146 return true; | 231 return false; |
147 } else { | 232 } else { |
148 if (reason) { | 233 if (reason) { |
149 *reason += "Not a tablet device"; | 234 *reason += "Not a tablet device"; |
150 result = true; | 235 result = true; |
151 } else { | 236 } else { |
152 return true; | 237 return true; |
153 } | 238 } |
154 } | 239 } |
155 | 240 |
156 // 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... |
383 signal(SIGABRT, ForceCrashOnSigAbort); | 468 signal(SIGABRT, ForceCrashOnSigAbort); |
384 } | 469 } |
385 | 470 |
386 bool IsTabletDevice(std::string* reason) { | 471 bool IsTabletDevice(std::string* reason) { |
387 if (GetVersion() < VERSION_WIN8) { | 472 if (GetVersion() < VERSION_WIN8) { |
388 if (reason) | 473 if (reason) |
389 *reason = "Tablet device detection not supported below Windows 8\n"; | 474 *reason = "Tablet device detection not supported below Windows 8\n"; |
390 return false; | 475 return false; |
391 } | 476 } |
392 | 477 |
| 478 if (IsWindows10TabletDevice()) |
| 479 return true; |
| 480 |
393 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { | 481 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { |
394 if (reason) { | 482 if (reason) { |
395 *reason += "Device does not support touch.\n"; | 483 *reason += "Device does not support touch.\n"; |
396 } else { | 484 } else { |
397 return false; | 485 return false; |
398 } | 486 } |
399 } | 487 } |
400 | 488 |
401 // 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. |
402 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { | 490 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { |
403 if (reason) { | 491 if (reason) { |
404 *reason += "SM_SYSTEMDOCKED\n"; | 492 *reason += "SM_SYSTEMDOCKED\n"; |
405 } else { | 493 } else { |
406 return false; | 494 return false; |
407 } | 495 } |
408 } | 496 } |
409 | 497 |
410 // PlatformRoleSlate was added in Windows 8+. | 498 // PlatformRoleSlate was added in Windows 8+. |
411 POWER_PLATFORM_ROLE role = GetPlatformRole(); | 499 POWER_PLATFORM_ROLE role = GetPlatformRole(); |
412 bool mobile_power_profile = (role == PlatformRoleMobile); | 500 bool mobile_power_profile = (role == PlatformRoleMobile); |
413 bool slate_power_profile = (role == PlatformRoleSlate); | 501 bool slate_power_profile = (role == PlatformRoleSlate); |
414 | 502 |
415 bool is_tablet = false; | 503 bool is_tablet = false; |
416 | 504 bool is_tablet_pc = false; |
417 if (mobile_power_profile || slate_power_profile) { | 505 if (mobile_power_profile || slate_power_profile) { |
| 506 is_tablet_pc = !GetSystemMetrics(SM_TABLETPC); |
418 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); | 507 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); |
419 if (!is_tablet) { | 508 if (!is_tablet) { |
420 if (reason) { | 509 if (reason) { |
421 *reason += "Not in slate mode.\n"; | 510 *reason += "Not in slate mode.\n"; |
422 } else { | 511 } else { |
423 return false; | 512 return false; |
424 } | 513 } |
425 } else { | 514 } else { |
426 if (reason) { | 515 if (reason) { |
427 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : | 516 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : |
428 "PlatformRoleSlate\n"; | 517 "PlatformRoleSlate\n"; |
429 } | 518 } |
430 } | 519 } |
431 } else { | 520 } else { |
432 if (reason) | 521 if (reason) |
433 *reason += "Device role is not mobile or slate.\n"; | 522 *reason += "Device role is not mobile or slate.\n"; |
434 } | 523 } |
435 return is_tablet; | 524 return is_tablet && is_tablet_pc; |
436 } | 525 } |
437 | 526 |
438 bool DisplayVirtualKeyboard() { | 527 bool DisplayVirtualKeyboard() { |
439 if (GetVersion() < VERSION_WIN8) | 528 if (GetVersion() < VERSION_WIN8) |
440 return false; | 529 return false; |
441 | 530 |
442 if (IsKeyboardPresentOnSlate(nullptr)) | 531 if (IsKeyboardPresentOnSlate(nullptr)) |
443 return false; | 532 return false; |
444 | 533 |
445 static LazyInstance<string16>::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; | 534 static LazyInstance<string16>::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 } | 665 } |
577 | 666 |
578 bool IsUser32AndGdi32Available() { | 667 bool IsUser32AndGdi32Available() { |
579 static base::LazyInstance<LazyIsUser32AndGdi32Available>::Leaky available = | 668 static base::LazyInstance<LazyIsUser32AndGdi32Available>::Leaky available = |
580 LAZY_INSTANCE_INITIALIZER; | 669 LAZY_INSTANCE_INITIALIZER; |
581 return available.Get().value(); | 670 return available.Get().value(); |
582 } | 671 } |
583 | 672 |
584 } // namespace win | 673 } // namespace win |
585 } // namespace base | 674 } // namespace base |
OLD | NEW |