• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2010 Igalia S.L
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Library General Public License
15  *  along with this library; see the file COPYING.LIB.  If not, write to
16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  *  Boston, MA 02110-1301, USA.
18  */
19 
20 #include "config.h"
21 
22 #if ENABLE(VIDEO)
23 
24 #include "FullscreenVideoController.h"
25 
26 #include "GRefPtrGtk.h"
27 #include "GtkVersioning.h"
28 #include "MediaPlayer.h"
29 
30 #include <gdk/gdk.h>
31 #include <gdk/gdkkeysyms.h>
32 #include <glib/gi18n-lib.h>
33 #include <gst/gst.h>
34 #include <gtk/gtk.h>
35 
36 using namespace std;
37 using namespace WebCore;
38 
39 #define HUD_AUTO_HIDE_INTERVAL 3000 // 3 seconds
40 #define PROGRESS_BAR_UPDATE_INTERVAL 150 // 150ms
41 #define VOLUME_UP_OFFSET 0.05 // 5%
42 #define VOLUME_DOWN_OFFSET 0.05 // 5%
43 
44 // Use symbolic icons only if we build with GTK+-3 support. They could
45 // be enabled for the GTK+2 build but we'd need to bump the required
46 // version to at least 2.22.
47 #if GTK_MAJOR_VERSION < 3
48 #define PLAY_ICON_NAME "media-playback-start"
49 #define PAUSE_ICON_NAME "media-playback-pause"
50 #define EXIT_FULLSCREEN_ICON_NAME "view-restore"
51 #else
52 #define PLAY_ICON_NAME "media-playback-start-symbolic"
53 #define PAUSE_ICON_NAME "media-playback-pause-symbolic"
54 #define EXIT_FULLSCREEN_ICON_NAME "view-restore-symbolic"
55 #endif
56 
hideHudCallback(FullscreenVideoController * controller)57 static gboolean hideHudCallback(FullscreenVideoController* controller)
58 {
59     controller->hideHud();
60     return FALSE;
61 }
62 
onFullscreenGtkMotionNotifyEvent(GtkWidget * widget,GdkEventMotion * event,FullscreenVideoController * controller)63 static gboolean onFullscreenGtkMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event,  FullscreenVideoController* controller)
64 {
65     controller->showHud(true);
66     return TRUE;
67 }
68 
onFullscreenGtkActiveNotification(GtkWidget * widget,GParamSpec * property,FullscreenVideoController * controller)69 static void onFullscreenGtkActiveNotification(GtkWidget* widget, GParamSpec* property, FullscreenVideoController* controller)
70 {
71     if (!gtk_window_is_active(GTK_WINDOW(widget)))
72         controller->hideHud();
73 }
74 
onFullscreenGtkConfigureEvent(GtkWidget * widget,GdkEventConfigure * event,FullscreenVideoController * controller)75 static gboolean onFullscreenGtkConfigureEvent(GtkWidget* widget, GdkEventConfigure* event, FullscreenVideoController* controller)
76 {
77     controller->gtkConfigure(event);
78     return TRUE;
79 }
80 
onFullscreenGtkDestroy(GtkWidget * widget,FullscreenVideoController * controller)81 static void onFullscreenGtkDestroy(GtkWidget* widget, FullscreenVideoController* controller)
82 {
83     controller->exitFullscreen();
84 }
85 
togglePlayPauseActivated(GtkAction * action,FullscreenVideoController * controller)86 static void togglePlayPauseActivated(GtkAction* action, FullscreenVideoController* controller)
87 {
88     controller->togglePlay();
89 }
90 
exitFullscreenActivated(GtkAction * action,FullscreenVideoController * controller)91 static void exitFullscreenActivated(GtkAction* action, FullscreenVideoController* controller)
92 {
93     controller->exitOnUserRequest();
94 }
95 
progressBarUpdateCallback(FullscreenVideoController * controller)96 static gboolean progressBarUpdateCallback(FullscreenVideoController* controller)
97 {
98     return controller->updateHudProgressBar();
99 }
100 
timeScaleButtonPressed(GtkWidget * widget,GdkEventButton * event,FullscreenVideoController * controller)101 static gboolean timeScaleButtonPressed(GtkWidget* widget, GdkEventButton* event, FullscreenVideoController* controller)
102 {
103     if (event->type != GDK_BUTTON_PRESS)
104         return FALSE;
105 
106     controller->beginSeek();
107     return FALSE;
108 }
109 
timeScaleButtonReleased(GtkWidget * widget,GdkEventButton * event,FullscreenVideoController * controller)110 static gboolean timeScaleButtonReleased(GtkWidget* widget, GdkEventButton* event, FullscreenVideoController* controller)
111 {
112     controller->endSeek();
113     return FALSE;
114 }
115 
timeScaleValueChanged(GtkWidget * widget,FullscreenVideoController * controller)116 static void timeScaleValueChanged(GtkWidget* widget, FullscreenVideoController* controller)
117 {
118     controller->doSeek();
119 }
120 
volumeValueChanged(GtkScaleButton * button,gdouble value,FullscreenVideoController * controller)121 static void volumeValueChanged(GtkScaleButton *button, gdouble value, FullscreenVideoController* controller)
122 {
123     controller->setVolume(static_cast<float>(value));
124 }
125 
playerVolumeChangedCallback(GObject * element,GParamSpec * pspec,FullscreenVideoController * controller)126 void playerVolumeChangedCallback(GObject *element, GParamSpec *pspec, FullscreenVideoController* controller)
127 {
128     controller->volumeChanged();
129 }
130 
playerMuteChangedCallback(GObject * element,GParamSpec * pspec,FullscreenVideoController * controller)131 void playerMuteChangedCallback(GObject *element, GParamSpec *pspec, FullscreenVideoController* controller)
132 {
133     controller->muteChanged();
134 }
135 
FullscreenVideoController()136 FullscreenVideoController::FullscreenVideoController()
137     : m_hudTimeoutId(0)
138     , m_progressBarUpdateId(0)
139     , m_seekLock(false)
140     , m_window(0)
141     , m_hudWindow(0)
142 {
143 }
144 
~FullscreenVideoController()145 FullscreenVideoController::~FullscreenVideoController()
146 {
147     exitFullscreen();
148 }
149 
setMediaElement(HTMLMediaElement * mediaElement)150 void FullscreenVideoController::setMediaElement(HTMLMediaElement* mediaElement)
151 {
152     if (mediaElement == m_mediaElement)
153         return;
154 
155     m_mediaElement = mediaElement;
156     if (!m_mediaElement) {
157         // Can't do full-screen, just get out
158         exitFullscreen();
159     }
160 }
161 
gtkConfigure(GdkEventConfigure * event)162 void FullscreenVideoController::gtkConfigure(GdkEventConfigure* event)
163 {
164     updateHudPosition();
165 }
166 
showHud(bool autoHide)167 void FullscreenVideoController::showHud(bool autoHide)
168 {
169     if (!m_hudWindow)
170         return;
171 
172     if (m_hudTimeoutId) {
173         g_source_remove(m_hudTimeoutId);
174         m_hudTimeoutId = 0;
175     }
176 
177     // Show the cursor.
178     GdkWindow* window = gtk_widget_get_window(m_window);
179     gdk_window_set_cursor(window, 0);
180 
181     // Update the progress bar immediately before showing the window.
182     updateHudProgressBar();
183     gtk_widget_show_all(m_hudWindow);
184     updateHudPosition();
185 
186     // Start periodic updates of the progress bar.
187     if (!m_progressBarUpdateId)
188         m_progressBarUpdateId = g_timeout_add(PROGRESS_BAR_UPDATE_INTERVAL, reinterpret_cast<GSourceFunc>(progressBarUpdateCallback), this);
189 
190     // Hide the hud in few seconds, if requested.
191     if (autoHide)
192         m_hudTimeoutId = g_timeout_add(HUD_AUTO_HIDE_INTERVAL, reinterpret_cast<GSourceFunc>(hideHudCallback), this);
193 }
194 
hideHud()195 void FullscreenVideoController::hideHud()
196 {
197     if (m_hudTimeoutId) {
198         g_source_remove(m_hudTimeoutId);
199         m_hudTimeoutId = 0;
200     }
201 
202     if (!m_hudWindow)
203         return;
204 
205     // Keep the hud visible if a seek is in progress or if the volume
206     // popup is visible.
207     GtkWidget* volumePopup = gtk_scale_button_get_popup(GTK_SCALE_BUTTON(m_volumeButton));
208     if (m_seekLock || gtk_widget_get_visible(volumePopup)) {
209         showHud(true);
210         return;
211     }
212 
213     GdkWindow* window = gtk_widget_get_window(m_window);
214     GdkCursor* cursor = blankCursor();
215     gdk_window_set_cursor(window, cursor);
216 
217     gtk_widget_hide(m_hudWindow);
218 
219     if (m_progressBarUpdateId) {
220         g_source_remove(m_progressBarUpdateId);
221         m_progressBarUpdateId = 0;
222     }
223 }
224 
onFullscreenGtkKeyPressEvent(GtkWidget * widget,GdkEventKey * event,FullscreenVideoController * controller)225 static gboolean onFullscreenGtkKeyPressEvent(GtkWidget* widget, GdkEventKey* event, FullscreenVideoController* controller)
226 {
227     switch (event->keyval) {
228     case GDK_Escape:
229     case 'f':
230     case 'F':
231         controller->exitOnUserRequest();
232         break;
233     case GDK_space:
234     case GDK_Return:
235         controller->togglePlay();
236         break;
237     case GDK_Up:
238         // volume up
239         controller->setVolume(controller->volume() + VOLUME_UP_OFFSET);
240         break;
241     case GDK_Down:
242         // volume down
243         controller->setVolume(controller->volume() - VOLUME_DOWN_OFFSET);
244         break;
245     default:
246         break;
247     }
248 
249     return TRUE;
250 }
251 
252 
enterFullscreen()253 void FullscreenVideoController::enterFullscreen()
254 {
255     if (!m_mediaElement)
256         return;
257 
258     if (m_mediaElement->platformMedia().type != WebCore::PlatformMedia::GStreamerGWorldType)
259         return;
260 
261     m_gstreamerGWorld = m_mediaElement->platformMedia().media.gstreamerGWorld;
262     if (!m_gstreamerGWorld->enterFullscreen())
263         return;
264 
265     m_window = reinterpret_cast<GtkWidget*>(m_gstreamerGWorld->platformVideoWindow()->window());
266 
267     GstElement* pipeline = m_gstreamerGWorld->pipeline();
268     g_signal_connect(pipeline, "notify::volume", G_CALLBACK(playerVolumeChangedCallback), this);
269     g_signal_connect(pipeline, "notify::mute", G_CALLBACK(playerMuteChangedCallback), this);
270 
271     if (!m_hudWindow)
272         createHud();
273 
274     // Ensure black background.
275 #ifdef GTK_API_VERSION_2
276     GdkColor color = { 1, 0, 0, 0 };
277     gtk_widget_modify_bg(m_window, GTK_STATE_NORMAL, &color);
278 #else
279     GdkRGBA color = { 0, 0, 0, 1};
280     gtk_widget_override_background_color(m_window, GTK_STATE_FLAG_NORMAL, &color);
281 #endif
282     gtk_widget_set_double_buffered(m_window, FALSE);
283 
284     g_signal_connect(m_window, "key-press-event", G_CALLBACK(onFullscreenGtkKeyPressEvent), this);
285     g_signal_connect(m_window, "destroy", G_CALLBACK(onFullscreenGtkDestroy), this);
286     g_signal_connect(m_window, "notify::is-active", G_CALLBACK(onFullscreenGtkActiveNotification), this);
287 
288     gtk_widget_show_all(m_window);
289 
290     GdkWindow* window = gtk_widget_get_window(m_window);
291     GRefPtr<GdkCursor> cursor(adoptGRef(blankCursor()));
292     gdk_window_set_cursor(window, cursor.get());
293 
294     g_signal_connect(m_window, "motion-notify-event", G_CALLBACK(onFullscreenGtkMotionNotifyEvent), this);
295     g_signal_connect(m_window, "configure-event", G_CALLBACK(onFullscreenGtkConfigureEvent), this);
296 
297     gtk_window_fullscreen(GTK_WINDOW(m_window));
298     showHud(true);
299 }
300 
updateHudPosition()301 void FullscreenVideoController::updateHudPosition()
302 {
303     if (!m_hudWindow)
304         return;
305 
306     // Get the screen rectangle.
307     GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(m_window));
308     GdkWindow* window = gtk_widget_get_window(m_window);
309     GdkRectangle fullscreenRectangle;
310     gdk_screen_get_monitor_geometry(screen, gdk_screen_get_monitor_at_window(screen, window),
311                                     &fullscreenRectangle);
312 
313     // Get the popup window size.
314     int hudWidth, hudHeight;
315     gtk_window_get_size(GTK_WINDOW(m_hudWindow), &hudWidth, &hudHeight);
316 
317     // Resize the hud to the full width of the screen.
318     gtk_window_resize(GTK_WINDOW(m_hudWindow), fullscreenRectangle.width, hudHeight);
319 
320     // Move the hud to the bottom of the screen.
321     gtk_window_move(GTK_WINDOW(m_hudWindow), fullscreenRectangle.x,
322                     fullscreenRectangle.height + fullscreenRectangle.y - hudHeight);
323 }
324 
exitOnUserRequest()325 void FullscreenVideoController::exitOnUserRequest()
326 {
327     m_mediaElement->exitFullscreen();
328 }
329 
exitFullscreen()330 void FullscreenVideoController::exitFullscreen()
331 {
332     if (!m_hudWindow)
333         return;
334 
335     g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkKeyPressEvent), this);
336     g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkDestroy), this);
337     g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkMotionNotifyEvent), this);
338     g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkConfigureEvent), this);
339 
340     GstElement* pipeline = m_mediaElement->platformMedia().media.gstreamerGWorld->pipeline();
341     g_signal_handlers_disconnect_by_func(pipeline, reinterpret_cast<void*>(playerVolumeChangedCallback), this);
342     g_signal_handlers_disconnect_by_func(pipeline, reinterpret_cast<void*>(playerMuteChangedCallback), this);
343 
344     if (m_hudTimeoutId) {
345         g_source_remove(m_hudTimeoutId);
346         m_hudTimeoutId = 0;
347     }
348 
349     if (m_progressBarUpdateId) {
350         g_source_remove(m_progressBarUpdateId);
351         m_progressBarUpdateId = 0;
352     }
353 
354     if (m_mediaElement->platformMedia().type == WebCore::PlatformMedia::GStreamerGWorldType)
355         m_mediaElement->platformMedia().media.gstreamerGWorld->exitFullscreen();
356 
357     gtk_widget_hide(m_window);
358 
359     gtk_widget_destroy(m_hudWindow);
360     m_hudWindow = 0;
361 }
362 
canPlay() const363 bool FullscreenVideoController::canPlay() const
364 {
365     return m_mediaElement && m_mediaElement->canPlay();
366 }
367 
play()368 void FullscreenVideoController::play()
369 {
370     if (m_mediaElement)
371         m_mediaElement->play(m_mediaElement->processingUserGesture());
372 
373     playStateChanged();
374     showHud(true);
375 }
376 
pause()377 void FullscreenVideoController::pause()
378 {
379     if (m_mediaElement)
380         m_mediaElement->pause(m_mediaElement->processingUserGesture());
381 
382     playStateChanged();
383     showHud(false);
384 }
385 
playStateChanged()386 void FullscreenVideoController::playStateChanged()
387 {
388     if (canPlay())
389         g_object_set(m_playPauseAction, "tooltip", _("Play"), "icon-name", PLAY_ICON_NAME, NULL);
390     else
391         g_object_set(m_playPauseAction, "tooltip", _("Pause"), "icon-name", PAUSE_ICON_NAME, NULL);
392 }
393 
togglePlay()394 void FullscreenVideoController::togglePlay()
395 {
396     if (canPlay())
397         play();
398     else
399         pause();
400 }
401 
volume() const402 float FullscreenVideoController::volume() const
403 {
404     return m_mediaElement ? m_mediaElement->volume() : 0;
405 }
406 
muted() const407 bool FullscreenVideoController::muted() const
408 {
409     return m_mediaElement ? m_mediaElement->muted() : false;
410 }
411 
setVolume(float volume)412 void FullscreenVideoController::setVolume(float volume)
413 {
414     if (volume < 0.0 || volume > 1.0)
415         return;
416 
417     if (m_mediaElement) {
418         ExceptionCode ec;
419         m_mediaElement->setVolume(volume, ec);
420     }
421 }
422 
volumeChanged()423 void FullscreenVideoController::volumeChanged()
424 {
425     g_signal_handler_block(m_volumeButton, m_volumeUpdateId);
426     gtk_scale_button_set_value(GTK_SCALE_BUTTON(m_volumeButton), volume());
427     g_signal_handler_unblock(m_volumeButton, m_volumeUpdateId);
428 }
429 
muteChanged()430 void FullscreenVideoController::muteChanged()
431 {
432     g_signal_handler_block(m_volumeButton, m_volumeUpdateId);
433     gtk_scale_button_set_value(GTK_SCALE_BUTTON(m_volumeButton), muted() ? 0 : volume());
434     g_signal_handler_unblock(m_volumeButton, m_volumeUpdateId);
435 }
436 
currentTime() const437 float FullscreenVideoController::currentTime() const
438 {
439     return m_mediaElement ? m_mediaElement->currentTime() : 0;
440 }
441 
setCurrentTime(float value)442 void FullscreenVideoController::setCurrentTime(float value)
443 {
444     if (m_mediaElement) {
445         ExceptionCode ec;
446         m_mediaElement->setCurrentTime(value, ec);
447     }
448 }
449 
duration() const450 float FullscreenVideoController::duration() const
451 {
452     return m_mediaElement ? m_mediaElement->duration() : 0;
453 }
454 
percentLoaded() const455 float FullscreenVideoController::percentLoaded() const
456 {
457     return m_mediaElement ? m_mediaElement->percentLoaded() : 0;
458 }
459 
beginSeek()460 void FullscreenVideoController::beginSeek()
461 {
462     m_seekLock = true;
463 
464     if (m_mediaElement)
465         m_mediaElement->beginScrubbing();
466 }
467 
doSeek()468 void FullscreenVideoController::doSeek()
469 {
470     if (!m_seekLock)
471          return;
472 
473     setCurrentTime(gtk_range_get_value(GTK_RANGE(m_timeHScale))*duration() / 100);
474 }
475 
endSeek()476 void FullscreenVideoController::endSeek()
477 {
478     if (m_mediaElement)
479         m_mediaElement->endScrubbing();
480 
481     m_seekLock = false;
482 }
483 
timeToString(float time)484 static String timeToString(float time)
485 {
486     if (!isfinite(time))
487         time = 0;
488     int seconds = fabsf(time);
489     int hours = seconds / (60 * 60);
490     int minutes = (seconds / 60) % 60;
491     seconds %= 60;
492 
493     if (hours) {
494         if (hours > 9)
495             return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
496         return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
497     }
498 
499     return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
500 }
501 
updateHudProgressBar()502 gboolean FullscreenVideoController::updateHudProgressBar()
503 {
504     float mediaDuration(duration());
505     float mediaPosition(currentTime());
506 
507     if (!m_seekLock) {
508         gdouble value = 0.0;
509 
510         if (mediaPosition && mediaDuration)
511             value = (mediaPosition * 100.0) / mediaDuration;
512 
513         GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(m_timeHScale));
514         gtk_adjustment_set_value(adjustment, value);
515     }
516 
517     gtk_range_set_fill_level(GTK_RANGE(m_timeHScale), percentLoaded()* 100);
518 
519     gchar* label = g_strdup_printf("%s / %s", timeToString(mediaPosition).utf8().data(),
520                                    timeToString(mediaDuration).utf8().data());
521     gtk_label_set_text(GTK_LABEL(m_timeLabel), label);
522     g_free(label);
523     return TRUE;
524 }
525 
createHud()526 void FullscreenVideoController::createHud()
527 {
528     m_hudWindow = gtk_window_new(GTK_WINDOW_POPUP);
529     gtk_window_set_gravity(GTK_WINDOW(m_hudWindow), GDK_GRAVITY_SOUTH_WEST);
530     gtk_window_set_type_hint(GTK_WINDOW(m_hudWindow), GDK_WINDOW_TYPE_HINT_NORMAL);
531 
532     g_signal_connect(m_hudWindow, "motion-notify-event", G_CALLBACK(onFullscreenGtkMotionNotifyEvent), this);
533 
534     GtkWidget* hbox = gtk_hbox_new(FALSE, 4);
535     gtk_container_add(GTK_CONTAINER(m_hudWindow), hbox);
536 
537     m_playPauseAction = gtk_action_new("play", _("Play / Pause"), _("Play or pause the media"), PAUSE_ICON_NAME);
538     g_signal_connect(m_playPauseAction, "activate", G_CALLBACK(togglePlayPauseActivated), this);
539 
540     playStateChanged();
541 
542     GtkWidget* item = gtk_action_create_tool_item(m_playPauseAction);
543     gtk_box_pack_start(GTK_BOX(hbox), item, FALSE, TRUE, 0);
544 
545     GtkWidget* label = gtk_label_new(_("Time:"));
546     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
547 
548     GtkAdjustment* adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 100.0, 0.1, 1.0, 1.0));
549     m_timeHScale = gtk_hscale_new(adjustment);
550     gtk_scale_set_draw_value(GTK_SCALE(m_timeHScale), FALSE);
551     gtk_range_set_show_fill_level(GTK_RANGE(m_timeHScale), TRUE);
552     g_signal_connect(m_timeHScale, "button-press-event", G_CALLBACK(timeScaleButtonPressed), this);
553     g_signal_connect(m_timeHScale, "button-release-event", G_CALLBACK(timeScaleButtonReleased), this);
554     m_hscaleUpdateId = g_signal_connect(m_timeHScale, "value-changed", G_CALLBACK(timeScaleValueChanged), this);
555 
556     gtk_box_pack_start(GTK_BOX(hbox), m_timeHScale, TRUE, TRUE, 0);
557 
558     m_timeLabel = gtk_label_new("");
559     gtk_box_pack_start(GTK_BOX(hbox), m_timeLabel, FALSE, TRUE, 0);
560 
561     // Volume button.
562     m_volumeButton = gtk_volume_button_new();
563     gtk_box_pack_start(GTK_BOX(hbox), m_volumeButton, FALSE, TRUE, 0);
564     gtk_scale_button_set_value(GTK_SCALE_BUTTON(m_volumeButton), volume());
565     m_volumeUpdateId = g_signal_connect(m_volumeButton, "value-changed", G_CALLBACK(volumeValueChanged), this);
566 
567 
568     m_exitFullscreenAction = gtk_action_new("exit", _("Exit Fullscreen"), _("Exit from fullscreen mode"), EXIT_FULLSCREEN_ICON_NAME);
569     g_signal_connect(m_exitFullscreenAction, "activate", G_CALLBACK(exitFullscreenActivated), this);
570     g_object_set(m_exitFullscreenAction, "icon-name", EXIT_FULLSCREEN_ICON_NAME, NULL);
571     item = gtk_action_create_tool_item(m_exitFullscreenAction);
572     gtk_box_pack_start(GTK_BOX(hbox), item, FALSE, TRUE, 0);
573 
574 
575     m_progressBarUpdateId = g_timeout_add(PROGRESS_BAR_UPDATE_INTERVAL, reinterpret_cast<GSourceFunc>(progressBarUpdateCallback), this);
576 }
577 
578 #endif
579