display_manager.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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
3// found in the LICENSE file.
4
5#include "ash/display/display_manager.h"
6
7#include <set>
8#include <string>
9#include <vector>
10
11#include "ash/ash_switches.h"
12#include "ash/display/display_controller.h"
13#include "ash/screen_ash.h"
14#include "ash/shell.h"
15#include "base/command_line.h"
16#include "base/logging.h"
17#include "base/stl_util.h"
18#include "base/string_number_conversions.h"
19#include "base/stringprintf.h"
20#include "base/strings/string_split.h"
21#include "base/utf_string_conversions.h"
22#include "grit/ash_strings.h"
23#include "ui/aura/client/screen_position_client.h"
24#include "ui/aura/env.h"
25#include "ui/aura/root_window.h"
26#include "ui/aura/root_window_host.h"
27#include "ui/aura/window_property.h"
28#include "ui/base/l10n/l10n_util.h"
29#include "ui/gfx/display.h"
30#include "ui/gfx/rect.h"
31#include "ui/gfx/screen.h"
32#include "ui/gfx/size_conversions.h"
33
34#if defined(USE_X11)
35#include "ui/base/x/x11_util.h"
36#endif
37
38#if defined(OS_CHROMEOS)
39#include "base/chromeos/chromeos_version.h"
40#include "chromeos/display/output_configurator.h"
41#endif
42
43#if defined(OS_WIN)
44#include "base/win/windows_version.h"
45#include "ui/aura/remote_root_window_host_win.h"
46#endif
47
48DECLARE_WINDOW_PROPERTY_TYPE(int64);
49
50namespace ash {
51namespace internal {
52typedef std::vector<gfx::Display> DisplayList;
53typedef std::vector<DisplayInfo> DisplayInfoList;
54
55namespace {
56
57// List of value UI Scale values. These scales are equivalent to 1024,
58// 1280, 1600 and 1920 pixel width respectively on 2560 pixel width 2x
59// density display.
60const float kUIScales[] = {0.8f, 1.0f, 1.25f, 1.5f};
61const size_t kUIScaleTableSize = arraysize(kUIScales);
62
63struct DisplaySortFunctor {
64  bool operator()(const gfx::Display& a, const gfx::Display& b) {
65    return a.id() < b.id();
66  }
67};
68
69struct DisplayInfoSortFunctor {
70  bool operator()(const DisplayInfo& a, const DisplayInfo& b) {
71    return a.id() < b.id();
72  }
73};
74
75gfx::Display& GetInvalidDisplay() {
76  static gfx::Display* invalid_display = new gfx::Display();
77  return *invalid_display;
78}
79
80bool IsValidUIScale(float scale) {
81  for (size_t i = 0; i < kUIScaleTableSize; ++i) {
82    if (kUIScales[i] == scale)
83      return true;
84  }
85  return false;
86}
87
88}  // namespace
89
90using aura::RootWindow;
91using aura::Window;
92using std::string;
93using std::vector;
94
95DEFINE_WINDOW_PROPERTY_KEY(int64, kDisplayIdKey,
96                           gfx::Display::kInvalidDisplayID);
97
98DisplayManager::DisplayManager()
99    : first_display_id_(gfx::Display::kInvalidDisplayID),
100      mirrored_display_id_(gfx::Display::kInvalidDisplayID),
101      num_connected_displays_(0),
102      force_bounds_changed_(false),
103      change_display_upon_host_resize_(false) {
104#if defined(OS_CHROMEOS)
105  change_display_upon_host_resize_ = !base::chromeos::IsRunningOnChromeOS();
106#endif
107  Init();
108}
109
110DisplayManager::~DisplayManager() {
111}
112
113// static
114void DisplayManager::CycleDisplay() {
115  Shell::GetInstance()->display_manager()->CycleDisplayImpl();
116}
117
118// static
119void DisplayManager::ToggleDisplayScaleFactor() {
120  Shell::GetInstance()->display_manager()->ScaleDisplayImpl();
121}
122
123// static
124float DisplayManager::GetNextUIScale(float scale, bool up) {
125  for (size_t i = 0; i < kUIScaleTableSize; ++i) {
126    if (kUIScales[i] == scale) {
127      if (up && i != kUIScaleTableSize -1)
128        return kUIScales[i + 1];
129      if (!up && i != 0)
130        return kUIScales[i - 1];
131      return kUIScales[i];
132    }
133  }
134  // Fallback to 1.0f if the |scale| wasn't in the list.
135  return 1.0f;
136}
137
138bool DisplayManager::IsActiveDisplay(const gfx::Display& display) const {
139  for (DisplayList::const_iterator iter = displays_.begin();
140       iter != displays_.end(); ++iter) {
141    if ((*iter).id() == display.id())
142      return true;
143  }
144  return false;
145}
146
147bool DisplayManager::HasInternalDisplay() const {
148  return gfx::Display::InternalDisplayId() != gfx::Display::kInvalidDisplayID;
149}
150
151bool DisplayManager::IsInternalDisplayId(int64 id) const {
152  return gfx::Display::InternalDisplayId() == id;
153}
154
155bool DisplayManager::UpdateWorkAreaOfDisplayNearestWindow(
156    const aura::Window* window,
157    const gfx::Insets& insets) {
158  const RootWindow* root = window->GetRootWindow();
159  gfx::Display& display = FindDisplayForRootWindow(root);
160  gfx::Rect old_work_area = display.work_area();
161  display.UpdateWorkAreaFromInsets(insets);
162  return old_work_area != display.work_area();
163}
164
165const gfx::Display& DisplayManager::GetDisplayForId(int64 id) const {
166  return const_cast<DisplayManager*>(this)->FindDisplayForId(id);
167}
168
169const gfx::Display& DisplayManager::FindDisplayContainingPoint(
170    const gfx::Point& point_in_screen) const {
171  for (DisplayList::const_iterator iter = displays_.begin();
172       iter != displays_.end(); ++iter) {
173    const gfx::Display& display = *iter;
174    if (display.bounds().Contains(point_in_screen))
175      return display;
176  }
177  return GetInvalidDisplay();
178}
179
180void DisplayManager::SetOverscanInsets(int64 display_id,
181                                       const gfx::Insets& insets_in_dip) {
182  // TODO(oshima): insets has to be rotated according to the
183  // the current display rotation.
184  display_info_[display_id].SetOverscanInsets(true, insets_in_dip);
185  DisplayInfoList display_info_list;
186  for (DisplayList::const_iterator iter = displays_.begin();
187       iter != displays_.end(); ++iter) {
188    display_info_list.push_back(GetDisplayInfo(iter->id()));
189  }
190  UpdateDisplays(display_info_list);
191}
192
193void DisplayManager::ClearCustomOverscanInsets(int64 display_id) {
194  display_info_[display_id].clear_has_custom_overscan_insets();
195  DisplayInfoList display_info_list;
196  for (DisplayList::const_iterator iter = displays_.begin();
197       iter != displays_.end(); ++iter) {
198    display_info_list.push_back(GetDisplayInfo(iter->id()));
199  }
200  UpdateDisplays(display_info_list);
201}
202
203void DisplayManager::SetDisplayRotation(int64 display_id,
204                                        gfx::Display::Rotation rotation) {
205  if (!IsDisplayRotationEnabled())
206    return;
207  DisplayInfoList display_info_list;
208  for (DisplayList::const_iterator iter = displays_.begin();
209       iter != displays_.end(); ++iter) {
210    DisplayInfo info = GetDisplayInfo(iter->id());
211    if (info.id() == display_id) {
212      if (info.rotation() == rotation)
213        return;
214      info.set_rotation(rotation);
215    }
216    display_info_list.push_back(info);
217  }
218  UpdateDisplays(display_info_list);
219}
220
221void DisplayManager::SetDisplayUIScale(int64 display_id,
222                                       float ui_scale) {
223  if (!IsDisplayUIScalingEnabled() || !IsValidUIScale(ui_scale))
224    return;
225
226  DisplayInfoList display_info_list;
227  for (DisplayList::const_iterator iter = displays_.begin();
228       iter != displays_.end(); ++iter) {
229    DisplayInfo info = GetDisplayInfo(iter->id());
230    if (info.id() == display_id) {
231      if (info.ui_scale() == ui_scale)
232        return;
233      info.set_ui_scale(ui_scale);
234    }
235    display_info_list.push_back(info);
236  }
237  UpdateDisplays(display_info_list);
238}
239
240void DisplayManager::RegisterDisplayProperty(
241    int64 display_id,
242    gfx::Display::Rotation rotation,
243    float ui_scale,
244    const gfx::Insets* overscan_insets) {
245  if (display_info_.find(display_id) == display_info_.end()) {
246    display_info_[display_id] =
247        DisplayInfo(display_id, std::string(""), false);
248  }
249
250  display_info_[display_id].set_rotation(rotation);
251  if (IsValidUIScale(ui_scale))
252    display_info_[display_id].set_ui_scale(ui_scale);
253  if (overscan_insets)
254    display_info_[display_id].SetOverscanInsets(true, *overscan_insets);
255}
256
257bool DisplayManager::IsDisplayRotationEnabled() const {
258  static bool enabled = !CommandLine::ForCurrentProcess()->
259      HasSwitch(switches::kAshDisableDisplayRotation);
260  return enabled;
261}
262
263bool DisplayManager::IsDisplayUIScalingEnabled() const {
264  static bool enabled = !CommandLine::ForCurrentProcess()->
265      HasSwitch(switches::kAshDisableUIScaling);
266  if (!enabled)
267    return false;
268  // UI Scaling is effective only when the internal display has
269  // 2x density (currently Pixel).
270  int64 display_id = gfx::Display::InternalDisplayId();
271#if defined(OS_CHROMEOS)
272  // On linux desktop, allow ui scaling on the first dislpay if an internal
273  // display isn't specified.
274  if (display_id == gfx::Display::kInvalidDisplayID &&
275      !base::chromeos::IsRunningOnChromeOS()) {
276    display_id = Shell::GetInstance()->display_manager()->first_display_id();
277  }
278#endif
279  return GetDisplayForId(display_id).device_scale_factor() == 2.0f;
280}
281
282gfx::Insets DisplayManager::GetOverscanInsets(int64 display_id) const {
283  std::map<int64, DisplayInfo>::const_iterator it =
284      display_info_.find(display_id);
285  return (it != display_info_.end()) ?
286      it->second.overscan_insets_in_dip() : gfx::Insets();
287}
288
289void DisplayManager::OnNativeDisplaysChanged(
290    const std::vector<DisplayInfo>& updated_displays) {
291  if (updated_displays.empty()) {
292    // Don't update the displays when all displays are disconnected.
293    // This happens when:
294    // - the device is idle and powerd requested to turn off all displays.
295    // - the device is suspended. (kernel turns off all displays)
296    // - the internal display's brightness is set to 0 and no external
297    //   display is connected.
298    // - the internal display's brightness is 0 and external display is
299    //   disconnected.
300    // The display will be updated when one of displays is turned on, and the
301    // display list will be updated correctly.
302    return;
303  }
304  first_display_id_ = updated_displays[0].id();
305  std::set<int> y_coords;
306  bool internal_display_connected = false;
307  num_connected_displays_ = updated_displays.size();
308  mirrored_display_id_ = gfx::Display::kInvalidDisplayID;
309  DisplayInfoList new_display_info_list;
310  for (DisplayInfoList::const_iterator iter = updated_displays.begin();
311       iter != updated_displays.end();
312       ++iter) {
313    if (!internal_display_connected) {
314      internal_display_connected = IsInternalDisplayId(iter->id());
315      if (internal_display_connected)
316        internal_display_info_.reset(new DisplayInfo(*iter));
317    }
318    // Mirrored monitors have the same y coordinates.
319    int y = iter->bounds_in_pixel().y();
320    if (y_coords.find(y) != y_coords.end()) {
321      InsertAndUpdateDisplayInfo(*iter);
322      mirrored_display_id_ = iter->id();
323    } else {
324      y_coords.insert(y);
325      new_display_info_list.push_back(*iter);
326    }
327  }
328  if (HasInternalDisplay() && !internal_display_connected) {
329    if (!internal_display_info_.get()) {
330      // TODO(oshima): Get has_custom value.
331      internal_display_info_.reset(new DisplayInfo(
332          gfx::Display::InternalDisplayId(),
333          l10n_util::GetStringUTF8(IDS_ASH_INTERNAL_DISPLAY_NAME),
334          false));
335      internal_display_info_->SetBounds(gfx::Rect(0, 0, 800, 600));
336    }
337    new_display_info_list.push_back(*internal_display_info_.get());
338    // An internal display is always considered *connected*.
339    num_connected_displays_++;
340  }
341  UpdateDisplays(new_display_info_list);
342}
343
344void DisplayManager::UpdateDisplays() {
345  DisplayInfoList display_info_list;
346  for (DisplayList::const_iterator iter = displays_.begin();
347       iter != displays_.end(); ++iter) {
348    display_info_list.push_back(GetDisplayInfo(iter->id()));
349  }
350  UpdateDisplays(display_info_list);
351}
352
353void DisplayManager::UpdateDisplays(
354    const std::vector<DisplayInfo>& updated_display_info_list) {
355  DisplayInfoList new_display_info_list = updated_display_info_list;
356  std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor());
357  std::sort(new_display_info_list.begin(),
358            new_display_info_list.end(),
359            DisplayInfoSortFunctor());
360  DisplayList removed_displays;
361  std::vector<size_t> changed_display_indices;
362  std::vector<size_t> added_display_indices;
363  gfx::Display current_primary;
364  if (DisplayController::HasPrimaryDisplay())
365    current_primary = DisplayController::GetPrimaryDisplay();
366
367  DisplayList::iterator curr_iter = displays_.begin();
368  DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin();
369
370  DisplayList new_displays;
371  while (curr_iter != displays_.end() ||
372         new_info_iter != new_display_info_list.end()) {
373    if (curr_iter == displays_.end()) {
374      // more displays in new list.
375      added_display_indices.push_back(new_displays.size());
376      InsertAndUpdateDisplayInfo(*new_info_iter);
377      new_displays.push_back(
378          CreateDisplayFromDisplayInfoById(new_info_iter->id()));
379      ++new_info_iter;
380    } else if (new_info_iter == new_display_info_list.end()) {
381      // more displays in current list.
382      removed_displays.push_back(*curr_iter);
383      ++curr_iter;
384    } else if (curr_iter->id() == new_info_iter->id()) {
385      const gfx::Display& current_display = *curr_iter;
386      // Copy the info because |CreateDisplayFromInfo| updates the instance.
387      const DisplayInfo current_display_info =
388          GetDisplayInfo(current_display.id());
389      InsertAndUpdateDisplayInfo(*new_info_iter);
390      gfx::Display new_display =
391          CreateDisplayFromDisplayInfoById(new_info_iter->id());
392      const DisplayInfo& new_display_info = GetDisplayInfo(new_display.id());
393      // TODO(oshima): Rotating square dislay doesn't work as the size
394      // won't change. This doesn't cause a problem now as there is no
395      // such display. This will be fixed by comparing the rotation as
396      // well when the rotation variable is added to gfx::Display.
397      if (force_bounds_changed_ ||
398          (current_display_info.bounds_in_pixel() !=
399           new_display_info.bounds_in_pixel()) ||
400          (current_display.device_scale_factor() !=
401           new_display.device_scale_factor()) ||
402          (current_display_info.size_in_pixel() !=
403           new_display.GetSizeInPixel())) {
404        changed_display_indices.push_back(new_displays.size());
405      }
406
407      new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets());
408      new_displays.push_back(new_display);
409      ++curr_iter;
410      ++new_info_iter;
411    } else if (curr_iter->id() < new_info_iter->id()) {
412      // more displays in current list between ids, which means it is deleted.
413      removed_displays.push_back(*curr_iter);
414      ++curr_iter;
415    } else {
416      // more displays in new list between ids, which means it is added.
417      added_display_indices.push_back(new_displays.size());
418      InsertAndUpdateDisplayInfo(*new_info_iter);
419      new_displays.push_back(
420          CreateDisplayFromDisplayInfoById(new_info_iter->id()));
421      ++new_info_iter;
422    }
423  }
424
425  // Do not update |displays_| if there's nothing to be updated. Without this,
426  // it will not update the display layout, which causes the bug
427  // http://crbug.com/155948.
428  if (changed_display_indices.empty() && added_display_indices.empty() &&
429      removed_displays.empty()) {
430    return;
431  }
432
433  displays_ = new_displays;
434
435  // Temporarily add displays to be removed because display object
436  // being removed are accessed during shutting down the root.
437  displays_.insert(displays_.end(), removed_displays.begin(),
438                   removed_displays.end());
439  DisplayController* display_controller =
440      Shell::GetInstance()->display_controller();
441  // |display_controller| is NULL during the bootstrap.
442  if (display_controller)
443    display_controller->NotifyDisplayConfigurationChanging();
444
445  for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin();
446       iter != removed_displays.rend(); ++iter) {
447    Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back());
448    displays_.pop_back();
449  }
450  for (std::vector<size_t>::iterator iter = added_display_indices.begin();
451       iter != added_display_indices.end(); ++iter) {
452    Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]);
453  }
454  for (std::vector<size_t>::iterator iter = changed_display_indices.begin();
455       iter != changed_display_indices.end(); ++iter) {
456    Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]);
457  }
458  if (display_controller)
459    display_controller->NotifyDisplayConfigurationChanged();
460
461  EnsurePointerInDisplays();
462#if defined(USE_X11) && defined(OS_CHROMEOS)
463  if (!changed_display_indices.empty() && base::chromeos::IsRunningOnChromeOS())
464    ui::ClearX11DefaultRootWindow();
465#endif
466}
467
468gfx::Display* DisplayManager::GetDisplayAt(size_t index) {
469  return index < displays_.size() ? &displays_[index] : NULL;
470}
471
472const gfx::Display* DisplayManager::GetPrimaryDisplayCandidate() const {
473  const gfx::Display* primary_candidate = &displays_[0];
474#if defined(OS_CHROMEOS)
475  if (base::chromeos::IsRunningOnChromeOS()) {
476    // On ChromeOS device, root windows are stacked vertically, and
477    // default primary is the one on top.
478    int count = GetNumDisplays();
479    int y = GetDisplayInfo(primary_candidate->id()).bounds_in_pixel().y();
480    for (int i = 1; i < count; ++i) {
481      const gfx::Display* display = &displays_[i];
482      const DisplayInfo& display_info = GetDisplayInfo(display->id());
483      if (display->IsInternal()) {
484        primary_candidate = display;
485        break;
486      } else if (display_info.bounds_in_pixel().y() < y) {
487        primary_candidate = display;
488        y = display_info.bounds_in_pixel().y();
489      }
490    }
491  }
492#endif
493  return primary_candidate;
494}
495
496size_t DisplayManager::GetNumDisplays() const {
497  return displays_.size();
498}
499
500bool DisplayManager::IsMirrored() const {
501  return mirrored_display_id_ != gfx::Display::kInvalidDisplayID;
502}
503
504const gfx::Display& DisplayManager::GetDisplayNearestWindow(
505    const Window* window) const {
506  if (!window)
507    return DisplayController::GetPrimaryDisplay();
508  const RootWindow* root = window->GetRootWindow();
509  DisplayManager* manager = const_cast<DisplayManager*>(this);
510  return root ?
511      manager->FindDisplayForRootWindow(root) :
512      DisplayController::GetPrimaryDisplay();
513}
514
515const gfx::Display& DisplayManager::GetDisplayNearestPoint(
516    const gfx::Point& point) const {
517  // Fallback to the primary display if there is no root display containing
518  // the |point|.
519  const gfx::Display& display = FindDisplayContainingPoint(point);
520  return display.is_valid() ? display : DisplayController::GetPrimaryDisplay();
521}
522
523const gfx::Display& DisplayManager::GetDisplayMatching(
524    const gfx::Rect& rect) const {
525  if (rect.IsEmpty())
526    return GetDisplayNearestPoint(rect.origin());
527
528  int max = 0;
529  const gfx::Display* matching = 0;
530  for (std::vector<gfx::Display>::const_iterator iter = displays_.begin();
531       iter != displays_.end(); ++iter) {
532    const gfx::Display& display = *iter;
533    gfx::Rect intersect = gfx::IntersectRects(display.bounds(), rect);
534    int area = intersect.width() * intersect.height();
535    if (area > max) {
536      max = area;
537      matching = &(*iter);
538    }
539  }
540  // Fallback to the primary display if there is no matching display.
541  return matching ? *matching : DisplayController::GetPrimaryDisplay();
542}
543
544const DisplayInfo& DisplayManager::GetDisplayInfo(int64 display_id) const {
545  std::map<int64, DisplayInfo>::const_iterator iter =
546      display_info_.find(display_id);
547  CHECK(iter != display_info_.end());
548  return iter->second;
549}
550
551std::string DisplayManager::GetDisplayNameForId(int64 id) {
552  if (id == gfx::Display::kInvalidDisplayID)
553    return l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME);
554
555  std::map<int64, DisplayInfo>::const_iterator iter = display_info_.find(id);
556  if (iter != display_info_.end() && !iter->second.name().empty())
557    return iter->second.name();
558
559  return base::StringPrintf("Display %d", static_cast<int>(id));
560}
561
562void DisplayManager::OnRootWindowResized(const aura::RootWindow* root,
563                                         const gfx::Size& old_size) {
564  if (change_display_upon_host_resize_) {
565    gfx::Display& display = FindDisplayForRootWindow(root);
566    gfx::Size old_display_size_in_pixel = display.GetSizeInPixel();
567    display_info_[display.id()].SetBounds(
568        gfx::Rect(root->GetHostOrigin(), root->GetHostSize()));
569    const gfx::Size& new_root_size = root->bounds().size();
570    if (old_size != new_root_size) {
571      display.SetSize(display_info_[display.id()].size_in_pixel());
572      Shell::GetInstance()->screen()->NotifyBoundsChanged(display);
573    }
574  }
575}
576
577void DisplayManager::Init() {
578  // TODO(oshima): Move this logic to DisplayChangeObserver.
579  const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
580      switches::kAshHostWindowBounds);
581  vector<string> parts;
582  base::SplitString(size_str, ',', &parts);
583  for (vector<string>::const_iterator iter = parts.begin();
584       iter != parts.end(); ++iter) {
585    AddDisplayFromSpec(*iter);
586  }
587  if (displays_.empty())
588    AddDisplayFromSpec(std::string() /* default */);
589  first_display_id_ = displays_[0].id();
590  num_connected_displays_ = displays_.size();
591}
592
593void DisplayManager::CycleDisplayImpl() {
594  DCHECK(!displays_.empty());
595  std::vector<DisplayInfo> new_display_info_list;
596  new_display_info_list.push_back(
597      GetDisplayInfo(DisplayController::GetPrimaryDisplay().id()));
598  // Add if there is only one display.
599  if (displays_.size() == 1) {
600    // Layout the 2nd display below the primary as with the real device.
601    aura::RootWindow* primary = Shell::GetPrimaryRootWindow();
602    gfx::Rect host_bounds =
603        gfx::Rect(primary->GetHostOrigin(),  primary->GetHostSize());
604    new_display_info_list.push_back(DisplayInfo::CreateFromSpec(
605        base::StringPrintf(
606            "%d+%d-500x400", host_bounds.x(), host_bounds.bottom())));
607  }
608  num_connected_displays_ = new_display_info_list.size();
609  UpdateDisplays(new_display_info_list);
610}
611
612void DisplayManager::ScaleDisplayImpl() {
613  DCHECK(!displays_.empty());
614  std::vector<DisplayInfo> new_display_info_list;
615  for (DisplayList::const_iterator iter = displays_.begin();
616       iter != displays_.end(); ++iter) {
617    DisplayInfo display_info = GetDisplayInfo(iter->id());
618    display_info.set_device_scale_factor(
619        display_info.device_scale_factor() == 1.0f ? 2.0f : 1.0f);
620    new_display_info_list.push_back(display_info);
621  }
622  UpdateDisplays(new_display_info_list);
623}
624
625gfx::Display& DisplayManager::FindDisplayForRootWindow(
626    const aura::RootWindow* root_window) {
627  int64 id = root_window->GetProperty(kDisplayIdKey);
628  // if id is |kInvaildDisplayID|, it's being deleted.
629  DCHECK(id != gfx::Display::kInvalidDisplayID);
630  gfx::Display& display = FindDisplayForId(id);
631  DCHECK(display.is_valid());
632  return display;
633}
634
635gfx::Display& DisplayManager::FindDisplayForId(int64 id) {
636  for (DisplayList::iterator iter = displays_.begin();
637       iter != displays_.end(); ++iter) {
638    if ((*iter).id() == id)
639      return *iter;
640  }
641  DLOG(WARNING) << "Could not find display:" << id;
642  return GetInvalidDisplay();
643}
644
645void DisplayManager::AddDisplayFromSpec(const std::string& spec) {
646  DisplayInfo display_info = DisplayInfo::CreateFromSpec(spec);
647  InsertAndUpdateDisplayInfo(display_info);
648  gfx::Display display = CreateDisplayFromDisplayInfoById(display_info.id());
649  displays_.push_back(display);
650}
651
652void DisplayManager::EnsurePointerInDisplays() {
653  // Don't try to move the pointer during the boot/startup.
654  if (!DisplayController::HasPrimaryDisplay())
655    return;
656  gfx::Point location_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
657  gfx::Point target_location;
658  int64 closest_distance_squared = -1;
659
660  for (DisplayList::const_iterator iter = displays_.begin();
661       iter != displays_.end(); ++iter) {
662    const gfx::Rect& display_bounds = iter->bounds();
663
664    if (display_bounds.Contains(location_in_screen)) {
665      target_location = location_in_screen;
666      break;
667    }
668    gfx::Point center = display_bounds.CenterPoint();
669    // Use the distance squared from the center of the dislay. This is not
670    // exactly "closest" display, but good enough to pick one
671    // appropriate (and there are at most two displays).
672    // We don't care about actual distance, only relative to other displays, so
673    // using the LengthSquared() is cheaper than Length().
674    int64 distance_squared = (center - location_in_screen).LengthSquared();
675    if (closest_distance_squared < 0 ||
676        closest_distance_squared > distance_squared) {
677      target_location = center;
678      closest_distance_squared = distance_squared;
679    }
680  }
681
682  aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
683  aura::client::ScreenPositionClient* client =
684      aura::client::GetScreenPositionClient(root_window);
685  client->ConvertPointFromScreen(root_window, &target_location);
686
687  root_window->MoveCursorTo(target_location);
688}
689
690void DisplayManager::InsertAndUpdateDisplayInfo(const DisplayInfo& new_info) {
691  std::map<int64, DisplayInfo>::iterator info =
692      display_info_.find(new_info.id());
693  if (info != display_info_.end())
694    info->second.Copy(new_info);
695  else {
696    display_info_[new_info.id()] = new_info;
697    display_info_[new_info.id()].set_native(false);
698  }
699  bool on_chromeos = false;
700#if defined(OS_CHROMEOS)
701  on_chromeos = base::chromeos::IsRunningOnChromeOS();
702#endif
703  CommandLine* command_line = CommandLine::ForCurrentProcess();
704  if ((new_info.id() == gfx::Display::InternalDisplayId() || !on_chromeos) &&
705      command_line->HasSwitch(switches::kAshInternalDisplayUIScale)) {
706    double scale_in_double = 1.0;
707    std::string value = CommandLine::ForCurrentProcess()->
708        GetSwitchValueASCII(switches::kAshInternalDisplayUIScale);
709    if (!base::StringToDouble(value, &scale_in_double))
710      LOG(ERROR) << "Failed to parse the display scale:" << value;
711    display_info_[new_info.id()].set_ui_scale(scale_in_double);
712  }
713
714  display_info_[new_info.id()].UpdateDisplaySize();
715}
716
717gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) {
718  DCHECK(display_info_.find(id) != display_info_.end());
719  const DisplayInfo& display_info = display_info_[id];
720
721  gfx::Display new_display(display_info.id());
722  gfx::Rect bounds_in_pixel(display_info.size_in_pixel());
723
724  // Simply set the origin to (0,0).  The primary display's origin is
725  // always (0,0) and the secondary display's bounds will be updated
726  // by |DisplayController::UpdateDisplayBoundsForLayout|.
727  new_display.SetScaleAndBounds(
728      display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size()));
729  new_display.set_rotation(display_info.rotation());
730  return new_display;
731}
732
733}  // namespace internal
734}  // namespace ash
735