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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/events/xinput_hierarchy_changed_event_listener.h" 6 7 #include <X11/extensions/XInput2.h> 8 #include <X11/Xlib.h> 9 10 #include "chromeos/ime/ime_keyboard.h" 11 #include "chromeos/ime/input_method_manager.h" 12 #include "ui/base/x/x11_util.h" 13 #include "ui/events/platform/platform_event_source.h" 14 15 namespace chromeos { 16 namespace { 17 18 // Checks the |event| and asynchronously sets the XKB layout when necessary. HandleHierarchyChangedEvent(XIHierarchyEvent * event,ObserverList<DeviceHierarchyObserver> * observer_list)19void HandleHierarchyChangedEvent( 20 XIHierarchyEvent* event, 21 ObserverList<DeviceHierarchyObserver>* observer_list) { 22 if (!(event->flags & (XISlaveAdded | XISlaveRemoved))) 23 return; 24 25 bool update_keyboard_status = false; 26 for (int i = 0; i < event->num_info; ++i) { 27 XIHierarchyInfo* info = &event->info[i]; 28 if ((info->flags & XISlaveAdded) && (info->use == XIFloatingSlave)) { 29 FOR_EACH_OBSERVER(DeviceHierarchyObserver, 30 *observer_list, 31 DeviceAdded(info->deviceid)); 32 update_keyboard_status = true; 33 } else if (info->flags & XISlaveRemoved) { 34 // Can't check info->use here; it appears to always be 0. 35 FOR_EACH_OBSERVER(DeviceHierarchyObserver, 36 *observer_list, 37 DeviceRemoved(info->deviceid)); 38 } 39 } 40 41 if (update_keyboard_status) { 42 chromeos::input_method::InputMethodManager* input_method_manager = 43 chromeos::input_method::InputMethodManager::Get(); 44 chromeos::input_method::ImeKeyboard* keyboard = 45 input_method_manager->GetImeKeyboard(); 46 keyboard->ReapplyCurrentModifierLockStatus(); 47 keyboard->ReapplyCurrentKeyboardLayout(); 48 } 49 } 50 51 } // namespace 52 53 // static 54 XInputHierarchyChangedEventListener* GetInstance()55XInputHierarchyChangedEventListener::GetInstance() { 56 return Singleton<XInputHierarchyChangedEventListener>::get(); 57 } 58 XInputHierarchyChangedEventListener()59XInputHierarchyChangedEventListener::XInputHierarchyChangedEventListener() 60 : stopped_(false) { 61 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); 62 } 63 ~XInputHierarchyChangedEventListener()64XInputHierarchyChangedEventListener::~XInputHierarchyChangedEventListener() { 65 Stop(); 66 } 67 Stop()68void XInputHierarchyChangedEventListener::Stop() { 69 if (stopped_) 70 return; 71 72 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this); 73 stopped_ = true; 74 } 75 AddObserver(DeviceHierarchyObserver * observer)76void XInputHierarchyChangedEventListener::AddObserver( 77 DeviceHierarchyObserver* observer) { 78 observer_list_.AddObserver(observer); 79 } 80 RemoveObserver(DeviceHierarchyObserver * observer)81void XInputHierarchyChangedEventListener::RemoveObserver( 82 DeviceHierarchyObserver* observer) { 83 observer_list_.RemoveObserver(observer); 84 } 85 WillProcessEvent(const ui::PlatformEvent & event)86void XInputHierarchyChangedEventListener::WillProcessEvent( 87 const ui::PlatformEvent& event) { 88 ProcessedXEvent(event); 89 } 90 DidProcessEvent(const ui::PlatformEvent & event)91void XInputHierarchyChangedEventListener::DidProcessEvent( 92 const ui::PlatformEvent& event) { 93 } 94 ProcessedXEvent(XEvent * xevent)95void XInputHierarchyChangedEventListener::ProcessedXEvent(XEvent* xevent) { 96 if (xevent->xcookie.type != GenericEvent) 97 return; 98 99 XGenericEventCookie* cookie = &(xevent->xcookie); 100 101 if (cookie->evtype == XI_HierarchyChanged) { 102 XIHierarchyEvent* event = static_cast<XIHierarchyEvent*>(cookie->data); 103 HandleHierarchyChangedEvent(event, &observer_list_); 104 if (event->flags & XIDeviceEnabled || event->flags & XIDeviceDisabled) 105 NotifyDeviceHierarchyChanged(); 106 } 107 } 108 NotifyDeviceHierarchyChanged()109void XInputHierarchyChangedEventListener::NotifyDeviceHierarchyChanged() { 110 FOR_EACH_OBSERVER(DeviceHierarchyObserver, 111 observer_list_, 112 DeviceHierarchyChanged()); 113 } 114 115 } // namespace chromeos 116