Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
sxychenjing
engine
提交
a9ef2410
E
engine
项目概览
sxychenjing
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
a9ef2410
编写于
11月 05, 2019
作者:
M
Mouad Debbar
提交者:
GitHub
11月 05, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[web] Don't send keyboard events from text fields to flutter (#13699)
上级
6c763bb5
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
131 addition
and
1 deletion
+131
-1
lib/web_ui/dev/chrome.dart
lib/web_ui/dev/chrome.dart
+1
-0
lib/web_ui/lib/src/engine/keyboard.dart
lib/web_ui/lib/src/engine/keyboard.dart
+35
-0
lib/web_ui/lib/src/engine/text_editing/text_editing.dart
lib/web_ui/lib/src/engine/text_editing/text_editing.dart
+10
-0
lib/web_ui/test/keyboard_test.dart
lib/web_ui/test/keyboard_test.dart
+85
-1
未找到文件。
lib/web_ui/dev/chrome.dart
浏览文件 @
a9ef2410
...
...
@@ -60,6 +60,7 @@ class Chrome extends Browser {
'--window-size=
$kMaxScreenshotWidth
,
$kMaxScreenshotHeight
'
,
// When headless, this is the actual size of the viewport
'--disable-extensions'
,
'--disable-popup-blocking'
,
// Indicates that the browser is in "browse without sign-in" (Guest session) mode.
'--bwsi'
,
'--no-first-run'
,
'--no-default-browser-check'
,
...
...
lib/web_ui/lib/src/engine/keyboard.dart
浏览文件 @
a9ef2410
...
...
@@ -4,6 +4,23 @@
part of
engine
;
/// Contains a whitelist of keys that must be sent to Flutter under all
/// circumstances.
///
/// When keys are pressed in a text field, we generally don't want to send them
/// to Flutter. This list of keys is the exception to that rule. Keys in this
/// list will be sent to Flutter even if pressed in a text field.
///
/// A good example is the "Tab" and "Shift" keys which are used by the framework
/// to move focus between text fields.
const
List
<
String
>
_alwaysSentKeys
=
<
String
>[
'Alt'
,
'Control'
,
'Meta'
,
'Shift'
,
'Tab'
,
];
/// Provides keyboard bindings, such as the `flutter/keyevent` channel.
class
Keyboard
{
/// Initializes the [Keyboard] singleton.
...
...
@@ -50,6 +67,10 @@ class Keyboard {
static
const
JSONMessageCodec
_messageCodec
=
JSONMessageCodec
();
void
_handleHtmlEvent
(
html
.
KeyboardEvent
event
)
{
if
(
_shouldIgnoreEvent
(
event
))
{
return
;
}
if
(
_shouldPreventDefault
(
event
))
{
event
.
preventDefault
();
}
...
...
@@ -66,6 +87,20 @@ class Keyboard {
_messageCodec
.
encodeMessage
(
eventData
),
_noopCallback
);
}
/// Whether the [Keyboard] class should ignore the given [html.KeyboardEvent].
///
/// When this method returns true, it prevents the keyboard event from being
/// sent to Flutter.
bool
_shouldIgnoreEvent
(
html
.
KeyboardEvent
event
)
{
// Keys in the [_alwaysSentKeys] list should never be ignored.
if
(
_alwaysSentKeys
.
contains
(
event
.
key
))
{
return
false
;
}
// Other keys should be ignored if triggered on a text field.
return
event
.
target
is
html
.
Element
&&
HybridTextEditing
.
isEditingElement
(
event
.
target
);
}
bool
_shouldPreventDefault
(
html
.
KeyboardEvent
event
)
{
switch
(
event
.
key
)
{
case
'Tab'
:
...
...
lib/web_ui/lib/src/engine/text_editing/text_editing.dart
浏览文件 @
a9ef2410
...
...
@@ -17,6 +17,8 @@ void _emptyCallback(dynamic _) {}
///
/// They are assigned once during the creation of the DOM element.
void
_setStaticStyleAttributes
(
html
.
HtmlElement
domElement
)
{
domElement
.
classes
.
add
(
HybridTextEditing
.
textEditingClass
);
final
html
.
CssStyleDeclaration
elementStyle
=
domElement
.
style
;
elementStyle
..
whiteSpace
=
'pre-wrap'
...
...
@@ -534,6 +536,14 @@ class HybridTextEditing {
return
_defaultEditingElement
;
}
/// A CSS class name used to identify all elements used for text editing.
@visibleForTesting
static
const
String
textEditingClass
=
'flt-text-editing'
;
static
bool
isEditingElement
(
html
.
Element
element
)
{
return
element
.
classes
.
contains
(
textEditingClass
);
}
/// Requests that [customEditingElement] is used for managing text editing state
/// instead of the hidden default element.
///
...
...
lib/web_ui/test/keyboard_test.dart
浏览文件 @
a9ef2410
...
...
@@ -13,6 +13,17 @@ import 'package:test/test.dart';
void
main
(
)
{
group
(
'Keyboard'
,
()
{
/// Used to save and restore [ui.window.onPlatformMessage] after each test.
ui
.
PlatformMessageCallback
savedCallback
;
setUp
(()
{
savedCallback
=
ui
.
window
.
onPlatformMessage
;
});
tearDown
(()
{
ui
.
window
.
onPlatformMessage
=
savedCallback
;
});
test
(
'initializes and disposes'
,
()
{
expect
(
Keyboard
.
instance
,
isNull
);
Keyboard
.
initialize
();
...
...
@@ -204,6 +215,12 @@ void main() {
test
(
'prevents default when "Tab" is pressed'
,
()
{
Keyboard
.
initialize
();
int
count
=
0
;
ui
.
window
.
onPlatformMessage
=
(
String
channel
,
ByteData
data
,
ui
.
PlatformMessageResponseCallback
callback
)
{
count
+=
1
;
};
final
html
.
KeyboardEvent
event
=
dispatchKeyboardEvent
(
'keydown'
,
key:
'Tab'
,
...
...
@@ -211,14 +228,78 @@ void main() {
);
expect
(
event
.
defaultPrevented
,
isTrue
);
expect
(
count
,
1
);
Keyboard
.
instance
.
dispose
();
});
test
(
'ignores keyboard events triggered on text fields'
,
()
{
Keyboard
.
initialize
();
int
count
=
0
;
ui
.
window
.
onPlatformMessage
=
(
String
channel
,
ByteData
data
,
ui
.
PlatformMessageResponseCallback
callback
)
{
count
+=
1
;
};
useTextEditingElement
((
html
.
Element
element
)
{
final
html
.
KeyboardEvent
event
=
dispatchKeyboardEvent
(
'keydown'
,
key:
'SomeKey'
,
code:
'SomeCode'
,
target:
element
,
);
expect
(
event
.
defaultPrevented
,
isFalse
);
expect
(
count
,
0
);
});
Keyboard
.
instance
.
dispose
();
});
test
(
'the "Tab" key should never be ignored'
,
()
{
Keyboard
.
initialize
();
int
count
=
0
;
ui
.
window
.
onPlatformMessage
=
(
String
channel
,
ByteData
data
,
ui
.
PlatformMessageResponseCallback
callback
)
{
count
+=
1
;
};
useTextEditingElement
((
html
.
Element
element
)
{
final
html
.
KeyboardEvent
event
=
dispatchKeyboardEvent
(
'keydown'
,
key:
'Tab'
,
code:
'Tab'
,
target:
element
,
);
expect
(
event
.
defaultPrevented
,
isTrue
);
expect
(
count
,
1
);
});
Keyboard
.
instance
.
dispose
();
});
});
}
typedef
ElementCallback
=
void
Function
(
html
.
Element
element
);
void
useTextEditingElement
(
ElementCallback
callback
)
{
final
html
.
InputElement
input
=
html
.
InputElement
();
input
.
classes
.
add
(
HybridTextEditing
.
textEditingClass
);
try
{
html
.
document
.
body
.
append
(
input
);
callback
(
input
);
}
finally
{
input
.
remove
();
}
}
html
.
KeyboardEvent
dispatchKeyboardEvent
(
String
type
,
{
html
.
EventTarget
target
,
String
key
,
String
code
,
bool
repeat
=
false
,
...
...
@@ -227,6 +308,8 @@ html.KeyboardEvent dispatchKeyboardEvent(
bool
isControlPressed
=
false
,
bool
isMetaPressed
=
false
,
})
{
target
??=
html
.
window
;
final
Function
jsKeyboardEvent
=
js_util
.
getProperty
(
html
.
window
,
'KeyboardEvent'
);
final
List
<
dynamic
>
eventArgs
=
<
dynamic
>[
...
...
@@ -239,12 +322,13 @@ html.KeyboardEvent dispatchKeyboardEvent(
'altKey'
:
isAltPressed
,
'ctrlKey'
:
isControlPressed
,
'metaKey'
:
isMetaPressed
,
'bubbles'
:
true
,
'cancelable'
:
true
,
}
];
final
html
.
KeyboardEvent
event
=
js_util
.
callConstructor
(
jsKeyboardEvent
,
js_util
.
jsify
(
eventArgs
));
html
.
window
.
dispatchEvent
(
event
);
target
.
dispatchEvent
(
event
);
return
event
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录