desktop_screen_x11.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_screen_x11.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <X11/extensions/Xrandr.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It clashes with out RootWindow.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef RootWindow
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/debug/trace_event.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window_tree_host.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/layout.h"
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/display/util/display_util.h"
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/display/util/x11/edid_parser_x11.h"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/platform/platform_event_source.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h"
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/display_observer.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/native_widget_types.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h"
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_screen.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// The delay to perform configuration after RRNotify.  See the comment
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// in |Dispatch()|.
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int64 kConfigureDelayMs = 500;
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)float GetDeviceScaleFactor(int screen_pixels, int screen_mm) {
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int kCSSDefaultDPI = 96;
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const float kInchInMm = 25.4f;
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  float screen_inches = screen_mm / kInchInMm;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  float screen_dpi = screen_pixels / screen_inches;
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  float scale = screen_dpi / kCSSDefaultDPI;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return ui::GetImageScale(ui::GetSupportedScaleFactor(scale));
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::vector<gfx::Display> GetFallbackDisplayList() {
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ::XDisplay* display = gfx::GetXDisplay();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Screen* screen = DefaultScreenOfDisplay(display);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = WidthOfScreen(screen);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height = HeightOfScreen(screen);
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Size physical_size(WidthMMOfScreen(screen), HeightMMOfScreen(screen));
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect bounds_in_pixels(0, 0, width, height);
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Display gfx_display(0, bounds_in_pixels);
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!gfx::Display::HasForceDeviceScaleFactor() &&
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      !ui::IsDisplaySizeBlackListed(physical_size)) {
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    float device_scale_factor = GetDeviceScaleFactor(
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        width, physical_size.width());
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK_LE(1.0f, device_scale_factor);
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx_display.SetScaleAndBounds(device_scale_factor, bounds_in_pixels);
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return std::vector<gfx::Display>(1, gfx_display);
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Helper class to GetWindowAtScreenPoint() which returns the topmost window at
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// the location passed to FindAt(). NULL is returned if a window which does not
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// belong to Chromium is topmost at the passed in location.
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ToplevelWindowFinder : public ui::EnumerateWindowsDelegate {
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ToplevelWindowFinder() : toplevel_(NULL) {
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~ToplevelWindowFinder() {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::Window* FindAt(const gfx::Point& screen_loc) {
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    screen_loc_ = screen_loc;
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::EnumerateTopLevelWindows(this);
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return toplevel_;
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected:
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool ShouldStopIterating(XID xid) OVERRIDE {
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)   if (!ui::IsWindowVisible(xid))
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)     return false;
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    aura::Window* window =
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        views::DesktopWindowTreeHostX11::GetContentWindowForXID(xid);
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (window) {
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      // Currently |window|->IsVisible() always returns true.
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      // TODO(pkotwicz): Fix this. crbug.com/353038
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (window->IsVisible() &&
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          window->GetBoundsInScreen().Contains(screen_loc_)) {
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        toplevel_ = window;
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return true;
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return false;
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (ui::WindowContainsPoint(xid, screen_loc_)) {
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // toplevel_ = NULL
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return true;
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Point screen_loc_;
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::Window* toplevel_;
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ToplevelWindowFinder);
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace views {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DesktopScreenX11, public:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)DesktopScreenX11::DesktopScreenX11()
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : xdisplay_(gfx::GetXDisplay()),
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      x_root_window_(DefaultRootWindow(xdisplay_)),
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      has_xrandr_(false),
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      xrandr_event_base_(0) {
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // We only support 1.3+. There were library changes before this and we should
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // use the new interface instead of the 1.2 one.
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int randr_version_major = 0;
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int randr_version_minor = 0;
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  has_xrandr_ = XRRQueryVersion(
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        xdisplay_, &randr_version_major, &randr_version_minor) &&
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      randr_version_major == 1 &&
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      randr_version_minor >= 3;
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (has_xrandr_) {
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int error_base_ignored = 0;
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (ui::PlatformEventSource::GetInstance())
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XRRSelectInput(xdisplay_,
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                   x_root_window_,
1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                   RRScreenChangeNotifyMask |
1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                   RROutputChangeNotifyMask |
1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                   RRCrtcChangeNotifyMask);
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    displays_ = BuildDisplaysFromXRandRInfo();
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    displays_ = GetFallbackDisplayList();
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopScreenX11::~DesktopScreenX11() {
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (has_xrandr_ && ui::PlatformEventSource::GetInstance())
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DesktopScreenX11::ProcessDisplayChange(
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::vector<gfx::Display>& incoming) {
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<gfx::Display> old_displays = displays_;
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  displays_ = incoming;
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef std::vector<gfx::Display>::const_iterator DisplayIt;
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<gfx::Display>::const_iterator old_it = old_displays.begin();
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (; old_it != old_displays.end(); ++old_it) {
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool found = false;
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (std::vector<gfx::Display>::const_iterator new_it =
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             displays_.begin(); new_it != displays_.end(); ++new_it) {
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (old_it->id() == new_it->id()) {
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        found = true;
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!found) {
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        OnDisplayRemoved(*old_it));
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<gfx::Display>::const_iterator new_it = displays_.begin();
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (; new_it != displays_.end(); ++new_it) {
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool found = false;
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (std::vector<gfx::Display>::const_iterator old_it =
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         old_displays.begin(); old_it != old_displays.end(); ++old_it) {
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (new_it->id() == old_it->id()) {
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (new_it->bounds() != old_it->bounds()) {
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            OnDisplayBoundsChanged(*new_it));
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        found = true;
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!found) {
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        OnDisplayAdded(*new_it));
20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DesktopScreenX11, gfx::Screen implementation:
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DesktopScreenX11::IsDIPEnabled() {
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TRACE_EVENT0("views", "DesktopScreenX11::GetCursorScreenPoint()");
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XDisplay* display = gfx::GetXDisplay();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Window root, child;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int root_x, root_y, win_x, win_y;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int mask;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XQueryPointer(display,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                DefaultRootWindow(display),
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &root,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &child,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &root_x,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &root_y,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &win_x,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &win_y,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &mask);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Point(root_x, root_y);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() {
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetWindowAtScreenPoint(GetCursorScreenPoint());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint(
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const gfx::Point& point) {
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ToplevelWindowFinder finder;
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return finder.FindAt(point);
241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int DesktopScreenX11::GetNumDisplays() const {
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return displays_.size();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
247424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::vector<gfx::Display> DesktopScreenX11::GetAllDisplays() const {
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return displays_;
249424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetDisplayNearestWindow(
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeView window) const {
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Getting screen bounds here safely is hard.
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // You'd think we'd be able to just call window->GetBoundsInScreen(), but we
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // can't because |window| (and the associated WindowEventDispatcher*) can be
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // partially initialized at this point; WindowEventDispatcher initializations
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // call through into GetDisplayNearestWindow(). But the X11 resources are
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // created before we create the aura::WindowEventDispatcher. So we ask what
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // the DRWHX11 believes the window bounds are instead of going through the
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // aura::Window's screen bounds.
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::WindowTreeHost* host = window->GetHost();
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (host) {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DesktopWindowTreeHostX11* rwh = DesktopWindowTreeHostX11::GetHostForXID(
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        host->GetAcceleratedWidget());
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (rwh)
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return GetDisplayMatching(rwh->GetX11RootWindowBounds());
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetPrimaryDisplay();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetDisplayNearestPoint(
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Point& point) const {
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::vector<gfx::Display>::const_iterator it = displays_.begin();
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       it != displays_.end(); ++it) {
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (it->bounds().Contains(point))
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return *it;
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetPrimaryDisplay();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetDisplayMatching(
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& match_rect) const {
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int max_area = 0;
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const gfx::Display* matching = NULL;
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::vector<gfx::Display>::const_iterator it = displays_.begin();
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       it != displays_.end(); ++it) {
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    gfx::Rect intersect = gfx::IntersectRects(it->bounds(), match_rect);
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int area = intersect.width() * intersect.height();
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (area > max_area) {
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      max_area = area;
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      matching = &*it;
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Fallback to the primary display if there is no matching display.
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return matching ? *matching : GetPrimaryDisplay();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetPrimaryDisplay() const {
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return displays_.front();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopScreenX11::AddObserver(gfx::DisplayObserver* observer) {
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.AddObserver(observer);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopScreenX11::RemoveObserver(gfx::DisplayObserver* observer) {
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.RemoveObserver(observer);
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
313c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DesktopScreenX11::CanDispatchEvent(const ui::PlatformEvent& event) {
314c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return event->type - xrandr_event_base_ == RRScreenChangeNotify ||
315c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         event->type - xrandr_event_base_ == RRNotify;
316c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
317c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
318c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochuint32_t DesktopScreenX11::DispatchEvent(const ui::PlatformEvent& event) {
31968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Pass the event through to xlib.
32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XRRUpdateConfiguration(event);
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (event->type - xrandr_event_base_ == RRNotify) {
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // There's some sort of observer dispatch going on here, but I don't think
32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // it's the screen's?
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (configure_timer_.get() && configure_timer_->IsRunning()) {
32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      configure_timer_->Reset();
32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else {
32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      configure_timer_.reset(new base::OneShotTimer<DesktopScreenX11>());
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      configure_timer_->Start(
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          FROM_HERE,
33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          base::TimeDelta::FromMilliseconds(kConfigureDelayMs),
33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          this,
33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          &DesktopScreenX11::ConfigureTimerFired);
33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
335c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else {
336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    NOTREACHED();
33768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
33868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
339c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return ui::POST_DISPATCH_NONE;
34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// DesktopScreenX11, private:
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)DesktopScreenX11::DesktopScreenX11(
34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::vector<gfx::Display>& test_displays)
347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : xdisplay_(gfx::GetXDisplay()),
34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      x_root_window_(DefaultRootWindow(xdisplay_)),
34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      has_xrandr_(false),
35068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      xrandr_event_base_(0),
35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      displays_(test_displays) {
35268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<gfx::Display> displays;
35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XRRScreenResources* resources =
35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      XRRGetScreenResourcesCurrent(xdisplay_, x_root_window_);
35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!resources) {
35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    LOG(ERROR) << "XRandR returned no displays. Falling back to Root Window.";
36068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return GetFallbackDisplayList();
36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
36268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
36368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool has_work_area = false;
36468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect work_area;
36568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<int> value;
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) &&
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      value.size() >= 4) {
36868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    work_area = gfx::Rect(value[0], value[1], value[2], value[3]);
36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    has_work_area = true;
37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
37168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  float device_scale_factor = 1.0f;
37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int i = 0; i < resources->noutput; ++i) {
37468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RROutput output_id = resources->outputs[i];
37568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XRROutputInfo* output_info =
37668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        XRRGetOutputInfo(xdisplay_, resources, output_id);
37768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
37868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool is_connected = (output_info->connection == RR_Connected);
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!is_connected) {
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      XRRFreeOutputInfo(output_info);
38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      continue;
38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
38468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (output_info->crtc) {
38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      XRRCrtcInfo *crtc = XRRGetCrtcInfo(xdisplay_,
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                         resources,
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                         output_info->crtc);
38868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
38968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      int64 display_id = -1;
390effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (!ui::GetDisplayId(output_id, static_cast<uint8>(i), &display_id)) {
39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        // It isn't ideal, but if we can't parse the EDID data, fallback on the
39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        // display number.
39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        display_id = i;
39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      gfx::Rect crtc_bounds(crtc->x, crtc->y, crtc->width, crtc->height);
39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      gfx::Display display(display_id, crtc_bounds);
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!gfx::Display::HasForceDeviceScaleFactor()) {
400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (i == 0 && !ui::IsDisplaySizeBlackListed(
401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            gfx::Size(output_info->mm_width, output_info->mm_height))) {
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          // As per display scale factor is not supported right now,
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          // the primary display's scale factor is always used.
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          device_scale_factor = GetDeviceScaleFactor(crtc->width,
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                     output_info->mm_width);
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          DCHECK_LE(1.0f, device_scale_factor);
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        display.SetScaleAndBounds(device_scale_factor, crtc_bounds);
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
41168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (has_work_area) {
41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        gfx::Rect intersection = crtc_bounds;
41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        intersection.Intersect(work_area);
41468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        display.set_work_area(intersection);
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
41668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      displays.push_back(display);
41868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      XRRFreeCrtcInfo(crtc);
42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
42168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    XRRFreeOutputInfo(output_info);
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
42468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XRRFreeScreenResources(resources);
42668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (displays.empty())
42868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return GetFallbackDisplayList();
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return displays;
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
43268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DesktopScreenX11::ConfigureTimerFired() {
43468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<gfx::Display> new_displays = BuildDisplaysFromXRandRInfo();
43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ProcessDisplayChange(new_displays);
43668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
43768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Screen* CreateDesktopScreen() {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new DesktopScreenX11;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace views
445