[gtk/BUG_popover_focus_from_another_window_GTK3] popover: fix focus when inside an unfocused window
- From: Nelson Benítez León <nbenitez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/BUG_popover_focus_from_another_window_GTK3] popover: fix focus when inside an unfocused window
- Date: Sat, 31 Aug 2019 02:25:26 +0000 (UTC)
commit 58f57aeb3bc92280c8e2ded2901aaa553dd6b34d
Author: Nelson Benítez León <nbenitezl gmail com>
Date: Fri Aug 30 21:14:17 2019 -0400
popover: fix focus when inside an unfocused window
Fix popovers to properly gain focus when clicked
inside an unfocused window.
We use the GTK_PHASE_CAPTURE of the 'pressed' event
to early detect that the popover is being clicked
inside an inactive window, this allow us to present
the window (and be focused) before the normal signal
handlers for the popover click/pressed events are run
which would ultimately give focus to popover widget.
This fix works for both modal and 'non modal' popovers
when being clicked inside unfocused windows.
Fixes issue #1871
gtk/gtkpopover.c | 47 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 39 insertions(+), 8 deletions(-)
---
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 59d1bc8587..a2d47b6281 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -159,6 +159,7 @@ struct _GtkPopoverPrivate
GdkRectangle pointing_to;
GtkPopoverConstraint constraint;
GtkProgressTracker tracker;
+ GtkGesture *multipress_gesture;
guint prev_focus_unmap_id;
guint hierarchy_changed_id;
guint size_allocate_id;
@@ -199,6 +200,12 @@ static void gtk_popover_apply_modality (GtkPopover *popover,
static void gtk_popover_set_scrollable_full (GtkPopover *popover,
GtkScrollable *scrollable);
+static void gtk_popover_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
+ gint n_press,
+ gdouble widget_x,
+ gdouble widget_y,
+ GtkPopover *popover);
+
G_DEFINE_TYPE_WITH_PRIVATE (GtkPopover, gtk_popover, GTK_TYPE_BIN)
static void
@@ -206,17 +213,26 @@ gtk_popover_init (GtkPopover *popover)
{
GtkWidget *widget;
GtkStyleContext *context;
+ GtkPopoverPrivate *priv;
widget = GTK_WIDGET (popover);
gtk_widget_set_has_window (widget, TRUE);
- popover->priv = gtk_popover_get_instance_private (popover);
- popover->priv->modal = TRUE;
- popover->priv->tick_id = 0;
- popover->priv->state = STATE_HIDDEN;
- popover->priv->visible = FALSE;
- popover->priv->transitions_enabled = TRUE;
- popover->priv->preferred_position = GTK_POS_TOP;
- popover->priv->constraint = GTK_POPOVER_CONSTRAINT_WINDOW;
+ priv = popover->priv = gtk_popover_get_instance_private (popover);
+ priv->modal = TRUE;
+ priv->tick_id = 0;
+ priv->state = STATE_HIDDEN;
+ priv->visible = FALSE;
+ priv->transitions_enabled = TRUE;
+ priv->preferred_position = GTK_POS_TOP;
+ priv->constraint = GTK_POPOVER_CONSTRAINT_WINDOW;
+
+ priv->multipress_gesture = gtk_gesture_multi_press_new (widget);
+ g_signal_connect (priv->multipress_gesture, "pressed",
+ G_CALLBACK (gtk_popover_multipress_gesture_pressed), popover);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->multipress_gesture), 0);
+ gtk_gesture_single_set_exclusive (GTK_GESTURE_SINGLE (priv->multipress_gesture), TRUE);
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->multipress_gesture),
+ GTK_PHASE_CAPTURE);
context = gtk_widget_get_style_context (GTK_WIDGET (popover));
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
@@ -336,6 +352,8 @@ gtk_popover_finalize (GObject *object)
if (priv->widget)
gtk_popover_update_relative_to (popover, NULL);
+ g_clear_object (&priv->multipress_gesture);
+
G_OBJECT_CLASS (gtk_popover_parent_class)->finalize (object);
}
@@ -2178,6 +2196,19 @@ gtk_popover_update_preferred_position (GtkPopover *popover,
g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_POSITION]);
}
+static void
+gtk_popover_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
+ gint n_press,
+ gdouble widget_x,
+ gdouble widget_y,
+ GtkPopover *popover)
+{
+ GtkPopoverPrivate *priv = popover->priv;
+
+ if (!gtk_window_is_active (priv->window) && gtk_widget_is_drawable (GTK_WIDGET (popover)))
+ gtk_window_present_with_time (priv->window, gtk_get_current_event_time ());
+}
+
/**
* gtk_popover_new:
* @relative_to: (allow-none): #GtkWidget the popover is related to
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]