Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chromeos / display / output_configurator.h
blob34e9384e21b560704a40285a649d5648cab40352
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_
8 #include <vector>
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;
22 typedef XID RROutput;
23 typedef XID RRCrtc;
24 typedef XID RRMode;
26 namespace chromeos {
28 // Used to describe the state of a multi-display configuration.
29 enum OutputState {
30 STATE_INVALID,
31 STATE_HEADLESS,
32 STATE_SINGLE,
33 STATE_DUAL_MIRROR,
34 STATE_DUAL_EXTENDED,
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.
41 struct OutputInfo {
42 RROutput output;
43 int output_index;
46 // This class interacts directly with the underlying Xrandr API to manipulate
47 // CTRCs and Outputs.
48 class CHROMEOS_EXPORT OutputConfigurator : public MessageLoop::Dispatcher {
49 public:
50 // Information about an output's current state.
51 struct OutputSnapshot {
52 OutputSnapshot();
54 RROutput output;
56 // CRTC that should be used for this output. Not necessarily the CRTC
57 // that XRandR reports is currently being used.
58 RRCrtc crtc;
60 RRMode current_mode;
61 RRMode native_mode;
62 RRMode mirror_mode;
64 int y;
65 int height;
67 bool is_internal;
68 bool is_aspect_preserving_scaling;
70 // XInput device ID or 0 if this output isn't a touchscreen.
71 int touch_device_id;
74 struct CoordinateTransformation {
75 // Initialized to the identity transformation.
76 CoordinateTransformation();
78 float x_scale;
79 float x_offset;
80 float y_scale;
81 float y_offset;
84 struct CrtcConfig {
85 CrtcConfig();
86 CrtcConfig(RRCrtc crtc, int x, int y, RRMode mode, RROutput output);
88 RRCrtc crtc;
89 int x;
90 int y;
91 RRMode mode;
92 RROutput output;
95 class Observer {
96 public:
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
109 // should be used.
110 class StateController {
111 public:
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.
120 class Delegate {
121 public:
122 virtual ~Delegate() {}
124 virtual void SetPanelFittingEnabled(bool enabled) = 0;
126 // Initializes the XRandR extension, saving the base event ID to
127 // |event_base|.
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,
157 int* width,
158 int* height,
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(
168 int width,
169 int height,
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.
186 class TestApi {
187 public:
188 TestApi(OutputConfigurator* configurator, int xrandr_event_base)
189 : configurator_(configurator),
190 xrandr_event_base_(xrandr_event_base) {}
191 ~TestApi() {}
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);
198 private:
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
247 // color.
248 void Init(bool is_panel_fitting_enabled, uint32 background_color_argb);
250 // Detects displays first time from unknown state.
251 void Start();
253 // Stop handling display configuration events/requests.
254 void Stop();
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
283 // suspended.
284 void ResumeDisplays();
286 private:
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
333 // Dispatch().
334 scoped_ptr<base::OneShotTimer<OutputConfigurator> > configure_timer_;
336 DISALLOW_COPY_AND_ASSIGN(OutputConfigurator);
339 } // namespace chromeos
341 #endif // CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_