1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_
6 #define UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_
14 #include "base/event_types.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/observer_list.h"
17 #include "base/timer/timer.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19 #include "ui/display/display_export.h"
20 #include "ui/display/types/chromeos/native_display_observer.h"
21 #include "ui/display/types/display_constants.h"
22 #include "ui/gfx/geometry/size.h"
31 class DisplaySnapshot
;
32 class NativeDisplayDelegate
;
34 // This class interacts directly with the system display configurator.
35 class DISPLAY_EXPORT DisplayConfigurator
: public NativeDisplayObserver
{
37 typedef uint64_t ContentProtectionClientId
;
38 static const ContentProtectionClientId kInvalidClientId
= 0;
43 DisplaySnapshot
* display
; // Not owned.
45 // XInput device ID or 0 if this display isn't a touchscreen.
48 // User-selected mode for the display.
49 const DisplayMode
* selected_mode
;
51 // Mode used when displaying the same desktop on multiple displays.
52 const DisplayMode
* mirror_mode
;
55 typedef std::vector
<DisplayState
> DisplayStateList
;
59 virtual ~Observer() {}
61 // Called after the display mode has been changed. |display| contains the
62 // just-applied configuration. Note that the X server is no longer grabbed
63 // when this method is called, so the actual configuration could've changed
65 virtual void OnDisplayModeChanged(
66 const std::vector
<DisplayState
>& displays
) {}
68 // Called after a display mode change attempt failed. |failed_new_state| is
69 // the new state which the system failed to enter.
70 virtual void OnDisplayModeChangeFailed(
71 MultipleDisplayState failed_new_state
) {}
74 // Interface for classes that make decisions about which display state
76 class StateController
{
78 virtual ~StateController() {}
80 // Called when displays are detected.
81 virtual MultipleDisplayState
GetStateForDisplayIds(
82 const std::vector
<int64_t>& display_ids
) const = 0;
84 // Queries the resolution (|size|) in pixels to select display mode for the
86 virtual bool GetResolutionForDisplayId(int64_t display_id
,
87 gfx::Size
* size
) const = 0;
90 // Interface for classes that implement software based mirroring.
91 class SoftwareMirroringController
{
93 virtual ~SoftwareMirroringController() {}
95 // Called when the hardware mirroring failed.
96 virtual void SetSoftwareMirroring(bool enabled
) = 0;
97 virtual bool SoftwareMirroringEnabled() const = 0;
100 class TouchscreenDelegate
{
102 virtual ~TouchscreenDelegate() {}
104 // Searches for touchscreens among input devices,
105 // and tries to match them up to screens in |displays|.
106 // |displays| is an array of detected screens.
107 // If a touchscreen with same resolution as a display's native mode
108 // is detected, its id will be stored in this display.
109 virtual void AssociateTouchscreens(std::vector
<DisplayState
>* displays
) = 0;
112 // Helper class used by tests.
115 TestApi(DisplayConfigurator
* configurator
) : configurator_(configurator
) {}
118 // If |configure_timer_| is started, stops the timer, runs
119 // ConfigureDisplays(), and returns true; returns false otherwise.
120 bool TriggerConfigureTimeout() WARN_UNUSED_RESULT
;
123 DisplayConfigurator
* configurator_
; // not owned
125 DISALLOW_COPY_AND_ASSIGN(TestApi
);
128 // Flags that can be passed to SetDisplayPower().
129 static const int kSetDisplayPowerNoFlags
;
130 // Configure displays even if the passed-in state matches |power_state_|.
131 static const int kSetDisplayPowerForceProbe
;
132 // Do not change the state if multiple displays are connected or if the
133 // only connected display is external.
134 static const int kSetDisplayPowerOnlyIfSingleInternalDisplay
;
136 // Gap between screens so cursor at bottom of active display doesn't
137 // partially appear on top of inactive display. Higher numbers guard
138 // against larger cursors, but also waste more memory.
139 // For simplicity, this is hard-coded to avoid the complexity of always
140 // determining the DPI of the screen and rationalizing which screen we
141 // need to use for the DPI calculation.
142 // See crbug.com/130188 for initial discussion.
143 static const int kVerticalGap
= 60;
145 // Returns the mode within |display| that matches the given size with highest
146 // refresh rate. Returns None if no matching display was found.
147 static const DisplayMode
* FindDisplayModeMatchingSize(
148 const DisplaySnapshot
& display
,
149 const gfx::Size
& size
);
151 DisplayConfigurator();
152 virtual ~DisplayConfigurator();
154 MultipleDisplayState
display_state() const { return display_state_
; }
155 chromeos::DisplayPowerState
power_state() const { return power_state_
; }
156 const gfx::Size
framebuffer_size() const { return framebuffer_size_
; }
157 const std::vector
<DisplayState
>& cached_displays() const {
158 return cached_displays_
;
161 void set_state_controller(StateController
* controller
) {
162 state_controller_
= controller
;
164 void set_mirroring_controller(SoftwareMirroringController
* controller
) {
165 mirroring_controller_
= controller
;
168 // Replaces |native_display_delegate_| and |touchscreen_delegate_| with the 2
169 // delegates passed in and sets |configure_display_| to true. Should be called
171 void SetDelegatesForTesting(
172 scoped_ptr
<NativeDisplayDelegate
> display_delegate
,
173 scoped_ptr
<TouchscreenDelegate
> touchscreen_delegate
);
175 // Sets the initial value of |power_state_|. Must be called before Start().
176 void SetInitialDisplayPower(chromeos::DisplayPowerState power_state
);
178 // Initialization, must be called right after constructor.
179 // |is_panel_fitting_enabled| indicates hardware panel fitting support.
180 void Init(bool is_panel_fitting_enabled
);
182 // Does initial configuration of displays during startup.
183 // If |background_color_argb| is non zero and there are multiple displays,
184 // DisplayConfigurator sets the background color of X's RootWindow to this
186 void ForceInitialConfigure(uint32_t background_color_argb
);
188 // Stop handling display configuration events/requests.
189 void PrepareForExit();
191 // Called when powerd notifies us that some set of displays should be turned
192 // on or off. This requires enabling or disabling the CRTC associated with
193 // the display(s) in question so that the low power state is engaged.
194 // |flags| contains bitwise-or-ed kSetDisplayPower* values.
195 bool SetDisplayPower(chromeos::DisplayPowerState power_state
, int flags
);
197 // Force switching the display mode to |new_state|. Returns false if
198 // switching failed (possibly because |new_state| is invalid for the
199 // current set of connected displays).
200 bool SetDisplayMode(MultipleDisplayState new_state
);
202 // NativeDisplayDelegate::Observer overrides:
203 virtual void OnConfigurationChanged() OVERRIDE
;
205 void AddObserver(Observer
* observer
);
206 void RemoveObserver(Observer
* observer
);
208 // Sets all the displays into pre-suspend mode; usually this means
209 // configure them for their resume state. This allows faster resume on
210 // machines where display configuration is slow.
211 void SuspendDisplays();
213 // Reprobes displays to handle changes made while the system was
215 void ResumeDisplays();
217 // Registers a client for display protection and requests a client id. Returns
218 // 0 if requesting failed.
219 ContentProtectionClientId
RegisterContentProtectionClient();
221 // Unregisters the client.
222 void UnregisterContentProtectionClient(ContentProtectionClientId client_id
);
224 // Queries link status and protection status.
225 // |link_mask| is the type of connected display links, which is a bitmask of
226 // DisplayConnectionType values. |protection_mask| is the desired protection
227 // methods, which is a bitmask of the ContentProtectionMethod values.
228 // Returns true on success.
229 bool QueryContentProtectionStatus(ContentProtectionClientId client_id
,
232 uint32_t* protection_mask
);
234 // Requests the desired protection methods.
235 // |protection_mask| is the desired protection methods, which is a bitmask
236 // of the ContentProtectionMethod values.
237 // Returns true when the protection request has been made.
238 bool EnableContentProtection(ContentProtectionClientId client_id
,
240 uint32_t desired_protection_mask
);
242 // Checks the available color profiles for |display_id| and fills the result
244 std::vector
<ui::ColorCalibrationProfile
> GetAvailableColorCalibrationProfiles(
247 // Updates the color calibration to |new_profile|.
248 bool SetColorCalibrationProfile(int64_t display_id
,
249 ui::ColorCalibrationProfile new_profile
);
252 // Mapping a display_id to a protection request bitmask.
253 typedef std::map
<int64_t, uint32_t> ContentProtections
;
254 // Mapping a client to its protection request.
255 typedef std::map
<ContentProtectionClientId
, ContentProtections
>
258 // Performs platform specific delegate initialization.
259 scoped_ptr
<NativeDisplayDelegate
> CreatePlatformNativeDisplayDelegate();
260 scoped_ptr
<TouchscreenDelegate
> CreatePlatformTouchscreenDelegate();
262 // Updates |cached_displays_| to contain currently-connected displays. Calls
263 // |delegate_->GetDisplays()| and then does additional work, like finding the
264 // mirror mode and setting user-preferred modes. Note that the server must be
265 // grabbed via |delegate_->GrabServer()| first.
266 void UpdateCachedDisplays();
268 // Helper method for UpdateCachedDisplays() that initializes the passed-in
269 // displays' |mirror_mode| fields by looking for a mode in |internal_display|
270 // and |external_display| having the same resolution. Returns false if a
272 // mode wasn't found or created.
274 // |try_panel_fitting| allows creating a panel-fitting mode for
275 // |internal_display| instead of only searching for a matching mode (note that
276 // it may lead to a crash if |internal_info| is not capable of panel fitting).
278 // |preserve_aspect| limits the search/creation only to the modes having the
279 // native aspect ratio of |external_display|.
280 bool FindMirrorMode(DisplayState
* internal_display
,
281 DisplayState
* external_display
,
282 bool try_panel_fitting
,
283 bool preserve_aspect
);
285 // Configures displays.
286 void ConfigureDisplays();
288 // Notifies observers about an attempted state change.
289 void NotifyObservers(bool success
, MultipleDisplayState attempted_state
);
291 // Switches to the state specified in |display_state| and |power_state|.
292 // If the hardware mirroring failed and |mirroring_controller_| is set,
293 // it switches to |STATE_DUAL_EXTENDED| and calls |SetSoftwareMirroring()|
294 // to enable software based mirroring.
295 // On success, updates |display_state_|, |power_state_|, and
296 // |cached_displays_| and returns true.
297 bool EnterStateOrFallBackToSoftwareMirroring(
298 MultipleDisplayState display_state
,
299 chromeos::DisplayPowerState power_state
);
301 // Switches to the state specified in |display_state| and |power_state|.
302 // On success, updates |display_state_|, |power_state_|, and
303 // |cached_displays_| and returns true.
304 bool EnterState(MultipleDisplayState display_state
,
305 chromeos::DisplayPowerState power_state
);
307 // Returns the display state that should be used with |cached_displays_| while
309 MultipleDisplayState
ChooseDisplayState(
310 chromeos::DisplayPowerState power_state
) const;
312 // Returns the ratio between mirrored mode area and native mode area:
313 // (mirror_mode_width * mirrow_mode_height) / (native_width * native_height)
314 float GetMirroredDisplayAreaRatio(const DisplayState
& display
);
316 // Returns true if in either hardware or software mirroring mode.
317 bool IsMirroring() const;
319 // Applies display protections according to requests.
320 bool ApplyProtections(const ContentProtections
& requests
);
322 StateController
* state_controller_
;
323 SoftwareMirroringController
* mirroring_controller_
;
324 scoped_ptr
<NativeDisplayDelegate
> native_display_delegate_
;
325 scoped_ptr
<TouchscreenDelegate
> touchscreen_delegate_
;
327 // Used to enable modes which rely on panel fitting.
328 bool is_panel_fitting_enabled_
;
330 // This is detected by the constructor to determine whether or not we should
331 // be enabled. If we aren't running on ChromeOS, we can't assume that the
332 // Xrandr X11 extension is supported.
333 // If this flag is set to false, any attempts to change the display
334 // configuration to immediately fail without changing the state.
335 bool configure_display_
;
337 // The current display state.
338 MultipleDisplayState display_state_
;
340 gfx::Size framebuffer_size_
;
342 // The current power state.
343 chromeos::DisplayPowerState power_state_
;
345 // Most-recently-used display configuration. Note that the actual
346 // configuration changes asynchronously.
347 DisplayStateList cached_displays_
;
349 ObserverList
<Observer
> observers_
;
351 // The timer to delay configuring displays. This is used to aggregate multiple
352 // display configuration events when they are reported in short time spans.
353 // See comment for NativeDisplayEventDispatcherX11 for more details.
354 base::OneShotTimer
<DisplayConfigurator
> configure_timer_
;
356 // Id for next display protection client.
357 ContentProtectionClientId next_display_protection_client_id_
;
359 // Display protection requests of each client.
360 ProtectionRequests client_protection_requests_
;
362 DISALLOW_COPY_AND_ASSIGN(DisplayConfigurator
);
367 #endif // UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_