浏览代码

Merge branch 'master' of https://github.com/UnityTech/UIWidgets into fix_emoji

/main
Yuncong Zhang 5 年前
当前提交
398ed9cc
共有 9 个文件被更改,包括 306 次插入100 次删除
  1. 15
      Runtime/editor/editor_window.cs
  2. 5
      Runtime/engine/input_utils.cs
  3. 2
      Runtime/gestures/recognizer.cs
  4. 234
      Runtime/gestures/tap.cs
  5. 12
      Runtime/rendering/editable.cs
  6. 66
      Runtime/service/keyboard.cs
  7. 14
      Runtime/service/text_input.cs
  8. 22
      Runtime/widgets/editable_text.cs
  9. 36
      Runtime/widgets/selectable_text.cs

15
Runtime/editor/editor_window.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.async;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;

timeStamp: Timer.timespanSinceStartup,
change: PointerChange.down,
kind: PointerDeviceKind.mouse,
device: evt.button,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);

timeStamp: Timer.timespanSinceStartup,
change: PointerChange.up,
kind: PointerDeviceKind.mouse,
device: evt.button,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);

timeStamp: Timer.timespanSinceStartup,
change: PointerChange.move,
kind: PointerDeviceKind.mouse,
device: evt.button,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);

timeStamp: Timer.timespanSinceStartup,
change: PointerChange.hover,
kind: PointerDeviceKind.mouse,
device: evt.button,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);

-evt.delta.y * this._devicePixelRatio,
evt.mousePosition.x * this._devicePixelRatio,
evt.mousePosition.y * this._devicePixelRatio,
evt.button
InputUtils.getMouseButtonKey(evt.button)
);
}
else if (evt.type == EventType.DragUpdated) {

kind: PointerDeviceKind.mouse,
device: evt.button,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);

timeStamp: Timer.timespanSinceStartup,
change: PointerChange.dragFromEditorRelease,
kind: PointerDeviceKind.mouse,
device: evt.button,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);

5
Runtime/engine/input_utils.cs


