[gtk/new-style-menu] popover bar: Add arrow keynav
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/new-style-menu] popover bar: Add arrow keynav
- Date: Sun, 9 Jun 2019 02:26:16 +0000 (UTC)
commit 457eac1669d64f326513c0eae824ee8272a26f8c
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Jun 8 17:48:29 2019 +0000
popover bar: Add arrow keynav
Make left/right cycle the active item
among the bars children. Separate the styling
for the active item from :hover, since it is
a separate state, and only mixed up in menus
for historical reasons.
gtk/gtkpopoverbar.c | 130 ++++++++++++++++++++++++++++++++---------
gtk/theme/Adwaita/_common.scss | 26 +++++++++
2 files changed, 128 insertions(+), 28 deletions(-)
---
diff --git a/gtk/gtkpopoverbar.c b/gtk/gtkpopoverbar.c
index 69c86df8ce..f702abf6e6 100644
--- a/gtk/gtkpopoverbar.c
+++ b/gtk/gtkpopoverbar.c
@@ -45,6 +45,8 @@
GType gtk_popover_bar_item_get_type (void) G_GNUC_CONST;
+typedef struct _GtkPopoverBarItem GtkPopoverBarItem;
+
struct _GtkPopoverBar
{
GtkWidget parent;
@@ -52,7 +54,8 @@ struct _GtkPopoverBar
GMenuModel *model;
GtkMenuTracker *tracker;
GtkWidget *box;
- GtkWidget *open_popover;
+
+ GtkPopoverBarItem *active_item;
};
typedef struct _GtkPopoverBarClass GtkPopoverBarClass;
@@ -61,13 +64,12 @@ struct _GtkPopoverBarClass
GtkWidgetClass parent_class;
};
-typedef struct _GtkPopoverBarItem GtkPopoverBarItem;
struct _GtkPopoverBarItem
{
GtkWidget parent;
GtkWidget *label;
- GtkWidget *popover;
+ GtkPopover *popover;
};
typedef struct _GtkPopoverBarItemClass GtkPopoverBarItemClass;
@@ -80,6 +82,52 @@ struct _GtkPopoverBarItemClass
G_DEFINE_TYPE (GtkPopoverBarItem, gtk_popover_bar_item, GTK_TYPE_WIDGET)
+static void
+set_active_item (GtkPopoverBar *bar,
+ GtkPopoverBarItem *item,
+ gboolean popup)
+{
+ gboolean changed;
+ gboolean was_popup;
+
+ changed = item != bar->active_item;
+
+ if (bar->active_item)
+ was_popup = gtk_widget_get_mapped (GTK_WIDGET (bar->active_item->popover));
+ else
+ was_popup = FALSE;
+
+ if (was_popup && changed)
+ gtk_popover_popdown (bar->active_item->popover);
+
+ if (changed)
+ {
+ GtkStyleContext *context;
+
+ if (bar->active_item)
+ {
+ context = gtk_widget_get_style_context (GTK_WIDGET (bar->active_item));
+ gtk_style_context_remove_class (context, "active");
+ }
+
+ bar->active_item = item;
+
+ if (bar->active_item)
+ {
+ context = gtk_widget_get_style_context (GTK_WIDGET (bar->active_item));
+ gtk_style_context_add_class (context, "active");
+ }
+ }
+
+ if (bar->active_item)
+ {
+ if (popup || (was_popup && changed))
+ gtk_popover_popup (bar->active_item->popover);
+ else
+ gtk_widget_grab_focus (GTK_WIDGET (bar->active_item));
+ }
+}
+
static void
clicked_cb (GtkGesture *gesture,
int n,
@@ -88,20 +136,12 @@ clicked_cb (GtkGesture *gesture,
gpointer data)
{
GtkWidget *target;
- GtkPopoverBarItem *item;
GtkPopoverBar *bar;
target = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
bar = GTK_POPOVER_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_BAR));
- item = GTK_POPOVER_BAR_ITEM (target);
- if (item->popover && item->popover != bar->open_popover)
- {
- if (bar->open_popover)
- gtk_popover_popdown (GTK_POPOVER (bar->open_popover));
- bar->open_popover = item->popover;
- gtk_popover_popup (GTK_POPOVER (bar->open_popover));
- }
+ set_active_item (bar, GTK_POPOVER_BAR_ITEM (target), TRUE);
}
static void
@@ -113,21 +153,48 @@ enter_cb (GtkEventController *controller,
gpointer data)
{
GtkWidget *target;
- GtkPopoverBarItem *item;
GtkPopoverBar *bar;
target = gtk_event_controller_get_widget (controller);
bar = GTK_POPOVER_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_BAR));
- item = GTK_POPOVER_BAR_ITEM (target);
- if (item->popover && bar->open_popover &&
- item->popover != bar->open_popover)
+ set_active_item (bar, GTK_POPOVER_BAR_ITEM (target), FALSE);
+}
+
+static gboolean
+key_pressed_cb (GtkEventController *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ gpointer data)
+{
+ GtkWidget *target;
+ GtkPopoverBar *bar;
+ GtkWidget *next;
+
+ target = gtk_event_controller_get_widget (controller);
+
+ bar = GTK_POPOVER_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_BAR));
+
+ if (keyval == GDK_KEY_Left)
+ {
+ next = gtk_widget_get_prev_sibling (target);
+ if (next == NULL)
+ next = gtk_widget_get_last_child (GTK_WIDGET (bar->box));
+ }
+ else if (keyval == GDK_KEY_Right)
{
- gtk_popover_popdown (GTK_POPOVER (bar->open_popover));
- bar->open_popover = item->popover;
- gtk_popover_popup (GTK_POPOVER (bar->open_popover));
+ next = gtk_widget_get_next_sibling (target);
+ if (next == NULL)
+ next = gtk_widget_get_first_child (GTK_WIDGET (bar->box));
}
+ else
+ return FALSE;
+
+ set_active_item (bar, GTK_POPOVER_BAR_ITEM (next), FALSE);
+
+ return TRUE;
}
static void
@@ -135,6 +202,8 @@ gtk_popover_bar_item_init (GtkPopoverBarItem *item)
{
GtkEventController *controller;
+ gtk_widget_set_can_focus (GTK_WIDGET (item), TRUE);
+
item->label = g_object_new (GTK_TYPE_LABEL,
"use-underline", TRUE,
NULL);
@@ -148,6 +217,11 @@ gtk_popover_bar_item_init (GtkPopoverBarItem *item)
gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), NULL);
gtk_widget_add_controller (GTK_WIDGET (item), controller);
+
+ controller = gtk_event_controller_key_new ();
+ gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
+ g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed_cb), NULL);
+ gtk_widget_add_controller (GTK_WIDGET (item), controller);
}
static void
@@ -226,7 +300,7 @@ gtk_popover_bar_item_class_init (GtkPopoverBarItemClass *klass)
NULL,
G_TYPE_NONE, 0);
- gtk_widget_class_set_css_name (widget_class, I_("menuitem"));
+ gtk_widget_class_set_css_name (widget_class, I_("item"));
}
enum
{
@@ -260,11 +334,11 @@ tracker_remove (gint position,
}
static void
-popover_unmap (GtkWidget *popover,
+popover_unmap (GtkPopover *popover,
GtkPopoverBar *bar)
{
- if (popover == bar->open_popover)
- bar->open_popover = NULL;
+ if (bar->active_item && bar->active_item->popover == popover)
+ set_active_item (bar, NULL, FALSE);
}
static void
@@ -280,7 +354,7 @@ tracker_insert (GtkMenuTrackerItem *item,
GMenuModel *model;
GtkWidget *sibling;
GtkWidget *child;
- GtkWidget *popover;
+ GtkPopover *popover;
int i;
widget = g_object_new (GTK_TYPE_POPOVER_BAR_ITEM, NULL);
@@ -289,10 +363,10 @@ tracker_insert (GtkMenuTrackerItem *item,
G_BINDING_SYNC_CREATE);
model = _gtk_menu_tracker_item_get_link (item, G_MENU_LINK_SUBMENU);
- popover = gtk_popover_menu_new_from_model (GTK_WIDGET (widget), model);
- gtk_popover_set_position (GTK_POPOVER (popover), GTK_POS_BOTTOM);
- gtk_popover_set_has_arrow (GTK_POPOVER (popover), FALSE);
- gtk_widget_set_halign (popover, GTK_ALIGN_START);
+ popover = GTK_POPOVER (gtk_popover_menu_new_from_model (GTK_WIDGET (widget), model));
+ gtk_popover_set_position (popover, GTK_POS_BOTTOM);
+ gtk_popover_set_has_arrow (popover, FALSE);
+ gtk_widget_set_halign (GTK_WIDGET (popover), GTK_ALIGN_START);
g_signal_connect (popover, "unmap", G_CALLBACK (popover_unmap), bar);
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index 3c0759b135..1c239e9f6b 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -2053,6 +2053,32 @@ menubar,
.csd.popup decoration {border-radius:0;}
}
+// popover menu bar
+
+menubar {
+ padding: 0px;
+ box-shadow: inset 0 -1px transparentize(black, 0.9);
+
+ &:backdrop { background-color: $backdrop_bg_color; }
+
+ > box > item {
+ min-height: 16px;
+ padding: 4px 8px;
+
+ &.active { //Seems like it :hover even with keyboard focus
+ box-shadow: inset 0 -3px $selected_bg_color;
+ color: $link_color;
+ }
+
+ &:disabled {
+ color: $insensitive_fg_color;
+ box-shadow: none;
+ }
+ }
+ // remove padding and rounding from menubar submenu decoration
+ .csd.popup decoration { border-radius:0; }
+}
+
// Needed to make the border-radius of menus work
// otherwise the background bleeds out of the menu edges
.background.popup { background-color: transparent; }
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]