diff --git a/ui/platform_window/x11/x11_window_base.cc b/ui/platform_window/x11/x11_window_base.cc index 0344ded1aba375..028e9fb412d593 100644 --- a/ui/platform_window/x11/x11_window_base.cc +++ b/ui/platform_window/x11/x11_window_base.cc @@ -44,26 +44,14 @@ X11WindowBase::X11WindowBase(PlatformWindowDelegate* delegate, xroot_window_(DefaultRootWindow(xdisplay_)), bounds_(bounds) { DCHECK(delegate_); + pointer_barriers_.fill(None); } X11WindowBase::~X11WindowBase() { + UnConfineCursor(); Destroy(); } -void X11WindowBase::Destroy() { - if (xwindow_ == None) - return; - - // Stop processing events. - XID xwindow = xwindow_; - XDisplay* xdisplay = xdisplay_; - xwindow_ = None; - delegate_->OnClosed(); - // |this| might be deleted because of the above call. - - XDestroyWindow(xdisplay, xwindow); -} - void X11WindowBase::Create() { DCHECK(!bounds_.size().IsEmpty()); @@ -243,12 +231,64 @@ void X11WindowBase::MoveCursorTo(const gfx::Point& location) { bounds_.x() + location.x(), bounds_.y() + location.y()); } -void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) {} +void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) { + UnConfineCursor(); + + if (bounds.IsEmpty()) + return; + + gfx::Rect barrier(bounds); + barrier.Offset(bounds_.x(), bounds_.y()); + + // Top horizontal barrier. + pointer_barriers_[0] = XFixesCreatePointerBarrier( + xdisplay_, xroot_window_, barrier.x(), barrier.y(), barrier.right(), + barrier.y(), BarrierPositiveY, 0, XIAllDevices); + // Bottom horizontal barrier. + pointer_barriers_[1] = XFixesCreatePointerBarrier( + xdisplay_, xroot_window_, barrier.x(), barrier.bottom(), barrier.right(), + barrier.bottom(), BarrierNegativeY, 0, XIAllDevices); + // Left vertical barrier. + pointer_barriers_[2] = XFixesCreatePointerBarrier( + xdisplay_, xroot_window_, barrier.x(), barrier.y(), barrier.x(), + barrier.bottom(), BarrierPositiveX, 0, XIAllDevices); + // Right vertical barrier. + pointer_barriers_[3] = XFixesCreatePointerBarrier( + xdisplay_, xroot_window_, barrier.right(), barrier.y(), barrier.right(), + barrier.bottom(), BarrierNegativeX, 0, XIAllDevices); + + has_pointer_barriers_ = true; +} PlatformImeController* X11WindowBase::GetPlatformImeController() { return nullptr; } +void X11WindowBase::Destroy() { + if (xwindow_ == None) + return; + + // Stop processing events. + XID xwindow = xwindow_; + XDisplay* xdisplay = xdisplay_; + xwindow_ = None; + delegate_->OnClosed(); + // |this| might be deleted because of the above call. + + XDestroyWindow(xdisplay, xwindow); +} + +void X11WindowBase::UnConfineCursor() { + if (!has_pointer_barriers_) + return; + + for (XID pointer_barrier : pointer_barriers_) + XFixesDestroyPointerBarrier(xdisplay_, pointer_barrier); + pointer_barriers_.fill(None); + + has_pointer_barriers_ = false; +} + bool X11WindowBase::IsEventForXWindow(const XEvent& xev) const { return xwindow_ != None && FindXEventTarget(xev) == xwindow_; } diff --git a/ui/platform_window/x11/x11_window_base.h b/ui/platform_window/x11/x11_window_base.h index 6f37c05fbf9b21..8f29fdf4fa6b4c 100644 --- a/ui/platform_window/x11/x11_window_base.h +++ b/ui/platform_window/x11/x11_window_base.h @@ -7,6 +7,8 @@ #include +#include + #include "base/callback.h" #include "base/macros.h" #include "ui/gfx/geometry/rect.h" @@ -47,12 +49,13 @@ class X11_WINDOW_EXPORT X11WindowBase : public PlatformWindow { PlatformImeController* GetPlatformImeController() override; protected: - void Destroy(); - PlatformWindowDelegate* delegate() { return delegate_; } XDisplay* xdisplay() { return xdisplay_; } XID xwindow() const { return xwindow_; } + void Destroy(); + void UnConfineCursor(); + // Checks if XEvent is for this XWindow. bool IsEventForXWindow(const XEvent& xev) const; @@ -60,7 +63,7 @@ class X11_WINDOW_EXPORT X11WindowBase : public PlatformWindow { void ProcessXWindowEvent(XEvent* xev); private: - PlatformWindowDelegate* delegate_; + PlatformWindowDelegate* const delegate_; XDisplay* xdisplay_; XID xwindow_; @@ -72,6 +75,10 @@ class X11_WINDOW_EXPORT X11WindowBase : public PlatformWindow { // The bounds of |xwindow_|. gfx::Rect bounds_; + // Keep track of barriers to confine cursor. + bool has_pointer_barriers_ = false; + std::array pointer_barriers_; + bool window_mapped_ = false; DISALLOW_COPY_AND_ASSIGN(X11WindowBase);