| OLD | NEW |
| 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 Loading... |
| 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 |
| OLD | NEW |