Browse Source

能正确输入中文

master
杨栋梁 2 years ago
parent
commit
99dcb3dbca
  1. 491
      Assets/ZFBrowser/Scripts/BrowserInput.cs

491
Assets/ZFBrowser/Scripts/BrowserInput.cs

@ -9,229 +9,266 @@ using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using UnityEngine; using UnityEngine;
namespace ZenFulcrum.EmbeddedBrowser { namespace ZenFulcrum.EmbeddedBrowser
{
/** Helper class for reading data from an IUIHandler, converting it, and feeding it to the native backend. */
internal class BrowserInput { /** Helper class for reading data from an IUIHandler, converting it, and feeding it to the native backend. */
internal class BrowserInput
private readonly Browser browser; {
public BrowserInput(Browser browser) { private readonly Browser browser;
this.browser = browser;
} public BrowserInput(Browser browser)
{
private bool kbWasFocused = false; this.browser = browser;
private bool mouseWasFocused = false; }
public void HandleInput() { private bool kbWasFocused = false;
browser.UIHandler.InputUpdate(); private bool mouseWasFocused = false;
bool focusChanged = false;
public void HandleInput()
if (browser.UIHandler.MouseHasFocus || mouseWasFocused) { {
HandleMouseInput(); browser.UIHandler.InputUpdate();
} bool focusChanged = false;
if (browser.UIHandler.MouseHasFocus != mouseWasFocused) {
browser.UIHandler.BrowserCursor.HasMouse = browser.UIHandler.MouseHasFocus; if (browser.UIHandler.MouseHasFocus || mouseWasFocused)
focusChanged = true; {
} HandleMouseInput();
mouseWasFocused = browser.UIHandler.MouseHasFocus; }
if (browser.UIHandler.MouseHasFocus != mouseWasFocused)
{
browser.UIHandler.BrowserCursor.HasMouse = browser.UIHandler.MouseHasFocus;
if (kbWasFocused != browser.UIHandler.KeyboardHasFocus) focusChanged = true; focusChanged = true;
}
if (browser.UIHandler.KeyboardHasFocus) { mouseWasFocused = browser.UIHandler.MouseHasFocus;
if (!kbWasFocused) {
BrowserNative.zfb_setFocused(browser.browserId, kbWasFocused = true);
}
HandleKeyInput(); if (kbWasFocused != browser.UIHandler.KeyboardHasFocus) focusChanged = true;
} else {
if (kbWasFocused) { if (browser.UIHandler.KeyboardHasFocus)
BrowserNative.zfb_setFocused(browser.browserId, kbWasFocused = false); {
} if (!kbWasFocused)
} {
BrowserNative.zfb_setFocused(browser.browserId, kbWasFocused = true);
if (focusChanged) { }
browser._RaiseFocusEvent(browser.UIHandler.MouseHasFocus, browser.UIHandler.KeyboardHasFocus); HandleKeyInput();
} }
} else
{
private static HashSet<KeyCode> keysToReleaseOnFocusLoss = new HashSet<KeyCode>(); if (kbWasFocused)
public List<Event> extraEventsToInject = new List<Event>(); {
BrowserNative.zfb_setFocused(browser.browserId, kbWasFocused = false);
private MouseButton prevButtons = 0; }
private Vector2 prevPos; }
private class ButtonHistory { if (focusChanged)
public float lastPressTime; {
public int repeatCount; browser._RaiseFocusEvent(browser.UIHandler.MouseHasFocus, browser.UIHandler.KeyboardHasFocus);
public Vector3 lastPosition; }
}
public void ButtonPress(Vector3 mousePos, IBrowserUI uiHandler, Vector2 browserSize) {
var now = Time.realtimeSinceStartup; private static HashSet<KeyCode> keysToReleaseOnFocusLoss = new HashSet<KeyCode>();
public List<Event> extraEventsToInject = new List<Event>();
if (now - lastPressTime > uiHandler.InputSettings.multiclickSpeed) {
//too long ago? forget the past private MouseButton prevButtons = 0;
repeatCount = 0; private Vector2 prevPos;
}
private class ButtonHistory
if (repeatCount > 0) { {
//close enough to be a multiclick? public float lastPressTime;
var p1 = Vector2.Scale(mousePos, browserSize); public int repeatCount;
var p2 = Vector2.Scale(lastPosition, browserSize); public Vector3 lastPosition;
if (Vector2.Distance(p1, p2) > uiHandler.InputSettings.multiclickTolerance) {
repeatCount = 0; public void ButtonPress(Vector3 mousePos, IBrowserUI uiHandler, Vector2 browserSize)
} {
} var now = Time.realtimeSinceStartup;
repeatCount++; if (now - lastPressTime > uiHandler.InputSettings.multiclickSpeed)
{
lastPressTime = now; //too long ago? forget the past
lastPosition = mousePos; repeatCount = 0;
} }
}
if (repeatCount > 0)
private readonly ButtonHistory leftClickHistory = new ButtonHistory(); {
//close enough to be a multiclick?
private void HandleMouseInput() { var p1 = Vector2.Scale(mousePos, browserSize);
var handler = browser.UIHandler; var p2 = Vector2.Scale(lastPosition, browserSize);
var mousePos = handler.MousePosition; if (Vector2.Distance(p1, p2) > uiHandler.InputSettings.multiclickTolerance)
{
var currentButtons = handler.MouseButtons; repeatCount = 0;
var mouseScroll = handler.MouseScroll; }
}
if (mousePos != prevPos) {
BrowserNative.zfb_mouseMove(browser.browserId, mousePos.x, 1 - mousePos.y); repeatCount++;
}
lastPressTime = now;
FeedScrolling(mouseScroll, handler.InputSettings.scrollSpeed); lastPosition = mousePos;
}
var leftChange = (prevButtons & MouseButton.Left) != (currentButtons & MouseButton.Left); }
var leftDown = (currentButtons & MouseButton.Left) == MouseButton.Left;
var middleChange = (prevButtons & MouseButton.Middle) != (currentButtons & MouseButton.Middle); private readonly ButtonHistory leftClickHistory = new ButtonHistory();
var middleDown = (currentButtons & MouseButton.Middle) == MouseButton.Middle;
var rightChange = (prevButtons & MouseButton.Right) != (currentButtons & MouseButton.Right); private void HandleMouseInput()
var rightDown = (currentButtons & MouseButton.Right) == MouseButton.Right; {
var handler = browser.UIHandler;
if (leftChange) { var mousePos = handler.MousePosition;
if (leftDown) leftClickHistory.ButtonPress(mousePos, handler, browser.Size);
BrowserNative.zfb_mouseButton( var currentButtons = handler.MouseButtons;
browser.browserId, BrowserNative.MouseButton.MBT_LEFT, leftDown, var mouseScroll = handler.MouseScroll;
leftDown ? leftClickHistory.repeatCount : 0
); if (mousePos != prevPos)
} {
if (middleChange) { BrowserNative.zfb_mouseMove(browser.browserId, mousePos.x, 1 - mousePos.y);
//no double-clicks, to be consistent with other browsers }
BrowserNative.zfb_mouseButton(
browser.browserId, BrowserNative.MouseButton.MBT_MIDDLE, middleDown, 1 FeedScrolling(mouseScroll, handler.InputSettings.scrollSpeed);
);
} var leftChange = (prevButtons & MouseButton.Left) != (currentButtons & MouseButton.Left);
if (rightChange) { var leftDown = (currentButtons & MouseButton.Left) == MouseButton.Left;
//no double-clicks, to be consistent with other browsers var middleChange = (prevButtons & MouseButton.Middle) != (currentButtons & MouseButton.Middle);
BrowserNative.zfb_mouseButton( var middleDown = (currentButtons & MouseButton.Middle) == MouseButton.Middle;
browser.browserId, BrowserNative.MouseButton.MBT_RIGHT, rightDown, 1 var rightChange = (prevButtons & MouseButton.Right) != (currentButtons & MouseButton.Right);
); var rightDown = (currentButtons & MouseButton.Right) == MouseButton.Right;
}
if (leftChange)
prevPos = mousePos; {
prevButtons = currentButtons; if (leftDown) leftClickHistory.ButtonPress(mousePos, handler, browser.Size);
} BrowserNative.zfb_mouseButton(
browser.browserId, BrowserNative.MouseButton.MBT_LEFT, leftDown,
private Vector2 accumulatedScroll; leftDown ? leftClickHistory.repeatCount : 0
private float lastScrollEvent; );
/// <summary> }
/// How often (in sec) we can send scroll events to the browser without it choking up. if (middleChange)
/// The right number seems to depend on how hard the page is to render, so there's not a perfect number. {
/// Hopefully this one works well, though. //no double-clicks, to be consistent with other browsers
/// </summary> BrowserNative.zfb_mouseButton(
private const float maxScrollEventRate = 1 / 15f; browser.browserId, BrowserNative.MouseButton.MBT_MIDDLE, middleDown, 1
);
/// <summary> }
/// Feeds scroll events to the browser. if (rightChange)
/// In particular, it will clump together scrolling "floods" into fewer larger scrolls {
/// to prevent the backend from getting choked up and taking forever to execute the requests. //no double-clicks, to be consistent with other browsers
/// </summary> BrowserNative.zfb_mouseButton(
/// <param name="mouseScroll"></param> browser.browserId, BrowserNative.MouseButton.MBT_RIGHT, rightDown, 1
private void FeedScrolling(Vector2 mouseScroll, float scrollSpeed) { );
accumulatedScroll += mouseScroll * scrollSpeed; }
if (accumulatedScroll.sqrMagnitude != 0 && Time.realtimeSinceStartup > lastScrollEvent + maxScrollEventRate) { prevPos = mousePos;
//Debug.Log("Do scroll: " + accumulatedScroll); prevButtons = currentButtons;
}
//The backend seems to have trouble coping with horizontal AND vertical scroll. So only do one at a time.
//(And if we do both at once, vertical appears to get priority and horizontal gets ignored.) private Vector2 accumulatedScroll;
private float lastScrollEvent;
if (Mathf.Abs(accumulatedScroll.x) > Mathf.Abs(accumulatedScroll.y)) { /// <summary>
BrowserNative.zfb_mouseScroll(browser.browserId, (int)accumulatedScroll.x, 0); /// How often (in sec) we can send scroll events to the browser without it choking up.
accumulatedScroll.x = 0; /// The right number seems to depend on how hard the page is to render, so there's not a perfect number.
accumulatedScroll.y = Mathf.Round(accumulatedScroll.y * .5f);//reduce the thing we weren't doing so it's less likely to accumulate strange /// Hopefully this one works well, though.
} else { /// </summary>
BrowserNative.zfb_mouseScroll(browser.browserId, 0, (int)accumulatedScroll.y); private const float maxScrollEventRate = 1 / 15f;
accumulatedScroll.x = Mathf.Round(accumulatedScroll.x * .5f);
accumulatedScroll.y = 0; /// <summary>
} /// Feeds scroll events to the browser.
/// In particular, it will clump together scrolling "floods" into fewer larger scrolls
lastScrollEvent = Time.realtimeSinceStartup; /// to prevent the backend from getting choked up and taking forever to execute the requests.
} /// </summary>
} /// <param name="mouseScroll"></param>
private void FeedScrolling(Vector2 mouseScroll, float scrollSpeed)
private void HandleKeyInput() { {
var keyEvents = browser.UIHandler.KeyEvents; accumulatedScroll += mouseScroll * scrollSpeed;
if (keyEvents.Count > 0) HandleKeyInput(keyEvents);
if (accumulatedScroll.sqrMagnitude != 0 && Time.realtimeSinceStartup > lastScrollEvent + maxScrollEventRate)
if (extraEventsToInject.Count > 0) { {
HandleKeyInput(extraEventsToInject); //Debug.Log("Do scroll: " + accumulatedScroll);
extraEventsToInject.Clear();
} //The backend seems to have trouble coping with horizontal AND vertical scroll. So only do one at a time.
} //(And if we do both at once, vertical appears to get priority and horizontal gets ignored.)
private void HandleKeyInput(List<Event> keyEvents) { if (Mathf.Abs(accumulatedScroll.x) > Mathf.Abs(accumulatedScroll.y))
{
BrowserNative.zfb_mouseScroll(browser.browserId, (int)accumulatedScroll.x, 0);
accumulatedScroll.x = 0;
accumulatedScroll.y = Mathf.Round(accumulatedScroll.y * .5f);//reduce the thing we weren't doing so it's less likely to accumulate strange
}
else
{
BrowserNative.zfb_mouseScroll(browser.browserId, 0, (int)accumulatedScroll.y);
accumulatedScroll.x = Mathf.Round(accumulatedScroll.x * .5f);
accumulatedScroll.y = 0;
}
lastScrollEvent = Time.realtimeSinceStartup;
}
}
private void HandleKeyInput()
{
var keyEvents = browser.UIHandler.KeyEvents;
if (keyEvents.Count > 0) HandleKeyInput(keyEvents);
if (extraEventsToInject.Count > 0)
{
HandleKeyInput(extraEventsToInject);
extraEventsToInject.Clear();
}
}
private void HandleKeyInput(List<Event> keyEvents)
{
#if ZF_OSX #if ZF_OSX
ReconstructInputs(keyEvents); ReconstructInputs(keyEvents);
#endif #endif
foreach (var ev in keyEvents) { foreach (var ev in keyEvents)
var keyCode = KeyMappings.GetWindowsKeyCode(ev); {
if (ev.character == '\n') ev.character = '\r';//'cuz that's what Chromium expects var keyCode = KeyMappings.GetWindowsKeyCode(ev);
if (ev.character == '\n') ev.character = '\r';//'cuz that's what Chromium expects
if (ev.character == 0) { if (ev.character == 0)
if (ev.type == EventType.KeyDown) keysToReleaseOnFocusLoss.Add(ev.keyCode); {
else keysToReleaseOnFocusLoss.Remove(ev.keyCode); if (ev.type == EventType.KeyDown) keysToReleaseOnFocusLoss.Add(ev.keyCode);
} else keysToReleaseOnFocusLoss.Remove(ev.keyCode);
}
// if (false) { // if (false) {
// if (ev.character != 0) Debug.Log("k >>> " + ev.character); // if (ev.character != 0) Debug.Log("k >>> " + ev.character);
// else if (ev.type == EventType.KeyUp) Debug.Log("k ^^^ " + ev.keyCode); // else if (ev.type == EventType.KeyUp) Debug.Log("k ^^^ " + ev.keyCode);
// else if (ev.type == EventType.KeyDown) Debug.Log("k vvv " + ev.keyCode); // else if (ev.type == EventType.KeyDown) Debug.Log("k vvv " + ev.keyCode);
// } // }
FireCommands(ev); FireCommands(ev);
if (ev.character != 0 && ev.type == EventType.KeyDown) { if (ev.character != 0 && ev.type == EventType.KeyDown)
{
#if ZF_LINUX #if ZF_LINUX
//It seems, on Linux, we don't get keydown, keypress, keyup, we just get a keypress, keyup. //It seems, on Linux, we don't get keydown, keypress, keyup, we just get a keypress, keyup.
//So, fire the keydown just before the keypress. //So, fire the keydown just before the keypress.
BrowserNative.zfb_keyEvent(browser.browserId, true, keyCode); BrowserNative.zfb_keyEvent(browser.browserId, true, keyCode);
//Thanks for being consistent, Unity. //Thanks for being consistent, Unity.
#endif #endif
Input.imeCompositionMode = IMECompositionMode.On;
BrowserNative.zfb_characterEvent(browser.browserId, ev.character, keyCode); BrowserNative.zfb_characterEvent(browser.browserId, ev.character, keyCode);
} else { }
BrowserNative.zfb_keyEvent(browser.browserId, ev.type == EventType.KeyDown, keyCode); else
} {
} BrowserNative.zfb_keyEvent(browser.browserId, ev.type == EventType.KeyDown, keyCode);
} }
}
public void HandleFocusLoss() { }
foreach (var keyCode in keysToReleaseOnFocusLoss) {
//Debug.Log("Key " + keyCode + " is held, release"); public void HandleFocusLoss()
var wCode = KeyMappings.GetWindowsKeyCode(new Event() { keyCode = keyCode }); {
BrowserNative.zfb_keyEvent(browser.browserId, false, wCode); foreach (var keyCode in keysToReleaseOnFocusLoss)
} {
//Debug.Log("Key " + keyCode + " is held, release");
keysToReleaseOnFocusLoss.Clear(); var wCode = KeyMappings.GetWindowsKeyCode(new Event() { keyCode = keyCode });
} BrowserNative.zfb_keyEvent(browser.browserId, false, wCode);
}
keysToReleaseOnFocusLoss.Clear();
}
#if ZF_OSX #if ZF_OSX
/** Used by ReconstructInputs */ /** Used by ReconstructInputs */
@ -282,14 +319,15 @@ internal class BrowserInput {
} }
#endif #endif
/** /**
* OS X + Unity has issues. * OS X + Unity has issues.
* Commands won't be run if the command is not in the application menu. * Commands won't be run if the command is not in the application menu.
* Here we trap keystrokes and manually fire the relevant events in the browser. * Here we trap keystrokes and manually fire the relevant events in the browser.
* *
* Also, ctrl+A stopped working with CEF at some point on Windows. * Also, ctrl+A stopped working with CEF at some point on Windows.
*/ */
protected void FireCommands(Event ev) { protected void FireCommands(Event ev)
{
#if ZF_OSX #if ZF_OSX
if (ev.type != EventType.KeyDown || ev.character != 0 || !ev.command) return; if (ev.type != EventType.KeyDown || ev.character != 0 || !ev.command) return;
@ -319,17 +357,18 @@ internal class BrowserInput {
} }
#else #else
//mmm, yeah. I guess Unity doesn't send us the keydown on a ctrl+a keystroke anymore. //mmm, yeah. I guess Unity doesn't send us the keydown on a ctrl+a keystroke anymore.
if (ev.type != EventType.KeyUp || !ev.control) return; if (ev.type != EventType.KeyUp || !ev.control) return;
switch (ev.keyCode) { switch (ev.keyCode)
case KeyCode.A: {
browser.SendFrameCommand(BrowserNative.FrameCommand.SelectAll); case KeyCode.A:
break; browser.SendFrameCommand(BrowserNative.FrameCommand.SelectAll);
} break;
}
#endif #endif
} }
} }
} }

Loading…
Cancel
Save