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/system_key_event_listener.h" 6 7 #define XK_MISCELLANY 1 8 #include <X11/keysymdef.h> 9 #include <X11/XF86keysym.h> 10 #include <X11/XKBlib.h> 11 #undef Status 12 13 #include "chromeos/ime/ime_keyboard.h" 14 #include "chromeos/ime/input_method_manager.h" 15 #include "ui/base/x/x11_util.h" 16 #include "ui/events/platform/platform_event_source.h" 17 18 namespace chromeos { 19 20 namespace { 21 static SystemKeyEventListener* g_system_key_event_listener = NULL; 22 } // namespace 23 24 // static 25 void SystemKeyEventListener::Initialize() { 26 CHECK(!g_system_key_event_listener); 27 g_system_key_event_listener = new SystemKeyEventListener(); 28 } 29 30 // static 31 void SystemKeyEventListener::Shutdown() { 32 // We may call Shutdown without calling Initialize, e.g. if we exit early. 33 if (g_system_key_event_listener) { 34 delete g_system_key_event_listener; 35 g_system_key_event_listener = NULL; 36 } 37 } 38 39 // static 40 SystemKeyEventListener* SystemKeyEventListener::GetInstance() { 41 return g_system_key_event_listener; 42 } 43 44 SystemKeyEventListener::SystemKeyEventListener() 45 : stopped_(false), 46 xkb_event_base_(0) { 47 XDisplay* display = gfx::GetXDisplay(); 48 int xkb_major_version = XkbMajorVersion; 49 int xkb_minor_version = XkbMinorVersion; 50 if (!XkbQueryExtension(display, 51 NULL, // opcode_return 52 &xkb_event_base_, 53 NULL, // error_return 54 &xkb_major_version, 55 &xkb_minor_version)) { 56 LOG(WARNING) << "Could not query Xkb extension"; 57 } 58 59 if (!XkbSelectEvents(display, XkbUseCoreKbd, 60 XkbStateNotifyMask, 61 XkbStateNotifyMask)) { 62 LOG(WARNING) << "Could not install Xkb Indicator observer"; 63 } 64 65 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); 66 } 67 68 SystemKeyEventListener::~SystemKeyEventListener() { 69 Stop(); 70 } 71 72 void SystemKeyEventListener::Stop() { 73 if (stopped_) 74 return; 75 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this); 76 stopped_ = true; 77 } 78 79 void SystemKeyEventListener::WillProcessEvent(const base::NativeEvent& event) { 80 ProcessedXEvent(event); 81 } 82 83 void SystemKeyEventListener::DidProcessEvent(const base::NativeEvent& event) { 84 } 85 86 void SystemKeyEventListener::ProcessedXEvent(XEvent* xevent) { 87 input_method::InputMethodManager* input_method_manager = 88 input_method::InputMethodManager::Get(); 89 90 if (xevent->type == xkb_event_base_) { 91 // TODO(yusukes): Move this part to aura::WindowTreeHost. 92 XkbEvent* xkey_event = reinterpret_cast<XkbEvent*>(xevent); 93 if (xkey_event->any.xkb_type == XkbStateNotify) { 94 if (xkey_event->state.mods) { 95 // TODO(yusukes,adlr): Let the user know that num lock is unsupported. 96 // Force turning off Num Lock (crosbug.com/29169) 97 input_method_manager->GetImeKeyboard()->DisableNumLock(); 98 } 99 } 100 } 101 } 102 103 } // namespace chromeos 104