| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/events/devices/input_device_observer_win.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/memory/singleton.h" |
| #include "base/strings/string16.h" |
| |
| #include <windows.h> |
| |
| // This macro provides the implementation for the observer notification methods. |
| #define WIN_NOTIFY_OBSERVERS(method_decl, input_device_types) \ |
| void InputDeviceObserverWin::method_decl { \ |
| for (InputDeviceEventObserver & observer : observers_) { \ |
| observer.OnInputDeviceConfigurationChanged( \ |
| InputDeviceEventObserver::input_device_types); \ |
| } \ |
| } |
| |
| namespace ui { |
| |
| // The registry subkey that contains information about the state of the |
| // detachable/convertible laptop, it tells if the device has an accessible |
| // keyboard. OEMs are expected to follow these guidelines to report |
| // docked/undocked state |
| // https://msdn.microsoft.com/en-us/windows/hardware/commercialize/customize/desktop/unattend/microsoft-windows-gpiobuttons-convertibleslatemode |
| InputDeviceObserverWin::InputDeviceObserverWin() |
| : registry_key_(HKEY_LOCAL_MACHINE, |
| L"System\\CurrentControlSet\\Control\\PriorityControl", |
| KEY_NOTIFY | KEY_READ) { |
| if (registry_key_.Valid()) { |
| slate_mode_enabled_ = IsSlateModeEnabled(); |
| // Start watching the registry for changes. |
| registry_key_.StartWatching(base::BindOnce( |
| &InputDeviceObserverWin::OnRegistryKeyChanged, base::Unretained(this))); |
| } |
| } |
| |
| InputDeviceObserverWin* InputDeviceObserverWin::GetInstance() { |
| return base::Singleton< |
| InputDeviceObserverWin, |
| base::LeakySingletonTraits<InputDeviceObserverWin>>::get(); |
| } |
| |
| InputDeviceObserverWin::~InputDeviceObserverWin() {} |
| |
| void InputDeviceObserverWin::OnRegistryKeyChanged() { |
| // |OnRegistryKeyChanged| is removed as an observer when the ChangeCallback is |
| // called, so we need to re-register. |
| registry_key_.StartWatching(base::BindOnce( |
| &InputDeviceObserverWin::OnRegistryKeyChanged, base::Unretained(this))); |
| |
| bool new_slate_mode = IsSlateModeEnabled(); |
| if (slate_mode_enabled_ == new_slate_mode) |
| return; |
| |
| NotifyObserversTouchpadDeviceConfigurationChanged(); |
| NotifyObserversKeyboardDeviceConfigurationChanged(); |
| slate_mode_enabled_ = new_slate_mode; |
| } |
| |
| bool InputDeviceObserverWin::IsSlateModeEnabled() { |
| DCHECK(registry_key_.Valid()); |
| DWORD slate_enabled = 0; |
| return registry_key_.ReadValueDW(L"ConvertibleSlateMode", &slate_enabled) == |
| ERROR_SUCCESS && |
| slate_enabled == 1; |
| } |
| |
| void InputDeviceObserverWin::AddObserver(InputDeviceEventObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void InputDeviceObserverWin::RemoveObserver( |
| InputDeviceEventObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| WIN_NOTIFY_OBSERVERS(NotifyObserversKeyboardDeviceConfigurationChanged(), |
| kKeyboard); |
| |
| WIN_NOTIFY_OBSERVERS(NotifyObserversTouchpadDeviceConfigurationChanged(), |
| kTouchpad); |
| |
| } // namespace ui |