Index: totem/browser-plugin/totem-plugin-viewer.c
===================================================================
--- totem/browser-plugin/totem-plugin-viewer.c	(revision 4423)
+++ totem/browser-plugin/totem-plugin-viewer.c	(working copy)
@@ -37,6 +37,7 @@
 #define SN_API_NOT_YET_FROZEN
 #include <libsn/sn.h>
 #include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
 
 #include <totem-pl-parser.h>
 
@@ -48,6 +49,8 @@
 #include "bacon-video-widget.h"
 #include "totem-interface.h"
 #include "totem-statusbar.h"
+#include "totem-time-label.h"
+#include "totem-fullscreen.h"
 #include "totem-glow-button.h"
 #include "video-utils.h"
 
@@ -99,6 +102,7 @@
 	GladeXML *menuxml, *xml;
 	GtkWidget *about;
 	GtkWidget *pp_button;
+	GtkWidget *pp_fs_button;
 	TotemStatusbar *statusbar;
 	int width, height;
 	const char *mimetype;
@@ -124,6 +128,13 @@
 	GtkAdjustment *seekadj;
 	GtkWidget *seek;
 
+	/* Volume */
+	GtkWidget *volume;
+
+	/* Fullscreen */
+	TotemFullscreen *fs;
+	GtkWidget * fs_window;
+
 	/* Error */
 
 	guint type : 3; /* TotemPluginType */
@@ -166,6 +177,8 @@
 static void totem_embedded_update_menu (TotemEmbedded *emb);
 static void on_open1_activate (GtkButton *button, TotemEmbedded *emb);
 
+static void totem_embedded_toggle_fullscreen (TotemEmbedded *emb);
+
 enum {
 	BUTTON_PRESS,
 	START_STREAM,
@@ -186,6 +199,8 @@
 		g_object_unref (embedded->xml);
 	if (embedded->menuxml)
 		g_object_unref (embedded->menuxml);
+	if (embedded->fs)
+		g_object_unref (embedded->fs);
 
 	/* FIXME etc */
 
@@ -257,6 +272,7 @@
 totem_embedded_set_state (TotemEmbedded *emb, TotemStates state)
 {
 	GtkWidget *image;
+	const char *fs_stock_id;
 	char id[32];
 	static const char *states[] = {
 		"PLAYING",
@@ -278,16 +294,20 @@
 			    gtk_widget_get_direction (image) ? "ltr" : "rtl");
 		totem_statusbar_set_text (emb->statusbar, _("Stopped"));
 		totem_statusbar_set_time_and_length (emb->statusbar, 0, 0);
+		totem_time_label_set_time 
+			(TOTEM_TIME_LABEL (emb->fs->time_label), 0, 0);
 		if (emb->href_uri != NULL && emb->hidden == FALSE) {
 			gdk_window_set_cursor
 				(GTK_WIDGET (emb->bvw)->window,
 				 emb->cursor);
 		}
+		fs_stock_id = GTK_STOCK_MEDIA_PLAY;
 		break;
 	case STATE_PAUSED:
 		g_snprintf (id, sizeof (id), "gtk-media-play-%s",
 				gtk_widget_get_direction (image) ? "ltr" : "rtl");
 		totem_statusbar_set_text (emb->statusbar, _("Paused"));
+		fs_stock_id = GTK_STOCK_MEDIA_PLAY;
 		break;
 	case STATE_PLAYING:
 		g_snprintf (id, sizeof (id), "gtk-media-pause");
@@ -297,12 +317,16 @@
 				(GTK_WIDGET (emb->bvw)->window,
 				 NULL);
 		}
+		fs_stock_id = GTK_STOCK_MEDIA_PAUSE;
 		break;
 	default:
+		g_assert_not_reached ();
 		break;
 	}
 
 	gtk_image_set_from_icon_name (GTK_IMAGE (image), id, GTK_ICON_SIZE_MENU);
+	gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (emb->pp_fs_button),
+				      fs_stock_id);
 	emb->state = state;
 }
 
@@ -371,6 +395,7 @@
 totem_embedded_set_pp_state (TotemEmbedded *emb, gboolean state)
 {
 	gtk_widget_set_sensitive (emb->pp_button, state);
+	gtk_widget_set_sensitive (emb->pp_fs_button, state);
 }
 
 static gboolean
@@ -438,6 +463,10 @@
 	}
 
 	totem_embedded_update_menu (emb);
+	if (emb->href_uri != NULL)
+		totem_fullscreen_set_title (emb->fs, emb->href_uri);
+	else
+		totem_fullscreen_set_title (emb->fs, emb->current_uri);
 
 	return retval;
 }
