[totem] backend: embed the fullscreen top header bar in the video widget



commit 80208a260e2c657753a03869b2693f3c0cb94efe
Author: Lionel Landwerlin <llandwerlin gmail com>
Date:   Mon Nov 30 23:29:36 2015 +0000

    backend: embed the fullscreen top header bar in the video widget
    
    On wayland the video has its own subsurface. It is directly painted by the
    compositor on top of Totem's main window. As a result on wayland the top
    header bar is not visible in fullscreen mode.
    
    To solve this issue, we can embed the top header bar in the video widget.
    This solves this issue nicely by having the same behavior on X11 and
    Wayland.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=758876

 configure.ac                     |    4 +-
 src/backend/bacon-video-widget.c |   54 ++++++++++++++++++++++++++++++-
 src/backend/bacon-video-widget.h |    4 ++
 src/totem-object.c               |   67 +++++++-------------------------------
 src/totem-private.h              |    1 -
 5 files changed, 71 insertions(+), 59 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 50f031b..2fa0eef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,7 +53,7 @@ AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums])
 # Requirements
 GLIB_REQS=2.35.0
 GIO_REQS=2.27.92
-GTK_REQS=3.19.3
+GTK_REQS=3.19.4
 TOTEM_PLPARSER_REQS=3.10.1
 VALA_REQS=0.14.1
 PEAS_REQS=1.1.0
@@ -93,7 +93,7 @@ GST_PLUG_BASE_REQS=1.6.0
 GSTPLUG_REQS=0.11.93
 CLUTTER_REQS=1.17.3
 CLUTTER_GST_REQS=2.99.2
-CLUTTER_GTK_REQS=1.5.5
+CLUTTER_GTK_REQS=1.7.1
 
 dnl Check for the required GStreamer versions for missing plugins
 dnl installation, unless this has been disabled.
diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c
index 59a9c20..0497950 100644
--- a/src/backend/bacon-video-widget.c
+++ b/src/backend/bacon-video-widget.c
@@ -204,6 +204,7 @@ struct BaconVideoWidgetPrivate
   ClutterActor                *stage;
   ClutterActor                *texture;
   ClutterActor                *frame;
+  ClutterActor                *header_controls;
   ClutterActor                *controls;
   ClutterActor                *spinner;
 
@@ -769,12 +770,24 @@ set_controls_visibility (BaconVideoWidget *bvw,
                         gboolean          animate)
 {
   guint8 opacity = visible ? OVERLAY_OPACITY : 0;
+  gint header_controls_height;
+  gfloat header_controls_y;
+  guint duration;
+
+  gtk_widget_get_preferred_height (gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR 
(bvw->priv->header_controls)),
+                                   NULL,
+                                   &header_controls_height);
+  header_controls_y = visible ? 0 : -header_controls_height;
+
+  duration = animate ? 250 : 0;
 
   /* FIXME:
    * Using a show/hide seems to not trigger the
    * controls to redraw, so let's change the opacity instead */
-  clutter_actor_set_easing_duration (bvw->priv->controls, animate ? 250 : 0);
+  clutter_actor_set_easing_duration (bvw->priv->controls, duration);
+  clutter_actor_set_easing_duration (bvw->priv->header_controls, duration);
   clutter_actor_set_opacity (bvw->priv->controls, opacity);
+  clutter_actor_set_y (bvw->priv->header_controls, header_controls_y);
 
   set_show_cursor (bvw, visible);
   if (visible && animate)
@@ -3721,6 +3734,14 @@ bacon_video_widget_get_controls_object (BaconVideoWidget *bvw)
   return G_OBJECT (bvw->priv->controls);
 }
 
+GObject *
+bacon_video_widget_get_header_controls_object (BaconVideoWidget *bvw)
+{
+  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), NULL);
+
+  return G_OBJECT (gtk_clutter_actor_get_widget (GTK_CLUTTER_ACTOR (bvw->priv->header_controls)));
+}
+
 /* =========================================== */
 /*                                             */
 /*               Play/Pause, Stop              */
@@ -6095,6 +6116,20 @@ bacon_video_widget_initable_init (GInitable     *initable,
                                         bvw->priv->frame);
   clutter_actor_hide (bvw->priv->spinner);
 
