[libdazzle] app: add DzlApplicationWindow:titlebar-animation property



commit ce56a559c06a4336f6c1b27ab3746bd3858cbbf2
Author: Christian Hergert <chergert redhat com>
Date:   Fri May 1 15:04:14 2020 -0700

    app: add DzlApplicationWindow:titlebar-animation property
    
    This property can be used to track the changes of the titlebar as they
    animate in and out. Some effort is made to ensure that changes are only
    emitted once and in order, however immediate changes to fullscreen may
    result in going from SHOWN to HIDDEN immediately.
    
    Related #38

 src/app/dzl-application-window.c | 134 +++++++++++++++++++++++++++++++++++++--
 src/app/dzl-application-window.h |  22 +++++--
 src/app/meson.build              |   4 ++
 src/dzl-enums.c.in               |   1 +
 4 files changed, 151 insertions(+), 10 deletions(-)
---
diff --git a/src/app/dzl-application-window.c b/src/app/dzl-application-window.c
index b23ec4d..6eccd74 100644
--- a/src/app/dzl-application-window.c
+++ b/src/app/dzl-application-window.c
@@ -26,6 +26,8 @@
 # include "backports/gtkeventcontrollermotion.c"
 #endif
 
+#include "dzl-enums.h"
+
 #include "app/dzl-application-window.h"
 #include "shortcuts/dzl-shortcut-manager.h"
 #include "util/dzl-gtk.h"
@@ -59,8 +61,12 @@ typedef struct
   GtkEventController *motion_controller;
   gulong              motion_controller_handler;
 
+  DzlTitlebarAnimation  last_titlebar_animation;
+
   guint        fullscreen_source;
   guint        fullscreen_reveal_source;
+  guint        titlebar_hiding;
+
   guint        fullscreen : 1;
   guint        in_key_press : 1;
 } DzlApplicationWindowPrivate;
@@ -68,6 +74,7 @@ typedef struct
 enum {
   PROP_0,
   PROP_FULLSCREEN,
+  PROP_TITLEBAR_ANIMATION,
   N_PROPS
 };
 
@@ -80,17 +87,58 @@ G_DEFINE_TYPE_WITH_CODE (DzlApplicationWindow, dzl_application_window, GTK_TYPE_
 static GParamSpec *properties [N_PROPS];
 static GtkBuildableIface *parent_buildable;
 
+static void
+update_titlebar_animation_property (DzlApplicationWindow *self)
+{
+  DzlApplicationWindowPrivate *priv = dzl_application_window_get_instance_private (self);
+  DzlTitlebarAnimation current;
+
+  g_assert (DZL_IS_APPLICATION_WINDOW (self));
+
+  current = dzl_application_window_get_titlebar_animation (self);
+
+  if (current != priv->last_titlebar_animation)
+    {
+      priv->last_titlebar_animation = current;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLEBAR_ANIMATION]);
+    }
+}
+
 static gboolean
-dzl_application_window_dismissal (DzlApplicationWindow *self)
+dzl_application_window_titlebar_hidden_cb (gpointer data)
 {
+  DzlApplicationWindow *self = data;
   DzlApplicationWindowPrivate *priv = dzl_application_window_get_instance_private (self);
 
   g_assert (DZL_IS_APPLICATION_WINDOW (self));
 
-  priv->fullscreen_reveal_source = 0;
+  priv->titlebar_hiding--;
+  update_titlebar_animation_property (self);
+
+  return G_SOURCE_REMOVE;
+}
+
+static gboolean
+dzl_application_window_dismissal (DzlApplicationWindow *self)
+{
+  DzlApplicationWindowPrivate *priv = dzl_application_window_get_instance_private (self);
+
+  g_assert (DZL_IS_APPLICATION_WINDOW (self));
 
   if (dzl_application_window_get_fullscreen (self))
-    gtk_revealer_set_reveal_child (priv->titlebar_revealer, FALSE);
+    {
+      priv->titlebar_hiding++;
+      gtk_revealer_set_reveal_child (priv->titlebar_revealer, FALSE);
+      g_timeout_add_full (G_PRIORITY_DEFAULT,
+                          gtk_revealer_get_transition_duration (priv->titlebar_revealer),
+                          dzl_application_window_titlebar_hidden_cb,
+                          g_object_ref (self),
+                          g_object_unref);
+    }
+
+  update_titlebar_animation_property (self);
+
+  priv->fullscreen_reveal_source = 0;
 
   return G_SOURCE_REMOVE;
 }
