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