• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)19 void 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()55 XInputHierarchyChangedEventListener::GetInstance() {
56   return Singleton<XInputHierarchyChangedEventListener>::get();
57 }
58 
XInputHierarchyChangedEventListener()59 XInputHierarchyChangedEventListener::XInputHierarchyChangedEventListener()
60     : stopped_(false) {
61   ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
62 }
63 
~XInputHierarchyChangedEventListener()64 XInputHierarchyChangedEventListener::~XInputHierarchyChangedEventListener() {
65   Stop();
66 }
67 
Stop()68 void XInputHierarchyChangedEventListener::Stop() {
69   if (stopped_)
70     return;
71 
72   ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
73   stopped_ = true;
74 }
75 
AddObserver(DeviceHierarchyObserver * observer)76 void XInputHierarchyChangedEventListener::AddObserver(
77     DeviceHierarchyObserver* observer) {
78   observer_list_.AddObserver(observer);
79 }
80 
RemoveObserver(DeviceHierarchyObserver * observer)81 void XInputHierarchyChangedEventListener::RemoveObserver(
82     DeviceHierarchyObserver* observer) {
83   observer_list_.RemoveObserver(observer);
84 }
85 
WillProcessEvent(const ui::PlatformEvent & event)86 void XInputHierarchyChangedEventListener::WillProcessEvent(
87     const ui::PlatformEvent& event) {
88   ProcessedXEvent(event);
89 }
90 
DidProcessEvent(const ui::PlatformEvent & event)91 void XInputHierarchyChangedEventListener::DidProcessEvent(
92     const ui::PlatformEvent& event) {
93 }
94 
ProcessedXEvent(XEvent * xevent)95 void 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()109 void XInputHierarchyChangedEventListener::NotifyDeviceHierarchyChanged() {
110   FOR_EACH_OBSERVER(DeviceHierarchyObserver,
111                     observer_list_,
112                     DeviceHierarchyChanged());
113 }
114 
115 }  // namespace chromeos
116