@@ -1065,6 +1094,13 @@
 }
 
 static void
+on_fullscreen1_activate (GtkMenuItem *menuitem, TotemEmbedded *emb)
+{
+	if (totem_fullscreen_is_fullscreen (emb->fs) == FALSE)
+		totem_embedded_toggle_fullscreen (emb);
+}
+
+static void
 on_about1_activate (GtkButton *button, TotemEmbedded *emb)
 {
 	char *backend_version, *description, *license;
@@ -1192,6 +1228,39 @@
 		totem_embedded_play (emb, NULL);
 }
 
+static void
+totem_embedded_toggle_fullscreen (TotemEmbedded *emb)
+{
+	GtkWidget * menutiem = glade_xml_get_widget (emb->menuxml, "fullscreen1");
+
+	if (totem_fullscreen_is_fullscreen (emb->fs) != FALSE)
+	{
+		GtkWidget * container;
+		container = glade_xml_get_widget (emb->xml, "video_box");
+
+		totem_fullscreen_set_fullscreen (emb->fs, FALSE);
+		gtk_widget_reparent (GTK_WIDGET (emb->bvw), container);
+		gtk_widget_hide_all (emb->fs_window);
+		
+		gtk_widget_set_sensitive (menutiem, TRUE);
+	} else {
+		gtk_widget_reparent (GTK_WIDGET (emb->bvw), emb->fs_window);
+		bacon_video_widget_set_fullscreen (emb->bvw, TRUE);
+		gtk_window_fullscreen (GTK_WINDOW (emb->fs_window));
+		totem_fullscreen_set_fullscreen (emb->fs, TRUE);
+		gtk_widget_show_all (emb->fs_window);
+
+		gtk_widget_set_sensitive (menutiem, FALSE);
+	}
+}
+
+static void
+totem_embedded_on_fullscreen_exit (GtkWidget *widget, TotemEmbedded *emb)
+{
+	if (totem_fullscreen_is_fullscreen (emb->fs) != FALSE)
+		totem_embedded_toggle_fullscreen (emb);
+}
+
 static gboolean
 on_video_button_press_event (BaconVideoWidget *bvw,
 			     GdkEventButton *event,
@@ -1221,6 +1290,9 @@
 				event->button, event->time);
 
 		handled = TRUE;
+	} else if (event->type == GDK_2BUTTON_PRESS &&
+		   event->button == 1) {
+		totem_embedded_toggle_fullscreen (emb);
 	}
 
 	return handled;
@@ -1299,6 +1371,7 @@
 {
 	if (emb->state != STATE_STOPPED) {
 		gtk_widget_set_sensitive (emb->seek, seekable);
+		gtk_widget_set_sensitive (emb->fs->seek, seekable);
 		if (emb->seeking == FALSE)
 			gtk_adjustment_set_value (emb->seekadj,
 					current_position * 65535);
@@ -1310,13 +1383,32 @@
 					(int) (current_time / 1000),
 					(int) (stream_length / 1000));
 		}
+
+		totem_time_label_set_time 
+			(TOTEM_TIME_LABEL (emb->fs->time_label),
+			 current_time, stream_length);
 	}
 }
 
+static void
+property_notify_cb_volume (BaconVideoWidget *bvw, GParamSpec *spec,
+			   TotemEmbedded *emb)
+{
+	double volume;
+	
+	volume = bacon_video_widget_get_volume (emb->bvw);
+	
+	g_signal_handlers_block_by_func (emb->volume, cb_vol, emb);
+	gtk_scale_button_set_value (GTK_SCALE_BUTTON (emb->volume), volume);
+	g_signal_handlers_unblock_by_func (emb->volume, cb_vol, emb);
+}
+
 static gboolean
 on_seek_start (GtkWidget *widget, GdkEventButton *event, TotemEmbedded *emb)
 {
 	emb->seeking = TRUE;
+	totem_time_label_set_seeking (TOTEM_TIME_LABEL (emb->fs->time_label),
+				      TRUE);
 
 	return FALSE;
 }
@@ -1326,6 +1418,8 @@
 {
 	bacon_video_widget_seek (emb->bvw,
 		gtk_range_get_value (GTK_RANGE (widget)) / 65535, NULL);
+	totem_time_label_set_seeking (TOTEM_TIME_LABEL (emb->fs->time_label),
+				      FALSE);
 	emb->seeking = FALSE;
 
 	return FALSE;
@@ -1342,13 +1436,82 @@
 }
 #endif
 
