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. 4 5 #ifndef CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_ 6 #define CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/event_types.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/observer_list.h" 17 #include "base/timer/timer.h" 18 #include "chromeos/chromeos_export.h" 19 #include "third_party/cros_system_api/dbus/service_constants.h" 20 21 // Forward declarations for Xlib and Xrandr. 22 // This is so unused X definitions don't pollute the namespace. 23 typedef unsigned long XID; 24 typedef XID RROutput; 25 typedef XID RRCrtc; 26 typedef XID RRMode; 27 28 namespace chromeos { 29 30 // Used to describe the state of a multi-display configuration. 31 enum OutputState { 32 STATE_INVALID, 33 STATE_HEADLESS, 34 STATE_SINGLE, 35 STATE_DUAL_MIRROR, 36 STATE_DUAL_EXTENDED, 37 }; 38 39 // This class interacts directly with the underlying Xrandr API to manipulate 40 // CTRCs and Outputs. 41 class CHROMEOS_EXPORT OutputConfigurator 42 : public base::MessageLoop::Dispatcher, 43 public base::MessagePumpObserver { 44 public: 45 struct CoordinateTransformation { 46 // Initialized to the identity transformation. 47 CoordinateTransformation(); 48 49 float x_scale; 50 float x_offset; 51 float y_scale; 52 float y_offset; 53 }; 54 55 // Information about an output's current state. 56 struct OutputSnapshot { 57 OutputSnapshot(); 58 59 RROutput output; 60 61 // CRTC that should be used for this output. Not necessarily the CRTC 62 // that XRandR reports is currently being used. 63 RRCrtc crtc; 64 65 // Mode currently being used by the output. 66 RRMode current_mode; 67 68 // "Best" mode supported by the output. 69 RRMode native_mode; 70 71 // Mode used when displaying the same desktop on multiple outputs. 72 RRMode mirror_mode; 73 74 // User-selected mode for the output. 75 RRMode selected_mode; 76 77 // Output's origin on the framebuffer. 78 int x; 79 int y; 80 81 bool is_internal; 82 bool is_aspect_preserving_scaling; 83 84 // XInput device ID or 0 if this output isn't a touchscreen. 85 int touch_device_id; 86 87 CoordinateTransformation transform; 88 89 // Display id for this output. 90 int64 display_id; 91 92 bool has_display_id; 93 }; 94 95 class Observer { 96 public: 97 virtual ~Observer() {} 98 99 // Called when the change of the display mode finished. It will usually 100 // start the fading in the displays. 101 virtual void OnDisplayModeChanged() {} 102 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) {} 106 }; 107 108 // Interface for classes that make decisions about which output state 109 // should be used. 110 class StateController { 111 public: 112 virtual ~StateController() {} 113 114 // Called when displays are detected. 115 virtual OutputState GetStateForDisplayIds( 116 const std::vector<int64>& display_ids) const = 0; 117 118 // Queries the resolution (|width|x|height|) in pixels 119 // to select output mode for the given display id. 120 virtual bool GetResolutionForDisplayId(int64 display_id, 121 int* width, 122 int* height) const = 0; 123 }; 124 125 // Interface for classes that implement software based mirroring. 126 class SoftwareMirroringController { 127 public: 128 virtual ~SoftwareMirroringController() {} 129 130 // Called when the hardware mirroring failed. 131 virtual void SetSoftwareMirroring(bool enabled) = 0; 132 }; 133 134 // Interface for classes that perform actions on behalf of OutputController. 135 class Delegate { 136 public: 137 virtual ~Delegate() {} 138 139 virtual void SetPanelFittingEnabled(bool enabled) = 0; 140 141 // Initializes the XRandR extension, saving the base event ID to 142 // |event_base|. 143 virtual void InitXRandRExtension(int* event_base) = 0; 144 145 // Tells XRandR to update its configuration in response to |event|, an 146 // RRScreenChangeNotify event. 147 virtual void UpdateXRandRConfiguration(const base::NativeEvent& event) = 0; 148 149 // Grabs the X server and refreshes XRandR-related resources. While 150 // the server is grabbed, other clients are blocked. Must be balanced 151 // by a call to UngrabServer(). 152 virtual void GrabServer() = 0; 153 154 // Ungrabs the server and frees XRandR-related resources. 155 virtual void UngrabServer() = 0; 156 157 // Flushes all pending requests and waits for replies. 158 virtual void SyncWithServer() = 0; 159 160 // Sets the window's background color to |color_argb|. 161 virtual void SetBackgroundColor(uint32 color_argb) = 0; 162 163 // Enables DPMS and forces it to the "on" state. 164 virtual void ForceDPMSOn() = 0; 165 166 // Returns information about the current outputs. 167 // This method may block for 60 milliseconds or more. 168 virtual std::vector<OutputSnapshot> GetOutputs( 169 const StateController* state_controller) = 0; 170 171 // Gets details corresponding to |mode|. Parameters may be NULL. 172 // Returns true on success. 173 virtual bool GetModeDetails(RRMode mode, 174 int* width, 175 int* height, 176 bool* interlaced) = 0; 177 178 // Calls XRRSetCrtcConfig() with the given options but some of our default 179 // output count and rotation arguments. Returns true on success. 180 virtual bool ConfigureCrtc(RRCrtc crtc, 181 RRMode mode, 182 RROutput output, 183 int x, 184 int y) = 0; 185 186 // Called to set the frame buffer (underlying XRR "screen") size. Has 187 // a side-effect of disabling all CRTCs. 188 virtual void CreateFrameBuffer( 189 int width, 190 int height, 191 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) = 0; 192 193 // Configures XInput's Coordinate Transformation Matrix property. 194 // |touch_device_id| the ID of the touchscreen device to configure. 195 // |ctm| contains the desired transformation parameters. The offsets 196 // in it should be normalized so that 1 corresponds to the X or Y axis 197 // size for the corresponding offset. 198 virtual void ConfigureCTM(int touch_device_id, 199 const CoordinateTransformation& ctm) = 0; 200 201 // Sends a D-Bus message to the power manager telling it that the 202 // machine is or is not projecting. 203 virtual void SendProjectingStateToPowerManager(bool projecting) = 0; 204 }; 205 206 // Helper class used by tests. 207 class TestApi { 208 public: 209 TestApi(OutputConfigurator* configurator, int xrandr_event_base) 210 : configurator_(configurator), 211 xrandr_event_base_(xrandr_event_base) {} 212 ~TestApi() {} 213 214 // Dispatches RRScreenChangeNotify and RRNotify_OutputChange events to 215 // |configurator_| and runs ConfigureOutputs(). Returns false if 216 // |configure_timer_| wasn't started. 217 bool SendOutputChangeEvents(bool connected); 218 219 private: 220 OutputConfigurator* configurator_; // not owned 221 222 int xrandr_event_base_; 223 224 DISALLOW_COPY_AND_ASSIGN(TestApi); 225 }; 226 227 // Flags that can be passed to SetDisplayPower(). 228 static const int kSetDisplayPowerNoFlags = 0; 229 // Configure displays even if the passed-in state matches |power_state_|. 230 static const int kSetDisplayPowerForceProbe = 1 << 0; 231 // Do not change the state if multiple displays are connected or if the 232 // only connected display is external. 233 static const int kSetDisplayPowerOnlyIfSingleInternalDisplay = 1 << 1; 234 235 // Gap between screens so cursor at bottom of active display doesn't 236 // partially appear on top of inactive display. Higher numbers guard 237 // against larger cursors, but also waste more memory. 238 // For simplicity, this is hard-coded to avoid the complexity of always 239 // determining the DPI of the screen and rationalizing which screen we 240 // need to use for the DPI calculation. 241 // See crbug.com/130188 for initial discussion. 242 static const int kVerticalGap = 60; 243 244 OutputConfigurator(); 245 virtual ~OutputConfigurator(); 246 247 OutputState output_state() const { return output_state_; } 248 DisplayPowerState power_state() const { return power_state_; } 249 250 void set_state_controller(StateController* controller) { 251 state_controller_ = controller; 252 } 253 void set_mirroring_controller(SoftwareMirroringController* controller) { 254 mirroring_controller_ = controller; 255 } 256 257 // Replaces |delegate_| with |delegate| and sets |configure_display_| to 258 // true. Should be called before Init(). 259 void SetDelegateForTesting(scoped_ptr<Delegate> delegate); 260 261 // Sets the initial value of |power_state_|. Must be called before Start(). 262 void SetInitialDisplayPower(DisplayPowerState power_state); 263 264 // Initialization, must be called right after constructor. 265 // |is_panel_fitting_enabled| indicates hardware panel fitting support. 266 void Init(bool is_panel_fitting_enabled); 267 268 // Does initial configuration of displays during startup. 269 // If |background_color_argb| is non zero and there are multiple displays, 270 // OutputConfigurator sets the background color of X's RootWindow to this 271 // color. 272 void Start(uint32 background_color_argb); 273 274 // Stop handling display configuration events/requests. 275 void Stop(); 276 277 // Called when powerd notifies us that some set of displays should be turned 278 // on or off. This requires enabling or disabling the CRTC associated with 279 // the display(s) in question so that the low power state is engaged. 280 // |flags| contains bitwise-or-ed kSetDisplayPower* values. 281 bool SetDisplayPower(DisplayPowerState power_state, int flags); 282 283 // Force switching the display mode to |new_state|. Returns false if 284 // switching failed (possibly because |new_state| is invalid for the 285 // current set of connected outputs). 286 bool SetDisplayMode(OutputState new_state); 287 288 // Called when an RRNotify event is received. The implementation is 289 // interested in the cases of RRNotify events which correspond to output 290 // add/remove events. Note that Output add/remove events are sent in response 291 // to our own reconfiguration operations so spurious events are common. 292 // Spurious events will have no effect. 293 virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; 294 295 // Overridden from base::MessagePumpObserver: 296 virtual base::EventStatus WillProcessEvent( 297 const base::NativeEvent& event) OVERRIDE; 298 virtual void DidProcessEvent( 299 const base::NativeEvent& event) OVERRIDE; 300 301 void AddObserver(Observer* observer); 302 void RemoveObserver(Observer* observer); 303 304 // Sets all the displays into pre-suspend mode; usually this means 305 // configure them for their resume state. This allows faster resume on 306 // machines where display configuration is slow. 307 void SuspendDisplays(); 308 309 // Reprobes displays to handle changes made while the system was 310 // suspended. 311 void ResumeDisplays(); 312 313 const std::map<int, float>& GetMirroredDisplayAreaRatioMap() { 314 return mirrored_display_area_ratio_map_; 315 } 316 317 // Configure outputs with |kConfigureDelayMs| delay, 318 // so that time-consuming ConfigureOutputs() won't be called multiple times. 319 void ScheduleConfigureOutputs(); 320 321 private: 322 // Configure outputs. 323 void ConfigureOutputs(); 324 325 // Fires OnDisplayModeChanged() event to the observers. 326 void NotifyOnDisplayChanged(); 327 328 // Switches to the state specified in |output_state| and |power_state|. 329 // If the hardware mirroring failed and |mirroring_controller_| is set, 330 // it switches to |STATE_DUAL_EXTENDED| and calls |SetSoftwareMirroring()| 331 // to enable software based mirroring. 332 // On success, updates |output_state_|, |power_state_|, and |cached_outputs_| 333 // and returns true. 334 bool EnterStateOrFallBackToSoftwareMirroring( 335 OutputState output_state, 336 DisplayPowerState power_state, 337 const std::vector<OutputSnapshot>& outputs); 338 339 // Switches to the state specified in |output_state| and |power_state|. 340 // On success, updates |output_state_|, |power_state_|, and 341 // |cached_outputs_| and returns true. 342 bool EnterState(OutputState output_state, 343 DisplayPowerState power_state, 344 const std::vector<OutputSnapshot>& outputs); 345 346 // Returns the output state that should be used with |outputs| connected 347 // while in |power_state|. 348 OutputState GetOutputState(const std::vector<OutputSnapshot>& outputs, 349 DisplayPowerState power_state) const; 350 351 // Computes the relevant transformation for mirror mode. 352 // |output| is the output on which mirror mode is being applied. 353 // Returns the transformation or identity if computations fail. 354 CoordinateTransformation GetMirrorModeCTM( 355 const OutputConfigurator::OutputSnapshot* output); 356 357 // Returns the ratio between mirrored mode area and native mode area: 358 // (mirror_mode_width * mirrow_mode_height) / (native_width * native_height) 359 float GetMirroredDisplayAreaRatio( 360 const OutputConfigurator::OutputSnapshot* output); 361 362 StateController* state_controller_; 363 SoftwareMirroringController* mirroring_controller_; 364 scoped_ptr<Delegate> delegate_; 365 366 // Key of the map is the touch display's id, and the value of the map is the 367 // touch display's area ratio in mirror mode defined as : 368 // mirror_mode_area / native_mode_area. 369 // This is used for scaling touch event's radius when the touch display is in 370 // mirror mode : 371 // new_touch_radius = sqrt(area_ratio) * old_touch_radius 372 std::map<int, float> mirrored_display_area_ratio_map_; 373 374 // This is detected by the constructor to determine whether or not we should 375 // be enabled. If we aren't running on ChromeOS, we can't assume that the 376 // Xrandr X11 extension is supported. 377 // If this flag is set to false, any attempts to change the output 378 // configuration to immediately fail without changing the state. 379 bool configure_display_; 380 381 // The base of the event numbers used to represent XRandr events used in 382 // decoding events regarding output add/remove. 383 int xrandr_event_base_; 384 385 // The current display state. 386 OutputState output_state_; 387 388 // The current power state. 389 DisplayPowerState power_state_; 390 391 // Most-recently-used output configuration. Note that the actual 392 // configuration changes asynchronously. 393 std::vector<OutputSnapshot> cached_outputs_; 394 395 ObserverList<Observer> observers_; 396 397 // The timer to delay configuring outputs. See also the comments in 398 // Dispatch(). 399 scoped_ptr<base::OneShotTimer<OutputConfigurator> > configure_timer_; 400 401 DISALLOW_COPY_AND_ASSIGN(OutputConfigurator); 402 }; 403 404 typedef std::vector<OutputConfigurator::OutputSnapshot> OutputSnapshotList; 405 406 } // namespace chromeos 407 408 #endif // CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_ 409