1 // Copyright (c) 2012 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 CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_
6 #define CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_
10 #include "base/basictypes.h"
11 #include "base/event_types.h"
12 #include "base/observer_list.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop.h"
15 #include "base/timer.h"
16 #include "chromeos/chromeos_export.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 // Forward declarations for Xlib and Xrandr.
20 // This is so unused X definitions don't pollute the namespace.
21 typedef unsigned long XID
;
28 // Used to describe the state of a multi-display configuration.
37 // Information that is necessary to construct display id
38 // in |OutputConfigurator::Delegate|.
39 // TODO(oshima): Move xrandr related functions to here
40 // from ui/base/x and replace this with display id list.
46 // This class interacts directly with the underlying Xrandr API to manipulate
48 class CHROMEOS_EXPORT OutputConfigurator
: public MessageLoop::Dispatcher
{
50 // Information about an output's current state.
51 struct OutputSnapshot
{
56 // CRTC that should be used for this output. Not necessarily the CRTC
57 // that XRandR reports is currently being used.
68 bool is_aspect_preserving_scaling
;
70 // XInput device ID or 0 if this output isn't a touchscreen.
74 struct CoordinateTransformation
{
75 // Initialized to the identity transformation.
76 CoordinateTransformation();
86 CrtcConfig(RRCrtc crtc
, int x
, int y
, RRMode mode
, RROutput output
);
97 virtual ~Observer() {}
99 // Called when the change of the display mode finished. It will usually
100 // start the fading in the displays.
101 virtual void OnDisplayModeChanged() {}
103 // Called when the change of the display mode is issued but failed.
104 // |failed_new_state| is the new state which the system failed to enter.
105 virtual void OnDisplayModeChangeFailed(OutputState failed_new_state
) {}
108 // Interface for classes that make decisions about which output state
110 class StateController
{
112 virtual ~StateController() {}
114 // Called when displays are detected.
115 virtual OutputState
GetStateForOutputs(
116 const std::vector
<OutputInfo
>& outputs
) const = 0;
119 // Interface for classes that perform actions on behalf of OutputController.
122 virtual ~Delegate() {}
124 virtual void SetPanelFittingEnabled(bool enabled
) = 0;
126 // Initializes the XRandR extension, saving the base event ID to
128 virtual void InitXRandRExtension(int* event_base
) = 0;
130 // Tells XRandR to update its configuration in response to |event|, an
131 // RRScreenChangeNotify event.
132 virtual void UpdateXRandRConfiguration(const base::NativeEvent
& event
) = 0;
134 // Grabs the X server and refreshes XRandR-related resources. While
135 // the server is grabbed, other clients are blocked. Must be balanced
136 // by a call to UngrabServer().
137 virtual void GrabServer() = 0;
139 // Ungrabs the server and frees XRandR-related resources.
140 virtual void UngrabServer() = 0;
142 // Flushes all pending requests and waits for replies.
143 virtual void SyncWithServer() = 0;
145 // Sets the window's background color to |color_argb|.
146 virtual void SetBackgroundColor(uint32 color_argb
) = 0;
148 // Enables DPMS and forces it to the "on" state.
149 virtual void ForceDPMSOn() = 0;
151 // Returns information about the current outputs.
152 virtual std::vector
<OutputSnapshot
> GetOutputs() = 0;
154 // Gets details corresponding to |mode|. Parameters may be NULL.
155 // Returns true on success.
156 virtual bool GetModeDetails(RRMode mode
,
159 bool* interlaced
) = 0;
161 // Calls XRRSetCrtcConfig() with the given options but some of our
162 // default output count and rotation arguments.
163 virtual void ConfigureCrtc(CrtcConfig
* config
) = 0;
165 // Called to set the frame buffer (underlying XRR "screen") size. Has
166 // a side-effect of disabling all CRTCs.
167 virtual void CreateFrameBuffer(
170 const std::vector
<OutputConfigurator::CrtcConfig
>& configs
) = 0;
172 // Configures XInput's Coordinate Transformation Matrix property.
173 // |touch_device_id| the ID of the touchscreen device to configure.
174 // |ctm| contains the desired transformation parameters. The offsets
175 // in it should be normalized so that 1 corresponds to the X or Y axis
176 // size for the corresponding offset.
177 virtual void ConfigureCTM(int touch_device_id
,
178 const CoordinateTransformation
& ctm
) = 0;
180 // Sends a D-Bus message to the power manager telling it that the
181 // machine is or is not projecting.
182 virtual void SendProjectingStateToPowerManager(bool projecting
) = 0;
185 // Helper class used by tests.
188 TestApi(OutputConfigurator
* configurator
, int xrandr_event_base
)
189 : configurator_(configurator
),
190 xrandr_event_base_(xrandr_event_base
) {}
193 // Dispatches RRScreenChangeNotify and RRNotify_OutputChange events to
194 // |configurator_| and runs ConfigureOutputs(). Returns false if
195 // |configure_timer_| wasn't started.
196 bool SendOutputChangeEvents(bool connected
);
199 OutputConfigurator
* configurator_
; // not owned
201 int xrandr_event_base_
;
203 DISALLOW_COPY_AND_ASSIGN(TestApi
);
206 // Flags that can be passed to SetDisplayPower().
207 static const int kSetDisplayPowerNoFlags
= 0;
208 // Configure displays even if the passed-in state matches |power_state_|.
209 static const int kSetDisplayPowerForceProbe
= 1 << 0;
210 // Do not change the state if multiple displays are connected or if the
211 // only connected display is external.
212 static const int kSetDisplayPowerOnlyIfSingleInternalDisplay
= 1 << 1;
214 // Gap between screens so cursor at bottom of active display doesn't
215 // partially appear on top of inactive display. Higher numbers guard
216 // against larger cursors, but also waste more memory.
217 // For simplicity, this is hard-coded to avoid the complexity of always
218 // determining the DPI of the screen and rationalizing which screen we
219 // need to use for the DPI calculation.
220 // See crbug.com/130188 for initial discussion.
221 static const int kVerticalGap
= 60;
223 // Returns true if an output named |name| is an internal display.
224 static bool IsInternalOutputName(const std::string
& name
);
226 OutputConfigurator();
227 virtual ~OutputConfigurator();
229 OutputState
output_state() const { return output_state_
; }
230 DisplayPowerState
power_state() const { return power_state_
; }
232 void set_state_controller(StateController
* controller
) {
233 state_controller_
= controller
;
236 // Replaces |delegate_| with |delegate| and sets |configure_display_| to
237 // true. Should be called before Init().
238 void SetDelegateForTesting(scoped_ptr
<Delegate
> delegate
);
240 // Sets the initial value of |power_state_|. Must be called before Start().
241 void SetInitialDisplayPower(DisplayPowerState power_state
);
243 // Initialization, must be called right after constructor.
244 // |is_panel_fitting_enabled| indicates hardware panel fitting support.
245 // If |background_color_argb| is non zero and there are multiple displays,
246 // OutputConfigurator sets the background color of X's RootWindow to this
248 void Init(bool is_panel_fitting_enabled
, uint32 background_color_argb
);
250 // Detects displays first time from unknown state.
253 // Stop handling display configuration events/requests.
256 // Called when powerd notifies us that some set of displays should be turned
257 // on or off. This requires enabling or disabling the CRTC associated with
258 // the display(s) in question so that the low power state is engaged.
259 // |flags| contains bitwise-or-ed kSetDisplayPower* values.
260 bool SetDisplayPower(DisplayPowerState power_state
, int flags
);
262 // Force switching the display mode to |new_state|. Returns false if
263 // switching failed (possibly because |new_state| is invalid for the
264 // current set of connected outputs).
265 bool SetDisplayMode(OutputState new_state
);
267 // Called when an RRNotify event is received. The implementation is
268 // interested in the cases of RRNotify events which correspond to output
269 // add/remove events. Note that Output add/remove events are sent in response
270 // to our own reconfiguration operations so spurious events are common.
271 // Spurious events will have no effect.
272 virtual bool Dispatch(const base::NativeEvent
& event
) OVERRIDE
;
274 void AddObserver(Observer
* observer
);
275 void RemoveObserver(Observer
* observer
);
277 // Sets all the displays into pre-suspend mode; usually this means
278 // configure them for their resume state. This allows faster resume on
279 // machines where display configuration is slow.
280 void SuspendDisplays();
282 // Reprobes displays to handle changes made while the system was
284 void ResumeDisplays();
287 // Configure outputs.
288 void ConfigureOutputs();
290 // Fires OnDisplayModeChanged() event to the observers.
291 void NotifyOnDisplayChanged();
293 // Switches to the state specified in |output_state| and |power_state|.
294 // On success, updates |output_state_| and |power_state_| and returns true.
295 bool EnterState(OutputState output_state
,
296 DisplayPowerState power_state
,
297 const std::vector
<OutputSnapshot
>& outputs
);
299 // Returns the output state that should be used with |outputs| connected
300 // while in |power_state|.
301 OutputState
GetOutputState(const std::vector
<OutputSnapshot
>& outputs
,
302 DisplayPowerState power_state
) const;
304 // Computes the relevant transformation for mirror mode.
305 // |output| is the output on which mirror mode is being applied.
306 // Returns the transformation or identity if computations fail.
307 CoordinateTransformation
GetMirrorModeCTM(
308 const OutputConfigurator::OutputSnapshot
* output
);
310 StateController
* state_controller_
;
311 scoped_ptr
<Delegate
> delegate_
;
313 // This is detected by the constructor to determine whether or not we should
314 // be enabled. If we aren't running on ChromeOS, we can't assume that the
315 // Xrandr X11 extension is supported.
316 // If this flag is set to false, any attempts to change the output
317 // configuration to immediately fail without changing the state.
318 bool configure_display_
;
320 // The base of the event numbers used to represent XRandr events used in
321 // decoding events regarding output add/remove.
322 int xrandr_event_base_
;
324 // The current display state.
325 OutputState output_state_
;
327 // The current power state.
328 DisplayPowerState power_state_
;
330 ObserverList
<Observer
> observers_
;
332 // The timer to delay configuring outputs. See also the comments in
334 scoped_ptr
<base::OneShotTimer
<OutputConfigurator
> > configure_timer_
;
336 DISALLOW_COPY_AND_ASSIGN(OutputConfigurator
);
339 } // namespace chromeos
341 #endif // CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_