Chromium Code Reviews| 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..ddfa36d044e02d3a70e52ababbb71bf27eb82266 100644 |
| --- a/ui/aura/root_window_host_linux.cc |
| +++ b/ui/aura/root_window_host_linux.cc |
| @@ -51,6 +51,11 @@ const int kForwardMouseButton = 9; |
| const int kAnimatedCursorFrameDelayMs = 25; |
| +const int kXRootWindowPaddingLeft = 40; |
|
Daniel Erat
2012/09/10 17:27:31
nit: add a comment documenting what these are, and
sadrul
2012/09/10 18:19:32
Done (to make sure this gets fixed properly, I hav
|
| +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 +273,33 @@ 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(); |
| + XISelectEvents(display, ui::GetX11RootWindow(), &evmask, 1); |
| +} |
| + |
| // 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 +563,12 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, |
| CWBackPixmap, |
| &swa); |
| base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); |
| + base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this); |
| + |
| + // Get the initial size of the X root window. |
| + XWindowAttributes attrs; |
| + XGetWindowAttributes(xdisplay_, x_root_window_, &attrs); |
|
Daniel Erat
2012/09/10 17:27:31
i was going to suggest XGetGeometry() instead, but
sadrul
2012/09/10 18:19:32
If XGetGeometry is less expensive than XGetWindowA
|
| + root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height); |
| prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); |
| @@ -543,9 +581,14 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, |
| XSelectInput(xdisplay_, xwindow_, event_mask); |
| XFlush(xdisplay_); |
| + // Receive resize events for the root-window so |root_bounds_| can be updated. |
| + XSelectInput(xdisplay_, x_root_window_, StructureNotifyMask); |
|
Daniel Erat
2012/09/10 17:27:31
do this before you query the bounds; otherwise the
sadrul
2012/09/10 18:19:32
Done.
|
| + |
| if (base::MessagePumpForUI::HasXInput2()) |
| ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
| + SelectEventsForRootWindow(); |
| + |
| // Initialize invisible cursor. |
| char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
| XColor black; |
| @@ -593,6 +636,7 @@ RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, |
| } |
| RootWindowHostLinux::~RootWindowHostLinux() { |
| + base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); |
| base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); |
| UnConfineCursor(); |
| @@ -648,38 +692,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); |
| + 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 +750,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(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; |
| } |