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

Side by Side Diff: ui/aura/desktop_host_linux.cc

Issue 8771015: Rename Desktop->RootWindow. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years 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
« no previous file with comments | « ui/aura/desktop_host.h ('k') | ui/aura/desktop_host_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "ui/aura/desktop_host.h"
6
7 #include <X11/cursorfont.h>
8 #include <X11/Xlib.h>
9
10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
11 #undef RootWindow
12
13 #include <algorithm>
14
15 #include "base/message_loop.h"
16 #include "base/message_pump_x.h"
17 #include "ui/aura/cursor.h"
18 #include "ui/aura/desktop.h"
19 #include "ui/aura/event.h"
20 #include "ui/base/keycodes/keyboard_codes.h"
21 #include "ui/base/touch/touch_factory.h"
22 #include "ui/base/x/x11_util.h"
23 #include "ui/gfx/compositor/layer.h"
24
25 #include <X11/cursorfont.h>
26 #include <X11/extensions/XInput2.h>
27 #include <X11/Xlib.h>
28
29 using std::max;
30 using std::min;
31
32 namespace aura {
33
34 namespace {
35
36 // The events reported for slave devices can have incorrect information for some
37 // fields. This utility function is used to check for such inconsistencies.
38 void CheckXEventForConsistency(XEvent* xevent) {
39 static bool expect_master_event = false;
40 static XIDeviceEvent slave_event;
41 static gfx::Point slave_location;
42
43 // Note: If an event comes from a slave pointer device, then it will be
44 // followed by the same event, but reported from its master pointer device.
45 // However, if the event comes from a floating slave device (e.g. a
46 // touchscreen), then it will not be followed by a duplicate event, since the
47 // floating slave isn't attached to a master.
48
49 bool was_expecting_master_event = expect_master_event;
50 expect_master_event = false;
51
52 if (!xevent || xevent->type != GenericEvent)
53 return;
54
55 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
56 if (xievent->evtype != XI_Motion &&
57 xievent->evtype != XI_ButtonPress &&
58 xievent->evtype != XI_ButtonRelease) {
59 return;
60 }
61
62 if (xievent->sourceid == xievent->deviceid) {
63 slave_event = *xievent;
64 slave_location = ui::EventLocationFromNative(xevent);
65 expect_master_event = true;
66 } else if (was_expecting_master_event) {
67 CHECK_EQ(slave_location.x(), ui::EventLocationFromNative(xevent).x());
68 CHECK_EQ(slave_location.y(), ui::EventLocationFromNative(xevent).y());
69
70 CHECK_EQ(slave_event.type, xievent->type);
71 CHECK_EQ(slave_event.evtype, xievent->evtype);
72 CHECK_EQ(slave_event.detail, xievent->detail);
73 CHECK_EQ(slave_event.flags, xievent->flags);
74 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len);
75 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len);
76 CHECK_EQ(slave_event.mods.base, xievent->mods.base);
77 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched);
78 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked);
79 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective);
80 }
81 }
82
83 // Returns X font cursor shape from an Aura cursor.
84 int CursorShapeFromNative(gfx::NativeCursor native_cursor) {
85 switch (native_cursor) {
86 case aura::kCursorNull:
87 return XC_left_ptr;
88 case aura::kCursorPointer:
89 return XC_left_ptr;
90 case aura::kCursorCross:
91 return XC_crosshair;
92 case aura::kCursorHand:
93 return XC_hand2;
94 case aura::kCursorIBeam:
95 return XC_xterm;
96 case aura::kCursorWait:
97 return XC_watch;
98 case aura::kCursorHelp:
99 return XC_question_arrow;
100 case aura::kCursorEastResize:
101 return XC_right_side;
102 case aura::kCursorNorthResize:
103 return XC_top_side;
104 case aura::kCursorNorthEastResize:
105 return XC_top_right_corner;
106 case aura::kCursorNorthWestResize:
107 return XC_top_left_corner;
108 case aura::kCursorSouthResize:
109 return XC_bottom_side;
110 case aura::kCursorSouthEastResize:
111 return XC_bottom_right_corner;
112 case aura::kCursorSouthWestResize:
113 return XC_bottom_left_corner;
114 case aura::kCursorWestResize:
115 return XC_left_side;
116 case aura::kCursorNorthSouthResize:
117 return XC_sb_v_double_arrow;
118 case aura::kCursorEastWestResize:
119 return XC_sb_h_double_arrow;
120 case aura::kCursorNorthEastSouthWestResize:
121 case aura::kCursorNorthWestSouthEastResize:
122 // There isn't really a useful cursor available for these.
123 NOTIMPLEMENTED();
124 return XC_left_ptr;
125 case aura::kCursorColumnResize:
126 return XC_sb_h_double_arrow;
127 case aura::kCursorRowResize:
128 return XC_sb_v_double_arrow;
129 case aura::kCursorMiddlePanning:
130 return XC_fleur;
131 case aura::kCursorEastPanning:
132 return XC_sb_right_arrow;
133 case aura::kCursorNorthPanning:
134 return XC_sb_up_arrow;
135 case aura::kCursorNorthEastPanning:
136 return XC_top_right_corner;
137 case aura::kCursorNorthWestPanning:
138 return XC_top_left_corner;
139 case aura::kCursorSouthPanning:
140 return XC_sb_down_arrow;
141 case aura::kCursorSouthEastPanning:
142 return XC_bottom_right_corner;
143 case aura::kCursorSouthWestPanning:
144 return XC_bottom_left_corner;
145 case aura::kCursorWestPanning:
146 return XC_sb_left_arrow;
147 case aura::kCursorMove:
148 return XC_fleur;
149 case aura::kCursorVerticalText:
150 case aura::kCursorCell:
151 case aura::kCursorContextMenu:
152 case aura::kCursorAlias:
153 case aura::kCursorProgress:
154 case aura::kCursorNoDrop:
155 case aura::kCursorCopy:
156 case aura::kCursorNone:
157 case aura::kCursorNotAllowed:
158 case aura::kCursorZoomIn:
159 case aura::kCursorZoomOut:
160 case aura::kCursorGrab:
161 case aura::kCursorGrabbing:
162 case aura::kCursorCustom:
163 // TODO(jamescook): Need cursors for these.
164 NOTIMPLEMENTED();
165 return XC_left_ptr;
166 }
167 NOTREACHED();
168 return XC_left_ptr;
169 }
170
171 // Coalesce all pending motion events that are at the top of the queue, and
172 // return the number eliminated, storing the last one in |last_event|.
173 int CoalescePendingXIMotionEvents(const XEvent* xev, XEvent* last_event) {
174 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
175 int num_coalesed = 0;
176 Display* display = xev->xany.display;
177
178 while (XPending(display)) {
179 XEvent next_event;
180 XPeekEvent(display, &next_event);
181
182 // If we can't get the cookie, abort the check.
183 if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie))
184 return num_coalesed;
185
186 // If this isn't from a valid device, throw the event away, as
187 // that's what the message pump would do. Device events come in pairs
188 // with one from the master and one from the slave so there will
189 // always be at least one pending.
190 if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(&next_event)) {
191 CheckXEventForConsistency(&next_event);
192 XFreeEventData(display, &next_event.xcookie);
193 XNextEvent(display, &next_event);
194 continue;
195 }
196
197 if (next_event.type == GenericEvent &&
198 next_event.xgeneric.evtype == XI_Motion) {
199 XIDeviceEvent* next_xievent =
200 static_cast<XIDeviceEvent*>(next_event.xcookie.data);
201 // Confirm that the motion event is targeted at the same window
202 // and that no buttons or modifiers have changed.
203 if (xievent->event == next_xievent->event &&
204 xievent->child == next_xievent->child &&
205 xievent->buttons.mask_len == next_xievent->buttons.mask_len &&
206 (memcmp(xievent->buttons.mask,
207 next_xievent->buttons.mask,
208 xievent->buttons.mask_len) == 0) &&
209 xievent->mods.base == next_xievent->mods.base &&
210 xievent->mods.latched == next_xievent->mods.latched &&
211 xievent->mods.locked == next_xievent->mods.locked &&
212 xievent->mods.effective == next_xievent->mods.effective) {
213 XFreeEventData(display, &next_event.xcookie);
214 // Free the previous cookie.
215 if (num_coalesed > 0)
216 XFreeEventData(display, &last_event->xcookie);
217 // Get the event and its cookie data.
218 XNextEvent(display, last_event);
219 XGetEventData(display, &last_event->xcookie);
220 CheckXEventForConsistency(last_event);
221 ++num_coalesed;
222 continue;
223 } else {
224 // This isn't an event we want so free its cookie data.
225 XFreeEventData(display, &next_event.xcookie);
226 }
227 }
228 break;
229 }
230 return num_coalesed;
231 }
232
233 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only
234 // generated for certain keys; see
235 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx.
236 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) {
237 if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) ||
238 (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) ||
239 (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) {
240 return true;
241 }
242
243 switch (keycode) {
244 case ui::VKEY_BACK:
245 case ui::VKEY_RETURN:
246 case ui::VKEY_ESCAPE:
247 case ui::VKEY_SPACE:
248 case ui::VKEY_TAB:
249 // In addition to the keys listed at MSDN, we include other
250 // graphic-character and numpad keys.
251 case ui::VKEY_MULTIPLY:
252 case ui::VKEY_ADD:
253 case ui::VKEY_SUBTRACT:
254 case ui::VKEY_DECIMAL:
255 case ui::VKEY_DIVIDE:
256 case ui::VKEY_OEM_1:
257 case ui::VKEY_OEM_2:
258 case ui::VKEY_OEM_3:
259 case ui::VKEY_OEM_4:
260 case ui::VKEY_OEM_5:
261 case ui::VKEY_OEM_6:
262 case ui::VKEY_OEM_7:
263 case ui::VKEY_OEM_102:
264 case ui::VKEY_OEM_PLUS:
265 case ui::VKEY_OEM_COMMA:
266 case ui::VKEY_OEM_MINUS:
267 case ui::VKEY_OEM_PERIOD:
268 return true;
269 default:
270 return false;
271 }
272 }
273
274 class DesktopHostLinux : public DesktopHost,
275 public MessageLoop::DestructionObserver {
276 public:
277 explicit DesktopHostLinux(const gfx::Rect& bounds);
278 virtual ~DesktopHostLinux();
279
280 private:
281 // MessageLoop::Dispatcher Override.
282 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE;
283
284 // DesktopHost Overrides.
285 virtual void SetDesktop(Desktop* desktop) OVERRIDE;
286 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
287 virtual void Show() OVERRIDE;
288 virtual void ToggleFullScreen() OVERRIDE;
289 virtual gfx::Size GetSize() const OVERRIDE;
290 virtual void SetSize(const gfx::Size& size) OVERRIDE;
291 virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
292 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
293 virtual gfx::Point QueryMouseLocation() OVERRIDE;
294 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
295
296 // MessageLoop::DestructionObserver Overrides.
297 virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
298
299 // Returns true if there's an X window manager present... in most cases. Some
300 // window managers (notably, ion3) don't implement enough of ICCCM for us to
301 // detect that they're there.
302 bool IsWindowManagerPresent();
303
304 Desktop* desktop_;
305
306 // The display and the native X window hosting the desktop.
307 Display* xdisplay_;
308 ::Window xwindow_;
309
310 // The native root window.
311 ::Window root_window_;
312
313 // Current Aura cursor.
314 gfx::NativeCursor current_cursor_;
315
316 // The bounds of |xwindow_|.
317 gfx::Rect bounds_;
318
319 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux);
320 };
321
322 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds)
323 : desktop_(NULL),
324 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
325 xwindow_(0),
326 root_window_(DefaultRootWindow(xdisplay_)),
327 current_cursor_(aura::kCursorNull),
328 bounds_(bounds) {
329 xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_,
330 bounds.x(), bounds.y(),
331 bounds.width(), bounds.height(),
332 0, 0, 0);
333
334 long event_mask = ButtonPressMask | ButtonReleaseMask |
335 KeyPressMask | KeyReleaseMask |
336 EnterWindowMask | LeaveWindowMask |
337 ExposureMask | VisibilityChangeMask |
338 StructureNotifyMask | PropertyChangeMask |
339 PointerMotionMask;
340 XSelectInput(xdisplay_, xwindow_, event_mask);
341 XSelectInput(xdisplay_, root_window_, StructureNotifyMask);
342 XFlush(xdisplay_);
343
344 // TODO(sad): Re-enable once crbug.com/106516 is fixed.
345 #if 0
346 if (base::MessagePumpForUI::HasXInput2())
347 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
348 #endif
349
350 base::MessagePumpX::SetDefaultDispatcher(this);
351 MessageLoopForUI::current()->AddDestructionObserver(this);
352 }
353
354 DesktopHostLinux::~DesktopHostLinux() {
355 XDestroyWindow(xdisplay_, xwindow_);
356
357 // Clears XCursorCache.
358 ui::GetXCursor(ui::kCursorClearXCursorCache);
359
360 MessageLoopForUI::current()->RemoveDestructionObserver(this);
361 base::MessagePumpX::SetDefaultDispatcher(NULL);
362 }
363
364 base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch(
365 XEvent* xev) {
366 bool handled = false;
367
368 CheckXEventForConsistency(xev);
369
370 switch (xev->type) {
371 case Expose:
372 desktop_->ScheduleDraw();
373 handled = true;
374 break;
375 case KeyPress: {
376 KeyEvent keydown_event(xev, false);
377 handled = desktop_->DispatchKeyEvent(&keydown_event);
378 if (ShouldSendCharEventForKeyboardCode(keydown_event.key_code())) {
379 KeyEvent char_event(xev, true);
380 handled |= desktop_->DispatchKeyEvent(&char_event);
381 }
382 break;
383 }
384 case KeyRelease: {
385 KeyEvent keyup_event(xev, false);
386 handled = desktop_->DispatchKeyEvent(&keyup_event);
387 break;
388 }
389 case ButtonPress:
390 case ButtonRelease: {
391 MouseEvent mouseev(xev);
392 handled = desktop_->DispatchMouseEvent(&mouseev);
393 break;
394 }
395 case ConfigureNotify: {
396 if (xev->xconfigure.window == root_window_) {
397 desktop_->OnNativeScreenResized(
398 gfx::Size(xev->xconfigure.width, xev->xconfigure.height));
399 handled = true;
400 break;
401 }
402
403 DCHECK_EQ(xwindow_, xev->xconfigure.window);
404 DCHECK_EQ(xwindow_, xev->xconfigure.event);
405
406 // It's possible that the X window may be resized by some other means than
407 // from within aura (e.g. the X window manager can change the size). Make
408 // sure the desktop size is maintained properly.
409 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
410 xev->xconfigure.width, xev->xconfigure.height);
411 bool size_changed = bounds_.size() != bounds.size();
412 bounds_ = bounds;
413 if (size_changed)
414 desktop_->OnHostResized(bounds.size());
415 handled = true;
416 break;
417 }
418 case GenericEvent: {
419 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
420 if (!factory->ShouldProcessXI2Event(xev))
421 break;
422
423 // If this is a motion event we want to coalesce all pending motion
424 // events that are at the top of the queue.
425 XEvent last_event;
426 int num_coalesced = 0;
427 if (xev->xgeneric.evtype == XI_Motion) {
428 num_coalesced = CoalescePendingXIMotionEvents(xev, &last_event);
429 if (num_coalesced > 0)
430 xev = &last_event;
431 }
432
433 ui::EventType type = ui::EventTypeFromNative(xev);
434 switch (type) {
435 case ui::ET_TOUCH_PRESSED:
436 case ui::ET_TOUCH_RELEASED:
437 case ui::ET_TOUCH_MOVED: {
438 TouchEvent touchev(xev);
439 handled = desktop_->DispatchTouchEvent(&touchev);
440 break;
441 }
442 case ui::ET_MOUSE_PRESSED:
443 case ui::ET_MOUSE_RELEASED:
444 case ui::ET_MOUSE_MOVED:
445 case ui::ET_MOUSE_DRAGGED:
446 case ui::ET_MOUSEWHEEL:
447 case ui::ET_MOUSE_ENTERED:
448 case ui::ET_MOUSE_EXITED: {
449 MouseEvent mouseev(xev);
450 handled = desktop_->DispatchMouseEvent(&mouseev);
451 break;
452 }
453 case ui::ET_UNKNOWN:
454 handled = false;
455 break;
456 default:
457 NOTREACHED();
458 }
459
460 // If we coalesced an event we need to free its cookie.
461 if (num_coalesced > 0)
462 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
463 break;
464 }
465 case MapNotify: {
466 // If there's no window manager running, we need to assign the X input
467 // focus to our host window.
468 if (!IsWindowManagerPresent())
469 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
470 handled = true;
471 break;
472 }
473 case MappingNotify: {
474 if (xev->xmapping.request == MappingModifier ||
475 xev->xmapping.request == MappingKeyboard)
476 XRefreshKeyboardMapping(&xev->xmapping);
477 break;
478 }
479 case MotionNotify: {
480 // Discard all but the most recent motion event that targets the same
481 // window with unchanged state.
482 XEvent last_event;
483 while (XPending(xev->xany.display)) {
484 XEvent next_event;
485 XPeekEvent(xev->xany.display, &next_event);
486 if (next_event.type == MotionNotify &&
487 next_event.xmotion.window == xev->xmotion.window &&
488 next_event.xmotion.subwindow == xev->xmotion.subwindow &&
489 next_event.xmotion.state == xev->xmotion.state) {
490 XNextEvent(xev->xany.display, &last_event);
491 xev = &last_event;
492 } else {
493 break;
494 }
495 }
496
497 MouseEvent mouseev(xev);
498 handled = desktop_->DispatchMouseEvent(&mouseev);
499 break;
500 }
501 }
502 return handled ? EVENT_PROCESSED : EVENT_IGNORED;
503 }
504
505 void DesktopHostLinux::SetDesktop(Desktop* desktop) {
506 desktop_ = desktop;
507 }
508
509 gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() {
510 return xwindow_;
511 }
512
513 void DesktopHostLinux::Show() {
514 XMapWindow(xdisplay_, xwindow_);
515 }
516
517 void DesktopHostLinux::ToggleFullScreen() {
518 NOTIMPLEMENTED();
519 }
520
521 gfx::Size DesktopHostLinux::GetSize() const {
522 return bounds_.size();
523 }
524
525 void DesktopHostLinux::SetSize(const gfx::Size& size) {
526 if (size == bounds_.size())
527 return;
528
529 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
530
531 // Assume that the resize will go through as requested, which should be the
532 // case if we're running without a window manager. If there's a window
533 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
534 // (possibly synthetic) ConfigureNotify about the actual size and correct
535 // |bounds_| later.
536 bounds_.set_size(size);
537 desktop_->OnHostResized(size);
538 }
539
540 gfx::Point DesktopHostLinux::GetLocationOnNativeScreen() const {
541 return bounds_.origin();
542 }
543
544 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) {
545 if (current_cursor_ == cursor)
546 return;
547 current_cursor_ = cursor;
548 // Custom web cursors are handled directly.
549 if (cursor == kCursorCustom)
550 return;
551 int cursor_shape = CursorShapeFromNative(cursor);
552 ::Cursor xcursor = ui::GetXCursor(cursor_shape);
553 XDefineCursor(xdisplay_, xwindow_, xcursor);
554 }
555
556 gfx::Point DesktopHostLinux::QueryMouseLocation() {
557 ::Window root_return, child_return;
558 int root_x_return, root_y_return, win_x_return, win_y_return;
559 unsigned int mask_return;
560 XQueryPointer(xdisplay_,
561 xwindow_,
562 &root_return,
563 &child_return,
564 &root_x_return, &root_y_return,
565 &win_x_return, &win_y_return,
566 &mask_return);
567 return gfx::Point(max(0, min(bounds_.width(), win_x_return)),
568 max(0, min(bounds_.height(), win_y_return)));
569 }
570
571 void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) {
572 DCHECK(xwindow_);
573 DCHECK(xdisplay_);
574 XEvent xevent = *native_event;
575 xevent.xany.display = xdisplay_;
576 xevent.xany.window = xwindow_;
577
578 switch (xevent.type) {
579 case EnterNotify:
580 case LeaveNotify:
581 case MotionNotify:
582 case KeyPress:
583 case KeyRelease:
584 case ButtonPress:
585 case ButtonRelease: {
586 // The fields used below are in the same place for all of events
587 // above. Using xmotion from XEvent's unions to avoid repeating
588 // the code.
589 xevent.xmotion.root = root_window_;
590 xevent.xmotion.time = CurrentTime;
591
592 gfx::Point point(xevent.xmotion.x, xevent.xmotion.y);
593 desktop_->ConvertPointToNativeScreen(&point);
594 xevent.xmotion.x_root = point.x();
595 xevent.xmotion.y_root = point.y();
596 }
597 default:
598 break;
599 }
600 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
601 }
602
603 void DesktopHostLinux::WillDestroyCurrentMessageLoop() {
604 aura::Desktop::DeleteInstance();
605 }
606
607 bool DesktopHostLinux::IsWindowManagerPresent() {
608 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
609 // of WM_Sn selections (where n is a screen number).
610 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False);
611 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None;
612 }
613
614 } // namespace
615
616 // static
617 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) {
618 return new DesktopHostLinux(bounds);
619 }
620
621 // static
622 gfx::Size DesktopHost::GetNativeScreenSize() {
623 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
624 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
625 }
626
627 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura/desktop_host.h ('k') | ui/aura/desktop_host_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698