+static void
+totem_embedded_action_volume_relative (TotemEmbedded *emb, double off_pct)
+{
+	double vol;
+
+	if (bacon_video_widget_can_set_volume (emb->bvw) == FALSE)
+		return;
+
+	vol = bacon_video_widget_get_volume (emb->bvw);
+	bacon_video_widget_set_volume (emb->bvw, vol + off_pct);
+}
+
 static gboolean
+totem_embedded_handle_key_press (TotemEmbedded *emb, GdkEventKey *event)
+{
+	switch (event->keyval) {
+	case GDK_Escape:
+		if (totem_fullscreen_is_fullscreen (emb->fs) != FALSE)
+			totem_embedded_toggle_fullscreen (emb);
+		return TRUE;
+	case GDK_F11:
+	case GDK_f:
+	case GDK_F:
+		totem_embedded_toggle_fullscreen (emb);
+		return TRUE;
+	case GDK_space:
+		on_play_pause (NULL, emb);
+		return TRUE;
+	case GDK_Up:
+		totem_embedded_action_volume_relative (emb, VOLUME_UP_OFFSET);
+		return TRUE;
+	case GDK_Down:
+		totem_embedded_action_volume_relative (emb, VOLUME_DOWN_OFFSET);
+		return TRUE;
+	case GDK_Left:
+	case GDK_Right:
+		/* FIXME: */
+		break;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+totem_embedded_key_press_event (GtkWidget *widget, GdkEventKey *event,
+				   TotemEmbedded *emb)
+{
+	if (event->type != GDK_KEY_PRESS)
+		return FALSE;
+
+	if (event->state & GDK_CONTROL_MASK)
+	{
+		switch (event->keyval) {
+		case GDK_Left:
+		case GDK_Right:
+			return totem_embedded_handle_key_press (emb, event);
+		}
+	}
+
+	if (event->state & GDK_CONTROL_MASK ||
+	    event->state & GDK_MOD1_MASK ||
+	    event->state & GDK_MOD3_MASK ||
+	    event->state & GDK_MOD4_MASK ||
+	    event->state & GDK_MOD5_MASK)
+		return FALSE;
+
+	return totem_embedded_handle_key_press (emb, event);
+}
+
+static gboolean
 totem_embedded_construct (TotemEmbedded *emb,
 			  GdkNativeWindow xid,
 			  int width,
 			  int height)
 {
-	GtkWidget *child, *container, *vbut;
+	GtkWidget *child, *container;
 	BvwUseType type;
 	GError *err = NULL;
 	GConfClient *gc;
@@ -1404,6 +1567,36 @@
 			g_error_free (err);
 	}
 
+	/* Fullscreen setup */
+	emb->fs_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_widget_realize (emb->fs_window);
+	gtk_window_set_title (GTK_WINDOW (emb->fs_window), _("Totem Movie Player"));
+
+	emb->fs = totem_fullscreen_new (GTK_WINDOW (emb->fs_window));
+	totem_fullscreen_set_video_widget (emb->fs, emb->bvw);
+	g_signal_connect (G_OBJECT (emb->fs->exit_button), "clicked",
+			  G_CALLBACK (totem_embedded_on_fullscreen_exit), emb);
+
+	emb->pp_fs_button = GTK_WIDGET (gtk_tool_button_new_from_stock 
+					(GTK_STOCK_MEDIA_PLAY));
+	g_signal_connect (G_OBJECT (emb->pp_fs_button), "clicked",
+			  G_CALLBACK (on_play_pause), emb);
+	gtk_container_add (GTK_CONTAINER (emb->fs->buttons_box), emb->pp_fs_button);
+
+	/* Connect the keys */
+	gtk_widget_add_events (emb->fs_window, GDK_KEY_PRESS_MASK |
+			       GDK_KEY_RELEASE_MASK);
+	g_signal_connect (G_OBJECT(emb->fs_window), "key_press_event",
+			G_CALLBACK (totem_embedded_key_press_event), emb);
+	g_signal_connect (G_OBJECT(emb->fs_window), "key_release_event",
+			G_CALLBACK (totem_embedded_key_press_event), emb);
+	gtk_widget_add_events (GTK_WIDGET (emb->bvw), GDK_KEY_PRESS_MASK | 
+			       GDK_KEY_RELEASE_MASK);
+	g_signal_connect (G_OBJECT(emb->bvw), "key_press_event",
+			G_CALLBACK (totem_embedded_key_press_event), emb);
+	g_signal_connect (G_OBJECT(emb->bvw), "key_release_event",
+			G_CALLBACK (totem_embedded_key_press_event), emb);
+
 	g_signal_connect (G_OBJECT(emb->bvw), "got-redirect",
 			G_CALLBACK (on_got_redirect), emb);
 	g_signal_connect (G_OBJECT (emb->bvw), "eos",
@@ -1415,6 +1608,9 @@
 	g_signal_connect (G_OBJECT(emb->bvw), "tick",
 			G_CALLBACK (on_tick), emb);
 
+	g_signal_connect (G_OBJECT (emb->bvw), "notify::volume",
+			G_CALLBACK (property_notify_cb_volume), emb);
+
 	container = glade_xml_get_widget (emb->xml, "video_box");
 	if (type == BVW_USE_TYPE_VIDEO) {
 		gtk_container_add (GTK_CONTAINER (container), GTK_WIDGET (emb->bvw));
@@ -1428,10 +1624,15 @@
 
 	emb->seek = glade_xml_get_widget (emb->xml, "time_hscale");
 	emb->seekadj = gtk_range_get_adjustment (GTK_RANGE (emb->seek));
+	gtk_range_set_adjustment (GTK_RANGE (emb->fs->seek), emb->seekadj);
 	g_signal_connect (emb->seek, "button-press-event",
 			  G_CALLBACK (on_seek_start), emb);
 	g_signal_connect (emb->seek, "button-release-event",
 			  G_CALLBACK (cb_on_seek), emb);
+	g_signal_connect (emb->fs->seek, "button-press-event",
+			  G_CALLBACK (on_seek_start), emb);
+	g_signal_connect (emb->fs->seek, "button-release-event",
+			  G_CALLBACK (cb_on_seek), emb);
 
 	emb->pp_button = glade_xml_get_widget (emb->xml, "pp_button");
 	g_signal_connect (G_OBJECT (emb->pp_button), "clicked",
@@ -1442,9 +1643,12 @@
 	g_object_unref (G_OBJECT (gc));
 
 	bacon_video_widget_set_volume (emb->bvw, volume);
-	vbut = glade_xml_get_widget (emb->xml, "volume_button");
-	gtk_scale_button_set_value (GTK_SCALE_BUTTON (vbut), volume);
-	g_signal_connect (G_OBJECT (vbut), "value-changed",
+	emb->volume = glade_xml_get_widget (emb->xml, "volume_button");
+	gtk_scale_button_set_adjustment (GTK_SCALE_BUTTON (emb->fs->volume),
+					 gtk_scale_button_get_adjustment 
+					 (GTK_SCALE_BUTTON (emb->volume)));
+	gtk_scale_button_set_value (GTK_SCALE_BUTTON (emb->volume), volume);
+	g_signal_connect (G_OBJECT (emb->volume), "value-changed",
 			  G_CALLBACK (cb_vol), emb);
 
 	emb->statusbar = TOTEM_STATUSBAR (glade_xml_get_widget (emb->xml, "statusbar"));
@@ -1504,6 +1708,9 @@
 			G_CALLBACK (on_copy_location1_activate), emb);
 	child = glade_xml_get_widget (emb->menuxml, "preferences1");
 	gtk_widget_hide (child);
+	child = glade_xml_get_widget (emb->menuxml, "fullscreen1");
+	g_signal_connect (G_OBJECT (child), "activate",
+			  G_CALLBACK (on_fullscreen1_activate), emb);
 
 	/* Create cursor and set the logo */
 	if (!emb->hidden) {
Index: totem/src/Makefile.am
===================================================================
--- totem/src/Makefile.am	(revision 4423)
+++ totem/src/Makefile.am	(working copy)
@@ -56,7 +56,9 @@
 	totem-interface.c		\
 	totem-interface.h		\
 	totem-fullscreen.c		\
-	totem-fullscreen.h
+	totem-fullscreen.h		\
+	totem-time-label.c		\
+	totem-time-label.h
 
 libtotem_player_la_CPPFLAGS = \
 	-I$(srcdir)/plparse	\
@@ -98,7 +100,6 @@
 	totem-open-location.c totem-open-location.h \
 	totem-menu.c totem-menu.h	\
 	totem-missing-plugins.c totem-missing-plugins.h \
-	totem-time-label.c totem-time-label.h \
 	totem-uri.c totem-uri.h		\
 	ev-sidebar.c ev-sidebar.h	\
 	totem-subtitle-encoding.c	\
Index: totem/src/totem.c
===================================================================
--- totem/src/totem.c	(revision 4423)
+++ totem/src/totem.c	(working copy)
@@ -3082,7 +3082,7 @@
 	totem->volume = glade_xml_get_widget (totem->xml, "tmw_volume_button");
 	totem->statusbar = glade_xml_get_widget (totem->xml, "tmw_statusbar");
 	totem->seek_lock = FALSE;
-	totem->fs = totem_fullscreen_new ();
+	totem->fs = totem_fullscreen_new (GTK_WINDOW (totem->win));
 	gtk_scale_button_set_adjustment (GTK_SCALE_BUTTON (totem->fs->volume),
 			gtk_scale_button_get_adjustment (GTK_SCALE_BUTTON (totem->volume)));
 	gtk_range_set_adjustment (GTK_RANGE (totem->fs->seek), totem->seekadj);
Index: totem/src/totem-fullscreen.c
===================================================================
--- totem/src/totem-fullscreen.c	(revision 4423)
+++ totem/src/totem-fullscreen.c	(working copy)
@@ -24,6 +24,8 @@
  *
  */
 
+#include <string.h>
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
@@ -284,7 +286,7 @@
 }
 
 TotemFullscreen *
-totem_fullscreen_new (void)
+totem_fullscreen_new (GtkWindow *toplevel_window)
 {
 	TotemFullscreenPrivate * priv;
 
@@ -309,6 +311,17 @@
 	fs->exit_button = glade_xml_get_widget (priv->xml,
 						"tefw_fs_exit_button");
 
+	fs->priv->parent_window = GTK_WIDGET (toplevel_window);
+
+	/* Screen size and Theme changes */
+	g_signal_connect (fs->priv->parent_window, "realize",
+			  G_CALLBACK (totem_fullscreen_window_realize_cb), fs);
+	g_signal_connect (fs->priv->parent_window, "unrealize",
+			  G_CALLBACK (totem_fullscreen_window_unrealize_cb), fs);
+	g_object_notify (G_OBJECT (fs->priv->parent_window), "is-active");
+	g_signal_connect_swapped (G_OBJECT (fs->priv->parent_window), "notify",
+				  G_CALLBACK (totem_fullscreen_popup_hide), fs);
+
 	/* Volume */
 	fs->volume = glade_xml_get_widget (priv->xml, "tcw_volume_button");
 	g_signal_connect (G_OBJECT(fs->volume), "button_press_event",
@@ -349,19 +362,9 @@
 	g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 
 	fs->priv->bvw = bvw;
-	fs->priv->parent_window = gtk_widget_get_toplevel (GTK_WIDGET (bvw));
 
-	/* Screen size and Theme changes */
-	g_signal_connect (fs->priv->parent_window, "realize",
-			  G_CALLBACK (totem_fullscreen_window_realize_cb), fs);
-	g_signal_connect (fs->priv->parent_window, "unrealize",
-			  G_CALLBACK (totem_fullscreen_window_unrealize_cb), fs);
 	g_signal_connect (G_OBJECT (fs->priv->bvw), "motion-notify-event",
 			  G_CALLBACK (totem_fullscreen_motion_notify), fs);
-	g_object_notify (G_OBJECT (fs->priv->parent_window), "is-active");
-	g_signal_connect_swapped (G_OBJECT (fs->priv->parent_window), "notify",
-				  G_CALLBACK (totem_fullscreen_popup_hide), fs);
-
 }
 
 static void
Index: totem/src/totem-fullscreen.h
===================================================================
--- totem/src/totem-fullscreen.h	(revision 4423)
+++ totem/src/totem-fullscreen.h	(working copy)
@@ -67,7 +67,7 @@
 };
 
 GType    totem_fullscreen_get_type           (void);
-TotemFullscreen * totem_fullscreen_new       (void);
+TotemFullscreen * totem_fullscreen_new       (GtkWindow *toplevel_window);
 void     totem_fullscreen_set_video_widget   (TotemFullscreen *fs,
 					      BaconVideoWidget *bvw);
 gboolean totem_fullscreen_motion_notify      (GtkWidget *widget,
Index: totem/data/mozilla-viewer.glade
===================================================================
--- totem/data/mozilla-viewer.glade	(revision 4423)
+++ totem/data/mozilla-viewer.glade	(working copy)
@@ -153,6 +153,17 @@
   </child>
 
   <child>
+    <widget class="GtkImageMenuItem" id="fullscreen1">
+      <property name="visible">True</property>
+      <property name="tooltip" translatable="yes">Switch to fullscreen</property>
+      <property name="label" translatable="yes">gtk-fullscreen</property>
+      <property name="use_underline">True</property>
+      <property name="use_stock">True</property>
+      <signal name="activate" handler="on_fullscreen1_activate" last_modification_time="Sat, 30 Jun 2007 12:30:00 GMT"/>
+    </widget>
+  </child>
+
+  <child>
     <widget class="GtkSeparatorMenuItem" id="separator1">
       <property name="visible">True</property>
     </widget>
