[totem] main: Use a client-side titlebar
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [totem] main: Use a client-side titlebar
- Date: Fri, 31 Jan 2014 10:54:26 +0000 (UTC)
commit 644e5e82b01565aa873df77a89e360ddadb2b169
Author: Bastien Nocera <hadess hadess net>
Date: Fri Jan 31 11:52:08 2014 +0100
main: Use a client-side titlebar
Remove the headerbar from the video widget. Note that the fullscreen
headerbar isn't handled yet.
https://bugzilla.gnome.org/show_bug.cgi?id=722420
src/backend/Makefile.am | 2 -
src/backend/bacon-video-header-actor.c | 109 --------------------------
src/backend/bacon-video-header-actor.h | 60 ---------------
src/backend/bacon-video-widget.c | 28 +-------
src/totem-grilo.c | 96 ++++++++++++++++++------
src/totem-grilo.h | 5 +-
src/totem-object.c | 131 ++++++++++++++++++++++++++------
src/totem-private.h | 12 +++
8 files changed, 199 insertions(+), 244 deletions(-)
---
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 7167ddb..1484922 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -56,8 +56,6 @@ libbaconvideowidget_la_SOURCES = \
bacon-video-osd-actor.h \
bacon-video-controls-actor.c \
bacon-video-controls-actor.h \
- bacon-video-header-actor.h \
- bacon-video-header-actor.c \
bacon-video-spinner-actor.h \
bacon-video-spinner-actor.c \
clock.c clock.h \
diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c
index c893aaf..b13445b 100644
--- a/src/backend/bacon-video-widget.c
+++ b/src/backend/bacon-video-widget.c
@@ -88,7 +88,6 @@
#include "bacon-video-widget-gst-missing-plugins.h"
#include "bacon-video-osd-actor.h"
#include "bacon-video-controls-actor.h"
-#include "bacon-video-header-actor.h"
#include "bacon-video-spinner-actor.h"
#include "bacon-video-widget-enums.h"
#include "video-utils.h"
@@ -213,7 +212,6 @@ struct BaconVideoWidgetPrivate
ClutterActor *frame;
ClutterActor *osd;
ClutterActor *controls;
- ClutterActor *header;
ClutterActor *spinner;
ClutterActor *logo_frame;
@@ -716,7 +714,6 @@ set_controls_visibility (BaconVideoWidget *bvw,
* Using a show/hide seems to not trigger the
* controls to redraw, so let's change the opacity instead */
clutter_actor_set_opacity (bvw->priv->controls, opacity);
- clutter_actor_set_opacity (bvw->priv->header, opacity);
}
static void
@@ -757,7 +754,7 @@ ignore_event (BaconVideoWidget *bvw,
actor = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (bvw->priv->stage), CLUTTER_PICK_REACTIVE, x, y);
/* Eat the GTK+ event if we're not clicking on the video itself */
- if (actor == bvw->priv->controls || actor == bvw->priv->header)
+ if (actor == bvw->priv->controls)
return TRUE;
return FALSE;
@@ -3477,14 +3474,6 @@ bacon_video_widget_get_controls_object (BaconVideoWidget *bvw)
return G_OBJECT (bvw->priv->controls);
}
-GObject *
-bacon_video_widget_get_header_object (BaconVideoWidget *bvw)
-{
- g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), NULL);
-
- return G_OBJECT (bvw->priv->header);
-}
-
/* =========================================== */
/* */
/* Play/Pause, Stop */
@@ -6175,21 +6164,6 @@ bacon_video_widget_initable_init (GInitable *initable,
layout,
bvw->priv->logo_frame);
- /* The header bar */
- bvw->priv->header = bacon_video_header_actor_new ();
- clutter_actor_set_name (bvw->priv->header, "header");
- layout = g_object_new (CLUTTER_TYPE_ACTOR,
- "layout-manager", clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_FILL,
CLUTTER_BIN_ALIGNMENT_START),
- NULL);
- clutter_actor_set_name (layout, "layout");
- clutter_actor_add_child (layout, bvw->priv->header);
-
- clutter_actor_add_child (bvw->priv->stage, layout);
-
- clutter_actor_set_child_above_sibling (bvw->priv->stage,
- layout,
- bvw->priv->logo_frame);
-
/* And tell playbin */
g_object_set (bvw->priv->play, "video-sink", video_sink, NULL);
diff --git a/src/totem-grilo.c b/src/totem-grilo.c
index 204ceaf..d936d6b 100644
--- a/src/totem-grilo.c
+++ b/src/totem-grilo.c
@@ -73,6 +73,9 @@ struct _TotemGriloPrivate {
/* Toolbar widgets */
GtkWidget *header;
+ gboolean show_back_button;
+ gboolean show_search_button;
+ gboolean show_select_button;
GMenuModel *selectmenu;
GSimpleAction *select_all_action;
GSimpleAction *select_none_action;
@@ -101,7 +104,9 @@ struct _TotemGriloPrivate {
enum {
PROP_0,
- PROP_TOTEM
+ PROP_TOTEM,
+ PROP_HEADER,
+ PROP_SHOW_BACK_BUTTON
};
G_DEFINE_TYPE_WITH_CODE (TotemGrilo, totem_grilo, GTK_TYPE_BOX,
@@ -774,7 +779,7 @@ search_entry_activate_cb (GtkEntry *entry, TotemGrilo *self)
const char *text;
GrlSource *source;
- g_object_set (self->priv->header, "show-back-button", FALSE, NULL);
+ g_object_set (self, "show-back-button", FALSE, NULL);
id = totem_search_entry_get_selected_id (TOTEM_SEARCH_ENTRY (self->priv->search_entry));
g_return_if_fail (id != NULL);
@@ -792,8 +797,8 @@ search_entry_activate_cb (GtkEntry *entry, TotemGrilo *self)
}
static void
-set_browser_filter_model_for_path (TotemGrilo *self,
- GtkTreePath *path)
+set_browser_filter_model_for_path (TotemGrilo *self,
+ GtkTreePath *path)
{
g_clear_object (&self->priv->browser_filter_model);
self->priv->browser_filter_model = gtk_tree_model_filter_new (self->priv->browser_model, path);
@@ -801,7 +806,7 @@ set_browser_filter_model_for_path (TotemGrilo *self,
gd_main_view_set_model (GD_MAIN_VIEW (self->priv->browser),
self->priv->browser_filter_model);
- g_object_set (self->priv->header, "show-back-button", path != NULL, NULL);
+ g_object_set (self, "show-back-button", path != NULL, NULL);
if (path == NULL) {
totem_main_toolbar_set_custom_title (TOTEM_MAIN_TOOLBAR (self->priv->header),
self->priv->switcher);
} else {
@@ -1419,13 +1424,15 @@ adjustment_value_changed_cb (GtkAdjustment *adjustment,
search_more (self);
}
-static void
-back_button_clicked_cb (TotemMainToolbar *toolbar,
- TotemGrilo *self)
+void
+totem_grilo_back_button_clicked (TotemGrilo *self)
{
GtkTreePath *path;
GtkTreeIter iter;
+ g_return_if_fail (TOTEM_IS_GRILO (self));
+
+ g_assert (self->priv->show_back_button);
g_assert (self->priv->browser_filter_model);
g_object_get (G_OBJECT (self->priv->browser_filter_model), "virtual-root", &path, NULL);
g_assert (path);
@@ -1877,15 +1884,6 @@ setup_browse (TotemGrilo *self)
G_CALLBACK (search_entry_source_changed_cb), self);
/* Toolbar */
- self->priv->header = g_object_new (TOTEM_TYPE_MAIN_TOOLBAR,
- "show-search-button", TRUE,
- "show-select-button", TRUE,
- "show-close-button", TRUE,
- "select-menu-model", self->priv->selectmenu,
- NULL);
- gtk_widget_show_all (self->priv->header);
- gtk_window_set_titlebar (GTK_WINDOW (self->priv->main_window), self->priv->header);
-
self->priv->select_all_action = g_simple_action_new ("select-all", NULL);
g_signal_connect (G_OBJECT (self->priv->select_all_action), "activate",
G_CALLBACK (select_all_action_cb), self);
@@ -1906,8 +1904,6 @@ setup_browse (TotemGrilo *self)
setup_source_switcher (self);
totem_main_toolbar_set_custom_title (TOTEM_MAIN_TOOLBAR (self->priv->header), self->priv->switcher);
- g_signal_connect (self->priv->header, "back-clicked",
- G_CALLBACK (back_button_clicked_cb), self);
g_object_bind_property (self->priv->header, "search-mode",
self->priv->search_bar, "search-mode-enabled",
G_BINDING_BIDIRECTIONAL);
@@ -1933,6 +1929,7 @@ setup_browse (TotemGrilo *self)
G_CALLBACK (selection_mode_requested), self);
/* Selection toolbar */
+ g_object_set (G_OBJECT (self->priv->header), "select-menu-model", self->priv->selectmenu, NULL);
self->priv->selection_bar = totem_selection_toolbar_new ();
/* FIXME only show when all not all the items are boxes */
totem_selection_toolbar_set_show_delete_button (TOTEM_SELECTION_TOOLBAR (self->priv->selection_bar),
TRUE);
@@ -2092,11 +2089,14 @@ setup_config (TotemGrilo *self)
}
GtkWidget *
-totem_grilo_new (TotemObject *totem)
+totem_grilo_new (TotemObject *totem,
+ GtkWidget *header)
{
g_return_val_if_fail (TOTEM_IS_OBJECT (totem), NULL);
- return GTK_WIDGET (g_object_new (TOTEM_TYPE_GRILO, "totem", totem, NULL));
+ return GTK_WIDGET (g_object_new (TOTEM_TYPE_GRILO,
+ "totem", totem,
+ "header", header, NULL));
}
static void
@@ -2146,6 +2146,14 @@ totem_grilo_constructed (GObject *object)
load_grilo_plugins (self);
}
+gboolean
+totem_grilo_get_show_back_button (TotemGrilo *self)
+{
+ g_return_val_if_fail (TOTEM_IS_GRILO (self), FALSE);
+
+ return self->priv->show_back_button;
+}
+
static void
totem_grilo_set_property (GObject *object,
guint prop_id,
@@ -2158,10 +2166,37 @@ totem_grilo_set_property (GObject *object,
switch (prop_id)
{
case PROP_TOTEM:
- g_assert (priv->totem == NULL);
priv->totem = g_value_dup_object (value);
break;
+ case PROP_HEADER:
+ priv->header = g_value_dup_object (value);
+ break;
+
+ case PROP_SHOW_BACK_BUTTON:
+ priv->show_back_button = g_value_get_boolean (value);
+ g_object_set (self->priv->header, "show-back-button", priv->show_back_button, NULL);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+totem_grilo_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TotemGrilo *self = TOTEM_GRILO (object);
+
+ switch (prop_id) {
+ case PROP_SHOW_BACK_BUTTON:
+ g_value_set_boolean (value, self->priv->show_back_button);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2177,6 +2212,7 @@ totem_grilo_class_init (TotemGriloClass *klass)
object_class->finalize = totem_grilo_finalize;
object_class->constructed = totem_grilo_constructed;
object_class->set_property = totem_grilo_set_property;
+ object_class->get_property = totem_grilo_get_property;
g_object_class_install_property (object_class,
PROP_TOTEM,
@@ -2186,6 +2222,22 @@ totem_grilo_class_init (TotemGriloClass *klass)
TOTEM_TYPE_OBJECT,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_HEADER,
+ g_param_spec_object ("header",
+ "Headerbar",
+ "Headerbar.",
+ GTK_TYPE_HEADER_BAR,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_SHOW_BACK_BUTTON,
+ g_param_spec_boolean ("show-back-button",
+ "Show Back Button",
+ "Whether the back button is visible",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
gtk_widget_class_set_template_from_resource (widget_class, "/org/totem/grilo/grilo.ui");
gtk_widget_class_bind_template_child_private (widget_class, TotemGrilo, selectmenu);
gtk_widget_class_bind_template_child_private (widget_class, TotemGrilo, search_bar);
diff --git a/src/totem-grilo.h b/src/totem-grilo.h
index 5f35393..893363c 100644
--- a/src/totem-grilo.h
+++ b/src/totem-grilo.h
@@ -58,7 +58,10 @@ struct _TotemGriloClass
};
GType totem_grilo_get_type (void) G_GNUC_CONST;
-GtkWidget* totem_grilo_new (TotemObject *totem);
+GtkWidget* totem_grilo_new (TotemObject *totem,
+ GtkWidget *header);
+void totem_grilo_back_button_clicked (TotemGrilo *self);
+gboolean totem_grilo_get_show_back_button (TotemGrilo *self);
G_END_DECLS
diff --git a/src/totem-object.c b/src/totem-object.c
index 58bcb69..9d28fbe 100644
--- a/src/totem-object.c
+++ b/src/totem-object.c
@@ -65,6 +65,7 @@
#include "totem-preferences.h"
#include "totem-session.h"
#include "totem-rtl-helpers.h"
+#include "totem-main-toolbar.h"
#define WANT_MIME_TYPES 1
#include "totem-mime-types.h"
@@ -420,6 +421,13 @@ totem_object_init (TotemObject *totem)
static void
totem_object_finalize (GObject *object)
{
+ TotemObject *totem = TOTEM_OBJECT (object);
+
+ g_clear_pointer (&totem->title, g_free);
+ g_clear_pointer (&totem->subtitle, g_free);
+ g_clear_pointer (&totem->search_string, g_free);
+ g_clear_pointer (&totem->player_title, g_free);
+ g_clear_object (&totem->custom_title);
G_OBJECT_CLASS (totem_object_parent_class)->finalize (object);
}
@@ -856,6 +864,48 @@ void
totem_object_set_main_page (TotemObject *totem,
const char *page_id)
{
+ if (g_strcmp0 (page_id, "player") == 0) {
+ g_object_get (totem->header,
+ "title", &totem->title,
+ "subtitle", &totem->subtitle,
+ "search-string", &totem->search_string,
+ "search-mode", &totem->search_mode,
+ "select-mode", &totem->select_mode,
+ "custom-title", &totem->custom_title,
+ NULL);
+ g_object_set (totem->header,
+ "show-back-button", TRUE,
+ "show-select-button", FALSE,
+ "show-search-button", FALSE,
+ "title", totem->player_title,
+ "subtitle", NULL,
+ "search-string", NULL,
+ "search-mode", FALSE,
+ "select-mode", FALSE,
+ "custom-title", NULL,
+ NULL);
+ gtk_widget_show (totem->fullscreen_button);
+ gtk_widget_show (totem->gear_button);
+ } else if (g_strcmp0 (page_id, "grilo") == 0) {
+ g_object_set (totem->header,
+ "show-back-button", totem_grilo_get_show_back_button (TOTEM_GRILO
(totem->grilo)),
+ "show-select-button", TRUE,
+ "show-search-button", TRUE,
+ "title", totem->title,
+ "subtitle", totem->subtitle,
+ "search-string", totem->search_string,
+ "search-mode", totem->search_mode,
+ "select-mode", totem->select_mode,
+ "custom-title", totem->custom_title,
+ NULL);
+ g_clear_pointer (&totem->title, g_free);
+ g_clear_pointer (&totem->subtitle, g_free);
+ g_clear_pointer (&totem->search_string, g_free);
+ g_clear_pointer (&totem->player_title, g_free);
+ g_clear_object (&totem->custom_title);
+ gtk_widget_hide (totem->fullscreen_button);
+ gtk_widget_hide (totem->gear_button);
+ }
gtk_stack_set_visible_child_full (GTK_STACK (totem->stack), page_id, GTK_STACK_TRANSITION_TYPE_NONE);
}
@@ -1627,7 +1677,8 @@ update_mrl_label (TotemObject *totem, const char *name)
{
if (name != NULL) {
/* Update the mrl label */
- gtk_header_bar_set_title (GTK_HEADER_BAR (totem->header), name);
+ g_clear_pointer (&totem->player_title, g_free);
+ totem->player_title = g_strdup (name);
} else {
bacon_time_label_set_time (totem->time_label,
0, 0);
@@ -1637,8 +1688,11 @@ update_mrl_label (TotemObject *totem, const char *name)
g_object_notify (G_OBJECT (totem), "stream-length");
/* Update the mrl label */
- gtk_header_bar_set_title (GTK_HEADER_BAR (totem->header), "");
+ g_clear_pointer (&totem->player_title, g_free);
}
+
+ if (g_strcmp0 (totem_object_get_main_page (totem), "player") == 0)
+ g_object_set (totem->header, "title", totem->player_title, NULL);
}
/**
@@ -2193,8 +2247,12 @@ static void
back_button_clicked_cb (GtkButton *button,
TotemObject *totem)
{
- totem_playlist_clear (totem->playlist);
- totem_object_set_main_page (totem, "grilo");
+ if (g_strcmp0 (totem_object_get_main_page (totem), "player") == 0) {
+ totem_playlist_clear (totem->playlist);
+ totem_object_set_main_page (totem, "grilo");
+ } else {
+ totem_grilo_back_button_clicked (TOTEM_GRILO (totem->grilo));
+ }
}
static void
@@ -3496,6 +3554,16 @@ totem_setup_window (TotemObject *totem)
gdk_rgba_parse (&black, "Black");
gtk_widget_override_background_color (vbox, (GTK_STATE_FLAG_FOCUSED << 1), &black);
+ /* Headerbar */
+ totem->header = g_object_new (TOTEM_TYPE_MAIN_TOOLBAR,
+ "show-search-button", TRUE,
+ "show-select-button", TRUE,
+ "show-close-button", TRUE,
+ NULL);
+ g_signal_connect (G_OBJECT (totem->header), "back-clicked",
+ G_CALLBACK (back_button_clicked_cb), totem);
+ gtk_window_set_titlebar (GTK_WINDOW (totem->win), totem->header);
+
return;
}
@@ -3514,6 +3582,24 @@ fullscreen_button_image_sync (GBinding *binding,
}
static GtkWidget *
+create_header_button (Totem *totem,
+ GtkWidget *button,
+ const char *icon_name)
+{
+ GtkWidget *image;
+ GtkStyleContext *context;
+
+ image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ context = gtk_widget_get_style_context (button);
+ gtk_style_context_add_class (context, "image-button");
+ g_object_set (G_OBJECT (button), "valign", GTK_ALIGN_CENTER, NULL);
+
+ gtk_header_bar_pack_end (GTK_HEADER_BAR (totem->header), button);
+ return button;
+}
+
+static GtkWidget *
create_control_button (TotemObject *totem,
const gchar *action_name,
const gchar *tooltip_text)
@@ -3552,7 +3638,6 @@ totem_callback_connect (TotemObject *totem)
GtkWidget *item, *image;
GtkBox *box;
GAction *gaction;
- AtkObject *accessible;
GMenuModel *menu;
/* Menu items */
@@ -3594,8 +3679,8 @@ totem_callback_connect (TotemObject *totem)
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (item), menu);
/* Fullscreen button */
- item = g_object_get_data (bacon_video_widget_get_header_object (totem->bvw),
- "fullscreen_button");
+ item = totem->fullscreen_button = create_header_button (totem, gtk_button_new (),
"view-fullscreen-symbolic");
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (item), "app.fullscreen");
image = gtk_button_get_image (GTK_BUTTON (item));
g_object_bind_property_full (totem, "fullscreen",
image, "icon-name",
@@ -3604,21 +3689,10 @@ totem_callback_connect (TotemObject *totem)
NULL, NULL, NULL);
/* Cog wheel */
- item = g_object_get_data (bacon_video_widget_get_header_object (totem->bvw),
- "button");
+ item = totem->gear_button = create_header_button (totem, gtk_menu_button_new (),
"emblem-system-symbolic");
menu = (GMenuModel *) gtk_builder_get_object (totem->xml, "playermenu");
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (item), menu);
- /* Add a back button */
- item = gd_header_simple_button_new ();
- gd_header_button_set_symbolic_icon_name (GD_HEADER_BUTTON (item),
- totem_get_rtl_icon_name ("go-previous"));
- accessible = gtk_widget_get_accessible (item);
- atk_object_set_name (accessible, _("Back"));
- gtk_header_bar_pack_start (GTK_HEADER_BAR (totem->header), item);
- gtk_widget_show (item);
- g_signal_connect (item, "clicked", G_CALLBACK (back_button_clicked_cb), totem);
-
/* Connect the keys */
gtk_widget_add_events (totem->win, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
@@ -3678,10 +3752,24 @@ playlist_widget_setup (TotemObject *totem)
totem);
}
+static void
+grilo_show_back_button_changed (TotemGrilo *grilo,
+ GParamSpec *spec,
+ TotemObject *totem)
+{
+ if (g_strcmp0 (totem_object_get_main_page (totem), "grilo") == 0) {
+ g_object_set (totem->header,
+ "show-back-button", totem_grilo_get_show_back_button (TOTEM_GRILO
(totem->grilo)),
+ NULL);
+ }
+}
+
void
grilo_widget_setup (TotemObject *totem)
{
- totem->grilo = totem_grilo_new (totem);
+ totem->grilo = totem_grilo_new (totem, totem->header);
+ g_signal_connect (G_OBJECT (totem->grilo), "notify::show-back-button",
+ G_CALLBACK (grilo_show_back_button_changed), totem);
gtk_stack_add_named (GTK_STACK (totem->stack),
totem->grilo,
"grilo");
@@ -3694,7 +3782,6 @@ video_widget_create (TotemObject *totem)
GError *err = NULL;
GtkContainer *container;
BaconVideoWidget **bvw;
- GObject *header;
totem->bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (&err));
@@ -3705,8 +3792,6 @@ video_widget_create (TotemObject *totem)
}
totem->controls = bacon_video_widget_get_controls_object (totem->bvw);
- header = bacon_video_widget_get_header_object (totem->bvw);
- totem->header = g_object_get_data (G_OBJECT (header), "header");
g_signal_connect_after (G_OBJECT (totem->bvw),
"button-press-event",
diff --git a/src/totem-private.h b/src/totem-private.h
index 40ec2cd..f6cfbf7 100644
--- a/src/totem-private.h
+++ b/src/totem-private.h
@@ -141,6 +141,18 @@ struct _TotemObject {
int window_w, window_h;
gboolean maximised;
+ /* Toolbar state */
+ char *title;
+ char *subtitle;
+ char *search_string;
+ gboolean search_mode;
+ gboolean select_mode;
+ GObject *custom_title;
+ GtkWidget *fullscreen_button;
+ GtkWidget *gear_button;
+
+ char *player_title;
+
/* other */
char *mrl;
TotemPlaylist *playlist;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]