OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/monitor/output_configurator.h" | 5 #include "chromeos/monitor/output_configurator.h" |
6 | 6 |
7 #include "base/chromeos/chromeos_version.h" | 7 #include "base/chromeos/chromeos_version.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_pump_aurax11.h" | 9 #include "base/message_pump_aurax11.h" |
10 #include "chromeos/dbus/dbus_thread_manager.h" | 10 #include "chromeos/dbus/dbus_thread_manager.h" |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 screen->crtcs[i], | 151 screen->crtcs[i], |
152 x, | 152 x, |
153 y, | 153 y, |
154 kMode, | 154 kMode, |
155 kOutput); | 155 kOutput); |
156 } | 156 } |
157 int mm_width = width * kPixelsToMmScale; | 157 int mm_width = width * kPixelsToMmScale; |
158 int mm_height = height * kPixelsToMmScale; | 158 int mm_height = height * kPixelsToMmScale; |
159 XRRSetScreenSize(display, window, width, height, mm_width, mm_height); | 159 XRRSetScreenSize(display, window, width, height, mm_width, mm_height); |
160 } | 160 } |
| 161 |
| 162 // A helper to get the current CRTC, Mode, and height for a given output. This |
| 163 // is read from the XRandR configuration and not any of our caches. |
| 164 static void GetOutputConfiguration(Display* display, |
| 165 XRRScreenResources* screen, |
| 166 RROutput output, |
| 167 RRCrtc* crtc, |
| 168 RRMode* mode, |
| 169 int* height) { |
| 170 XRROutputInfo* output_info = XRRGetOutputInfo(display, screen, output); |
| 171 CHECK(output_info != NULL); |
| 172 *crtc = output_info->crtc; |
| 173 XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display, screen, *crtc); |
| 174 if (crtc_info != NULL) { |
| 175 *mode = crtc_info->mode; |
| 176 *height = crtc_info->height; |
| 177 XRRFreeCrtcInfo(crtc_info); |
| 178 } |
| 179 XRRFreeOutputInfo(output_info); |
| 180 } |
161 } // namespace | 181 } // namespace |
162 | 182 |
163 bool OutputConfigurator::TryRecacheOutputs(Display* display, | 183 bool OutputConfigurator::TryRecacheOutputs(Display* display, |
164 XRRScreenResources* screen) { | 184 XRRScreenResources* screen) { |
165 bool outputs_did_change = false; | 185 bool outputs_did_change = false; |
166 int previous_connected_count = 0; | 186 int previous_connected_count = 0; |
167 int new_connected_count = 0; | 187 int new_connected_count = 0; |
168 | 188 |
169 if (output_count_ != screen->noutput) { | 189 if (output_count_ != screen->noutput) { |
170 outputs_did_change = true; | 190 outputs_did_change = true; |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 | 333 |
314 // Cache the initial output state. | 334 // Cache the initial output state. |
315 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 335 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
316 CHECK(display != NULL); | 336 CHECK(display != NULL); |
317 XGrabServer(display); | 337 XGrabServer(display); |
318 Window window = DefaultRootWindow(display); | 338 Window window = DefaultRootWindow(display); |
319 XRRScreenResources* screen = XRRGetScreenResources(display, window); | 339 XRRScreenResources* screen = XRRGetScreenResources(display, window); |
320 CHECK(screen != NULL); | 340 CHECK(screen != NULL); |
321 bool did_detect_outputs = TryRecacheOutputs(display, screen); | 341 bool did_detect_outputs = TryRecacheOutputs(display, screen); |
322 CHECK(did_detect_outputs); | 342 CHECK(did_detect_outputs); |
323 State state = GetDefaultState(); | 343 State current_state = InferCurrentState(display, screen); |
324 UpdateCacheAndXrandrToState(display, screen, window, state); | 344 if (current_state == STATE_INVALID) { |
| 345 // Unknown state. Transition into the default state. |
| 346 State state = GetDefaultState(); |
| 347 UpdateCacheAndXrandrToState(display, screen, window, state); |
| 348 } else { |
| 349 // This is a valid state so just save it to |output_state_|. |
| 350 output_state_ = current_state; |
| 351 } |
325 // Find xrandr_event_base_ since we need it to interpret events, later. | 352 // Find xrandr_event_base_ since we need it to interpret events, later. |
326 int error_base_ignored = 0; | 353 int error_base_ignored = 0; |
327 XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored); | 354 XRRQueryExtension(display, &xrandr_event_base_, &error_base_ignored); |
328 // Relinquish X resources. | 355 // Relinquish X resources. |
329 XRRFreeScreenResources(screen); | 356 XRRFreeScreenResources(screen); |
330 XUngrabServer(display); | 357 XUngrabServer(display); |
331 } | 358 } |
332 } | 359 } |
333 | 360 |
334 OutputConfigurator::~OutputConfigurator() { | 361 OutputConfigurator::~OutputConfigurator() { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 State state = STATE_HEADLESS; | 493 State state = STATE_HEADLESS; |
467 if (-1 != primary_output_index_) { | 494 if (-1 != primary_output_index_) { |
468 if (-1 != secondary_output_index_) | 495 if (-1 != secondary_output_index_) |
469 state = mirror_supported_ ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY; | 496 state = mirror_supported_ ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY; |
470 else | 497 else |
471 state = STATE_SINGLE; | 498 state = STATE_SINGLE; |
472 } | 499 } |
473 return state; | 500 return state; |
474 } | 501 } |
475 | 502 |
| 503 State OutputConfigurator::InferCurrentState(Display* display, |
| 504 XRRScreenResources* screen) const { |
| 505 // STATE_INVALID will be our default or "unknown" state. |
| 506 State state = STATE_INVALID; |
| 507 // First step: count the number of connected outputs. |
| 508 if (secondary_output_index_ == -1) { |
| 509 // No secondary display. |
| 510 if (primary_output_index_ == -1) { |
| 511 // No primary display implies HEADLESS. |
| 512 state = STATE_HEADLESS; |
| 513 } else { |
| 514 // The common case of primary-only. |
| 515 // The only sanity check we require in this case is that the current mode |
| 516 // of the output's CRTC is the ideal mode we determined for it. |
| 517 RRCrtc primary_crtc = None; |
| 518 RRMode primary_mode = None; |
| 519 int primary_height = 0; |
| 520 GetOutputConfiguration(display, |
| 521 screen, |
| 522 output_cache_[primary_output_index_].output, |
| 523 &primary_crtc, |
| 524 &primary_mode, |
| 525 &primary_height); |
| 526 if (primary_mode == output_cache_[primary_output_index_].ideal_mode) |
| 527 state = STATE_SINGLE; |
| 528 } |
| 529 } else { |
| 530 // We have two displays attached so we need to look at their configuration. |
| 531 // Note that, for simplicity, we will only detect the states that we would |
| 532 // have used and will assume anything unexpected is INVALID (which should |
| 533 // not happen in any expected usage scenario). |
| 534 RRCrtc primary_crtc = None; |
| 535 RRMode primary_mode = None; |
| 536 int primary_height = 0; |
| 537 GetOutputConfiguration(display, |
| 538 screen, |
| 539 output_cache_[primary_output_index_].output, |
| 540 &primary_crtc, |
| 541 &primary_mode, |
| 542 &primary_height); |
| 543 RRCrtc secondary_crtc = None; |
| 544 RRMode secondary_mode = None; |
| 545 int secondary_height = 0; |
| 546 GetOutputConfiguration(display, |
| 547 screen, |
| 548 output_cache_[secondary_output_index_].output, |
| 549 &secondary_crtc, |
| 550 &secondary_mode, |
| 551 &secondary_height); |
| 552 // Make sure the CRTCs are matched to the expected outputs. |
| 553 if ((output_cache_[primary_output_index_].crtc == primary_crtc) && |
| 554 (output_cache_[secondary_output_index_].crtc == secondary_crtc)) { |
| 555 // Check the mode matching: either both mirror or both ideal. |
| 556 if ((output_cache_[primary_output_index_].mirror_mode == primary_mode) && |
| 557 (output_cache_[secondary_output_index_].mirror_mode == |
| 558 secondary_mode)) { |
| 559 // We are already in mirror mode. |
| 560 state = STATE_DUAL_MIRROR; |
| 561 } else if ((output_cache_[primary_output_index_].ideal_mode == |
| 562 primary_mode) && |
| 563 (output_cache_[secondary_output_index_].ideal_mode == |
| 564 secondary_mode)) { |
| 565 // Both outputs are in their "ideal" mode so check their Y-offsets to |
| 566 // see which "ideal" configuration this is. |
| 567 if (primary_height == output_cache_[secondary_output_index_].y) { |
| 568 // Secondary is tiled first. |
| 569 state = STATE_DUAL_SECONDARY_ONLY; |
| 570 } else if (secondary_height == output_cache_[primary_output_index_].y) { |
| 571 // Primary is tiled first. |
| 572 state = STATE_DUAL_PRIMARY_ONLY; |
| 573 } |
| 574 } |
| 575 } |
| 576 } |
| 577 |
| 578 return state; |
| 579 } |
| 580 |
476 bool OutputConfigurator::CycleDisplayMode() { | 581 bool OutputConfigurator::CycleDisplayMode() { |
477 VLOG(1) << "CycleDisplayMode"; | 582 VLOG(1) << "CycleDisplayMode"; |
478 bool did_change = false; | 583 bool did_change = false; |
479 if (is_running_on_chrome_os_) { | 584 if (is_running_on_chrome_os_) { |
480 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 585 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
481 CHECK(display != NULL); | 586 CHECK(display != NULL); |
482 XGrabServer(display); | 587 XGrabServer(display); |
483 Window window = DefaultRootWindow(display); | 588 Window window = DefaultRootWindow(display); |
484 XRRScreenResources* screen = XRRGetScreenResources(display, window); | 589 XRRScreenResources* screen = XRRGetScreenResources(display, window); |
485 CHECK(screen != NULL); | 590 CHECK(screen != NULL); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 RecacheAndUseDefaultState(); | 697 RecacheAndUseDefaultState(); |
593 } | 698 } |
594 // Ignore the case of RR_UnkownConnection. | 699 // Ignore the case of RR_UnkownConnection. |
595 } | 700 } |
596 } | 701 } |
597 return true; | 702 return true; |
598 } | 703 } |
599 | 704 |
600 } // namespace chromeos | 705 } // namespace chromeos |
601 | 706 |
OLD | NEW |