From 7ec583cc8f41cc5af9c338bfe2f2d47532860024 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Fri, 24 Jul 2015 09:45:00 +1000 Subject: [PATCH] Bug 1160014 part 6 - Implement fullscreen transition for GTK. r=roc --HG-- extra : source : ae8bf45b7efcd297ad92039b5ea6985dbfa725e9 --- widget/gtk/mozgtk/mozgtk.c | 4 ++ widget/gtk/nsWindow.cpp | 111 +++++++++++++++++++++++++++++++++++++ widget/gtk/nsWindow.h | 5 ++ 3 files changed, 120 insertions(+) diff --git a/widget/gtk/mozgtk/mozgtk.c b/widget/gtk/mozgtk/mozgtk.c index 697de376cec9..00e60834b51b 100644 --- a/widget/gtk/mozgtk/mozgtk.c +++ b/widget/gtk/mozgtk/mozgtk.c @@ -61,6 +61,7 @@ STUB(gdk_screen_get_resolution) STUB(gdk_screen_get_rgba_visual) STUB(gdk_screen_get_root_window) STUB(gdk_screen_get_system_visual) +STUB(gdk_screen_get_width) STUB(gdk_screen_height) STUB(gdk_screen_is_composited) STUB(gdk_screen_width) @@ -437,11 +438,14 @@ STUB(gtk_widget_hide) STUB(gtk_widget_is_focus) STUB(gtk_widget_is_toplevel) STUB(gtk_widget_map) +STUB(gtk_widget_modify_bg) STUB(gtk_widget_realize) STUB(gtk_widget_reparent) STUB(gtk_widget_set_allocation) STUB(gtk_widget_set_app_paintable) STUB(gtk_window_set_auto_startup_notification) +STUB(gtk_window_set_opacity) +STUB(gtk_window_set_screen) STUB(gtk_widget_set_can_focus) STUB(gtk_widget_set_direction) STUB(gtk_widget_set_double_buffered) diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 32b60f837b0d..15ffdafc0b96 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -4611,6 +4611,117 @@ nsWindow::ConvertBorderStyles(nsBorderStyle aStyle) return w; } +class FullscreenTransitionWindow final : public nsISupports +{ +public: + NS_DECL_ISUPPORTS + + explicit FullscreenTransitionWindow(GtkWidget* aWidget); + + GtkWidget* mWindow; + +private: + ~FullscreenTransitionWindow(); +}; + +NS_IMPL_ISUPPORTS0(FullscreenTransitionWindow) + +FullscreenTransitionWindow::FullscreenTransitionWindow(GtkWidget* aWidget) +{ + mWindow = gtk_window_new(GTK_WINDOW_POPUP); + GtkWindow* gtkWin = GTK_WINDOW(mWindow); + + gtk_window_set_type_hint(gtkWin, GDK_WINDOW_TYPE_HINT_SPLASHSCREEN); + gtk_window_set_transient_for(gtkWin, GTK_WINDOW(aWidget)); + gtk_window_set_decorated(gtkWin, false); + + GdkScreen* screen = gtk_widget_get_screen(aWidget); + gint width = gdk_screen_get_width(screen); + gint height = gdk_screen_get_height(screen); + gtk_window_set_screen(gtkWin, screen); + gtk_window_move(gtkWin, 0, 0); + gtk_window_resize(gtkWin, width, height); + + GdkColor bgColor; + bgColor.red = bgColor.green = bgColor.blue = 0; + gtk_widget_modify_bg(mWindow, GTK_STATE_NORMAL, &bgColor); + + gtk_window_set_opacity(gtkWin, 0.0); + gtk_widget_show(mWindow); +} + +FullscreenTransitionWindow::~FullscreenTransitionWindow() +{ + gtk_widget_destroy(mWindow); +} + +class FullscreenTransitionData +{ +public: + FullscreenTransitionData(nsIWidget::FullscreenTransitionStage aStage, + uint16_t aDuration, nsIRunnable* aCallback, + FullscreenTransitionWindow* aWindow) + : mStage(aStage) + , mStep(0) + , mTotalSteps(aDuration / sInterval) + , mCallback(aCallback) + , mWindow(aWindow) { } + + static const guint sInterval = 10; // 10ms + static gboolean TimeoutCallback(gpointer aData); + +private: + nsIWidget::FullscreenTransitionStage mStage; + uint16_t mStep, mTotalSteps; + nsCOMPtr mCallback; + nsRefPtr mWindow; +}; + +/* static */ gboolean +FullscreenTransitionData::TimeoutCallback(gpointer aData) +{ + auto data = static_cast(aData); + data->mStep++; + gdouble opacity = data->mStep / gdouble(data->mTotalSteps); + if (data->mStage == nsIWidget::eAfterFullscreenToggle) { + opacity = 1.0 - opacity; + } + gtk_window_set_opacity(GTK_WINDOW(data->mWindow->mWindow), opacity); + + if (data->mStep != data->mTotalSteps) { + return TRUE; + } + NS_DispatchToMainThread(data->mCallback.forget()); + delete data; + return FALSE; +} + +/* virtual */ bool +nsWindow::PrepareForFullscreenTransition(nsISupports** aData) +{ + GdkScreen* screen = gtk_widget_get_screen(mShell); + if (!gdk_screen_is_composited(screen)) { + return false; + } + *aData = do_AddRef(new FullscreenTransitionWindow(mShell)).take(); + return true; +} + +/* virtual */ void +nsWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage, + uint16_t aDuration, nsISupports* aData, + nsIRunnable* aCallback) +{ + auto data = static_cast(aData); + // This will be released at the end of the last timeout callback for it. + auto transitionData = new FullscreenTransitionData(aStage, aDuration, + aCallback, data); + g_timeout_add_full(G_PRIORITY_HIGH, + FullscreenTransitionData::sInterval, + FullscreenTransitionData::TimeoutCallback, + transitionData, nullptr); +} + NS_IMETHODIMP nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) { diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 05ed0e4113ae..59656e40c647 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -147,6 +147,11 @@ public: bool aIntersectWithExisting) override; virtual bool HasPendingInputEvent() override; + virtual bool PrepareForFullscreenTransition(nsISupports** aData) override; + virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, + uint16_t aDuration, + nsISupports* aData, + nsIRunnable* aCallback) override; NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override; NS_IMETHOD HideWindowChrome(bool aShouldHide) override;