chromium/ash/system/screen_layout_observer.h

// Copyright 2012 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_SYSTEM_SCREEN_LAYOUT_OBSERVER_H_
#define ASH_SYSTEM_SCREEN_LAYOUT_OBSERVER_H_

#include <stdint.h>

#include <map>
#include <set>
#include <string>

#include "ash/ash_export.h"
#include "base/gtest_prod_util.h"
#include "ui/display/manager/display_manager_observer.h"
#include "ui/display/manager/managed_display_info.h"

namespace ash {

// ScreenLayoutObserver is responsible to send notification to users when screen
// resolution changes or screen rotation changes.
class ASH_EXPORT ScreenLayoutObserver : public display::DisplayManagerObserver {
 public:
  ScreenLayoutObserver();

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

  ~ScreenLayoutObserver() override;

  static const char kNotificationId[];

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

  // No notification will be shown only for the next ui scale change for the
  // display with |display_id|. This state will be consumed and subsequent
  // changes won't be affected.
  void SetDisplayChangedFromSettingsUI(int64_t display_id);

  // Notifications are shown in production and are not shown in unit tests.
  // Allow individual unit tests to show notifications.
  void set_show_notifications_for_testing(bool show) {
    show_notifications_for_testing_ = show;
  }

 private:
  FRIEND_TEST_ALL_PREFIXES(ScreenLayoutObserverTestMultiMirroring,
                           DisplayNotifications);
  friend class ScreenLayoutObserverTest;

  using DisplayInfoMap = std::map<int64_t, display::ManagedDisplayInfo>;

  // Scans the current display info and updates |display_info_|. Sets the
  // previous data to |old_info| if it's not NULL.
  void UpdateDisplayInfo(DisplayInfoMap* old_info);

  // Compares the current display settings with |old_info| and determine what
  // message should be shown for notification. Returns true if there's a
  // meaningful change. Note that it's possible to return true and set
  // |out_message| to empty, which means the notification should be removed. It
  // also sets |out_additional_message| which appears in the notification with
  // the |out_message|.
  bool GetUnassociatedDisplayMessage(const DisplayInfoMap& old_info,
                                     std::u16string* out_message,
                                     std::u16string* out_additional_message);

  // Creates or updates the display notification.
  void CreateOrUpdateNotification(const std::u16string& message,
                                  const std::u16string& additional_message);

  // Returns the notification message that should be shown when mirror display
  // mode is exited.
  bool GetExitMirrorModeMessage(std::u16string* out_message,
                                std::u16string* out_additional_message);

  DisplayInfoMap display_info_;

  enum class DisplayMode {
    SINGLE,
    EXTENDED_2,       // 2 displays in extended mode.
    EXTENDED_3_PLUS,  // 3+ displays in extended mode.
    MIRRORING,
    UNIFIED,
    DOCKED
  };

  DisplayMode old_display_mode_ = DisplayMode::SINGLE;
  DisplayMode current_display_mode_ = DisplayMode::SINGLE;

  bool has_unassociated_display_ = false;

  // When the UI scale of a display is modified from the Settings UI, we should
  // ignore this change and avoid showing a notification for it.
  std::set<int64_t> displays_changed_from_settings_ui_;

  bool show_notifications_for_testing_ = true;
};

}  // namespace ash

#endif  // ASH_SYSTEM_SCREEN_LAYOUT_OBSERVER_H_