blob: fb63bb213fef239e29371b32938e56f6b5450604 [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_EVENTS_EVENT_REWRITER_H_
#define UI_EVENTS_EVENT_REWRITER_H_
#include <memory>
#include "base/memory/weak_ptr.h"
#include "ui/events/event_dispatcher.h"
#include "ui/events/events_export.h"
#include "ui/events/platform_event.h"
namespace ui {
class Event;
class EventRewriterContinuation;
class EventSource; // TODO(kpschoedel): Remove with old API.
// Return status of EventRewriter operations; see that class below.
// TODO(kpschoedel): Remove old API.
enum EventRewriteStatus {
// Nothing was done; no rewritten event returned. Pass the original
// event to later rewriters, or send it to the EventSink if this
// was the final rewriter.
//
// TODO(kpschoedel): Replace old API uses of
// return EVENT_REWRITE_CONTINUE;
// with new API
// return SendEvent(continuation, &incoming_event);
EVENT_REWRITE_CONTINUE,
// The event has been rewritten. Send the rewritten event to the
// EventSink instead of the original event (without sending
// either to any later rewriters).
//
// TODO(kpschoedel): Replace old API uses of
// *rewritten_event = std::move(replacement_event);
// return EVENT_REWRITE_REWRITTEN;
// with new API
// return SendEventFinally(continuation, replacement_event);
EVENT_REWRITE_REWRITTEN,
// The event should be discarded, neither passing it to any later
// rewriters nor sending it to the EventSink.
//
// TODO(kpschoedel): Replace old API uses of
// return EVENT_REWRITE_DISCARD;
// with new API
// return DiscardEvent(continuation);
EVENT_REWRITE_DISCARD,
// The event has been rewritten. As for EVENT_REWRITE_REWRITTEN,
// send the rewritten event to the EventSink instead of the original
// event (without sending either to any later rewriters).
// In addition the rewriter has one or more additional new events
// to be retrieved using |NextDispatchEvent()| and sent to the
// EventSink.
//
// TODO(kpschoedel): Replace old API uses of
// *rewritten_event = std::move(new_event_1);
// // record new_event_2 … new_event_N
// return EVENT_REWRITE_DISPATCH_ANOTHER;
// with new API
// details = SendEventFinally(new_event_1);
// ⋮
// return SendEventFinally(new_event_N);
EVENT_REWRITE_DISPATCH_ANOTHER,
};
// EventRewriter provides a mechanism for Events to be rewritten
// before being dispatched from EventSource to EventSink.
class EVENTS_EXPORT EventRewriter {
public:
// Copyable opaque type, to be used only as an argument to SendEvent(),
// SendEventFinally(), or DiscardEvent(). The current implementation is
// a WeakPtr because some EventRewriters outlive their registration and
// can try to send events through an absent source (e.g. from a timer).
using Continuation = base::WeakPtr<EventRewriterContinuation>;
EventRewriter() = default;
EventRewriter(const EventRewriter&) = delete;
EventRewriter& operator=(const EventRewriter&) = delete;
virtual ~EventRewriter() = default;
// Potentially rewrites (replaces) an event, possibly with multiple events,
// or causes it to be discarded.
//
// To accept the supplied event without change,
// return SendEvent(continuation, &event)
//
// To replace the supplied event with a new event, call either
// return SendEvent(continuation, new_event)
// or
// return SendEventFinally(continuation, new_event)
// depending on whether or not |new_event| should be provided to any
// later rewriters. These functions can be called more than once to
// replace an incoming event with multiple new events; when doing so,
// check |details.dispatcher_destroyed| after each call.
//
// To discard the incoming event without replacement,
// return DiscardEvent()
//
// In the common case of one event at a time, the EventDispatchDetails
// from the above calls can and should be returned directly by RewriteEvent().
// When a rewriter generates multiple events synchronously, it should
// typically bail and return on a non-vacuous EventDispatchDetails.
// When a rewriter generates events asynchronously (e.g. from a timer)
// there is no opportunity to return the result directly, but a rewriter
// can consider retaining it for the next call.
//
// The supplied WeakPtr<Continuation> can be saved in order to respond
// asynchronously, e.g. after a double-click timeout. Normally, with
// EventRewriters subordinate to EventSources, the Continuation lives as
// long as the EventRewriter remains registered. If the continuation is not
// valid, the Send functions will return with |details.dispatcher_destroyed|.
//
// Design note: We need to pass the continuation state explicitly because
// Ash registers some EventRewriter instances with multiple EventSources.
//
virtual EventDispatchDetails RewriteEvent(const Event& event,
const Continuation continuation);
// Tells if this rewriter supports processing located events with location !=
// root_location as well as honors event target when rewriting an event.
// TODO(crbug.com/1459680): Remove once all rewriters honor event target.
virtual bool SupportsNonRootLocation() const;
// Potentially rewrites (replaces) an event, or requests it be discarded.
// or discards an event. If the rewriter wants to rewrite an event, and
// dispatch another event once the rewritten event is dispatched, it should
// return EVENT_REWRITE_DISPATCH_ANOTHER, and return the next event to
// dispatch from |NextDispatchEvent()|.
// TODO(kpschoedel): Remove old API.
virtual EventRewriteStatus RewriteEvent(
const Event& event,
std::unique_ptr<Event>* rewritten_event);
// Supplies an additional event to be dispatched. It is only valid to
// call this after the immediately previous call to |RewriteEvent()|
// or |NextDispatchEvent()| has returned EVENT_REWRITE_DISPATCH_ANOTHER.
// Should only return either EVENT_REWRITE_REWRITTEN or
// EVENT_REWRITE_DISPATCH_ANOTHER; otherwise the previous call should not
// have returned EVENT_REWRITE_DISPATCH_ANOTHER.
// TODO(kpschoedel): Remove old API.
virtual EventRewriteStatus NextDispatchEvent(
const Event& last_event,
std::unique_ptr<Event>* new_event);
protected:
// Forwards an event, through any subsequent rewriters.
[[nodiscard]] static EventDispatchDetails SendEvent(
const Continuation continuation,
const Event* event);
// Forwards an event, skipping any subsequent rewriters.
[[nodiscard]] static EventDispatchDetails SendEventFinally(
const Continuation continuation,
const Event* event);
// Discards an event, so that it will not be passed to the sink.
[[nodiscard]] static EventDispatchDetails DiscardEvent(
const Continuation continuation);
// A helper that calls a protected EventSource function, which sends the event
// to subsequent event rewriters on the source and onto its event sink.
// TODO(kpschoedel): Replace with SendEvent(continuation, event).
EventDispatchDetails SendEventToEventSource(EventSource* source,
Event* event) const;
#if BUILDFLAG(IS_CHROMEOS)
// Explicitly sets the `Event::native_event_` field bypassing any checks if
// the `PlatformEvent` should be copied from one event to another. The
// lifetime of `native_event` must be guaranteed to be longer than `event`. In
// the context of event rewriting, this is almost always the case.
void SetNativeEvent(Event& event, const PlatformEvent& native_event);
#endif
void SetEventTarget(Event& event, EventTarget* target);
};
} // namespace ui
#endif // UI_EVENTS_EVENT_REWRITER_H_