diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-27 21:51:44 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-27 21:51:44 +0000 |
commit | e72fa4d643005f438978d8a9c21272f3acd64061 (patch) | |
tree | fabd135523ba0954c3c6b861dd21c5e165512580 /chromeos/display | |
parent | f33386d952654acfad4f62029ece49f0e7ecb200 (diff) | |
download | chromium_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/DEPS | 3 | ||||
-rw-r--r-- | chromeos/display/output_configurator.cc | 804 | ||||
-rw-r--r-- | chromeos/display/output_configurator.h | 165 |
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_ |