1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.compat;
import android.graphics.Matrix;
import android.graphics.RectF;
import com.android.inputmethod.annotations.UsedForTesting;
@UsedForTesting
public final class CursorAnchorInfoCompatWrapper {
/**
* The insertion marker or character bounds have at least one visible region.
*/
public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
/**
* The insertion marker or character bounds have at least one invisible (clipped) region.
*/
public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
/**
* The insertion marker or character bounds is placed at right-to-left (RTL) character.
*/
public static final int FLAG_IS_RTL = 0x04;
// Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX).
private static final CompatUtils.ClassWrapper sCursorAnchorInfoClass;
private static final CompatUtils.ToObjectMethodWrapper<RectF> sGetCharacterBoundsMethod;
private static final CompatUtils.ToIntMethodWrapper sGetCharacterBoundsFlagsMethod;
private static final CompatUtils.ToObjectMethodWrapper<CharSequence> sGetComposingTextMethod;
private static final CompatUtils.ToIntMethodWrapper sGetComposingTextStartMethod;
private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBaselineMethod;
private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBottomMethod;
private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerHorizontalMethod;
private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerTopMethod;
private static final CompatUtils.ToObjectMethodWrapper<Matrix> sGetMatrixMethod;
private static final CompatUtils.ToIntMethodWrapper sGetInsertionMarkerFlagsMethod;
private static int COMPOSING_TEXT_START_DEFAULT = -1;
static {
sCursorAnchorInfoClass = CompatUtils.getClassWrapper(
"android.view.inputmethod.CursorAnchorInfo");
sGetCharacterBoundsMethod = sCursorAnchorInfoClass.getMethod(
"getCharacterBounds", (RectF)null, int.class);
sGetCharacterBoundsFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
"getCharacterBoundsFlags", 0, int.class);
sGetComposingTextMethod = sCursorAnchorInfoClass.getMethod(
"getComposingText", (CharSequence)null);
sGetComposingTextStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
"getComposingTextStart", COMPOSING_TEXT_START_DEFAULT);
sGetInsertionMarkerBaselineMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
"getInsertionMarkerBaseline", 0.0f);
sGetInsertionMarkerBottomMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
"getInsertionMarkerBottom", 0.0f);
sGetInsertionMarkerHorizontalMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
"getInsertionMarkerHorizontal", 0.0f);
sGetInsertionMarkerTopMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
"getInsertionMarkerTop", 0.0f);
sGetMatrixMethod = sCursorAnchorInfoClass.getMethod("getMatrix", (Matrix)null);
sGetInsertionMarkerFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
"getInsertionMarkerFlags", 0);
}
@UsedForTesting
public static boolean isAvailable() {
return sCursorAnchorInfoClass.exists();
}
private Object mInstance;
private CursorAnchorInfoCompatWrapper(final Object instance) {
mInstance = instance;
}
@UsedForTesting
public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) {
if (!isAvailable()) {
return new CursorAnchorInfoCompatWrapper(null);
}
return new CursorAnchorInfoCompatWrapper(instance);
}
private static final class FakeHolder {
static CursorAnchorInfoCompatWrapper sInstance = new CursorAnchorInfoCompatWrapper(null);
}
@UsedForTesting
public static CursorAnchorInfoCompatWrapper getFake() {
return FakeHolder.sInstance;
}
public CharSequence getComposingText() {
return sGetComposingTextMethod.invoke(mInstance);
}
public int getComposingTextStart() {
return sGetComposingTextStartMethod.invoke(mInstance);
}
public Matrix getMatrix() {
return sGetMatrixMethod.invoke(mInstance);
}
public RectF getCharacterBounds(final int index) {
return sGetCharacterBoundsMethod.invoke(mInstance, index);
}
public int getCharacterBoundsFlags(final int index) {
return sGetCharacterBoundsFlagsMethod.invoke(mInstance, index);
}
public float getInsertionMarkerBaseline() {
return sGetInsertionMarkerBaselineMethod.invoke(mInstance);
}
public float getInsertionMarkerBottom() {
return sGetInsertionMarkerBottomMethod.invoke(mInstance);
}
public float getInsertionMarkerHorizontal() {
return sGetInsertionMarkerHorizontalMethod.invoke(mInstance);
}
public float getInsertionMarkerTop() {
return sGetInsertionMarkerTopMethod.invoke(mInstance);
}
public int getInsertionMarkerFlags() {
return sGetInsertionMarkerFlagsMethod.invoke(mInstance);
}
}
|