Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqnxinputcontext_imf.cpp
Go to the documentation of this file.
1// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include "qqnxintegration.h"
7#include "qqnxscreen.h"
9
10#include <QtGui/QGuiApplication>
11#include <QtGui/QInputMethodEvent>
12#include <QtGui/QTextCharFormat>
13
14#include <QtCore/QDebug>
15#include <QtCore/QMutex>
16#include <QtCore/QVariant>
17#include <QtCore/QVariantHash>
18#include <QtCore/QWaitCondition>
19#include <QtCore/QQueue>
20#include <QtCore/QGlobalStatic>
21
22#include <dlfcn.h>
23#include "imf/imf_client.h"
24#include "imf/input_control.h"
25#include <process.h>
26#include <sys/keycodes.h>
27
28#if defined(QQNXINPUTCONTEXT_IMF_EVENT_DEBUG)
29#define qInputContextIMFRequestDebug qDebug
30#else
31#define qInputContextIMFRequestDebug QT_NO_QDEBUG_MACRO
32#endif
33
34#if defined(QQNXINPUTCONTEXT_DEBUG)
35#define qInputContextDebug qDebug
36#else
37#define qInputContextDebug QT_NO_QDEBUG_MACRO
38#endif
39
41static QColor sSelectedColor(0,0xb8,0,85);
42
43static const input_session_t *sSpellCheckSession = nullptr;
44static const input_session_t *sInputSession = nullptr;
45static bool isSessionOkay(input_session_t *ic)
46{
47 return ic !=0 && sInputSession != 0 && ic->component_id == sInputSession->component_id;
48}
49
51{
63};
64
66 SpellCheckInfo(void *_context, void (*_spellCheckDone)(void *, const QString &, const QList<int> &))
67 : context(_context), spellCheckDone(_spellCheckDone) {}
68 void *context;
69 void (*spellCheckDone)(void *, const QString &, const QList<int> &);
70};
72
73// IMF requests all arrive on IMF's own thread and have to be posted to the main thread to be processed.
75{
76public:
77 QQnxImfRequest(input_session_t *_session, ImfEventType _type)
78 : session(_session), type(_type)
79 { }
81
82 input_session_t *session;
84 union {
85 struct {
86 int32_t n;
87 int32_t flags;
88 bool before;
89 spannable_string_t *result;
90 } gtac; // ic_get_text_before_cursor/ic_get_text_after_cursor
91 struct {
92 int32_t result;
93 } gcp; // ic_get_cursor_position
94 struct {
95 int32_t start;
96 int32_t end;
97 int32_t result;
98 } scr; // ic_set_composing_region
99 struct {
100 spannable_string_t* text;
102 int32_t result;
103 } sct; // ic_set_composing_text
104 struct {
105 spannable_string_t* text;
106 int32_t new_cursor_position;
107 int32_t result;
108 } ct; // ic_commit_text
109 struct {
110 int32_t result;
111 } fct; // ic_finish_composing_text
112 struct {
113 int32_t left_length;
115 int32_t result;
116 } dst; // ic_delete_surrounding_text
117 struct {
118 event_t *event;
119 int32_t result;
120 } sae; // ic_send_async_event/ic_send_event
121 struct {
122 int32_t *pIsSelected;
123 int32_t result;
124 } its; // ic_is_text_selected/ic_is_all_text_selected
125 };
126};
127
128// Invoke an IMF initiated request synchronously on Qt's main thread. As describe below all
129// IMF requests are made from another thread but need to be executed on the main thread.
131{
133 "processImfEvent",
136}
137
138// The following functions (ic_*) are callback functions called by the input system to query information
139// about the text object that currently has focus or to make changes to it. All calls are made from the
140// input system's own thread. The pattern for each callback function is to copy its parameters into
141// a QQnxImfRequest structure and call executeIMFRequest to have it passed synchronously to Qt's main thread.
142// Any return values should be pre-initialised with suitable default values as in some cases
143// (e.g. a stale session) the call will return without having executed any request specific code.
144//
145// To make the correspondence more obvious, the names of these functions match those defined in the headers.
146// They're in an anonymous namespace to avoid compiler conflicts with external functions defined with the
147// same names.
148namespace
149{
150
151// See comment at beginning of namespace declaration for general information
152static int32_t ic_begin_batch_edit(input_session_t *ic)
153{
154 Q_UNUSED(ic);
155
156 // Ignore silently.
157 return 0;
158}
159
160// End composition, committing the supplied text.
161// See comment at beginning of namespace declaration for general information
162static int32_t ic_commit_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
163{
165
167 event.ct.text = text;
168 event.ct.new_cursor_position = new_cursor_position;
169 event.ct.result = -1;
171
172 return event.ct.result;
173}
174
175// Delete left_length characters before and right_length characters after the cursor.
176// See comment at beginning of namespace declaration for general information
177static int32_t ic_delete_surrounding_text(input_session_t *ic, int32_t left_length, int32_t right_length)
178{
180
182 event.dst.left_length = left_length;
183 event.dst.right_length = right_length;
184 event.dst.result = -1;
186
187 return event.dst.result;
188}
189
190// See comment at beginning of namespace declaration for general information
191static int32_t ic_end_batch_edit(input_session_t *ic)
192{
193 Q_UNUSED(ic);
194
195 // Ignore silently.
196 return 0;
197}
198
199// End composition, committing what's there.
200// See comment at beginning of namespace declaration for general information
201static int32_t ic_finish_composing_text(input_session_t *ic)
202{
204
206 event.fct.result = -1;
208
209 return event.fct.result;
210}
211
212// Return the position of the cursor.
213// See comment at beginning of namespace declaration for general information
214static int32_t ic_get_cursor_position(input_session_t *ic)
215{
217
219 event.gcp.result = -1;
221
222 return event.gcp.result;
223}
224
225// Return the n characters after the cursor.
226// See comment at beginning of namespace declaration for general information
227static spannable_string_t *ic_get_text_after_cursor(input_session_t *ic, int32_t n, int32_t flags)
228{
230
232 event.gtac.n = n;
233 event.gtac.flags = flags;
234 event.gtac.result = 0;
236
237 return event.gtac.result;
238}
239
240// Return the n characters before the cursor.
241// See comment at beginning of namespace declaration for general information
242static spannable_string_t *ic_get_text_before_cursor(input_session_t *ic, int32_t n, int32_t flags)
243{
245
247 event.gtac.n = n;
248 event.gtac.flags = flags;
249 event.gtac.result = 0;
251
252 return event.gtac.result;
253}
254
255// Process an event from IMF. Primarily used for reflecting back keyboard events.
256// See comment at beginning of namespace declaration for general information
257static int32_t ic_send_event(input_session_t *ic, event_t *event)
258{
260
261 QQnxImfRequest imfEvent(ic, ImfSendEvent);
262 imfEvent.sae.event = event;
263 imfEvent.sae.result = -1;
264 executeIMFRequest(&imfEvent);
265
266 return imfEvent.sae.result;
267}
268
269// Same as ic_send_event.
270// See comment at beginning of namespace declaration for general information
271static int32_t ic_send_async_event(input_session_t *ic, event_t *event)
272{
274
275 // There's no difference from our point of view between ic_send_event & ic_send_async_event
276 QQnxImfRequest imfEvent(ic, ImfSendEvent);
277 imfEvent.sae.event = event;
278 imfEvent.sae.result = -1;
279 executeIMFRequest(&imfEvent);
280
281 return imfEvent.sae.result;
282}
283
284// Set the range of text between start and end as the composition range.
285// See comment at beginning of namespace declaration for general information
286static int32_t ic_set_composing_region(input_session_t *ic, int32_t start, int32_t end)
287{
289
291 event.scr.start = start;
292 event.scr.end = end;
293 event.scr.result = -1;
295
296 return event.scr.result;
297}
298
299// Update the composition range with the supplied text. This can be called when no composition
300// range is in effect in which case one is started at the current cursor position.
301// See comment at beginning of namespace declaration for general information
302static int32_t ic_set_composing_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
303{
305
307 event.sct.text = text;
308 event.sct.new_cursor_position = new_cursor_position;
309 event.sct.result = -1;
311
312 return event.sct.result;
313}
314
315// Indicate if any text is selected
316// See comment at beginning of namespace declaration for general information
317static int32_t ic_is_text_selected(input_session_t* ic, int32_t* pIsSelected)
318{
320
322 event.its.pIsSelected = pIsSelected;
323 event.its.result = -1;
325
326 return event.its.result;
327}
328
329// Indicate if all text is selected
330// See comment at beginning of namespace declaration for general information
331static int32_t ic_is_all_text_selected(input_session_t* ic, int32_t* pIsSelected)
332{
334
336 event.its.pIsSelected = pIsSelected;
337 event.its.result = -1;
339
340 return event.its.result;
341}
342
343// LCOV_EXCL_START - exclude from code coverage analysis
344// The following functions are defined in the IMF headers but are not currently called.
345
346// Not currently used
347static int32_t ic_perform_editor_action(input_session_t *ic, int32_t editor_action)
348{
349 Q_UNUSED(ic);
350 Q_UNUSED(editor_action);
351
352 qCritical("ic_perform_editor_action not implemented");
353 return 0;
354}
355
356// Not currently used
357static int32_t ic_report_fullscreen_mode(input_session_t *ic, int32_t enabled)
358{
359 Q_UNUSED(ic);
361
362 qCritical("ic_report_fullscreen_mode not implemented");
363 return 0;
364}
365
366// Not currently used
367static extracted_text_t *ic_get_extracted_text(input_session_t *ic, extracted_text_request_t *request, int32_t flags)
368{
369 Q_UNUSED(ic);
372
373 qCritical("ic_get_extracted_text not implemented");
374 return 0;
375}
376
377// Not currently used
378static spannable_string_t *ic_get_selected_text(input_session_t *ic, int32_t flags)
379{
380 Q_UNUSED(ic);
382
383 qCritical("ic_get_selected_text not implemented");
384 return 0;
385}
386
387// Not currently used
388static int32_t ic_get_cursor_caps_mode(input_session_t *ic, int32_t req_modes)
389{
390 Q_UNUSED(ic);
391 Q_UNUSED(req_modes);
392
393 qCritical("ic_get_cursor_caps_mode not implemented");
394 return 0;
395}
396
397// Not currently used
398static int32_t ic_clear_meta_key_states(input_session_t *ic, int32_t states)
399{
400 Q_UNUSED(ic);
402
403 qCritical("ic_clear_meta_key_states not implemented");
404 return 0;
405}
406
407// Not currently used
408static int32_t ic_set_selection(input_session_t *ic, int32_t start, int32_t end)
409{
410 Q_UNUSED(ic);
412 Q_UNUSED(end);
413
414 qCritical("ic_set_selection not implemented");
415 return 0;
416}
417
418// End of un-hittable code
419// LCOV_EXCL_STOP
420
421
422static connection_interface_t ic_funcs = {
423 ic_begin_batch_edit,
424 ic_clear_meta_key_states,
425 ic_commit_text,
426 ic_delete_surrounding_text,
427 ic_end_batch_edit,
428 ic_finish_composing_text,
429 ic_get_cursor_caps_mode,
430 ic_get_cursor_position,
431 ic_get_extracted_text,
432 ic_get_selected_text,
433 ic_get_text_after_cursor,
434 ic_get_text_before_cursor,
435 ic_perform_editor_action,
436 ic_report_fullscreen_mode,
437 0, //ic_send_key_event
438 ic_send_event,
439 ic_send_async_event,
440 ic_set_composing_region,
441 ic_set_composing_text,
442 ic_set_selection,
443 0, //ic_set_candidates,
444 0, //ic_get_cursor_offset,
445 0, //ic_get_selection,
446 ic_is_text_selected,
447 ic_is_all_text_selected,
448 0, //ic_get_max_cursor_offset_t
449};
450
451} // namespace
452
453static void
454initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId, int eventSize)
455{
456 static int s_transactionId;
457
458 // Make sure structure is squeaky clean since it's not clear just what is significant.
459 memset(pEvent, 0, eventSize);
460 pEvent->event_type = eventType;
461 pEvent->event_id = eventId;
462 pEvent->pid = getpid();
463 pEvent->component_id = pSession->component_id;
464 pEvent->transaction_id = ++s_transactionId;
465}
466
467static spannable_string_t *toSpannableString(const QString &text)
468{
470
471 spannable_string_t *pString = static_cast<spannable_string_t *>(malloc(sizeof(spannable_string_t)));
472 pString->str = static_cast<wchar_t *>(malloc(sizeof(wchar_t) * text.length() + 1));
473 pString->length = text.toWCharArray(pString->str);
474 pString->spans = 0;
475 pString->spans_count = 0;
476 pString->str[pString->length] = 0;
477
478 return pString;
479}
480
481
482static const input_session_t *(*p_ictrl_open_session)(connection_interface_t *) = nullptr;
483static void (*p_ictrl_close_session)(input_session_t *) = nullptr;
484static int32_t (*p_ictrl_dispatch_event)(event_t*) = nullptr;
485static int32_t (*p_imf_client_init)() = nullptr;
486static void (*p_imf_client_disconnect)() = nullptr;
487static int32_t (*p_vkb_init_selection_service)() = nullptr;
488static int32_t (*p_ictrl_get_num_active_sessions)() = nullptr;
489static bool s_imfInitFailed = false;
490
491static bool imfAvailable()
492{
493 static bool s_imfDisabled = getenv("DISABLE_IMF") != 0;
494 static bool s_imfReady = false;
495
496 if ( s_imfInitFailed || s_imfDisabled)
497 return false;
498 else if ( s_imfReady )
499 return true;
500
501 if ( p_imf_client_init == 0 ) {
502 void *handle = dlopen("libinput_client.so.1", 0);
503 if (Q_UNLIKELY(!handle)) {
504 qCritical("libinput_client.so.1 is not present - IMF services are disabled.");
505 s_imfDisabled = true;
506 return false;
507 }
508 p_imf_client_init = (int32_t (*)()) dlsym(handle, "imf_client_init");
509 p_imf_client_disconnect = (void (*)()) dlsym(handle, "imf_client_disconnect");
510 p_ictrl_open_session = (const input_session_t *(*)(connection_interface_t *))dlsym(handle, "ictrl_open_session");
511 p_ictrl_close_session = (void (*)(input_session_t *))dlsym(handle, "ictrl_close_session");
512 p_ictrl_dispatch_event = (int32_t (*)(event_t *))dlsym(handle, "ictrl_dispatch_event");
513 p_vkb_init_selection_service = (int32_t (*)())dlsym(handle, "vkb_init_selection_service");
514 p_ictrl_get_num_active_sessions = (int32_t (*)())dlsym(handle, "ictrl_get_num_active_sessions");
515
519 s_imfDisabled = true;
520 qCritical("libinput_client.so.1 did not contain the correct symbols, library mismatch? IMF services are disabled.");
521 return false;
522 }
523
524 s_imfReady = true;
525 }
526
527 return s_imfReady;
528}
529
531
534 m_caretPosition(0),
535 m_isComposing(false),
536 m_isUpdatingText(false),
537 m_inputPanelVisible(false),
538 m_inputPanelLocale(QLocale::c()),
539 m_focusObject(0),
540 m_integration(integration),
541 m_virtualKeyboard(keyboard)
542{
544
545 if (!imfAvailable())
546 return;
547
548 // Save a pointer to ourselves so we can execute calls from IMF through executeIMFRequest
549 // In practice there will only ever be a single instance.
552
553 if (Q_UNLIKELY(p_imf_client_init() != 0)) {
554 s_imfInitFailed = true;
555 qCritical("imf_client_init failed - IMF services will be unavailable");
556 }
557
558 connect(&keyboard, SIGNAL(visibilityChanged(bool)), this, SLOT(keyboardVisibilityChanged(bool)));
559 connect(&keyboard, SIGNAL(localeChanged(QLocale)), this, SLOT(keyboardLocaleChanged(QLocale)));
560 keyboardVisibilityChanged(keyboard.isVisible());
561 keyboardLocaleChanged(keyboard.locale());
562}
563
565{
567
569 sInputContextInstance = nullptr;
570
571 if (!imfAvailable())
572 return;
573
575}
576
578{
579 return imfAvailable();
580}
581
582void QQnxInputContext::processImfEvent(QQnxImfRequest *imfEvent)
583{
584 // If input session is no longer current, just bail, imfEvent should already be set with the appropriate
585 // return value. The only exception is spell check events since they're not associated with the
586 // object with focus.
587 if (imfEvent->type != ImfSendEvent || imfEvent->sae.event->event_type != EVENT_SPELL_CHECK) {
588 if (!isSessionOkay(imfEvent->session))
589 return;
590 }
591
592 switch (imfEvent->type) {
593 case ImfCommitText:
594 imfEvent->ct.result = onCommitText(imfEvent->ct.text, imfEvent->ct.new_cursor_position);
595 break;
596
598 imfEvent->dst.result = onDeleteSurroundingText(imfEvent->dst.left_length, imfEvent->dst.right_length);
599 break;
600
602 imfEvent->fct.result = onFinishComposingText();
603 break;
604
606 imfEvent->gcp.result = onGetCursorPosition();
607 break;
608
610 imfEvent->gtac.result = onGetTextAfterCursor(imfEvent->gtac.n, imfEvent->gtac.flags);
611 break;
612
614 imfEvent->gtac.result = onGetTextBeforeCursor(imfEvent->gtac.n, imfEvent->gtac.flags);
615 break;
616
617 case ImfSendEvent:
618 imfEvent->sae.result = onSendEvent(imfEvent->sae.event);
619 break;
620
622 imfEvent->scr.result = onSetComposingRegion(imfEvent->scr.start, imfEvent->scr.end);
623 break;
624
626 imfEvent->sct.result = onSetComposingText(imfEvent->sct.text, imfEvent->sct.new_cursor_position);
627 break;
628
630 imfEvent->its.result = onIsTextSelected(imfEvent->its.pIsSelected);
631 break;
632
634 imfEvent->its.result = onIsAllTextSelected(imfEvent->its.pIsSelected);
635 break;
636 }; //switch
637}
638
640{
642
643 switch (event->type()) {
645 return dispatchCloseSoftwareInputPanel();
646
648 return dispatchRequestSoftwareInputPanel();
649
650 default:
651 return false;
652 }
653}
654
656{
657 QRect screenGeometry = m_integration->primaryDisplay()->geometry();
658 return QRectF(screenGeometry.x(), screenGeometry.height() - m_virtualKeyboard.height(),
659 screenGeometry.width(), m_virtualKeyboard.height());
660}
661
663{
665 endComposition();
666}
667
669{
671 endComposition();
672}
673
674void QQnxInputContext::update(Qt::InputMethodQueries queries)
675{
676 qInputContextDebug() << queries;
677
678 if (queries & Qt::ImCursorPosition) {
679 int lastCaret = m_caretPosition;
680 updateCursorPosition();
681 // If caret position has changed we need to inform IMF unless this is just due to our own action
682 // such as committing text.
683 if (hasSession() && !m_isUpdatingText && lastCaret != m_caretPosition) {
684 caret_event_t caretEvent;
685 initEvent(&caretEvent.event, sInputSession, EVENT_CARET, CARET_POS_CHANGED, sizeof(caretEvent));
686 caretEvent.old_pos = lastCaret;
687 caretEvent.new_pos = m_caretPosition;
688 qInputContextDebug("ictrl_dispatch_event caret changed %d %d", lastCaret, m_caretPosition);
689 p_ictrl_dispatch_event(&caretEvent.event);
690 }
691 }
692}
693
694void QQnxInputContext::closeSession()
695{
697 if (!imfAvailable())
698 return;
699
700 if (sInputSession) {
701 p_ictrl_close_session((input_session_t *)sInputSession);
702 sInputSession = nullptr;
703 }
704 // These are likely already in the right state but this depends on the text control
705 // having called reset or commit. So, just in case, set them to proper values.
706 m_isComposing = false;
707 m_composingText.clear();
708}
709
710bool QQnxInputContext::openSession()
711{
712 if (!imfAvailable())
713 return false;
714
715 closeSession();
717
719
720 return sInputSession != 0;
721}
722
723bool QQnxInputContext::hasSession()
724{
725 return sInputSession != 0;
726}
727
728bool QQnxInputContext::hasSelectedText()
729{
730 QObject *input = qGuiApp->focusObject();
731 if (!input)
732 return false;
733
736
737 return !query.value(Qt::ImCurrentSelection).toString().isEmpty();
738}
739
740bool QQnxInputContext::dispatchRequestSoftwareInputPanel()
741{
742 qInputContextDebug() << "requesting keyboard" << m_inputPanelVisible;
743 m_virtualKeyboard.showKeyboard();
744
745 return true;
746}
747
748bool QQnxInputContext::dispatchCloseSoftwareInputPanel()
749{
750 qInputContextDebug() << "hiding keyboard" << m_inputPanelVisible;
751 m_virtualKeyboard.hideKeyboard();
752
753 return true;
754}
755
759bool QQnxInputContext::dispatchFocusGainEvent(int inputHints)
760{
761 if (hasSession())
762 dispatchFocusLossEvent();
763
764 QObject *input = qGuiApp->focusObject();
765
766 if (!input || !openSession())
767 return false;
768
769 // Set the last caret position to 0 since we don't really have one and we don't
770 // want to have the old one.
771 m_caretPosition = 0;
772
775
776 focus_event_t focusEvent;
777 initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_GAINED, sizeof(focusEvent));
778 focusEvent.style = DEFAULT_STYLE;
779
780 if (inputHints & Qt::ImhNoPredictiveText)
781 focusEvent.style |= NO_PREDICTION | NO_AUTO_CORRECTION;
782 if (inputHints & Qt::ImhNoAutoUppercase)
783 focusEvent.style |= NO_AUTO_TEXT;
784
785 // Following styles are mutually exclusive
786 if (inputHints & Qt::ImhHiddenText) {
787 focusEvent.style |= IMF_PASSWORD_TYPE;
788 } else if (inputHints & Qt::ImhDialableCharactersOnly) {
789 focusEvent.style |= IMF_PHONE_TYPE;
790 } else if (inputHints & Qt::ImhUrlCharactersOnly) {
791 focusEvent.style |= IMF_URL_TYPE;
792 } else if (inputHints & Qt::ImhEmailCharactersOnly) {
793 focusEvent.style |= IMF_EMAIL_TYPE;
794 }
795
796 qInputContextDebug() << "ictrl_dispatch_event focus gain style:" << focusEvent.style;
797
798 p_ictrl_dispatch_event((event_t *)&focusEvent);
799
800 return true;
801}
802
803void QQnxInputContext::dispatchFocusLossEvent()
804{
805 if (hasSession()) {
806 qInputContextDebug("ictrl_dispatch_event focus lost");
807
808 focus_event_t focusEvent;
809 initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_LOST, sizeof(focusEvent));
810 p_ictrl_dispatch_event((event_t *)&focusEvent);
811 closeSession();
812 }
813}
814
815bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId)
816{
817 Q_UNUSED(scan);
818
819 if (!hasSession())
820 return false;
821
822 int key = (flags & KEY_SYM_VALID) ? sym : cap;
823 bool navigationKey = false;
824 switch (key) {
825 case KEYCODE_RETURN:
826 /* In a single line edit we should end composition because enter might be used by something.
827 endComposition();
828 return false;*/
829 break;
830
831 case KEYCODE_BACKSPACE:
832 case KEYCODE_DELETE:
833 // If there is a selection range, then we want a delete key to operate on that (by
834 // deleting the contents of the select range) rather than operating on the composition
835 // range.
836 if (hasSelectedText())
837 return false;
838 break;
839 case KEYCODE_LEFT:
840 key = NAVIGATE_LEFT;
841 navigationKey = true;
842 break;
843 case KEYCODE_RIGHT:
844 key = NAVIGATE_RIGHT;
845 navigationKey = true;
846 break;
847 case KEYCODE_UP:
848 key = NAVIGATE_UP;
849 navigationKey = true;
850 break;
851 case KEYCODE_DOWN:
852 key = NAVIGATE_DOWN;
853 navigationKey = true;
854 break;
855 case KEYCODE_LEFT_CTRL:
856 case KEYCODE_RIGHT_CTRL:
857 case KEYCODE_MENU:
858 case KEYCODE_LEFT_HYPER:
859 case KEYCODE_RIGHT_HYPER:
860 case KEYCODE_INSERT:
861 case KEYCODE_HOME:
862 case KEYCODE_PG_UP:
863 case KEYCODE_END:
864 case KEYCODE_PG_DOWN:
865 // Don't send these
866 key = 0;
867 break;
868 }
869
870 // Pass the keys we don't know about on through
871 if ( key == 0 )
872 return false;
873
874 if (navigationKey) {
875 // Even if we're forwarding up events, we can't do this for
876 // navigation keys.
877 if ( flags & KEY_DOWN ) {
878 navigation_event_t navEvent;
879 initEvent(&navEvent.event, sInputSession, EVENT_NAVIGATION, key, sizeof(navEvent));
880 navEvent.magnitude = 1;
881 qInputContextDebug("ictrl_dispatch_even navigation %d", key);
882 p_ictrl_dispatch_event(&navEvent.event);
883 }
884 } else {
885 key_event_t keyEvent;
886 initEvent(&keyEvent.event, sInputSession, EVENT_KEY, flags & KEY_DOWN ? IMF_KEY_DOWN : IMF_KEY_UP,
887 sizeof(keyEvent));
888 keyEvent.key_code = cap;
889 keyEvent.character = sym;
890 keyEvent.meta_key_state = mod;
891 keyEvent.sequence_id = sequenceId;
892
893 p_ictrl_dispatch_event(&keyEvent.event);
894 qInputContextDebug("ictrl_dispatch_even key %d", key);
895 }
896
897 return true;
898}
899
900void QQnxInputContext::updateCursorPosition()
901{
902 QObject *input = qGuiApp->focusObject();
903 if (!input)
904 return;
905
908 m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
909
910 qInputContextDebug("%d", m_caretPosition);
911}
912
913void QQnxInputContext::endComposition()
914{
915 if (!m_isComposing)
916 return;
917
918 finishComposingText();
919
920 if (hasSession()) {
921 action_event_t actionEvent;
922 initEvent(&actionEvent.event, sInputSession, EVENT_ACTION, ACTION_END_COMPOSITION, sizeof(actionEvent));
923 qInputContextDebug("ictrl_dispatch_even end composition");
924 p_ictrl_dispatch_event(&actionEvent.event);
925 }
926}
927
928void QQnxInputContext::updateComposition(spannable_string_t *text, int32_t new_cursor_position)
929{
930 QObject *input = qGuiApp->focusObject();
931 if (!input)
932 return;
933
934 if (new_cursor_position > 0)
935 new_cursor_position += text->length - 1;
936
937 m_composingText = QString::fromWCharArray(text->str, text->length);
938 m_isComposing = true;
939
940 qInputContextDebug() << m_composingText << new_cursor_position;
941
944 new_cursor_position,
945 1,
946 QVariant()));
947
948 for (unsigned int i = 0; i < text->spans_count; ++i) {
949 QColor highlightColor;
950 bool underline = false;
951
952 if ((text->spans[i].attributes_mask & COMPOSED_TEXT_ATTRIB) != 0)
953 underline = true;
954
955 if ((text->spans[i].attributes_mask & ACTIVE_REGION_ATTRIB) != 0) {
956 underline = true;
957 highlightColor = m_highlightColor[ActiveRegion];
958 } else if ((text->spans[i].attributes_mask & AUTO_CORRECTION_ATTRIB) != 0) {
959 highlightColor = m_highlightColor[AutoCorrected];
960 } else if ((text->spans[i].attributes_mask & REVERT_CORRECTION_ATTRIB) != 0) {
961 highlightColor = m_highlightColor[Reverted];
962 }
963
964 if (underline || highlightColor.isValid()) {
966 if (underline)
967 format.setFontUnderline(true);
968 if (highlightColor.isValid())
969 format.setBackground(QBrush(highlightColor));
970 qInputContextDebug() << " attrib: " << underline << highlightColor << text->spans[i].start << text->spans[i].end;
972 text->spans[i].end - text->spans[i].start + 1, QVariant(format)));
973
974 }
975 }
976 QInputMethodEvent event(m_composingText, attributes);
977 m_isUpdatingText = true;
979 m_isUpdatingText = false;
980
981 updateCursorPosition();
982}
983
984void QQnxInputContext::finishComposingText()
985{
986 QObject *input = qGuiApp->focusObject();
987
988 if (input) {
989 qInputContextDebug() << m_composingText;
990
992 event.setCommitString(m_composingText);
993 m_isUpdatingText = true;
995 m_isUpdatingText = false;
996 }
997 m_composingText = QString();
998 m_isComposing = false;
999
1000 updateCursorPosition();
1001}
1002
1003// Return the index relative to a UTF-16 sequence of characters for a index that is relative to the
1004// corresponding UTF-32 character string given a starting index in the UTF-16 string and a count
1005// of the number of lead surrogates prior to that index. Updates the highSurrogateCount to reflect the
1006// new surrogate characters encountered.
1007static int adjustIndex(const QChar *text, int utf32Index, int utf16StartIndex, int *highSurrogateCount)
1008{
1009 int utf16Index = utf32Index + *highSurrogateCount;
1010 while (utf16StartIndex < utf16Index) {
1011 if (text[utf16StartIndex].isHighSurrogate()) {
1012 ++utf16Index;
1013 ++*highSurrogateCount;
1014 }
1015 ++utf16StartIndex;
1016 }
1017 return utf16StartIndex;
1018}
1019
1020int QQnxInputContext::handleSpellCheck(spell_check_event_t *event)
1021{
1022 // These should never happen.
1023 if (sSpellCheckQueue->isEmpty() || event->event.event_id != NOTIFY_SP_CHECK_MISSPELLINGS)
1024 return -1;
1025
1026 SpellCheckInfo callerInfo = sSpellCheckQueue->dequeue();
1027 spannable_string_t* spellCheckData = *event->data;
1028 QString text = QString::fromWCharArray(spellCheckData->str, spellCheckData->length);
1029 // Generate the list of indices indicating misspelled words in the text. We use end + 1
1030 // since it's more conventional to have the end index point just past the string. We also
1031 // can't use the indices directly since they are relative to UTF-32 encoded data and the
1032 // conversion to Qt's UTF-16 internal format might cause lengthening.
1034 int adjustment = 0;
1035 int index = 0;
1036 for (unsigned int i = 0; i < spellCheckData->spans_count; ++i) {
1037 if (spellCheckData->spans[i].attributes_mask & MISSPELLED_WORD_ATTRIB) {
1038 index = adjustIndex(text.data(), spellCheckData->spans[i].start, index, &adjustment);
1039 indices.push_back(index);
1040 index = adjustIndex(text.data(), spellCheckData->spans[i].end + 1, index, &adjustment);
1041 indices.push_back(index);
1042 }
1043 }
1044 callerInfo.spellCheckDone(callerInfo.context, text, indices);
1045
1046 return 0;
1047}
1048
1049int32_t QQnxInputContext::processEvent(event_t *event)
1050{
1051 int32_t result = -1;
1052 switch (event->event_type) {
1053 case EVENT_SPELL_CHECK: {
1054 qInputContextDebug("EVENT_SPELL_CHECK");
1055 result = handleSpellCheck(reinterpret_cast<spell_check_event_t *>(event));
1056 break;
1057 }
1058
1059 case EVENT_NAVIGATION: {
1060 qInputContextDebug("EVENT_NAVIGATION");
1061
1062 int key = event->event_id == NAVIGATE_UP ? KEYCODE_UP :
1063 event->event_id == NAVIGATE_DOWN ? KEYCODE_DOWN :
1064 event->event_id == NAVIGATE_LEFT ? KEYCODE_LEFT :
1065 event->event_id == NAVIGATE_RIGHT ? KEYCODE_RIGHT : 0;
1066
1067 QQnxScreenEventHandler::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, key, 0, 0, 0);
1068 QQnxScreenEventHandler::injectKeyboardEvent(KEY_CAP_VALID, key, 0, 0, 0);
1069 result = 0;
1070 break;
1071 }
1072
1073 case EVENT_KEY: {
1074 key_event_t *kevent = reinterpret_cast<key_event_t *>(event);
1075 int keySym = kevent->character != 0 ? kevent->character : kevent->key_code;
1076 int keyCap = kevent->key_code;
1077 int modifiers = 0;
1078 if (kevent->meta_key_state & META_SHIFT_ON)
1079 modifiers |= KEYMOD_SHIFT;
1080 int flags = KEY_SYM_VALID | KEY_CAP_VALID;
1081 if (event->event_id == IMF_KEY_DOWN)
1082 flags |= KEY_DOWN;
1083 qInputContextDebug("EVENT_KEY %d %d", flags, keySym);
1085 result = 0;
1086 break;
1087 }
1088
1089 case EVENT_ACTION:
1090 // Don't care, indicates that IMF is done.
1091 break;
1092
1093 case EVENT_CARET:
1094 case EVENT_NOTHING:
1095 case EVENT_FOCUS:
1096 case EVENT_USER_ACTION:
1097 case EVENT_STROKE:
1098 case EVENT_INVOKE_LATER:
1099 qCritical() << "Unsupported event type: " << event->event_type;
1100 break;
1101 default:
1102 qCritical() << "Unknown event type: " << event->event_type;
1103 }
1104 return result;
1105}
1106
1111int32_t QQnxInputContext::onCommitText(spannable_string_t *text, int32_t new_cursor_position)
1112{
1113 Q_UNUSED(new_cursor_position);
1114
1115 updateComposition(text, new_cursor_position);
1116 finishComposingText();
1117
1118 return 0;
1119}
1120
1121int32_t QQnxInputContext::onDeleteSurroundingText(int32_t left_length, int32_t right_length)
1122{
1123 qInputContextDebug("L: %d R: %d", int(left_length), int(right_length));
1124
1125 QObject *input = qGuiApp->focusObject();
1126 if (!input)
1127 return 0;
1128
1129 int replacementLength = left_length + right_length;
1130 int replacementStart = -left_length;
1131
1132 finishComposingText();
1133
1135 event.setCommitString(QString(), replacementStart, replacementLength);
1136 m_isUpdatingText = true;
1138 m_isUpdatingText = false;
1139
1140 updateCursorPosition();
1141
1142 return 0;
1143}
1144
1145int32_t QQnxInputContext::onFinishComposingText()
1146{
1147 finishComposingText();
1148
1149 return 0;
1150}
1151
1152int32_t QQnxInputContext::onGetCursorPosition()
1153{
1155
1156 QObject *input = qGuiApp->focusObject();
1157 if (!input)
1158 return 0;
1159
1160 updateCursorPosition();
1161
1162 return m_caretPosition;
1163}
1164
1165spannable_string_t *QQnxInputContext::onGetTextAfterCursor(int32_t n, int32_t flags)
1166{
1167 Q_UNUSED(flags);
1169
1170 QObject *input = qGuiApp->focusObject();
1171 if (!input)
1172 return toSpannableString("");
1173
1176 QString text = query.value(Qt::ImSurroundingText).toString();
1177 m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
1178
1179 return toSpannableString(text.mid(m_caretPosition, n));
1180}
1181
1182spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(int32_t n, int32_t flags)
1183{
1184 Q_UNUSED(flags);
1186
1187 QObject *input = qGuiApp->focusObject();
1188 if (!input)
1189 return toSpannableString("");
1190
1193 QString text = query.value(Qt::ImSurroundingText).toString();
1194 m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
1195
1196 if (n < m_caretPosition)
1197 return toSpannableString(text.mid(m_caretPosition - n, n));
1198 else
1199 return toSpannableString(text.mid(0, m_caretPosition));
1200}
1201
1202int32_t QQnxInputContext::onSendEvent(event_t *event)
1203{
1205
1206 return processEvent(event);
1207}
1208
1209int32_t QQnxInputContext::onSetComposingRegion(int32_t start, int32_t end)
1210{
1211 QObject *input = qGuiApp->focusObject();
1212 if (!input)
1213 return 0;
1214
1217 QString text = query.value(Qt::ImSurroundingText).toString();
1218 m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
1219
1221
1222 m_isUpdatingText = true;
1223
1224 // Delete the current text.
1225 QInputMethodEvent deleteEvent;
1226 deleteEvent.setCommitString(QString(), start - m_caretPosition, end - start);
1227 QCoreApplication::sendEvent(input, &deleteEvent);
1228
1229 m_composingText = text.mid(start, end - start);
1230 m_isComposing = true;
1231
1234 format.setFontUnderline(true);
1236
1237 QInputMethodEvent setTextEvent(m_composingText, attributes);
1238 QCoreApplication::sendEvent(input, &setTextEvent);
1239
1240 m_isUpdatingText = false;
1241
1242 return 0;
1243}
1244
1245int32_t QQnxInputContext::onSetComposingText(spannable_string_t *text, int32_t new_cursor_position)
1246{
1247 if (text->length > 0) {
1248 updateComposition(text, new_cursor_position);
1249 } else {
1250 // If the composing text is empty we can simply end composition, the visual effect is the same.
1251 // However, sometimes one wants to display hint text in an empty text field and for this to work
1252 // QQuickTextEdit.inputMethodComposing has to be false if the composition string is empty.
1253 m_composingText.clear();
1254 finishComposingText();
1255 }
1256 return 0;
1257}
1258
1259int32_t QQnxInputContext::onIsTextSelected(int32_t* pIsSelected)
1260{
1261 *pIsSelected = hasSelectedText();
1262
1263 qInputContextDebug() << *pIsSelected;
1264
1265 return 0;
1266}
1267
1268int32_t QQnxInputContext::onIsAllTextSelected(int32_t* pIsSelected)
1269{
1270 QObject *input = qGuiApp->focusObject();
1271 if (!input)
1272 return -1;
1273
1276
1277 *pIsSelected = query.value(Qt::ImSurroundingText).toString().length() == query.value(Qt::ImCurrentSelection).toString().length();
1278
1279 qInputContextDebug() << *pIsSelected;
1280
1281 return 0;
1282}
1283
1285{
1287 dispatchRequestSoftwareInputPanel();
1288}
1289
1291{
1293 dispatchCloseSoftwareInputPanel();
1294}
1295
1297{
1298 return m_inputPanelVisible;
1299}
1300
1302{
1303 return m_inputPanelLocale;
1304}
1305
1306void QQnxInputContext::keyboardVisibilityChanged(bool visible)
1307{
1308 qInputContextDebug() << "visible=" << visible;
1309 if (m_inputPanelVisible != visible) {
1310 m_inputPanelVisible = visible;
1312 }
1313}
1314
1315void QQnxInputContext::keyboardLocaleChanged(const QLocale &locale)
1316{
1317 qInputContextDebug() << "locale=" << locale;
1318 if (m_inputPanelLocale != locale) {
1319 m_inputPanelLocale = locale;
1321 }
1322}
1323
1325{
1326 qInputContextDebug() << "setHighlightColor" << index << color << qGuiApp->focusObject();
1327
1329 return;
1330
1331 // If the focus has changed, revert all colors to the default.
1332 if (sInputContextInstance->m_focusObject != qGuiApp->focusObject()) {
1333 QColor invalidColor;
1335 sInputContextInstance->m_highlightColor[AutoCorrected] = invalidColor;
1336 sInputContextInstance->m_highlightColor[Reverted] = invalidColor;
1337 sInputContextInstance->m_focusObject = qGuiApp->focusObject();
1338 }
1339 if (index >= 0 && index <= Reverted)
1340 sInputContextInstance->m_highlightColor[index] = color;
1341}
1342
1344{
1345 qInputContextDebug() << "input item=" << object;
1346
1347 // Ensure the colors are reset if we've a change in focus object
1349
1350 if (!inputMethodAccepted()) {
1351 if (m_inputPanelVisible)
1353 if (hasSession())
1354 dispatchFocusLossEvent();
1355 } else {
1358 int inputHints = query.value(Qt::ImHints).toInt();
1359 Qt::EnterKeyType qtEnterKeyType = Qt::EnterKeyType(query.value(Qt::ImEnterKeyType).toInt());
1360
1361 dispatchFocusGainEvent(inputHints);
1362
1363 m_virtualKeyboard.setInputHints(inputHints);
1364 m_virtualKeyboard.setEnterKeyType(
1366 );
1367
1368 if (!m_inputPanelVisible)
1370 }
1371}
1372
1373bool QQnxInputContext::checkSpelling(const QString &text, void *context, void (*spellCheckDone)(void *context, const QString &text, const QList<int> &indices))
1374{
1375 qInputContextDebug() << "text" << text;
1376
1377 if (!imfAvailable())
1378 return false;
1379
1380 if (!sSpellCheckSession)
1382
1383 action_event_t spellEvent;
1384 initEvent(&spellEvent.event, sSpellCheckSession, EVENT_ACTION, ACTION_CHECK_MISSPELLINGS, sizeof(spellEvent));
1385 int len = text.length();
1386 spellEvent.event_data = alloca(sizeof(wchar_t) * (len + 1));
1387 spellEvent.length_data = text.toWCharArray(static_cast<wchar_t*>(spellEvent.event_data)) * sizeof(wchar_t);
1388
1389 int rc = p_ictrl_dispatch_event(reinterpret_cast<event_t*>(&spellEvent));
1390
1391 if (rc == 0) {
1392 sSpellCheckQueue->enqueue(SpellCheckInfo(context, spellCheckDone));
1393 return true;
1394 }
1395 return false;
1396}
1397
\inmodule QtGui
Definition qbrush.h:30
\inmodule QtCore
Definition qchar.h:48
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
bool isValid() const noexcept
Returns true if the color is valid; otherwise returns false.
Definition qcolor.h:285
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
\inmodule QtCore
Definition qcoreevent.h:45
@ CloseSoftwareInputPanel
Definition qcoreevent.h:249
@ RequestSoftwareInputPanel
Definition qcoreevent.h:248
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:624
void setCommitString(const QString &commitString, int replaceFrom=0, int replaceLength=0)
Sets the commit string to commitString.
Definition qevent.cpp:2269
The QInputMethodQueryEvent class provides an event sent by the input context to input objects.
Definition qevent.h:678
Definition qlist.h:74
void push_back(parameter_type t)
Definition qlist.h:672
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
The QPlatformInputContext class abstracts the input method dependent data and composing state.
bool inputMethodAccepted() const
Returns true if current focus object supports input method events.
void emitInputPanelVisibleChanged()
Active QPlatformInputContext is responsible for providing visible property to QInputMethod.
virtual bool showKeyboard()=0
static EnterKeyType qtEnterKeyTypeToQnx(Qt::EnterKeyType type)
virtual bool hideKeyboard()=0
input_session_t * session
spannable_string_t * text
struct QQnxImfRequest::@438::@446 dst
struct QQnxImfRequest::@438::@448 its
spannable_string_t * result
struct QQnxImfRequest::@438::@441 gcp
struct QQnxImfRequest::@438::@443 sct
QQnxImfRequest(input_session_t *_session, ImfEventType _type)
struct QQnxImfRequest::@438::@445 fct
struct QQnxImfRequest::@438::@444 ct
struct QQnxImfRequest::@438::@442 scr
struct QQnxImfRequest::@438::@447 sae
struct QQnxImfRequest::@438::@440 gtac
bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId) override
void update(Qt::InputMethodQueries) override
Notification on editor updates.
QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard)
bool isInputPanelVisible() const override
Returns input panel visibility status.
void reset() override
Method to be called when input method needs to be reset.
void hideInputPanel() override
Request to hide input panel.
static bool checkSpelling(const QString &text, void *context, void(*spellCheckDone)(void *context, const QString &text, const QList< int > &indices))
void setFocusObject(QObject *object) override
This virtual method gets called to notify updated focus to object.
QLocale locale() const override
bool isValid() const override
Returns input context validity.
bool filterEvent(const QEvent *event) override
This function can be reimplemented to filter input events.
QRectF keyboardRect() const override
This function can be reimplemented to return virtual keyboard rectangle in currently active window co...
void showInputPanel() override
Request to show input panel.
static void setHighlightColor(int index, const QColor &color)
QQnxScreen * primaryDisplay() const
static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap)
QRect geometry() const override
Reimplement in subclass to return the pixel geometry of the screen.
Definition qqnxscreen.h:44
\inmodule QtCore
Definition qqueue.h:14
\inmodule QtCore\reentrant
Definition qrect.h:483
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype toWCharArray(wchar_t *array) const
Definition qstring.h:1146
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
iterator end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing just after the last character in the ...
Definition qstring.h:1205
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1164
qsizetype length() const
Returns the number of characters in this string.
Definition qstring.h:187
\inmodule QtCore
Definition qvariant.h:64
EGLImageKHR int int EGLuint64KHR * modifiers
QString text
Combined button and popup list for selecting options.
@ ImSurroundingText
@ ImCursorPosition
@ ImEnterKeyType
@ ImCurrentSelection
@ ImHints
@ ImhUrlCharactersOnly
@ ImhNoPredictiveText
@ ImhEmailCharactersOnly
@ ImhHiddenText
@ ImhNoAutoUppercase
@ ImhDialableCharactersOnly
@ BlockingQueuedConnection
EnterKeyType
static void * context
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qGuiApp
#define qCritical
Definition qlogging.h:163
#define SLOT(a)
Definition qobjectdefs.h:51
#define Q_ARG(Type, data)
Definition qobjectdefs.h:62
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLuint64 GLenum void * handle
GLuint64 key
GLuint index
[2]
GLuint GLuint end
GLuint object
[3]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum type
GLenum GLenum dst
GLbitfield flags
GLuint start
GLfloat n
GLint GLsizei GLsizei GLenum format
GLsizei GLenum const void * indices
struct _cl_event * event
GLenum query
const GLubyte * c
GLenum GLsizei len
GLuint64EXT * result
[6]
GLenum GLenum GLenum input
GLenum cap
GLuint * states
static QColor sSelectedColor(0, 0xb8, 0, 85)
static const input_session_t * sInputSession
static const input_session_t *(* p_ictrl_open_session)(connection_interface_t *)
static void(* p_imf_client_disconnect)()
static bool imfAvailable()
static const input_session_t * sSpellCheckSession
static bool s_imfInitFailed
static bool isSessionOkay(input_session_t *ic)
static QQnxInputContext * sInputContextInstance
static spannable_string_t * toSpannableString(const QString &text)
static int32_t(* p_ictrl_get_num_active_sessions)()
static int adjustIndex(const QChar *text, int utf32Index, int utf16StartIndex, int *highSurrogateCount)
static int32_t(* p_imf_client_init)()
#define qInputContextDebug
static void(* p_ictrl_close_session)(input_session_t *)
static void initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId, int eventSize)
static int32_t(* p_ictrl_dispatch_event)(event_t *)
static void executeIMFRequest(QQnxImfRequest *event)
@ ImfSetComposingRegion
@ ImfDeleteSurroundingText
@ ImfGetTextBeforeCursor
@ ImfGetTextAfterCursor
@ ImfIsAllTextSelected
@ ImfSetComposingText
@ ImfFinishComposingText
@ ImfGetCursorPosition
@ ImfIsTextSelected
static int32_t(* p_vkb_init_selection_service)()
#define qInputContextIMFRequestDebug
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_UNUSED(x)
EventType
Definition qwasmevent.h:22
QNetworkRequest request(url)
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
void(* spellCheckDone)(void *, const QString &, const QList< int > &)
SpellCheckInfo(void *_context, void(*_spellCheckDone)(void *, const QString &, const QList< int > &))