chromium/chromeos/crosapi/mojom/cros_display_config.mojom

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

module crosapi.mojom;

import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/display/mojom/display.mojom";

// This API is used for communication between Settings WebUI and Ash C++ code.
// Next MinVersion: 3

// All points, bounds, and insets are in display pixels unless otherwise
// sepcified.

// SetDisplayLayoutInfo or SetDisplayProperties result.
[Stable, Extensible]
enum DisplayConfigResult {
  // CrosDisplayConfigController method call was successful.
  [Default] kSuccess = 0,
  // Operation is not supported.
  kInvalidOperationError,
  // Input display ID represents an invalid display.
  kInvalidDisplayIdError,
  // Unified desktop mode is disabled.
  kUnifiedNotEnabledError,
  // Input property for operation is out of range. E.g. display zoom factor,
  // bounds origin or overscan.
  kPropertyValueOutOfRangeError,
  // Operation is not supported for internal displays.
  kNotSupportedOnInternalDisplayError,
  // Negative values are not supportet for the operation.
  kNegativeValueError,
  // Setting the display mode failed.
  kSetDisplayModeError,
  // Invalid display layout error.
  kInvalidDisplayLayoutError,
  // Mode requires multiple displays.
  kSingleDisplayError,
  // Mirror mode source ID is invalid.
  kMirrorModeSourceIdError,
  // Mirror mode destination ID is invalid.
  kMirrorModeDestIdError,
  // Calibration is not available (e.g. no external touch screen device).
  kCalibrationNotAvailableError,
  // Calibration was not started.
  kCalibrationNotStartedError,
  // Touch calibration is already active.
  kCalibrationInProgressError,
  // Invalid input data for calibration.
  kCalibrationInvalidDataError,
  // Calibration procedure failed.
  kCalibrationFailedError,
};

// Describes how the displays are laid out.
[Stable, Extensible]
enum DisplayLayoutMode {
  // In normal mode displays are laid out as described by
  // DisplayLayoutInfo.layouts.
  [Default] kNormal = 0,
  // In unified desktop mode, a single desktop will be stretched across all
  // available displays.
  kUnified,
  // In mirrored mode, the display defined by DisplayLayoutInfo.mirrorSourceId
  // will be mirrored in the displays defined by
  // DisplayLayoutInfo.mirrorDestinationIds, or in all other displays if
  // mirrorDestinationIds is empty.
  kMirrored
};

// Describes a display edge.
[Stable, Extensible]
enum DisplayLayoutPosition {
  [Default] kTop = 0,
  kRight,
  kBottom,
  kLeft
};

// Describes an overscan or touch calibration operation.
[Stable, Extensible]
enum DisplayConfigOperation {
  // Start a calibration procedure.
  [Default] kStart = 0,
  // Adjusts the current overscan insets for a display.
  kAdjust,
  // Resets the overscan insets for a display to the last saved value.
  kReset,
  // Finish calibration procedure. Save current values and hide the overlay.
  kComplete,
  // Displays the native touch calibration.
  kShowNative,
  // Displays the native touch screen mapping experience which goes through each
  // connected external display and allows you to map the touch device to the
  // corresponding display.
  [MinVersion=2] kShowNativeMappingDisplays,
};

// Describes who initiated configuration change.
[Stable, Extensible]
enum DisplayConfigSource {
  // Display configuration change was requested by the user.
  [Default] kUser = 0,
  // Display configuration change was requested by the policy.
  // Don't show notifications to confirm/revert the change.
  kPolicy
};

// Describes the options the DisplayConfigProperties.rotation and
// DisplayUnitInfo.rotation_options can be set to.
[Stable, Extensible]
enum DisplayRotationOptions {
  // In physical tablet state, enables auto-rotation and clears the user
  // rotation lock. Otherwise, it behaves the same as kZeroDegrees.
  [Default] kAutoRotate = 0,
  // In physical tablet state, Sets the user rotation lock to 0 degrees.
  // Otherwise, it sets the display rotation to 0.
  kZeroDegrees,
  // In physical tablet state, Sets the user rotation lock to 90 degrees.
  // Otherwise, it sets the display rotation 90.
  k90Degrees,
  // In physical tablet state, Sets the user rotation lock to 180 degrees.
  // Otherwise, it sets the display rotation 180.
  k180Degrees,
  // In physical tablet state, Sets the user rotation lock to 270 degrees.
  // Otherwise, it sets the display rotation 270.
  k270Degrees,
};

// Defines a pair of display + touch points used for touch calibration.
[Stable]
struct TouchCalibrationPair {
  // The coordinates of the display point.
  gfx.mojom.Point display_point@0;
  // The coordinates of the touch point corresponding to the display point.
  gfx.mojom.Point touch_point@1;
};

