Skip to content

Commit

Permalink
Cleanup fullscreen code
Browse files Browse the repository at this point in the history
The current code handling fullscreen is a mess and extremelly difficult
to follow. We've been adding patches over time to fix special situations
and that is making it even more unmaintanable.

The root problem is that there are two different fullscreen events
that are not properly handled. On the one hand we have the fullscreen
event from the content delegate. That could be triggered by any
HTML element that wants to go fullscreen (it does not have to be
media). And the other one is the fullscreen event triggered by media.
That is triggered after the previous one in the case of media
content.

Our code should perfectly handle the case of media fullscreen
while still allowing other HTML elements to go fullscreen as well.

This patch tries to address that by:
* splitting the code that performs the content fullscreen and the
media (video) fullscreen
* moving all the code related to media fullscreen to the handlers
of the media fullscreen event
* moving all the generic code that does window fullscreen to the
content fullscreen handlers. We know have enterFullscreenMode and
exitFullscreenMode for that.
* removing some handlers in the mAttachedWindow that are now
not needed.
* moving the creation of the projection menu to the media fullscreen
handlers as it is not required by content fullscreen
  • Loading branch information
svillar committed Jan 23, 2024
1 parent 70d9aad commit 346ecaf
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -663,71 +663,73 @@ public void onSessionChanged(@NonNull Session aOldSession, @NonNull Session aSes
mAttachedWindow.setIsFullScreen(false);
}

