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

Side by Side Diff: ui/views/widget/desktop_aura/desktop_screen_x11.cc

Issue 23536057: linux_aura: Implement most of DesktopScreenX11. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Attempt at fixing chromeos compile. Created 7 years, 2 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 "ui/views/widget/desktop_aura/desktop_screen.h" 5 #include "ui/views/widget/desktop_aura/desktop_screen_x11.h"
6 6
7 #include <X11/extensions/Xrandr.h>
7 #include <X11/Xlib.h> 8 #include <X11/Xlib.h>
8 9
9 // It clashes with out RootWindow. 10 // It clashes with out RootWindow.
10 #undef RootWindow 11 #undef RootWindow
11 12
12 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/x11/edid_parser_x11.h"
13 #include "ui/aura/root_window.h" 15 #include "ui/aura/root_window.h"
14 #include "ui/aura/root_window_host.h" 16 #include "ui/aura/root_window_host.h"
17 #include "ui/base/x/x11_util.h"
15 #include "ui/gfx/display.h" 18 #include "ui/gfx/display.h"
19 #include "ui/gfx/display_observer.h"
16 #include "ui/gfx/native_widget_types.h" 20 #include "ui/gfx/native_widget_types.h"
17 #include "ui/gfx/screen.h" 21 #include "ui/gfx/screen.h"
18 #include "ui/gfx/x/x11_types.h" 22 #include "ui/gfx/x/x11_types.h"
23 #include "ui/views/widget/desktop_aura/desktop_screen.h"
19 24
20 namespace { 25 namespace {
21 26
22 // TODO(erg): This method is a temporary hack, until we can reliably extract 27 // The delay to perform configuration after RRNotify. See the comment
23 // location data out of XRandR. 28 // in |Dispatch()|.
24 gfx::Size GetPrimaryDisplaySize() { 29 const int64 kConfigureDelayMs = 500;
30
31 std::vector<gfx::Display> GetFallbackDisplayList() {
25 ::XDisplay* display = gfx::GetXDisplay(); 32 ::XDisplay* display = gfx::GetXDisplay();
26 ::Screen* screen = DefaultScreenOfDisplay(display); 33 ::Screen* screen = DefaultScreenOfDisplay(display);
27 int width = WidthOfScreen(screen); 34 int width = WidthOfScreen(screen);
28 int height = HeightOfScreen(screen); 35 int height = HeightOfScreen(screen);
29 36
30 return gfx::Size(width, height); 37 return std::vector<gfx::Display>(
38 1, gfx::Display(0, gfx::Rect(0, 0, width, height)));
31 } 39 }
32 40
33 class DesktopScreenX11 : public gfx::Screen { 41 } // namespace
34 public:
35 DesktopScreenX11();
36 virtual ~DesktopScreenX11();
37 42
38 // Overridden from gfx::Screen: 43 namespace views {
39 virtual bool IsDIPEnabled() OVERRIDE;
40 virtual gfx::Point GetCursorScreenPoint() OVERRIDE;
41 virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE;
42 virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
43 OVERRIDE;
44 virtual int GetNumDisplays() const OVERRIDE;
45 virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE;
46 virtual gfx::Display GetDisplayNearestWindow(
47 gfx::NativeView window) const OVERRIDE;
48 virtual gfx::Display GetDisplayNearestPoint(
49 const gfx::Point& point) const OVERRIDE;
50 virtual gfx::Display GetDisplayMatching(
51 const gfx::Rect& match_rect) const OVERRIDE;
52 virtual gfx::Display GetPrimaryDisplay() const OVERRIDE;
53 virtual void AddObserver(gfx::DisplayObserver* observer) OVERRIDE;
54 virtual void RemoveObserver(gfx::DisplayObserver* observer) OVERRIDE;
55
56 private:
57 DISALLOW_COPY_AND_ASSIGN(DesktopScreenX11);
58 };
59 44
60 //////////////////////////////////////////////////////////////////////////////// 45 ////////////////////////////////////////////////////////////////////////////////
61 // DesktopScreenX11, public: 46 // DesktopScreenX11, public:
62 47
63 DesktopScreenX11::DesktopScreenX11() { 48 DesktopScreenX11::DesktopScreenX11()
49 : xdisplay_(base::MessagePumpX11::GetDefaultXDisplay()),
50 x_root_window_(DefaultRootWindow(xdisplay_)),
51 has_xrandr_(false),
52 xrandr_event_base_(0) {
53 // We only support 1.3+. There were library changes before this and we should
54 // use the new interface instead of the 1.2 one.
55 int randr_version_major = 0;
56 int randr_version_minor = 0;
57 has_xrandr_ = XRRQueryVersion(
58 xdisplay_, &randr_version_major, &randr_version_minor) &&
59 randr_version_major == 1 &&
60 randr_version_minor >= 3;
61
62 if (has_xrandr_) {
63 int error_base_ignored = 0;
64 XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);
65
66 base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this);
67 XRRSelectInput(xdisplay_,
68 x_root_window_,
69 RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
70
71 displays_ = BuildDisplaysFromXRandRInfo();
72 } else {
73 displays_ = GetFallbackDisplayList();
74 }
64 } 75 }
65 76
66 DesktopScreenX11::~DesktopScreenX11() { 77 DesktopScreenX11::~DesktopScreenX11() {
78 if (has_xrandr_)
79 base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this);
80 }
81
82 void DesktopScreenX11::ProcessDisplayChange(
83 const std::vector<gfx::Display>& incoming) {
84 std::vector<gfx::Display>::const_iterator cur_it = displays_.begin();
85 for (; cur_it != displays_.end(); ++cur_it) {
86 bool found = false;
87 for (std::vector<gfx::Display>::const_iterator incoming_it =
88 incoming.begin(); incoming_it != incoming.end(); ++incoming_it) {
89 if (cur_it->id() == incoming_it->id()) {
90 found = true;
91 break;
92 }
93 }
94
95 if (!found) {
96 FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
97 OnDisplayRemoved(*cur_it));
98 }
99 }
100
101 std::vector<gfx::Display>::const_iterator incoming_it = incoming.begin();
102 for (; incoming_it != incoming.end(); ++incoming_it) {
103 bool found = false;
104 for (std::vector<gfx::Display>::const_iterator cur_it = displays_.begin();
105 cur_it != displays_.end(); ++cur_it) {
106 if (incoming_it->id() == cur_it->id()) {
107 if (incoming_it->bounds() != cur_it->bounds()) {
108 FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
109 OnDisplayBoundsChanged(*incoming_it));
110 }
111
112 found = true;
113 break;
114 }
115 }
116
117 if (!found) {
118 FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
119 OnDisplayAdded(*incoming_it));
120 }
121 }
122
123 displays_ = incoming;
67 } 124 }
68 125
69 //////////////////////////////////////////////////////////////////////////////// 126 ////////////////////////////////////////////////////////////////////////////////
70 // DesktopScreenX11, gfx::Screen implementation: 127 // DesktopScreenX11, gfx::Screen implementation:
71 128
72 bool DesktopScreenX11::IsDIPEnabled() { 129 bool DesktopScreenX11::IsDIPEnabled() {
73 return false; 130 return false;
74 } 131 }
75 132
76 gfx::Point DesktopScreenX11::GetCursorScreenPoint() { 133 gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
77 XDisplay* display = gfx::GetXDisplay(); 134 XDisplay* display = gfx::GetXDisplay();
78 135
79 ::Window root, child; 136 ::Window root, child;
80 int root_x, root_y, win_x, win_y; 137 int root_x, root_y, win_x, win_y;
81 unsigned int mask; 138 unsigned int mask;
82 XQueryPointer(display, 139 XQueryPointer(display,
83 DefaultRootWindow(display), 140 DefaultRootWindow(display),
84 &root, 141 &root,
85 &child, 142 &child,
86 &root_x, 143 &root_x,
87 &root_y, 144 &root_y,
88 &win_x, 145 &win_x,
89 &win_y, 146 &win_y,
90 &mask); 147 &mask);
91 148
92 return gfx::Point(root_x, root_y); 149 return gfx::Point(root_x, root_y);
93 } 150 }
94 151
95 gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() { 152 gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() {
96 // TODO(erg): Implement using the discussion at 153 return GetWindowAtScreenPoint(GetCursorScreenPoint());
97 // http://codereview.chromium.org/10279005/
98 return NULL;
99 } 154 }
100 155
101 gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint( 156 gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint(
102 const gfx::Point& point) { 157 const gfx::Point& point) {
158 // TODO(erg): Implement using the discussion at
159 // http://codereview.chromium.org/10279005/
103 NOTIMPLEMENTED(); 160 NOTIMPLEMENTED();
104 return NULL; 161 return NULL;
105 } 162 }
106 163
107 int DesktopScreenX11::GetNumDisplays() const { 164 int DesktopScreenX11::GetNumDisplays() const {
108 // TODO(erg): Figure this out with oshima or piman because I have no clue 165 return displays_.size();
109 // about the XRandR implications here.
110 return 1;
111 } 166 }
112 167
113 std::vector<gfx::Display> DesktopScreenX11::GetAllDisplays() const { 168 std::vector<gfx::Display> DesktopScreenX11::GetAllDisplays() const {
114 // TODO(erg): Do the right thing once we know what that is. 169 return displays_;
115 return std::vector<gfx::Display>(1, GetPrimaryDisplay());
116 } 170 }
117 171
118 gfx::Display DesktopScreenX11::GetDisplayNearestWindow( 172 gfx::Display DesktopScreenX11::GetDisplayNearestWindow(
119 gfx::NativeView window) const { 173 gfx::NativeView window) const {
120 // TODO(erg): Do the right thing once we know what that is. 174 // TODO(erg): This should theoretically be easy, but it isn't. At the time we
121 return gfx::Display(0, gfx::Rect(GetPrimaryDisplaySize())); 175 // get called here, our aura::Window has not been Init()ed, because this
176 // method is called to get the device scale factor as part of
177 // RootWindow::Init(), before Window::Init(). This seems very confused; we're
178 // trying to get a display nearest window even before we've allocated the
179 // root window. Once fixed, the correct implementation should probably be:
180 //
181 // return GetDisplayMatching(window->GetBoundsInScreen());
182 //
183 // But at least for now, we'll just fallback:
184 return GetPrimaryDisplay();
122 } 185 }
123 186
124 gfx::Display DesktopScreenX11::GetDisplayNearestPoint( 187 gfx::Display DesktopScreenX11::GetDisplayNearestPoint(
125 const gfx::Point& point) const { 188 const gfx::Point& point) const {
126 // TODO(erg): Do the right thing once we know what that is. 189 for (std::vector<gfx::Display>::const_iterator it = displays_.begin();
127 return gfx::Display(0, gfx::Rect(GetPrimaryDisplaySize())); 190 it != displays_.end(); ++it) {
191 if (it->bounds().Contains(point))
192 return *it;
193 }
194
195 return GetPrimaryDisplay();
128 } 196 }
129 197
130 gfx::Display DesktopScreenX11::GetDisplayMatching( 198 gfx::Display DesktopScreenX11::GetDisplayMatching(
131 const gfx::Rect& match_rect) const { 199 const gfx::Rect& match_rect) const {
132 // TODO(erg): Do the right thing once we know what that is. 200 int max_area = 0;
133 return gfx::Display(0, gfx::Rect(GetPrimaryDisplaySize())); 201 const gfx::Display* matching = NULL;
202 for (std::vector<gfx::Display>::const_iterator it = displays_.begin();
203 it != displays_.end(); ++it) {
204 gfx::Rect intersect = gfx::IntersectRects(it->bounds(), match_rect);
205 int area = intersect.width() * intersect.height();
206 if (area > max_area) {
207 max_area = area;
208 matching = &*it;
209 }
210 }
211 // Fallback to the primary display if there is no matching display.
212 return matching ? *matching : GetPrimaryDisplay();
134 } 213 }
135 214
136 gfx::Display DesktopScreenX11::GetPrimaryDisplay() const { 215 gfx::Display DesktopScreenX11::GetPrimaryDisplay() const {
137 // TODO(erg): Do the right thing once we know what that is. 216 return displays_.front();
138 return gfx::Display(0, gfx::Rect(GetPrimaryDisplaySize()));
139 } 217 }
140 218
141 void DesktopScreenX11::AddObserver(gfx::DisplayObserver* observer) { 219 void DesktopScreenX11::AddObserver(gfx::DisplayObserver* observer) {
142 // TODO(erg|oshima): Do the right thing once we know what that is. 220 observer_list_.AddObserver(observer);
143 // crbug.com/122863
144 }
145 void DesktopScreenX11::RemoveObserver(gfx::DisplayObserver* observer) {
146 // TODO(erg|oshima): Do the right thing once we know what that is.
147 // crbug.com/122863
148 } 221 }
149 222
150 } // namespace 223 void DesktopScreenX11::RemoveObserver(gfx::DisplayObserver* observer) {
224 observer_list_.RemoveObserver(observer);
225 }
226
227 bool DesktopScreenX11::Dispatch(const base::NativeEvent& event) {
228 if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
229 // Pass the event through to xlib.
230 XRRUpdateConfiguration(event);
231 } else if (event->type - xrandr_event_base_ == RRNotify) {
232 // There's some sort of observer dispatch going on here, but I don't think
233 // it's the screen's?
234 DLOG(ERROR) << "DesktopScreenX11::Dispatch() -> RRNotify";
235
236 if (configure_timer_.get()) {
237 configure_timer_->Reset();
238 } else {
239 configure_timer_.reset(new base::OneShotTimer<DesktopScreenX11>());
240 configure_timer_->Start(
241 FROM_HERE,
242 base::TimeDelta::FromMilliseconds(kConfigureDelayMs),
243 this,
244 &DesktopScreenX11::ConfigureTimerFired);
245 }
246 }
247
248 return true;
249 }
250
251 ////////////////////////////////////////////////////////////////////////////////
252 // DesktopScreenX11, private:
253
254 DesktopScreenX11::DesktopScreenX11(
255 const std::vector<gfx::Display>& test_displays)
256 : xdisplay_(base::MessagePumpX11::GetDefaultXDisplay()),
257 x_root_window_(DefaultRootWindow(xdisplay_)),
258 has_xrandr_(false),
259 xrandr_event_base_(0),
260 displays_(test_displays) {
261 }
262
263 std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
264 std::vector<gfx::Display> displays;
265 XRRScreenResources* resources =
266 XRRGetScreenResourcesCurrent(xdisplay_, x_root_window_);
267 if (!resources) {
268 LOG(ERROR) << "XRandR returned no displays. Falling back to Root Window.";
269 return GetFallbackDisplayList();
270 }
271
272 bool has_work_area = false;
273 gfx::Rect work_area;
274 std::vector<int> value;
275 if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) &&
276 value.size() >= 4) {
277 work_area = gfx::Rect(value[0], value[1], value[2], value[3]);
278 has_work_area = true;
279 }
280
281 for (int i = 0; i < resources->noutput; ++i) {
282 RROutput output_id = resources->outputs[i];
283 XRROutputInfo* output_info =
284 XRRGetOutputInfo(xdisplay_, resources, output_id);
285
286 bool is_connected = (output_info->connection == RR_Connected);
287 if (!is_connected) {
288 XRRFreeOutputInfo(output_info);
289 continue;
290 }
291
292 if (output_info->crtc) {
293 XRRCrtcInfo *crtc = XRRGetCrtcInfo(xdisplay_,
294 resources,
295 output_info->crtc);
296
297 int64 display_id = -1;
298 if (!base::GetDisplayId(output_id, i, &display_id)) {
299 // It isn't ideal, but if we can't parse the EDID data, fallback on the
300 // display number.
301 display_id = i;
302 }
303
304 gfx::Rect crtc_bounds(crtc->x, crtc->y, crtc->width, crtc->height);
305 gfx::Display display(display_id, crtc_bounds);
306 if (has_work_area) {
307 gfx::Rect intersection = crtc_bounds;
308 intersection.Intersect(work_area);
309 display.set_work_area(intersection);
310 }
311
312 displays.push_back(display);
313
314 XRRFreeCrtcInfo(crtc);
315 }
316
317 XRRFreeOutputInfo(output_info);
318 }
319
320 XRRFreeScreenResources(resources);
321
322 if (displays.empty())
323 return GetFallbackDisplayList();
324
325 return displays;
326 }
327
328 void DesktopScreenX11::ConfigureTimerFired() {
329 std::vector<gfx::Display> new_displays = BuildDisplaysFromXRandRInfo();
330 ProcessDisplayChange(new_displays);
331 }
151 332
152 //////////////////////////////////////////////////////////////////////////////// 333 ////////////////////////////////////////////////////////////////////////////////
153 334
154 namespace views {
155
156 gfx::Screen* CreateDesktopScreen() { 335 gfx::Screen* CreateDesktopScreen() {
157 return new DesktopScreenX11; 336 return new DesktopScreenX11;
158 } 337 }
159 338
160 } // namespace views 339 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/widget/desktop_aura/desktop_screen_x11.h ('k') | ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698