blob: 0fe3972ec33f17798fa212df80bbaf96f1702dac [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_WS_EVENT_QUEUE_H_
#define SERVICES_WS_EVENT_QUEUE_H_
#include <stdint.h>
#include <memory>
#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/timer/timer.h"
#include "services/ws/ids.h"
#include "services/ws/window_service_observer.h"
namespace aura {
class WindowTreeHost;
}
namespace ui {
class Event;
struct EventDispatchDetails;
}
namespace ws {
class WindowService;
// EventQueue handles queueing, waiting, and delivering events to event sinks.
// EventQueue tracks the dispatch by way of being a WindowServiceObserver.
// EventQueue also supports queueing callbacks run in order with queued events.
class COMPONENT_EXPORT(WINDOW_SERVICE) EventQueue
: public WindowServiceObserver {
public:
explicit EventQueue(WindowService* service);
~EventQueue() override;
// Queue the event if needed, or deliver it directly to the host's event sink.
// Call WindowTreeHost::SendEventToSink instead, if the event should be passed
// through the host's EventRewriters; that calls through here after rewriting.
base::Optional<ui::EventDispatchDetails> DeliverOrQueueEvent(
aura::WindowTreeHost* host,
ui::Event* event);
// Notifies |closure| when this EventQueue is ready to dispatch an event,
// which may be immediately.
void NotifyWhenReadyToDispatch(base::OnceClosure closure);
private:
friend class EventQueueTestHelper;
struct QueuedEvent;
// Tracks an event that was sent to a client.
struct InFlightEvent {
ClientSpecificId client_id = 0u;
uint32_t event_id = 0u;
};
// Returns true if |event| should be queued at this time for the given |host|.
bool ShouldQueueEvent(aura::WindowTreeHost* host, const ui::Event& event);
// Adds |event| to |queued_events_| for delivery to |host|.
void QueueEvent(aura::WindowTreeHost* host, const ui::Event& event);
// Called by |ack_timer_| if the client does not respond to the event in a
// timely manner.
void OnClientTookTooLongToAckEvent();
// Processes QueuedEvents until |queued_events_| is empty, or there is an
// event sent to a client.
void DispatchNextQueuedEvent();
// WindowServiceObserver:
void OnWillSendEventToClient(ClientSpecificId client_id,
uint32_t event_id,
const ui::Event& event) override;
void OnClientAckedEvent(ClientSpecificId client_id,
uint32_t event_id) override;
void OnWillDestroyClient(ClientSpecificId client_id) override;
WindowService* window_service_;
base::circular_deque<std::unique_ptr<QueuedEvent>> queued_events_;
// Set when an event has been sent to a client.
base::Optional<InFlightEvent> in_flight_event_;
base::OneShotTimer ack_timer_;
// Because of destruction order HostEventQueues may outlive this.
base::WeakPtrFactory<EventQueue> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(EventQueue);
};
} // namespace ws
#endif // SERVICES_WS_EVENT_QUEUE_H_