Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
QtEditText.java
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:critical reason:password-input-type
5
6package org.qtproject.qt.android;
7
8import android.annotation.SuppressLint;
9import android.app.Activity;
10import android.content.Context;
11import android.graphics.Canvas;
12import android.text.InputType;
13import android.view.View;
14import android.view.inputmethod.EditorInfo;
15import android.view.inputmethod.ExtractedText;
16import android.view.inputmethod.ExtractedTextRequest;
17import android.view.inputmethod.InputConnection;
18import android.view.KeyEvent;
19import android.util.Log;
20
21import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener;
22
23@SuppressLint("ViewConstructor")
24class QtEditText extends View
25{
26 static final String QtTAG = "QtEditText";
27
28 int m_initialCapsMode = 0;
29 int m_imeOptions = 0;
30 int m_inputType = InputType.TYPE_CLASS_TEXT;
31 boolean m_optionsChanged = false;
32 QtInputConnection m_inputConnection = null;
33
34 // input method hints - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
35 private final int ImhHiddenText = 0x1;
36 private final int ImhSensitiveData = 0x2;
37 private final int ImhNoAutoUppercase = 0x4;
38 private final int ImhPreferNumbers = 0x8;
39 private final int ImhPreferUppercase = 0x10;
40 private final int ImhPreferLowercase = 0x20;
41 private final int ImhNoPredictiveText = 0x40;
42
43 private final int ImhDate = 0x80;
44 private final int ImhTime = 0x100;
45
46 private final int ImhPreferLatin = 0x200;
47
48 private final int ImhMultiLine = 0x400;
49
50 private final int ImhNoFullscreen = 0x2000;
51
52 private final int ImhDigitsOnly = 0x10000;
53 private final int ImhFormattedNumbersOnly = 0x20000;
54 private final int ImhUppercaseOnly = 0x40000;
55 private final int ImhLowercaseOnly = 0x80000;
56 private final int ImhDialableCharactersOnly = 0x100000;
57 private final int ImhEmailCharactersOnly = 0x200000;
58 private final int ImhUrlCharactersOnly = 0x400000;
59 private final int ImhLatinOnly = 0x800000;
60 private final int ImhDecimaNumbersOnly = 0x1000000;
61
62 private final QtInputConnectionListener m_qtInputConnectionListener;
63
64
65 // Values coming from QAndroidInputContext::CursorHandleShowMode
66 static final int CursorHandleNotShown = 0;
67 static final int CursorHandleShowNormal = 1;
68 static final int CursorHandleShowSelection = 2;
69 static final int CursorHandleShowEdit = 0x100;
70
71 private CursorHandle m_cursorHandle;
72 private CursorHandle m_leftSelectionHandle;
73 private CursorHandle m_rightSelectionHandle;
74
75 final private EditPopupMenu m_editPopupMenu;
76
77 QtEditText(Context context, QtInputConnectionListener listener)
78 {
79 super(context);
80 setFocusable(true);
81 setFocusableInTouchMode(true);
82 m_qtInputConnectionListener = listener;
83 m_editPopupMenu = new EditPopupMenu(this);
84 }
85
86 private void setImeOptions(int imeOptions)
87 {
88 if (m_imeOptions == imeOptions)
89 return;
90 m_imeOptions = imeOptions;
91 m_optionsChanged = true;
92 }
93
94 private void setInitialCapsMode(int initialCapsMode)
95 {
96 if (m_initialCapsMode == initialCapsMode)
97 return;
98 m_initialCapsMode = initialCapsMode;
99 m_optionsChanged = true;
100 }
101
102
103 private void setInputType(int inputType)
104 {
105 if (m_inputType == inputType)
106 return;
107 m_inputType = inputType;
108 m_optionsChanged = true;
109 }
110
111 @Override
112 public InputConnection onCreateInputConnection(EditorInfo outAttrs)
113 {
114 outAttrs.inputType = m_inputType;
115
116 outAttrs.imeOptions = m_imeOptions;
117 if (System.getenv("QT_ANDROID_NO_FULLSCREEN_KEYBOARD") != null) {
118 outAttrs.imeOptions = m_imeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN;
119 Log.w(QtTAG, "Use Qt::ImhNoFullscreen instead of QT_ANDROID_NO_FULLSCREEN_KEYBOARD "
120 + "environment variable on Qt 6.12 and newer.");
121 }
122
123 outAttrs.initialCapsMode = m_initialCapsMode;
124 m_inputConnection = new QtInputConnection(this,m_qtInputConnectionListener);
125
126 ExtractedText extracted = m_inputConnection.getExtractedText(new ExtractedTextRequest(), 0);
127 if (extracted != null) {
128 outAttrs.initialSelStart = extracted.selectionStart;
129 outAttrs.initialSelEnd = extracted.selectionEnd;
130 }
131
132 return m_inputConnection;
133 }
134
135 @Override
136 public boolean onCheckIsTextEditor ()
137 {
138 return true;
139 }
140
141 @Override
142 public boolean onKeyDown (int keyCode, KeyEvent event)
143 {
144 if (null != m_inputConnection)
145 m_inputConnection.restartImmInput();
146
147 return super.onKeyDown(keyCode, event);
148 }
149
150 @Override
151 protected void onDraw(Canvas canvas) {
152 // DEBUG CODE
153 // canvas.drawARGB(127, 255, 0, 255);
154 super.onDraw(canvas);
155 }
156
157
158 void setEditTextOptions(int enterKeyType, int inputHints)
159 {
160 int initialCapsMode = 0;
161 int imeOptions = imeOptionsFromEnterKeyType(enterKeyType);
162 int inputType = android.text.InputType.TYPE_CLASS_TEXT;
163
164 if ((inputHints & (ImhPreferNumbers | ImhDigitsOnly | ImhFormattedNumbersOnly)) != 0) {
165 inputType = android.text.InputType.TYPE_CLASS_NUMBER;
166 if ((inputHints & ImhFormattedNumbersOnly) != 0) {
167 inputType |= (android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL
168 | android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
169 }
170
171 if ((inputHints & ImhHiddenText) != 0)
172 inputType |= android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD;
173 } else if ((inputHints & ImhDecimaNumbersOnly) != 0) {
174 inputType |= android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL;
175 } else if ((inputHints & ImhDialableCharactersOnly) != 0) {
176 inputType = android.text.InputType.TYPE_CLASS_PHONE;
177 } else if ((inputHints & (ImhDate | ImhTime)) != 0) {
178 inputType = android.text.InputType.TYPE_CLASS_DATETIME;
179 if ((inputHints & (ImhDate | ImhTime)) != (ImhDate | ImhTime)) {
180 if ((inputHints & ImhDate) != 0)
181 inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE;
182 else
183 inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME;
184 } // else { TYPE_DATETIME_VARIATION_NORMAL(0) }
185 } else { // CLASS_TEXT
186 if ((inputHints & ImhHiddenText) != 0) {
187 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
188 } else if ((inputHints & ImhSensitiveData) != 0 ||
189 isDisablePredictiveTextWorkaround(inputHints)) {
190 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
191 } else if ((inputHints & ImhUrlCharactersOnly) != 0) {
192 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI;
193 if (enterKeyType == 0) // not explicitly overridden
194 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
195 } else if ((inputHints & ImhEmailCharactersOnly) != 0) {
196 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
197 }
198
199 if ((inputHints & ImhMultiLine) != 0) {
200 inputType |= android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE;
201 // Clear imeOptions for Multi-Line Type
202 // User should be able to insert new line in such case
203 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
204 }
205 if ((inputHints & (ImhNoPredictiveText | ImhSensitiveData | ImhHiddenText)) != 0)
206 inputType |= android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
207
208 if ((inputHints & ImhUppercaseOnly) != 0) {
209 initialCapsMode |= android.text.TextUtils.CAP_MODE_CHARACTERS;
210 inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
211 } else if ((inputHints & ImhLowercaseOnly) == 0
212 && (inputHints & ImhNoAutoUppercase) == 0) {
213 initialCapsMode |= android.text.TextUtils.CAP_MODE_SENTENCES;
214 inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
215 }
216 }
217
218 if (enterKeyType == 0 && (inputHints & ImhMultiLine) != 0)
219 imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
220
221 if ((inputHints & ImhNoFullscreen) != 0)
222 imeOptions |= android.view.inputmethod.EditorInfo.IME_FLAG_NO_FULLSCREEN;
223
224 setInitialCapsMode(initialCapsMode);
225 setImeOptions(imeOptions);
226 setInputType(inputType);
227 }
228
229 private int imeOptionsFromEnterKeyType(int enterKeyType)
230 {
231 int imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
232
233 // enter key type - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
234 switch (enterKeyType) {
235 case 0: // EnterKeyDefault
236 break;
237 case 1: // EnterKeyReturn
238 imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
239 break;
240 case 2: // EnterKeyDone
241 break;
242 case 3: // EnterKeyGo
243 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
244 break;
245 case 4: // EnterKeySend
246 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEND;
247 break;
248 case 5: // EnterKeySearch
249 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH;
250 break;
251 case 6: // EnterKeyNext
252 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
253 break;
254 case 7: // EnterKeyPrevious
255 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
256 break;
257 }
258 return imeOptions;
259 }
260
261 int getSelectionHandleBottom()
262 {
263 if (m_cursorHandle != null)
264 return m_cursorHandle.bottom();
265 if (m_leftSelectionHandle != null && m_rightSelectionHandle != null)
266 return Math.max(m_leftSelectionHandle.bottom(), m_rightSelectionHandle.bottom());
267
268 return 0;
269 }
270
271 int getSelectionHandleWidth()
272 {
273 if (m_leftSelectionHandle != null && m_rightSelectionHandle != null)
274 return Math.max(m_leftSelectionHandle.width(), m_rightSelectionHandle.width());
275 if (m_cursorHandle != null)
276 return m_cursorHandle.width();
277
278 return 0;
279 }
280
281 void updateHandles(int mode, int editX, int editY, int editButtons,
282 int x1, int y1, int x2, int y2, boolean rtl)
283 {
284 switch (mode & 0xff)
285 {
286 case CursorHandleNotShown:
287 if (m_cursorHandle != null) {
288 m_cursorHandle.hide();
289 m_cursorHandle = null;
290 }
291 if (m_rightSelectionHandle != null) {
292 m_rightSelectionHandle.hide();
293 m_leftSelectionHandle.hide();
294 m_rightSelectionHandle = null;
295 m_leftSelectionHandle = null;
296 }
297 break;
298 case CursorHandleShowNormal:
299 if (m_cursorHandle == null) {
300 m_cursorHandle = new CursorHandle((Activity) getContext(), this,
301 CursorHandle.IdCursorHandle,
302 android.R.attr.textSelectHandle, false);
303 }
304 m_cursorHandle.setPosition(x1, y1);
305 if (m_rightSelectionHandle != null) {
306 m_rightSelectionHandle.hide();
307 m_leftSelectionHandle.hide();
308 m_rightSelectionHandle = null;
309 m_leftSelectionHandle = null;
310 }
311 break;
312 case CursorHandleShowSelection:
313 if (m_rightSelectionHandle == null) {
314 m_leftSelectionHandle = new CursorHandle((Activity) getContext(), this,
315 CursorHandle.IdLeftHandle,
316 !rtl ? android.R.attr.textSelectHandleLeft :
317 android.R.attr.textSelectHandleRight,
318 rtl);
319 m_rightSelectionHandle = new CursorHandle((Activity) getContext(), this,
320 CursorHandle.IdRightHandle,
321 !rtl ? android.R.attr.textSelectHandleRight :
322 android.R.attr.textSelectHandleLeft,
323 rtl);
324 }
325 m_leftSelectionHandle.setPosition(x1,y1);
326 m_rightSelectionHandle.setPosition(x2,y2);
327 if (m_cursorHandle != null) {
328 m_cursorHandle.hide();
329 m_cursorHandle = null;
330 }
331 mode |= CursorHandleShowEdit;
332 break;
333 }
334
335 if (!QtClipboardManager.hasClipboardText(getContext()))
336 editButtons &= ~EditContextView.PASTE_BUTTON;
337
338 final boolean setEditPopupPosition = (mode & QtEditText.CursorHandleShowEdit) ==
339 QtEditText.CursorHandleShowEdit && editButtons != 0;
340 if (setEditPopupPosition)
341 m_editPopupMenu.setPosition(editX, editY, editButtons);
342 else
343 m_editPopupMenu.hide();
344 }
345
346 private boolean isDisablePredictiveTextWorkaround(int inputHints)
347 {
348 return (inputHints & ImhNoPredictiveText) != 0 &&
349 System.getenv("QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT") != null;
350 }
351}
QPainter Context
static const QString context()
Definition java.cpp:396
void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl)
@ ImhPreferUppercase
@ ImhPreferLatin
@ ImhUrlCharactersOnly
@ ImhPreferLowercase
@ ImhTime
@ ImhFormattedNumbersOnly
@ ImhMultiLine
@ ImhLatinOnly
@ ImhUppercaseOnly
@ ImhNoPredictiveText
@ ImhDigitsOnly
@ ImhNoFullscreen
@ ImhSensitiveData
@ ImhLowercaseOnly
@ ImhEmailCharactersOnly
@ ImhHiddenText
@ ImhDecimaNumbersOnly
@ ImhNoAutoUppercase
@ ImhDialableCharactersOnly
@ ImhDate
@ ImhPreferNumbers
GLenum mode
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
struct _cl_event * event
GLfixed GLfixed GLfixed y2
GLfixed GLfixed x2