Commit 0fd2fb36 authored by ncj674@motorola.com's avatar ncj674@motorola.com

Linux GTK: Support keyboard navigation in avatar menu.

BUG=101399
TEST= Navigate inside the avatar menu using keyboard.
Tab key and down arrow key to navigate forward.
Shift-Tab key and up arrow key to navigate backward.
Enter key to open/edit a profile.

Review URL: http://codereview.chromium.org/8834010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113577 0039d316-1c4b-4281-b951-d872f2087c98
parent 01a41a36
...@@ -133,12 +133,16 @@ void AvatarMenuBubbleGtk::InitContents() { ...@@ -133,12 +133,16 @@ void AvatarMenuBubbleGtk::InitContents() {
GtkWidget* items_vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); GtkWidget* items_vbox = gtk_vbox_new(FALSE, ui::kContentAreaSpacing);
for (size_t i = 0; i < profile_count; ++i) { for (size_t i = 0; i < profile_count; ++i) {
AvatarMenuModel::Item menu_item = avatar_menu_model_->GetItemAt(i);
AvatarMenuItemGtk* item = new AvatarMenuItemGtk( AvatarMenuItemGtk* item = new AvatarMenuItemGtk(
this, avatar_menu_model_->GetItemAt(i), i, theme_service_); this, menu_item, i, theme_service_);
items_.push_back(item); items_.push_back(item);
gtk_box_pack_start(GTK_BOX(items_vbox), item->widget(), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(items_vbox), item->widget(), TRUE, TRUE, 0);
gtk_widget_set_can_focus(item->widget(), TRUE);
if (menu_item.active)
gtk_container_set_focus_child(GTK_CONTAINER(items_vbox), item->widget());
} }
gtk_box_pack_start(GTK_BOX(contents_), items_vbox, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(contents_), items_vbox, TRUE, TRUE, 0);
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chrome/browser/ui/gtk/avatar_menu_item_gtk.h" #include "chrome/browser/ui/gtk/avatar_menu_item_gtk.h"
#include <gdk/gdkkeysyms.h>
#include "base/bind.h" #include "base/bind.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/utf_string_conversions.h" #include "base/utf_string_conversions.h"
...@@ -82,16 +84,66 @@ gboolean AvatarMenuItemGtk::OnProfileClick(GtkWidget* widget, ...@@ -82,16 +84,66 @@ gboolean AvatarMenuItemGtk::OnProfileClick(GtkWidget* widget,
return FALSE; return FALSE;
} }
gboolean AvatarMenuItemGtk::OnProfileKeyPress(GtkWidget* widget,
GdkEventKey* event) {
// delegate_->EditProfile() will close the avatar bubble which in turn
// try to destroy this AvatarMenuItemGtk.
// This is not OK to do this from the signal handler, so we'll
// defer it.
if (event->keyval == GDK_Return ||
event->keyval == GDK_ISO_Enter ||
event->keyval == GDK_KP_Enter) {
if (item_.active)
MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&AvatarMenuItemGtk::EditProfile,
weak_factory_.GetWeakPtr()));
else
MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&AvatarMenuItemGtk::OpenProfile,
weak_factory_.GetWeakPtr()));
}
return FALSE;
}
void AvatarMenuItemGtk::ShowStatusLabel() {
gtk_widget_show(status_label_);
gtk_widget_hide(link_alignment_);
}
void AvatarMenuItemGtk::ShowEditLink() {
gtk_widget_hide(status_label_);
gtk_widget_show(link_alignment_);
}
gboolean AvatarMenuItemGtk::OnProfileFocusIn(GtkWidget* widget,
GdkEventFocus* event) {
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &highlighted_color_);
if (item_.active)
ShowEditLink();
return FALSE;
}
gboolean AvatarMenuItemGtk::OnProfileFocusOut(GtkWidget* widget,
GdkEventFocus* event) {
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, unhighlighted_color_);
if (item_.active)
ShowStatusLabel();
return FALSE;
}
gboolean AvatarMenuItemGtk::OnProfileEnter(GtkWidget* widget, gboolean AvatarMenuItemGtk::OnProfileEnter(GtkWidget* widget,
GdkEventCrossing* event) { GdkEventCrossing* event) {
if (event->detail == GDK_NOTIFY_INFERIOR) if (event->detail == GDK_NOTIFY_INFERIOR)
return FALSE; return FALSE;
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &highlighted_color_); gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &highlighted_color_);
if (item_.active) { if (item_.active)
gtk_widget_hide(status_label_); ShowEditLink();
gtk_widget_show(link_alignment_);
}
return FALSE; return FALSE;
} }
...@@ -102,10 +154,8 @@ gboolean AvatarMenuItemGtk::OnProfileLeave(GtkWidget* widget, ...@@ -102,10 +154,8 @@ gboolean AvatarMenuItemGtk::OnProfileLeave(GtkWidget* widget,
return FALSE; return FALSE;
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, unhighlighted_color_); gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, unhighlighted_color_);
if (item_.active) { if (item_.active)
gtk_widget_show(status_label_); ShowStatusLabel();
gtk_widget_hide(link_alignment_);
}
return FALSE; return FALSE;
} }
...@@ -160,6 +210,12 @@ void AvatarMenuItemGtk::Init(GtkThemeService* theme_service) { ...@@ -160,6 +210,12 @@ void AvatarMenuItemGtk::Init(GtkThemeService* theme_service) {
G_CALLBACK(OnProfileEnterThunk), this); G_CALLBACK(OnProfileEnterThunk), this);
g_signal_connect(widget_.get(), "leave-notify-event", g_signal_connect(widget_.get(), "leave-notify-event",
G_CALLBACK(OnProfileLeaveThunk), this); G_CALLBACK(OnProfileLeaveThunk), this);
g_signal_connect(widget_.get(), "focus-in-event",
G_CALLBACK(OnProfileFocusInThunk), this);
g_signal_connect(widget_.get(), "focus-out-event",
G_CALLBACK(OnProfileFocusOutThunk), this);
g_signal_connect(widget_.get(), "key-press-event",
G_CALLBACK(OnProfileKeyPressThunk), this);
GtkWidget* item_hbox = gtk_hbox_new(FALSE, ui::kControlSpacing); GtkWidget* item_hbox = gtk_hbox_new(FALSE, ui::kControlSpacing);
GdkPixbuf* avatar_pixbuf = NULL; GdkPixbuf* avatar_pixbuf = NULL;
......
...@@ -51,12 +51,22 @@ class AvatarMenuItemGtk : public content::NotificationObserver { ...@@ -51,12 +51,22 @@ class AvatarMenuItemGtk : public content::NotificationObserver {
const content::NotificationDetails& details) OVERRIDE; const content::NotificationDetails& details) OVERRIDE;
private: private:
void ShowStatusLabel();
void ShowEditLink();
CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileClick, CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileClick,
GdkEventButton*); GdkEventButton*);
CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileEnter, CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileEnter,
GdkEventCrossing*); GdkEventCrossing*);
CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileLeave, CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileLeave,
GdkEventCrossing*); GdkEventCrossing*);
CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileFocusIn,
GdkEventFocus*);
CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileFocusOut,
GdkEventFocus*);
CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileKeyPress,
GdkEventKey*);
CHROMEGTK_CALLBACK_0(AvatarMenuItemGtk, void, OnEditProfileLinkClicked); CHROMEGTK_CALLBACK_0(AvatarMenuItemGtk, void, OnEditProfileLinkClicked);
// Create all widgets in this menu item, using |theme_service|. // Create all widgets in this menu item, using |theme_service|.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment