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) { | |
Daniel Erat
2012/06/07 19:17:40
nit: remove curly braces
disher
2012/06/07 19:40:23
Done.
| |
527 state = STATE_SINGLE; | |
528 } | |
529 } | |
530 } else { | |
531 // We have two displays attached so we need to look at their configuration. | |
532 // Note that, for simplicity, we will only detect the states that we would | |
533 // have used and will assume anything unexpected is INVALID (which should | |
534 // not happen in any expected usage scenario). | |
535 RRCrtc primary_crtc = None; | |
536 RRMode primary_mode = None; | |
537 int primary_height = 0; | |
538 GetOutputConfiguration(display, | |
539 screen, | |
540 output_cache_[primary_output_index_].output, | |
541 &primary_crtc, | |
542 &primary_mode, | |
543 &primary_height); | |
544 RRCrtc secondary_crtc = None; | |
545 RRMode secondary_mode = None; | |
546 int secondary_height = 0; | |
547 GetOutputConfiguration(display, | |
548 screen, | |
549 output_cache_[secondary_output_index_].output, | |
550 &secondary_crtc, | |
551 &secondary_mode, | |
552 &secondary_height); | |
553 // Make sure the CRTCs are matched to the expected outputs. | |
554 if ((output_cache_[primary_output_index_].crtc == primary_crtc) && | |
555 (output_cache_[secondary_output_index_].crtc == secondary_crtc)) { | |
556 // Check the mode matching: either both mirror or both ideal. | |
557 if ((output_cache_[primary_output_index_].mirror_mode == primary_mode) && | |
558 (output_cache_[secondary_output_index_].mirror_mode == | |
559 secondary_mode)) { | |
560 // We are already in mirror mode. | |
561 state = STATE_DUAL_MIRROR; | |
562 } else if ((output_cache_[primary_output_index_].ideal_mode == | |
563 primary_mode) && | |
564 (output_cache_[secondary_output_index_].ideal_mode == | |
565 secondary_mode)) { | |
566 // Both outputs are in their "ideal" mode so check their Y-offsets to | |
567 // see which "ideal" configuration this is. | |
568 if (primary_height == output_cache_[secondary_output_index_].y) { | |
569 // Secondary is tiled first. | |
570 state = STATE_DUAL_SECONDARY_ONLY; | |
571 } else if (secondary_height == output_cache_[primary_output_index_].y) { | |
572 // Primary is tiled first. | |
573 state = STATE_DUAL_PRIMARY_ONLY; | |
574 } | |
575 } | |
576 } | |
577 } | |
578 | |
579 return state; | |
580 } | |
581 | |
476 bool OutputConfigurator::CycleDisplayMode() { | 582 bool OutputConfigurator::CycleDisplayMode() { |
477 VLOG(1) << "CycleDisplayMode"; | 583 VLOG(1) << "CycleDisplayMode"; |
478 bool did_change = false; | 584 bool did_change = false; |
479 if (is_running_on_chrome_os_) { | 585 if (is_running_on_chrome_os_) { |
480 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 586 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
481 CHECK(display != NULL); | 587 CHECK(display != NULL); |
482 XGrabServer(display); | 588 XGrabServer(display); |
483 Window window = DefaultRootWindow(display); | 589 Window window = DefaultRootWindow(display); |
484 XRRScreenResources* screen = XRRGetScreenResources(display, window); | 590 XRRScreenResources* screen = XRRGetScreenResources(display, window); |
485 CHECK(screen != NULL); | 591 CHECK(screen != NULL); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
592 RecacheAndUseDefaultState(); | 698 RecacheAndUseDefaultState(); |
593 } | 699 } |
594 // Ignore the case of RR_UnkownConnection. | 700 // Ignore the case of RR_UnkownConnection. |
595 } | 701 } |
596 } | 702 } |
597 return true; | 703 return true; |
598 } | 704 } |
599 | 705 |
600 } // namespace chromeos | 706 } // namespace chromeos |
601 | 707 |
OLD | NEW |