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
QtInputDelegate.java
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4package org.qtproject.qt.android;
5
6import java.util.List;
7import android.app.Activity;
8import android.content.Context;
9import android.graphics.Rect;
10import android.os.Build;
11import android.os.Bundle;
12import android.os.Handler;
13import android.os.Looper;
14import android.os.ResultReceiver;
15import android.text.method.MetaKeyKeyListener;
16import android.util.DisplayMetrics;
17import android.util.Log;
18import android.view.InputDevice;
19import android.view.KeyCharacterMap;
20import android.view.KeyEvent;
21import android.view.MotionEvent;
22import android.view.WindowInsets;
23import android.view.WindowInsets.Type;
24import android.view.Window;
25import android.view.WindowInsetsAnimation;
26import android.view.WindowInsetsAnimation.Callback;
27import android.view.WindowManager;
28import android.view.View;
29import android.view.ViewTreeObserver;
30import android.view.inputmethod.InputMethodManager;
31import android.window.OnBackInvokedCallback;
32import android.window.OnBackInvokedDispatcher;
33
34class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, QtInputInterface
35{
36
37 private static final String TAG = "QtInputDelegate";
38 // keyboard methods
39 static native void keyDown(int key, int unicode, int modifier, boolean autoRepeat);
40 static native void keyUp(int key, int unicode, int modifier, boolean autoRepeat);
41 static native void keyboardVisibilityChanged(boolean visibility);
42 static native void keyboardGeometryChanged(int x, int y, int width, int height);
43 // keyboard methods
44
45 // dispatch events methods
46 static native boolean dispatchGenericMotionEvent(MotionEvent event);
47 static native boolean dispatchKeyEvent(KeyEvent event);
48 // dispatch events methods
49
50 // handle methods
51 static native void handleLocationChanged(int id, int x, int y);
52 // handle methods
53
54 private QtEditText m_currentEditText = null;
55 private InputMethodManager m_imm;
56
57 // We can't rely on a hardcoded value, because screens have different resolutions.
58 // That is why we assume that the keyboard should be higher than 0.15 of the screen.
59 private static final float KEYBOARD_TO_SCREEN_RATIO = 0.15f;
60
61 private boolean m_keyboardTransitionInProgress = false;
62 private boolean m_keyboardIsVisible = false;
63 private boolean m_isKeyboardHidingAnimationOngoing = false;
64 private long m_showHideTimeStamp = System.nanoTime();
65 private int m_portraitKeyboardHeight = 0;
66 private int m_landscapeKeyboardHeight = 0;
67 private int m_probeKeyboardHeightDelayMs = 50;
68
69 private int m_softInputMode = 0;
70
71 private static Boolean m_tabletEventSupported = null;
72
73 private static int m_oldX, m_oldY;
74
75
76 private long m_metaState;
77 private int m_lastChar = 0;
78 private boolean m_backKeyPressedSent = false;
79 private boolean m_backKeyDown = false;
80
81 private final OnBackInvokedCallback m_backInvokeCallback;
82
83 // Note: because of the circular call to updateFullScreen() from the delegate, we need
84 // a listener to be able to do that call from the delegate, because that's where that
85 // logic lives
89
90 private final KeyboardVisibilityListener m_keyboardVisibilityListener;
91
92 QtInputDelegate(KeyboardVisibilityListener listener)
93 {
94 m_keyboardVisibilityListener = listener;
95 m_backInvokeCallback = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
96 ? () -> {
97 onKeyDown(KeyEvent.KEYCODE_BACK,
98 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
99 onKeyUp(KeyEvent.KEYCODE_BACK,
100 new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
101 }
102 : null;
103 }
104
105 void initInputMethodManager(Activity activity)
106 {
107 m_imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
108 if (m_imm == null)
109 Log.w(TAG, "getSystemService() returned a null InputMethodManager instance");
110
111 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
112 View rootView = activity.getWindow().getDecorView();
113 ViewTreeObserver observer = rootView.getViewTreeObserver();
114 observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
115 private boolean m_lastImeVisibility = false;
116
117 @Override
118 public void onGlobalLayout() {
119 WindowInsets windowInsets = rootView.getRootWindowInsets();
120 if (windowInsets == null)
121 return;
122
123 boolean imeVisible = windowInsets.isVisible(WindowInsets.Type.ime());
124 if (m_lastImeVisibility != imeVisible) {
125 m_lastImeVisibility = imeVisible;
126 setKeyboardVisibility_internal(imeVisible, System.nanoTime());
127 }
128
129 if (!isKeyboardHidden())
130 setKeyboardTransitionInProgress(false);
131 }
132 });
133 }
134 }
135
136 private void setKeyboardTransitionInProgress(boolean state)
137 {
138 if (m_currentEditText == null || m_keyboardTransitionInProgress == state)
139 return;
140
141 m_keyboardTransitionInProgress = state;
142 }
143
144 // QtInputInterface implementation begin
145 @Override
146 public void updateSelection(final int selStart, final int selEnd,
147 final int candidatesStart, final int candidatesEnd)
148 {
149 if (m_imm != null) {
150 QtNative.runAction(() -> {
151 if (m_imm != null) {
152 m_imm.updateSelection(m_currentEditText, selStart, selEnd,
153 candidatesStart, candidatesEnd);
154 }
155 });
156 }
157 }
158
159 private void showKeyboard(Activity activity,
160 final int x, final int y, final int width, final int height,
161 final int inputHints, final int enterKeyType)
162 {
163 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
164 Window window = activity.getWindow();
165 View decorView = window.getDecorView();
166 decorView.setWindowInsetsAnimationCallback(
167 new WindowInsetsAnimation.Callback(
168 WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
169 @Override
170 public WindowInsets onProgress(
171 WindowInsets insets, List<WindowInsetsAnimation> animationList) {
172 return insets;
173 }
174 @Override
175 public void onEnd(WindowInsetsAnimation animation) {
176 decorView.setWindowInsetsAnimationCallback(null);
177 if ((animation.getTypeMask() & WindowInsets.Type.ime()) == 0) {
178 QtInputConnection.QtNativeInputConnection.updateCursorPosition();
179 if (m_softInputMode == 0) {
180 probeForKeyboardHeight(activity, x, y, width, height,
181 inputHints, enterKeyType);
182 }
183 }
184 }
185 });
186 window.getInsetsController().show(Type.ime());
187 } else {
188 if (m_imm == null)
189 return;
190 m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler(Looper.getMainLooper())) {
191 @Override
192 @SuppressWarnings("fallthrough")
193 protected void onReceiveResult(int resultCode, Bundle resultData) {
194 switch (resultCode) {
195 case InputMethodManager.RESULT_SHOWN:
196 QtInputConnection.QtNativeInputConnection.updateCursorPosition();
197 //FALLTHROUGH
198 case InputMethodManager.RESULT_UNCHANGED_SHOWN:
199 setKeyboardVisibility(true, System.nanoTime());
200 if (m_softInputMode == 0) {
201 probeForKeyboardHeight(activity,
202 x, y, width, height, inputHints, enterKeyType);
203 }
204 break;
205 case InputMethodManager.RESULT_HIDDEN:
206 case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
207 setKeyboardVisibility(false, System.nanoTime());
208 break;
209 }
210 }
211 });
212 }
213 }
214
215 @Override
216 public void showSoftwareKeyboard(Activity activity,
217 final int x, final int y, final int width, final int height,
218 final int inputHints, final int enterKeyType)
219 {
220 if (m_imm == null)
221 return;
222
223 QtNative.runAction(() -> {
224 if (m_imm == null || m_currentEditText == null)
225 return;
226
227 if (updateSoftInputMode(activity, height))
228 return;
229
230 m_currentEditText.setEditTextOptions(enterKeyType, inputHints);
231 m_currentEditText.setLayoutParams(new QtLayout.LayoutParams(width, height, x, y));
232 m_currentEditText.requestFocus();
233 m_currentEditText.postDelayed(() -> {
234 showKeyboard(activity, x, y, width, height, inputHints, enterKeyType);
235 if (m_currentEditText.m_optionsChanged) {
236 m_imm.restartInput(m_currentEditText);
237 m_currentEditText.m_optionsChanged = false;
238 }
239 }, 15);
240 });
241 }
242
243 @Override
244 public int getSelectionHandleWidth()
245 {
246 return m_currentEditText == null ? 0 : m_currentEditText.getSelectionHandleWidth();
247 }
248
249 /* called from the C++ code when the position of the cursor or selection handles needs to
250 be adjusted.
251 mode is one of QAndroidInputContext::CursorHandleShowMode
252 */
253 @Override
254 public void updateHandles(int mode, int editX, int editY, int editButtons,
255 int x1, int y1, int x2, int y2, boolean rtl)
256 {
257 QtNative.runAction(() -> {
258 if (m_currentEditText != null)
259 m_currentEditText.updateHandles(mode, editX, editY, editButtons, x1, y1, x2, y2, rtl);
260 });
261 }
262
263 @Override
264 public QtInputConnection.QtInputConnectionListener getInputConnectionListener()
265 {
266 return this;
267 }
268
269 @Override
270 public void resetSoftwareKeyboard()
271 {
272 if (m_imm == null || m_currentEditText == null)
273 return;
274 m_currentEditText.postDelayed(() -> {
275 if (m_imm == null || m_currentEditText == null)
276 return;
277 m_imm.restartInput(m_currentEditText);
278 m_currentEditText.m_optionsChanged = false;
279 }, 5);
280 }
281
282 @Override
283 public void hideSoftwareKeyboard()
284 {
285 if (m_imm == null || m_currentEditText == null)
286 return;
287
288 m_isKeyboardHidingAnimationOngoing = true;
289 QtNative.runAction(() -> {
290 if (m_imm == null || m_currentEditText == null)
291 return;
292
293 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
294 Activity activity = QtNative.activity();
295 if (activity == null) {
296 Log.w(TAG, "hideSoftwareKeyboard: The activity reference is null");
297 return;
298 }
299 activity.getWindow().getInsetsController().hide(Type.ime());
300 } else {
301 m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
302 new ResultReceiver(new Handler(Looper.getMainLooper())) {
303 @Override
304 protected void onReceiveResult(int resultCode, Bundle resultData) {
305 switch (resultCode) {
306 case InputMethodManager.RESULT_SHOWN:
307 case InputMethodManager.RESULT_UNCHANGED_SHOWN:
308 setKeyboardVisibility(true, System.nanoTime());
309 break;
310 case InputMethodManager.RESULT_HIDDEN:
311 case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
312 setKeyboardVisibility(false, System.nanoTime());
313 break;
314 }
315 }
316 });
317 }
318 });
319 }
320
321 // Is the keyboard fully visible i.e. visible and no ongoing animation
322 @Override
323 public boolean isSoftwareKeyboardVisible()
324 {
325 return isKeyboardVisible() && !m_isKeyboardHidingAnimationOngoing;
326 }
327 // QtInputInterface implementation end
328
329 // QtInputConnectionListener methods
330 @Override
331 public boolean keyboardTransitionInProgress() {
332 return m_keyboardTransitionInProgress;
333 }
334
335 @Override
336 public boolean isKeyboardHidden() {
337 Activity activity = QtNative.activity();
338 if (activity == null) {
339 Log.w(TAG, "isKeyboardHidden: The activity reference is null");
340 return true;
341 }
342
343 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
344 Rect r = new Rect();
345 activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
346 DisplayMetrics metrics = new DisplayMetrics();
347 QtDisplayManager.getDisplay(activity).getMetrics(metrics);
348 int screenHeight = metrics.heightPixels;
349 final int kbHeight = screenHeight - r.bottom;
350 return kbHeight < screenHeight * KEYBOARD_TO_SCREEN_RATIO;
351 }
352
353 return !m_keyboardIsVisible;
354 }
355
356 @Override
357 public void onSetClosing(boolean closing) {
358 if (!closing)
359 setKeyboardVisibility(true, System.nanoTime());
360 }
361
362 @Override
363 public void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp) {
364 setKeyboardVisibility(visibility, hideTimeStamp);
365 }
366
367 @Override
368 public void onSendKeyEventDefaultCase() {
370 }
371
372 @Override
373 public void onEditTextChanged(QtEditText editText) {
374 setFocusedView(editText);
375 }
376 // QtInputConnectionListener methods
377
378 boolean isKeyboardVisible()
379 {
380 return m_keyboardIsVisible;
381 }
382
383 void setSoftInputMode(int inputMode)
384 {
385 m_softInputMode = inputMode;
386 }
387
388 QtEditText getCurrentQtEditText()
389 {
390 return m_currentEditText;
391 }
392
393 private void keyboardVisibilityUpdated(boolean visibility)
394 {
395 m_isKeyboardHidingAnimationOngoing = false;
396 QtInputDelegate.keyboardVisibilityChanged(visibility);
397 }
398
399 void setKeyboardVisibility(boolean visibility, long timeStamp)
400 {
401 // Since API 30 keyboard visibility changes are tracked by the global layout listener
402 // observing root window insets. There are no manual changes anymore
403 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
404 setKeyboardVisibility_internal(visibility, timeStamp);
405 }
406
407 private void setKeyboardVisibility_internal(boolean visibility, long timeStamp)
408 {
409 if (m_showHideTimeStamp > timeStamp)
410 return;
411 m_showHideTimeStamp = timeStamp;
412
413 if (m_keyboardIsVisible == visibility)
414 return;
415 m_keyboardIsVisible = visibility;
416 keyboardVisibilityUpdated(m_keyboardIsVisible);
417 setKeyboardTransitionInProgress(visibility);
418
419 if (!visibility) {
420 // Hiding the keyboard clears the immersive mode, so we need to set it again.
421 m_keyboardVisibilityListener.onKeyboardVisibilityChange();
422 if (m_currentEditText != null)
423 m_currentEditText.clearFocus();
424 }
425 }
426
427 void setFocusedView(QtEditText currentEditText)
428 {
429 setKeyboardTransitionInProgress(false);
430 m_currentEditText = currentEditText;
431 }
432
433 private boolean updateSoftInputMode(Activity activity, int height)
434 {
435 DisplayMetrics metrics = new DisplayMetrics();
436 QtDisplayManager.getDisplay(activity).getMetrics(metrics);
437
438 // If the screen is in portrait mode than we estimate that keyboard height
439 // will not be higher than 2/5 of the screen. Otherwise we estimate that keyboard height
440 // will not be higher than 2/3 of the screen
441 final int visibleHeight;
442 if (metrics.widthPixels < metrics.heightPixels) {
443 visibleHeight = m_portraitKeyboardHeight != 0 ?
444 m_portraitKeyboardHeight : metrics.heightPixels * 3 / 5;
445 } else {
446 visibleHeight = m_landscapeKeyboardHeight != 0 ?
447 m_landscapeKeyboardHeight : metrics.heightPixels / 3;
448 }
449
450 if (m_softInputMode != 0) {
451 activity.getWindow().setSoftInputMode(m_softInputMode);
452 int stateHidden = WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
453 return (m_softInputMode & stateHidden) != 0;
454 } else {
455 int stateUnchanged = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
456 if (height > visibleHeight) {
457 int adjustResize = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
458 activity.getWindow().setSoftInputMode(stateUnchanged | adjustResize);
459 } else {
460 int adjustPan = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
461 activity.getWindow().setSoftInputMode(stateUnchanged | adjustPan);
462 }
463 }
464 return false;
465 }
466
467 private void probeForKeyboardHeight(Activity activity, int x, int y,
468 int width, int height, int inputHints, int enterKeyType)
469 {
470 if (m_currentEditText == null) {
471 Log.w(TAG, "probeForKeyboardHeight: null QtEditText");
472 return;
473 }
474 m_currentEditText.postDelayed(() -> {
475 if (!m_keyboardIsVisible)
476 return;
477 DisplayMetrics metrics = new DisplayMetrics();
478 QtDisplayManager.getDisplay(activity).getMetrics(metrics);
479 Rect r = new Rect();
480 activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
481 if (metrics.heightPixels != r.bottom) {
482 if (metrics.widthPixels > metrics.heightPixels) { // landscape
483 if (m_landscapeKeyboardHeight != r.bottom) {
484 m_landscapeKeyboardHeight = r.bottom;
485 showSoftwareKeyboard(activity, x, y, width, height,
486 inputHints, enterKeyType);
487 }
488 } else {
489 if (m_portraitKeyboardHeight != r.bottom) {
490 m_portraitKeyboardHeight = r.bottom;
491 showSoftwareKeyboard(activity, x, y, width, height,
492 inputHints, enterKeyType);
493 }
494 }
495 } else {
496 // no luck ?
497 // maybe the delay was too short, so let's make it longer
498 if (m_probeKeyboardHeightDelayMs < 1000)
499 m_probeKeyboardHeightDelayMs *= 2;
500 }
501 }, m_probeKeyboardHeightDelayMs);
502 }
503
504 boolean onKeyDown(int keyCode, KeyEvent event)
505 {
506 m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event);
507 int metaState = MetaKeyKeyListener.getMetaState(m_metaState) | event.getMetaState();
508 int c = event.getUnicodeChar(metaState);
509 int lc = c;
510 m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState);
511
512 if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
513 c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
514 c = KeyEvent.getDeadChar(m_lastChar, c);
515 }
516
517 if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP
518 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
519 || keyCode == KeyEvent.KEYCODE_MUTE)
520 && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) {
521 return false;
522 }
523
524 m_lastChar = lc;
525 if (keyCode == KeyEvent.KEYCODE_BACK) {
526 // Physical events can overlap the pair from OnBackInvokedCallback.
527 if (m_backKeyDown && event.getRepeatCount() == 0)
528 return true;
529 m_backKeyDown = true;
530 m_backKeyPressedSent = !isKeyboardVisible();
531 if (!m_backKeyPressedSent)
532 return true;
533 }
534
535 QtInputDelegate.keyDown(keyCode, c, event.getMetaState(), event.getRepeatCount() > 0);
536
537 return true;
538 }
539
540 boolean onKeyUp(int keyCode, KeyEvent event)
541 {
542 if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP
543 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
544 || keyCode == KeyEvent.KEYCODE_MUTE)
545 && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) {
546 return false;
547 }
548
549 if (keyCode == KeyEvent.KEYCODE_BACK) {
550 if (!m_backKeyDown)
551 return true;
552 m_backKeyDown = false;
553 if (!m_backKeyPressedSent) {
555 setKeyboardVisibility(false, System.nanoTime());
556 return true;
557 }
558 }
559
560 m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode, event);
561 boolean autoRepeat = event.getRepeatCount() > 0;
562 QtInputDelegate.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState(), autoRepeat);
563
564 return true;
565 }
566
567 boolean handleDispatchKeyEvent(KeyEvent event)
568 {
569 if (event.getAction() == KeyEvent.ACTION_MULTIPLE
570 && event.getCharacters() != null
571 && event.getCharacters().length() == 1
572 && event.getKeyCode() == 0) {
573 keyDown(0, event.getCharacters().charAt(0), event.getMetaState(),
574 event.getRepeatCount() > 0);
575 keyUp(0, event.getCharacters().charAt(0), event.getMetaState(),
576 event.getRepeatCount() > 0);
577 }
578
579 return dispatchKeyEvent(event);
580 }
581
582 boolean handleDispatchGenericMotionEvent(MotionEvent event)
583 {
584 return dispatchGenericMotionEvent(event);
585 }
586
587 void registerBackGestureCallback(Activity activity)
588 {
589 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
590 return;
591 try {
592 activity.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
593 OnBackInvokedDispatcher.PRIORITY_DEFAULT,
594 m_backInvokeCallback);
595 } catch (IllegalStateException ise) {
596 Log.e(TAG, "Failed to register OnBackInvokedCallback: " + ise.getMessage());
597 }
598 }
599
600 void unregisterBackGestureCallback(Activity activity)
601 {
602 m_backKeyDown = false;
603 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
604 return;
605 try {
606 activity.getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(
607 m_backInvokeCallback);
608 } catch (IllegalStateException ise) {
609 Log.e(TAG, "Failed to unregister OnBackInvokedCallback: " + ise.getMessage());
610 }
611 }
612
614 // Mouse and Touch Input //
616
617 // tablet methods
618 static native boolean isTabletEventSupported();
619 static native void tabletEvent(int winId, int deviceId, long time, int action,
620 int pointerType, int buttonState, float x, float y,
621 float pressure, int metaState);
622 // tablet methods
623
624 // pointer methods
625 static native void mouseDown(int winId, int x, int y, int mouseButtonState, int metaState);
626 static native void mouseUp(int winId, int x, int y, int mouseButtonState, int metaState);
627 static native void mouseMove(int winId, int x, int y, int mouseButtonState, int metaState);
628 static native void mouseWheel(int winId, int x, int y, float hDelta, float vDelta, int metaState);
629 static native void touchBegin(int winId);
630 static native void touchAdd(int winId, int pointerId, int action, boolean primary,
631 int x, int y, float major, float minor, float rotation,
632 float pressure);
633 static native void touchEnd(int winId, int action, int metaState);
634 static native void touchCancel(int winId, int metaState);
635 static native void longPress(int winId, int x, int y, int metaState);
636 // pointer methods
637
638 static private int getAction(int index, MotionEvent event)
639 {
640 int action = event.getActionMasked();
641 if (action == MotionEvent.ACTION_MOVE) {
642 int hsz = event.getHistorySize();
643 if (hsz > 0) {
644 float x = event.getX(index);
645 float y = event.getY(index);
646 for (int h = 0; h < hsz; ++h) {
647 if ( event.getHistoricalX(index, h) != x ||
648 event.getHistoricalY(index, h) != y )
649 return 1;
650 }
651 return 2;
652 }
653 return 1;
654 }
655 if (action == MotionEvent.ACTION_DOWN
656 || action == MotionEvent.ACTION_POINTER_DOWN && index == event.getActionIndex()) {
657 return 0;
658 } else if (action == MotionEvent.ACTION_UP
659 || action == MotionEvent.ACTION_POINTER_UP && index == event.getActionIndex()) {
660 return 3;
661 }
662 return 2;
663 }
664
665 static void sendTouchEvent(MotionEvent event, int id)
666 {
667 int pointerType = 0;
668
669 if (m_tabletEventSupported == null)
670 m_tabletEventSupported = isTabletEventSupported();
671
672 switch (event.getToolType(0)) {
673 case MotionEvent.TOOL_TYPE_STYLUS:
674 pointerType = 1; // QTabletEvent::Pen
675 break;
676 case MotionEvent.TOOL_TYPE_ERASER:
677 pointerType = 3; // QTabletEvent::Eraser
678 break;
679 }
680
681 if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
682 sendMouseEvent(event, id);
683 } else if (m_tabletEventSupported && pointerType != 0) {
684 tabletEvent(id, event.getDeviceId(), event.getEventTime(), event.getActionMasked(),
685 pointerType, event.getButtonState(),
686 event.getX(), event.getY(), event.getPressure(),
687 event.getMetaState());
688 } else {
689 touchBegin(id);
690 for (int i = 0; i < event.getPointerCount(); ++i) {
691 touchAdd(id,
692 event.getPointerId(i),
693 getAction(i, event),
694 i == 0,
695 (int)event.getX(i),
696 (int)event.getY(i),
697 event.getTouchMajor(i),
698 event.getTouchMinor(i),
699 event.getOrientation(i),
700 event.getPressure(i));
701 }
702
703 switch (event.getAction()) {
704 case MotionEvent.ACTION_DOWN:
705 touchEnd(id, 0, event.getMetaState());
706 break;
707
708 case MotionEvent.ACTION_UP:
709 touchEnd(id, 2, event.getMetaState());
710 break;
711
712 case MotionEvent.ACTION_CANCEL:
713 touchCancel(id, event.getMetaState());
714 break;
715
716 default:
717 touchEnd(id, 1, event.getMetaState());
718 }
719 }
720 }
721
722 static void sendTrackballEvent(MotionEvent event, int id)
723 {
724 sendMouseEvent(event,id);
725 }
726
727 static boolean sendGenericMotionEvent(MotionEvent event, int id)
728 {
729 int scrollOrHoverMove = MotionEvent.ACTION_SCROLL | MotionEvent.ACTION_HOVER_MOVE;
730 int pointerDeviceModifier = (event.getSource() & InputDevice.SOURCE_CLASS_POINTER);
731 boolean isPointerDevice = pointerDeviceModifier == InputDevice.SOURCE_CLASS_POINTER;
732
733 if ((event.getAction() & scrollOrHoverMove) == 0 || !isPointerDevice )
734 return false;
735
736 return sendMouseEvent(event, id);
737 }
738
739 static boolean sendMouseEvent(MotionEvent event, int id)
740 {
741 switch (event.getActionMasked()) {
742 case MotionEvent.ACTION_UP:
743 mouseUp(id, (int) event.getX(), (int) event.getY(), event.getButtonState(),
744 event.getMetaState());
745 break;
746
747 case MotionEvent.ACTION_DOWN:
748 mouseDown(id, (int) event.getX(), (int) event.getY(), event.getButtonState(),
749 event.getMetaState());
750 m_oldX = (int) event.getX();
751 m_oldY = (int) event.getY();
752 break;
753 case MotionEvent.ACTION_HOVER_MOVE:
754 case MotionEvent.ACTION_MOVE:
755 if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
756 mouseMove(id, (int) event.getX(), (int) event.getY(), event.getButtonState(),
757 event.getMetaState());
758 } else {
759 int dx = (int) (event.getX() - m_oldX);
760 int dy = (int) (event.getY() - m_oldY);
761 if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
762 mouseMove(id, (int) event.getX(), (int) event.getY(), event.getButtonState(),
763 event.getMetaState());
764 m_oldX = (int) event.getX();
765 m_oldY = (int) event.getY();
766 }
767 }
768 break;
769 case MotionEvent.ACTION_SCROLL:
770 mouseWheel(id, (int) event.getX(), (int) event.getY(),
771 event.getAxisValue(MotionEvent.AXIS_HSCROLL),
772 event.getAxisValue(MotionEvent.AXIS_VSCROLL),
773 event.getMetaState());
774 break;
775 default:
776 return false;
777 }
778 return true;
779 }
780}
PeripheralState state
QPainter Context
Napi::String String
Definition qnapi_p.h:70
Napi::Boolean Boolean
Definition qnapi_p.h:62
void mouseMove(QWindow *window, QPoint pos=QPoint(), int delay=-1)
Definition qtestmouse.h:147
void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd)
void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType)
bool isSoftwareKeyboardVisible()
void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl)
Q_CORE_EXPORT QtJniTypes::Activity activity()
@ Window
Definition qnamespace.h:219
self window
[2]
#define TAG(x)
GLint GLint GLint GLint GLint x
GLenum mode
GLuint64 key
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLboolean r
GLuint GLfloat GLfloat GLfloat x1
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLuint index
GLint GLsizei width
GLint y
GLfloat GLfloat GLfloat GLfloat h
struct _cl_event * event
const GLubyte * c
GLfixed GLfixed GLfixed y2
GLfixed GLfixed x2
@ Handler
Type
[0]
Definition moc.h:33