[gtk+] GtkPopover: Add gtk_popover_popdown/popup



commit 1f7b6c1d6f822ee660b8cca3b08a2bcc1c48b359
Author: Timm Bäder <mail baedert org>
Date:   Wed Aug 10 18:28:14 2016 +0200

    GtkPopover: Add gtk_popover_popdown/popup
    
    Since not chaining up in gtk_widget_show/gtk_widget_hide is not allowed,
    we can't just implicitly delay the hiding in GtkPopover's hide
    implementation. Fix this by introducing gtk_popover_popup() and
    gtk_popover_popdown() to show or hide a popover with transition and
    revert GtkPopover's show/hide implementation to apply their effect
    without the transition.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=769706

 docs/reference/gtk/gtk3-sections.txt |    2 +
 gtk/gtkpopover.c                     |  146 ++++++++++++++++++++++++++-------
 gtk/gtkpopover.h                     |    7 ++
 3 files changed, 124 insertions(+), 31 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index a049638..b1a81c7 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -8159,6 +8159,8 @@ GtkPopover
 gtk_popover_new
 gtk_popover_new_from_model
 gtk_popover_bind_model
+gtk_popover_popup
+gtk_popover_popdown
 gtk_popover_set_relative_to
 gtk_popover_get_relative_to
 gtk_popover_set_pointing_to
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 3e5e6e7..48be0ef 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -208,6 +208,8 @@ gtk_popover_init (GtkPopover *popover)
   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;
@@ -296,6 +298,30 @@ transitions_enabled (GtkPopover *popover)
 }
 
 static void
+gtk_popover_hide_internal (GtkPopover *popover)
+{
+  GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+  GtkWidget *widget = GTK_WIDGET (popover);
+
+  if (!priv->visible)
+    return;
+
+  priv->visible = FALSE;
+  g_signal_emit (widget, signals[CLOSED], 0);
+
+  if (priv->modal)
+    gtk_popover_apply_modality (popover, FALSE);
+
+  if (gtk_widget_get_realized (widget))
+    {
+      cairo_region_t *region = cairo_region_create ();
+      gdk_window_input_shape_combine_region (gtk_widget_get_parent_window (widget),
+                                             region, 0, 0);
+      cairo_region_destroy (region);
+    }
+}
+
+static void
 gtk_popover_finalize (GObject *object)
 {
   GtkPopover *popover = GTK_POPOVER (object);
@@ -550,12 +576,27 @@ show_animate_cb (GtkWidget     *widget,
             gtk_popover_set_state (popover, STATE_HIDING);
         }
       else
-        gtk_popover_set_state (popover, STATE_HIDDEN);
+        {
+          gtk_widget_hide (widget);
+        }
 
-      return FALSE;
+      priv->tick_id = 0;
+      return G_SOURCE_REMOVE;
     }
   else
-    return TRUE;
+    return G_SOURCE_CONTINUE;
+}
+
+static void
+gtk_popover_stop_transition (GtkPopover *popover)
+{
+  GtkPopoverPrivate *priv = popover->priv;
+
+  if (priv->tick_id != 0)
+    {
+      gtk_widget_remove_tick_callback (GTK_WIDGET (popover), priv->tick_id);
+      priv->tick_id = 0;
+    }
 }
 
 static void
@@ -593,11 +634,7 @@ gtk_popover_set_state (GtkPopover *popover,
     gtk_popover_start_transition (popover);
   else
     {
-      if (priv->tick_id)
-        {
-          gtk_widget_remove_tick_callback (GTK_WIDGET (popover), priv->tick_id);
-          priv->tick_id = 0;
-        }
+      gtk_popover_stop_transition (popover);
 
       gtk_widget_set_visible (GTK_WIDGET (popover), state == STATE_SHOWN);
     }
@@ -1483,10 +1520,12 @@ gtk_popover_button_release (GtkWidget      *widget,
           event->x > child_alloc.x + child_alloc.width ||
           event->y < child_alloc.y ||
           event->y > child_alloc.y + child_alloc.height)
-        gtk_widget_hide (widget);
+        gtk_popover_popdown (popover);
     }
   else if (!gtk_widget_is_ancestor (event_widget, widget))
-    gtk_widget_hide (widget);
+    {
+      gtk_popover_popdown (popover);
+    }
 
   return GDK_EVENT_PROPAGATE;
 }
@@ -1583,7 +1622,7 @@ gtk_popover_show (GtkWidget *widget)
   if (priv->modal)
     gtk_popover_apply_modality (GTK_POPOVER (widget), TRUE);
 
