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. 4 5 #ifndef UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_ 6 #define UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_ 7 8 #include <stdint.h> 9 10 #include <map> 11 #include <string> 12 #include <vector> 13 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" 23 24 namespace gfx { 25 class Point; 26 class Size; 27 } 28 29 namespace ui { 30 class DisplayMode; 31 class DisplaySnapshot; 32 class NativeDisplayDelegate; 33 34 // This class interacts directly with the system display configurator. 35 class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver { 36 public: 37 typedef uint64_t ContentProtectionClientId; 38 static const ContentProtectionClientId kInvalidClientId = 0; 39 40 struct DisplayState { 41 DisplayState(); 42 43 DisplaySnapshot* display; // Not owned. 44 45 // XInput device ID or 0 if this display isn't a touchscreen. 46 int touch_device_id; 47 48 // User-selected mode for the display. 49 const DisplayMode* selected_mode; 50 51 // Mode used when displaying the same desktop on multiple displays. 52 const DisplayMode* mirror_mode; 53 }; 54 55 typedef std::vector<DisplayState> DisplayStateList; 56 57 class Observer { 58 public: ~Observer()59 virtual ~Observer() {} 60 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 64 // already. OnDisplayModeChanged(const std::vector<DisplayState> & displays)65 virtual void OnDisplayModeChanged( 66 const std::vector<DisplayState>& displays) {} 67 68 // Called after a display mode change attempt failed. |failed_new_state| is 69 // the new state which the system failed to enter. OnDisplayModeChangeFailed(MultipleDisplayState failed_new_state)70 virtual void OnDisplayModeChangeFailed( 71 MultipleDisplayState failed_new_state) {} 72 }; 73 74 // Interface for classes that make decisions about which display state 75 // should be used. 76 class StateController { 77 public: ~StateController()78 virtual ~StateController() {} 79 80 // Called when displays are detected. 81 virtual MultipleDisplayState GetStateForDisplayIds( 82 const std::vector<int64_t>& display_ids) const = 0; 83 84 // Queries the resolution (|size|) in pixels to select display mode for the 85 // given display id. 86 virtual bool GetResolutionForDisplayId(int64_t display_id, 87 gfx::Size* size) const = 0; 88 }; 89 90 // Interface for classes that implement software based mirroring. 91 class SoftwareMirroringController { 92 public: ~SoftwareMirroringController()93 virtual ~SoftwareMirroringController() {} 94 95 // Called when the hardware mirroring failed. 96 virtual void SetSoftwareMirroring(bool enabled) = 0; 97 virtual bool SoftwareMirroringEnabled() const = 0; 98 }; 99 100 class TouchscreenDelegate { 101 public: ~TouchscreenDelegate()102 virtual ~TouchscreenDelegate() {} 103 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; 110 }; 111 112 // Helper class used by tests. 113 class TestApi { 114 public: TestApi(DisplayConfigurator * configurator)115 TestApi(DisplayConfigurator* configurator) : configurator_(configurator) {} ~TestApi()116 ~TestApi() {} 117 118 // If |configure_timer_| is started, stops the timer, runs 119 // ConfigureDisplays(), and returns true; returns false otherwise. 120 bool TriggerConfigureTimeout(); 121 122 private: 123 DisplayConfigurator* configurator_; // not owned 124 125 DISALLOW_COPY_AND_ASSIGN(TestApi); 126 }; 127 128 // Flags that can be passed to SetDisplayPower(). 129 static const int kSetDisplayPowerNoFlags = 0; 130 // Configure displays even if the passed-in state matches |power_state_|. 131 static const int kSetDisplayPowerForceProbe = 1 << 0; 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 = 1 << 1; 135 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; 144 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); 150 151 DisplayConfigurator(); 152 virtual ~DisplayConfigurator(); 153 display_state()154 MultipleDisplayState display_state() const { return display_state_; } power_state()155 chromeos::DisplayPowerState power_state() const { return power_state_; } framebuffer_size()156 const gfx::Size framebuffer_size() const { return framebuffer_size_; } cached_displays()157 const std::vector<DisplayState>& cached_displays() const { 158 return cached_displays_; 159 } 160 set_state_controller(StateController * controller)161 void set_state_controller(StateController* controller) { 162 state_controller_ = controller; 163 } set_mirroring_controller(SoftwareMirroringController * controller)164 void set_mirroring_controller(SoftwareMirroringController* controller) { 165 mirroring_controller_ = controller; 166 } 167 168 // Replaces |native_display_delegate_| and |touchscreen_delegate_| with the 2 169 // delegates passed in and sets |configure_display_| to true. Should be called 170 // before Init(). 171 void SetDelegatesForTesting( 172 scoped_ptr<NativeDisplayDelegate> display_delegate, 173 scoped_ptr<TouchscreenDelegate> touchscreen_delegate); 174 175 // Sets the initial value of |power_state_|. Must be called before Start(). 176 void SetInitialDisplayPower(chromeos::DisplayPowerState power_state); 177 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); 181 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 185 // color. 186 void ForceInitialConfigure(uint32_t background_color_argb); 187 188 // Stop handling display configuration events/requests. 189 void PrepareForExit(); 190 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); 196 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); 201 202 // NativeDisplayDelegate::Observer overrides: 203 virtual void OnConfigurationChanged() OVERRIDE; 204 205 void AddObserver(Observer* observer); 206 void RemoveObserver(Observer* observer); 207 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(); 212 213 // Reprobes displays to handle changes made while the system was 214 // suspended. 215 void ResumeDisplays(); 216 GetMirroredDisplayAreaRatioMap()217 const std::map<int, float>& GetMirroredDisplayAreaRatioMap() { 218 return mirrored_display_area_ratio_map_; 219 } 220 221 // Registers a client for display protection and requests a client id. Returns 222 // 0 if requesting failed. 223 ContentProtectionClientId RegisterContentProtectionClient(); 224 225 // Unregisters the client. 226 void UnregisterContentProtectionClient(ContentProtectionClientId client_id); 227 228 // Queries link status and protection status. 229 // |link_mask| is the type of connected display links, which is a bitmask of 230 // DisplayConnectionType values. |protection_mask| is the desired protection 231 // methods, which is a bitmask of the ContentProtectionMethod values. 232 // Returns true on success. 233 bool QueryContentProtectionStatus(ContentProtectionClientId client_id, 234 int64_t display_id, 235 uint32_t* link_mask, 236 uint32_t* protection_mask); 237 238 // Requests the desired protection methods. 239 // |protection_mask| is the desired protection methods, which is a bitmask 240 // of the ContentProtectionMethod values. 241 // Returns true when the protection request has been made. 242 bool EnableContentProtection(ContentProtectionClientId client_id, 243 int64_t display_id, 244 uint32_t desired_protection_mask); 245 246 // Checks the available color profiles for |display_id| and fills the result 247 // into |profiles|. 248 std::vector<ui::ColorCalibrationProfile> GetAvailableColorCalibrationProfiles( 249 int64_t display_id); 250 251 // Updates the color calibration to |new_profile|. 252 bool SetColorCalibrationProfile(int64_t display_id, 253 ui::ColorCalibrationProfile new_profile); 254 255 private: 256 // Mapping a display_id to a protection request bitmask. 257 typedef std::map<int64_t, uint32_t> ContentProtections; 258 // Mapping a client to its protection request. 259 typedef std::map<ContentProtectionClientId, ContentProtections> 260 ProtectionRequests; 261 262 // If |native_display_delegate_| and |touchscreen_delegate_| are not set, then 263 // set them to the passed in values. 264 void InitializeDelegates( 265 scoped_ptr<NativeDisplayDelegate> display_delegate, 266 scoped_ptr<TouchscreenDelegate> touchscreen_delegate); 267 268 // Performs platform specific delegate initialization. 269 void PlatformInitialize(); 270 271 // Updates |cached_displays_| to contain currently-connected displays. Calls 272 // |delegate_->GetDisplays()| and then does additional work, like finding the 273 // mirror mode and setting user-preferred modes. Note that the server must be 274 // grabbed via |delegate_->GrabServer()| first. 275 void UpdateCachedDisplays(); 276 277 // Helper method for UpdateCachedDisplays() that initializes the passed-in 278 // displays' |mirror_mode| fields by looking for a mode in |internal_display| 279 // and |external_display| having the same resolution. Returns false if a 280 // shared 281 // mode wasn't found or created. 282 // 283 // |try_panel_fitting| allows creating a panel-fitting mode for 284 // |internal_display| instead of only searching for a matching mode (note that 285 // it may lead to a crash if |internal_info| is not capable of panel fitting). 286 // 287 // |preserve_aspect| limits the search/creation only to the modes having the 288 // native aspect ratio of |external_display|. 289 bool FindMirrorMode(DisplayState* internal_display, 290 DisplayState* external_display, 291 bool try_panel_fitting, 292 bool preserve_aspect); 293 294 // Configures displays. 295 void ConfigureDisplays(); 296 297 // Notifies observers about an attempted state change. 298 void NotifyObservers(bool success, MultipleDisplayState attempted_state); 299 300 // Switches to the state specified in |display_state| and |power_state|. 301 // If the hardware mirroring failed and |mirroring_controller_| is set, 302 // it switches to |STATE_DUAL_EXTENDED| and calls |SetSoftwareMirroring()| 303 // to enable software based mirroring. 304 // On success, updates |display_state_|, |power_state_|, and 305 // |cached_displays_| and returns true. 306 bool EnterStateOrFallBackToSoftwareMirroring( 307 MultipleDisplayState display_state, 308 chromeos::DisplayPowerState power_state); 309 310 // Switches to the state specified in |display_state| and |power_state|. 311 // On success, updates |display_state_|, |power_state_|, and 312 // |cached_displays_| and returns true. 313 bool EnterState(MultipleDisplayState display_state, 314 chromeos::DisplayPowerState power_state); 315 316 // Returns the display state that should be used with |cached_displays_| while 317 // in |power_state|. 318 MultipleDisplayState ChooseDisplayState( 319 chromeos::DisplayPowerState power_state) const; 320 321 // Returns the ratio between mirrored mode area and native mode area: 322 // (mirror_mode_width * mirrow_mode_height) / (native_width * native_height) 323 float GetMirroredDisplayAreaRatio(const DisplayState& display); 324 325 // Returns true if in either hardware or software mirroring mode. 326 bool IsMirroring() const; 327 328 // Applies display protections according to requests. 329 bool ApplyProtections(const ContentProtections& requests); 330 331 StateController* state_controller_; 332 SoftwareMirroringController* mirroring_controller_; 333 scoped_ptr<NativeDisplayDelegate> native_display_delegate_; 334 scoped_ptr<TouchscreenDelegate> touchscreen_delegate_; 335 336 // Used to enable modes which rely on panel fitting. 337 bool is_panel_fitting_enabled_; 338 339 // Key of the map is the touch display's id, and the value of the map is the 340 // touch display's area ratio in mirror mode defined as : 341 // mirror_mode_area / native_mode_area. 342 // This is used for scaling touch event's radius when the touch display is in 343 // mirror mode : 344 // new_touch_radius = sqrt(area_ratio) * old_touch_radius 345 std::map<int, float> mirrored_display_area_ratio_map_; 346 347 // This is detected by the constructor to determine whether or not we should 348 // be enabled. If we aren't running on ChromeOS, we can't assume that the 349 // Xrandr X11 extension is supported. 350 // If this flag is set to false, any attempts to change the display 351 // configuration to immediately fail without changing the state. 352 bool configure_display_; 353 354 // The current display state. 355 MultipleDisplayState display_state_; 356 357 gfx::Size framebuffer_size_; 358 359 // The current power state. 360 chromeos::DisplayPowerState power_state_; 361 362 // Most-recently-used display configuration. Note that the actual 363 // configuration changes asynchronously. 364 DisplayStateList cached_displays_; 365 366 ObserverList<Observer> observers_; 367 368 // The timer to delay configuring displays. See also the comments in 369 // Dispatch(). 370 scoped_ptr<base::OneShotTimer<DisplayConfigurator> > configure_timer_; 371 372 // Id for next display protection client. 373 ContentProtectionClientId next_display_protection_client_id_; 374 375 // Display protection requests of each client. 376 ProtectionRequests client_protection_requests_; 377 378 DISALLOW_COPY_AND_ASSIGN(DisplayConfigurator); 379 }; 380 381 } // namespace ui 382 383 #endif // UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_ 384