summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavej@chromium.org <davej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 01:05:37 +0000
committerdavej@chromium.org <davej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 01:05:37 +0000
commitdac8d58753088854bc020e0971697d2e6d458093 (patch)
tree1bccff912e66b8ba83b474c07c47a30a73c03279
parent4cbe2befd53a4183b69cf6295e4afd5fa09fe07e (diff)
downloadchromium_src-dac8d58753088854bc020e0971697d2e6d458093.zip
chromium_src-dac8d58753088854bc020e0971697d2e6d458093.tar.gz
chromium_src-dac8d58753088854bc020e0971697d2e6d458093.tar.bz2
Merge 64709 - 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 TBR=davej@chromium.org Review URL: http://codereview.chromium.org/4334002 git-svn-id: svn://svn.chromium.org/chrome/branches/552/src@64857 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser_init.cc8
-rw-r--r--chrome/browser/chromeos/login/screen_locker.cc5
-rw-r--r--chrome/browser/chromeos/system_key_event_listener.cc121
-rw-r--r--chrome/browser/chromeos/system_key_event_listener.h37
4 files changed, 122 insertions, 49 deletions
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index c503ab9..9c0d868 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -402,6 +402,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();
@@ -440,10 +444,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 0ccc06e..0199da7 100644
--- a/chrome/browser/chromeos/login/screen_locker.cc
+++ b/chrome/browser/chromeos/login/screen_locker.cc
@@ -30,6 +30,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"
@@ -608,6 +609,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_;