-  gtk_popover_set_state (GTK_POPOVER (widget), STATE_SHOWING);
+  priv->state = STATE_SHOWN;
 
   if (gtk_widget_get_realized (widget))
     gdk_window_input_shape_combine_region (gtk_widget_get_parent_window (widget),
@@ -1594,29 +1633,17 @@ static void
 gtk_popover_hide (GtkWidget *widget)
 {
   GtkPopoverPrivate *priv = GTK_POPOVER (widget)->priv;
-  cairo_region_t *region;
 
-  if (priv->visible)
-    {
-      priv->visible = FALSE;
-      g_signal_emit (widget, signals[CLOSED], 0);
+  gtk_popover_hide_internal (GTK_POPOVER (widget));
 
-      if (priv->modal)
-        gtk_popover_apply_modality (GTK_POPOVER (widget), FALSE);
-    }
+  gtk_popover_stop_transition (GTK_POPOVER (widget));
+  priv->state = STATE_HIDDEN;
+  priv->transition_diff = 0;
+  gtk_progress_tracker_finish (&priv->tracker);
+  gtk_widget_set_opacity (widget, 1.0);
 
-  if (gtk_widget_get_realized (widget))
-    {
-      region = cairo_region_create ();
-      gdk_window_input_shape_combine_region (gtk_widget_get_parent_window (widget),
-                                             region, 0, 0);
-      cairo_region_destroy (region);
-    }
 
-  if (!priv->window || priv->state == STATE_HIDDEN)
-    GTK_WIDGET_CLASS (gtk_popover_parent_class)->hide (widget);
-  else if (priv->state != STATE_SHOWING)
-    gtk_popover_set_state (GTK_POPOVER (widget), STATE_HIDING);
+  GTK_WIDGET_CLASS (gtk_popover_parent_class)->hide (widget);
 }
 
 static void
@@ -1827,7 +1854,7 @@ _gtk_popover_parent_grab_notify (GtkWidget  *widget,
       grab_widget = gtk_grab_get_current ();
 
       if (!grab_widget || !GTK_IS_POPOVER (grab_widget))
-        gtk_widget_hide (GTK_WIDGET (popover));
+        gtk_popover_popdown (popover);
     }
 }
 
@@ -2569,3 +2596,60 @@ gtk_popover_get_constrain_to (GtkPopover *popover)
 
   return priv->constraint;
 }
+
+/**
+ * gtk_popover_popup:
+ * @popover: a #GtkPopover
+ *
+ * Pops @popover up. This is different than a gtk_widget_show() call
+ * in that it shows the popover with a transition. If you want to show
+ * the popover without a transition, use gtk_widget_show().
+ *
+ * Since: 3.22
+ */
+void
+gtk_popover_popup (GtkPopover *popover)
+{
+  GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+  g_return_if_fail (GTK_IS_POPOVER (popover));
+
+  if (priv->state == STATE_SHOWING ||
+      priv->state == STATE_SHOWN)
+    return;
+
+  gtk_widget_show (GTK_WIDGET (popover));
+
+  if (transitions_enabled (popover))
+    gtk_popover_set_state (popover, STATE_SHOWING);
+}
+
+/**
+ * gtk_popover_popdown:
+ * @popover: a #GtkPopover
+ *
+ * Pops @popover down.This is different than a gtk_widget_hide() call
+ * in that it shows the popover with a transition. If you want to hide
+ * the popover without a transition, use gtk_widget_hide().
+ *
+ * Since: 3.22
+ */
+void
+gtk_popover_popdown (GtkPopover *popover)
+{
+  GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+  g_return_if_fail (GTK_IS_POPOVER (popover));
+
+  if (priv->state == STATE_HIDING ||
+      priv->state == STATE_HIDDEN)
+    return;
+
+
+  if (!transitions_enabled (popover))
+    gtk_widget_hide (GTK_WIDGET (popover));
+  else
+    gtk_popover_set_state (popover, STATE_HIDING);
+
+  gtk_popover_hide_internal (popover);
+}
diff --git a/gtk/gtkpopover.h b/gtk/gtkpopover.h
index 61bcd92..af8359c 100644
--- a/gtk/gtkpopover.h
+++ b/gtk/gtkpopover.h
@@ -116,6 +116,13 @@ void                 gtk_popover_set_constrain_to (GtkPopover           *popover
 GDK_AVAILABLE_IN_3_20
 GtkPopoverConstraint gtk_popover_get_constrain_to (GtkPopover           *popover);
 
+GDK_AVAILABLE_IN_3_22
+void                 gtk_popover_popup            (GtkPopover *popover);
+
+GDK_AVAILABLE_IN_3_22
+void                 gtk_popover_popdown          (GtkPopover *popover);
+
+
 G_END_DECLS
 
 #endif /* __GTK_POPOVER_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]