1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136

ash / display / display_configuration_controller.h [blame]

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_DISPLAY_DISPLAY_CONFIGURATION_CONTROLLER_H_
#define ASH_DISPLAY_DISPLAY_CONFIGURATION_CONTROLLER_H_

#include <memory>

#include "ash/ash_export.h"
#include "ash/display/window_tree_host_manager.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "ui/display/display.h"
#include "ui/display/manager/display_manager_observer.h"
#include "ui/display/unified_desktop_utils.h"

namespace display {
class DisplayLayout;
class DisplayManager;
}  // namespace display

namespace ash {

class DisplayAnimator;
class ScreenRotationAnimator;

// This class controls Display related configuration. Specifically it:
// * Handles animated transitions where appropriate.
// * Limits the frequency of certain operations.
// * Provides a single interface for UI and API classes.
// * TODO: Forwards display configuration changed events to UI and API classes.
class ASH_EXPORT DisplayConfigurationController
    : public display::DisplayManagerObserver {
 public:
  // Use SYNC if it is important to rotate immediately after the
  // |SetDisplayRotation()|. As a side effect, the animation is less smooth.
  // ASYNC is actually slower because it takes longer to rotate the screen after
  // a screenshot is taken. http://crbug.com/757851.
  enum RotationAnimation {
    ANIMATION_SYNC = 0,
    ANIMATION_ASYNC,
  };

  DisplayConfigurationController(
      display::DisplayManager* display_manager,
      WindowTreeHostManager* window_tree_host_manager);

  DisplayConfigurationController(const DisplayConfigurationController&) =
      delete;
  DisplayConfigurationController& operator=(
      const DisplayConfigurationController&) = delete;

  ~DisplayConfigurationController() override;

  // Sets the layout for the current displays with a fade in/out
  // animation.
  void SetDisplayLayout(std::unique_ptr<display::DisplayLayout> layout);

  // This should be called instead of SetDisplayLayout() to set the display
  // layout in the case of Unified Desktop mode. A fade in/out animation is
  // used as well.
  void SetUnifiedDesktopLayoutMatrix(
      const display::UnifiedDesktopLayoutMatrix& matrix);

  // Sets the mirror mode with a fade-in/fade-out animation. Affects all
  // displays. If |throttle| is true, this will fail if called within the
  // throttle time.
  void SetMirrorMode(bool mirror, bool throttle);

  // Sets the display's rotation with animation if available.
  void SetDisplayRotation(int64_t display_id,
                          display::Display::Rotation rotation,
                          display::Display::RotationSource source,
                          RotationAnimation mode = ANIMATION_ASYNC);

  // Returns the rotation of the display given by |display_id|. This returns
  // the target rotation when the display is being rotated.
  display::Display::Rotation GetTargetRotation(int64_t display_id);

  // Sets the primary display id. If |throttle| is true, this will fail if
  // called within the throttle time.
  void SetPrimaryDisplayId(int64_t display_id, bool throttle);

  // In Unified Desktop mode, we consider the display in which the shelf will be
  // placed to be the "primary mirroring display". Note that this is different
  // from the "normal" primary display, which is just the single unified display
  // in unified mode. This display will be:
  //   - The bottom-left in the matrix if the shelf alignment is "bottom",
  //   - The top-left in the matrix if the shelf alignment is "left",
  //   - The top-right in the matrix if the shelf alignment is "right".
  // This should only be called when Unified Desktop mode is active.
  display::Display GetPrimaryMirroringDisplayForUnifiedDesktop() const;

  // display::DisplayManagerObserver
  void OnDidApplyDisplayChanges() override;

  static void DisableAnimatorForTest();

 protected:
  friend class DisplayConfigurationControllerTestApi;

  // Allow tests to enable or disable animations.
  void SetAnimatorForTest(bool enable);

 private:
  class DisplayChangeLimiter;

  // Sets the timeout for the DisplayChangeLimiter if it exists. Call this
  // *before* starting any animations.
  void SetThrottleTimeout(int64_t throttle_ms);
  bool IsLimited();
  void SetDisplayLayoutImpl(std::unique_ptr<display::DisplayLayout> layout);
  void SetMirrorModeImpl(bool mirror);
  void SetPrimaryDisplayIdImpl(int64_t display_id);
  void SetUnifiedDesktopLayoutMatrixImpl(
      const display::UnifiedDesktopLayoutMatrix& matrix);

  // Returns the ScreenRotationAnimator associated with the |display_id|'s
  // |root_window|. If there is no existing ScreenRotationAnimator for
  // |root_window|, it will make one and store in the |root_window| property
  // |kScreenRotationAnimatorKey|.
  ScreenRotationAnimator* GetScreenRotationAnimatorForDisplay(
      int64_t display_id);

  raw_ptr<display::DisplayManager> display_manager_;         // weak ptr
  raw_ptr<WindowTreeHostManager> window_tree_host_manager_;  // weak ptr
  std::unique_ptr<DisplayAnimator> display_animator_;
  std::unique_ptr<DisplayChangeLimiter> limiter_;

  base::WeakPtrFactory<DisplayConfigurationController> weak_ptr_factory_{this};
};

}  // namespace ash

#endif  // ASH_DISPLAY_DISPLAY_CONFIGURATION_CONTROLLER_H_