10#include <QtGui/QGuiApplication>
11#include <QtGui/QInputMethodEvent>
12#include <QtGui/QTextCharFormat>
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>
23#include "imf/imf_client.h"
24#include "imf/input_control.h"
26#include <sys/keycodes.h>
28#if defined(QQNXINPUTCONTEXT_IMF_EVENT_DEBUG)
29#define qInputContextIMFRequestDebug qDebug
31#define qInputContextIMFRequestDebug QT_NO_QDEBUG_MACRO
34#if defined(QQNXINPUTCONTEXT_DEBUG)
35#define qInputContextDebug qDebug
37#define qInputContextDebug QT_NO_QDEBUG_MACRO
78 : session(_session),
type(_type)
105 spannable_string_t*
text;
106 int32_t new_cursor_position;
152static int32_t ic_begin_batch_edit(input_session_t *ic)
162static int32_t ic_commit_text(input_session_t *ic, spannable_string_t *
text, int32_t new_cursor_position)
167 event.ct.text =
text;
168 event.ct.new_cursor_position = new_cursor_position;
169 event.ct.result = -1;
172 return event.ct.result;
177static int32_t ic_delete_surrounding_text(input_session_t *ic, int32_t left_length, int32_t right_length)
182 event.dst.left_length = left_length;
183 event.dst.right_length = right_length;
184 event.dst.result = -1;
187 return event.dst.result;
191static int32_t ic_end_batch_edit(input_session_t *ic)
201static int32_t ic_finish_composing_text(input_session_t *ic)
206 event.fct.result = -1;
209 return event.fct.result;
214static int32_t ic_get_cursor_position(input_session_t *ic)
219 event.gcp.result = -1;
222 return event.gcp.result;
227static spannable_string_t *ic_get_text_after_cursor(input_session_t *ic, int32_t
n, int32_t
flags)
233 event.gtac.flags =
flags;
234 event.gtac.result = 0;
237 return event.gtac.result;
242static spannable_string_t *ic_get_text_before_cursor(input_session_t *ic, int32_t
n, int32_t
flags)
248 event.gtac.flags =
flags;
249 event.gtac.result = 0;
252 return event.gtac.result;
257static int32_t ic_send_event(input_session_t *ic, event_t *
event)
262 imfEvent.sae.event =
event;
263 imfEvent.sae.result = -1;
266 return imfEvent.sae.result;
271static int32_t ic_send_async_event(input_session_t *ic, event_t *
event)
277 imfEvent.sae.event =
event;
278 imfEvent.sae.result = -1;
281 return imfEvent.sae.result;
286static int32_t ic_set_composing_region(input_session_t *ic, int32_t
start, int32_t
end)
291 event.scr.start =
start;
293 event.scr.result = -1;
296 return event.scr.result;
302static int32_t ic_set_composing_text(input_session_t *ic, spannable_string_t *
text, int32_t new_cursor_position)
307 event.sct.text =
text;
308 event.sct.new_cursor_position = new_cursor_position;
309 event.sct.result = -1;
312 return event.sct.result;
317static int32_t ic_is_text_selected(input_session_t* ic, int32_t* pIsSelected)
322 event.its.pIsSelected = pIsSelected;
323 event.its.result = -1;
326 return event.its.result;
331static int32_t ic_is_all_text_selected(input_session_t* ic, int32_t* pIsSelected)
336 event.its.pIsSelected = pIsSelected;
337 event.its.result = -1;
340 return event.its.result;
347static int32_t ic_perform_editor_action(input_session_t *ic, int32_t editor_action)
352 qCritical(
"ic_perform_editor_action not implemented");
357static int32_t ic_report_fullscreen_mode(input_session_t *ic, int32_t
enabled)
362 qCritical(
"ic_report_fullscreen_mode not implemented");
367static extracted_text_t *ic_get_extracted_text(input_session_t *ic, extracted_text_request_t *
request, int32_t
flags)
373 qCritical(
"ic_get_extracted_text not implemented");
378static spannable_string_t *ic_get_selected_text(input_session_t *ic, int32_t
flags)
383 qCritical(
"ic_get_selected_text not implemented");
388static int32_t ic_get_cursor_caps_mode(input_session_t *ic, int32_t req_modes)
393 qCritical(
"ic_get_cursor_caps_mode not implemented");
398static int32_t ic_clear_meta_key_states(input_session_t *ic, int32_t
states)
403 qCritical(
"ic_clear_meta_key_states not implemented");
408static int32_t ic_set_selection(input_session_t *ic, int32_t
start, int32_t
end)
414 qCritical(
"ic_set_selection not implemented");
422static connection_interface_t ic_funcs = {
424 ic_clear_meta_key_states,
426 ic_delete_surrounding_text,
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,
440 ic_set_composing_region,
441 ic_set_composing_text,
447 ic_is_all_text_selected,
454initEvent(event_t *pEvent,
const input_session_t *pSession,
EventType eventType,
int eventId,
int eventSize)
456 static int s_transactionId;
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;
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));
475 pString->spans_count = 0;
476 pString->str[pString->length] = 0;
482static const input_session_t *(*p_ictrl_open_session)(connection_interface_t *) =
nullptr;
493 static bool s_imfDisabled = getenv(
"DISABLE_IMF") != 0;
494 static bool s_imfReady =
false;
498 else if ( s_imfReady )
502 void *
handle = dlopen(
"libinput_client.so.1", 0);
504 qCritical(
"libinput_client.so.1 is not present - IMF services are disabled.");
505 s_imfDisabled =
true;
519 s_imfDisabled =
true;
520 qCritical(
"libinput_client.so.1 did not contain the correct symbols, library mismatch? IMF services are disabled.");
535 m_isComposing(
false),
536 m_isUpdatingText(
false),
537 m_inputPanelVisible(
false),
540 m_integration(integration),
541 m_virtualKeyboard(keyboard)
555 qCritical(
"imf_client_init failed - IMF services will be unavailable");
558 connect(&keyboard,
SIGNAL(visibilityChanged(
bool)),
this,
SLOT(keyboardVisibilityChanged(
bool)));
560 keyboardVisibilityChanged(keyboard.
isVisible());
561 keyboardLocaleChanged(keyboard.
locale());
592 switch (imfEvent->
type) {
602 imfEvent->
fct.
result = onFinishComposingText();
606 imfEvent->
gcp.
result = onGetCursorPosition();
643 switch (
event->type()) {
645 return dispatchCloseSoftwareInputPanel();
648 return dispatchRequestSoftwareInputPanel();
659 screenGeometry.
width(), m_virtualKeyboard.
height());
679 int lastCaret = m_caretPosition;
680 updateCursorPosition();
683 if (hasSession() && !m_isUpdatingText && lastCaret != m_caretPosition) {
684 caret_event_t caretEvent;
686 caretEvent.old_pos = lastCaret;
687 caretEvent.new_pos = m_caretPosition;
688 qInputContextDebug(
"ictrl_dispatch_event caret changed %d %d", lastCaret, m_caretPosition);
694void QQnxInputContext::closeSession()
706 m_isComposing =
false;
707 m_composingText.
clear();
710bool QQnxInputContext::openSession()
723bool QQnxInputContext::hasSession()
728bool QQnxInputContext::hasSelectedText()
740bool QQnxInputContext::dispatchRequestSoftwareInputPanel()
748bool QQnxInputContext::dispatchCloseSoftwareInputPanel()
759bool QQnxInputContext::dispatchFocusGainEvent(
int inputHints)
762 dispatchFocusLossEvent();
766 if (!
input || !openSession())
776 focus_event_t focusEvent;
778 focusEvent.style = DEFAULT_STYLE;
781 focusEvent.style |= NO_PREDICTION | NO_AUTO_CORRECTION;
783 focusEvent.style |= NO_AUTO_TEXT;
787 focusEvent.style |= IMF_PASSWORD_TYPE;
789 focusEvent.style |= IMF_PHONE_TYPE;
791 focusEvent.style |= IMF_URL_TYPE;
793 focusEvent.style |= IMF_EMAIL_TYPE;
803void QQnxInputContext::dispatchFocusLossEvent()
808 focus_event_t focusEvent;
823 bool navigationKey =
false;
831 case KEYCODE_BACKSPACE:
836 if (hasSelectedText())
841 navigationKey =
true;
844 key = NAVIGATE_RIGHT;
845 navigationKey =
true;
849 navigationKey =
true;
853 navigationKey =
true;
855 case KEYCODE_LEFT_CTRL:
856 case KEYCODE_RIGHT_CTRL:
858 case KEYCODE_LEFT_HYPER:
859 case KEYCODE_RIGHT_HYPER:
864 case KEYCODE_PG_DOWN:
877 if (
flags & KEY_DOWN ) {
878 navigation_event_t navEvent;
880 navEvent.magnitude = 1;
885 key_event_t keyEvent;
888 keyEvent.key_code =
cap;
889 keyEvent.character = sym;
890 keyEvent.meta_key_state = mod;
891 keyEvent.sequence_id = sequenceId;
900void QQnxInputContext::updateCursorPosition()
913void QQnxInputContext::endComposition()
918 finishComposingText();
921 action_event_t actionEvent;
928void QQnxInputContext::updateComposition(spannable_string_t *
text, int32_t new_cursor_position)
934 if (new_cursor_position > 0)
938 m_isComposing =
true;
948 for (
unsigned int i = 0;
i <
text->spans_count; ++
i) {
950 bool underline =
false;
952 if ((
text->spans[
i].attributes_mask & COMPOSED_TEXT_ATTRIB) != 0)
955 if ((
text->spans[
i].attributes_mask & ACTIVE_REGION_ATTRIB) != 0) {
958 }
else if ((
text->spans[
i].attributes_mask & AUTO_CORRECTION_ATTRIB) != 0) {
960 }
else if ((
text->spans[
i].attributes_mask & REVERT_CORRECTION_ATTRIB) != 0) {
961 highlightColor = m_highlightColor[
Reverted];
964 if (underline || highlightColor.
isValid()) {
967 format.setFontUnderline(
true);
977 m_isUpdatingText =
true;
979 m_isUpdatingText =
false;
981 updateCursorPosition();
984void QQnxInputContext::finishComposingText()
992 event.setCommitString(m_composingText);
993 m_isUpdatingText =
true;
995 m_isUpdatingText =
false;
998 m_isComposing =
false;
1000 updateCursorPosition();
1009 int utf16Index = utf32Index + *highSurrogateCount;
1010 while (utf16StartIndex < utf16Index) {
1011 if (
text[utf16StartIndex].isHighSurrogate()) {
1013 ++*highSurrogateCount;
1017 return utf16StartIndex;
1020int QQnxInputContext::handleSpellCheck(spell_check_event_t *
event)
1023 if (sSpellCheckQueue->isEmpty() ||
event->event.event_id != NOTIFY_SP_CHECK_MISSPELLINGS)
1027 spannable_string_t* spellCheckData = *
event->data;
1036 for (
unsigned int i = 0;
i < spellCheckData->spans_count; ++
i) {
1037 if (spellCheckData->spans[
i].attributes_mask & MISSPELLED_WORD_ATTRIB) {
1049int32_t QQnxInputContext::processEvent(event_t *
event)
1052 switch (
event->event_type) {
1053 case EVENT_SPELL_CHECK: {
1055 result = handleSpellCheck(
reinterpret_cast<spell_check_event_t *
>(
event));
1059 case EVENT_NAVIGATION: {
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;
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;
1078 if (kevent->meta_key_state & META_SHIFT_ON)
1080 int flags = KEY_SYM_VALID | KEY_CAP_VALID;
1081 if (
event->event_id == IMF_KEY_DOWN)
1096 case EVENT_USER_ACTION:
1098 case EVENT_INVOKE_LATER:
1099 qCritical() <<
"Unsupported event type: " <<
event->event_type;
1102 qCritical() <<
"Unknown event type: " <<
event->event_type;
1111int32_t QQnxInputContext::onCommitText(spannable_string_t *
text, int32_t new_cursor_position)
1115 updateComposition(
text, new_cursor_position);
1116 finishComposingText();
1121int32_t QQnxInputContext::onDeleteSurroundingText(int32_t left_length, int32_t right_length)
1129 int replacementLength = left_length + right_length;
1130 int replacementStart = -left_length;
1132 finishComposingText();
1135 event.setCommitString(
QString(), replacementStart, replacementLength);
1136 m_isUpdatingText =
true;
1138 m_isUpdatingText =
false;
1140 updateCursorPosition();
1145int32_t QQnxInputContext::onFinishComposingText()
1147 finishComposingText();
1152int32_t QQnxInputContext::onGetCursorPosition()
1160 updateCursorPosition();
1162 return m_caretPosition;
1165spannable_string_t *QQnxInputContext::onGetTextAfterCursor(int32_t
n, int32_t
flags)
1182spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(int32_t
n, int32_t
flags)
1196 if (
n < m_caretPosition)
1202int32_t QQnxInputContext::onSendEvent(event_t *
event)
1206 return processEvent(
event);
1209int32_t QQnxInputContext::onSetComposingRegion(int32_t
start, int32_t
end)
1222 m_isUpdatingText =
true;
1230 m_isComposing =
true;
1234 format.setFontUnderline(
true);
1240 m_isUpdatingText =
false;
1245int32_t QQnxInputContext::onSetComposingText(spannable_string_t *
text, int32_t new_cursor_position)
1248 updateComposition(
text, new_cursor_position);
1253 m_composingText.
clear();
1254 finishComposingText();
1259int32_t QQnxInputContext::onIsTextSelected(int32_t* pIsSelected)
1261 *pIsSelected = hasSelectedText();
1268int32_t QQnxInputContext::onIsAllTextSelected(int32_t* pIsSelected)
1287 dispatchRequestSoftwareInputPanel();
1293 dispatchCloseSoftwareInputPanel();
1298 return m_inputPanelVisible;
1303 return m_inputPanelLocale;
1306void QQnxInputContext::keyboardVisibilityChanged(
bool visible)
1309 if (m_inputPanelVisible != visible) {
1310 m_inputPanelVisible = visible;
1315void QQnxInputContext::keyboardLocaleChanged(
const QLocale &locale)
1318 if (m_inputPanelLocale !=
locale) {
1319 m_inputPanelLocale =
locale;
1351 if (m_inputPanelVisible)
1354 dispatchFocusLossEvent();
1361 dispatchFocusGainEvent(inputHints);
1368 if (!m_inputPanelVisible)
1383 action_event_t spellEvent;
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);
The QColor class provides colors based on RGB, HSV or CMYK values.
bool isValid() const noexcept
Returns true if the color is valid; otherwise returns false.
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
@ CloseSoftwareInputPanel
@ RequestSoftwareInputPanel
void push_back(parameter_type t)
void append(parameter_type t)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
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.
void setEnterKeyType(EnterKeyType type)
virtual bool showKeyboard()=0
void setInputHints(int inputHints)
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
int32_t new_cursor_position
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.
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr int width() const noexcept
Returns the width of the rectangle.
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype toWCharArray(wchar_t *array) const
void clear()
Clears the contents of the string and makes it null.
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
iterator end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing just after the last character in the ...
QChar * data()
Returns a pointer to the data stored in the QString.
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
qsizetype length() const
Returns the number of characters in this string.
EGLImageKHR int int EGLuint64KHR * modifiers
Combined button and popup list for selecting options.
@ ImhDialableCharactersOnly
@ BlockingQueuedConnection
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 Q_ARG(Type, data)
GLuint64 GLenum void * handle
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei GLsizei GLenum format
GLsizei GLenum const void * indices
GLenum GLenum GLenum input
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)
@ ImfDeleteSurroundingText
static int32_t(* p_vkb_init_selection_service)()
#define qInputContextIMFRequestDebug
QNetworkRequest request(url)
void(* spellCheckDone)(void *, const QString &, const QList< int > &)
SpellCheckInfo(void *_context, void(*_spellCheckDone)(void *, const QString &, const QList< int > &))