From 65c5f90299193d1ef658b9b17cab551e03fbe14a Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Thu, 20 Oct 2011 16:46:12 +0300 Subject: Accepting predicted text using hardware keyboard replaces unwanted part Current implementation of Symbian input context assumes that predicted word replacement happens so that the original typed text is at the end of the surrounded text. The logic fails, if to-be-predicted text is in the middle of, or in the beginning of another, already accepted word. As a fix, input context need to store the original cursor position, when reset() was called (this happens when word selection list appears). Input context is already storing a copy of a preedit string in this situation. Then, when word replacement happens, this stored cursor position is used instead of current cursor position (the native side might temporarily move the cursor to the end when word selection list opens or closes) to replace the typed word with one selected from suggested word list. Stored cursor position is dismissed immediately after used, or if cached preedit string is dismissed. Task-number: QTBUG-22147 Reviewed-by: Miikka Heikkinen --- src/gui/inputmethod/qcoefepinputcontext_p.h | 1 + src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 37 +++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 8c30838071..cefae5e519 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -162,6 +162,7 @@ private: QBasicTimer m_tempPreeditStringTimeout; bool m_hasTempPreeditString; QString m_cachedPreeditString; + int m_cachedCursorAndAnchorPosition; int m_splitViewResizeBy; Qt::WindowStates m_splitViewPreviousWindowStates; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 79005ce88a..66ab4c886d 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -115,6 +115,7 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_formatRetriever(0), m_pointerHandler(0), m_hasTempPreeditString(false), + m_cachedCursorAndAnchorPosition(-1), m_splitViewResizeBy(0), m_splitViewPreviousWindowStates(Qt::WindowNoState) { @@ -158,9 +159,18 @@ void QCoeFepInputContext::reset() } // Store a copy of preedit text, if prediction is active and input context is reseted. // This is to ensure that we can replace preedit string after losing focus to FEP manager's - // internal sub-windows. - if (m_cachedPreeditString.isEmpty() && !(currentHints & Qt::ImhNoPredictiveText)) + // internal sub-windows. Additionally, store the cursor position if there is no selected text. + // This allows input context to replace preedit strings if they are not at the end of current + // text. + if (m_cachedPreeditString.isEmpty() && !(currentHints & Qt::ImhNoPredictiveText)) { m_cachedPreeditString = m_preeditString; + if (focusWidget()) { + int cursor = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt(); + int anchor = focusWidget()->inputMethodQuery(Qt::ImAnchorPosition).toInt(); + if (cursor == anchor) + m_cachedCursorAndAnchorPosition = cursor; + } + } commitCurrentString(true); } @@ -196,6 +206,7 @@ void QCoeFepInputContext::setFocusWidget(QWidget *w) void QCoeFepInputContext::widgetDestroyed(QWidget *w) { m_cachedPreeditString.clear(); + m_cachedCursorAndAnchorPosition = -1; // Make sure that the input capabilities of whatever new widget got focused are queried. CCoeControl *ctrl = w->effectiveWinId(); @@ -981,6 +992,7 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, return; m_cachedPreeditString.clear(); + m_cachedCursorAndAnchorPosition = -1; commitTemporaryPreeditString(); @@ -1039,8 +1051,16 @@ void QCoeFepInputContext::UpdateFepInlineTextL(const TDesC& aNewInlineText, QString newPreeditString = qt_TDesC2QString(aNewInlineText); QInputMethodEvent event(newPreeditString, attributes); if (!m_cachedPreeditString.isEmpty()) { - event.setCommitString(QLatin1String(""), -m_cachedPreeditString.length(), m_cachedPreeditString.length()); + int cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); + // Predicted word is either replaced from the end of the word (normal case), + // or from stored location, if the predicted word is either in the beginning of, + // or in the middle of already committed word. + int diff = cursorPos - m_cachedCursorAndAnchorPosition; + int replaceLocation = (diff != m_cachedPreeditString.length()) ? diff : m_cachedPreeditString.length(); + + event.setCommitString(QLatin1String(""), -replaceLocation, m_cachedPreeditString.length()); m_cachedPreeditString.clear(); + m_cachedCursorAndAnchorPosition = -1; } else if (newPreeditString.isEmpty() && m_preeditString.isEmpty()) { // In Symbian world this means "erase last character". event.setCommitString(QLatin1String(""), -1, 1); @@ -1138,6 +1158,10 @@ void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCur int pos = aCursorSelection.iAnchorPos; int length = aCursorSelection.iCursorPos - pos; + if (m_cachedCursorAndAnchorPosition != -1) { + pos = m_cachedCursorAndAnchorPosition; + length = 0; + } QList attributes; attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos, length, QVariant()); @@ -1155,6 +1179,13 @@ void QCoeFepInputContext::GetCursorSelectionForFep(TCursorSelection& aCursorSele int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt() + m_preeditString.size(); int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt() + m_preeditString.size(); + + // If the position is stored, use that value, so that word replacement from proposed word + // lists are added to the correct position. + if (m_cachedCursorAndAnchorPosition != -1) { + cursor = m_cachedCursorAndAnchorPosition; + anchor = m_cachedCursorAndAnchorPosition; + } QString text = w->inputMethodQuery(Qt::ImSurroundingText).value(); int combinedSize = text.size() + m_preeditString.size(); if (combinedSize < anchor || combinedSize < cursor) { -- cgit v1.2.1 From e2b892c48c986c38f431b1af98023d16af53bc96 Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Fri, 21 Oct 2011 12:14:58 +0200 Subject: Fix security problem on webpage due to bad JS Reviewed-by: Trust Me --- doc/src/template/scripts/functions.js | 13 +------------ tools/qdoc3/doc/config/scripts/functions.js | 13 +------------ tools/qdoc3/test/qt-html-templates-online.qdocconf | 13 ------------- tools/qdoc3/test/qt-html-templates_ja_JP-online.qdocconf | 11 ----------- tools/qdoc3/test/qt-html-templates_zh_CN-online.qdocconf | 11 ----------- 5 files changed, 2 insertions(+), 59 deletions(-) diff --git a/doc/src/template/scripts/functions.js b/doc/src/template/scripts/functions.js index 3ab4a082a7..af204d8d06 100755 --- a/doc/src/template/scripts/functions.js +++ b/doc/src/template/scripts/functions.js @@ -183,17 +183,6 @@ var blankRE=/^\s*$/; function CheckEmptyAndLoadList() { - /* Start Extracting information for feedback and adding this to the feedback form */ - var pageUrl = window.location.pathname; - var pageVal = $('title').html(); - $('#pageType').removeClass('red'); - $('#feedUrl').remove(); - $('#pageVal').remove(); - $('.menuAlert').remove(); - $('#feedform').append(''); - $('#feedform').append(''); - /* End Extracting information for feedback and adding this to the feedback form */ - /* extracts search query */ var value = document.getElementById('pageType').value; /* if the search is less than three chars long remove class names and remove elements from old search*/ @@ -255,4 +244,4 @@ function CheckEmptyAndLoadList() }); }, 500); /* timer set to 500 ms */ }); - }); \ No newline at end of file + }); diff --git a/tools/qdoc3/doc/config/scripts/functions.js b/tools/qdoc3/doc/config/scripts/functions.js index 62bc53508e..af204d8d06 100755 --- a/tools/qdoc3/doc/config/scripts/functions.js +++ b/tools/qdoc3/doc/config/scripts/functions.js @@ -183,17 +183,6 @@ var blankRE=/^\s*$/; function CheckEmptyAndLoadList() { - /* Start Extracting information for feedback and adding this to the feedback form */ - var pageUrl = window.location.href; - var pageVal = $('title').html(); - $('#pageType').removeClass('red'); - $('#feedUrl').remove(); - $('#pageVal').remove(); - $('.menuAlert').remove(); - $('#feedform').append(''); - $('#feedform').append(''); - /* End Extracting information for feedback and adding this to the feedback form */ - /* extracts search query */ var value = document.getElementById('pageType').value; /* if the search is less than three chars long remove class names and remove elements from old search*/ @@ -255,4 +244,4 @@ function CheckEmptyAndLoadList() }); }, 500); /* timer set to 500 ms */ }); - }); \ No newline at end of file + }); diff --git a/tools/qdoc3/test/qt-html-templates-online.qdocconf b/tools/qdoc3/test/qt-html-templates-online.qdocconf index 77ab3c5e8a..af78088967 100644 --- a/tools/qdoc3/test/qt-html-templates-online.qdocconf +++ b/tools/qdoc3/test/qt-html-templates-online.qdocconf @@ -142,8 +142,6 @@ HTML.postpostheader = \ "
\n" HTML.footer = \ - "
\n" \ - " [+] Documentation Feedback
\n" \ "
\n" \ " \n" \ " \n" \ @@ -169,17 +167,6 @@ HTML.footer = \ " Free Documentation License version 1.3\n" \ " as published by the Free Software Foundation.

\n" \ " \n" \ - "
\n" \ - "
X
\n" \ - "
\n" \ - "

Thank you for giving your feedback.

Make sure it is related to this specific page. For more general bugs and \n" \ - " requests, please use the Qt Bug Tracker.

\n" \ - "

\n" \ - "

\n" \ - "
\n" \ - "
\n" \ - "
\n" \ - "
\n" \ "\n" \ " \n" \ "