Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: ash/display/display_change_observer_x11.cc

Issue 21297003: Add ability to set resolution on external display (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: adraddressed comment, adjusted test Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/display/display_change_observer_x11.h" 5 #include "ash/display/display_change_observer_x11.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <vector> 10 #include <vector>
11 11
12 #include <X11/extensions/Xrandr.h> 12 #include <X11/extensions/Xrandr.h>
13 13
14 #include "ash/ash_switches.h" 14 #include "ash/ash_switches.h"
15 #include "ash/display/display_info.h" 15 #include "ash/display/display_info.h"
16 #include "ash/display/display_layout_store.h" 16 #include "ash/display/display_layout_store.h"
17 #include "ash/display/display_manager.h" 17 #include "ash/display/display_manager.h"
18 #include "ash/display/display_util_x11.h"
18 #include "ash/shell.h" 19 #include "ash/shell.h"
19 #include "base/command_line.h" 20 #include "base/command_line.h"
20 #include "base/message_loop/message_pump_aurax11.h" 21 #include "base/message_loop/message_pump_aurax11.h"
21 #include "chromeos/display/output_util.h" 22 #include "chromeos/display/output_util.h"
22 #include "grit/ash_strings.h" 23 #include "grit/ash_strings.h"
23 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/compositor/dip_util.h" 25 #include "ui/compositor/dip_util.h"
25 #include "ui/gfx/display.h" 26 #include "ui/gfx/display.h"
26 27
27 namespace ash { 28 namespace ash {
28 namespace internal { 29 namespace internal {
29
30 namespace { 30 namespace {
31 31
32 // The DPI threshold to detect high density screen. 32 // The DPI threshold to detect high density screen.
33 // Higher DPI than this will use device_scale_factor=2. 33 // Higher DPI than this will use device_scale_factor=2.
34 // Note: This value has to be kept in sync with the mouse/touchpad driver
35 // which controls mouse pointer acceleration. If you need to update this value,
36 // please update the bug (crosbug.com/31628) first and make sure that the
37 // driver will use the same value.
38 // This value also has to be kept in sync with the value in
39 // chromeos/display/output_configurator.cc. See crbug.com/130188
40 const unsigned int kHighDensityDPIThreshold = 160; 34 const unsigned int kHighDensityDPIThreshold = 160;
41 35
42 // 1 inch in mm. 36 // 1 inch in mm.
43 const float kInchInMm = 25.4f; 37 const float kInchInMm = 25.4f;
44 38
45 XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) {
46 for (int m = 0; m < screen_resources->nmode; m++) {
47 XRRModeInfo *mode = &screen_resources->modes[m];
48 if (mode->id == current_mode)
49 return mode;
50 }
51 return NULL;
52 }
53
54 // A list of bogus sizes in mm that X detects and should be ignored.
55 // See crbug.com/136533.
56 const unsigned long kInvalidDisplaySizeList[][2] = {
57 {40, 30},
58 {50, 40},
59 {160, 90},
60 {160, 100},
61 };
62
63 int64 GetDisplayId(XID output, size_t output_index) { 39 int64 GetDisplayId(XID output, size_t output_index) {
64 int64 display_id; 40 int64 display_id;
65 if (chromeos::GetDisplayId(output, output_index, &display_id)) 41 if (chromeos::GetDisplayId(output, output_index, &display_id))
66 return display_id; 42 return display_id;
67 return gfx::Display::kInvalidDisplayID; 43 return gfx::Display::kInvalidDisplayID;
68 } 44 }
69 45
70 } // namespace 46 } // namespace
71 47
72 bool ShouldIgnoreSize(unsigned long mm_width, unsigned long mm_height) {
73 // Ignore if the reported display is smaller than minimum size.
74 if (mm_width <= kInvalidDisplaySizeList[0][0] ||
75 mm_height <= kInvalidDisplaySizeList[0][1]) {
76 LOG(WARNING) << "Smaller than minimum display size";
77 return true;
78 }
79 for (unsigned long i = 1 ; i < arraysize(kInvalidDisplaySizeList); ++i) {
80 const unsigned long* size = kInvalidDisplaySizeList[i];
81 if (mm_width == size[0] && mm_height == size[1]) {
82 LOG(WARNING) << "Black listed display size detected:"
83 << size[0] << "x" << size[1];
84 return true;
85 }
86 }
87 return false;
88 }
89
90 DisplayChangeObserverX11::DisplayChangeObserverX11() 48 DisplayChangeObserverX11::DisplayChangeObserverX11()
91 : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), 49 : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()),
92 x_root_window_(DefaultRootWindow(xdisplay_)), 50 x_root_window_(DefaultRootWindow(xdisplay_)),
93 xrandr_event_base_(0) { 51 xrandr_event_base_(0) {
94 int error_base_ignored; 52 int error_base_ignored;
95 XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored); 53 XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);
96 54
97 Shell::GetInstance()->AddShellObserver(this); 55 Shell::GetInstance()->AddShellObserver(this);
98 } 56 }
99 57
100 DisplayChangeObserverX11::~DisplayChangeObserverX11() { 58 DisplayChangeObserverX11::~DisplayChangeObserverX11() {
101 Shell::GetInstance()->RemoveShellObserver(this); 59 Shell::GetInstance()->RemoveShellObserver(this);
102 } 60 }
103 61
104 chromeos::OutputState DisplayChangeObserverX11::GetStateForDisplayIds( 62 chromeos::OutputState DisplayChangeObserverX11::GetStateForDisplayIds(
105 const std::vector<int64>& display_ids) const { 63 const std::vector<int64>& display_ids) const {
106 if (CommandLine::ForCurrentProcess()->HasSwitch( 64 if (CommandLine::ForCurrentProcess()->HasSwitch(
107 switches::kAshForceMirrorMode)) { 65 switches::kAshForceMirrorMode)) {
108 return chromeos::STATE_DUAL_MIRROR; 66 return chromeos::STATE_DUAL_MIRROR;
109 } 67 }
110 68
111 CHECK_EQ(2U, display_ids.size()); 69 CHECK_EQ(2U, display_ids.size());
112 DisplayIdPair pair = std::make_pair(display_ids[0], display_ids[1]); 70 DisplayIdPair pair = std::make_pair(display_ids[0], display_ids[1]);
113 DisplayLayout layout = Shell::GetInstance()->display_manager()-> 71 DisplayLayout layout = Shell::GetInstance()->display_manager()->
114 layout_store()->GetRegisteredDisplayLayout(pair); 72 layout_store()->GetRegisteredDisplayLayout(pair);
115 return layout.mirrored ? 73 return layout.mirrored ?
116 chromeos::STATE_DUAL_MIRROR : chromeos::STATE_DUAL_EXTENDED; 74 chromeos::STATE_DUAL_MIRROR : chromeos::STATE_DUAL_EXTENDED;
117 } 75 }
118 76
77 bool DisplayChangeObserverX11::GetResolutionForDisplayId(int64 display_id,
78 int* width,
79 int* height) const {
80
81 gfx::Size resolution;
82 if (!Shell::GetInstance()->display_manager()->
83 GetSelectedResolutionForDisplayId(display_id, &resolution)) {
84 return false;
85 }
86
87 *width = resolution.width();
88 *height = resolution.height();
89 return true;
90 }
91
119 void DisplayChangeObserverX11::OnDisplayModeChanged() { 92 void DisplayChangeObserverX11::OnDisplayModeChanged() {
120 XRRScreenResources* screen_resources = 93 XRRScreenResources* screen_resources =
121 XRRGetScreenResources(xdisplay_, x_root_window_); 94 XRRGetScreenResources(xdisplay_, x_root_window_);
122 std::map<XID, XRRCrtcInfo*> crtc_info_map; 95 std::map<XID, XRRCrtcInfo*> crtc_info_map;
123 96
124 for (int c = 0; c < screen_resources->ncrtc; c++) { 97 for (int c = 0; c < screen_resources->ncrtc; c++) {
125 XID crtc_id = screen_resources->crtcs[c]; 98 XID crtc_id = screen_resources->crtcs[c];
126 XRRCrtcInfo *crtc_info = 99 XRRCrtcInfo *crtc_info =
127 XRRGetCrtcInfo(xdisplay_, screen_resources, crtc_id); 100 XRRGetCrtcInfo(xdisplay_, screen_resources, crtc_id);
128 crtc_info_map[crtc_id] = crtc_info; 101 crtc_info_map[crtc_id] = crtc_info;
(...skipping 15 matching lines...) Expand all
144 int64 id = GetDisplayId(output, output_index); 117 int64 id = GetDisplayId(output, output_index);
145 // Fallback to output index. crbug.com/180100 118 // Fallback to output index. crbug.com/180100
146 gfx::Display::SetInternalDisplayId( 119 gfx::Display::SetInternalDisplayId(
147 id == gfx::Display::kInvalidDisplayID ? output_index : id); 120 id == gfx::Display::kInvalidDisplayID ? output_index : id);
148 } 121 }
149 122
150 if (output_info->connection != RR_Connected) { 123 if (output_info->connection != RR_Connected) {
151 XRRFreeOutputInfo(output_info); 124 XRRFreeOutputInfo(output_info);
152 continue; 125 continue;
153 } 126 }
154 XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc]; 127 const XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc];
155 if (!crtc_info) { 128 if (!crtc_info) {
156 LOG(WARNING) << "Crtc not found for output: output_index=" 129 LOG(WARNING) << "Crtc not found for output: output_index="
157 << output_index; 130 << output_index;
158 continue; 131 continue;
159 } 132 }
160 XRRModeInfo* mode = FindMode(screen_resources, crtc_info->mode); 133 const XRRModeInfo* mode =
134 chromeos::FindModeInfo(screen_resources, crtc_info->mode);
161 if (!mode) { 135 if (!mode) {
162 LOG(WARNING) << "Could not find a mode for the output: output_index=" 136 LOG(WARNING) << "Could not find a mode for the output: output_index="
163 << output_index; 137 << output_index;
164 continue; 138 continue;
165 } 139 }
166 140
167 float device_scale_factor = 1.0f; 141 float device_scale_factor = 1.0f;
168 if (!ShouldIgnoreSize(output_info->mm_width, output_info->mm_height) && 142 if (!ShouldIgnoreSize(output_info->mm_width, output_info->mm_height) &&
169 (kInchInMm * mode->width / output_info->mm_width) > 143 (kInchInMm * mode->width / output_info->mm_width) >
170 kHighDensityDPIThreshold) { 144 kHighDensityDPIThreshold) {
171 device_scale_factor = 2.0f; 145 device_scale_factor = 2.0f;
172 } 146 }
173 gfx::Rect display_bounds( 147 gfx::Rect display_bounds(
174 crtc_info->x, crtc_info->y, mode->width, mode->height); 148 crtc_info->x, crtc_info->y, mode->width, mode->height);
175 149
150 std::vector<Resolution> resolutions;
151 if (!is_internal)
152 resolutions = GetResolutionList(screen_resources, output_info);
153
176 XRRFreeOutputInfo(output_info); 154 XRRFreeOutputInfo(output_info);
177 155
178 std::string name = is_internal ? 156 std::string name = is_internal ?
179 l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME) : 157 l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME) :
180 chromeos::GetDisplayName(output); 158 chromeos::GetDisplayName(output);
181 if (name.empty()) 159 if (name.empty())
182 name = l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); 160 name = l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
183 161
184 bool has_overscan = false; 162 bool has_overscan = false;
185 chromeos::GetOutputOverscanFlag(output, &has_overscan); 163 chromeos::GetOutputOverscanFlag(output, &has_overscan);
186 164
187 int64 id = GetDisplayId(output, output_index); 165 int64 id = GetDisplayId(output, output_index);
188 166
189 // If ID is invalid or there is an duplicate, just use output index. 167 // If ID is invalid or there is an duplicate, just use output index.
190 if (id == gfx::Display::kInvalidDisplayID || ids.find(id) != ids.end()) 168 if (id == gfx::Display::kInvalidDisplayID || ids.find(id) != ids.end())
191 id = output_index; 169 id = output_index;
192 ids.insert(id); 170 ids.insert(id);
193 171
194 displays.push_back(DisplayInfo(id, name, has_overscan)); 172 displays.push_back(DisplayInfo(id, name, has_overscan));
195 displays.back().set_device_scale_factor(device_scale_factor); 173 displays.back().set_device_scale_factor(device_scale_factor);
196 displays.back().SetBounds(display_bounds); 174 displays.back().SetBounds(display_bounds);
197 displays.back().set_native(true); 175 displays.back().set_native(true);
176 displays.back().set_resolutions(resolutions);
198 } 177 }
199 178
200 // Free all allocated resources. 179 // Free all allocated resources.
201 for (std::map<XID, XRRCrtcInfo*>::const_iterator iter = crtc_info_map.begin(); 180 for (std::map<XID, XRRCrtcInfo*>::const_iterator iter = crtc_info_map.begin();
202 iter != crtc_info_map.end(); ++iter) { 181 iter != crtc_info_map.end(); ++iter) {
203 XRRFreeCrtcInfo(iter->second); 182 XRRFreeCrtcInfo(iter->second);
204 } 183 }
205 XRRFreeScreenResources(screen_resources); 184 XRRFreeScreenResources(screen_resources);
206 185
207 // DisplayManager can be null during the boot. 186 // DisplayManager can be null during the boot.
208 Shell::GetInstance()->display_manager()->OnNativeDisplaysChanged(displays); 187 Shell::GetInstance()->display_manager()->OnNativeDisplaysChanged(displays);
209 } 188 }
210 189
211 void DisplayChangeObserverX11::OnAppTerminating() { 190 void DisplayChangeObserverX11::OnAppTerminating() {
212 #if defined(USE_ASH) 191 #if defined(USE_ASH)
213 // Stop handling display configuration events once the shutdown 192 // Stop handling display configuration events once the shutdown
214 // process starts. crbug.com/177014. 193 // process starts. crbug.com/177014.
215 Shell::GetInstance()->output_configurator()->Stop(); 194 Shell::GetInstance()->output_configurator()->Stop();
216 #endif 195 #endif
217 } 196 }
218 197
219 } // namespace internal 198 } // namespace internal
220 } // namespace ash 199 } // namespace ash
OLDNEW
« no previous file with comments | « ash/display/display_change_observer_x11.h ('k') | ash/display/display_change_observer_x11_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698