| Index: ui/aura/root_window_host_linux.cc
|
| diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc
|
| index 9b9885670ea1a68b31e51af9f6a09b6dd5306db3..a643c56b2fee672ea480664368c63ce48827fd8c 100644
|
| --- a/ui/aura/root_window_host_linux.cc
|
| +++ b/ui/aura/root_window_host_linux.cc
|
| @@ -51,6 +51,14 @@ const int kForwardMouseButton = 9;
|
|
|
| const int kAnimatedCursorFrameDelayMs = 25;
|
|
|
| +// These are the same values that are used to calibrate touch events in
|
| +// |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc).
|
| +// TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605)
|
| +const int kXRootWindowPaddingLeft = 40;
|
| +const int kXRootWindowPaddingRight = 40;
|
| +const int kXRootWindowPaddingBottom = 30;
|
| +const int kXRootWindowPaddingTop = 0;
|
| +
|
| const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__";
|
|
|
| const char* kAtomsToCache[] = {
|
| @@ -268,6 +276,38 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) {
|
| return num_coalesed;
|
| }
|
|
|
| +void SelectEventsForRootWindow() {
|
| + XIEventMask evmask;
|
| + unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
|
| + memset(mask, 0, sizeof(mask));
|
| +
|
| + XISetMask(mask, XI_HierarchyChanged);
|
| +
|
| + XISetMask(mask, XI_KeyPress);
|
| + XISetMask(mask, XI_KeyRelease);
|
| +
|
| +#if defined(USE_XI2_MT)
|
| + XISetMask(mask, XI_TouchBegin);
|
| + XISetMask(mask, XI_TouchUpdate);
|
| + XISetMask(mask, XI_TouchEnd);
|
| +#endif
|
| + XISetMask(mask, XI_ButtonPress);
|
| + XISetMask(mask, XI_ButtonRelease);
|
| + XISetMask(mask, XI_Motion);
|
| +
|
| + evmask.deviceid = XIAllDevices;
|
| + evmask.mask_len = sizeof(mask);
|
| + evmask.mask = mask;
|
| +
|
| + Display* display = ui::GetXDisplay();
|
| + ::Window root_window = ui::GetX11RootWindow();
|
| + XISelectEvents(display, root_window, &evmask, 1);
|
| +
|
| + // Receive resize events for the root-window so |x_root_bounds_| can be
|
| + // updated.
|
| + XSelectInput(display, root_window, StructureNotifyMask);
|
| +}
|
| +
|
| // 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. Per
|
| @@ -531,6 +571,7 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate,
|
| CWBackPixmap,
|
| &swa);
|
| base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_);
|
| + base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this);
|
|
|
| prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this));
|
|
|
| @@ -546,6 +587,13 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate,
|
| if (base::MessagePumpForUI::HasXInput2())
|
| ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
|
|
|
| + SelectEventsForRootWindow();
|
| +
|
| + // Get the initial size of the X root window.
|
| + XWindowAttributes attrs;
|
| + XGetWindowAttributes(xdisplay_, x_root_window_, &attrs);
|
| + x_root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height);
|
| +
|
| // Initialize invisible cursor.
|
| char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
| XColor black;
|
| @@ -593,6 +641,7 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate,
|
| }
|
|
|
| RootWindowHostLinux::~RootWindowHostLinux() {
|
| + base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this);
|
| base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
|
|
|
| UnConfineCursor();
|
| @@ -648,38 +697,44 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
|
| delegate_->OnHostLostCapture();
|
| break;
|
| case ConfigureNotify: {
|
| - 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 root window 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();
|
| - bool origin_changed = bounds_.origin() != bounds.origin();
|
| - bounds_ = bounds;
|
| - // Update barrier and mouse location when the root window has
|
| - // moved/resized.
|
| - if (pointer_barriers_.get() && (size_changed || origin_changed)) {
|
| - UnConfineCursor();
|
| - RootWindow* root = delegate_->AsRootWindow();
|
| - client::ScreenPositionClient* client =
|
| + if (xev->xconfigure.window == xwindow_) {
|
| + 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 root window 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();
|
| + bool origin_changed = bounds_.origin() != bounds.origin();
|
| + bounds_ = bounds;
|
| + // Update barrier and mouse location when the root window has
|
| + // moved/resized.
|
| + if (pointer_barriers_.get() && (size_changed || origin_changed)) {
|
| + UnConfineCursor();
|
| + RootWindow* root = delegate_->AsRootWindow();
|
| + client::ScreenPositionClient* client =
|
| client::GetScreenPositionClient(root);
|
| - if (client) {
|
| - gfx::Point p = gfx::Screen::GetCursorScreenPoint();
|
| - client->ConvertPointFromScreen(root, &p);
|
| - if (root->ContainsPoint(p)) {
|
| - root->ConvertPointToNativeScreen(&p);
|
| - XWarpPointer(
|
| - xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y());
|
| + if (client) {
|
| + gfx::Point p = gfx::Screen::GetCursorScreenPoint();
|
| + client->ConvertPointFromScreen(root, &p);
|
| + if (root->ContainsPoint(p)) {
|
| + root->ConvertPointToNativeScreen(&p);
|
| + XWarpPointer(
|
| + xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y());
|
| + }
|
| }
|
| + ConfineCursorToRootWindow();
|
| }
|
| - ConfineCursorToRootWindow();
|
| + if (size_changed)
|
| + delegate_->OnHostResized(bounds.size());
|
| + if (origin_changed)
|
| + delegate_->OnHostMoved(bounds_.origin());
|
| + } else {
|
| + DCHECK_EQ(x_root_window_, xev->xconfigure.event);
|
| + DCHECK_EQ(x_root_window_, xev->xconfigure.window);
|
| + x_root_bounds_.SetRect(xev->xconfigure.x, xev->xconfigure.y,
|
| + xev->xconfigure.width, xev->xconfigure.height);
|
| }
|
| - if (size_changed)
|
| - delegate_->OnHostResized(bounds.size());
|
| - if (origin_changed)
|
| - delegate_->OnHostMoved(bounds_.origin());
|
| break;
|
| }
|
| case GenericEvent: {
|
| @@ -700,6 +755,22 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
|
| case ui::ET_TOUCH_PRESSED:
|
| case ui::ET_TOUCH_RELEASED: {
|
| ui::TouchEvent touchev(xev);
|
| + // X maps the touch-surface to the size of the X root-window. In
|
| + // multi-monitor setup, the X root-window size is a combination of
|
| + // both the monitor sizes. So it is necessary to remap the location of
|
| + // the event from the X root-window to the X host-window for the aura
|
| + // root-window.
|
| + touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size());
|
| + if (!bounds_.Contains(touchev.location())) {
|
| + // This might still be in the bezel region.
|
| + gfx::Rect expanded(bounds_);
|
| + expanded.Inset(-kXRootWindowPaddingLeft,
|
| + -kXRootWindowPaddingTop,
|
| + -kXRootWindowPaddingRight,
|
| + -kXRootWindowPaddingBottom);
|
| + if (!expanded.Contains(touchev.location()))
|
| + break;
|
| + }
|
| delegate_->OnHostTouchEvent(&touchev);
|
| break;
|
| }
|
|
|