diff options
-rw-r--r-- | chrome/browser/chromeos/login/screen_lock_view.cc | 29 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/screen_locker.cc | 50 | ||||
-rw-r--r-- | views/focus/focus_manager_gtk.cc | 10 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 9 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 3 |
5 files changed, 87 insertions, 14 deletions
diff --git a/chrome/browser/chromeos/login/screen_lock_view.cc b/chrome/browser/chromeos/login/screen_lock_view.cc index 3c879d7..c554f30 100644 --- a/chrome/browser/chromeos/login/screen_lock_view.cc +++ b/chrome/browser/chromeos/login/screen_lock_view.cc @@ -23,6 +23,31 @@ namespace chromeos { +namespace { + +// A Textfield for password, which also sets focus to itself +// when a mouse is clicked on it. This is necessary in screen locker +// as mouse events are grabbed in the screen locker. +class PasswordField : public views::Textfield { + public: + PasswordField() + : views::Textfield(views::Textfield::STYLE_PASSWORD) { + set_text_to_display_when_empty( + l10n_util::GetStringUTF16(IDS_LOGIN_EMPTY_PASSWORD_TEXT)); + } + + // views::View overrides. + virtual bool OnMousePressed(const views::MouseEvent& e) { + RequestFocus(); + return false; + } + + private: + DISALLOW_COPY_AND_ASSIGN(PasswordField); +}; + +} // namespace + using views::GridLayout; using login::kBorderSize; @@ -45,9 +70,7 @@ void ScreenLockView::Init() { views::Background::CreateSolidBackground(login::kBackgroundColor)); // Password field. - password_field_ = new views::Textfield(views::Textfield::STYLE_PASSWORD); - password_field_->set_text_to_display_when_empty( - l10n_util::GetStringUTF16(IDS_LOGIN_EMPTY_PASSWORD_TEXT)); + password_field_ = new PasswordField(); password_field_->SetController(this); // Unlock button. diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc index 1ea943a..e8d156a 100644 --- a/chrome/browser/chromeos/login/screen_locker.cc +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -145,6 +145,50 @@ class ScreenLockObserver : public chromeos::ScreenLockLibrary::Observer, DISALLOW_COPY_AND_ASSIGN(ScreenLockObserver); }; +// A ScreenLock window that covers entire screen to keeps the keyboard +// focus/events inside the grab widget. +class LockWindow : public views::WidgetGtk { + public: + LockWindow() + : WidgetGtk(views::WidgetGtk::TYPE_POPUP), + toplevel_focus_widget_(NULL) { + } + + // GTK propagates key events from parents to children. + // Make sure LockWindow will never handle key events. + virtual gboolean OnKeyPress(GtkWidget* widget, GdkEventKey* event) { + // Don't handle key event in the lock window. + return false; + } + + virtual gboolean OnKeyRelease(GtkWidget* widget, GdkEventKey* event) { + // Don't handle key event in the lock window. + return false; + } + + virtual void ClearNativeFocus() { + DCHECK(toplevel_focus_widget_); + gtk_widget_grab_focus(toplevel_focus_widget_); + } + + // Sets the widget to move the focus to when clearning the native + // widget's focus. + void set_toplevel_focus_widget(GtkWidget* widget) { + GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS); + toplevel_focus_widget_ = widget; + } + + private: + // The widget we set focus to when clearning the focus on native + // widget. In screen locker, gdk input is grabbed in GrabWidget, + // and resetting the focus by using gtk_window_set_focus seems to + // confuse gtk and doesn't let focus move to native widget under + // GrabWidget. + GtkWidget* toplevel_focus_widget_; + + DISALLOW_COPY_AND_ASSIGN(LockWindow); +}; + // A child widget that grabs both keyboard and pointer input. // TODO(oshima): catch grab-broke event and quit if it ever happenes. class GrabWidget : public views::WidgetGtk { @@ -352,7 +396,8 @@ ScreenLocker::ScreenLocker(const UserManager::User& user) void ScreenLocker::Init(const gfx::Rect& bounds) { // TODO(oshima): Figure out which UI to keep and remove in the background. views::View* screen = new BackgroundView(); - lock_window_ = new views::WidgetGtk(views::WidgetGtk::TYPE_POPUP); + LockWindow* lock_window = new LockWindow(); + lock_window_ = lock_window; lock_window_->Init(NULL, bounds); g_signal_connect(lock_window_->GetNativeView(), "map-event", @@ -383,7 +428,7 @@ void ScreenLocker::Init(const gfx::Rect& bounds) { lock_widget_->MakeTransparent(); lock_widget_->InitWithWidget(lock_window_, gfx::Rect((bounds.width() - size.width()) / 2, - (bounds.height() - size.width()) / 2, + (bounds.height() - size.height()) / 2, size.width(), size.height())); if (screen_lock_view_) @@ -397,6 +442,7 @@ void ScreenLocker::Init(const gfx::Rect& bounds) { NULL, false); gdk_window_set_back_pixmap(lock_widget_->GetNativeView()->window, NULL, false); + lock_window->set_toplevel_focus_widget(lock_widget_->window_contents()); } void ScreenLocker::OnLoginFailure(const std::string& error) { diff --git a/views/focus/focus_manager_gtk.cc b/views/focus/focus_manager_gtk.cc index a52a6d9..6e9dbcf 100644 --- a/views/focus/focus_manager_gtk.cc +++ b/views/focus/focus_manager_gtk.cc @@ -13,15 +13,7 @@ namespace views { void FocusManager::ClearNativeFocus() { - GtkWidget* gtk_widget = widget_->GetNativeView(); - if (!gtk_widget) { - NOTREACHED(); - return; - } - - // Since only top-level WidgetGtk have a focus manager, the native view is - // expected to be a GtkWindow. - gtk_window_set_focus(GTK_WINDOW(gtk_widget), NULL); + static_cast<WidgetGtk*>(widget_)->ClearNativeFocus(); } void FocusManager::FocusNativeView(gfx::NativeView native_view) { diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index 2f21358..c3b0814 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -849,6 +849,15 @@ View* WidgetGtk::GetFocusTraversableParentView() { return NULL; } +void WidgetGtk::ClearNativeFocus() { + DCHECK(type_ != TYPE_CHILD); + if (!GetNativeView()) { + NOTREACHED(); + return; + } + gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL); +} + //////////////////////////////////////////////////////////////////////////////// // WidgetGtk, protected: diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index 3b95140..816a263 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -194,6 +194,9 @@ class WidgetGtk virtual FocusTraversable* GetFocusTraversableParent(); virtual View* GetFocusTraversableParentView(); + // Clears the focus on the native widget having the focus. + virtual void ClearNativeFocus(); + protected: // If widget containes another widget, translates event coordinates to the // contained widget's coordinates, else returns original event coordinates. |