Index: ui/aura/desktop_host_linux.cc |
=================================================================== |
--- ui/aura/desktop_host_linux.cc (revision 113260) |
+++ ui/aura/desktop_host_linux.cc (working copy) |
@@ -1,627 +0,0 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "ui/aura/desktop_host.h" |
- |
-#include <X11/cursorfont.h> |
-#include <X11/Xlib.h> |
- |
-// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. |
-#undef RootWindow |
- |
-#include <algorithm> |
- |
-#include "base/message_loop.h" |
-#include "base/message_pump_x.h" |
-#include "ui/aura/cursor.h" |
-#include "ui/aura/desktop.h" |
-#include "ui/aura/event.h" |
-#include "ui/base/keycodes/keyboard_codes.h" |
-#include "ui/base/touch/touch_factory.h" |
-#include "ui/base/x/x11_util.h" |
-#include "ui/gfx/compositor/layer.h" |
- |
-#include <X11/cursorfont.h> |
-#include <X11/extensions/XInput2.h> |
-#include <X11/Xlib.h> |
- |
-using std::max; |
-using std::min; |
- |
-namespace aura { |
- |
-namespace { |
- |
-// The events reported for slave devices can have incorrect information for some |
-// fields. This utility function is used to check for such inconsistencies. |
-void CheckXEventForConsistency(XEvent* xevent) { |
- static bool expect_master_event = false; |
- static XIDeviceEvent slave_event; |
- static gfx::Point slave_location; |
- |
- // Note: If an event comes from a slave pointer device, then it will be |
- // followed by the same event, but reported from its master pointer device. |
- // However, if the event comes from a floating slave device (e.g. a |
- // touchscreen), then it will not be followed by a duplicate event, since the |
- // floating slave isn't attached to a master. |
- |
- bool was_expecting_master_event = expect_master_event; |
- expect_master_event = false; |
- |
- if (!xevent || xevent->type != GenericEvent) |
- return; |
- |
- XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); |
- if (xievent->evtype != XI_Motion && |
- xievent->evtype != XI_ButtonPress && |
- xievent->evtype != XI_ButtonRelease) { |
- return; |
- } |
- |
- if (xievent->sourceid == xievent->deviceid) { |
- slave_event = *xievent; |
- slave_location = ui::EventLocationFromNative(xevent); |
- expect_master_event = true; |
- } else if (was_expecting_master_event) { |
- CHECK_EQ(slave_location.x(), ui::EventLocationFromNative(xevent).x()); |
- CHECK_EQ(slave_location.y(), ui::EventLocationFromNative(xevent).y()); |
- |
- CHECK_EQ(slave_event.type, xievent->type); |
- CHECK_EQ(slave_event.evtype, xievent->evtype); |
- CHECK_EQ(slave_event.detail, xievent->detail); |
- CHECK_EQ(slave_event.flags, xievent->flags); |
- CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); |
- CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); |
- CHECK_EQ(slave_event.mods.base, xievent->mods.base); |
- CHECK_EQ(slave_event.mods.latched, xievent->mods.latched); |
- CHECK_EQ(slave_event.mods.locked, xievent->mods.locked); |
- CHECK_EQ(slave_event.mods.effective, xievent->mods.effective); |
- } |
-} |
- |
-// Returns X font cursor shape from an Aura cursor. |
-int CursorShapeFromNative(gfx::NativeCursor native_cursor) { |
- switch (native_cursor) { |
- case aura::kCursorNull: |
- return XC_left_ptr; |
- case aura::kCursorPointer: |
- return XC_left_ptr; |
- case aura::kCursorCross: |
- return XC_crosshair; |
- case aura::kCursorHand: |
- return XC_hand2; |
- case aura::kCursorIBeam: |
- return XC_xterm; |
- case aura::kCursorWait: |
- return XC_watch; |
- case aura::kCursorHelp: |
- return XC_question_arrow; |
- case aura::kCursorEastResize: |
- return XC_right_side; |
- case aura::kCursorNorthResize: |
- return XC_top_side; |
- case aura::kCursorNorthEastResize: |
- return XC_top_right_corner; |
- case aura::kCursorNorthWestResize: |
- return XC_top_left_corner; |
- case aura::kCursorSouthResize: |
- return XC_bottom_side; |
- case aura::kCursorSouthEastResize: |
- return XC_bottom_right_corner; |
- case aura::kCursorSouthWestResize: |
- return XC_bottom_left_corner; |
- case aura::kCursorWestResize: |
- return XC_left_side; |
- case aura::kCursorNorthSouthResize: |
- return XC_sb_v_double_arrow; |
- case aura::kCursorEastWestResize: |
- return XC_sb_h_double_arrow; |
- case aura::kCursorNorthEastSouthWestResize: |
- case aura::kCursorNorthWestSouthEastResize: |
- // There isn't really a useful cursor available for these. |
- NOTIMPLEMENTED(); |
- return XC_left_ptr; |
- case aura::kCursorColumnResize: |
- return XC_sb_h_double_arrow; |
- case aura::kCursorRowResize: |
- return XC_sb_v_double_arrow; |
- case aura::kCursorMiddlePanning: |
- return XC_fleur; |
- case aura::kCursorEastPanning: |
- return XC_sb_right_arrow; |
- case aura::kCursorNorthPanning: |
- return XC_sb_up_arrow; |
- case aura::kCursorNorthEastPanning: |
- return XC_top_right_corner; |
- case aura::kCursorNorthWestPanning: |
- return XC_top_left_corner; |
- case aura::kCursorSouthPanning: |
- return XC_sb_down_arrow; |
- case aura::kCursorSouthEastPanning: |
- return XC_bottom_right_corner; |
- case aura::kCursorSouthWestPanning: |
- return XC_bottom_left_corner; |
- case aura::kCursorWestPanning: |
- return XC_sb_left_arrow; |
- case aura::kCursorMove: |
- return XC_fleur; |
- case aura::kCursorVerticalText: |
- case aura::kCursorCell: |
- case aura::kCursorContextMenu: |
- case aura::kCursorAlias: |
- case aura::kCursorProgress: |
- case aura::kCursorNoDrop: |
- case aura::kCursorCopy: |
- case aura::kCursorNone: |
- case aura::kCursorNotAllowed: |
- case aura::kCursorZoomIn: |
- case aura::kCursorZoomOut: |
- case aura::kCursorGrab: |
- case aura::kCursorGrabbing: |
- case aura::kCursorCustom: |
- // TODO(jamescook): Need cursors for these. |
- NOTIMPLEMENTED(); |
- return XC_left_ptr; |
- } |
- NOTREACHED(); |
- return XC_left_ptr; |
-} |
- |
-// Coalesce all pending motion events that are at the top of the queue, and |
-// return the number eliminated, storing the last one in |last_event|. |
-int CoalescePendingXIMotionEvents(const XEvent* xev, XEvent* last_event) { |
- XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
- int num_coalesed = 0; |
- Display* display = xev->xany.display; |
- |
- while (XPending(display)) { |
- XEvent next_event; |
- XPeekEvent(display, &next_event); |
- |
- // If we can't get the cookie, abort the check. |
- if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) |
- return num_coalesed; |
- |
- // If this isn't from a valid device, throw the event away, as |
- // that's what the message pump would do. Device events come in pairs |
- // with one from the master and one from the slave so there will |
- // always be at least one pending. |
- if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(&next_event)) { |
- CheckXEventForConsistency(&next_event); |
- XFreeEventData(display, &next_event.xcookie); |
- XNextEvent(display, &next_event); |
- continue; |
- } |
- |
- if (next_event.type == GenericEvent && |
- next_event.xgeneric.evtype == XI_Motion) { |
- XIDeviceEvent* next_xievent = |
- static_cast<XIDeviceEvent*>(next_event.xcookie.data); |
- // Confirm that the motion event is targeted at the same window |
- // and that no buttons or modifiers have changed. |
- if (xievent->event == next_xievent->event && |
- xievent->child == next_xievent->child && |
- xievent->buttons.mask_len == next_xievent->buttons.mask_len && |
- (memcmp(xievent->buttons.mask, |
- next_xievent->buttons.mask, |
- xievent->buttons.mask_len) == 0) && |
- xievent->mods.base == next_xievent->mods.base && |
- xievent->mods.latched == next_xievent->mods.latched && |
- xievent->mods.locked == next_xievent->mods.locked && |
- xievent->mods.effective == next_xievent->mods.effective) { |
- XFreeEventData(display, &next_event.xcookie); |
- // Free the previous cookie. |
- if (num_coalesed > 0) |
- XFreeEventData(display, &last_event->xcookie); |
- // Get the event and its cookie data. |
- XNextEvent(display, last_event); |
- XGetEventData(display, &last_event->xcookie); |
- CheckXEventForConsistency(last_event); |
- ++num_coalesed; |
- continue; |
- } else { |
- // This isn't an event we want so free its cookie data. |
- XFreeEventData(display, &next_event.xcookie); |
- } |
- } |
- break; |
- } |
- return num_coalesed; |
-} |
- |
-// We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only |
-// generated for certain keys; see |
-// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx. |
-bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) { |
- if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) || |
- (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) || |
- (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) { |
- return true; |
- } |
- |
- switch (keycode) { |
- case ui::VKEY_BACK: |
- case ui::VKEY_RETURN: |
- case ui::VKEY_ESCAPE: |
- case ui::VKEY_SPACE: |
- case ui::VKEY_TAB: |
- // In addition to the keys listed at MSDN, we include other |
- // graphic-character and numpad keys. |
- case ui::VKEY_MULTIPLY: |
- case ui::VKEY_ADD: |
- case ui::VKEY_SUBTRACT: |
- case ui::VKEY_DECIMAL: |
- case ui::VKEY_DIVIDE: |
- case ui::VKEY_OEM_1: |
- case ui::VKEY_OEM_2: |
- case ui::VKEY_OEM_3: |
- case ui::VKEY_OEM_4: |
- case ui::VKEY_OEM_5: |
- case ui::VKEY_OEM_6: |
- case ui::VKEY_OEM_7: |
- case ui::VKEY_OEM_102: |
- case ui::VKEY_OEM_PLUS: |
- case ui::VKEY_OEM_COMMA: |
- case ui::VKEY_OEM_MINUS: |
- case ui::VKEY_OEM_PERIOD: |
- return true; |
- default: |
- return false; |
- } |
-} |
- |
-class DesktopHostLinux : public DesktopHost, |
- public MessageLoop::DestructionObserver { |
- public: |
- explicit DesktopHostLinux(const gfx::Rect& bounds); |
- virtual ~DesktopHostLinux(); |
- |
- private: |
- // MessageLoop::Dispatcher Override. |
- virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE; |
- |
- // DesktopHost Overrides. |
- virtual void SetDesktop(Desktop* desktop) OVERRIDE; |
- virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; |
- virtual void Show() OVERRIDE; |
- virtual void ToggleFullScreen() OVERRIDE; |
- virtual gfx::Size GetSize() const OVERRIDE; |
- virtual void SetSize(const gfx::Size& size) OVERRIDE; |
- virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE; |
- virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; |
- virtual gfx::Point QueryMouseLocation() OVERRIDE; |
- virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; |
- |
- // MessageLoop::DestructionObserver Overrides. |
- virtual void WillDestroyCurrentMessageLoop() OVERRIDE; |
- |
- // Returns true if there's an X window manager present... in most cases. Some |
- // window managers (notably, ion3) don't implement enough of ICCCM for us to |
- // detect that they're there. |
- bool IsWindowManagerPresent(); |
- |
- Desktop* desktop_; |
- |
- // The display and the native X window hosting the desktop. |
- Display* xdisplay_; |
- ::Window xwindow_; |
- |
- // The native root window. |
- ::Window root_window_; |
- |
- // Current Aura cursor. |
- gfx::NativeCursor current_cursor_; |
- |
- // The bounds of |xwindow_|. |
- gfx::Rect bounds_; |
- |
- DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); |
-}; |
- |
-DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
- : desktop_(NULL), |
- xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), |
- xwindow_(0), |
- root_window_(DefaultRootWindow(xdisplay_)), |
- current_cursor_(aura::kCursorNull), |
- bounds_(bounds) { |
- xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_, |
- bounds.x(), bounds.y(), |
- bounds.width(), bounds.height(), |
- 0, 0, 0); |
- |
- long event_mask = ButtonPressMask | ButtonReleaseMask | |
- KeyPressMask | KeyReleaseMask | |
- EnterWindowMask | LeaveWindowMask | |
- ExposureMask | VisibilityChangeMask | |
- StructureNotifyMask | PropertyChangeMask | |
- PointerMotionMask; |
- XSelectInput(xdisplay_, xwindow_, event_mask); |
- XSelectInput(xdisplay_, root_window_, StructureNotifyMask); |
- XFlush(xdisplay_); |
- |
- // TODO(sad): Re-enable once crbug.com/106516 is fixed. |
-#if 0 |
- if (base::MessagePumpForUI::HasXInput2()) |
- ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
-#endif |
- |
- base::MessagePumpX::SetDefaultDispatcher(this); |
- MessageLoopForUI::current()->AddDestructionObserver(this); |
-} |
- |
-DesktopHostLinux::~DesktopHostLinux() { |
- XDestroyWindow(xdisplay_, xwindow_); |
- |
- // Clears XCursorCache. |
- ui::GetXCursor(ui::kCursorClearXCursorCache); |
- |
- MessageLoopForUI::current()->RemoveDestructionObserver(this); |
- base::MessagePumpX::SetDefaultDispatcher(NULL); |
-} |
- |
-base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( |
- XEvent* xev) { |
- bool handled = false; |
- |
- CheckXEventForConsistency(xev); |
- |
- switch (xev->type) { |
- case Expose: |
- desktop_->ScheduleDraw(); |
- handled = true; |
- break; |
- case KeyPress: { |
- KeyEvent keydown_event(xev, false); |
- handled = desktop_->DispatchKeyEvent(&keydown_event); |
- if (ShouldSendCharEventForKeyboardCode(keydown_event.key_code())) { |
- KeyEvent char_event(xev, true); |
- handled |= desktop_->DispatchKeyEvent(&char_event); |
- } |
- break; |
- } |
- case KeyRelease: { |
- KeyEvent keyup_event(xev, false); |
- handled = desktop_->DispatchKeyEvent(&keyup_event); |
- break; |
- } |
- case ButtonPress: |
- case ButtonRelease: { |
- MouseEvent mouseev(xev); |
- handled = desktop_->DispatchMouseEvent(&mouseev); |
- break; |
- } |
- case ConfigureNotify: { |
- if (xev->xconfigure.window == root_window_) { |
- desktop_->OnNativeScreenResized( |
- gfx::Size(xev->xconfigure.width, xev->xconfigure.height)); |
- handled = true; |
- break; |
- } |
- |
- DCHECK_EQ(xwindow_, xev->xconfigure.window); |
- DCHECK_EQ(xwindow_, xev->xconfigure.event); |
- |
- // It's possible that the X window may be resized by some other means than |
- // from within aura (e.g. the X window manager can change the size). Make |
- // sure the desktop size is maintained properly. |
- gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
- xev->xconfigure.width, xev->xconfigure.height); |
- bool size_changed = bounds_.size() != bounds.size(); |
- bounds_ = bounds; |
- if (size_changed) |
- desktop_->OnHostResized(bounds.size()); |
- handled = true; |
- break; |
- } |
- case GenericEvent: { |
- ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
- if (!factory->ShouldProcessXI2Event(xev)) |
- break; |
- |
- // If this is a motion event we want to coalesce all pending motion |
- // events that are at the top of the queue. |
- XEvent last_event; |
- int num_coalesced = 0; |
- if (xev->xgeneric.evtype == XI_Motion) { |
- num_coalesced = CoalescePendingXIMotionEvents(xev, &last_event); |
- if (num_coalesced > 0) |
- xev = &last_event; |
- } |
- |
- ui::EventType type = ui::EventTypeFromNative(xev); |
- switch (type) { |
- case ui::ET_TOUCH_PRESSED: |
- case ui::ET_TOUCH_RELEASED: |
- case ui::ET_TOUCH_MOVED: { |
- TouchEvent touchev(xev); |
- handled = desktop_->DispatchTouchEvent(&touchev); |
- break; |
- } |
- case ui::ET_MOUSE_PRESSED: |
- case ui::ET_MOUSE_RELEASED: |
- case ui::ET_MOUSE_MOVED: |
- case ui::ET_MOUSE_DRAGGED: |
- case ui::ET_MOUSEWHEEL: |
- case ui::ET_MOUSE_ENTERED: |
- case ui::ET_MOUSE_EXITED: { |
- MouseEvent mouseev(xev); |
- handled = desktop_->DispatchMouseEvent(&mouseev); |
- break; |
- } |
- case ui::ET_UNKNOWN: |
- handled = false; |
- break; |
- default: |
- NOTREACHED(); |
- } |
- |
- // If we coalesced an event we need to free its cookie. |
- if (num_coalesced > 0) |
- XFreeEventData(xev->xgeneric.display, &last_event.xcookie); |
- break; |
- } |
- case MapNotify: { |
- // If there's no window manager running, we need to assign the X input |
- // focus to our host window. |
- if (!IsWindowManagerPresent()) |
- XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); |
- handled = true; |
- break; |
- } |
- case MappingNotify: { |
- if (xev->xmapping.request == MappingModifier || |
- xev->xmapping.request == MappingKeyboard) |
- XRefreshKeyboardMapping(&xev->xmapping); |
- break; |
- } |
- case MotionNotify: { |
- // Discard all but the most recent motion event that targets the same |
- // window with unchanged state. |
- XEvent last_event; |
- while (XPending(xev->xany.display)) { |
- XEvent next_event; |
- XPeekEvent(xev->xany.display, &next_event); |
- if (next_event.type == MotionNotify && |
- next_event.xmotion.window == xev->xmotion.window && |
- next_event.xmotion.subwindow == xev->xmotion.subwindow && |
- next_event.xmotion.state == xev->xmotion.state) { |
- XNextEvent(xev->xany.display, &last_event); |
- xev = &last_event; |
- } else { |
- break; |
- } |
- } |
- |
- MouseEvent mouseev(xev); |
- handled = desktop_->DispatchMouseEvent(&mouseev); |
- break; |
- } |
- } |
- return handled ? EVENT_PROCESSED : EVENT_IGNORED; |
-} |
- |
-void DesktopHostLinux::SetDesktop(Desktop* desktop) { |
- desktop_ = desktop; |
-} |
- |
-gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() { |
- return xwindow_; |
-} |
- |
-void DesktopHostLinux::Show() { |
- XMapWindow(xdisplay_, xwindow_); |
-} |
- |
-void DesktopHostLinux::ToggleFullScreen() { |
- NOTIMPLEMENTED(); |
-} |
- |
-gfx::Size DesktopHostLinux::GetSize() const { |
- return bounds_.size(); |
-} |
- |
-void DesktopHostLinux::SetSize(const gfx::Size& size) { |
- if (size == bounds_.size()) |
- return; |
- |
- XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); |
- |
- // Assume that the resize will go through as requested, which should be the |
- // case if we're running without a window manager. If there's a window |
- // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
- // (possibly synthetic) ConfigureNotify about the actual size and correct |
- // |bounds_| later. |
- bounds_.set_size(size); |
- desktop_->OnHostResized(size); |
-} |
- |
-gfx::Point DesktopHostLinux::GetLocationOnNativeScreen() const { |
- return bounds_.origin(); |
-} |
- |
-void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { |
- if (current_cursor_ == cursor) |
- return; |
- current_cursor_ = cursor; |
- // Custom web cursors are handled directly. |
- if (cursor == kCursorCustom) |
- return; |
- int cursor_shape = CursorShapeFromNative(cursor); |
- ::Cursor xcursor = ui::GetXCursor(cursor_shape); |
- XDefineCursor(xdisplay_, xwindow_, xcursor); |
-} |
- |
-gfx::Point DesktopHostLinux::QueryMouseLocation() { |
- ::Window root_return, child_return; |
- int root_x_return, root_y_return, win_x_return, win_y_return; |
- unsigned int mask_return; |
- XQueryPointer(xdisplay_, |
- xwindow_, |
- &root_return, |
- &child_return, |
- &root_x_return, &root_y_return, |
- &win_x_return, &win_y_return, |
- &mask_return); |
- return gfx::Point(max(0, min(bounds_.width(), win_x_return)), |
- max(0, min(bounds_.height(), win_y_return))); |
-} |
- |
-void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) { |
- DCHECK(xwindow_); |
- DCHECK(xdisplay_); |
- XEvent xevent = *native_event; |
- xevent.xany.display = xdisplay_; |
- xevent.xany.window = xwindow_; |
- |
- switch (xevent.type) { |
- case EnterNotify: |
- case LeaveNotify: |
- case MotionNotify: |
- case KeyPress: |
- case KeyRelease: |
- case ButtonPress: |
- case ButtonRelease: { |
- // The fields used below are in the same place for all of events |
- // above. Using xmotion from XEvent's unions to avoid repeating |
- // the code. |
- xevent.xmotion.root = root_window_; |
- xevent.xmotion.time = CurrentTime; |
- |
- gfx::Point point(xevent.xmotion.x, xevent.xmotion.y); |
- desktop_->ConvertPointToNativeScreen(&point); |
- xevent.xmotion.x_root = point.x(); |
- xevent.xmotion.y_root = point.y(); |
- } |
- default: |
- break; |
- } |
- XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); |
-} |
- |
-void DesktopHostLinux::WillDestroyCurrentMessageLoop() { |
- aura::Desktop::DeleteInstance(); |
-} |
- |
-bool DesktopHostLinux::IsWindowManagerPresent() { |
- // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
- // of WM_Sn selections (where n is a screen number). |
- ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); |
- return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; |
-} |
- |
-} // namespace |
- |
-// static |
-DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { |
- return new DesktopHostLinux(bounds); |
-} |
- |
-// static |
-gfx::Size DesktopHost::GetNativeScreenSize() { |
- ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); |
- return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
-} |
- |
-} // namespace aura |