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 15namespace chromeos { 16namespace { 17 18// Checks the |event| and asynchronously sets the XKB layout when necessary. 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 54XInputHierarchyChangedEventListener* 55XInputHierarchyChangedEventListener::GetInstance() { 56 return Singleton<XInputHierarchyChangedEventListener>::get(); 57} 58 59XInputHierarchyChangedEventListener::XInputHierarchyChangedEventListener() 60 : stopped_(false) { 61 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); 62} 63 64XInputHierarchyChangedEventListener::~XInputHierarchyChangedEventListener() { 65 Stop(); 66} 67 68void XInputHierarchyChangedEventListener::Stop() { 69 if (stopped_) 70 return; 71 72 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this); 73 stopped_ = true; 74} 75 76void XInputHierarchyChangedEventListener::AddObserver( 77 DeviceHierarchyObserver* observer) { 78 observer_list_.AddObserver(observer); 79} 80 81void XInputHierarchyChangedEventListener::RemoveObserver( 82 DeviceHierarchyObserver* observer) { 83 observer_list_.RemoveObserver(observer); 84} 85 86void XInputHierarchyChangedEventListener::WillProcessEvent( 87 const ui::PlatformEvent& event) { 88 ProcessedXEvent(event); 89} 90 91void XInputHierarchyChangedEventListener::DidProcessEvent( 92 const ui::PlatformEvent& event) { 93} 94 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 109void XInputHierarchyChangedEventListener::NotifyDeviceHierarchyChanged() { 110 FOR_EACH_OBSERVER(DeviceHierarchyObserver, 111 observer_list_, 112 DeviceHierarchyChanged()); 113} 114 115} // namespace chromeos 116