Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
徽霖
Vscode
提交
9c46f948
V
Vscode
项目概览
徽霖
/
Vscode
通知
9
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
Vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9c46f948
编写于
8月 22, 2017
作者:
A
Alex Dima
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add a physical mouse wheel classifier with tests
上级
d73f9a6f
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
332 addition
and
0 deletion
+332
-0
src/vs/base/browser/ui/scrollbar/scrollableElement.ts
src/vs/base/browser/ui/scrollbar/scrollableElement.ts
+122
-0
src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts
.../base/test/browser/ui/scrollbar/scrollableElement.test.ts
+210
-0
未找到文件。
src/vs/base/browser/ui/scrollbar/scrollableElement.ts
浏览文件 @
9c46f948
...
...
@@ -31,6 +31,126 @@ export interface IOverviewRulerLayoutInfo {
insertBefore
:
HTMLElement
;
}
class
MouseWheelClassifierItem
{
public
timestamp
:
number
;
public
deltaX
:
number
;
public
deltaY
:
number
;
public
score
:
number
;
constructor
(
timestamp
:
number
,
deltaX
:
number
,
deltaY
:
number
)
{
this
.
timestamp
=
timestamp
;
this
.
deltaX
=
deltaX
;
this
.
deltaY
=
deltaY
;
this
.
score
=
0
;
}
}
export
class
MouseWheelClassifier
{
private
readonly
_capacity
:
number
;
private
_memory
:
MouseWheelClassifierItem
[];
private
_front
:
number
;
private
_rear
:
number
;
constructor
()
{
this
.
_capacity
=
5
;
this
.
_memory
=
[];
this
.
_front
=
-
1
;
this
.
_rear
=
-
1
;
}
// private isE
public
isPhysicalMouseWheel
():
boolean
{
if
(
this
.
_front
===
-
1
&&
this
.
_rear
===
-
1
)
{
// no elements
return
false
;
}
// 0.5 * last + 0.25 * before last + 0.125 * before before last + ...
let
remainingInfluence
=
1
;
let
score
=
0
;
let
iteration
=
1
;
let
index
=
this
.
_rear
;
do
{
const
influence
=
(
index
===
this
.
_front
?
remainingInfluence
:
Math
.
pow
(
2
,
-
iteration
));
remainingInfluence
-=
influence
;
score
+=
this
.
_memory
[
index
].
score
*
influence
;
if
(
index
===
this
.
_front
)
{
break
;
}
index
=
(
this
.
_capacity
+
index
-
1
)
%
this
.
_capacity
;
iteration
++
;
}
while
(
true
);
return
(
score
<=
0.5
);
}
public
accept
(
timestamp
:
number
,
deltaX
:
number
,
deltaY
:
number
):
void
{
const
item
=
new
MouseWheelClassifierItem
(
timestamp
,
deltaX
,
deltaY
);
item
.
score
=
this
.
_computeScore
(
item
);
if
(
this
.
_front
===
-
1
&&
this
.
_rear
===
-
1
)
{
this
.
_memory
[
0
]
=
item
;
this
.
_front
=
0
;
this
.
_rear
=
0
;
}
else
{
this
.
_rear
=
(
this
.
_rear
+
1
)
%
this
.
_capacity
;
if
(
this
.
_rear
===
this
.
_front
)
{
// Drop oldest
this
.
_front
=
(
this
.
_front
+
1
)
%
this
.
_capacity
;
}
this
.
_memory
[
this
.
_rear
]
=
item
;
// if ()
// if (this._front === this._rea)
}
// this._lastIndex = (this._lastIndex + 1) % this._capacity;
// if (this._firstIndex === this._lastIndex) {
// this._firstIndex = (this._firstIndex + 1) % this._capacity;
// }
// this._memory[this._lastIndex] = item;
}
/**
* A score between 0 and 1 for `item`.
* - a score towards 0 indicates that the source appears to be a physical mouse wheel
* - a score towards 1 indicates that the source appears to be a touchpad or magic mouse, etc.
*/
private
_computeScore
(
item
:
MouseWheelClassifierItem
):
number
{
if
(
Math
.
abs
(
item
.
deltaX
)
>
0
&&
Math
.
abs
(
item
.
deltaY
)
>
0
)
{
// both axes exercised => definitely not a physical mouse wheel
return
1
;
}
let
score
:
number
=
0.5
;
const
prev
=
(
this
.
_front
===
-
1
&&
this
.
_rear
===
-
1
?
null
:
this
.
_memory
[
this
.
_rear
]);
if
(
prev
)
{
// const deltaT = item.timestamp - prev.timestamp;
// if (deltaT < 1000 / 30) {
// // sooner than X times per second => indicator that this is not a physical mouse wheel
// score += 0.25;
// }
// if (item.deltaX === prev.deltaX && item.deltaY === prev.deltaY) {
// // equal amplitude => indicator that this is a physical mouse wheel
// score -= 0.25;
// }
}
if
(
Math
.
abs
(
item
.
deltaX
-
Math
.
round
(
item
.
deltaX
))
>
0
||
Math
.
abs
(
item
.
deltaY
-
Math
.
round
(
item
.
deltaY
))
>
0
)
{
// non-integer deltas => indicator that this is not a physical mouse wheel
score
+=
0.25
;
}
return
Math
.
min
(
Math
.
max
(
score
,
0
),
1
);
}
}
export
abstract
class
AbstractScrollableElement
extends
Widget
{
private
readonly
_options
:
ScrollableElementResolvedOptions
;
...
...
@@ -216,6 +336,8 @@ export abstract class AbstractScrollableElement extends Widget {
private
_onMouseWheel
(
e
:
StandardMouseWheelEvent
):
void
{
const
currentMouseWheelEventTime
=
Date
.
now
();
// console.log(`${Date.now()}, ${e.deltaY}, ${e.deltaX}`);
if
(
e
.
deltaY
||
e
.
deltaX
)
{
let
deltaY
=
e
.
deltaY
*
this
.
_options
.
mouseWheelScrollSensitivity
;
let
deltaX
=
e
.
deltaX
*
this
.
_options
.
mouseWheelScrollSensitivity
;
...
...
src/vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts
0 → 100644
浏览文件 @
9c46f948
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
MouseWheelClassifier
}
from
"
vs/base/browser/ui/scrollbar/scrollableElement
"
;
import
*
as
assert
from
'
assert
'
;
export
type
IMouseWheelEvent
=
[
number
,
number
,
number
];
suite
(
'
MouseWheelClassifier
'
,
()
=>
{
test
(
'
Apple Magic Mouse
'
,
()
=>
{
const
testData
:
IMouseWheelEvent
[]
=
[
[
1503409622410
,
-
0.025
,
0
],
[
1503409622435
,
-
0.175
,
0
],
[
1503409622446
,
-
0.225
,
0
],
[
1503409622489
,
-
0.65
,
0
],
[
1503409622514
,
-
1.225
,
0
],
[
1503409622537
,
-
1.025
,
0
],
[
1503409622543
,
-
0.55
,
0
],
[
1503409622587
,
-
0.75
,
0
],
[
1503409622623
,
-
1.45
,
0
],
[
1503409622641
,
-
1.325
,
0
],
[
1503409622663
,
-
0.6
,
0
],
[
1503409622681
,
-
1.125
,
0
],
[
1503409622703
,
-
0.5166666666666667
,
0
],
[
1503409622721
,
-
0.475
,
0
],
[
1503409622822
,
-
0.425
,
0
],
[
1503409622871
,
-
1.9916666666666667
,
0
],
[
1503409622933
,
-
0.7
,
0
],
[
1503409622991
,
-
0.725
,
0
],
[
1503409623032
,
-
0.45
,
0
],
[
1503409623083
,
-
0.25
,
0
],
[
1503409623122
,
-
0.4
,
0
],
[
1503409623176
,
-
0.2
,
0
],
[
1503409623197
,
-
0.225
,
0
],
[
1503409623219
,
-
0.05
,
0
],
[
1503409623249
,
-
0.1
,
0
],
[
1503409623278
,
-
0.1
,
0
],
[
1503409623292
,
-
0.025
,
0
],
[
1503409623315
,
-
0.025
,
0
],
[
1503409623324
,
-
0.05
,
0
],
[
1503409623356
,
-
0.025
,
0
],
[
1503409623415
,
-
0.025
,
0
],
[
1503409623443
,
-
0.05
,
0
],
[
1503409623452
,
-
0.025
,
0
],
];
const
classifier
=
new
MouseWheelClassifier
();
for
(
let
i
=
0
,
len
=
testData
.
length
;
i
<
len
;
i
++
)
{
const
[
timestamp
,
deltaY
,
deltaX
]
=
testData
[
i
];
classifier
.
accept
(
timestamp
,
deltaX
,
deltaY
);
const
actual
=
classifier
.
isPhysicalMouseWheel
();
assert
.
equal
(
actual
,
false
);
}
});
test
(
'
Apple Touch Pad
'
,
()
=>
{
const
testData
:
IMouseWheelEvent
[]
=
[
[
1503409780792
,
0.025
,
0
],
[
1503409780808
,
0.175
,
-
0.025
],
[
1503409780811
,
0.35
,
-
0.05
],
[
1503409780816
,
0.55
,
-
0.075
],
[
1503409780836
,
0.825
,
-
0.1
],
[
1503409780840
,
0.725
,
-
0.075
],
[
1503409780842
,
1.5
,
-
0.125
],
[
1503409780848
,
1.1
,
-
0.1
],
[
1503409780877
,
2.05
,
-
0.1
],
[
1503409780882
,
3.9
,
0
],
[
1503409780908
,
3.825
,
0
],
[
1503409780915
,
3.65
,
0
],
[
1503409780940
,
3.45
,
0
],
[
1503409780949
,
3.25
,
0
],
[
1503409780979
,
3.075
,
0
],
[
1503409780982
,
2.9
,
0
],
[
1503409781016
,
2.75
,
0
],
[
1503409781018
,
2.625
,
0
],
[
1503409781051
,
2.5
,
0
],
[
1503409781071
,
2.4
,
0
],
[
1503409781089
,
2.3
,
0
],
[
1503409781111
,
2.175
,
0
],
[
1503409781140
,
3.975
,
0
],
[
1503409781165
,
1.8
,
0
],
[
1503409781183
,
3.3
,
0
],
[
1503409781202
,
1.475
,
0
],
[
1503409781223
,
1.375
,
0
],
[
1503409781244
,
1.275
,
0
],
[
1503409781269
,
2.25
,
0
],
[
1503409781285
,
1.025
,
0
],
[
1503409781300
,
0.925
,
0
],
[
1503409781303
,
0.875
,
0
],
[
1503409781321
,
0.8
,
0
],
[
1503409781333
,
0.725
,
0
],
[
1503409781355
,
0.65
,
0
],
[
1503409781370
,
0.6
,
0
],
[
1503409781384
,
0.55
,
0
],
[
1503409781410
,
0.5
,
0
],
[
1503409781422
,
0.475
,
0
],
[
1503409781435
,
0.425
,
0
],
[
1503409781454
,
0.4
,
0
],
[
1503409781470
,
0.35
,
0
],
[
1503409781486
,
0.325
,
0
],
[
1503409781501
,
0.3
,
0
],
[
1503409781519
,
0.275
,
0
],
[
1503409781534
,
0.25
,
0
],
[
1503409781553
,
0.225
,
0
],
[
1503409781569
,
0.2
,
0
],
[
1503409781589
,
0.2
,
0
],
[
1503409781601
,
0.175
,
0
],
[
1503409781621
,
0.15
,
0
],
[
1503409781631
,
0.15
,
0
],
[
1503409781652
,
0.125
,
0
],
[
1503409781667
,
0.125
,
0
],
[
1503409781685
,
0.125
,
0
],
[
1503409781703
,
0.1
,
0
],
[
1503409781715
,
0.1
,
0
],
[
1503409781734
,
0.1
,
0
],
[
1503409781753
,
0.075
,
0
],
[
1503409781768
,
0.075
,
0
],
[
1503409781783
,
0.075
,
0
],
[
1503409781801
,
0.075
,
0
],
[
1503409781815
,
0.05
,
0
],
[
1503409781836
,
0.05
,
0
],
[
1503409781850
,
0.05
,
0
],
[
1503409781865
,
0.05
,
0
],
[
1503409781880
,
0.05
,
0
],
[
1503409781899
,
0.025
,
0
],
[
1503409781916
,
0.025
,
0
],
[
1503409781933
,
0.025
,
0
],
[
1503409781952
,
0.025
,
0
],
[
1503409781965
,
0.025
,
0
],
[
1503409781996
,
0.025
,
0
],
[
1503409782015
,
0.025
,
0
],
[
1503409782045
,
0.025
,
0
],
];
const
classifier
=
new
MouseWheelClassifier
();
for
(
let
i
=
0
,
len
=
testData
.
length
;
i
<
len
;
i
++
)
{
const
[
timestamp
,
deltaY
,
deltaX
]
=
testData
[
i
];
classifier
.
accept
(
timestamp
,
deltaX
,
deltaY
);
const
actual
=
classifier
.
isPhysicalMouseWheel
();
assert
.
equal
(
actual
,
false
);
}
});
test
(
'
Apple Physical Mouse Wheel
'
,
()
=>
{
const
testData
:
IMouseWheelEvent
[]
=
[
[
1503409880776
,
-
1
,
0
],
[
1503409880791
,
-
1
,
0
],
[
1503409880810
,
-
4
,
0
],
[
1503409880820
,
-
5
,
0
],
[
1503409880848
,
-
6
,
0
],
[
1503409880876
,
-
7
,
0
],
[
1503409881319
,
-
1
,
0
],
[
1503409881387
,
-
1
,
0
],
[
1503409881407
,
-
2
,
0
],
[
1503409881443
,
-
4
,
0
],
[
1503409881444
,
-
5
,
0
],
[
1503409881470
,
-
6
,
0
],
[
1503409881496
,
-
7
,
0
],
[
1503409881812
,
-
1
,
0
],
[
1503409881829
,
-
1
,
0
],
[
1503409881850
,
-
4
,
0
],
[
1503409881871
,
-
5
,
0
],
[
1503409881896
,
-
13
,
0
],
[
1503409881914
,
-
16
,
0
],
[
1503409882551
,
-
1
,
0
],
[
1503409882589
,
-
1
,
0
],
[
1503409882625
,
-
2
,
0
],
[
1503409883035
,
-
1
,
0
],
[
1503409883098
,
-
1
,
0
],
[
1503409883143
,
-
2
,
0
],
[
1503409883217
,
-
2
,
0
],
[
1503409883270
,
-
3
,
0
],
[
1503409883388
,
-
3
,
0
],
[
1503409883531
,
-
3
,
0
],
[
1503409884095
,
-
1
,
0
],
[
1503409884122
,
-
1
,
0
],
[
1503409884160
,
-
3
,
0
],
[
1503409884208
,
-
4
,
0
],
[
1503409884292
,
-
4
,
0
],
[
1503409884447
,
-
1
,
0
],
[
1503409884788
,
-
1
,
0
],
[
1503409884835
,
-
1
,
0
],
[
1503409884898
,
-
2
,
0
],
[
1503409884965
,
-
3
,
0
],
[
1503409885085
,
-
2
,
0
],
[
1503409885552
,
-
1
,
0
],
[
1503409885619
,
-
1
,
0
],
[
1503409885670
,
-
1
,
0
],
[
1503409885733
,
-
2
,
0
],
[
1503409885784
,
-
4
,
0
],
[
1503409885916
,
-
3
,
0
],
];
const
classifier
=
new
MouseWheelClassifier
();
for
(
let
i
=
0
,
len
=
testData
.
length
;
i
<
len
;
i
++
)
{
const
[
timestamp
,
deltaY
,
deltaX
]
=
testData
[
i
];
classifier
.
accept
(
timestamp
,
deltaX
,
deltaY
);
const
actual
=
classifier
.
isPhysicalMouseWheel
();
assert
.
equal
(
actual
,
true
);
}
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录