Commit 70baca1c authored by reveman's avatar reveman Committed by Commit bot

exo: Implement lazy cursor changes.

Pointer::SetCursor() is now required to be called in response to
focus change events. This provides more seamless cursor changes
as the cursor will remain the same until it has been re-defined.

Simply clients that never define the cursor will now get the
default cursor instead of no cursor at all. Clients that draw
their own cursor now have a chance to provide a new frame before
the cursor is changed.

BUG=549781

Review-Url: https://codereview.chromium.org/2028443002
Cr-Commit-Position: refs/heads/master@{#396919}
parent c026ebf7
......@@ -46,8 +46,10 @@ Pointer::~Pointer() {
delegate_->OnPointerDestroying(this);
if (surface_)
surface_->RemoveSurfaceObserver(this);
if (focus_)
if (focus_) {
focus_->RemoveSurfaceObserver(this);
focus_->UnregisterCursorProvider(this);
}
if (widget_)
widget_->CloseNow();
ash::Shell::GetInstance()->RemovePreTargetHandler(this);
......@@ -86,7 +88,22 @@ void Pointer::SetCursor(Surface* surface, const gfx::Point& hotspot) {
surface_->layer()->size()));
if (!surface_->IsVisible())
surface_->Show();
// Show widget now that cursor has been defined.
if (!widget_->IsVisible())
widget_->Show();
}
// Register pointer as cursor provider now that the cursor for |focus_| has
// been defined.
focus_->RegisterCursorProvider(this);
// Update cursor in case the registration of pointer as cursor provider
// caused the cursor to change.
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(focus_->GetRootWindow());
if (cursor_client)
cursor_client->SetCursor(focus_->GetCursor(gfx::ToFlooredPoint(location_)));
}
////////////////////////////////////////////////////////////////////////////////
......@@ -102,6 +119,9 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) {
if (focus_) {
delegate_->OnPointerLeave(focus_);
focus_->RemoveSurfaceObserver(this);
// Require SetCursor() to be called and cursor to be re-defined in
// response to each OnPointerEnter() call.
focus_->UnregisterCursorProvider(this);
focus_ = nullptr;
}
// Second generate an enter event if focus moved to a new target.
......@@ -204,9 +224,6 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) {
widget_->GetNativeWindow()->SetTransform(transform);
cursor_scale_ = ui_scale;
}
if (!widget_->IsVisible())
widget_->Show();
} else {
if (widget_ && widget_->IsVisible())
widget_->Hide();
......
......@@ -78,7 +78,10 @@ class CustomWindowDelegate : public aura::WindowDelegate {
void OnBoundsChanged(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) override {}
gfx::NativeCursor GetCursor(const gfx::Point& point) override {
return ui::kCursorNone;
// If surface has a cursor provider then return 'none' as cursor providers
// are responsible for drawing cursors. Use default cursor if no cursor
// provider is registered.
return surface_->HasCursorProvider() ? ui::kCursorNone : ui::kCursorNull;
}
int GetNonClientComponent(const gfx::Point& point) const override {
return HTNOWHERE;
......@@ -740,6 +743,18 @@ gfx::Rect Surface::GetNonTransparentBounds() const {
return non_transparent_bounds;
}
void Surface::RegisterCursorProvider(Pointer* provider) {
cursor_providers_.insert(provider);
}
void Surface::UnregisterCursorProvider(Pointer* provider) {
cursor_providers_.erase(provider);
}
bool Surface::HasCursorProvider() const {
return !cursor_providers_.empty();
}
void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) {
DCHECK(!delegate_ || !delegate);
delegate_ = delegate;
......
......@@ -7,6 +7,7 @@
#include <list>
#include <memory>
#include <set>
#include <utility>
#include "base/callback.h"
......@@ -39,10 +40,15 @@ class Path;
namespace exo {
class Buffer;
class Pointer;
class SurfaceDelegate;
class SurfaceObserver;
class Surface;
// The pointer class is currently the only cursor provider class but this can
// change in the future when better hardware cursor support is added.
using CursorProvider = Pointer;
// This class owns the SurfaceFactory and keeps track of references to the
// contents of Buffers. It's keeped alive by references from
// release_callbacks_. It's destroyed when its owning Surface is destroyed and
......@@ -167,6 +173,14 @@ class Surface : public aura::Window,
// Returns the bounds of the surface area that is not know to be transparent.
gfx::Rect GetNonTransparentBounds() const;
// Surface does not own cursor providers. It is the responsibility of the
// caller to remove the cursor provider before it is destroyed.
void RegisterCursorProvider(CursorProvider* provider);
void UnregisterCursorProvider(CursorProvider* provider);
// Returns true if surface has at least one cursor provider registered.
bool HasCursorProvider() const;
// Set the surface delegate.
void SetSurfaceDelegate(SurfaceDelegate* delegate);
......@@ -305,6 +319,9 @@ class Surface : public aura::Window,
// The compsitor being observer or null if not observing a compositor.
ui::Compositor* compositor_;
// Cursor providers. Surface does not own the cursor providers.
std::set<CursorProvider*> cursor_providers_;
// This can be set to have some functions delegated. E.g. ShellSurface class
// can set this to handle Commit() and apply any double buffered state it
// maintains.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment