summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2019-06-13 00:13:21 +0000
committerMatthias Clasen <mclasen@redhat.com>2019-06-12 21:50:46 -0400
commitcbc0a8447d12aee306d2c2e56a53527384142240 (patch)
tree806e3e9ae13c4c2178055f063b373477afc2fb44 /gtk
parenta7e121384cf2b5ee470ccade9defdf27273b1797 (diff)
downloadgtk+-cbc0a8447d12aee306d2c2e56a53527384142240.tar.gz
popover menu: Unify hover and focus
Menus traditionally don't have separate hover and focus locations. Make the same change here that we already did for popover menubars: Track the active item and set its selected state. Both keynav and mouse change the active item.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkmodelbutton.c79
-rw-r--r--gtk/gtkpopovermenu.c23
-rw-r--r--gtk/gtkpopovermenuprivate.h30
3 files changed, 131 insertions, 1 deletions
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c
index 57c333536b..80552ec33b 100644
--- a/gtk/gtkmodelbutton.c
+++ b/gtk/gtkmodelbutton.c
@@ -31,7 +31,7 @@
#include "gtkstylecontext.h"
#include "gtktypebuiltins.h"
#include "gtkstack.h"
-#include "gtkpopover.h"
+#include "gtkpopovermenuprivate.h"
#include "gtkintl.h"
#include "gtkcssnodeprivate.h"
#include "gtkcsstypesprivate.h"
@@ -41,6 +41,8 @@
#include "gtksizegroup.h"
#include "gtkaccellabelprivate.h"
#include "gtkactionable.h"
+#include "gtkeventcontrollermotion.h"
+#include "gtkeventcontrollerkey.h"
/**
* SECTION:gtkmodelbutton
@@ -1128,8 +1130,74 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
}
static void
+enter_cb (GtkEventController *controller,
+ double x,
+ double y,
+ GdkCrossingMode mode,
+ GdkNotifyType type,
+ gpointer data)
+{
+ GtkWidget *target;
+ GtkWidget *popover;
+ gboolean is;
+ gboolean contains;
+
+ target = gtk_event_controller_get_widget (controller);
+ popover = gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU);
+
+ g_object_get (controller,
+ "is-pointer-focus", &is,
+ "contains-pointer-focus", &contains,
+ NULL);
+
+ if (popover && (is || contains))
+ gtk_popover_menu_set_active_item (GTK_POPOVER_MENU (popover), target);
+}
+
+static void
+leave_cb (GtkEventController *controller,
+ GdkCrossingMode mode,
+ GdkNotifyType type,
+ gpointer data)
+{
+ GtkWidget *target;
+ GtkWidget *popover;
+ gboolean is;
+ gboolean contains;
+
+ target = gtk_event_controller_get_widget (controller);
+ popover = gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU);
+
+ g_object_get (controller,
+ "is-pointer-focus", &is,
+ "contains-pointer-focus", &contains,
+ NULL);
+
+ if (popover && !(is || contains))
+ gtk_popover_menu_set_active_item (GTK_POPOVER_MENU (popover), NULL);
+}
+
+static void
+focus_in_cb (GtkEventController *controller,
+ GdkCrossingMode mode,
+ GdkNotifyType type,
+ gpointer data)
+{
+ GtkWidget *target;
+ GtkWidget *popover;
+
+ target = gtk_event_controller_get_widget (controller);
+ popover = gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU);
+
+ if (popover)
+ gtk_popover_menu_set_active_item (GTK_POPOVER_MENU (popover), target);
+}
+
+static void
gtk_model_button_init (GtkModelButton *button)
{
+ GtkEventController *controller;
+
button->role = GTK_BUTTON_ROLE_NORMAL;
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
button->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
@@ -1161,6 +1229,15 @@ gtk_model_button_init (GtkModelButton *button)
gtk_widget_hide (button->start_indicator);
gtk_widget_hide (button->end_indicator);
update_node_ordering (button);
+
+ controller = gtk_event_controller_motion_new ();
+ g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), NULL);
+ g_signal_connect (controller, "leave", G_CALLBACK (leave_cb), NULL);
+ gtk_widget_add_controller (GTK_WIDGET (button), controller);
+
+ controller = gtk_event_controller_key_new ();
+ g_signal_connect (controller, "focus-in", G_CALLBACK (focus_in_cb), NULL);
+ gtk_widget_add_controller (GTK_WIDGET (button), controller);
}
/**
diff --git a/gtk/gtkpopovermenu.c b/gtk/gtkpopovermenu.c
index 93a0ba8953..856b017cb5 100644
--- a/gtk/gtkpopovermenu.c
+++ b/gtk/gtkpopovermenu.c
@@ -17,6 +17,8 @@
#include "config.h"
#include "gtkpopovermenu.h"
+#include "gtkpopovermenuprivate.h"
+
#include "gtkstack.h"
#include "gtkstylecontext.h"
#include "gtkintl.h"
@@ -120,6 +122,8 @@ typedef struct _GtkPopoverMenuClass GtkPopoverMenuClass;
struct _GtkPopoverMenu
{
GtkPopover parent_instance;
+
+ GtkWidget *active_item;
};
struct _GtkPopoverMenuClass
@@ -133,6 +137,25 @@ enum {
G_DEFINE_TYPE (GtkPopoverMenu, gtk_popover_menu, GTK_TYPE_POPOVER)
+void
+gtk_popover_menu_set_active_item (GtkPopoverMenu *menu,
+ GtkWidget *item)
+{
+ if (menu->active_item != item)
+ {
+ if (menu->active_item)
+ gtk_widget_unset_state_flags (menu->active_item, GTK_STATE_FLAG_SELECTED);
+
+ menu->active_item = item;
+
+ if (menu->active_item)
+ {
+ gtk_widget_set_state_flags (menu->active_item, GTK_STATE_FLAG_SELECTED, FALSE);
+ gtk_widget_grab_focus (menu->active_item);
+ }
+ }
+}
+
static void
visible_submenu_changed (GObject *object,
GParamSpec *pspec,
diff --git a/gtk/gtkpopovermenuprivate.h b/gtk/gtkpopovermenuprivate.h
new file mode 100644
index 0000000000..024d20c91c
--- /dev/null
+++ b/gtk/gtkpopovermenuprivate.h
@@ -0,0 +1,30 @@
+/* GTK - The GIMP Toolkit
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_POPOVER_MENU_PRIVATE_H__
+#define __GTK_POPOVER_MENU_PRIVATE_H__
+
+#include "gtkpopovermenu.h"
+
+G_BEGIN_DECLS
+
+void gtk_popover_menu_set_active_item (GtkPopoverMenu *popover,
+ GtkWidget *item);
+
+G_END_DECLS
+
+#endif /* __GTK_POPOVER_PRIVATE_H__ */