@@ -223,6 +271,8 @@ dzl_application_window_complete_fullscreen (DzlApplicationWindow *self)
 
   g_object_unref (titlebar);
 
+  update_titlebar_animation_property (self);
+
   return G_SOURCE_REMOVE;
 }
 
@@ -370,6 +420,17 @@ dzl_application_window_window_state_event (GtkWidget           *widget,
   return ret;
 }
 
+static void
+dzl_application_window_revealer_notify_child_state (DzlApplicationWindow *self,
+                                                    GParamSpec           *pspec,
+                                                    GtkRevealer          *revealer)
+{
+  g_assert (DZL_IS_APPLICATION_WINDOW (self));
+  g_assert (GTK_IS_REVEALER (revealer));
+
+  update_titlebar_animation_property (self);
+}
+
 static void
 dzl_application_window_destroy (GtkWidget *widget)
 {
@@ -404,6 +465,10 @@ dzl_application_window_get_property (GObject    *object,
       g_value_set_boolean (value, dzl_application_window_get_fullscreen (self));
       break;
 
+    case PROP_TITLEBAR_ANIMATION:
+      g_value_set_enum (value, dzl_application_window_get_titlebar_animation (self));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -467,6 +532,14 @@ dzl_application_window_class_init (DzlApplicationWindowClass *klass)
                           FALSE,
                           (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  properties [PROP_TITLEBAR_ANIMATION] =
+    g_param_spec_enum ("titlebar-animation",
+                       "Titlebar Animation",
+                       "The state of the titlebar animation",
+                       DZL_TYPE_TITLEBAR_ANIMATION,
+                       DZL_TITLEBAR_ANIMATION_SHOWN,
+                       (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_properties (object_class, N_PROPS, properties);
 }
 
@@ -476,6 +549,8 @@ dzl_application_window_init (DzlApplicationWindow *self)
   DzlApplicationWindowPrivate *priv = dzl_application_window_get_instance_private (self);
   g_autoptr(GPropertyAction) fullscreen = NULL;
 
+  priv->last_titlebar_animation = DZL_TITLEBAR_ANIMATION_SHOWN;
+
   priv->titlebar_container = g_object_new (GTK_TYPE_STACK,
                                            "name", "titlebar_container",
                                            "visible", TRUE,
@@ -513,6 +588,16 @@ dzl_application_window_init (DzlApplicationWindow *self)
                                           "reveal-child", TRUE,
                                           "visible", TRUE,
                                           NULL);
+  g_signal_connect_object (priv->titlebar_revealer,
+                           "notify::child-revealed",
+                           G_CALLBACK (dzl_application_window_revealer_notify_child_state),
+                           self,
+                           G_CONNECT_SWAPPED);
+  g_signal_connect_object (priv->titlebar_revealer,
+                           "notify::reveal-child",
+                           G_CALLBACK (dzl_application_window_revealer_notify_child_state),
+                           self,
+                           G_CONNECT_SWAPPED);
   g_signal_connect (priv->titlebar_revealer,
                     "destroy",
                     G_CALLBACK (gtk_widget_destroyed),
@@ -566,7 +651,10 @@ dzl_application_window_set_fullscreen (DzlApplicationWindow *self,
   fullscreen = !!fullscreen;
 
   if (fullscreen != dzl_application_window_get_fullscreen (self))
-    DZL_APPLICATION_WINDOW_GET_CLASS (self)->set_fullscreen (self, fullscreen);
+    {
+      DZL_APPLICATION_WINDOW_GET_CLASS (self)->set_fullscreen (self, fullscreen);
+      update_titlebar_animation_property (self);
+    }
 }
 
 static void
@@ -644,3 +732,41 @@ dzl_application_window_set_titlebar (DzlApplicationWindow *self,
   if (titlebar != NULL)
     gtk_container_add (GTK_CONTAINER (priv->titlebar_container), titlebar);
 }
+
+DzlTitlebarAnimation
+dzl_application_window_get_titlebar_animation (DzlApplicationWindow *self)
+{
+  DzlApplicationWindowPrivate *priv = dzl_application_window_get_instance_private (self);
+  GtkWidget *titlebar;
+
+  g_return_val_if_fail (DZL_IS_APPLICATION_WINDOW (self), 0);
+
+  titlebar = dzl_application_window_get_titlebar (self);
+  if (titlebar == NULL)
+    return DZL_TITLEBAR_ANIMATION_HIDDEN;
+
+  if (!dzl_application_window_get_fullscreen (self))
+    {
+      if (gtk_widget_get_visible (titlebar))
+        return DZL_TITLEBAR_ANIMATION_SHOWN;
+      else
+        return DZL_TITLEBAR_ANIMATION_HIDDEN;
+    }
+
+  /* If the source from queue_dismissal is 0, then we already
+   * fired and we are hiding the titlebar.
+   */
+  if (priv->titlebar_hiding)
+    return DZL_TITLEBAR_ANIMATION_HIDING;
+
+  /* Titlebar currently visible */
+  if (gtk_revealer_get_reveal_child (priv->titlebar_revealer) &&
+      gtk_revealer_get_child_revealed (priv->titlebar_revealer))
+    return DZL_TITLEBAR_ANIMATION_SHOWN;
+
+  /* Working towards becoming visible */
+  if (gtk_revealer_get_reveal_child (priv->titlebar_revealer))
+    return DZL_TITLEBAR_ANIMATION_SHOWING;
+
+  return DZL_TITLEBAR_ANIMATION_HIDDEN;
+}
diff --git a/src/app/dzl-application-window.h b/src/app/dzl-application-window.h
index d9bfe87..752dfd4 100644
--- a/src/app/dzl-application-window.h
+++ b/src/app/dzl-application-window.h
@@ -30,6 +30,14 @@ G_BEGIN_DECLS
 DZL_AVAILABLE_IN_ALL
 G_DECLARE_DERIVABLE_TYPE (DzlApplicationWindow, dzl_application_window, DZL, APPLICATION_WINDOW, 
GtkApplicationWindow)
 
+typedef enum
+{
+  DZL_TITLEBAR_ANIMATION_HIDDEN  = 0,
+  DZL_TITLEBAR_ANIMATION_SHOWING = 1,
+  DZL_TITLEBAR_ANIMATION_SHOWN   = 2,
+  DZL_TITLEBAR_ANIMATION_HIDING  = 3,
+} DzlTitlebarAnimation;
+
 struct _DzlApplicationWindowClass
 {
   GtkApplicationWindowClass parent_class;
@@ -49,15 +57,17 @@ struct _DzlApplicationWindowClass
 };
 
 DZL_AVAILABLE_IN_ALL
-gboolean   dzl_application_window_get_fullscreen (DzlApplicationWindow *self);
+gboolean              dzl_application_window_get_fullscreen         (DzlApplicationWindow *self);
 DZL_AVAILABLE_IN_ALL
-void       dzl_application_window_set_fullscreen (DzlApplicationWindow *self,
-                                                  gboolean              fullscreen);
+void                  dzl_application_window_set_fullscreen         (DzlApplicationWindow *self,
+                                                                     gboolean              fullscreen);
 DZL_AVAILABLE_IN_ALL
-GtkWidget *dzl_application_window_get_titlebar   (DzlApplicationWindow *self);
+GtkWidget            *dzl_application_window_get_titlebar           (DzlApplicationWindow *self);
 DZL_AVAILABLE_IN_ALL
-void       dzl_application_window_set_titlebar   (DzlApplicationWindow *self,
-                                                  GtkWidget            *titlebar);
+void                  dzl_application_window_set_titlebar           (DzlApplicationWindow *self,
+                                                                     GtkWidget            *titlebar);
+DZL_AVAILABLE_IN_3_38
+DzlTitlebarAnimation  dzl_application_window_get_titlebar_animation (DzlApplicationWindow *self);
 
 G_END_DECLS
 
diff --git a/src/app/meson.build b/src/app/meson.build
index 363569c..a1471a8 100644
--- a/src/app/meson.build
+++ b/src/app/meson.build
@@ -8,6 +8,10 @@ app_sources = [
   'dzl-application-window.c',
 ]
 
+dzl_enum_headers += files([
+  'dzl-application-window.h',
+])
+
 libdazzle_public_headers += files(app_headers)
 libdazzle_public_sources += files(app_sources)
 
diff --git a/src/dzl-enums.c.in b/src/dzl-enums.c.in
index d132b52..0b362ca 100644
--- a/src/dzl-enums.c.in
+++ b/src/dzl-enums.c.in
@@ -4,6 +4,7 @@
 
 #include "dzl-enums.h"
 
+#include "app/dzl-application-window.h"
 #include "files/dzl-file-transfer.h"
 #include "tree/dzl-tree-types.h"
 


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