Skip to content

Commit

Permalink
Add ability to set resolution on external display
Browse files Browse the repository at this point in the history
 * OutputConfigurator gets selected resolution via StateController::GetResolutionForDisplay
 * It only shows one selection per one resolution.
   Non interlaced takes precedence and best refresh rate
   is chosen.
 * Resolution list is added to DisplayInfo. UI can use this
   to present options to users.
 * Created separate display_util_x11 for utility functions that
   depends on xrandr.

BUG=230733
TEST=covered by tests. more to come. manual test should be possible after UI is added. (crbug.com/266097)

Review URL: https://chromiumcodereview.appspot.com/21297003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214997 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
oshima@chromium.org committed Aug 1, 2013
1 parent 2a7d887 commit a5792d3
Show file tree
Hide file tree
Showing 21 changed files with 691 additions and 121 deletions.
4 changes: 3 additions & 1 deletion ash/ash.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@
'display/display_manager.cc',
'display/display_manager.h',
'display/display_pref_util.h',
'display/display_util_x11.cc',
'display/display_util_x11.h',
'display/event_transformation_handler.cc',
'display/event_transformation_handler.h',
'display/mirror_window_controller.cc',
Expand Down Expand Up @@ -791,7 +793,7 @@
}],
['use_x11==1', {
'sources': [
'display/display_change_observer_x11_unittest.cc'
'display/display_util_x11_unittest.cc'
],
}],
['chromeos!=1', {
Expand Down
69 changes: 24 additions & 45 deletions ash/display/display_change_observer_x11.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "ash/display/display_info.h"
#include "ash/display/display_layout_store.h"
#include "ash/display/display_manager.h"
#include "ash/display/display_util_x11.h"
#include "ash/shell.h"
#include "base/command_line.h"
#include "base/message_loop/message_pump_aurax11.h"
Expand All @@ -26,40 +27,15 @@

namespace ash {
namespace internal {

namespace {

// The DPI threshold to detect high density screen.
// Higher DPI than this will use device_scale_factor=2.
// Note: This value has to be kept in sync with the mouse/touchpad driver
// which controls mouse pointer acceleration. If you need to update this value,
// please update the bug (crosbug.com/31628) first and make sure that the
// driver will use the same value.
// This value also has to be kept in sync with the value in
// chromeos/display/output_configurator.cc. See crbug.com/130188
const unsigned int kHighDensityDPIThreshold = 160;

// 1 inch in mm.
const float kInchInMm = 25.4f;

XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) {
for (int m = 0; m < screen_resources->nmode; m++) {
XRRModeInfo *mode = &screen_resources->modes[m];
if (mode->id == current_mode)
return mode;
}
return NULL;
}

// A list of bogus sizes in mm that X detects and should be ignored.
// See crbug.com/136533.
const unsigned long kInvalidDisplaySizeList[][2] = {
{40, 30},
{50, 40},
{160, 90},
{160, 100},
};

int64 GetDisplayId(XID output, size_t output_index) {
int64 display_id;
if (chromeos::GetDisplayId(output, output_index, &display_id))
Expand All @@ -69,24 +45,6 @@ int64 GetDisplayId(XID output, size_t output_index) {

} // namespace

bool ShouldIgnoreSize(unsigned long mm_width, unsigned long mm_height) {
// Ignore if the reported display is smaller than minimum size.
if (mm_width <= kInvalidDisplaySizeList[0][0] ||
mm_height <= kInvalidDisplaySizeList[0][1]) {
LOG(WARNING) << "Smaller than minimum display size";
return true;
}
for (unsigned long i = 1 ; i < arraysize(kInvalidDisplaySizeList); ++i) {
const unsigned long* size = kInvalidDisplaySizeList[i];
if (mm_width == size[0] && mm_height == size[1]) {
LOG(WARNING) << "Black listed display size detected:"
<< size[0] << "x" << size[1];
return true;
}
}
return false;
}

DisplayChangeObserverX11::DisplayChangeObserverX11()
: xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)),
Expand Down Expand Up @@ -116,6 +74,21 @@ chromeos::OutputState DisplayChangeObserverX11::GetStateForDisplayIds(
chromeos::STATE_DUAL_MIRROR : chromeos::STATE_DUAL_EXTENDED;
}

bool DisplayChangeObserverX11::GetResolutionForDisplayId(int64 display_id,
int* width,
int* height) const {

gfx::Size resolution;
if (!Shell::GetInstance()->display_manager()->
GetSelectedResolutionForDisplayId(display_id, &resolution)) {
return false;
}

*width = resolution.width();
*height = resolution.height();
return true;
}

void DisplayChangeObserverX11::OnDisplayModeChanged() {
XRRScreenResources* screen_resources =
XRRGetScreenResources(xdisplay_, x_root_window_);
Expand Down Expand Up @@ -151,13 +124,14 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() {
XRRFreeOutputInfo(output_info);
continue;
}
XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc];
const XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc];
if (!crtc_info) {
LOG(WARNING) << "Crtc not found for output: output_index="
<< output_index;
continue;
}
XRRModeInfo* mode = FindMode(screen_resources, crtc_info->mode);
const XRRModeInfo* mode =
chromeos::FindModeInfo(screen_resources, crtc_info->mode);
if (!mode) {
LOG(WARNING) << "Could not find a mode for the output: output_index="
<< output_index;
Expand All @@ -173,6 +147,10 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() {
gfx::Rect display_bounds(
crtc_info->x, crtc_info->y, mode->width, mode->height);

std::vector<Resolution> resolutions;
if (!is_internal)
resolutions = GetResolutionList(screen_resources, output_info);

XRRFreeOutputInfo(output_info);

std::string name = is_internal ?
Expand All @@ -195,6 +173,7 @@ void DisplayChangeObserverX11::OnDisplayModeChanged() {
displays.back().set_device_scale_factor(device_scale_factor);
displays.back().SetBounds(display_bounds);
displays.back().set_native(true);
displays.back().set_resolutions(resolutions);
}

// Free all allocated resources.
Expand Down
9 changes: 3 additions & 6 deletions ash/display/display_change_observer_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class DisplayChangeObserverX11
// chromeos::OutputConfigurator::StateController overrides:
virtual chromeos::OutputState GetStateForDisplayIds(
const std::vector<int64>& outputs) const OVERRIDE;
virtual bool GetResolutionForDisplayId(int64 display_id,
int* width,
int* height) const OVERRIDE;

// Overriden from chromeos::OutputConfigurator::Observer:
virtual void OnDisplayModeChanged() OVERRIDE;
Expand All @@ -48,12 +51,6 @@ class DisplayChangeObserverX11
DISALLOW_COPY_AND_ASSIGN(DisplayChangeObserverX11);
};

// Returns true if the size info in the output_info isn't valid
// and should be ignored. This is exposed for testing.
// |mm_width| and |mm_height| are given in millimeters.
ASH_EXPORT bool ShouldIgnoreSize(unsigned long mm_width,
unsigned long mm_height);

} // namespace internal
} // namespace ash

Expand Down
31 changes: 0 additions & 31 deletions ash/display/display_change_observer_x11_unittest.cc

This file was deleted.

19 changes: 19 additions & 0 deletions ash/display/display_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
namespace ash {
namespace internal {

Resolution::Resolution(const gfx::Size& size, bool interlaced)
: size(size),
interlaced(interlaced) {
}

// satic
DisplayInfo DisplayInfo::CreateFromSpec(const std::string& spec) {
return CreateFromSpecWithID(spec, gfx::Display::kInvalidDisplayID);
Expand Down Expand Up @@ -148,6 +153,7 @@ void DisplayInfo::Copy(const DisplayInfo& native_info) {
bounds_in_pixel_ = native_info.bounds_in_pixel_;
size_in_pixel_ = native_info.size_in_pixel_;
device_scale_factor_ = native_info.device_scale_factor_;
resolutions_ = native_info.resolutions_;

// Copy overscan_insets_in_dip_ if it's not empty. This is for test
// cases which use "/o" annotation which sets the overscan inset
Expand Down Expand Up @@ -214,5 +220,18 @@ std::string DisplayInfo::ToString() const {
ui_scale_);
}

std::string DisplayInfo::ToFullString() const {
std::string resolutions_str;
std::vector<Resolution>::const_iterator iter = resolutions_.begin();
for (; iter != resolutions_.end(); ++iter) {
if (!resolutions_str.empty())
resolutions_str += ",";
resolutions_str += iter->size.ToString();
if (iter->interlaced)
resolutions_str += "(i)";
}
return ToString() + ", resolutions=" + resolutions_str;
}

} // namespace internal
} // namespace ash
27 changes: 26 additions & 1 deletion ash/display/display_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define ASH_DISPLAY_DISPLAY_INFO_H_

#include <string>
#include <vector>

#include "ash/ash_export.h"
#include "base/gtest_prod_util.h"
Expand All @@ -16,6 +17,15 @@
namespace ash {
namespace internal {

// A struct that represents the display's resolution and
// interlaced info.
struct ASH_EXPORT Resolution {
Resolution(const gfx::Size& size, bool interlaced);

gfx::Size size;
bool interlaced;
};

// DisplayInfo contains metadata for each display. This is used to
// create |gfx::Display| as well as to maintain extra infomation
// to manage displays in ash environment.
Expand Down Expand Up @@ -114,9 +124,21 @@ class ASH_EXPORT DisplayInfo {
void set_native(bool native) { native_ = native; }
bool native() const { return native_; }

// Returns a string representation of the DisplayInfo;
const std::vector<Resolution>& resolutions() const {
return resolutions_;
}
void set_resolutions(std::vector<Resolution>& resolution) {
resolutions_.swap(resolution);
}

// Returns a string representation of the DisplayInfo
// excluding resolutions.
std::string ToString() const;

// Returns a string representation of the DisplayInfo
// including resolutions.
std::string ToFullString() const;

private:
int64 id_;
std::string name_;
Expand All @@ -134,6 +156,9 @@ class ASH_EXPORT DisplayInfo {

// True if this comes from native platform (DisplayChangeObserverX11).
bool native_;

// The list of resolutions supported by this display.
std::vector<Resolution> resolutions_;
};

} // namespace internal
Expand Down
28 changes: 27 additions & 1 deletion ash/display/display_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,24 @@ void DisplayManager::SetDisplayUIScale(int64 display_id,
UpdateDisplays(display_info_list);
}

void DisplayManager::SetDisplayResolution(int64 display_id,
const gfx::Size& resolution) {
DCHECK_NE(gfx::Display::InternalDisplayId(), display_id);
if (gfx::Display::InternalDisplayId() == display_id)
return;
resolutions_[display_id] = resolution;
#if defined(OS_CHROMEOS) && defined(USE_X11)
if (base::chromeos::IsRunningOnChromeOS())
Shell::GetInstance()->output_configurator()->ScheduleConfigureOutputs();
#endif
}

void DisplayManager::RegisterDisplayProperty(
int64 display_id,
gfx::Display::Rotation rotation,
float ui_scale,
const gfx::Insets* overscan_insets) {
const gfx::Insets* overscan_insets,
const gfx::Size& resolution_in_pixels) {
if (display_info_.find(display_id) == display_info_.end()) {
display_info_[display_id] =
DisplayInfo(display_id, std::string(""), false);
Expand All @@ -337,6 +350,19 @@ void DisplayManager::RegisterDisplayProperty(
display_info_[display_id].set_ui_scale(ui_scale);
if (overscan_insets)
display_info_[display_id].SetOverscanInsets(*overscan_insets);
if (!resolution_in_pixels.IsEmpty())
resolutions_[display_id] = resolution_in_pixels;
}

bool DisplayManager::GetSelectedResolutionForDisplayId(
int64 id,
gfx::Size* resolution_out) const {
std::map<int64, gfx::Size>::const_iterator iter =
resolutions_.find(id);
if (iter == resolutions_.end())
return false;
*resolution_out = iter->second;
return true;
}

bool DisplayManager::IsDisplayRotationEnabled() const {
Expand Down
13 changes: 12 additions & 1 deletion ash/display/display_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,20 @@ class ASH_EXPORT DisplayManager
// Sets the display's ui scale.
void SetDisplayUIScale(int64 display_id, float ui_scale);

// Sets the display's resolution.
void SetDisplayResolution(int64 display_id, const gfx::Size& resolution);

// Register per display properties. |overscan_insets| is NULL if
// the display has no custom overscan insets.
void RegisterDisplayProperty(int64 display_id,
gfx::Display::Rotation rotation,
float ui_scale,
const gfx::Insets* overscan_insets);
const gfx::Insets* overscan_insets,
const gfx::Size& resolution_in_pixels);

// Returns the display's selected resolution.
bool GetSelectedResolutionForDisplayId(int64 display_id,
gfx::Size* resolution_out) const;

// Tells if display rotation/ui scaling features are enabled.
bool IsDisplayRotationEnabled() const;
Expand Down Expand Up @@ -270,6 +278,9 @@ class ASH_EXPORT DisplayManager
// The mapping from the display ID to its internal data.
std::map<int64, DisplayInfo> display_info_;

// Selected resolutions for displays. Key is the displays' ID.
std::map<int64, gfx::Size> resolutions_;

// When set to true, the host window's resize event updates
// the display's size. This is set to true when running on
// desktop environment (for debugging) so that resizing the host
Expand Down
Loading

0 comments on commit a5792d3

Please sign in to comment.