diff options
author | davej@chromium.org <davej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-02 02:06:06 +0000 |
---|---|---|
committer | davej@chromium.org <davej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-02 02:06:06 +0000 |
commit | 3d962bbcd4148cf258c5dfdcb324b59f5ec8291b (patch) | |
tree | a5dd318c25b14ca943e69599e4a310fa0de614f5 | |
parent | b2e4296c6bfac676bc886594054d8eb7388349a5 (diff) | |
download | chromium_src-3d962bbcd4148cf258c5dfdcb324b59f5ec8291b.zip chromium_src-3d962bbcd4148cf258c5dfdcb324b59f5ec8291b.tar.gz chromium_src-3d962bbcd4148cf258c5dfdcb324b59f5ec8291b.tar.bz2 |
Volume Up/Down/Mute are handled within Chrome itself, without depending on Window Manager. The SystemKeyEventListener keyboard filter is instantiated in screen_locker as well as browser_init, so these keys will be handled at the screen lock and when logged in.
The on-screen UI is shown when logged in, but currently is not being allowed to show at screen lock. (A screen lock can be forced with /usr/bin/powerd_lock_screen).
After this patch, keyboard handling within Chrome supersedes the key handling in window_manager.cc, and so that functionality can safely be removed (http://codereview.chromium.org/4159004) and chromeos_wm_ipc_enums.h (http://codereview.chromium.org/4172004).
BUG=chromium-os:6074
TEST=Volume Up/Down and Mute keys should work when screen is locked and when logged in normally.
Review URL: http://codereview.chromium.org/4098003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64709 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/browser_init.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/screen_locker.cc | 5 | ||||
-rw-r--r-- | chrome/browser/chromeos/system_key_event_listener.cc | 121 | ||||
-rw-r--r-- | chrome/browser/chromeos/system_key_event_listener.h | 37 |
4 files changed, 122 insertions, 49 deletions
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index c1ab3a9..228f092 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -403,6 +403,10 @@ bool BrowserInit::LaunchBrowser(const CommandLine& command_line, // of what window has focus. chromeos::WmMessageListener::instance(); + // Create the SystemKeyEventListener so it can listen for system keyboard + // messages regardless of focus. + chromeos::SystemKeyEventListener::instance(); + // Create the WmOverviewController so it can register with the listener. chromeos::WmOverviewController::instance(); @@ -441,10 +445,6 @@ bool BrowserInit::LaunchBrowser(const CommandLine& command_line, chromeos::CrosLibrary::Get()->GetNetworkLibrary()->AddObserver( chromeos::NetworkStateNotifier::Get()); - - // Creates the SystemKeyEventListener to listen for keypress messages - // regardless of what window has focus. - chromeos::SystemKeyEventListener::instance(); } #endif return true; diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc index 92bafc8..7b4d6b5 100644 --- a/chrome/browser/chromeos/login/screen_locker.cc +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -31,6 +31,7 @@ #include "chrome/browser/chromeos/login/message_bubble.h" #include "chrome/browser/chromeos/login/screen_lock_view.h" #include "chrome/browser/chromeos/login/shutdown_button.h" +#include "chrome/browser/chromeos/system_key_event_listener.h" #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/common/chrome_switches.h" @@ -610,6 +611,10 @@ void ScreenLocker::Init() { gdk_window_set_back_pixmap(lock_widget_->GetNativeView()->window, NULL, false); lock_window->set_toplevel_focus_widget(lock_widget_->window_contents()); + + // Create the SystemKeyEventListener so it can listen for system keyboard + // messages regardless of focus while screen locked. + SystemKeyEventListener::instance(); } void ScreenLocker::OnLoginFailure(const LoginFailure& error) { diff --git a/chrome/browser/chromeos/system_key_event_listener.cc b/chrome/browser/chromeos/system_key_event_listener.cc index 21f28f2..f6baaf7 100644 --- a/chrome/browser/chromeos/system_key_event_listener.cc +++ b/chrome/browser/chromeos/system_key_event_listener.cc @@ -4,9 +4,11 @@ #include "chrome/browser/chromeos/system_key_event_listener.h" +#include <gdk/gdkx.h> +#include <X11/XF86keysym.h> + #include "chrome/browser/chromeos/audio_handler.h" #include "chrome/browser/chromeos/volume_bubble.h" -#include "cros/chromeos_wm_ipc_enums.h" namespace chromeos { @@ -23,11 +25,68 @@ SystemKeyEventListener* SystemKeyEventListener::instance() { SystemKeyEventListener::SystemKeyEventListener() : audio_handler_(AudioHandler::instance()) { - WmMessageListener::instance()->AddObserver(this); + key_volume_mute_ = XKeysymToKeycode(GDK_DISPLAY(), XF86XK_AudioMute); + key_volume_down_ = XKeysymToKeycode(GDK_DISPLAY(), XF86XK_AudioLowerVolume); + key_volume_up_ = XKeysymToKeycode(GDK_DISPLAY(), XF86XK_AudioRaiseVolume); + key_f8_ = XKeysymToKeycode(GDK_DISPLAY(), XK_F8); + key_f9_ = XKeysymToKeycode(GDK_DISPLAY(), XK_F9); + key_f10_ = XKeysymToKeycode(GDK_DISPLAY(), XK_F10); + + if (key_volume_mute_) + GrabKey(key_volume_mute_, 0); + if (key_volume_down_) + GrabKey(key_volume_down_, 0); + if (key_volume_up_) + GrabKey(key_volume_up_, 0); + GrabKey(key_f8_, 0); + GrabKey(key_f9_, 0); + GrabKey(key_f10_, 0); + gdk_window_add_filter(NULL, GdkEventFilter, this); } SystemKeyEventListener::~SystemKeyEventListener() { - WmMessageListener::instance()->RemoveObserver(this); + gdk_window_remove_filter(NULL, GdkEventFilter, this); +} + +// static +GdkFilterReturn SystemKeyEventListener::GdkEventFilter(GdkXEvent* gxevent, + GdkEvent* gevent, + gpointer data) { + SystemKeyEventListener* listener = static_cast<SystemKeyEventListener*>(data); + XEvent* xevent = static_cast<XEvent*>(gxevent); + + if (xevent->type == KeyPress) { + int32 keycode = xevent->xkey.keycode; + if (keycode) { + if ((keycode == listener->key_f8_) || + (keycode == listener->key_volume_mute_)) { + listener->OnVolumeMute(); + return GDK_FILTER_REMOVE; + } else if ((keycode == listener->key_f9_) || + keycode == listener->key_volume_down_) { + listener->OnVolumeDown(); + return GDK_FILTER_REMOVE; + } else if ((keycode == listener->key_f10_) || + (keycode == listener->key_volume_up_)) { + listener->OnVolumeUp(); + return GDK_FILTER_REMOVE; + } + } + } + return GDK_FILTER_CONTINUE; +} + +void SystemKeyEventListener::GrabKey(int32 key, uint32 mask) { + uint32 num_lock_mask = Mod2Mask; + uint32 caps_lock_mask = LockMask; + Window root = DefaultRootWindow(GDK_DISPLAY()); + XGrabKey(GDK_DISPLAY(), key, mask, root, True, GrabModeAsync, GrabModeAsync); + XGrabKey(GDK_DISPLAY(), key, mask | caps_lock_mask, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(GDK_DISPLAY(), key, mask | num_lock_mask, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(GDK_DISPLAY(), key, mask | caps_lock_mask | num_lock_mask, root, + True, GrabModeAsync, GrabModeAsync); } // TODO(davej): Move the ShowVolumeBubble() calls in to AudioHandler so that @@ -38,40 +97,30 @@ SystemKeyEventListener::~SystemKeyEventListener() { // to an AdjustVolumeByPercentOrUnmute() function which can do the steps off // of this thread when ShowVolumeBubble() is moved in to AudioHandler. -void SystemKeyEventListener::ProcessWmMessage(const WmIpc::Message& message, - GdkWindow* window) { - if (message.type() != WM_IPC_MESSAGE_CHROME_NOTIFY_SYSKEY_PRESSED) - return; - - switch (message.param(0)) { - case WM_IPC_SYSTEM_KEY_VOLUME_MUTE: - // Always muting (and not toggling) as per final decision on - // http://crosbug.com/3751 - audio_handler_->SetMute(true); - VolumeBubble::instance()->ShowVolumeBubble(0); - break; - case WM_IPC_SYSTEM_KEY_VOLUME_DOWN: - if (audio_handler_->IsMute()) { - VolumeBubble::instance()->ShowVolumeBubble(0); - } else { - audio_handler_->AdjustVolumeByPercent(-kStepPercentage); - VolumeBubble::instance()->ShowVolumeBubble( - audio_handler_->GetVolumePercent()); - } - break; - case WM_IPC_SYSTEM_KEY_VOLUME_UP: - if (audio_handler_->IsMute()) - audio_handler_->SetMute(false); - else - audio_handler_->AdjustVolumeByPercent(kStepPercentage); - VolumeBubble::instance()->ShowVolumeBubble( - audio_handler_->GetVolumePercent()); - break; - default: - DLOG(ERROR) << "SystemKeyEventListener: Unexpected message " - << message.param(0) - << " received"; +void SystemKeyEventListener::OnVolumeMute() { + // Always muting (and not toggling) as per final decision on + // http://crosbug.com/3751 + audio_handler_->SetMute(true); + VolumeBubble::instance()->ShowVolumeBubble(0); +} + +void SystemKeyEventListener::OnVolumeDown() { + if (audio_handler_->IsMute()) { + VolumeBubble::instance()->ShowVolumeBubble(0); + } else { + audio_handler_->AdjustVolumeByPercent(-kStepPercentage); + VolumeBubble::instance()->ShowVolumeBubble( + audio_handler_->GetVolumePercent()); } } +void SystemKeyEventListener::OnVolumeUp() { + if (audio_handler_->IsMute()) + audio_handler_->SetMute(false); + else + audio_handler_->AdjustVolumeByPercent(kStepPercentage); + VolumeBubble::instance()->ShowVolumeBubble( + audio_handler_->GetVolumePercent()); +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/system_key_event_listener.h b/chrome/browser/chromeos/system_key_event_listener.h index b731b94..fac1665 100644 --- a/chrome/browser/chromeos/system_key_event_listener.h +++ b/chrome/browser/chromeos/system_key_event_listener.h @@ -6,25 +6,22 @@ #define CHROME_BROWSER_CHROMEOS_SYSTEM_KEY_EVENT_LISTENER_H_ #pragma once +#include <gdk/gdk.h> + #include "base/singleton.h" -#include "chrome/browser/chromeos/wm_message_listener.h" namespace chromeos { class AudioHandler; -// SystemKeyEventListener listens for volume related key presses from the -// window manager, then tells the AudioHandler to adjust volume accordingly. -// Start by just calling instance() to get it going. +// SystemKeyEventListener listens for volume related key presses from GDK, then +// tells the AudioHandler to adjust volume accordingly. Start by just calling +// instance() to get it going. -class SystemKeyEventListener : public WmMessageListener::Observer { +class SystemKeyEventListener { public: static SystemKeyEventListener* instance(); - // WmMessageListener::Observer: - virtual void ProcessWmMessage(const WmIpc::Message& message, - GdkWindow* window); - private: // Defines the delete on exit Singleton traits we like. Best to have this // and const/dest private as recommended for Singletons. @@ -33,6 +30,28 @@ class SystemKeyEventListener : public WmMessageListener::Observer { SystemKeyEventListener(); virtual ~SystemKeyEventListener(); + // This event filter intercepts events before they reach GDK, allowing us to + // check for system level keyboard events regardless of which window has + // focus. + static GdkFilterReturn GdkEventFilter(GdkXEvent* gxevent, + GdkEvent* gevent, + gpointer data); + + // Tell X we are interested in the specified key/mask combination. + // Capslock and Numlock are always ignored. + void GrabKey(int32 key, uint32 mask); + + void OnVolumeMute(); + void OnVolumeDown(); + void OnVolumeUp(); + + int32 key_volume_mute_; + int32 key_volume_down_; + int32 key_volume_up_; + int32 key_f8_; + int32 key_f9_; + int32 key_f10_; + // AudioHandler is a Singleton class we are just caching a pointer to here, // and we do not own the pointer. AudioHandler* const audio_handler_; |