[gtk+] popover: Track toplevel focus changes
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] popover: Track toplevel focus changes
- Date: Thu, 6 Mar 2014 23:46:14 +0000 (UTC)
commit dcba77fcc454229079049f41f4ddc23e5c27353f
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu Mar 6 14:50:35 2014 +0100
popover: Track toplevel focus changes
Make the popover temporarily undo the GTK+ grab, so it remains modal
to its window, but does not attempt to steal focus on other non-modal
windows that get the focus.
This was most confusing with keyboard navigation, as the focus would
remain stuck on the popover, and not move to the newly focused window
after the popover was dismissed. It didn't have as much effect on
pointer operations as only the first click would be consumed in order
to hide the popover.
gtk/gtkpopover.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 53 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 1cc9e9c..2286cff 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -102,6 +102,7 @@ struct _GtkPopoverPrivate
guint modal : 1;
guint button_pressed : 1;
guint apply_shape : 1;
+ guint grab_notify_blocked : 1;
};
static GQuark quark_widget_popovers = 0;
@@ -254,6 +255,52 @@ gtk_popover_realize (GtkWidget *widget)
gtk_widget_set_realized (widget, TRUE);
}
+static gboolean
+window_focus_in (GtkWidget *widget,
+ GdkEvent *event,
+ GtkPopover *popover)
+{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ /* Regain the grab when the window is focused */
+ if (priv->modal &&
+ gtk_widget_is_drawable (GTK_WIDGET (popover)))
+ {
+ GtkWidget *focus;
+
+ gtk_grab_add (GTK_WIDGET (popover));
+
+ focus = gtk_window_get_focus (GTK_WINDOW (widget));
+
+ if (!gtk_widget_is_ancestor (focus, GTK_WIDGET (popover)))
+ gtk_widget_grab_focus (GTK_WIDGET (popover));
+
+ if (priv->grab_notify_blocked)
+ g_signal_handler_unblock (priv->widget, priv->grab_notify_id);
+
+ priv->grab_notify_blocked = FALSE;
+ }
+ return FALSE;
+}
+
+static gboolean
+window_focus_out (GtkWidget *widget,
+ GdkEvent *event,
+ GtkPopover *popover)
+{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ /* Temporarily remove the grab when unfocused */
+ if (priv->modal &&
+ gtk_widget_is_drawable (GTK_WIDGET (popover)))
+ {
+ g_signal_handler_block (priv->widget, priv->grab_notify_id);
+ gtk_grab_remove (GTK_WIDGET (popover));
+ priv->grab_notify_blocked = TRUE;
+ }
+ return FALSE;
+}
+
static void
gtk_popover_apply_modality (GtkPopover *popover,
gboolean modal)
@@ -270,9 +317,15 @@ gtk_popover_apply_modality (GtkPopover *popover,
g_object_ref (prev_focus);
gtk_grab_add (GTK_WIDGET (popover));
gtk_widget_grab_focus (GTK_WIDGET (popover));
+
+ g_signal_connect (priv->window, "focus-in-event",
+ G_CALLBACK (window_focus_in), popover);
+ g_signal_connect (priv->window, "focus-out-event",
+ G_CALLBACK (window_focus_out), popover);
}
else
{
+ g_signal_handlers_disconnect_by_data (priv->window, popover);
gtk_grab_remove (GTK_WIDGET (popover));
if (priv->prev_focus_widget)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]