Bug 1254448 part 1 - Invoke fullscreen change callback after size gets changed.
MozReview-Commit-ID: IxuXV9L7nlP
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -433,16 +433,17 @@ nsWindow::nsWindow()
mContainer = nullptr;
mGdkWindow = nullptr;
mShell = nullptr;
mPluginNativeWindow = nullptr;
mHasMappedToplevel = false;
mIsFullyObscured = false;
mRetryPointerGrab = false;
+ mFullscreenChange = FullscreenStep::NotInChange;
mWindowType = eWindowType_child;
mSizeState = nsSizeMode_Normal;
mLastSizeMode = nsSizeMode_Normal;
mSizeConstraints.mMaxSize = GetSafeWindowSize(mSizeConstraints.mMaxSize);
#ifdef MOZ_X11
mOldFocusWindow = 0;
@@ -2468,16 +2469,26 @@ nsWindow::OnSizeAllocate(GtkAllocation *
// Gecko permits running nested event loops during processing of events,
// GtkWindow callers of gtk_widget_size_allocate expect the signal
// handlers to return sometime in the near future.
mNeedsDispatchResized = true;
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableMethod(this, &nsWindow::MaybeDispatchResized);
NS_DispatchToCurrentThread(r.forget());
+
+ if (mFullscreenChange == FullscreenStep::StateChanged) {
+ mFullscreenChange = FullscreenStep::NotInChange;
+ NS_ASSERTION(mSizeState == mSizeMode, "State should have been changed");
+ if (mWidgetListener) {
+ mWidgetListener->SizeModeChanged(mSizeState);
+ mWidgetListener->
+ FullscreenChanged(mSizeState == nsSizeMode_Fullscreen);
+ }
+ }
}
void
nsWindow::OnDeleteEvent()
{
if (mWidgetListener)
mWidgetListener->RequestWindowClose(this);
}
@@ -3313,22 +3324,27 @@ nsWindow::OnWindowStateEvent(GtkWidget *
else {
LOG(("\tNormal\n"));
mSizeState = nsSizeMode_Normal;
#ifdef ACCESSIBILITY
DispatchRestoreEventAccessible();
#endif //ACCESSIBILITY
}
- if (mWidgetListener) {
- mWidgetListener->SizeModeChanged(mSizeState);
- if (aEvent->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
- mWidgetListener->FullscreenChanged(
- aEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN);
- }
+ if (aEvent->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+ NS_ASSERTION(mFullscreenChange == FullscreenStep::Started,
+ "Fullscreen change process doesn't match");
+ // The sizemode change events for switching into or out from
+ // fullscreen state are delayed until the window size gets
+ // changed in the handler of size-allocation signal, just
+ // before we invoke the fullscreen changed callback, so that
+ // fullscreen code can rely on detecting this event as well.
+ mFullscreenChange = FullscreenStep::StateChanged;
+ } else if (mWidgetListener) {
+ mWidgetListener->SizeModeChanged(mSizeState);
}
}
void
nsWindow::ThemeChanged()
{
NotifyThemeChanged();
@@ -5001,16 +5017,17 @@ nsWindow::MakeFullScreen(bool aFullScree
{
LOG(("nsWindow::MakeFullScreen [%p] aFullScreen %d\n",
(void *)this, aFullScreen));
if (!IsFullscreenSupported(mShell)) {
return NS_ERROR_NOT_AVAILABLE;
}
+ mFullscreenChange = FullscreenStep::Started;
if (aFullScreen) {
if (mSizeMode != nsSizeMode_Fullscreen)
mLastSizeMode = mSizeMode;
mSizeMode = nsSizeMode_Fullscreen;
gtk_window_fullscreen(GTK_WINDOW(mShell));
}
else {
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -424,21 +424,41 @@ private:
GdkWindow** aWindow, gint* aButton,
gint* aRootX, gint* aRootY);
void ClearCachedResources();
GtkWidget *mShell;
MozContainer *mContainer;
GdkWindow *mGdkWindow;
+ // Fullscreen change has four steps:
+ // 1. the change is started via MakeFullscreen;
+ // 2. the window state gets changed in OnWindowStateEvent;
+ // 3. the position of the window gets changed in OnConfigureEvent;
+ // 4. the size of the window gets changed in OnSizeAllocate.
+ // We want to continue the fullscreen change only after all of them
+ // finish. However, the order of step 2 and 3 is not consistent
+ // across machines. Some trigger step 3 first, others do step 2
+ // first instead. It seems OnSizeAllocate is always the last signal
+ // in these steps, and thus we invoke the callback there. However,
+ // actually this is not documented anywhere, so this assumption
+ // could be broken in some cases as well.
+ enum class FullscreenStep
+ {
+ NotInChange,
+ Started,
+ StateChanged
+ };
+
uint32_t mHasMappedToplevel : 1,
mIsFullyObscured : 1,
mRetryPointerGrab : 1;
nsSizeMode mSizeState;
PluginType mPluginType;
+ FullscreenStep mFullscreenChange;
int32_t mTransparencyBitmapWidth;
int32_t mTransparencyBitmapHeight;
nsIntPoint mClientOffset;
#if GTK_CHECK_VERSION(3,4,0)
// This field omits duplicate scroll events caused by GNOME bug 726878.