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 <hstring.h> | |
9 #include <lm.h> | 10 #include <lm.h> |
10 #include <powrprof.h> | 11 #include <powrprof.h> |
11 #include <shellapi.h> | 12 #include <shellapi.h> |
12 #include <shlobj.h> | 13 #include <shlobj.h> |
13 #include <shobjidl.h> // Must be before propkey. | 14 #include <shobjidl.h> // Must be before propkey. |
14 #include <initguid.h> | 15 #include <initguid.h> |
16 #include <inspectable.h> | |
15 #include <propkey.h> | 17 #include <propkey.h> |
16 #include <propvarutil.h> | 18 #include <propvarutil.h> |
17 #include <psapi.h> | 19 #include <psapi.h> |
20 #include <roapi.h> | |
18 #include <sddl.h> | 21 #include <sddl.h> |
19 #include <setupapi.h> | 22 #include <setupapi.h> |
20 #include <signal.h> | 23 #include <signal.h> |
21 #include <stddef.h> | 24 #include <stddef.h> |
22 #include <stdlib.h> | 25 #include <stdlib.h> |
26 #include <winstring.h> | |
23 | 27 |
24 #include "base/base_switches.h" | 28 #include "base/base_switches.h" |
25 #include "base/command_line.h" | 29 #include "base/command_line.h" |
26 #include "base/lazy_instance.h" | 30 #include "base/lazy_instance.h" |
27 #include "base/logging.h" | 31 #include "base/logging.h" |
28 #include "base/macros.h" | 32 #include "base/macros.h" |
29 #include "base/memory/scoped_ptr.h" | 33 #include "base/memory/scoped_ptr.h" |
30 #include "base/strings/string_util.h" | 34 #include "base/strings/string_util.h" |
31 #include "base/strings/stringprintf.h" | 35 #include "base/strings/stringprintf.h" |
32 #include "base/strings/utf_string_conversions.h" | 36 #include "base/strings/utf_string_conversions.h" |
33 #include "base/threading/thread_restrictions.h" | 37 #include "base/threading/thread_restrictions.h" |
34 #include "base/win/registry.h" | 38 #include "base/win/registry.h" |
35 #include "base/win/scoped_co_mem.h" | 39 #include "base/win/scoped_co_mem.h" |
40 #include "base/win/scoped_comptr.h" | |
36 #include "base/win/scoped_handle.h" | 41 #include "base/win/scoped_handle.h" |
37 #include "base/win/scoped_propvariant.h" | 42 #include "base/win/scoped_propvariant.h" |
38 #include "base/win/windows_version.h" | 43 #include "base/win/windows_version.h" |
39 | 44 |
40 namespace base { | 45 namespace base { |
41 namespace win { | 46 namespace win { |
42 | 47 |
43 namespace { | 48 namespace { |
44 | 49 |
45 // Sets the value of |property_key| to |property_value| in |property_store|. | 50 // 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[] = | 105 const wchar_t kWindows8OSKRegPath[] = |
101 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" | 106 L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}" |
102 L"\\LocalServer32"; | 107 L"\\LocalServer32"; |
103 | 108 |
104 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx | 109 // Returns the current platform role. We use the PowerDeterminePlatformRoleEx |
105 // API for that. | 110 // API for that. |
106 POWER_PLATFORM_ROLE GetPlatformRole() { | 111 POWER_PLATFORM_ROLE GetPlatformRole() { |
107 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); | 112 return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); |
108 } | 113 } |
109 | 114 |
115 // Windows 10 stuff defined while we wait for Windows 10 headers. | |
116 // These definitions need to be removed once we have the new headers. | |
jschuh
2016/03/11 22:01:44
How close are we to landing the Win10 SDK? Because
Will Harris
2016/03/11 22:05:06
I thought we had landed Win10 SDK since it was nee
ananta
2016/03/11 23:14:14
Removed these definitions. Thanks to Will for lett
| |
117 namespace ABI { | |
118 namespace Windows { | |
119 namespace UI { | |
120 namespace ViewManagement { | |
121 | |
122 enum UserInteractionMode { | |
123 UserInteractionMode_Mouse = 0, | |
124 UserInteractionMode_Touch = 1 | |
125 }; | |
126 | |
127 interface __declspec(uuid("C63657F6-8850-470D-88F8-455E16EA2C26")) | |
128 IUIViewSettings : public IInspectable { | |
129 public: | |
130 virtual HRESULT STDMETHODCALLTYPE get_UserInteractionMode( | |
131 UserInteractionMode* value) = 0; | |
132 }; | |
133 | |
134 extern const __declspec(selectany) IID & IID_IUIViewSettings = | |
135 __uuidof(IUIViewSettings); | |
136 | |
137 } // namespace ViewManagement | |
138 } // namespace UI | |
139 } // namespace Windows | |
140 } // namespace ABI | |
141 | |
142 interface __declspec(uuid("3694dbf9-8f68-44be-8ff5-195c98ede8a6")) | |
143 IUIViewSettingsInterop : public IInspectable { | |
144 public: | |
145 virtual HRESULT STDMETHODCALLTYPE GetForWindow(HWND window, REFIID riid, | |
146 void** ppv) = 0; | |
147 }; | |
148 | |
149 // Uses the Windows 10 WRL API's to query the current system state. The API's | |
150 // we are using in the function below are supported in Win32 apps as per msdn. | |
151 // It looks like the API implementation is buggy at least on Surface 4 causing | |
152 // it to always return UserInteractionMode_Touch which as per documentation | |
153 // indicates tablet mode. | |
154 bool IsWindows10TabletDevice() { | |
155 if (GetVersion() < VERSION_WIN10) | |
156 return false; | |
157 | |
158 typedef HRESULT (WINAPI* GetActivationFactory)(HSTRING class_id, | |
jschuh
2016/03/11 22:01:45
ROGetActivationFactoryFunction
Will Harris
2016/03/11 22:05:06
consider using typedef decltype if the prototype i
ananta
2016/03/11 23:14:14
Thanks. Removed these
| |
159 REFIID iid, | |
160 void** factory); | |
161 | |
162 typedef HRESULT (WINAPI* CreateString)(LPCWSTR source, | |
jschuh
2016/03/11 22:01:45
WindowsCreateStringFunction
ananta
2016/03/11 23:14:14
Done
| |
163 UINT32 length, | |
164 HSTRING* target); | |
165 | |
166 static GetActivationFactory get_factory = nullptr; | |
167 static CreateString create_string = nullptr; | |
168 | |
169 if (!get_factory) { | |
170 DCHECK_EQ(create_string, static_cast<CreateString>(nullptr)); | |
171 | |
172 HMODULE combase_dll = ::LoadLibrary(L"combase.dll"); | |
173 if (!combase_dll) | |
174 return false; | |
175 | |
176 get_factory = reinterpret_cast<GetActivationFactory>( | |
177 ::GetProcAddress(combase_dll, "RoGetActivationFactory")); | |
178 if (!get_factory) { | |
179 CHECK(false); | |
180 return false; | |
181 } | |
182 | |
183 create_string = reinterpret_cast<CreateString>( | |
184 ::GetProcAddress(combase_dll, "WindowsCreateString")); | |
185 if (!create_string) { | |
186 CHECK(false); | |
187 return false; | |
188 } | |
189 } | |
190 | |
191 HRESULT hr = E_FAIL; | |
192 // This HSTRING is allocated on the heap and is leaked. | |
193 static HSTRING view_settings_guid = NULL; | |
jschuh
2016/03/11 22:01:45
Is there a race here where you could allocate the
ananta
2016/03/11 23:14:14
No. This only gets called from the UI thread
| |
194 if (!view_settings_guid) { | |
195 hr = create_string(L"Windows.UI.ViewManagement.UIViewSettings", | |
196 static_cast<UINT32>( | |
197 wcslen(L"Windows.UI.ViewManagement.UIViewSettings")), | |
jschuh
2016/03/11 22:01:45
Declare this as a static constant so you don't hav
ananta
2016/03/11 23:14:14
We use the defined constant from the include file
| |
198 &view_settings_guid); | |
199 if (FAILED(hr)) | |
200 return false; | |
201 } | |
202 | |
203 base::win::ScopedComPtr<IUIViewSettingsInterop> view_settings_interop; | |
204 hr = get_factory(view_settings_guid, | |
205 __uuidof(IUIViewSettingsInterop), | |
206 view_settings_interop.ReceiveVoid()); | |
207 if (FAILED(hr)) | |
208 return false; | |
209 | |
210 base::win::ScopedComPtr<ABI::Windows::UI::ViewManagement::IUIViewSettings> | |
211 view_settings; | |
212 // TODO(ananta) | |
213 // Avoid using GetForegroundWindow here and pass in the HWND of the window | |
214 // intiating the request to display the keyboard. | |
215 hr = view_settings_interop->GetForWindow( | |
216 ::GetForegroundWindow(), | |
217 __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings), | |
218 view_settings.ReceiveVoid()); | |
219 if (FAILED(hr)) | |
220 return false; | |
221 | |
222 ABI::Windows::UI::ViewManagement::UserInteractionMode mode = | |
223 ABI::Windows::UI::ViewManagement::UserInteractionMode_Mouse; | |
224 view_settings->get_UserInteractionMode(&mode); | |
jschuh
2016/03/11 22:01:45
Are we sure the overhead is acceptable in doing th
ananta
2016/03/11 23:14:14
There should not be much overhead here. The functi
jschuh
2016/03/11 23:50:26
Okay. It just seems like we keep piling more logic
| |
225 return mode == ABI::Windows::UI::ViewManagement::UserInteractionMode_Touch; | |
226 } | |
227 | |
110 } // namespace | 228 } // namespace |
111 | 229 |
112 // Returns true if a physical keyboard is detected on Windows 8 and up. | 230 // 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 | 231 // 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 | 232 // 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 | 233 // it won't work if there are devices which expose keyboard interfaces which |
116 // are attached to the machine. | 234 // are attached to the machine. |
117 bool IsKeyboardPresentOnSlate(std::string* reason) { | 235 bool IsKeyboardPresentOnSlate(std::string* reason) { |
118 bool result = false; | 236 bool result = false; |
119 | 237 |
(...skipping 14 matching lines...) Expand all Loading... | |
134 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) | 252 if ((GetSystemMetrics(SM_DIGITIZER) & NID_INTEGRATED_TOUCH) |
135 != NID_INTEGRATED_TOUCH) { | 253 != NID_INTEGRATED_TOUCH) { |
136 if (reason) { | 254 if (reason) { |
137 *reason += "NID_INTEGRATED_TOUCH\n"; | 255 *reason += "NID_INTEGRATED_TOUCH\n"; |
138 result = true; | 256 result = true; |
139 } else { | 257 } else { |
140 return true; | 258 return true; |
141 } | 259 } |
142 } | 260 } |
143 | 261 |
262 // If it is a tablet device we assume that there is no keyboard attached. | |
144 if (IsTabletDevice(reason)) { | 263 if (IsTabletDevice(reason)) { |
145 if (reason) | 264 if (reason) |
146 *reason += "Tablet device.\n"; | 265 *reason += "Tablet device.\n"; |
147 return true; | 266 return false; |
148 } else { | 267 } else { |
149 if (reason) { | 268 if (reason) { |
150 *reason += "Not a tablet device"; | 269 *reason += "Not a tablet device"; |
151 result = true; | 270 result = true; |
152 } else { | 271 } else { |
153 return true; | 272 return true; |
154 } | 273 } |
155 } | 274 } |
156 | 275 |
157 // To determine whether a keyboard is present on the device, we do the | 276 // 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); | 503 signal(SIGABRT, ForceCrashOnSigAbort); |
385 } | 504 } |
386 | 505 |
387 bool IsTabletDevice(std::string* reason) { | 506 bool IsTabletDevice(std::string* reason) { |
388 if (GetVersion() < VERSION_WIN8) { | 507 if (GetVersion() < VERSION_WIN8) { |
389 if (reason) | 508 if (reason) |
390 *reason = "Tablet device detection not supported below Windows 8\n"; | 509 *reason = "Tablet device detection not supported below Windows 8\n"; |
391 return false; | 510 return false; |
392 } | 511 } |
393 | 512 |
513 if (IsWindows10TabletDevice()) | |
514 return true; | |
515 | |
394 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { | 516 if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { |
395 if (reason) { | 517 if (reason) { |
396 *reason += "Device does not support touch.\n"; | 518 *reason += "Device does not support touch.\n"; |
397 } else { | 519 } else { |
398 return false; | 520 return false; |
399 } | 521 } |
400 } | 522 } |
401 | 523 |
402 // If the device is docked, the user is treating the device as a PC. | 524 // If the device is docked, the user is treating the device as a PC. |
403 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { | 525 if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) { |
404 if (reason) { | 526 if (reason) { |
405 *reason += "SM_SYSTEMDOCKED\n"; | 527 *reason += "SM_SYSTEMDOCKED\n"; |
406 } else { | 528 } else { |
407 return false; | 529 return false; |
408 } | 530 } |
409 } | 531 } |
410 | 532 |
411 // PlatformRoleSlate was added in Windows 8+. | 533 // PlatformRoleSlate was added in Windows 8+. |
412 POWER_PLATFORM_ROLE role = GetPlatformRole(); | 534 POWER_PLATFORM_ROLE role = GetPlatformRole(); |
413 bool mobile_power_profile = (role == PlatformRoleMobile); | 535 bool mobile_power_profile = (role == PlatformRoleMobile); |
414 bool slate_power_profile = (role == PlatformRoleSlate); | 536 bool slate_power_profile = (role == PlatformRoleSlate); |
415 | 537 |
416 bool is_tablet = false; | 538 bool is_tablet = false; |
417 | 539 bool is_tablet_pc = false; |
418 if (mobile_power_profile || slate_power_profile) { | 540 if (mobile_power_profile || slate_power_profile) { |
541 is_tablet_pc = !GetSystemMetrics(SM_TABLETPC); | |
419 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); | 542 is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); |
420 if (!is_tablet) { | 543 if (!is_tablet) { |
421 if (reason) { | 544 if (reason) { |
422 *reason += "Not in slate mode.\n"; | 545 *reason += "Not in slate mode.\n"; |
423 } else { | 546 } else { |
424 return false; | 547 return false; |
425 } | 548 } |
426 } else { | 549 } else { |
427 if (reason) { | 550 if (reason) { |
428 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : | 551 *reason += (role == PlatformRoleMobile) ? "PlatformRoleMobile\n" : |
429 "PlatformRoleSlate\n"; | 552 "PlatformRoleSlate\n"; |
430 } | 553 } |
431 } | 554 } |
432 } else { | 555 } else { |
433 if (reason) | 556 if (reason) |
434 *reason += "Device role is not mobile or slate.\n"; | 557 *reason += "Device role is not mobile or slate.\n"; |
435 } | 558 } |
436 return is_tablet; | 559 return is_tablet && is_tablet_pc; |
437 } | 560 } |
438 | 561 |
439 bool DisplayVirtualKeyboard() { | 562 bool DisplayVirtualKeyboard() { |
440 if (GetVersion() < VERSION_WIN8) | 563 if (GetVersion() < VERSION_WIN8) |
441 return false; | 564 return false; |
442 | 565 |
443 if (IsKeyboardPresentOnSlate(nullptr)) | 566 if (IsKeyboardPresentOnSlate(nullptr)) |
444 return false; | 567 return false; |
445 | 568 |
446 static LazyInstance<string16>::Leaky osk_path = LAZY_INSTANCE_INITIALIZER; | 569 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); | 724 snapshot->resize(num_modules + 8, NULL); |
602 } | 725 } |
603 } while (--retries_remaining); | 726 } while (--retries_remaining); |
604 | 727 |
605 DLOG(ERROR) << "Failed to enumerate modules."; | 728 DLOG(ERROR) << "Failed to enumerate modules."; |
606 return false; | 729 return false; |
607 } | 730 } |
608 | 731 |
609 } // namespace win | 732 } // namespace win |
610 } // namespace base | 733 } // namespace base |
OLD | NEW |