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