Index: chrome/browser/ui/cocoa/fullscreen_low_power_coordinator.mm |
diff --git a/chrome/browser/ui/cocoa/fullscreen_low_power_coordinator.mm b/chrome/browser/ui/cocoa/fullscreen_low_power_coordinator.mm |
index e3404c2f4072b6064bf7a19cd795b77687d1aa8b..fddcf9073ccf56b67a3438f2138251965eef56c5 100644 |
--- a/chrome/browser/ui/cocoa/fullscreen_low_power_coordinator.mm |
+++ b/chrome/browser/ui/cocoa/fullscreen_low_power_coordinator.mm |
@@ -4,11 +4,14 @@ |
#include "chrome/browser/ui/cocoa/fullscreen_low_power_coordinator.h" |
+#include "ui/base/cocoa/animation_utils.h" |
+#include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h" |
+ |
namespace { |
-// The minimum number of frames with valid low power contents that we need to |
-// receive in a row before showing the low power window. |
-const uint64_t kMinValidFrames = 15; |
+// The number of frames we need to be in the WarmUp state before moving to the |
+// Enabled state. |
+const uint64_t kWarmUpFramesBeforeEnteringLowPowerMode = 30; |
} // namespace |
@@ -85,6 +88,14 @@ - (void)sendEvent:(NSEvent*)event { |
bool in_fullscreen_transition) { |
allowed_by_fullscreen_transition_ = !in_fullscreen_transition; |
EnterOrExitLowPowerModeIfNeeded(); |
+ |
+ // Note that we should close the window here so that it does not appear in |
+ // the background during the transition back to windowed mode. Closing a |
+ // window that is in detached mode results in a janky transition and system |
+ // crashes. |
+ // TODO(ccameron): Allow closing the window here if we have not been in |
+ // detached mode for several frames. |
+ // https://crbug.com/644133 |
} |
void FullscreenLowPowerCoordinatorCocoa::SetLayoutParameters( |
@@ -139,11 +150,15 @@ - (void)sendEvent:(NSEvent*)event { |
} |
void FullscreenLowPowerCoordinatorCocoa::SetLowPowerLayerValid(bool valid) { |
- if (valid) |
- low_power_layer_valid_frame_count_ += 1; |
- else |
- low_power_layer_valid_frame_count_ = 0; |
+ State old_state = state_; |
+ |
+ low_power_layer_valid_ = valid; |
EnterOrExitLowPowerModeIfNeeded(); |
+ |
+ if (state_ == old_state) |
+ frames_in_state_ += 1; |
+ else |
+ frames_in_state_ = 0; |
} |
void FullscreenLowPowerCoordinatorCocoa::WillLoseAcceleratedWidget() { |
@@ -153,33 +168,58 @@ - (void)sendEvent:(NSEvent*)event { |
EnterOrExitLowPowerModeIfNeeded(); |
} |
+void FullscreenLowPowerCoordinatorCocoa::TickEnterOrExitForTesting() { |
+ frames_in_state_ += 1; |
+ EnterOrExitLowPowerModeIfNeeded(); |
+} |
+ |
void FullscreenLowPowerCoordinatorCocoa::EnterOrExitLowPowerModeIfNeeded() { |
- bool new_in_low_power_mode = |
- widget_ && low_power_window_ && |
- low_power_layer_valid_frame_count_ > kMinValidFrames && |
+ bool can_use_low_power_window = |
+ widget_ && low_power_window_ && low_power_layer_valid_ && |
allowed_by_fullscreen_transition_ && allowed_by_nsview_layout_ && |
allowed_by_child_windows_ && allowed_by_active_sheet_; |
- if (new_in_low_power_mode) { |
- // Update whether or not we are in low power mode based on whether or not |
- // the low power window is in front (we do not get notifications of window |
- // order change). |
- in_low_power_mode_ &= |
- [[NSApp orderedWindows] firstObject] == low_power_window_.get(); |
- |
- if (!in_low_power_mode_) { |
- [low_power_window_ setFrame:[content_window_ frame] display:YES]; |
- [low_power_window_ |
- setStyleMask:[low_power_window_ styleMask] | NSFullScreenWindowMask]; |
- [low_power_window_ orderWindow:NSWindowAbove |
- relativeTo:[content_window_ windowNumber]]; |
- in_low_power_mode_ = true; |
- } |
- } else { |
- if (in_low_power_mode_) { |
- [low_power_window_ orderWindow:NSWindowBelow |
- relativeTo:[content_window_ windowNumber]]; |
- in_low_power_mode_ = false; |
- } |
+ switch (state_) { |
+ case Disabled: |
+ if (can_use_low_power_window) { |
+ // Ensure that the window's frame and style are set, and order it behind |
+ // the main window, so that it's ready to be moved in front. |
+ state_ = WarmingUp; |
+ [low_power_window_ setStyleMask:[low_power_window_ styleMask] | |
+ NSFullScreenWindowMask]; |
+ [low_power_window_ setFrame:[content_window_ frame] |
+ display:YES |
+ animate:NO]; |
+ [low_power_window_ orderWindow:NSWindowBelow |
+ relativeTo:[content_window_ windowNumber]]; |
+ } |
+ break; |
+ case WarmingUp: |
+ if (can_use_low_power_window) { |
+ // After a few frames, move in front of the main window. |
+ if (frames_in_state_ > kWarmUpFramesBeforeEnteringLowPowerMode) { |
+ state_ = Enabled; |
+ [low_power_window_ orderWindow:NSWindowAbove |
+ relativeTo:[content_window_ windowNumber]]; |
+ } |
+ } else { |
+ state_ = Disabled; |
+ } |
+ break; |
+ case Enabled: |
+ if (can_use_low_power_window) { |
+ // We do not get notifications of window order change. Check here that |
+ // the low power window is in front (and move it there if it isn't). |
+ if ([[NSApp orderedWindows] firstObject] != low_power_window_.get()) { |
+ [low_power_window_ orderWindow:NSWindowAbove |
+ relativeTo:[content_window_ windowNumber]]; |
+ } |
+ } else { |
+ // Move behind the main window. |
+ state_ = Disabled; |
+ [low_power_window_ orderWindow:NSWindowBelow |
+ relativeTo:[content_window_ windowNumber]]; |
+ } |
+ break; |
} |
} |