+  /* Fullscreen header controls */
+  bvw->priv->header_controls = gtk_clutter_actor_new ();
+  clutter_actor_set_name (bvw->priv->header_controls, "header-controls");
+  clutter_actor_add_constraint (bvw->priv->header_controls,
+                                clutter_bind_constraint_new (bvw->priv->stage,
+                                                             CLUTTER_BIND_WIDTH,
+                                                             0));
+  layout = g_object_new (CLUTTER_TYPE_ACTOR,
+                        "layout-manager", clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, 
CLUTTER_BIN_ALIGNMENT_START),
+                        NULL);
+  clutter_actor_set_name (layout, "layout");
+  clutter_actor_add_child (layout, bvw->priv->header_controls);
+  clutter_actor_add_child (bvw->priv->stage, layout);
+
   /* The controls */
   bvw->priv->controls = bacon_video_controls_actor_new ();
   clutter_actor_set_name (bvw->priv->controls, "controls");
@@ -6250,6 +6285,23 @@ bacon_video_widget_set_rate (BaconVideoWidget *bvw,
   return retval;
 }
 
+/**
+ * bacon_video_widget_set_fullscreen:
+ * @bvw: a #BaconVideoWidget
+ * @fullscreen: the new fullscreen state
+ *
+ * Sets the fullscreen state, enabling a toplevel header bar sliding from
+ * the top of the video widget.
+ **/
+void
+bacon_video_widget_set_fullscreen (BaconVideoWidget *bvw,
+                                   gboolean          fullscreen)
+{
+  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
+
+  g_object_set (bvw->priv->header_controls, "visible", fullscreen, NULL);
+}
+
 /*
  * vim: sw=2 ts=8 cindent noai bs=2
  */
diff --git a/src/backend/bacon-video-widget.h b/src/backend/bacon-video-widget.h
index 172c2bb..8d63933 100644
--- a/src/backend/bacon-video-widget.h
+++ b/src/backend/bacon-video-widget.h
@@ -186,6 +186,9 @@ gboolean bacon_video_widget_set_rate                 (BaconVideoWidget *bvw,
                                                  gfloat new_rate);
 gfloat bacon_video_widget_get_rate              (BaconVideoWidget *bvw);
 
