summaryrefslogtreecommitdiffstats
path: root/chromeos/display
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-27 21:51:44 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-27 21:51:44 +0000
commite72fa4d643005f438978d8a9c21272f3acd64061 (patch)
treefabd135523ba0954c3c6b861dd21c5e165512580 /chromeos/display
parentf33386d952654acfad4f62029ece49f0e7ecb200 (diff)
downloadchromium_src-e72fa4d643005f438978d8a9c21272f3acd64061.zip
chromium_src-e72fa4d643005f438978d8a9c21272f3acd64061.tar.gz
chromium_src-e72fa4d643005f438978d8a9c21272f3acd64061.tar.bz2
Revert r 144499 "Rename the remaining usage of Monitor to Display"
Temporarily reverting rename change to investigate 133784 TBR=oshima@chromium.org BUG=123160 TEST=none Review URL: https://chromiumcodereview.appspot.com/10689014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144573 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/display')
-rw-r--r--chromeos/display/DEPS3
-rw-r--r--chromeos/display/output_configurator.cc804
-rw-r--r--chromeos/display/output_configurator.h165
3 files changed, 0 insertions, 972 deletions
diff --git a/chromeos/display/DEPS b/chromeos/display/DEPS
deleted file mode 100644
index d6abdda..0000000
--- a/chromeos/display/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+dbus",
-]
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
deleted file mode 100644
index 4543a52..0000000
--- a/chromeos/display/output_configurator.cc
+++ /dev/null
@@ -1,804 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/display/output_configurator.h"
-
-#include <X11/Xlib.h>
-#include <X11/extensions/dpms.h>
-#include <X11/extensions/Xrandr.h>
-
-// Xlib defines Status as int which causes our include of dbus/bus.h to fail
-// when it tries to name an enum Status. Thus, we need to undefine it (note
-// that this will cause a problem if code needs to use the Status type).
-// RootWindow causes similar problems in that there is a Chromium type with that
-// name.
-#undef Status
-#undef RootWindow
-
-#include "base/chromeos/chromeos_version.h"
-#include "base/logging.h"
-#include "base/message_pump_aurax11.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "dbus/bus.h"
-#include "dbus/exported_object.h"
-#include "dbus/message.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
-
-namespace chromeos {
-
-namespace {
-// DPI measurements.
-const float kMmInInch = 25.4;
-const float kDpi96 = 96.0;
-const float kPixelsToMmScale = kMmInInch / kDpi96;
-
-// The DPI threshold to detech high density screen.
-// Higher DPI than this will use device_scale_factor=2
-// Should be kept in sync with display_change_observer_x11.cc
-const unsigned int kHighDensityDIPThreshold = 160;
-
-// Prefixes for the built-in displays.
-const char kInternal_LVDS[] = "LVDS";
-const char kInternal_eDP[] = "eDP";
-
-// Gap between screens so cursor at bottom of active display doesn't partially
-// appear on top of inactive display. Higher numbers guard against larger
-// cursors, but also waste more memory. We will double this gap for screens
-// with a device_scale_factor of 2. While this gap will not guard against all
-// possible cursors in X, it should handle the ones we actually use. See
-// crbug.com/130188
-const int kVerticalGap = 30;
-
-// TODO: Determine if we need to organize modes in a way which provides better
-// than O(n) lookup time. In many call sites, for example, the "next" mode is
-// typically what we are looking for so using this helper might be too
-// expensive.
-static XRRModeInfo* ModeInfoForID(XRRScreenResources* screen, RRMode modeID) {
- XRRModeInfo* result = NULL;
- for (int i = 0; (i < screen->nmode) && (result == NULL); i++)
- if (modeID == screen->modes[i].id)
- result = &screen->modes[i];
-
- // We can't fail to find a mode referenced from the same screen.
- CHECK(result != NULL);
- return result;
-}
-
-// Identifies the modes which will be used by the respective outputs when in a
-// mirror mode. This means that the two modes will have the same resolution.
-// The RROutput IDs |one| and |two| are used to look up the modes and
-// |out_one_mode| and |out_two_mode| are the out-parameters for the respective
-// modes.
-// Returns false if it fails to find a compatible set of modes.
-static bool FindMirrorModeForOutputs(Display* display,
- XRRScreenResources* screen,
- RROutput one,
- RROutput two,
- RRMode* out_one_mode,
- RRMode* out_two_mode) {
- XRROutputInfo* primary = XRRGetOutputInfo(display, screen, one);
- XRROutputInfo* secondary = XRRGetOutputInfo(display, screen, two);
-
- int one_index = 0;
- int two_index = 0;
- bool found = false;
- while (!found &&
- (one_index < primary->nmode) &&
- (two_index < secondary->nmode)) {
- RRMode one_id = primary->modes[one_index];
- RRMode two_id = secondary->modes[two_index];
- XRRModeInfo* one_mode = ModeInfoForID(screen, one_id);
- XRRModeInfo* two_mode = ModeInfoForID(screen, two_id);
- int one_width = one_mode->width;
- int one_height = one_mode->height;
- int two_width = two_mode->width;
- int two_height = two_mode->height;
- if ((one_width == two_width) && (one_height == two_height)) {
- *out_one_mode = one_id;
- *out_two_mode = two_id;
- found = true;
- } else {
- // The sort order of the modes is NOT by mode area but is sorted by width,
- // then by height within each like width.
- if (one_width > two_width) {
- one_index += 1;
- } else if (one_width < two_width) {
- two_index += 1;
- } else {
- if (one_height > two_height) {
- one_index += 1;
- } else {
- two_index += 1;
- }
- }
- }
- }
- XRRFreeOutputInfo(primary);
- XRRFreeOutputInfo(secondary);
- return found;
-}
-
-// A helper to call XRRSetCrtcConfig with the given options but some of our
-// default output count and rotation arguments.
-static void ConfigureCrtc(Display *display,
- XRRScreenResources* screen,
- RRCrtc crtc,
- int x,
- int y,
- RRMode mode,
- RROutput output) {
- const Rotation kRotate = RR_Rotate_0;
- RROutput* outputs = NULL;
- int num_outputs = 0;
-
- // Check the output and mode argument - if either are None, we should disable.
- if ((output != None) && (mode != None)) {
- outputs = &output;
- num_outputs = 1;
- }
-
- XRRSetCrtcConfig(display,
- screen,
- crtc,
- CurrentTime,
- x,
- y,
- mode,
- kRotate,
- outputs,
- num_outputs);
- if (num_outputs == 1) {
- // We are enabling a display so make sure it is turned on.
- CHECK(DPMSEnable(display));
- CHECK(DPMSForceLevel(display, DPMSModeOn));
- }
-}
-
-// Called to set the frame buffer (underling XRR "screen") size. Has a
-// side-effect of disabling all CRTCs.
-static void CreateFrameBuffer(Display* display,
- XRRScreenResources* screen,
- Window window,
- int width,
- int height) {
- // Note that setting the screen size fails if any CRTCs are currently
- // pointing into it so disable them all.
- for (int i = 0; i < screen->ncrtc; ++i) {
- const int x = 0;
- const int y = 0;
- const RRMode kMode = None;
- const RROutput kOutput = None;
-
- ConfigureCrtc(display,
- screen,
- screen->crtcs[i],
- x,
- y,
- kMode,
- kOutput);
- }
- int mm_width = width * kPixelsToMmScale;
- int mm_height = height * kPixelsToMmScale;
- XRRSetScreenSize(display, window, width, height, mm_width, mm_height);
-}
-
-// A helper to get the current CRTC, Mode, and height for a given output. This
-// is read from the XRandR configuration and not any of our caches.
-static void GetOutputConfiguration(Display* display,
- XRRScreenResources* screen,
- RROutput output,
- RRCrtc* crtc,
- RRMode* mode,
- int* height) {
- XRROutputInfo* output_info = XRRGetOutputInfo(display, screen, output);
- CHECK(output_info != NULL);
- *crtc = output_info->crtc;
- XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display, screen, *crtc);
- if (crtc_info != NULL) {
- *mode = crtc_info->mode;
- *height = crtc_info->height;
- XRRFreeCrtcInfo(crtc_info);
- }
- XRRFreeOutputInfo(output_info);
-}
-
-// A helper to determine the device_scale_factor given pixel width and mm_width.
-// This currently only reports two scale factors (1.0 and 2.0)
-static float ComputeDeviceScaleFactor(unsigned int width,
- unsigned long mm_width) {
- float device_scale_factor = 1.0f;
- if (mm_width > 0 && (kMmInInch * width / mm_width) > kHighDensityDIPThreshold)
- device_scale_factor = 2.0f;
- return device_scale_factor;
-}
-
-} // namespace
-
-bool OutputConfigurator::TryRecacheOutputs(Display* display,
- XRRScreenResources* screen) {
- bool outputs_did_change = false;
- int previous_connected_count = 0;
- int new_connected_count = 0;
-
- if (output_count_ != screen->noutput) {
- outputs_did_change = true;
- } else {
- // The outputs might have changed so compare the connected states in the
- // screen to our existing cache.
- for (int i = 0; (i < output_count_) && !outputs_did_change; ++i) {
- RROutput thisID = screen->outputs[i];
- XRROutputInfo* output = XRRGetOutputInfo(display, screen, thisID);
- bool now_connected = (RR_Connected == output->connection);
- outputs_did_change = (now_connected != output_cache_[i].is_connected);
- XRRFreeOutputInfo(output);
-
- if (output_cache_[i].is_connected)
- previous_connected_count += 1;
- if (now_connected)
- new_connected_count += 1;
- }
- }
-
- 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_]);
- }
-
- // 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;
- }
- }
-
- 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);
- }
-
- // 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);
-
- 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;
- }
- }
- 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();
- }
-}
-
-OutputConfigurator::~OutputConfigurator() {
-}
-
-void OutputConfigurator::UpdateCacheAndXrandrToState(
- Display* display,
- XRRScreenResources* screen,
- Window window,
- State new_state) {
- // Default rules:
- // - single display = rebuild framebuffer and set to ideal_mode.
- // - multi display = rebuild framebuffer and set to mirror_mode.
-
- // First, calculate the width and height of the framebuffer (we could retain
- // the existing buffer, if it isn't resizing, but that causes an odd display
- // state where the CRTCs are repositioned over the root windows before Chrome
- // can move them). It is a feature worth considering, though, and wouldn't
- // be difficult to implement (just check the current framebuffer size before
- // changing it).
- int width = 0;
- int height = 0;
- int primary_height = 0;
- int secondary_height = 0;
- int vertical_gap = 0;
- if (new_state == STATE_SINGLE) {
- CHECK_NE(-1, primary_output_index_);
-
- XRRModeInfo* ideal_mode = ModeInfoForID(
- screen,
- output_cache_[primary_output_index_].ideal_mode);
- width = ideal_mode->width;
- height = ideal_mode->height;
- } else if (new_state == STATE_DUAL_MIRROR) {
- CHECK_NE(-1, primary_output_index_);
- CHECK_NE(-1, secondary_output_index_);
-
- XRRModeInfo* mirror_mode = ModeInfoForID(
- screen,
- output_cache_[primary_output_index_].mirror_mode);
- width = mirror_mode->width;
- height = mirror_mode->height;
- } else if ((new_state == STATE_DUAL_PRIMARY_ONLY) ||
- (new_state == STATE_DUAL_SECONDARY_ONLY)) {
- CHECK_NE(-1, primary_output_index_);
- CHECK_NE(-1, secondary_output_index_);
-
- XRRModeInfo* one_ideal = ModeInfoForID(
- screen,
- output_cache_[primary_output_index_].ideal_mode);
- XRRModeInfo* two_ideal = ModeInfoForID(
- screen,
- output_cache_[secondary_output_index_].ideal_mode);
-
- // Compute the device scale factor for the topmost display. We only need
- // to take this device's scale factor into account as we are creating a gap
- // to avoid the cursor drawing onto the second (unused) display when the
- // cursor is near the bottom of the topmost display.
- float top_scale_factor;
- if (new_state == STATE_DUAL_PRIMARY_ONLY) {
- top_scale_factor = ComputeDeviceScaleFactor(one_ideal->width,
- output_cache_[primary_output_index_].mm_width);
- } else {
- top_scale_factor = ComputeDeviceScaleFactor(two_ideal->width,
- output_cache_[secondary_output_index_].mm_width);
- }
- vertical_gap = kVerticalGap * top_scale_factor;
-
- width = std::max<int>(one_ideal->width, two_ideal->width);
- height = one_ideal->height + two_ideal->height + vertical_gap;
- primary_height = one_ideal->height;
- secondary_height = two_ideal->height;
- }
- CreateFrameBuffer(display, screen, window, width, height);
-
- // Now, tile the outputs appropriately.
- const int x = 0;
- const int y = 0;
- switch (new_state) {
- case STATE_SINGLE:
- ConfigureCrtc(display,
- screen,
- output_cache_[primary_output_index_].crtc,
- x,
- y,
- output_cache_[primary_output_index_].ideal_mode,
- output_cache_[primary_output_index_].output);
- break;
- case STATE_DUAL_MIRROR:
- case STATE_DUAL_PRIMARY_ONLY:
- case STATE_DUAL_SECONDARY_ONLY: {
- RRMode primary_mode = output_cache_[primary_output_index_].mirror_mode;
- RRMode secondary_mode =
- output_cache_[secondary_output_index_].mirror_mode;
- int primary_y = y;
- int secondary_y = y;
-
- if (new_state != STATE_DUAL_MIRROR) {
- primary_mode = output_cache_[primary_output_index_].ideal_mode;
- secondary_mode = output_cache_[secondary_output_index_].ideal_mode;
- }
- if (new_state == STATE_DUAL_PRIMARY_ONLY)
- secondary_y = y + primary_height + vertical_gap;
- if (new_state == STATE_DUAL_SECONDARY_ONLY)
- primary_y = y + secondary_height + vertical_gap;
-
- ConfigureCrtc(display,
- screen,
- output_cache_[primary_output_index_].crtc,
- x,
- primary_y,
- primary_mode,
- output_cache_[primary_output_index_].output);
- ConfigureCrtc(display,
- screen,
- output_cache_[secondary_output_index_].crtc,
- x,
- secondary_y,
- secondary_mode,
- output_cache_[secondary_output_index_].output);
- }
- break;
- case STATE_HEADLESS:
- // Do nothing.
- break;
- default:
- NOTREACHED() << "Unhandled state " << new_state;
- }
- output_state_ = new_state;
-}
-
-bool OutputConfigurator::RecacheAndUseDefaultState() {
- 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_change = TryRecacheOutputs(display, screen);
- if (did_detect_change) {
- State state = GetDefaultState();
- UpdateCacheAndXrandrToState(display, screen, window, state);
- }
- XRRFreeScreenResources(screen);
- XUngrabServer(display);
- return did_detect_change;
-}
-
-State OutputConfigurator::GetDefaultState() const {
- State state = STATE_HEADLESS;
- if (-1 != primary_output_index_) {
- if (-1 != secondary_output_index_)
- state = mirror_supported_ ? STATE_DUAL_MIRROR : STATE_DUAL_PRIMARY_ONLY;
- else
- state = STATE_SINGLE;
- }
- return state;
-}
-
-State OutputConfigurator::InferCurrentState(Display* display,
- XRRScreenResources* screen) const {
- // STATE_INVALID will be our default or "unknown" state.
- State state = STATE_INVALID;
- // First step: count the number of connected outputs.
- if (secondary_output_index_ == -1) {
- // No secondary display.
- if (primary_output_index_ == -1) {
- // No primary display implies HEADLESS.
- state = STATE_HEADLESS;
- } else {
- // The common case of primary-only.
- // The only sanity check we require in this case is that the current mode
- // of the output's CRTC is the ideal mode we determined for it.
- RRCrtc primary_crtc = None;
- RRMode primary_mode = None;
- int primary_height = 0;
- GetOutputConfiguration(display,
- screen,
- output_cache_[primary_output_index_].output,
- &primary_crtc,
- &primary_mode,
- &primary_height);
- if (primary_mode == output_cache_[primary_output_index_].ideal_mode)
- state = STATE_SINGLE;
- }
- } else {
- // We have two displays attached so we need to look at their configuration.
- // Note that, for simplicity, we will only detect the states that we would
- // have used and will assume anything unexpected is INVALID (which should
- // not happen in any expected usage scenario).
- RRCrtc primary_crtc = None;
- RRMode primary_mode = None;
- int primary_height = 0;
- GetOutputConfiguration(display,
- screen,
- output_cache_[primary_output_index_].output,
- &primary_crtc,
- &primary_mode,
- &primary_height);
- RRCrtc secondary_crtc = None;
- RRMode secondary_mode = None;
- int secondary_height = 0;
- GetOutputConfiguration(display,
- screen,
- output_cache_[secondary_output_index_].output,
- &secondary_crtc,
- &secondary_mode,
- &secondary_height);
- // Make sure the CRTCs are matched to the expected outputs.
- if ((output_cache_[primary_output_index_].crtc == primary_crtc) &&
- (output_cache_[secondary_output_index_].crtc == secondary_crtc)) {
- // Check the mode matching: either both mirror or both ideal.
- if ((output_cache_[primary_output_index_].mirror_mode == primary_mode) &&
- (output_cache_[secondary_output_index_].mirror_mode ==
- secondary_mode)) {
- // We are already in mirror mode.
- state = STATE_DUAL_MIRROR;
- } else if ((output_cache_[primary_output_index_].ideal_mode ==
- primary_mode) &&
- (output_cache_[secondary_output_index_].ideal_mode ==
- secondary_mode)) {
- // Both outputs are in their "ideal" mode so check their Y-offsets to
- // see which "ideal" configuration this is.
- if (primary_height == output_cache_[secondary_output_index_].y) {
- // Secondary is tiled first.
- state = STATE_DUAL_SECONDARY_ONLY;
- } else if (secondary_height == output_cache_[primary_output_index_].y) {
- // Primary is tiled first.
- state = STATE_DUAL_PRIMARY_ONLY;
- }
- }
- }
- }
-
- return state;
-}
-
-bool OutputConfigurator::CycleDisplayMode() {
- 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.
- State new_state = STATE_INVALID;
- switch (output_state_) {
- case STATE_DUAL_MIRROR:
- new_state = STATE_DUAL_PRIMARY_ONLY;
- break;
- case STATE_DUAL_PRIMARY_ONLY:
- 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;
- 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.
- bool has_internal_output = false;
- int connected_output_count = 0;
- for (int i = 0; i < output_count_; ++i) {
- if (output_cache_[i].is_connected) {
- connected_output_count += 1;
- has_internal_output |= output_cache_[i].is_internal;
- }
- }
-
- // "Projecting" is defined as having more than 1 output connected while at
- // least one of them is an internal output.
- bool is_projecting = has_internal_output && (connected_output_count > 1);
- chromeos::DBusThreadManager* manager = chromeos::DBusThreadManager::Get();
- dbus::Bus* bus = manager->GetSystemBus();
- dbus::ObjectProxy* power_manager_proxy = bus->GetObjectProxy(
- power_manager::kPowerManagerServiceName,
- dbus::ObjectPath(power_manager::kPowerManagerServicePath));
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kSetIsProjectingMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendBool(is_projecting);
- power_manager_proxy->CallMethod(
- &method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- dbus::ObjectProxy::EmptyResponseCallback());
-}
-
-} // namespace chromeos
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
deleted file mode 100644
index 2b6d2d4..0000000
--- a/chromeos/display/output_configurator.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_
-#define CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_
-#pragma once
-
-#include "base/basictypes.h"
-#include "base/event_types.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "chromeos/chromeos_export.h"
-
-// Forward declarations for Xlib and Xrandr.
-// This is so unused X definitions don't pollute the namespace.
-typedef unsigned long XID;
-typedef XID Window;
-typedef XID RROutput;
-typedef XID RRCrtc;
-typedef XID RRMode;
-
-struct _XRRScreenResources;
-typedef _XRRScreenResources XRRScreenResources;
-
-namespace chromeos {
-
-// The information we need to cache from an output to implement operations such
-// as power state but also to eliminate duplicate operations within a given
-// action (determining which CRTC to use for a given output, for example).
-struct CachedOutputDescription {
- RROutput output;
- RRCrtc crtc;
- RRMode mirror_mode;
- RRMode ideal_mode;
- int x;
- int y;
- bool is_connected;
- bool is_powered_on;
- bool is_internal;
- unsigned long mm_width;
- unsigned long mm_height;
-};
-
-// Used to describe the state of a multi-display configuration.
-enum State {
- STATE_INVALID,
- STATE_HEADLESS,
- STATE_SINGLE,
- STATE_DUAL_MIRROR,
- STATE_DUAL_PRIMARY_ONLY,
- STATE_DUAL_SECONDARY_ONLY,
-};
-
-// This class interacts directly with the underlying Xrandr API to manipulate
-// CTRCs and Outputs. It will likely grow more state, over time, or expose
-// Output info in other ways as more of the Chrome display code grows up around
-// it.
-class CHROMEOS_EXPORT OutputConfigurator : public MessageLoop::Dispatcher {
- public:
- OutputConfigurator();
- virtual ~OutputConfigurator();
-
- State output_state() const { return output_state_; }
-
- // Called when the user hits ctrl-F4 to request a display mode change.
- // This method should only return false if it was called in a single-head or
- // headless mode.
- bool CycleDisplayMode();
-
- // Called when powerd notifies us that some set of displays should be turned
- // on or off. This requires enabling or disabling the CRTC associated with
- // the display(s) in question so that the low power state is engaged.
- bool ScreenPowerSet(bool power_on, bool all_displays);
-
- // Force switching the display mode to |new_state|. This method is used when
- // the user explicitly changes the display mode in the options UI. Returns
- // false if it was called in a single-head or headless mode.
- bool SetDisplayMode(State new_state);
-
- // Called when an RRNotify event is received. The implementation is
- // interested in the cases of RRNotify events which correspond to output
- // add/remove events. Note that Output add/remove events are sent in response
- // to our own reconfiguration operations so spurious events are common.
- // Spurious events will have no effect.
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
-
- private:
- // Updates |output_count_|, |output_cache_|, |mirror_supported_|,
- // |primary_output_index_|, and |secondary_output_index_| with new data.
- // Returns true if the update succeeded or false if it was skipped since no
- // actual change was observed.
- // Note that |output_state_| is not updated by this call.
- bool TryRecacheOutputs(Display* display, XRRScreenResources* screen);
-
- // Uses the data stored in |output_cache_| and the given |new_state| to
- // configure the Xrandr interface and then updates |output_state_| to reflect
- // the new state.
- void UpdateCacheAndXrandrToState(Display* display,
- XRRScreenResources* screen,
- Window window,
- State new_state);
-
- // A helper to re-cache instance variable state and transition into the
- // appropriate default state for the observed displays.
- bool RecacheAndUseDefaultState();
-
- // Checks the |primary_output_index_|, |secondary_output_index_|, and
- // |mirror_supported_| to see how many displays are currently connected and
- // returns the state which is most appropriate as a default state for those
- // displays.
- State GetDefaultState() const;
-
- // Called during start-up to determine what the current state of the displays
- // appears to be, by investigating how the outputs compare to the data stored
- // in |output_cache_|. Returns STATE_INVALID if the current display state
- // doesn't match any supported state. |output_cache_| must be up-to-date with
- // regards to the state of X or this method may return incorrect results.
- State InferCurrentState(Display* display, XRRScreenResources* screen) const;
-
- // Scans the |output_cache_| to determine whether or not we are in a
- // "projecting" state and then calls the DBus kSetIsProjectingMethod on powerd
- // with the result.
- void CheckIsProjectingAndNotify();
-
- // This is detected by the constructor to determine whether or not we should
- // be enabled. If we aren't running on ChromeOS, we can't assume that the
- // Xrandr X11 extension is supported.
- // If this flag is set to false, any attempts to change the output
- // configuration to immediately fail without changing the state.
- bool is_running_on_chrome_os_;
-
- // The number of outputs in the output_cache_ array.
- int output_count_;
-
- // The list of cached output descriptions (|output_count_| elements long).
- scoped_array<CachedOutputDescription> output_cache_;
-
- // True if |output_cache_| describes a permutation of outputs which support a
- // mirrored device mode.
- bool mirror_supported_;
-
- // The index of the primary connected output in |output_cache_|. -1 if there
- // is no primary output. This implies the machine currently has no outputs.
- int primary_output_index_;
-
- // The index of the secondary connected output in |output_cache_|. -1 if
- // there is no secondary output. This implies the machine currently has one
- // output.
- int secondary_output_index_;
-
- // The base of the event numbers used to represent XRandr events used in
- // decoding events regarding output add/remove.
- int xrandr_event_base_;
-
- // The display state as derived from the outputs observed in |output_cache_|.
- // This is used for rotating display modes.
- State output_state_;
-
- DISALLOW_COPY_AND_ASSIGN(OutputConfigurator);
-};
-
-} // namespace chromeos
-
-#endif // CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_