summaryrefslogtreecommitdiffstats
path: root/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-10-17 10:44:30 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-10-17 10:44:30 (GMT)
commitf7df64c90e3490f33a9e8115cc5697d878a6ff96 (patch)
treef7c638ff2ea9b2cdd402df20b87834cc0c7d9b15 /src/gui/inputmethod/qcoefepinputcontext_s60.cpp
parentbb47d070b0ad0cccd3a60b6344292f97164c9231 (diff)
parentb01c2c90bf58a96afadc6fc5547203a6a37893c5 (diff)
downloadQt-f7df64c90e3490f33a9e8115cc5697d878a6ff96.zip
Qt-f7df64c90e3490f33a9e8115cc5697d878a6ff96.tar.gz
Qt-f7df64c90e3490f33a9e8115cc5697d878a6ff96.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-symbian-staging into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/qt-symbian-staging: (35 commits) runonphone timestamps nanosecond formating set to 9 chars, 0 padded Put Qt translation files to rom on Symbian. Fix QDeclarativeEngine::setOfflineStoragePath() for Symbian Converting from double to qreal in gui Fix XML schema validation failure. Fix construction races in QtNetwork Removing accidental use of double instead of qreal from QLine Fix incorrect QFileInfo permissions on windows Converting accidental use of doubles to qreal in declarative Copy and Cut are not available for some QML editors Ignore CcpuCan calls if input context is being destroyed Remove one local variable from QCoeFepInputContext Symbian: Fix native dialog with splitscreen VKB focus loss issue Create auto test for http HEAD request QNAM - fix poor performance of HEAD request with authentication runonphone - Implement CODA autodetection Symbian: Parse ts filenames case-insensitively for localize_deployment Do not crash in copy() of pixmaps without an underlying bitmap QTBUG-9113 - reinstating tst_qobjectrace tests for Symbian on Qt 4.8 symbian - document behaviour of QFile::handle() ...
Diffstat (limited to 'src/gui/inputmethod/qcoefepinputcontext_s60.cpp')
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_s60.cpp139
1 files changed, 104 insertions, 35 deletions
diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
index 9025221..8f13c53 100644
--- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
@@ -94,6 +94,11 @@
#define QT_EPSUidAknFep 0x100056de
#define QT_EAknFepTouchInputActive 0x00000004
+// For compatibility with older Symbian^3 environments, which do not have this define yet.
+#ifndef R_AVKON_DISCREET_POPUP_TEXT_COPIED
+#define R_AVKON_DISCREET_POPUP_TEXT_COPIED 0x8cc0227
+#endif
+
_LIT(KAvkonResourceFile, "z:\\resource\\avkon.rsc" );
QT_BEGIN_NAMESPACE
@@ -377,6 +382,7 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent)
m_hasTempPreeditString(false),
m_splitViewResizeBy(0),
m_splitViewPreviousWindowStates(Qt::WindowNoState),
+ m_splitViewPreviousFocusItem(0),
m_ccpu(0)
{
m_fepState->SetObjectProvider(this);
@@ -446,6 +452,11 @@ void QCoeFepInputContext::reset()
if (m_cachedPreeditString.isEmpty() && !(currentHints & Qt::ImhNoPredictiveText))
m_cachedPreeditString = m_preeditString;
commitCurrentString(true);
+
+ // QGraphicsScene calls reset() when changing focus item. Unfortunately, the new focus item is
+ // set right after resetting the input context. Therefore, asynchronously call ensureWidgetVisibility().
+ if (S60->splitViewLastWidget)
+ QMetaObject::invokeMethod(this,"ensureWidgetVisibility", Qt::QueuedConnection);
}
void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType)
@@ -788,9 +799,8 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget)
{
QGraphicsView *gv = qobject_cast<QGraphicsView*>(S60->splitViewLastWidget);
- if (!gv) {
+ if (!gv)
return;
- }
QSymbianControl *symControl = static_cast<QSymbianControl*>(gv->effectiveWinId());
symControl->CancelLongTapTimer();
@@ -805,11 +815,13 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget)
if (!alwaysResize) {
if (gv->scene() && S60->partial_keyboardAutoTranslation) {
if (gv->scene()->focusItem()) {
+ QGraphicsItem *focusItem =
+ m_splitViewPreviousFocusItem ? m_splitViewPreviousFocusItem : gv->scene()->focusItem();
// Check if the widget contains cursorPositionChanged signal and disconnect from it.
QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged()));
- int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1));
+ int index = focusItem->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1));
if (index != -1)
- disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget()));
+ disconnect(focusItem->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget()));
}
QGraphicsItem *rootItem = 0;
@@ -877,10 +889,18 @@ bool QCoeFepInputContext::isPartialKeyboardSupported()
return (S60->partial_keyboard || !QApplication::testAttribute(Qt::AA_S60DisablePartialScreenInputMode));
}
+void QCoeFepInputContext::ensureWidgetVisibility()
+{
+ ensureFocusWidgetVisible(S60->splitViewLastWidget);
+}
+
// Ensure that the input widget is visible in the splitview rect.
void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget)
{
+ if (!widget)
+ return;
+
// Native side opening and closing its virtual keyboard when it changes the keyboard layout,
// has an adverse impact on long tap timer. Cancel the timer when splitview opens to avoid this.
QSymbianControl *symControl = static_cast<QSymbianControl*>(widget->effectiveWinId());
@@ -908,17 +928,22 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget)
// states getting changed.
if (!moveWithinVisibleArea) {
- // Check if the widget contains cursorPositionChanged signal and connect to it.
- QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged()));
- if (gv->scene() && gv->scene()->focusItem() && S60->partial_keyboardAutoTranslation) {
- int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1));
- if (index != -1)
- connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget()));
- }
S60->splitViewLastWidget = widget;
m_splitViewPreviousWindowStates = windowToMove->windowState();
}
+ // Check if the widget contains cursorPositionChanged signal and connect to it.
+ if (gv->scene() && gv->scene()->focusItem() && S60->partial_keyboardAutoTranslation) {
+ QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged()));
+ if (m_splitViewPreviousFocusItem && m_splitViewPreviousFocusItem != gv->scene()->focusItem())
+ disconnect(m_splitViewPreviousFocusItem->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget()));
+ int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1));
+ if (index != -1) {
+ connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget()));
+ m_splitViewPreviousFocusItem = gv->scene()->focusItem();
+ }
+ }
+
int windowTop = widget->window()->pos().y();
const bool userResize = widget->testAttribute(Qt::WA_Resized);
@@ -1083,6 +1108,9 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
} else if (hints & ImhNoAutoUppercase) {
m_fepState->SetDefaultCase(EAknEditorLowerCase);
m_fepState->SetCurrentCase(EAknEditorLowerCase);
+ } else if (hints & ImhHiddenText) {
+ m_fepState->SetDefaultCase(EAknEditorLowerCase);
+ m_fepState->SetCurrentCase(EAknEditorLowerCase);
} else {
m_fepState->SetDefaultCase(EAknEditorTextCase);
m_fepState->SetCurrentCase(EAknEditorTextCase);
@@ -1094,6 +1122,10 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
if (hints & ImhLowercaseOnly) {
flags |= EAknEditorLowerCase;
}
+ if (hints & ImhHiddenText) {
+ flags = EAknEditorAllCaseModes;
+ flags &= ~EAknEditorTextCase;
+ }
if (flags == 0) {
flags = EAknEditorAllCaseModes;
if (hints & ImhNoAutoUppercase) {
@@ -1254,10 +1286,15 @@ void QCoeFepInputContext::translateInputWidget()
m_transformation = (rootItem->transform().isTranslating()) ? QRectF(0,0, gv->width(), rootItem->transform().dy()) : QRectF();
- // Adjust cursor bounding rect to be lower, so that view translates if the cursor gets near
- // the splitview border.
- QRect cursorRect = cursorP.boundingRect().adjusted(0, cursor.height(), 0, cursor.height());
- if (splitViewRect.contains(cursorRect))
+ // Adjust cursor bounding rect towards navigation direction,
+ // so that view translates if the cursor gets near the splitview border.
+ QRect cursorRect = (cursorP.boundingRect().top() < 0) ?
+ cursorP.boundingRect().adjusted(0, -cursor.height(), 0, -cursor.height()) :
+ cursorP.boundingRect().adjusted(0, cursor.height(), 0, cursor.height());
+
+ // If the current cursor position and upcoming cursor positions are visible in the splitview
+ // area, do not move the view.
+ if (splitViewRect.contains(cursorRect) && splitViewRect.contains(cursorP.boundingRect()))
return;
// New Y position should be ideally just above the keyboard.
@@ -1269,18 +1306,29 @@ void QCoeFepInputContext::translateInputWidget()
const qreal itemHeight = path.boundingRect().height();
// Limit the maximum translation so that underlaying window content is not exposed.
- qreal maxY = gv->sceneRect().bottom() - splitViewRect.bottom();
- maxY = m_transformation.height() ? (qMin(itemHeight, maxY) + m_transformation.height()) : maxY;
- if (maxY < 0)
- maxY = 0;
+ qreal availableSpace = gv->sceneRect().bottom() - splitViewRect.bottom();
+ availableSpace = m_transformation.height() ?
+ (qMin(itemHeight, availableSpace) + m_transformation.height()) :
+ availableSpace;
// Translation should happen row-by-row, but initially it needs to ensure that cursor is visible.
const qreal translation = m_transformation.height() ?
cursor.height() : (cursorRect.bottom() - vkbRect.top());
- const qreal dy = -(qMin(maxY, translation));
+ qreal dy = 0.0;
+ if (availableSpace > 0)
+ dy = -(qMin(availableSpace, translation));
+ else
+ dy = -(translation);
+
+ // Correct the translation direction, if the cursor rect would be moved above application area.
+ if ((cursorP.boundingRect().bottom() + dy) < 0)
+ dy *= -1;
- // Do not allow transform above screen top, nor beyond scenerect
- if (m_transformation.height() + dy > 0 || gv->sceneRect().bottom() + m_transformation.height() < 0) {
+ // Do not allow transform above screen top, nor beyond scenerect. Also, if there is no available
+ // space anymore, skip translation.
+ if ((m_transformation.height() + dy) > 0
+ || (gv->sceneRect().bottom() + m_transformation.height()) < 0
+ || !availableSpace) {
// If we already have some transformation, remove it.
if (m_transformation.height() < 0 || gv->sceneRect().bottom() + m_transformation.height() < 0) {
rootItem->resetTransform();
@@ -1596,8 +1644,6 @@ void QCoeFepInputContext::changeCBA(bool showCopyAndOrPaste)
void QCoeFepInputContext::copyOrCutTextToClipboard(const char *operation)
{
- bool hasText = false;
-
QWidget *w = focusWidget();
QObject *focusObject = 0;
if (!w) {
@@ -1613,11 +1659,13 @@ void QCoeFepInputContext::copyOrCutTextToClipboard(const char *operation)
if (cursor != anchor) {
if (ccpuInvokeSlot(w, focusObject, operation)) {
- TRAP_IGNORE(
- CAknDiscreetPopup::ShowGlobalPopupL(
- R_AVKON_DISCREET_POPUP_TEXT_COPIED,
- KAvkonResourceFile);
- )
+ if (QSysInfo::symbianVersion() > QSysInfo::SV_SF_3) {
+ TRAP_IGNORE(
+ CAknDiscreetPopup::ShowGlobalPopupL(
+ R_AVKON_DISCREET_POPUP_TEXT_COPIED,
+ KAvkonResourceFile);
+ )
+ }
}
}
}
@@ -1696,15 +1744,33 @@ TBool QCoeFepInputContext::CcpuIsFocused() const
TBool QCoeFepInputContext::CcpuCanCut() const
{
bool retval = false;
+ if (m_inDestruction)
+ return retval;
QWidget *w = focusWidget();
- if (!w)
+ QObject *focusObject = 0;
+ if (!w) {
w = m_lastFocusedEditor;
- else
- w = getQWidgetFromQGraphicsView(w);
+ focusObject = m_lastFocusedObject;
+ } else {
+ w = getQWidgetFromQGraphicsView(w, &focusObject);
+ }
if (w) {
- int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
- int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt();
- retval = cursor != anchor;
+ QRect microFocus = w->inputMethodQuery(Qt::ImMicroFocus).toRect();
+ if (microFocus.isNull()) {
+ // For some reason, the editor does not have microfocus. Most probably,
+ // it is due to using native fullscreen editing mode with QML apps.
+ // Try accessing "selectedText" directly.
+ QObject *invokeTarget = w;
+ if (focusObject)
+ invokeTarget = focusObject;
+
+ QString selectedText = invokeTarget->property("selectedText").toString();
+ retval = !selectedText.isNull();
+ } else {
+ int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
+ int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt();
+ retval = cursor != anchor;
+ }
}
return retval;
}
@@ -1727,6 +1793,9 @@ void QCoeFepInputContext::CcpuCopyL()
TBool QCoeFepInputContext::CcpuCanPaste() const
{
bool canPaste = false;
+ if (m_inDestruction)
+ return canPaste;
+
QString textToPaste = QApplication::clipboard()->text();
if (!textToPaste.isEmpty()) {
QWidget *w = focusWidget();