mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This corrects the button state emitted on synthetic pointer move and hover events generated by the engine. When an embedder notifies the engine of a pointer up or down event, and the pointer's position has changed since the last move or hover event, `PointerDataPacketConverter` generates a synthetic move or hover to notify the framework of the change in position. In these cases, the current event from the embedder contains the new button state *after* the pointer up/down event, but the move/hover needs to be synthesized such that it occurs *before* the pointer up/down, with the previous button state. This patch stores the button state after each pointer down, up, move, or hover event such that it can be used by the next event if a synthetic event must be issued. The bug in the previous logic was revealed by the release of macOS 11 (Big Sur), which appears to issue move events between mouse down and mouse up, which did not use to be the case. This fixes https://github.com/flutter/flutter/issues/64961, which is the desktop-specific tracking bug for the more general Big Sur mouse click umbrella issue https://github.com/flutter/flutter/issues/71190.
119 lines
4.2 KiB
C++
119 lines
4.2 KiB
C++
// Copyright 2013 The Flutter 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 FLUTTER_LIB_UI_WINDOW_POINTER_DATA_PACKET_CONVERTER_H_
|
|
#define FLUTTER_LIB_UI_WINDOW_POINTER_DATA_PACKET_CONVERTER_H_
|
|
|
|
#include <cstring>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "flutter/fml/macros.h"
|
|
#include "flutter/lib/ui/window/pointer_data_packet.h"
|
|
|
|
namespace flutter {
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// The current information about a pointer.
|
|
///
|
|
/// This struct is used by PointerDataPacketConverter to fill in necessary
|
|
/// information for the raw pointer packet sent from embedding. This struct also
|
|
/// stores the button state of the last pointer down, up, move, or hover event.
|
|
/// When an embedder issues a pointer up or down event where the pointer's
|
|
/// position has changed since the last move or hover event,
|
|
/// PointerDataPacketConverter generates a synthetic move or hover to notify the
|
|
/// framework. In these cases, these events must be issued with the button state
|
|
/// prior to the pointer up or down.
|
|
///
|
|
struct PointerState {
|
|
int64_t pointer_identifier;
|
|
bool isDown;
|
|
double physical_x;
|
|
double physical_y;
|
|
int64_t buttons;
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Converter to convert the raw pointer data packet from the platforms.
|
|
///
|
|
/// Framework requires certain information to process pointer data. e.g. pointer
|
|
/// identifier and the delta of pointer moment. The converter keeps track each
|
|
/// pointer state and fill in those information appropriately.
|
|
///
|
|
/// The converter is also resposible for providing a clean pointer data stream.
|
|
/// It will attempt to correct the stream if the it contains illegal pointer
|
|
/// transitions.
|
|
///
|
|
/// Example 1 Missing Add:
|
|
///
|
|
/// Down(position x) -> Up(position x)
|
|
///
|
|
/// ###After Conversion###
|
|
///
|
|
/// Synthesized_Add(position x) -> Down(position x) -> Up(position x)
|
|
///
|
|
/// Example 2 Missing another move:
|
|
///
|
|
/// Add(position x) -> Down(position x) -> Move(position y) ->
|
|
/// Up(position z)
|
|
///
|
|
/// ###After Conversion###
|
|
///
|
|
/// Add(position x) -> Down(position x) -> Move(position y) ->
|
|
/// Synthesized_Move(position z) -> Up(position z)
|
|
///
|
|
/// Platform view is the only client that uses this class to convert all the
|
|
/// incoming pointer packet and is responsible for the life cycle of its
|
|
/// instance.
|
|
///
|
|
class PointerDataPacketConverter {
|
|
public:
|
|
PointerDataPacketConverter();
|
|
~PointerDataPacketConverter();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Converts pointer data packet into a form that framework
|
|
/// understands. The raw pointer data packet from embedding does
|
|
/// not have sufficient information and may contain illegal
|
|
/// pointer transitions. This method will fill out that
|
|
/// information and attempt to correct pointer transitions.
|
|
///
|
|
/// @param[in] packet The raw pointer packet sent from
|
|
/// embedding.
|
|
///
|
|
/// @return A full converted packet with all the required information
|
|
/// filled.
|
|
/// It may contain synthetic pointer data as the result of
|
|
/// converter's attempt to correct illegal pointer transitions.
|
|
///
|
|
std::unique_ptr<PointerDataPacket> Convert(
|
|
std::unique_ptr<PointerDataPacket> packet);
|
|
|
|
private:
|
|
std::map<int64_t, PointerState> states_;
|
|
|
|
int64_t pointer_;
|
|
|
|
void ConvertPointerData(PointerData pointer_data,
|
|
std::vector<PointerData>& converted_pointers);
|
|
|
|
PointerState EnsurePointerState(PointerData pointer_data);
|
|
|
|
void UpdateDeltaAndState(PointerData& pointer_data, PointerState& state);
|
|
|
|
void UpdatePointerIdentifier(PointerData& pointer_data,
|
|
PointerState& state,
|
|
bool start_new_pointer);
|
|
|
|
bool LocationNeedsUpdate(const PointerData pointer_data,
|
|
const PointerState state);
|
|
|
|
FML_DISALLOW_COPY_AND_ASSIGN(PointerDataPacketConverter);
|
|
};
|
|
|
|
} // namespace flutter
|
|
|
|
#endif // FLUTTER_LIB_UI_WINDOW_POINTER_DATA_PACKET_CONVERTER_H_
|