private void onEnterFullScreen(@NonNull WindowWidget aWindow) {
enterFullScreenMode();

mBeforeFullscreenPlacement = mWidgetPlacement.clone();
mWidgetPlacement.cylinder = SettingsStore.getInstance(getContext()).isCurvedModeEnabled();
updateWidget();

if (mAttachedWindow.isResizing()) {
exitResizeMode(ResizeAction.KEEP_SIZE);
}
AtomicBoolean autoEnter = new AtomicBoolean(false);
if (getSession().getFullScreenVideo() == null) {
mAutoSelectedProjection = VIDEO_PROJECTION_NONE;
autoEnter.set(false);
} else {
mAutoSelectedProjection = VideoProjectionMenuWidget.getAutomaticProjection(getSession().getCurrentUri(), autoEnter);
}
private void createProjectionMenuIfNeeded() {
if (mProjectionMenu != null)
return;

if (mAutoSelectedProjection != VIDEO_PROJECTION_NONE && autoEnter.get()) {
mViewModel.setAutoEnteredVRVideo(true);
postDelayed(() -> enterVRVideo(mAutoSelectedProjection), 300);
} else {
mViewModel.setAutoEnteredVRVideo(false);
if (mProjectionMenu != null) {
mProjectionMenu.setSelectedProjection(mAutoSelectedProjection);
mProjectionMenu = new VideoProjectionMenuWidget(getContext());
mProjectionMenu.setParentWidget(this);
mProjectionMenuPlacement = new WidgetPlacement(getContext());
mWidgetManager.addWidget(mProjectionMenu);
mProjectionMenu.setDelegate((projection)-> {
if (mViewModel.getIsInVRVideo().getValue().get()) {
if (projection == VIDEO_PROJECTION_NONE) {
exitVRVideo();
mAttachedWindow.reCenterFrontWindow();
} else {
// Reproject while reproducing VRVideo
mWidgetManager.showVRVideo(mAttachedWindow.getHandle(), projection);
}
closeFloatingMenus();
} else {
enterVRVideo(projection);
}
}
mAttachedWindow.reCenterFrontWindow();
});
}

@Override
public void onFullScreen(@NonNull WindowWidget aWindow, boolean aFullScreen) {
public void onMediaFullScreen(@NonNull WMediaSession mediaSession, boolean aFullScreen) {
if (aFullScreen) {
if (getSession().getFullScreenVideo() != null) {
onEnterFullScreen(aWindow);
// The content fullscreen event might have arrived before the media fullscreen event
if (!mAttachedWindow.isFullScreen())
enterFullScreenMode();

createProjectionMenuIfNeeded();

AtomicBoolean autoEnter = new AtomicBoolean(false);
if (getSession().getFullScreenVideo() == null) {
mAutoSelectedProjection = VIDEO_PROJECTION_NONE;
autoEnter.set(false);
} else {
// No active fullscreen video. There might be two reasons for that:
// 1. The video is not active yet -> wait for onVideoAvailabilityChanged
// 2. The video is active but not in fullscreen -> wait for onMediaFullscreen
mAttachedWindow.addWindowListener(new WindowWidget.WindowListener() {
@Override
public void onVideoAvailabilityChanged(@NonNull WindowWidget aWindow) {
WindowWidget.WindowListener.super.onVideoAvailabilityChanged(aWindow);
assert getSession().getActiveVideo() != null;
onEnterFullScreen(aWindow);
mAttachedWindow.removeWindowListener(this);
}
@Override
public void onMediaFullScreen(@NonNull WMediaSession mediaSession, boolean aFullScreen) {
assert getSession().getFullScreenVideo() != null;
onEnterFullScreen(aWindow);
mAttachedWindow.removeWindowListener(this);
}
});
mAutoSelectedProjection = VideoProjectionMenuWidget.getAutomaticProjection(getSession().getCurrentUri(), autoEnter);
}

if (mAutoSelectedProjection != VIDEO_PROJECTION_NONE && autoEnter.get()) {
mViewModel.setAutoEnteredVRVideo(true);
postDelayed(() -> enterVRVideo(mAutoSelectedProjection), 300);
} else {
mViewModel.setAutoEnteredVRVideo(false);
if (mProjectionMenu != null) {
mProjectionMenu.setSelectedProjection(mAutoSelectedProjection);
}
}
mAttachedWindow.reCenterFrontWindow();
} else {
mWidgetPlacement = mBeforeFullscreenPlacement;
updateWidget();
// This can be called by content's fullscreen event later but will be a noop.
exitFullScreenMode();

if (mViewModel.getIsInVRVideo().getValue().get()) {
if (isInVRVideo()) {
exitVRVideo();
}
exitFullScreenMode();
mAttachedWindow.centerFrontWindowIfNeeded();
}
}

@Override
public void onContentFullScreen(@NonNull WindowWidget aWindow, boolean aFullScreen) {
if (aFullScreen)
enterFullScreenMode();
else
exitFullScreenMode();
}

public boolean isInVRVideo() {
Expand All @@ -747,37 +749,25 @@ protected void onDraw(Canvas canvas) {
}

private void enterFullScreenMode() {
assert !mAttachedWindow.isFullScreen();
hideMenu();
hideAllNotifications();

mBeforeFullscreenPlacement = mWidgetPlacement.clone();
mWidgetPlacement.cylinder = SettingsStore.getInstance(getContext()).isCurvedModeEnabled();
updateWidget();

if (mAttachedWindow.isResizing()) {
exitResizeMode(ResizeAction.KEEP_SIZE);
}

mBinding.navigationBarFullscreen.brightnessButton.setVisibility(mWidgetManager.isPassthroughEnabled() ? GONE : VISIBLE);
mWidgetManager.pushBackHandler(mFullScreenBackHandler);

mWidgetManager.setControllersVisible(false);
AnimationHelper.fadeOut(mBinding.navigationBarNavigation.navigationBarContainer, 0, null);

mTrayViewModel.setShouldBeVisible(false);

if (mProjectionMenu == null) {
mProjectionMenu = new VideoProjectionMenuWidget(getContext());
mProjectionMenu.setParentWidget(this);
mProjectionMenuPlacement = new WidgetPlacement(getContext());
mWidgetManager.addWidget(mProjectionMenu);
mProjectionMenu.setDelegate((projection)-> {
if (mViewModel.getIsInVRVideo().getValue().get()) {
if (projection == VIDEO_PROJECTION_NONE) {
exitVRVideo();
mAttachedWindow.reCenterFrontWindow();
} else {
// Reproject while reproducing VRVideo
mWidgetManager.showVRVideo(mAttachedWindow.getHandle(), projection);
}
closeFloatingMenus();
} else {
enterVRVideo(projection);
}
});
}
if (mBrightnessWidget == null) {
mBrightnessWidget = new BrightnessMenuWidget(getContext());
mBrightnessWidget.setParentWidget(this);
Expand All @@ -788,12 +778,11 @@ private void enterFullScreenMode() {
}

private void exitFullScreenMode() {
hideMenu();
hideAllNotifications();

if (mAttachedWindow == null || !mAttachedWindow.isFullScreen()) {
return;
}
hideMenu();
hideAllNotifications();

mWidgetManager.setControllersVisible(true);

Expand All @@ -805,6 +794,8 @@ private void exitFullScreenMode() {
}
}, 50);

this.setVisible(!mAttachedWindow.isKioskMode());
mWidgetManager.updateWidget(this);
mWidgetManager.updateWidget(mAttachedWindow);

mWidgetManager.popBackHandler(mFullScreenBackHandler);
Expand Down Expand Up @@ -923,7 +914,6 @@ private void enterVRVideo(@VideoProjectionMenuWidget.VideoProjectionFlags int aP
mProjectionMenu.setSelectedProjection(aProjection);
// Backup the placement because the same widget is reused in FullScreen & MediaControl menus
mProjectionMenuPlacement.copyFrom(mProjectionMenu.getPlacement());
this.setVisible(false);

mFullScreenMedia = getSession().getFullScreenVideo();
// This should not happen, but Gecko does not notify about fullscreen changes in media if
Expand Down Expand Up @@ -997,7 +987,6 @@ private void exitVRVideo() {
closeFloatingMenus();
mWidgetManager.setControllersVisible(true);

this.setVisible(!mAttachedWindow.isKioskMode());
mAttachedWindow.disableVRVideoMode();
mAttachedWindow.setVisible(true);
mMediaControlsWidget.setVisible(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public interface WindowListener {
default void onFocusRequest(@NonNull WindowWidget aWindow) {}
default void onBorderChanged(@NonNull WindowWidget aWindow) {}
default void onSessionChanged(@NonNull Session aOldSession, @NonNull Session aSession) {}
default void onFullScreen(@NonNull WindowWidget aWindow, boolean aFullScreen) {}
default void onContentFullScreen(@NonNull WindowWidget aWindow, boolean aFullScreen) {}
default void onMediaFullScreen(@NonNull final WMediaSession mediaSession, boolean aFullScreen) {}
default void onVideoAvailabilityChanged(@NonNull WindowWidget aWindow) {}
default void onKioskMode(WindowWidget aWindow, boolean isKioskMode) {}
Expand Down Expand Up @@ -935,7 +935,7 @@ public void setIsFullScreen(boolean isFullScreen) {
if (mViewModel.getIsFullscreen().getValue().get() != isFullScreen) {
mViewModel.setIsFullscreen(isFullScreen);
for (WindowListener listener: mListeners) {
listener.onFullScreen(this, isFullScreen);
listener.onContentFullScreen(this, isFullScreen);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ public WindowWidget addWindow() {

if (mFullscreenWindow != null) {
mFullscreenWindow.getSession().exitFullScreen();
onFullScreen(mFullscreenWindow, false);
onContentFullScreen(mFullscreenWindow, false);
}

WindowWidget frontWindow = getFrontWindow();
Expand Down Expand Up @@ -1328,7 +1328,7 @@ public void onVideoAvailabilityChanged(@NonNull WindowWidget aWindow) {
}

@Override
public void onFullScreen(@NonNull WindowWidget aWindow, boolean aFullScreen) {
public void onContentFullScreen(@NonNull WindowWidget aWindow, boolean aFullScreen) {
if (aFullScreen) {
mFullscreenWindow = aWindow;
aWindow.saveBeforeFullscreenPlacement();
Expand Down

0 comments on commit 346ecaf

Please sign in to comment.