| 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 |