// Defines the data required for touch calibration.
[Stable]
struct TouchCalibration {
  // Must contain exactly four pairs of touch calibration points.
  array<TouchCalibrationPair> pairs@0;
  // Width and height of the display area when the touch calibration was
  // performed.
  gfx.mojom.Size bounds@1;
};

// Defines the layout of a single display.
[Stable]
struct DisplayLayout {
  // The unique identifier of the display.
  string id@0;
  // The unique identifier of the parent display. Empty for the root display.
  string parent_id@1;
  // The edge of the display that is shared with the parent display. Ignored for
  // the root display.
  DisplayLayoutPosition position@2;
  // The offset of the display along the connected edge. 0 indicates that
  // the topmost or leftmost corner is aligned.
  int32 offset@3;
};

// Defines the layout mode and details.
[Stable]
struct DisplayLayoutInfo {
  // The layout mode to use, see DisplayLayoutMode for details.
  DisplayLayoutMode layout_mode@0;
  // Ignored if If layout_mode is not kMirrored. Otherwise, if provided,
  // specifies the unique identifier of the source display for mirroring. If
  // not provided, mirror_destination_ids will be ignored and default ('normal')
  // mirrored mode will be enabled.
  string? mirror_source_id@1;
  // Ignored if layout_mode is not kMirrored. Otherwise, if provided, specifies
  // the unique identifiers of the displays to mirror the source display. If not
  // provided or empty, all displays will mirror the source display.
  array<string>? mirror_destination_ids@2;
  // An array of layouts describing a directed graph of displays. Required if
  // layout_mode is kNormal or kMirrored and not all displays are mirrored
  // ('mixed' mode). Ignored if layout_mode is kUnified.
  array<DisplayLayout>? layouts@3;
};

// EDID extracted parameters. Field description refers to "VESA ENHANCED
// EXTENDED DISPLAY IDENTIFICATION DATA STANDARD (Defines EDID Structure
// Version 1, Revision 4)" Release A, Revision 2 September 25, 2006.
// https://www.vesa.org/vesa-standards
[Stable]
struct Edid {
  // Three character manufacturer code, Sec. 3.4.1 page 21.
  string manufacturer_id@0;
  // Two byte manufacturer-assigned code, Sec. 3.4.2 page 21.
  string product_id@1;
  // Year of manufacture. Sec. 3.4.4 page 22.
  int32 year_of_manufacture@2;
};

// Struct wrapper so that the property can be optional.
[Stable]
struct DisplayRotation {
  DisplayRotationOptions rotation@0;
};

// Defines the properties for a display mode, i.e. a valid size and scale.
[Stable]
struct DisplayMode {
  // The display mode size in device independent (user visible) pixels.
  gfx.mojom.Size size@0;
  // The display mode size in native pixels.
  gfx.mojom.Size size_in_native_pixels@1;
  // The display mode device scale factor.
  double device_scale_factor@2;
  // The display mode refresh rate in hertz.
  double refresh_rate@3;
  // True if the mode is the display's native mode.
  bool is_native@4;
  // True if the mode is interlaced.
  bool is_interlaced@5;
};

// Defines the properties of an individual display, returned by
// GetDisplayLayoutInfo.
[Stable]
struct DisplayUnitInfo {
  // The unique identifier of the display.
  string id@0;
  // The user-friendly name (e.g. "Acme LCD monitor").
  string name@1;
  // EDID properties when available.
  Edid? edid@2;
  // True if this is the primary display.
  bool is_primary@3;
  // True if this is an internal display.
  bool is_internal@4;
  // True if this display is enabled.
  bool is_enabled@5;
  // True if auto-rotation is allowed. It happens when the device is in a
  // physical tablet state or kSupportsClamshellAutoRotation is set.
  bool is_auto_rotation_allowed@6;
  // True if this display has a touch input device associated with it.
  bool has_touch_support@7;
  // True if this display has an accelerometer associated with it.
  bool has_accelerometer_support@8;
  // The number of pixels per inch along the x-axis.
  double dpi_x@9;
  // The number of pixels per inch along the y-axis.
  double dpi_y@10;
  // The display rotation options.
  DisplayRotationOptions rotation_options@11;
  // The display's logical bounds.
  gfx.mojom.Rect bounds@12;
  // The display's ovserscan insets within its screen's bounds.
  gfx.mojom.Insets overscan@13;
  // The usable work area of the display within the display bounds. Excludes
  // areas of the display reserved for the OS, e.g. the taskbar and launcher.
  gfx.mojom.Rect work_area@14;
  // The index of the selected display mode.
  int32 selected_display_mode_index@15;
  // The list of available display modes.
  array<DisplayMode> available_display_modes@16;
  // The ratio between the display's current and default zoom. i.e. 1.0 is
  // is equivalent to 100% zoom, and value 1.5 is equivalent to 150% zoom.
  double display_zoom_factor@17;
  // The list of allowed zoom factor values for the display.
  array<double> available_display_zoom_factors@18;
  // True if the display was detected by the system.
  [MinVersion=1] bool is_detected@19;
};