+void bacon_video_widget_set_fullscreen           (BaconVideoWidget *bvw,
+                                                  gboolean          fullscreen);
+
 /* Metadata */
 /**
  * BvwMetadataType:
@@ -433,6 +436,7 @@ void bacon_video_widget_unmark_popup_busy         (BaconVideoWidget *bvw,
                                                   const char       *reason);
 
 GObject * bacon_video_widget_get_controls_object  (BaconVideoWidget *bvw);
+GObject * bacon_video_widget_get_header_controls_object (BaconVideoWidget *bvw);
 
 G_END_DECLS
 
diff --git a/src/totem-object.c b/src/totem-object.c
index f419620..fcb5c4a 100644
--- a/src/totem-object.c
+++ b/src/totem-object.c
@@ -1635,30 +1635,6 @@ totem_object_pause (TotemObject *totem)
        }
 }
 
-static void
-update_toolbar_visibility (TotemObject *totem,
-                          gboolean     animate)
-{
-       gboolean visible;
-       guint duration;
-
-       if (totem->controls_visibility != TOTEM_CONTROLS_FULLSCREEN) {
-               visible = FALSE;
-               duration = 0;
-       } else {
-               g_object_get (G_OBJECT (totem->bvw), "reveal-controls", &visible, NULL);
-               duration = animate ? 250 : 0;
-       }
-
-       if (visible)
-               gtk_widget_show (totem->revealer);
-
-       /* We don't change the transition type, because it causes
-        * a queue resize, and it might short-circuit the animation */
-       gtk_revealer_set_transition_duration (GTK_REVEALER (totem->revealer), duration);
-       gtk_revealer_set_reveal_child (GTK_REVEALER (totem->revealer), visible);
-}
-
 gboolean
 window_state_event_cb (GtkWidget           *window,
                       GdkEventWindowState *event,
@@ -1682,7 +1658,8 @@ window_state_event_cb (GtkWidget           *window,
                show_controls (totem, TRUE);
        }
 
-       update_toolbar_visibility (totem, FALSE);
+       bacon_video_widget_set_fullscreen (totem->bvw,
+                                          totem->controls_visibility == TOTEM_CONTROLS_FULLSCREEN);
 
        action = g_action_map_lookup_action (G_ACTION_MAP (totem), "fullscreen");
        g_simple_action_set_state (G_SIMPLE_ACTION (action),
@@ -2473,14 +2450,6 @@ update_fill (TotemObject *totem, gdouble level)
 }
 
 static void
-on_reveal_controls_changed (GObject     *gobject,
-                           GParamSpec  *pspec,
-                           TotemObject *totem)
-{
-       update_toolbar_visibility (totem, TRUE);
-}
-
-static void
 update_seekable (TotemObject *totem)
 {
        gboolean seekable;
@@ -3960,24 +3929,13 @@ grilo_widget_setup (TotemObject *totem)
 }
 
 static void
-child_revealed_changed_cb (GObject      *object,
-                          GParamSpec   *pspec,
-                          gpointer      user_data)
-{
-       gboolean val;
-
-       g_object_get (object, "child-revealed", &val, NULL);
-       if (!val)
-               gtk_widget_hide (GTK_WIDGET (object));
-}
-
-static void
 add_fullscreen_toolbar (TotemObject *totem)
 {
-       GtkWidget *item;
+       GtkWidget *container, *item;
        GMenuModel *menu;
 
-       totem->revealer = GTK_WIDGET (gtk_builder_get_object (totem->xml, "toolbar-revealer"));
+       container = GTK_WIDGET (bacon_video_widget_get_header_controls_object (totem->bvw));
+
        totem->fullscreen_header = g_object_new (TOTEM_TYPE_MAIN_TOOLBAR,
                                                 "show-search-button", FALSE,
                                                 "show-select-button", FALSE,
@@ -4010,11 +3968,8 @@ add_fullscreen_toolbar (TotemObject *totem)
                          G_CALLBACK (popup_menu_shown_cb), totem);
        totem->fullscreen_gear_button = item;
 
-       gtk_container_add (GTK_CONTAINER (totem->revealer), totem->fullscreen_header);
+       gtk_container_add (GTK_CONTAINER (container), totem->fullscreen_header);
        gtk_widget_show_all (totem->fullscreen_header);
-
-       g_signal_connect (totem->revealer, "notify::child-revealed",
-                         G_CALLBACK (child_revealed_changed_cb), NULL);
 }
 
 void
@@ -4023,6 +3978,8 @@ video_widget_create (TotemObject *totem)
        GError *err = NULL;
        GtkContainer *container;
        BaconVideoWidget **bvw;
+       GdkWindow *window;
+       gboolean fullscreen;
 
        totem->bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (&err));
 
@@ -4032,6 +3989,10 @@ video_widget_create (TotemObject *totem)
                        g_error_free (err);
        }
 
+       fullscreen = window && ((gdk_window_get_state (window) & GDK_WINDOW_STATE_FULLSCREEN) != 0);
+
+       window = gtk_widget_get_window (totem->win);
+       bacon_video_widget_set_fullscreen (totem->bvw, fullscreen);
        totem->controls = bacon_video_widget_get_controls_object (totem->bvw);
 
        g_signal_connect_after (G_OBJECT (totem->bvw),
@@ -4071,10 +4032,6 @@ video_widget_create (TotemObject *totem)
                        G_CALLBACK (on_error_event),
                        totem);
        g_signal_connect (G_OBJECT (totem->bvw),
-                         "notify::reveal-controls",
-                         G_CALLBACK (on_reveal_controls_changed),
-                         totem);
-       g_signal_connect (G_OBJECT (totem->bvw),
                          "seek-requested",
                          G_CALLBACK (on_seek_requested_event),
                          totem);
diff --git a/src/totem-private.h b/src/totem-private.h
index e844b8c..76942b1 100644
--- a/src/totem-private.h
+++ b/src/totem-private.h
@@ -87,7 +87,6 @@ struct _TotemObject {
        BaconTimeLabel *time_rem_label;
        GtkWidget *header;
 
-       GtkWidget *revealer;
        GtkWidget *fullscreen_header;
        GtkWidget *fullscreen_gear_button;
 


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