[totem/wip/hadess/glsink: 12/13] reimplement popup showing/hiding
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [totem/wip/hadess/glsink: 12/13] reimplement popup showing/hiding
- Date: Fri, 28 Jan 2022 17:37:43 +0000 (UTC)
commit 4a89341575cba977d5738dc8045a7ffaaed1db66
Author: Bastien Nocera <hadess hadess net>
Date: Fri Jan 28 16:50:37 2022 +0100
reimplement popup showing/hiding
src/backend/bacon-video-widget.c | 332 +++++++++------------------------------
src/backend/bacon-video-widget.h | 9 +-
src/totem-object.c | 207 +++++++++++++++++++++---
src/totem-private.h | 4 +
4 files changed, 259 insertions(+), 293 deletions(-)
---
diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c
index d08225dd4..f4c38d9ca 100644
--- a/src/backend/bacon-video-widget.c
+++ b/src/backend/bacon-video-widget.c
@@ -87,7 +87,6 @@
#define DEFAULT_CONTROLS_WIDTH 600 /* In pixels */
#define LOGO_SIZE 256 /* Maximum size of the logo */
#define REWIND_OR_PREVIOUS 4000
-#define POPUP_HIDING_TIMEOUT 2
#define MAX_NETWORK_SPEED 10752
#define BUFFERING_LEFT_RATIO 1.1
@@ -119,6 +118,7 @@ enum
SIGNAL_BUFFERING,
SIGNAL_MISSING_PLUGINS,
SIGNAL_DOWNLOAD_BUFFERING,
+ SIGNAL_PLAY_STARTING,
LAST_SIGNAL
};
@@ -142,7 +142,7 @@ enum
PROP_HUE,
PROP_AUDIO_OUTPUT_TYPE,
PROP_AV_OFFSET,
- PROP_REVEAL_CONTROLS
+ PROP_SHOW_CURSOR,
};
static const gchar *video_props_str[4] = {
@@ -191,11 +191,6 @@ struct _BaconVideoWidget
GdkCursor *cursor;
- /* Controls */
- gboolean reveal_controls;
- guint transition_timeout_id;
- GHashTable *busy_popup_ht; /* key=reason string, value=gboolean */
-
/* Visual effects */
GstElement *audio_capsfilter;
GstElement *audio_pitchcontrol;
@@ -280,9 +275,6 @@ static gboolean bacon_video_widget_seek_time_no_lock (BaconVideoWidget *bvw,
gint64 _time,
GstSeekFlags flag,
GError **error);
-static void set_controls_visibility (BaconVideoWidget *bvw,
- gboolean visible,
- gboolean animate);
typedef struct {
GstTagList *tags;
@@ -376,36 +368,6 @@ bvw_check_if_video_decoder_is_missing (BaconVideoWidget * bvw)
}
}
-static gboolean
-leave_notify_cb (GtkWidget *widget,
- GdkEventCrossing *event,
- gpointer user_data)
-{
- gboolean res = GDK_EVENT_PROPAGATE;
- BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (user_data);
- GdkDevice *device;
-
- if (event->detail != GDK_NOTIFY_NONLINEAR &&
- event->detail != GDK_NOTIFY_NONLINEAR_VIRTUAL)
- return res;
-
- device = gdk_event_get_source_device ((GdkEvent *) event);
- if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN)
- return res;
-
- if (bvw->reveal_controls) {
- gboolean not_busy;
-
- not_busy = g_hash_table_size (bvw->busy_popup_ht) == 0;
- if (not_busy) {
- GST_DEBUG ("will hide because we're not busy and cursor left");
- set_controls_visibility (bvw, FALSE, TRUE);
- }
- }
-
- return res;
-}
-
static void
bacon_video_widget_realize (GtkWidget * widget)
{
@@ -417,11 +379,6 @@ bacon_video_widget_realize (GtkWidget * widget)
gtk_widget_set_realized (widget, TRUE);
/* setup the toplevel, ready to be resized */
- toplevel = gtk_widget_get_toplevel (widget);
- gtk_window_set_geometry_hints (GTK_WINDOW (toplevel), widget, NULL, 0);
- g_signal_connect (G_OBJECT (toplevel), "leave-notify-event",
- G_CALLBACK (leave_notify_cb), bvw);
-
bvw->missing_plugins_cancellable = g_cancellable_new ();
g_object_set_data_full (G_OBJECT (bvw), "missing-plugins-cancellable",
bvw->missing_plugins_cancellable, g_object_unref);
@@ -438,10 +395,6 @@ bacon_video_widget_unrealize (GtkWidget *widget)
gtk_widget_set_realized (widget, FALSE);
- toplevel = gtk_widget_get_toplevel (widget);
- g_signal_handlers_disconnect_by_func (G_OBJECT (toplevel),
- leave_notify_cb, bvw);
-
g_cancellable_cancel (bvw->missing_plugins_cancellable);
bvw->missing_plugins_cancellable = NULL;
g_object_set_data (G_OBJECT (bvw), "missing-plugins-cancellable", NULL);
@@ -458,90 +411,6 @@ set_current_actor (BaconVideoWidget *bvw)
draw_logo ? "logo" : "video");
}
-static void
-unschedule_hiding_popup (BaconVideoWidget *bvw)
-{
- if (bvw->transition_timeout_id > 0)
- g_source_remove (bvw->transition_timeout_id);
- bvw->transition_timeout_id = 0;
-}
-
-static gboolean
-hide_popup_timeout_cb (BaconVideoWidget *bvw)
-{
- set_controls_visibility (bvw, FALSE, TRUE);
- unschedule_hiding_popup (bvw);
- return G_SOURCE_REMOVE;
-}
-
-static void
-schedule_hiding_popup (BaconVideoWidget *bvw)
-{
- unschedule_hiding_popup (bvw);
- bvw->transition_timeout_id = g_timeout_add_seconds (POPUP_HIDING_TIMEOUT, (GSourceFunc)
hide_popup_timeout_cb, bvw);
- g_source_set_name_by_id (bvw->transition_timeout_id, "[totem] hide_popup_timeout_cb");
-}
-
-static void
-set_show_cursor (BaconVideoWidget *bvw,
- gboolean show_cursor)
-{
- GdkWindow *window;
-
- bvw->cursor_shown = show_cursor;
- window = gtk_widget_get_window (GTK_WIDGET (bvw));
-
- if (!window)
- return;
-
- if (show_cursor == FALSE) {
- GdkCursor *cursor;
- GdkDisplay *display;
-
- display = gdk_window_get_display (window);
- cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
- gdk_window_set_cursor (window, cursor);
- g_object_unref (cursor);
- } else {
- gdk_window_set_cursor (window, bvw->cursor);
- }
-}
-
-static void
-set_controls_visibility (BaconVideoWidget *bvw,
- gboolean visible,
- gboolean animate)
-{
-#if 0
- 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->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->controls, duration);
- clutter_actor_set_easing_duration (bvw->header_controls, duration);
- clutter_actor_set_opacity (bvw->controls, opacity);
- clutter_actor_set_y (bvw->header_controls, header_controls_y);
-
- set_show_cursor (bvw, visible);
- if (visible && animate)
- schedule_hiding_popup (bvw);
-
- bvw->reveal_controls = visible;
- g_object_notify (G_OBJECT (bvw), "reveal-controls");
-#endif
-}
-
static void
translate_coords (GtkWidget *widget,
GdkWindow *window,
@@ -561,23 +430,6 @@ translate_coords (GtkWidget *widget,
}
}
-static gboolean
-ignore_event (BaconVideoWidget *bvw,
- int x,
- int y)
-{
-#if 0
- ClutterActor *actor;
-
- actor = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (bvw->stage), CLUTTER_PICK_REACTIVE, x, y);
-
- /* Eat the GTK+ event if we're not clicking on the video itself */
- if (actor == bvw->controls)
- return TRUE;
-#endif
- return FALSE;
-}
-
/* need to use gstnavigation interface for these vmethods, to allow for the sink
to map screen coordinates to video coordinates in the presence of e.g.
hardware scaling */
@@ -599,20 +451,6 @@ bacon_video_widget_motion_notify (GtkWidget *widget, GdkEventMotion *event)
res |= GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
device = gdk_event_get_source_device ((GdkEvent *) event);
- if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN)
- return res;
-
- if (!bvw->reveal_controls)
- set_controls_visibility (bvw, TRUE, TRUE);
-
- translate_coords (widget, event->window, event->x, event->y, &x, &y);
- if (ignore_event (bvw, x, y)) {
- /* Is the mouse on the popups? */
- unschedule_hiding_popup (bvw);
- } else {
- schedule_hiding_popup (bvw);
- }
-
return res;
}
@@ -621,7 +459,6 @@ bacon_video_widget_button_press_or_release (GtkWidget *widget, GdkEventButton *e
{
gboolean res = FALSE;
BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (widget);
- int x, y;
GdkDevice *device;
device = gdk_event_get_source_device ((GdkEvent *) event);
@@ -630,10 +467,6 @@ bacon_video_widget_button_press_or_release (GtkWidget *widget, GdkEventButton *e
g_return_val_if_fail (bvw->play != NULL, FALSE);
- translate_coords (widget, event->window, event->x, event->y, &x, &y);
- if (ignore_event (bvw, x, y))
- return GDK_EVENT_STOP;
-
if (event->type != GDK_BUTTON_PRESS &&
event->type != GDK_BUTTON_RELEASE)
goto bail;
@@ -641,8 +474,10 @@ bacon_video_widget_button_press_or_release (GtkWidget *widget, GdkEventButton *e
if (bvw->navigation &&
event->button == 1 &&
bvw->is_menu != FALSE) {
+ int x, y;
const char *event_str;
event_str = (event->type == GDK_BUTTON_PRESS) ? "mouse-button-press" : "mouse-button-release";
+ translate_coords (widget, event->window, event->x, event->y, &x, &y);
gst_navigation_send_mouse_event (bvw->navigation,
event_str, event->button, x, y);
@@ -888,14 +723,14 @@ bacon_video_widget_class_init (BaconVideoWidgetClass * klass)
G_PARAM_STATIC_STRINGS));
/**
- * BaconVideoWidget:reveal-controls:
+ * BaconVideoWidget:show-cursor:
*
- * Whether to show or hide the controls.
+ * Whether the mouse cursor is shown.
**/
- g_object_class_install_property (object_class, PROP_REVEAL_CONTROLS,
- g_param_spec_boolean ("reveal-controls", "Reveal controls",
- "Whether to show or hide the controls.", FALSE,
- G_PARAM_READABLE |
+ g_object_class_install_property (object_class, PROP_SHOW_CURSOR,
+ g_param_spec_boolean ("show-cursor", "Show cursor",
+ "Whether the mouse cursor is shown.", FALSE,
+ G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/* Signals */
@@ -1052,6 +887,25 @@ bacon_video_widget_class_init (BaconVideoWidgetClass * klass)
0,
NULL, NULL,
g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE);
+
+ /**
+ * BaconVideoWidget::play-starting:
+ * @bvw: the #BaconVideoWidget which received the signal
+ *
+ * Emitted when a movie will start playing, meaning it's not buffering, pausing
+ * waiting for plugins to be installed, drives to be mounted or authentication
+ * to succeed.
+ *
+ * This usually means that popups showing state can be hidden.
+ *
+ **/
+ bvw_signals[SIGNAL_PLAY_STARTING] =
+ g_signal_new ("play-starting",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
static void
@@ -1088,8 +942,6 @@ bacon_video_widget_init (BaconVideoWidget * bvw)
bvw->auth_last_result = G_MOUNT_OPERATION_HANDLED;
bvw->auth_dialog = NULL;
- bvw->busy_popup_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
bacon_video_widget_gst_missing_plugins_block ();
}
@@ -2521,8 +2373,6 @@ bacon_video_widget_finalize (GObject * object)
g_type_class_unref (g_type_class_peek (BVW_TYPE_DVD_EVENT));
g_type_class_unref (g_type_class_peek (BVW_TYPE_ROTATION));
- unschedule_hiding_popup (bvw);
-
if (bvw->bus) {
/* make bus drop all messages to make sure none of our callbacks is ever
* called again (main loop might be run again to display error dialog) */
@@ -2538,7 +2388,6 @@ bacon_video_widget_finalize (GObject * object)
g_clear_pointer (&bvw->referrer, g_free);
g_clear_pointer (&bvw->mrl, g_free);
g_clear_pointer (&bvw->subtitle_uri, g_free);
- g_clear_pointer (&bvw->busy_popup_ht, g_hash_table_destroy);
g_clear_object (&bvw->clock);
@@ -2620,6 +2469,9 @@ bacon_video_widget_set_property (GObject * object, guint property_id,
case PROP_AV_OFFSET:
g_object_set_property (G_OBJECT (bvw->play), "av-offset", value);
break;
+ case PROP_SHOW_CURSOR:
+ bacon_video_widget_set_show_cursor (bvw, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -2680,8 +2532,8 @@ bacon_video_widget_get_property (GObject * object, guint property_id,
case PROP_AV_OFFSET:
g_object_get_property (G_OBJECT (bvw->play), "av-offset", value);
break;
- case PROP_REVEAL_CONTROLS:
- g_value_set_boolean (value, bvw->reveal_controls);
+ case PROP_SHOW_CURSOR:
+ g_value_set_boolean (value, bvw->cursor_shown);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -3272,81 +3124,6 @@ bacon_video_widget_set_audio_output_type (BaconVideoWidget *bvw,
set_audio_filter (bvw);
}
-/**
- * bacon_video_widget_show_popup:
- * @bvw: a #BaconVideoWidget
- *
- * Show the video controls popup, and schedule for it to be hidden again after
- * a timeout.
- *
- * Since: 3.12
- */
-void
-bacon_video_widget_show_popup (BaconVideoWidget *bvw)
-{
- g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
-
- set_controls_visibility (bvw, TRUE, FALSE);
- schedule_hiding_popup (bvw);
-}
-
-/**
- * bacon_video_widget_mark_popup_busy:
- * @bvw: a #BaconVideoWidget
- * @reason: human-readable reason for the controls popup being marked as busy
- *
- * Mark the video controls popup as busy, for the given @reason. Use
- * bacon_video_widget_unmark_popup_busy() to undo.
- *
- * Since: 3.12
- */
-void
-bacon_video_widget_mark_popup_busy (BaconVideoWidget *bvw,
- const char *reason)
-{
- g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
-
- g_hash_table_insert (bvw->busy_popup_ht,
- g_strdup (reason),
- GINT_TO_POINTER (1));
-
- set_controls_visibility (bvw, TRUE, FALSE);
-
- GST_DEBUG ("Adding popup busy for reason %s", reason);
-
- unschedule_hiding_popup (bvw);
-}
-
-/**
- * bacon_video_widget_unmark_popup_busy:
- * @bvw: a #BaconVideoWidget
- * @reason: human-readable reason for the controls popup being unmarked as busy
- *
- * Unmark the video controls popup as busy, for the given @reason. The popup
- * must previously have been marked as busy using
- * bacon_video_widget_mark_popup_busy().
- *
- * Since: 3.12
- */
-void
-bacon_video_widget_unmark_popup_busy (BaconVideoWidget *bvw,
- const char *reason)
-{
-#if 0
- g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
-
- g_hash_table_remove (bvw->busy_popup_ht, reason);
-
- GST_DEBUG ("Removing popup busy for reason %s", reason);
-
- if (g_hash_table_size (bvw->busy_popup_ht) == 0 &&
- clutter_actor_get_opacity (bvw->controls) != 0) {
- GST_DEBUG ("Will hide popup soon");
- schedule_hiding_popup (bvw);
- }
-#endif
-}
-
/* =========================================== */
/* */
/* Play/Pause, Stop */
@@ -3621,8 +3398,6 @@ bacon_video_widget_open (BaconVideoWidget *bvw,
bvw->target_state = GST_STATE_PAUSED;
bvw_clear_missing_plugins_messages (bvw);
- bacon_video_widget_mark_popup_busy (bvw, "opening file");
-
gst_element_set_state (bvw->play, GST_STATE_PAUSED);
g_signal_emit (bvw, bvw_signals[SIGNAL_CHANNELS_CHANGE], 0);
@@ -3687,7 +3462,7 @@ bacon_video_widget_play (BaconVideoWidget * bvw, GError ** error)
return FALSE;
}
- bacon_video_widget_unmark_popup_busy (bvw, "opening file");
+ g_signal_emit (bvw, bvw_signals[SIGNAL_PLAY_STARTING], 0);
GST_DEBUG ("play");
gst_element_set_state (bvw->play, GST_STATE_PLAYING);
@@ -4361,6 +4136,43 @@ bacon_video_widget_get_volume (BaconVideoWidget * bvw)
return bvw->volume;
}
+/**
+ * bacon_video_widget_set_show_cursor:
+ * @bvw: a #BaconVideoWidget
+ * @show_cursor: %TRUE to show the cursor, %FALSE otherwise
+ *
+ * Sets whether the cursor should be shown when it is over the video
+ * widget. If @show_cursor is %FALSE, the cursor will be invisible
+ * when it is moved over the video widget.
+ **/
+void
+bacon_video_widget_set_show_cursor (BaconVideoWidget * bvw,
+ gboolean show_cursor)
+{
+ GdkWindow *window;
+
+ g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
+
+
+ bvw->cursor_shown = show_cursor;
+ window = gtk_widget_get_window (GTK_WIDGET (bvw));
+
+ if (!window)
+ return;
+
+ if (show_cursor == FALSE) {
+ GdkCursor *cursor;
+ GdkDisplay *display;
+
+ display = gdk_window_get_display (window);
+ cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
+ gdk_window_set_cursor (window, cursor);
+ g_object_unref (cursor);
+ } else {
+ gdk_window_set_cursor (window, bvw->cursor);
+ }
+}
+
/**
* bacon_video_widget_set_aspect_ratio:
* @bvw: a #BaconVideoWidget
diff --git a/src/backend/bacon-video-widget.h b/src/backend/bacon-video-widget.h
index 4b90bf0cc..4221b608b 100644
--- a/src/backend/bacon-video-widget.h
+++ b/src/backend/bacon-video-widget.h
@@ -142,6 +142,8 @@ gfloat bacon_video_widget_get_rate (BaconVideoWidget *bvw);
void bacon_video_widget_set_fullscreen (BaconVideoWidget *bvw,
gboolean fullscreen);
+void bacon_video_widget_set_show_cursor (BaconVideoWidget *bvw,
+ gboolean show_cursor);
/* Metadata */
/**
@@ -411,10 +413,3 @@ BvwAudioOutputType bacon_video_widget_get_audio_output_type
(BaconVideoWidget *bvw);
void bacon_video_widget_set_audio_output_type (BaconVideoWidget *bvw,
BvwAudioOutputType type);
-
-/* OSD */
-void bacon_video_widget_show_popup (BaconVideoWidget *bvw);
-void bacon_video_widget_mark_popup_busy (BaconVideoWidget *bvw,
- const char *reason);
-void bacon_video_widget_unmark_popup_busy (BaconVideoWidget *bvw,
- const char *reason);
diff --git a/src/totem-object.c b/src/totem-object.c
index 77b26f161..a98c0897b 100644
--- a/src/totem-object.c
+++ b/src/totem-object.c
@@ -77,6 +77,9 @@
#define DEFAULT_WINDOW_W 650
#define DEFAULT_WINDOW_H 500
+#define POPUP_HIDING_TIMEOUT 2 /* seconds */
+#define OVERLAY_OPACITY 0.86
+
#define TOTEM_SESSION_SAVE_TIMEOUT 10 /* seconds */
/* casts are to shut gcc up */
@@ -527,6 +530,8 @@ totem_object_init (TotemObject *totem)
g_application_add_main_option_entries (G_APPLICATION (totem), all_options);
g_application_add_option_group (G_APPLICATION (totem), bacon_video_widget_get_option_group ());
+ totem->busy_popup_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
totem_app_actions_setup (totem);
}
@@ -535,6 +540,7 @@ totem_object_finalize (GObject *object)
{
TotemObject *totem = TOTEM_OBJECT (object);
+ g_clear_pointer (&totem->busy_popup_ht, g_hash_table_destroy);
g_clear_pointer (&totem->title, g_free);
g_clear_pointer (&totem->subtitle, g_free);
g_clear_pointer (&totem->search_string, g_free);
@@ -997,6 +1003,41 @@ totem_object_set_current_subtitle (TotemObject *totem, const char *subtitle_uri)
totem_playlist_set_current_subtitle (totem->playlist, subtitle_uri);
}
+static void set_controls_visibility (TotemObject *totem,
+ gboolean visible,
+ gboolean animate);
+
+static void
+unschedule_hiding_popup (TotemObject *totem)
+{
+ if (totem->transition_timeout_id > 0)
+ g_source_remove (totem->transition_timeout_id);
+ totem->transition_timeout_id = 0;
+}
+
+static gboolean
+hide_popup_timeout_cb (TotemObject *totem)
+{
+ set_controls_visibility (totem, FALSE, TRUE);
+ unschedule_hiding_popup (totem);
+ return G_SOURCE_REMOVE;
+}
+
+static void
+schedule_hiding_popup (TotemObject *totem)
+{
+ unschedule_hiding_popup (totem);
+ totem->transition_timeout_id = g_timeout_add_seconds (POPUP_HIDING_TIMEOUT, (GSourceFunc)
hide_popup_timeout_cb, totem);
+ g_source_set_name_by_id (totem->transition_timeout_id, "[totem] schedule_hiding_popup");
+}
+
+static void
+totem_show_popup (TotemObject *totem)
+{
+ set_controls_visibility (totem, TRUE, FALSE);
+ schedule_hiding_popup (totem);
+}
+
void
totem_object_set_main_page (TotemObject *totem,
const char *page_id)
@@ -1034,7 +1075,7 @@ totem_object_set_main_page (TotemObject *totem,
gtk_widget_show (totem->gear_button);
gtk_widget_hide (totem->add_button);
gtk_widget_hide (totem->main_menu_button);
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
} else if (g_strcmp0 (page_id, "grilo") == 0) {
totem_grilo_start (TOTEM_GRILO (totem->grilo));
g_object_set (totem->header,
@@ -1239,6 +1280,10 @@ totem_remote_setting_get_type (void)
return etype;
}
+static void
+bacon_video_widget_unmark_popup_busy (TotemObject *totem,
+ const char *reason);
+
static void
reset_seek_status (TotemObject *totem)
{
@@ -1247,7 +1292,7 @@ reset_seek_status (TotemObject *totem)
if (totem->seek_lock != FALSE) {
totem->seek_lock = FALSE;
- bacon_video_widget_unmark_popup_busy (totem->bvw, "seek started");
+ bacon_video_widget_unmark_popup_busy (totem, "seek started");
bacon_video_widget_seek (totem->bvw, 0, NULL);
bacon_video_widget_stop (totem->bvw);
play_pause_set_label (totem, STATE_STOPPED);
@@ -1825,6 +1870,91 @@ totem_object_set_next_subtitle (TotemObject *totem,
totem->next_subtitle = g_strdup (subtitle);
}
+static void
+set_controls_visibility (TotemObject *totem,
+ gboolean visible,
+ gboolean animate)
+{
+ double opacity = visible ? OVERLAY_OPACITY : 0;
+#if 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->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->controls, duration);
+ clutter_actor_set_easing_duration (bvw->header_controls, duration);
+ clutter_actor_set_opacity (bvw->controls, opacity);
+ clutter_actor_set_y (bvw->header_controls, header_controls_y);
+#endif
+ gtk_widget_set_opacity (GTK_WIDGET (gtk_builder_get_object (totem->controls, "toolbar")), opacity);
+ //FIXME
+ bacon_video_widget_set_show_cursor (totem->bvw, visible);
+ if (visible && animate)
+ schedule_hiding_popup (totem);
+ totem->reveal_controls = visible;
+}
+
+/**
+ * bacon_video_widget_mark_popup_busy:
+ * @bvw: a #BaconVideoWidget
+ * @reason: human-readable reason for the controls popup being marked as busy
+ *
+ * Mark the video controls popup as busy, for the given @reason. Use
+ * bacon_video_widget_unmark_popup_busy() to undo.
+ *
+ * Since: 3.12
+ */
+static void
+bacon_video_widget_mark_popup_busy (TotemObject *totem,
+ const char *reason)
+{
+ g_hash_table_insert (totem->busy_popup_ht,
+ g_strdup (reason),
+ GINT_TO_POINTER (1));
+
+ set_controls_visibility (totem, TRUE, FALSE);
+
+ g_debug ("Adding popup busy for reason %s", reason);
+
+ unschedule_hiding_popup (totem);
+}
+
+/**
+ * bacon_video_widget_unmark_popup_busy:
+ * @bvw: a #BaconVideoWidget
+ * @reason: human-readable reason for the controls popup being unmarked as busy
+ *
+ * Unmark the video controls popup as busy, for the given @reason. The popup
+ * must previously have been marked as busy using
+ * bacon_video_widget_mark_popup_busy().
+ *
+ * Since: 3.12
+ */
+void
+bacon_video_widget_unmark_popup_busy (TotemObject *totem,
+ const char *reason)
+{
+ g_hash_table_remove (totem->busy_popup_ht, reason);
+
+ g_debug ("Removing popup busy for reason %s", reason);
+
+ if (g_hash_table_size (totem->busy_popup_ht) == 0 &&
+ gtk_widget_get_opacity (GTK_WIDGET (gtk_builder_get_object (totem->controls, "toolbar"))) != 0.0) {
+ g_debug ("Will hide popup soon");
+ schedule_hiding_popup (totem);
+ }
+}
+
/**
* totem_object_set_mrl:
* @totem: a #TotemObject
@@ -1892,6 +2022,7 @@ totem_object_set_mrl (TotemObject *totem,
g_application_mark_busy (G_APPLICATION (totem));
bacon_video_widget_open (totem->bvw, mrl);
+ bacon_video_widget_mark_popup_busy (totem, "opening file");
if (subtitle) {
bacon_video_widget_set_text_subtitle (totem->bvw, subtitle);
} else if (autoload_sub) {
@@ -2523,6 +2654,34 @@ on_download_buffering_event (BaconVideoWidget *bvw, gdouble level, TotemObject *
update_fill (totem, level);
}
+static void
+play_starting_cb (BaconVideoWidget *bvw,
+ TotemObject *totem)
+{
+ bacon_video_widget_unmark_popup_busy (totem, "opening file");
+}
+
+static gboolean
+on_bvw_motion_notify_cb (BaconVideoWidget *bvw,
+ GdkEventMotion *event,
+ TotemObject *totem)
+{
+ if (!totem->reveal_controls)
+ set_controls_visibility (totem, TRUE, TRUE);
+
+ //translate_coords (widget, event->window, event->x, event->y, &x, &y);
+#if 0
+ if (ignore_event (bvw, x, y)) {
+ /* Is the mouse on the popups? */
+ unschedule_hiding_popup (bvw);
+ } else {
+#endif
+ schedule_hiding_popup (totem);
+// }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
static void
update_fill (TotemObject *totem, gdouble level)
{
@@ -2684,7 +2843,7 @@ seek_slider_pressed_cb (GtkWidget *widget, GdkEventButton *event, TotemObject *t
event->button = GDK_BUTTON_PRIMARY;
totem->seek_lock = TRUE;
- bacon_video_widget_mark_popup_busy (totem->bvw, "seek started");
+ bacon_video_widget_mark_popup_busy (totem, "seek started");
return FALSE;
}
@@ -2722,7 +2881,7 @@ seek_slider_released_cb (GtkWidget *widget, GdkEventButton *event, TotemObject *
/* set to FALSE here to avoid triggering a final seek when
* syncing the adjustments while being in direct seek mode */
totem->seek_lock = FALSE;
- bacon_video_widget_unmark_popup_busy (totem->bvw, "seek started");
+ bacon_video_widget_unmark_popup_busy (totem, "seek started");
/* sync both adjustments */
adj = gtk_range_get_adjustment (GTK_RANGE (widget));
@@ -3361,7 +3520,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
case GDK_KEY_B:
case GDK_KEY_b:
totem_object_seek_previous (totem);
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
break;
case GDK_KEY_C:
case GDK_KEY_c:
@@ -3403,7 +3562,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
case GDK_KEY_n:
case GDK_KEY_End:
totem_object_seek_next (totem);
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
break;
case GDK_KEY_OpenURL:
totem_object_set_fullscreen (totem, FALSE);
@@ -3508,7 +3667,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
if (totem_object_is_seekable (totem)) {
totem_object_handle_seek (totem, event, is_forward);
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
}
} else {
if (event->keyval == GDK_KEY_Left || event->keyval == GDK_KEY_Page_Down)
@@ -3519,7 +3678,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
break;
case GDK_KEY_Home:
totem_object_seek (totem, 0);
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
break;
case GDK_KEY_Up:
if (bacon_video_widget_has_menus (totem->bvw) != FALSE)
@@ -3547,7 +3706,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
break;
case GDK_KEY_Menu:
case GDK_KEY_F10:
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
if (totem->controls_visibility != TOTEM_CONTROLS_FULLSCREEN) {
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (totem->gear_button),
!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(totem->gear_button)));
@@ -3557,7 +3716,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
}
break;
case GDK_KEY_Time:
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
break;
case GDK_KEY_equal:
if (mask == GDK_CONTROL_MASK)
@@ -3571,7 +3730,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
case GDK_KEY_KP_Add:
if (mask != GDK_CONTROL_MASK) {
totem_object_seek_next (totem);
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
} else {
totem_object_set_zoom (totem, TRUE);
}
@@ -3580,7 +3739,7 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
case GDK_KEY_KP_Subtract:
if (mask != GDK_CONTROL_MASK) {
totem_object_seek_previous (totem);
- bacon_video_widget_show_popup (totem->bvw);
+ totem_show_popup (totem);
} else {
totem_object_set_zoom (totem, FALSE);
}
@@ -3616,14 +3775,6 @@ totem_object_handle_key_press (TotemObject *totem, GdkEventKey *event)
return retval;
}
-static void
-on_track_skip_requested_event (BaconVideoWidget *bvw,
- gboolean is_forward,
- TotemObject *totem)
-{
- totem_object_direction (totem, is_forward ? TOTEM_PLAYLIST_DIRECTION_NEXT :
TOTEM_PLAYLIST_DIRECTION_PREVIOUS);
-}
-
gboolean
window_key_press_event_cb (GtkWidget *win, GdkEventKey *event, TotemObject *totem)
{
@@ -3839,9 +3990,9 @@ popup_menu_shown_cb (GtkToggleButton *button,
TotemObject *totem)
{
if (gtk_toggle_button_get_active (button))
- bacon_video_widget_mark_popup_busy (totem->bvw, "toolbar/go menu visible");
+ bacon_video_widget_mark_popup_busy (totem, "toolbar/go menu visible");
else
- bacon_video_widget_unmark_popup_busy (totem->bvw, "toolbar/go menu visible");
+ bacon_video_widget_unmark_popup_busy (totem, "toolbar/go menu visible");
}
static void
@@ -3850,9 +4001,9 @@ volume_button_menu_shown_cb (GObject *popover,
TotemObject *totem)
{
if (gtk_widget_is_visible (GTK_WIDGET (popover)))
- bacon_video_widget_mark_popup_busy (totem->bvw, "volume menu visible");
+ bacon_video_widget_mark_popup_busy (totem, "volume menu visible");
else
- bacon_video_widget_unmark_popup_busy (totem->bvw, "volume menu visible");
+ bacon_video_widget_unmark_popup_busy (totem, "volume menu visible");
}
static void
@@ -4215,13 +4366,17 @@ video_widget_create (TotemObject *totem)
G_CALLBACK (on_error_event),
totem);
g_signal_connect (G_OBJECT (totem->bvw),
- "track-skip-requested",
- G_CALLBACK (on_track_skip_requested_event),
+ "play-starting",
+ G_CALLBACK (play_starting_cb),
totem);
g_signal_connect (G_OBJECT (totem->bvw),
"scroll-event",
G_CALLBACK (seek_slider_scroll_event_cb),
totem);
+ g_signal_connect (G_OBJECT (totem->bvw),
+ "motion-notify-event",
+ G_CALLBACK (on_bvw_motion_notify_cb),
+ totem);
container = GTK_CONTAINER (gtk_builder_get_object (totem->xml, "tmw_bvw_box"));
gtk_container_add (container,
diff --git a/src/totem-private.h b/src/totem-private.h
index 867ba3757..802976c5e 100644
--- a/src/totem-private.h
+++ b/src/totem-private.h
@@ -115,6 +115,10 @@ struct _TotemObject {
/* controls management */
ControlsVisibility controls_visibility;
+ gboolean reveal_controls;
+ guint transition_timeout_id;
+ GHashTable *busy_popup_ht; /* key=reason string, value=gboolean */
+
/* Stream info */
gint64 stream_length;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]