using UnityEngine.EventSystems;
namespace Unity.UIWidgets.engine {
static class InputUtils {
public static class InputUtils {
public const int MouseLeftKeyDevice = preservedKeyNum;
public const int MouseRightKeyDevice = preservedKeyNum + 1;
public static PointerDeviceKind getPointerDeviceKind(PointerEventData eventData) {
return isTouchEvent(eventData) ? PointerDeviceKind.touch : PointerDeviceKind.mouse;

2
Runtime/gestures/recognizer.cs


protected virtual void handleNonAllowedPointer(PointerDownEvent evt) {
}
protected bool isPointerAllowed(PointerDownEvent evt) {
protected virtual bool isPointerAllowed(PointerDownEvent evt) {
return this._kind == null || this._kind == evt.kind;
}

234
Runtime/gestures/tap.cs


namespace Unity.UIWidgets.gestures {
public class TapDownDetails {
public TapDownDetails(Offset globalPosition = null) {
public TapDownDetails(Offset globalPosition = null,
Offset localPosition = null,
PointerDeviceKind kind = PointerDeviceKind.touch,
int device = 0) {
this.localPosition = localPosition ?? this.globalPosition;
this.kind = kind;
this.device = device;
public readonly Offset localPosition;
public readonly PointerDeviceKind kind;
public readonly int device;
public TapUpDetails(Offset globalPosition = null) {
public TapUpDetails(Offset globalPosition = null,
Offset localPosition = null,
PointerDeviceKind kind = PointerDeviceKind.touch,
int device = 0) {
this.localPosition = localPosition ?? this.globalPosition;
this.kind = kind;
this.device = device;
public readonly Offset localPosition;
public readonly PointerDeviceKind kind;
public readonly int device;
}
public delegate void GestureTapUpCallback(TapUpDetails details);

public delegate void GestureTapCancelCallback();
public class TapGestureRecognizer : PrimaryPointerGestureRecognizer {
public TapGestureRecognizer(object debugOwner = null)
: base(deadline: Constants.kPressTimeout, debugOwner: debugOwner) { }
public GestureTapDownCallback onTapDown;
public abstract class BaseTapGestureRecognizer : PrimaryPointerGestureRecognizer {
public BaseTapGestureRecognizer(object debugOwner = null)
: base(deadline: Constants.kPressTimeout, debugOwner: debugOwner) {
}
public GestureTapUpCallback onTapUp;
bool _sentTapDown = false;
bool _wonArenaForPrimaryPointer = false;
public GestureTapCallback onTap;
PointerDownEvent _down;
PointerUpEvent _up;
public GestureTapCancelCallback onTapCancel;
protected abstract void handleTapDown(PointerDownEvent down);
bool _sentTapDown = false;
protected abstract void handleTapUp(PointerDownEvent down, PointerUpEvent up);
bool _wonArenaForPrimaryPointer = false;
protected abstract void handleTapCancel(PointerDownEvent down, PointerCancelEvent cancel, string reason);
Offset _finalPosition;
public override void addAllowedPointer(PointerDownEvent evt) {
if (this.state == GestureRecognizerState.ready) {
this._down = evt;
}
base.addAllowedPointer(evt);
}
this._finalPosition = evt.position;
if (this._wonArenaForPrimaryPointer) {
this.resolve(GestureDisposition.accepted);
this._checkUp();
}
}
else if (evt is PointerCancelEvent) {
if (this._sentTapDown && this.onTapCancel != null) {
this.invokeCallback<object>("onTapCancel", () => this.onTapCancel);
this._up = (PointerUpEvent) evt;
this._checkUp();
} else if (evt is PointerCancelEvent) {
this.resolve(GestureDisposition.rejected);
if (this._sentTapDown) {
this._checkCancel((PointerCancelEvent) evt, "");
} else if (evt.buttons != this._down?.buttons) {
this.resolve(GestureDisposition.rejected);
this.stopTrackingPointer(this.primaryPointer);
}
}

if (this.onTapCancel != null) {
this.invokeCallback<object>("spontaneous onTapCancel", () => {
this.onTapCancel();
return null;
});
}
this._checkCancel(null, "spontaneous");
base.resolve(disposition);
}

public override void acceptGesture(int pointer) {
base.acceptGesture(pointer);
if (pointer == this.primaryPointer) {
this._checkDown();
this._wonArenaForPrimaryPointer = true;

public override void rejectGesture(int pointer) {
base.rejectGesture(pointer);
if (pointer == this.primaryPointer) {
if (this._sentTapDown && this.onTapCancel != null) {
this.invokeCallback<object>("forced onTapCancel", () => {
this.onTapCancel();
return null;
});
D.assert(this.state != GestureRecognizerState.possible);
if (this._sentTapDown) {
this._checkCancel(null, "forced");
}
this._reset();

void _checkDown() {
if (!this._sentTapDown) {
if (this.onTapDown != null) {
this.invokeCallback<object>("onTapDown", () => {
this.onTapDown(new TapDownDetails(globalPosition: this.initialPosition));
return null;
});
}
this._sentTapDown = true;
if (this._sentTapDown) {
return;
this.handleTapDown(down: this._down);
this._sentTapDown = true;
if (this._finalPosition != null) {
if (this.onTapUp != null) {
this.invokeCallback<object>("onTapUp", () => {
this.onTapUp(new TapUpDetails(globalPosition: this._finalPosition));
return null;
});
}
if (this.onTap != null) {
this.invokeCallback<object>("onTap", () => {
this.onTap();
return null;
});
}
if (!this._wonArenaForPrimaryPointer || this._up == null) {
return;
}
this.handleTapUp(down: this._down, up: this._up);
this._reset();
}
this._reset();
}
void _checkCancel(PointerCancelEvent evt, string note) {
this.handleTapCancel(down: this._down, cancel: evt, reason: note);
this._finalPosition = null;
this._up = null;
this._down = null;
get { return "tap"; }
get { return "base tap"; }
properties.add(new FlagProperty("wonArenaForPrimaryPointer",
value: this._wonArenaForPrimaryPointer,
ifTrue: "won arena"));
properties.add(new DiagnosticsProperty<Offset>("finalPosition",
this._finalPosition, defaultValue: Diagnostics.kNullDefaultValue));
properties.add(new FlagProperty("sentTapDown",
value: this._sentTapDown, ifTrue: "sent tap down"));
properties.add(new FlagProperty("wonArenaForPrimaryPointer", value: this._wonArenaForPrimaryPointer, ifTrue: "won arena"));
properties.add(new DiagnosticsProperty<Offset>("finalPosition", this._up?.position, defaultValue: null));
properties.add(new DiagnosticsProperty<Offset>("finalLocalPosition", this._up?.position, defaultValue: this._up?.position));
properties.add(new DiagnosticsProperty<int>("button", this._down?.buttons?? 0, defaultValue: 0));
properties.add(new FlagProperty("sentTapDown", value: this._sentTapDown, ifTrue: "sent tap down"));
}
}
public class TapGestureRecognizer : BaseTapGestureRecognizer {
public TapGestureRecognizer(object debugOwner = null) : base(debugOwner: debugOwner) {
}
public GestureTapDownCallback onTapDown;
public GestureTapUpCallback onTapUp;
public GestureTapCallback onTap;
public GestureTapCancelCallback onTapCancel;
public GestureTapDownCallback onSecondaryTapDown;
public GestureTapUpCallback onSecondaryTapUp;
public GestureTapCancelCallback onSecondaryTapCancel;
protected override bool isPointerAllowed(PointerDownEvent evt) {
if (this.onTapDown == null &&
this.onTap == null &&
this.onTapUp == null &&
this.onTapCancel == null) {
return false;
}
return base.isPointerAllowed(evt);
}
protected override void handleTapDown(PointerDownEvent down) {
if (this.onTapDown != null) {
TapDownDetails details = new TapDownDetails(
globalPosition: down.position,
kind: down.kind,
device: down.device
);
this.invokeCallback<object>("onTapDown", () => {
this.onTapDown(details);
return null;
});
}
}
protected override void handleTapUp(PointerDownEvent down, PointerUpEvent up) {
TapUpDetails details = new TapUpDetails(
globalPosition: up.position,
kind: up.kind,
device: up.device
);
if (this.onTapUp != null) {
this.invokeCallback<object>("onTapUp", () => {
this.onTapUp(details);
return null;
});
}
if (this.onTap != null) {
this.invokeCallback<object>("onTap", () => {
this.onTap();
return null;
});
}
}
protected override void handleTapCancel(PointerDownEvent down, PointerCancelEvent cancel, string note) {
if (this.onTapCancel != null) {
this.invokeCallback<object>("onTapCancel", () => {
this.onTapCancel();
return null;
});
}
}
public override string debugDescription {
get { return "tap"; }
}
}
}

12
Runtime/rendering/editable.cs


using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;

float devicePixelRatio = 1.0f,
bool? enableInteractiveSelection = null,
EdgeInsets floatingCursorAddedMargin = null,
TextSelectionDelegate textSelectionDelegate = null) {
TextSelectionDelegate textSelectionDelegate = null,
GlobalKeyEventHandlerDelegate globalKeyEventHandler = null) {
floatingCursorAddedMargin = floatingCursorAddedMargin ?? EdgeInsets.fromLTRB(4, 4, 4, 5);
D.assert(textSelectionDelegate != null);
D.assert(minLines == null || minLines > 0);

this.onCaretChanged = onCaretChanged;
this.onSelectionChanged = onSelectionChanged;
this.textSelectionDelegate = textSelectionDelegate;
this.globalKeyEventHandler = globalKeyEventHandler;
D.assert(this._maxLines == null || this._maxLines > 0);
D.assert(this._showCursor != null);

}
public TextSelectionDelegate textSelectionDelegate;
public GlobalKeyEventHandlerDelegate globalKeyEventHandler;
Rect _lastCaretRect;

if (this.selection.isCollapsed) {
this._extentOffset = this.selection.extentOffset;
this._baseOffset = this.selection.baseOffset;
}
if (this.globalKeyEventHandler?.Invoke(keyEvent, false)?.swallow ?? false) {
return;
}
KeyCode pressedKeyCode = keyEvent.data.unityEvent.keyCode;

66
Runtime/service/keyboard.cs


using Unity.UIWidgets.ui;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public delegate RawInputKeyResponse GlobalKeyEventHandlerDelegate(RawKeyEvent rawEvt, bool enableCustomAction = false);
public class RawInputKeyResponse {
public readonly bool swallow;
public readonly char input;
public readonly TextInputAction? inputAction;
public RawInputKeyResponse(bool swallow, char input = '\0', TextInputAction? inputAction = null) {
this.swallow = swallow;
this.input = input;
this.inputAction = inputAction;
}
public static RawInputKeyResponse convert(RawKeyEvent evt) {
return new RawInputKeyResponse(
false,
evt.data.unityEvent.character,
null);
}
public static readonly RawInputKeyResponse swallowResponse = new RawInputKeyResponse(true, '\0', null);
}
interface KeyboardDelegate: IDisposable {
void show();

public void setEditingState(TextEditingValue value) {
this._value = value;
}
Offset _editorWindowPosToScreenPos(Offset position) {
#if UNITY_EDITOR_WIN
return position * EditorGUIUtility.pixelsPerPoint;
#elif UNITY_EDITOR_OSX
//locate the IME 30 logical pixels lower than the caret
var offsetY = 30f;
return new Offset(position.dx, position.dy + offsetY);
#else
return position;
#endif
}
if (uiWidgetWindowAdapter != null) {
var screenPos = uiWidgetWindowAdapter.windowPosToScreenPos(imeGlobalPos);
Input.compositionCursorPos = new Vector2(screenPos.dx, screenPos.dy);
}
else { // editor window case
Input.compositionCursorPos = new Vector2(imeGlobalPos.dx, imeGlobalPos.dy);
}
Offset screenPos = uiWidgetWindowAdapter != null
? uiWidgetWindowAdapter.windowPosToScreenPos(imeGlobalPos)
: this._editorWindowPosToScreenPos(imeGlobalPos);
Input.compositionCursorPos = new Vector2(screenPos.dx, screenPos.dy);
}
public void setClient(int client, TextInputConfiguration configuration) {

var currentEvent = Event.current;
var oldValue = this._value;
if (currentEvent.keyCode == KeyCode.Backspace) {
var response = TextInput._handleGlobalInputKey(this._client,
new RawKeyDownEvent(new RawKeyEventData(currentEvent)));
if (response.swallow) {
if (response.inputAction != null) {
Window.instance.run(() => { TextInput._performAction(this._client, response.inputAction.Value); });
}
if (_validateCharacter(response.input)) {
this._value = this._value.insert(new string(response.input, 1));
}
} else if (currentEvent.keyCode == KeyCode.Backspace) {
if (this._value.selection.isValid) {
this._value = this._value.deleteSelection(true);
}

14
Runtime/service/text_input.cs


void performAction(TextInputAction action);
void updateFloatingCursor(RawFloatingCursorPoint point);
RawInputKeyResponse globalInputKeyHandler(RawKeyEvent evt);
}
public enum TextInputAction {

}
_currentConnection._client.performAction(action);
}
internal static RawInputKeyResponse _handleGlobalInputKey(int client, RawKeyEvent evt) {
if (_currentConnection == null) {
return RawInputKeyResponse.convert(evt);
}
if (client != _currentConnection._id) {
return RawInputKeyResponse.convert(evt);
}
return _currentConnection._client.globalInputKeyHandler(evt);
}
static bool _hidePending = false;

22
Runtime/widgets/editable_text.cs


Brightness? keyboardAppearance = Brightness.light,
DragStartBehavior dragStartBehavior = DragStartBehavior.down,
bool? enableInteractiveSelection = null,
ScrollPhysics scrollPhysics = null
ScrollPhysics scrollPhysics = null,
GlobalKeyEventHandlerDelegate globalKeyEventHandler = null
) : base(key) {
D.assert(controller != null);
D.assert(focusNode != null);

this.enableInteractiveSelection = enableInteractiveSelection;
this.dragStartBehavior = dragStartBehavior;
this.scrollPhysics = scrollPhysics;
this.globalKeyEventHandler = globalKeyEventHandler;
}
public readonly TextEditingController controller;

public readonly DragStartBehavior dragStartBehavior;
public readonly bool? enableInteractiveSelection;
public readonly ScrollPhysics scrollPhysics;
public readonly GlobalKeyEventHandlerDelegate globalKeyEventHandler;
public bool selectionEnabled {
get { return this.enableInteractiveSelection ?? !this.obscureText; }

curve: Curves.decelerate);
break;
}
}
public RawInputKeyResponse globalInputKeyHandler(RawKeyEvent evt) {
return this.widget.globalKeyEventHandler?.Invoke(evt, true) ?? RawInputKeyResponse.convert(evt);
}
void _onFloatingCursorResetTick() {

paintCursorAboveText: this.widget.paintCursorAboveText,
enableInteractiveSelection: this.widget.enableInteractiveSelection == true,
textSelectionDelegate: this,
devicePixelRatio: this._devicePixelRatio
devicePixelRatio: this._devicePixelRatio,
globalKeyEventHandler : this.widget.globalKeyEventHandler
)
)
);

public readonly TextSelectionDelegate textSelectionDelegate;
public readonly bool? paintCursorAboveText;
public readonly float? devicePixelRatio;
public readonly GlobalKeyEventHandlerDelegate globalKeyEventHandler;
public _Editable(TextSpan textSpan = null,
TextEditingValue value = null,

Offset cursorOffset = null,
bool enableInteractiveSelection = true,
bool? paintCursorAboveText = null,
float? devicePixelRatio = null) : base(key) {
float? devicePixelRatio = null,
GlobalKeyEventHandlerDelegate globalKeyEventHandler = null) : base(key) {
this.textSpan = textSpan;
this.value = value;
this.cursorColor = cursorColor;

this.enableInteractiveSelection = enableInteractiveSelection;
this.paintCursorAboveText = paintCursorAboveText;
this.devicePixelRatio = devicePixelRatio;
this.globalKeyEventHandler = globalKeyEventHandler;
}
public override RenderObject createRenderObject(BuildContext context) {

enableInteractiveSelection: this.enableInteractiveSelection,
textSelectionDelegate: this.textSelectionDelegate,
paintCursorAboveText: this.paintCursorAboveText == true,
devicePixelRatio: this.devicePixelRatio ?? 1.0f
devicePixelRatio: this.devicePixelRatio ?? 1.0f,
globalKeyEventHandler : this.globalKeyEventHandler
);
}

edit.enableInteractiveSelection = this.enableInteractiveSelection;
edit.paintCursorAboveText = this.paintCursorAboveText == true;
edit.devicePixelRatio = this.devicePixelRatio ?? 1.0f;
edit.globalKeyEventHandler = this.globalKeyEventHandler;
}
}
}

36
Runtime/widgets/selectable_text.cs


using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Color = Unity.UIWidgets.ui.Color;
using Constants = Unity.UIWidgets.gestures.Constants;
using TextStyle = Unity.UIWidgets.painting.TextStyle;

float? textScaleFactor = null,
int? maxLines = null,
FocusNode focusNode = null,
Color selectionColor = null) : base(key) {
Color selectionColor = null,
GestureTapDownCallback onTapDown = null,
GestureTapUpCallback onTapUp = null,
GestureTapCancelCallback onTapCancel = null) : base(key) {
D.assert(data != null);
this.textSpan = null;
this.data = data;

this.maxLines = maxLines;
this.focusNode = focusNode ?? new FocusNode();
this.selectionColor = selectionColor;
this.onTapDown = onTapDown;
this.onTapUp = onTapUp;
this.onTapCancel = onTapCancel;
}
public SelectableText(TextSpan textSpan,

float? textScaleFactor = null,
int? maxLines = null,
FocusNode focusNode = null,
Color selectionColor = null) : base(key) {
Color selectionColor = null,
GestureTapDownCallback onTapDown = null,
GestureTapUpCallback onTapUp = null,
GestureTapCancelCallback onTapCancel = null) : base(key) {
D.assert(textSpan != null);
this.textSpan = textSpan;
this.data = null;

this.maxLines = maxLines;
this.focusNode = focusNode ?? new FocusNode();
this.selectionColor = selectionColor;
this.onTapDown = onTapDown;
this.onTapUp = onTapUp;
this.onTapCancel = onTapCancel;
}
public static SelectableText rich(TextSpan textSpan,

float? textScaleFactor = null,
int? maxLines = null,
FocusNode focusNode = null,
Color selectionColor = null) {
Color selectionColor = null,
GestureTapDownCallback onTapDown = null,
GestureTapUpCallback onTapUp = null,
GestureTapCancelCallback onTapCancel = null) {
return new SelectableText(
textSpan, key,
style,

textScaleFactor,
maxLines,
focusNode,
selectionColor);
selectionColor,
onTapDown,
onTapUp,
onTapCancel);
}
public readonly string data;

public readonly int? maxLines;
public readonly Color selectionColor;
public readonly GestureTapDownCallback onTapDown;
public readonly GestureTapUpCallback onTapUp;
public readonly GestureTapCancelCallback onTapCancel;
public override State createState() {
return new _SelectableTextState();

}
void _handleTapDown(TapDownDetails details) {
this.widget.onTapDown?.Invoke(details);
this.widget.onTapUp?.Invoke(details);
this.widget.onTapCancel?.Invoke();
}
void _handleLongPress() {

正在加载...
取消
保存