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