// Properties for configuring an individual display, used in
// SetDisplayProperties.
[Stable]
struct DisplayConfigProperties {
  // If true, makes the display primary. No-op if set to false.
  bool set_primary@0;
  // If provided, sets the display's overscan insets to the provided value.
  // Note: overscan values may not be negative or larger than a half of the
  // screen's size. Overscan cannot be changed on the internal monitor.
  gfx.mojom.Insets? overscan@1;
  // If provided updates the display's rotation, or if the auto-rotation is
  // allowed in the device, it can be used to set or clear the user rotation
  // lock, enabling or disabling auto-rotation.
  DisplayRotation? rotation@2;
  // If provided, updates the display's logical bounds origin. Note: when
  // updating the display origin, some constraints will be applied. so the final
  // bounds origin may be different than the one set. The actual bounds will be
  // reflected in DisplayUnitInfo. Cannot be changed on the primary display (or
  // if set_primary is true).
  gfx.mojom.Point? bounds_origin@3;
  // If non zero, updates the zoom associated with the display. This zoom
  // performs relayout and repaint thus resulting in a better quality zoom than
  // just performing a pixel by pixel stretch enlargement.
  double display_zoom_factor@4;
  // Optional DisplayMode properties to set. This should match one of the
  // modes listed in DisplayUnitInfo.available_display_modes. Other custom
  // modes may or may not be valid.
  DisplayMode? display_mode@5;
};

// Interface for configuring displays in Chrome OS. Currently this is
// implemented in Ash through classes owned by ash::Shell, but the interface
// should not have any Ash specific dependencies.
[Stable, Uuid="a172cdb1-c97f-4a53-9ac9-6b96c18da099"]
interface CrosDisplayConfigController {
  // Observers are notified when the display layout or any display properties
  // change.
  AddObserver@0(pending_associated_remote<CrosDisplayConfigObserver> observer);

  // Returns the display layout info, including the list of layouts.
  GetDisplayLayoutInfo@1() => (DisplayLayoutInfo info);

  // Sets the layout mode, mirroring, and layouts. Returns kSuccess if the
  // layout is valid or an error value otherwise.
  SetDisplayLayoutInfo@2(DisplayLayoutInfo info) =>
    (DisplayConfigResult result);

  // Returns the properties for all displays. If |single_unified| is true, a
  // single display will be returned if the display layout is in unifed mode.
  GetDisplayUnitInfoList@3(bool single_unified) =>
    (array<DisplayUnitInfo> info_list);

  // Sets |properties| for individual display with identifier |id|. |source|
  // should describe who initiated the change. Returns Success if the properties
  // are valid or an error value otherwise.
  SetDisplayProperties@4(string id,
                       DisplayConfigProperties properties,
                       DisplayConfigSource source) =>
    (DisplayConfigResult result);

  // Enables or disables unified desktop mode. If the current display mode is
  // kMirrored the mode will not be changed, if it is kNormal then the mode will
  // be set to kUnified.
  SetUnifiedDesktopEnabled@5(bool enabled);

  // Starts, updates, completes, or resets overscan calibration for the display
  // with identifier |display_id|. If |op| is kAdjust, |delta| describes the
  // amount to change the overscan value. Runs the callback after performing the
  // operation or on error.
  OverscanCalibration@6(string display_id,
                      DisplayConfigOperation op,
                      gfx.mojom.Insets? delta) => (DisplayConfigResult result);

  // Starts, completes, or resets touch calibration for the display with
  // identifier |display_id|. If |op| is kShowNative shows the native
  // calibration UI. Runs the callback after performing the operation or on
  // error.
  TouchCalibration@7(string display_id,
                   DisplayConfigOperation op,
                   TouchCalibration? calibration) =>
    (DisplayConfigResult result);

  // Sets |id| of display to render identification highlight on. Invalid |id|
  // turns identification highlight off.
  HighlightDisplay@8(int64 id);

  // Updates preview indicators with change in position of display being dragged
  // in display layouts section of the display settings page. |display_id| is
  // the ID of the display being dragged. |delta_x| and |delta_y| are the change
  // in position of the dragged display since DragDisplayDelta() was last
  // called. |display_id| remains the same while the drag is in progress, once
  // the display is dropped, the new layout is applied, updating the display
  // configuration.
  DragDisplayDelta@9(int64 display_id, int32 delta_x, int32 delta_y);
};

// Interface for clients needing to be informed when the display configuration
// changes.
[Stable, Uuid="61eda0c8-63dc-49eb-ad43-02acfd48d4f5"]
interface CrosDisplayConfigObserver {
  // Called any time the display configuration changes.
  OnDisplayConfigChanged@0();
};