Index: chromeos/display/output_configurator.cc |
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc |
index f9565853360723d7999eaf10da41b4f211aed4a5..d4d7708c4c955fad0f63e5e2b670d23f150e0189 100644 |
--- a/chromeos/display/output_configurator.cc |
+++ b/chromeos/display/output_configurator.cc |
@@ -222,6 +222,207 @@ static float ComputeDeviceScaleFactor(unsigned int width, |
} // namespace |
+OutputConfigurator::OutputConfigurator() |
+ : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()), |
+ output_count_(0), |
+ output_cache_(NULL), |
+ mirror_supported_(false), |
+ primary_output_index_(-1), |
+ secondary_output_index_(-1), |
+ xrandr_event_base_(0), |
+ output_state_(STATE_INVALID) { |
+ if (!is_running_on_chrome_os_) |
+ return; |
+ // Send the signal to powerd to tell it that we will take over output |
+ // control. |
+ // Note that this can be removed once the legacy powerd support is removed. |
+ chromeos::DBusThreadManager* manager = chromeos::DBusThreadManager::Get(); |
+ dbus::Bus* bus = manager->GetSystemBus(); |
+ dbus::ExportedObject* remote_object = bus->GetExportedObject( |
+ dbus::ObjectPath(power_manager::kPowerManagerServicePath)); |
+ dbus::Signal signal(power_manager::kPowerManagerInterface, |
+ power_manager::kUseNewMonitorConfigSignal); |
+ CHECK(signal.raw_message() != NULL); |
+ remote_object->SendSignal(&signal); |
+ |
+ // Cache the initial output state. |
+ Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
+ CHECK(display != NULL); |
+ XGrabServer(display); |
+ Window window = DefaultRootWindow(display); |
+ XRRScreenResources* screen = XRRGetScreenResources(display, window); |
+ CHECK(screen != NULL); |
+ bool did_detect_outputs = TryRecacheOutputs(display, screen); |
+ CHECK(did_detect_outputs); |
+ OutputState current_state = InferCurrentState(display, screen); |
+ if (current_state == STATE_INVALID) { |
+ // Unknown state. Transition into the default state. |
+ OutputState state = GetDefaultState(); |
+ UpdateCacheAndXrandrToState(display, screen, window, state); |
+ } else { |
+ // This is a valid state so just save it to |output_state_|. |
+ output_state_ = current_state; |
+ } |
+ // Find xrandr_event_base_ since we need it to interpret events, later. |
+ int error_base_ignored = 0; |
+ XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored); |
+ // Relinquish X resources. |
+ XRRFreeScreenResources(screen); |
+ XUngrabServer(display); |
+ CheckIsProjectingAndNotify(); |
+} |
+ |
+OutputConfigurator::~OutputConfigurator() { |
+} |
+ |
+bool OutputConfigurator::CycleDisplayMode(bool extended_desktop_enabled) { |
+ VLOG(1) << "CycleDisplayMode"; |
+ if (!is_running_on_chrome_os_) |
+ return false; |
+ |
+ bool did_change = false; |
+ // Rules: |
+ // - if there are 0 or 1 displays, do nothing and return false. |
+ // - use y-coord of CRTCs to determine if we are mirror, primary-first, or |
+ // secondary-first. The cycle order is: |
+ // mirror->primary->secondary->mirror. |
+ // Note: If the extended desktop is enabled, the cycle order becomes, |
+ // mirror->extended->mirror |
+ OutputState new_state = STATE_INVALID; |
+ switch (output_state_) { |
+ case STATE_DUAL_MIRROR: |
+ new_state = STATE_DUAL_PRIMARY_ONLY; |
+ break; |
+ case STATE_DUAL_PRIMARY_ONLY: |
+ if (extended_desktop_enabled) { |
+ if (mirror_supported_) |
+ new_state = STATE_DUAL_MIRROR; |
+ else |
+ new_state = STATE_INVALID; |
+ } else { |
+ new_state = STATE_DUAL_SECONDARY_ONLY; |
+ } |
+ break; |
+ case STATE_DUAL_SECONDARY_ONLY: |
+ new_state = mirror_supported_ ? |
+ STATE_DUAL_MIRROR : |
+ STATE_DUAL_PRIMARY_ONLY; |
+ break; |
+ default: |
+ // Do nothing - we aren't in a mode which we can rotate. |
+ break; |
+ } |
+ if (STATE_INVALID != new_state) |
+ did_change = SetDisplayMode(new_state); |
+ |
+ return did_change; |
+} |
+ |
+bool OutputConfigurator::ScreenPowerSet(bool power_on, bool all_displays) { |
+ VLOG(1) << "OutputConfigurator::SetScreensOn " << power_on |
+ << " all displays " << all_displays; |
+ if (!is_running_on_chrome_os_) |
+ return false; |
+ |
+ bool success = false; |
+ Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
+ CHECK(display != NULL); |
+ XGrabServer(display); |
+ Window window = DefaultRootWindow(display); |
+ XRRScreenResources* screen = XRRGetScreenResources(display, window); |
+ CHECK(screen != NULL); |
+ |
+ // Set the CRTCs based on whether we want to turn the power on or off and |
+ // select the outputs to operate on by name or all_displays. |
+ for (int i = 0; i < output_count_; ++i) { |
+ if (all_displays || output_cache_[i].is_internal) { |
+ const int x = output_cache_[i].x; |
+ const int y = output_cache_[i].y; |
+ RROutput output = output_cache_[i].output; |
+ RRCrtc crtc = output_cache_[i].crtc; |
+ RRMode mode = None; |
+ if (power_on) { |
+ mode = (STATE_DUAL_MIRROR == output_state_) ? |
+ output_cache_[i].mirror_mode : |
+ output_cache_[i].ideal_mode; |
+ } |
+ |
+ VLOG(1) << "SET POWER crtc: " << crtc |
+ << ", mode " << mode |
+ << ", output " << output |
+ << ", x " << x |
+ << ", y " << y; |
+ // The values we are setting are already from the cache so no update |
+ // required. |
+ ConfigureCrtc(display, |
+ screen, |
+ crtc, |
+ x, |
+ y, |
+ mode, |
+ output); |
+ output_cache_[i].is_powered_on = power_on; |
+ success = true; |
+ } |
+ } |
+ |
+ // Force the DPMS on since the driver doesn't always detect that it should |
+ // turn on. |
+ if (power_on) { |
+ CHECK(DPMSEnable(display)); |
+ CHECK(DPMSForceLevel(display, DPMSModeOn)); |
+ } |
+ |
+ XRRFreeScreenResources(screen); |
+ XUngrabServer(display); |
+ |
+ return success; |
+} |
+ |
+bool OutputConfigurator::SetDisplayMode(OutputState new_state) { |
+ if (output_state_ == STATE_INVALID || |
+ output_state_ == STATE_HEADLESS || |
+ output_state_ == STATE_SINGLE) |
+ return false; |
+ |
+ Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
+ CHECK(display != NULL); |
+ XGrabServer(display); |
+ Window window = DefaultRootWindow(display); |
+ XRRScreenResources* screen = XRRGetScreenResources(display, window); |
+ CHECK(screen != NULL); |
+ |
+ UpdateCacheAndXrandrToState(display, |
+ screen, |
+ window, |
+ new_state); |
+ XRRFreeScreenResources(screen); |
+ XUngrabServer(display); |
+ return true; |
+} |
+ |
+bool OutputConfigurator::Dispatch(const base::NativeEvent& event) { |
+ // Ignore this event if the Xrandr extension isn't supported. |
+ if (!is_running_on_chrome_os_ || |
+ (event->type - xrandr_event_base_ != RRNotify)) { |
+ return true; |
+ } |
+ XEvent* xevent = static_cast<XEvent*>(event); |
+ XRRNotifyEvent* notify_event = |
+ reinterpret_cast<XRRNotifyEvent*>(xevent); |
+ if (notify_event->subtype == RRNotify_OutputChange) { |
+ XRROutputChangeNotifyEvent* output_change_event = |
+ reinterpret_cast<XRROutputChangeNotifyEvent*>(xevent); |
+ if ((output_change_event->connection == RR_Connected) || |
+ (output_change_event->connection == RR_Disconnected)) { |
+ RecacheAndUseDefaultState(); |
+ CheckIsProjectingAndNotify(); |
+ } |
+ // Ignore the case of RR_UnkownConnection. |
+ } |
+ return true; |
+} |
+ |
bool OutputConfigurator::TryRecacheOutputs(Display* display, |
XRRScreenResources* screen) { |
bool outputs_did_change = false; |
@@ -247,174 +448,121 @@ bool OutputConfigurator::TryRecacheOutputs(Display* display, |
} |
} |
- if (outputs_did_change) { |
- // We now know that we need to recache so free and re-alloc the buffer. |
- output_count_ = screen->noutput; |
- if (output_count_ == 0) { |
- output_cache_.reset(NULL); |
- } else { |
- // Ideally, this would be allocated inline in the OutputConfigurator |
- // instance since we support at most 2 connected outputs but this dynamic |
- // allocation was specifically requested. |
- output_cache_.reset(new CachedOutputDescription[output_count_]); |
- } |
+ if (!outputs_did_change) |
+ return false; |
+ // We now know that we need to recache so free and re-alloc the buffer. |
+ output_count_ = screen->noutput; |
+ if (output_count_ == 0) { |
+ output_cache_.reset(NULL); |
+ } else { |
+ // Ideally, this would be allocated inline in the OutputConfigurator |
+ // instance since we support at most 2 connected outputs but this dynamic |
+ // allocation was specifically requested. |
+ output_cache_.reset(new CachedOutputDescription[output_count_]); |
+ } |
- // TODO: This approach to finding CRTCs only supports two. Expand on this. |
- RRCrtc used_crtc = None; |
- primary_output_index_ = -1; |
- secondary_output_index_ = -1; |
- |
- for (int i = 0; i < output_count_; ++i) { |
- RROutput this_id = screen->outputs[i]; |
- XRROutputInfo* output = XRRGetOutputInfo(display, screen, this_id); |
- bool is_connected = (RR_Connected == output->connection); |
- RRCrtc crtc = None; |
- RRMode ideal_mode = None; |
- int x = 0; |
- int y = 0; |
- unsigned long mm_width = output->mm_width; |
- unsigned long mm_height = output->mm_height; |
- bool is_internal = false; |
- |
- if (is_connected) { |
- for (int j = 0; (j < output->ncrtc) && (None == crtc); ++j) { |
- RRCrtc possible = output->crtcs[j]; |
- if (possible != used_crtc) { |
- crtc = possible; |
- used_crtc = possible; |
- } |
- } |
+ // TODO: This approach to finding CRTCs only supports two. Expand on this. |
+ RRCrtc used_crtc = None; |
+ primary_output_index_ = -1; |
+ secondary_output_index_ = -1; |
- const char* name = output->name; |
- is_internal = |
- (strncmp(kInternal_LVDS, |
- name, |
- arraysize(kInternal_LVDS) - 1) == 0) || |
- (strncmp(kInternal_eDP, |
- name, |
- arraysize(kInternal_eDP) - 1) == 0); |
- if (output->nmode > 0) |
- ideal_mode = output->modes[0]; |
- |
- if (crtc != None) { |
- XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screen, crtc); |
- x = crtcInfo->x; |
- y = crtcInfo->y; |
- XRRFreeCrtcInfo(crtcInfo); |
+ for (int i = 0; i < output_count_; ++i) { |
+ RROutput this_id = screen->outputs[i]; |
+ XRROutputInfo* output = XRRGetOutputInfo(display, screen, this_id); |
+ bool is_connected = (RR_Connected == output->connection); |
+ RRCrtc crtc = None; |
+ RRMode ideal_mode = None; |
+ int x = 0; |
+ int y = 0; |
+ unsigned long mm_width = output->mm_width; |
+ unsigned long mm_height = output->mm_height; |
+ bool is_internal = false; |
+ |
+ if (is_connected) { |
+ for (int j = 0; (j < output->ncrtc) && (None == crtc); ++j) { |
+ RRCrtc possible = output->crtcs[j]; |
+ if (possible != used_crtc) { |
+ crtc = possible; |
+ used_crtc = possible; |
} |
- |
- // Save this for later mirror mode detection. |
- if (primary_output_index_ == -1) |
- primary_output_index_ = i; |
- else if (secondary_output_index_ == -1) |
- secondary_output_index_ = i; |
} |
- XRRFreeOutputInfo(output); |
- |
- // Now save the cached state for this output (we will default to mirror |
- // disabled and detect that after we have identified the first two |
- // connected outputs). |
- VLOG(1) << "Recache output index: " << i |
- << ", output id: " << this_id |
- << ", crtc id: " << crtc |
- << ", ideal mode id: " << ideal_mode |
- << ", x: " << x |
- << ", y: " << y |
- << ", is connected: " << is_connected |
- << ", is_internal: " << is_internal |
- << ", mm_width: " << mm_width |
- << ", mm_height: " << mm_height; |
- output_cache_[i].output = this_id; |
- output_cache_[i].crtc = crtc; |
- output_cache_[i].mirror_mode = None; |
- output_cache_[i].ideal_mode = ideal_mode; |
- output_cache_[i].x = x; |
- output_cache_[i].y = y; |
- output_cache_[i].is_connected = is_connected; |
- output_cache_[i].is_powered_on = true; |
- output_cache_[i].is_internal = is_internal; |
- output_cache_[i].mm_width = mm_width; |
- output_cache_[i].mm_height = mm_height; |
- } |
- // Now, detect the mirror modes if we have two connected outputs. |
- if ((primary_output_index_ != -1) && (secondary_output_index_ != -1)) { |
- mirror_supported_ = FindMirrorModeForOutputs( |
- display, |
- screen, |
- output_cache_[primary_output_index_].output, |
- output_cache_[secondary_output_index_].output, |
- &output_cache_[primary_output_index_].mirror_mode, |
- &output_cache_[secondary_output_index_].mirror_mode); |
+ const char* name = output->name; |
+ is_internal = |
+ (strncmp(kInternal_LVDS, |
+ name, |
+ arraysize(kInternal_LVDS) - 1) == 0) || |
+ (strncmp(kInternal_eDP, |
+ name, |
+ arraysize(kInternal_eDP) - 1) == 0); |
+ if (output->nmode > 0) |
+ ideal_mode = output->modes[0]; |
+ |
+ if (crtc != None) { |
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screen, crtc); |
+ x = crtcInfo->x; |
+ y = crtcInfo->y; |
+ XRRFreeCrtcInfo(crtcInfo); |
+ } |
- RRMode primary_mode = output_cache_[primary_output_index_].mirror_mode; |
- RRMode second_mode = output_cache_[secondary_output_index_].mirror_mode; |
- VLOG(1) << "Mirror mode supported " << mirror_supported_ |
- << " primary " << primary_mode |
- << " secondary " << second_mode; |
+ // Save this for later mirror mode detection. |
+ if (primary_output_index_ == -1) |
+ primary_output_index_ = i; |
+ else if (secondary_output_index_ == -1) |
+ secondary_output_index_ = i; |
} |
+ XRRFreeOutputInfo(output); |
+ |
+ // Now save the cached state for this output (we will default to mirror |
+ // disabled and detect that after we have identified the first two |
+ // connected outputs). |
+ VLOG(1) << "Recache output index: " << i |
+ << ", output id: " << this_id |
+ << ", crtc id: " << crtc |
+ << ", ideal mode id: " << ideal_mode |
+ << ", x: " << x |
+ << ", y: " << y |
+ << ", is connected: " << is_connected |
+ << ", is_internal: " << is_internal |
+ << ", mm_width: " << mm_width |
+ << ", mm_height: " << mm_height; |
+ output_cache_[i].output = this_id; |
+ output_cache_[i].crtc = crtc; |
+ output_cache_[i].mirror_mode = None; |
+ output_cache_[i].ideal_mode = ideal_mode; |
+ output_cache_[i].x = x; |
+ output_cache_[i].y = y; |
+ output_cache_[i].is_connected = is_connected; |
+ output_cache_[i].is_powered_on = true; |
+ output_cache_[i].is_internal = is_internal; |
+ output_cache_[i].mm_width = mm_width; |
+ output_cache_[i].mm_height = mm_height; |
} |
- return outputs_did_change; |
-} |
-OutputConfigurator::OutputConfigurator() |
- : is_running_on_chrome_os_(base::chromeos::IsRunningOnChromeOS()), |
- output_count_(0), |
- output_cache_(NULL), |
- mirror_supported_(false), |
- primary_output_index_(-1), |
- secondary_output_index_(-1), |
- xrandr_event_base_(0), |
- output_state_(STATE_INVALID) { |
- if (is_running_on_chrome_os_) { |
- // Send the signal to powerd to tell it that we will take over output |
- // control. |
- // Note that this can be removed once the legacy powerd support is removed. |
- chromeos::DBusThreadManager* manager = chromeos::DBusThreadManager::Get(); |
- dbus::Bus* bus = manager->GetSystemBus(); |
- dbus::ExportedObject* remote_object = bus->GetExportedObject( |
- dbus::ObjectPath(power_manager::kPowerManagerServicePath)); |
- dbus::Signal signal(power_manager::kPowerManagerInterface, |
- power_manager::kUseNewMonitorConfigSignal); |
- CHECK(signal.raw_message() != NULL); |
- remote_object->SendSignal(&signal); |
- |
- // Cache the initial output state. |
- Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
- CHECK(display != NULL); |
- XGrabServer(display); |
- Window window = DefaultRootWindow(display); |
- XRRScreenResources* screen = XRRGetScreenResources(display, window); |
- CHECK(screen != NULL); |
- bool did_detect_outputs = TryRecacheOutputs(display, screen); |
- CHECK(did_detect_outputs); |
- State current_state = InferCurrentState(display, screen); |
- if (current_state == STATE_INVALID) { |
- // Unknown state. Transition into the default state. |
- State state = GetDefaultState(); |
- UpdateCacheAndXrandrToState(display, screen, window, state); |
- } else { |
- // This is a valid state so just save it to |output_state_|. |
- output_state_ = current_state; |
- } |
- // Find xrandr_event_base_ since we need it to interpret events, later. |
- int error_base_ignored = 0; |
- XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored); |
- // Relinquish X resources. |
- XRRFreeScreenResources(screen); |
- XUngrabServer(display); |
- CheckIsProjectingAndNotify(); |
+ // Now, detect the mirror modes if we have two connected outputs. |
+ if ((primary_output_index_ != -1) && (secondary_output_index_ != -1)) { |
+ mirror_supported_ = FindMirrorModeForOutputs( |
+ display, |
+ screen, |
+ output_cache_[primary_output_index_].output, |
+ output_cache_[secondary_output_index_].output, |
+ &output_cache_[primary_output_index_].mirror_mode, |
+ &output_cache_[secondary_output_index_].mirror_mode); |
+ |
+ RRMode primary_mode = output_cache_[primary_output_index_].mirror_mode; |
+ RRMode second_mode = output_cache_[secondary_output_index_].mirror_mode; |
+ VLOG(1) << "Mirror mode supported " << mirror_supported_ |
+ << " primary " << primary_mode |
+ << " secondary " << second_mode; |
} |
-} |
- |
-OutputConfigurator::~OutputConfigurator() { |
+ return outputs_did_change; |
} |
void OutputConfigurator::UpdateCacheAndXrandrToState( |
Display* display, |
XRRScreenResources* screen, |
Window window, |
- State new_state) { |
+ OutputState new_state) { |
// Default rules: |
// - single display = rebuild framebuffer and set to ideal_mode. |
// - multi display = rebuild framebuffer and set to mirror_mode. |
@@ -562,7 +710,7 @@ bool OutputConfigurator::RecacheAndUseDefaultState() { |
bool did_detect_change = TryRecacheOutputs(display, screen); |
if (did_detect_change) { |
- State state = GetDefaultState(); |
+ OutputState state = GetDefaultState(); |
UpdateCacheAndXrandrToState(display, screen, window, state); |
} |
XRRFreeScreenResources(screen); |
@@ -570,8 +718,8 @@ bool OutputConfigurator::RecacheAndUseDefaultState() { |
return did_detect_change; |
} |
-State OutputConfigurator::GetDefaultState() const { |
- State state = STATE_HEADLESS; |
+OutputState OutputConfigurator::GetDefaultState() const { |
+ OutputState state = STATE_HEADLESS; |
if (-1 != primary_output_index_) { |
if (-1 != secondary_output_index_) |
state = mirror_supported_ ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY; |
@@ -581,10 +729,10 @@ State OutputConfigurator::GetDefaultState() const { |
return state; |
} |
-State OutputConfigurator::InferCurrentState(Display* display, |
- XRRScreenResources* screen) const { |
+OutputState OutputConfigurator::InferCurrentState( |
+ Display* display, XRRScreenResources* screen) const { |
// STATE_INVALID will be our default or "unknown" state. |
- State state = STATE_INVALID; |
+ OutputState state = STATE_INVALID; |
// First step: count the number of connected outputs. |
if (secondary_output_index_ == -1) { |
// No secondary display. |
@@ -659,150 +807,6 @@ State OutputConfigurator::InferCurrentState(Display* display, |
return state; |
} |
-bool OutputConfigurator::CycleDisplayMode(bool extended_desktop_enabled) { |
- VLOG(1) << "CycleDisplayMode"; |
- bool did_change = false; |
- |
- if (is_running_on_chrome_os_) { |
- // Rules: |
- // - if there are 0 or 1 displays, do nothing and return false. |
- // - use y-coord of CRTCs to determine if we are mirror, primary-first, or |
- // secondary-first. The cycle order is: |
- // mirror->primary->secondary->mirror. |
- // Note: If the extended desktop is enabled, the cycle order becomes, |
- // mirror->extended->mirror |
- State new_state = STATE_INVALID; |
- switch (output_state_) { |
- case STATE_DUAL_MIRROR: |
- new_state = STATE_DUAL_PRIMARY_ONLY; |
- break; |
- case STATE_DUAL_PRIMARY_ONLY: |
- if (extended_desktop_enabled) { |
- if (mirror_supported_) |
- new_state = STATE_DUAL_MIRROR; |
- else |
- new_state = STATE_INVALID; |
- } else { |
- new_state = STATE_DUAL_SECONDARY_ONLY; |
- } |
- break; |
- case STATE_DUAL_SECONDARY_ONLY: |
- new_state = mirror_supported_ ? |
- STATE_DUAL_MIRROR : |
- STATE_DUAL_PRIMARY_ONLY; |
- break; |
- default: |
- // Do nothing - we aren't in a mode which we can rotate. |
- break; |
- } |
- if (STATE_INVALID != new_state) |
- did_change = SetDisplayMode(new_state); |
- } |
- return did_change; |
-} |
- |
-bool OutputConfigurator::ScreenPowerSet(bool power_on, bool all_displays) { |
- VLOG(1) << "OutputConfigurator::SetScreensOn " << power_on |
- << " all displays " << all_displays; |
- bool success = false; |
- if (is_running_on_chrome_os_) { |
- Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
- CHECK(display != NULL); |
- XGrabServer(display); |
- Window window = DefaultRootWindow(display); |
- XRRScreenResources* screen = XRRGetScreenResources(display, window); |
- CHECK(screen != NULL); |
- |
- // Set the CRTCs based on whether we want to turn the power on or off and |
- // select the outputs to operate on by name or all_displays. |
- for (int i = 0; i < output_count_; ++i) { |
- if (all_displays || output_cache_[i].is_internal) { |
- const int x = output_cache_[i].x; |
- const int y = output_cache_[i].y; |
- RROutput output = output_cache_[i].output; |
- RRCrtc crtc = output_cache_[i].crtc; |
- RRMode mode = None; |
- if (power_on) { |
- mode = (STATE_DUAL_MIRROR == output_state_) ? |
- output_cache_[i].mirror_mode : |
- output_cache_[i].ideal_mode; |
- } |
- |
- VLOG(1) << "SET POWER crtc: " << crtc |
- << ", mode " << mode |
- << ", output " << output |
- << ", x " << x |
- << ", y " << y; |
- // The values we are setting are already from the cache so no update |
- // required. |
- ConfigureCrtc(display, |
- screen, |
- crtc, |
- x, |
- y, |
- mode, |
- output); |
- output_cache_[i].is_powered_on = power_on; |
- success = true; |
- } |
- } |
- |
- // Force the DPMS on since the driver doesn't always detect that it should |
- // turn on. |
- if (power_on) { |
- CHECK(DPMSEnable(display)); |
- CHECK(DPMSForceLevel(display, DPMSModeOn)); |
- } |
- |
- XRRFreeScreenResources(screen); |
- XUngrabServer(display); |
- } |
- return success; |
-} |
- |
-bool OutputConfigurator::SetDisplayMode(State new_state) { |
- if (output_state_ == STATE_INVALID || |
- output_state_ == STATE_HEADLESS || |
- output_state_ == STATE_SINGLE) |
- return false; |
- |
- Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
- CHECK(display != NULL); |
- XGrabServer(display); |
- Window window = DefaultRootWindow(display); |
- XRRScreenResources* screen = XRRGetScreenResources(display, window); |
- CHECK(screen != NULL); |
- |
- UpdateCacheAndXrandrToState(display, |
- screen, |
- window, |
- new_state); |
- XRRFreeScreenResources(screen); |
- XUngrabServer(display); |
- return true; |
-} |
- |
-bool OutputConfigurator::Dispatch(const base::NativeEvent& event) { |
- // Ignore this event if the Xrandr extension isn't supported. |
- if (is_running_on_chrome_os_ && |
- (event->type - xrandr_event_base_ == RRNotify)) { |
- XEvent* xevent = static_cast<XEvent*>(event); |
- XRRNotifyEvent* notify_event = |
- reinterpret_cast<XRRNotifyEvent*>(xevent); |
- if (notify_event->subtype == RRNotify_OutputChange) { |
- XRROutputChangeNotifyEvent* output_change_event = |
- reinterpret_cast<XRROutputChangeNotifyEvent*>(xevent); |
- if ((output_change_event->connection == RR_Connected) || |
- (output_change_event->connection == RR_Disconnected)) { |
- RecacheAndUseDefaultState(); |
- CheckIsProjectingAndNotify(); |
- } |
- // Ignore the case of RR_UnkownConnection. |
- } |
- } |
- return true; |
-} |
- |
void OutputConfigurator::CheckIsProjectingAndNotify() { |
// Determine if there is an "internal" output and how many outputs are |
// connected. |