display_util_x11.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/display/display_util_x11.h"
6
7#include <algorithm>
8#include <map>
9#include <X11/extensions/Xrandr.h>
10
11#include "ash/display/display_info.h"
12#include "base/logging.h"
13#include "chromeos/display/output_util.h"
14
15namespace ash {
16namespace internal {
17namespace {
18
19// A list of bogus sizes in mm that X detects that should be ignored.
20// See crbug.com/136533. The first element maintains the minimum
21// size required to be valid size.
22const unsigned long kInvalidDisplaySizeList[][2] = {
23  {40, 30},
24  {50, 40},
25  {160, 90},
26  {160, 100},
27};
28
29// Resolution list are sorted by the area in pixels and the larger
30// one comes first.
31struct ResolutionSorter {
32  bool operator()(const Resolution& a, const Resolution& b) {
33    return a.size.width() * a.size.height() > b.size.width() * b.size.height();
34  }
35};
36
37}  // namespace
38
39bool ShouldIgnoreSize(unsigned long mm_width, unsigned long mm_height) {
40  // Ignore if the reported display is smaller than minimum size.
41  if (mm_width <= kInvalidDisplaySizeList[0][0] ||
42      mm_height <= kInvalidDisplaySizeList[0][1]) {
43    LOG(WARNING) << "Smaller than minimum display size";
44    return true;
45  }
46  for (unsigned long i = 1 ; i < arraysize(kInvalidDisplaySizeList); ++i) {
47    const unsigned long* size = kInvalidDisplaySizeList[i];
48    if (mm_width == size[0] && mm_height == size[1]) {
49      LOG(WARNING) << "Black listed display size detected:"
50                   << size[0] << "x" << size[1];
51      return true;
52    }
53  }
54  return false;
55}
56
57std::vector<Resolution> GetResolutionList(
58    XRRScreenResources* screen_resources,
59    XRROutputInfo* output_info) {
60  typedef std::map<std::pair<int,int>, Resolution> ResolutionMap;
61
62  ResolutionMap resolution_map;
63
64  for (int i = 0; i < output_info->nmode; i++) {
65    RRMode mode = output_info->modes[i];
66    const XRRModeInfo* info = chromeos::FindModeInfo(screen_resources, mode);
67    DCHECK(info);
68    // Just ignore bad entry on Release build.
69    if (!info)
70      continue;
71    ResolutionMap::key_type size = std::make_pair(info->width, info->height);
72    bool interlaced = (info->modeFlags & RR_Interlace) != 0;
73
74    ResolutionMap::iterator iter = resolution_map.find(size);
75
76    // Add new resolution if it's new size or override interlaced mode.
77    if (iter == resolution_map.end()) {
78      resolution_map.insert(ResolutionMap::value_type(
79          size,
80          Resolution(gfx::Size(info->width, info->height), interlaced)));
81    } else if (iter->second.interlaced && !interlaced) {
82      iter->second.interlaced = false;
83    }
84  }
85
86  std::vector<Resolution> resolution_list;
87  for (ResolutionMap::const_iterator iter = resolution_map.begin();
88       iter != resolution_map.end();
89       ++iter) {
90    resolution_list.push_back(iter->second);
91  }
92  std::sort(resolution_list.begin(), resolution_list.end(), ResolutionSorter());
93  return resolution_list;
94}
95
96}  // namespace internal
97}  // namespace ash
98