[meego-commits] 14385: Changes to Trunk/meegotouch-inputmethodkeyboard
Peter Zhu
no_reply at build.meego.com
Tue Mar 1 12:55:10 UTC 2011
Hi,
I have made the following changes to meegotouch-inputmethodkeyboard in project Trunk. Please review and accept ASAP.
Thank You,
Peter Zhu
[This message was auto-generated]
---
Request #14385:
submit: Trunk:Testing/meegotouch-inputmethodkeyboard(r2) -> Trunk/meegotouch-inputmethodkeyboard
Message:
Move to Trunk
State: new 2011-02-28T23:53:08 peter
Comment: None
changes files:
--------------
--- meegotouch-inputmethodkeyboard.changes
+++ meegotouch-inputmethodkeyboard.changes
@@ -0,0 +1,8 @@
+* Thu Feb 24 2011 Luis Araujo <luis.araujo at collabora.co.uk> - 0.5.28
+- Update to release tag 0.5.28-1 (BMC#13345, BMC#12978)
+
+* Fri Feb 04 2011 Luis Araujo <luis.araujo at collabora.co.uk> - 0.5.26
+- Update to release tag 0.5.26-1 (BMC#13233)
+- Add version dependency on framework >= 0.19.41, meegotouch >= 0.20.77
+- Update files paths
+
old:
----
meegotouch-inputmethodkeyboard-0.5.25.tar.bz2
new:
----
meegotouch-inputmethodkeyboard-0.5.28.tar.bz2
spec files:
-----------
--- meegotouch-inputmethodkeyboard.spec
+++ meegotouch-inputmethodkeyboard.spec
@@ -7,20 +7,17 @@
Name: meegotouch-inputmethodkeyboard
Summary: MeeGo Virtual Keyboard
-Version: 0.5.25
+Version: 0.5.28
Release: 1
Group: System/GUI/Other
License: LGPLv2.1
URL: http://meego.gitorious.org/meegotouch/meegotouch-inputmethodkeyboard
Source0: %{name}-%{version}.tar.bz2
Source100: meegotouch-inputmethodkeyboard.yaml
-Requires(pre): GConf2
-Requires(preun): GConf2
-Requires(post): GConf2
BuildRequires: pkgconfig(QtGui) >= 4.6.0
BuildRequires: pkgconfig(MeegoImEngine) >= 0.4.1
-BuildRequires: pkgconfig(MeegoImFramework) >= 0.19.40
-BuildRequires: pkgconfig(meegotouch) >= 0.20
+BuildRequires: pkgconfig(MeegoImFramework) >= 0.19.41
+BuildRequires: pkgconfig(meegotouch) >= 0.20.77
BuildRequires: pkgconfig(meegotouch-feedbackreactionmaps)
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(xkbfile) >= 1.0.6
@@ -85,26 +82,8 @@
# >> install post
# << install post
-%pre
-if [ "$1" -gt 1 ]; then
- export GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source`
- gconftool-2 --makefile-uninstall-rule \
- %{_datadir}/gconf/schemas/meego-keyboard.schemas \
- > /dev/null || :
-fi
-
-%preun
-if [ "$1" -eq 0 ]; then
- export GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source`
- gconftool-2 --makefile-uninstall-rule \
- %{_datadir}/gconf/schemas/meego-keyboard.schemas \
- > /dev/null || :
-fi
-
-%post
-export GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source`
-gconftool-2 --makefile-install-rule \
- %{_datadir}/gconf/schemas/meego-keyboard.schemas > /dev/null || :
+
+
other changes:
--------------
++++++ meegotouch-inputmethodkeyboard-0.5.25.tar.bz2 -> meegotouch-inputmethodkeyboard-0.5.28.tar.bz2
--- debian/changelog
+++ debian/changelog
@@ -1,8 +1,28 @@
-meego-keyboard (0.5.26~1) unstable; urgency=low
+meego-keyboard (0.5.29~1) unstable; urgency=low
* [UNRELEASED]
- -- huaming wang <huaming.wang at nokia.com> Wed, 26 Jan 2011 10:31:42 +0200
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Thu, 24 Feb 2011 13:35:46 +0200
+
+meego-keyboard (0.5.28-1) unstable; urgency=low
+
+ * New release
+
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Thu, 24 Feb 2011 13:34:10 +0200
+
+meego-keyboard (0.5.27-1) unstable; urgency=low
+
+ * Fixes: NB#228917 - meego-keyboard provides dev package with missing dependencies
+
+ -- huaming wang <huaming.wang at nokia.com> Wed, 23 Feb 2011 16:16:40 +0200
+
+meego-keyboard (0.5.26-1) unstable; urgency=low
+
+ * Fixes: NB#218821 - With the VKB default language as English(UK), error correction and word completion are not working
+ * Fixes: NB#222168 - libmeegotouch in can't uphold locked window orientation
+ * Fixes: unwanted long presses in case of delays in event delivery
+
+ -- huaming wang <huaming.wang at nokia.com> Thu, 03 Feb 2011 13:18:26 +0200
meego-keyboard (0.5.25-1) unstable; urgency=low
--- debian/control
+++ debian/control
@@ -2,7 +2,7 @@
Section: libs
Priority: extra
Maintainer: Mohammad Anwari <Mohammad.Anwari at nokia.com>
-Build-Depends: debhelper (>= 5), libqt4-dev (>= 4.6), doxygen, libmeegoimengine-dev (>= 0.4.1), libmeegoimframework-dev (>= 0.19.40~1), libmeegotouch-dev (>= 0.20), libmeegoreactionmap-dev (>= 0.14.0-1), libxkbfile-dev (>= 1.0.6)
+Build-Depends: debhelper (>= 5), libqt4-dev (>= 4.6), doxygen, libmeegoimengine-dev (>= 0.4.1), libmeegoimframework-dev (>= 0.19.41~1), libmeegotouch-dev (>= 0.20), libmeegoreactionmap-dev (>= 0.14.0-1), libxkbfile-dev (>= 1.0.6)
Standards-Version: 3.7.2
Package: meego-keyboard
@@ -21,7 +21,7 @@
Package: meego-keyboard-dev
Section: devel
Architecture: all
-Depends: meego-keyboard (= ${binary:Version})
+Depends: meego-keyboard (= ${binary:Version}), libqt4-dev (>= 4.6), libmeegotouch-dev, libmeegofeedback-dev
Description: MeegoTouch Input Method Keyboard header files
MeegoTouch Keyboard header files.
--- doc/src/layoutxml.dox
+++ doc/src/layoutxml.dox
@@ -119,10 +119,6 @@
just keys and spacers. A row may be empty.
-\subsection Key
-
-Key element describes a visible key on the keyboard.
-
\subsection Spacer
Spacers can be used for alignment purposes. They distribute all remaining space
@@ -130,6 +126,10 @@
For instance, to get a center-aligned row, put spacer elements in the beginning and end of a row. Spacer elements are cumulative, i.e., <spacer/><spacer/> will get twice the space of a single spacer.
+\subsection Key
+
+Key element describes a visible key on the keyboard.
+
Attributes:
\li \c style The style type this key should use. The style type is defined in
@@ -139,6 +139,7 @@
\li \c fixed If false, this button uses a relative width. Otherwise uses fixed
width.
\li \c rtl If true, this button uses RTL version of icon.
+\li \c id Unique identifier of the key, optional. Needs to exist for keys that can be customized by the application.
\subsection Binding
--- m-keyboard/common/common.pri
+++ m-keyboard/common/common.pri
@@ -5,10 +5,12 @@
$$COMMON_DIR/keyevent.h \
$$COMMON_DIR/layoutdata.h \
$$COMMON_DIR/mkeyboardcommon.h \
+ $$COMMON_DIR/reactionmappainter.h \
$$COMMON_DIR/regiontracker.h \
HEADERS += \
$$INSTALL_HEADERS \
+ $$COMMON_DIR/reactionmappainter_p.h \
$$COMMON_DIR/regiontracker_p.h \
$$COMMON_DIR/keyboarddata.h \
$$COMMON_DIR/layoutsmanager.h \
@@ -21,6 +23,8 @@
$$COMMON_DIR/flickgesture.h \
$$COMMON_DIR/flickgesturerecognizer.h \
$$COMMON_DIR/keyboardmapping.h \
+ $$COMMON_DIR/simplefilelog.h \
+ $$COMMON_DIR/mimreactionmap.h \
SOURCES += \
$$COMMON_DIR/keyboarddata.cpp\
@@ -37,8 +41,9 @@
$$COMMON_DIR/flickgesture.cpp \
$$COMMON_DIR/flickgesturerecognizer.cpp \
$$COMMON_DIR/keyboardmapping.cpp \
+ $$COMMON_DIR/reactionmappainter.cpp \
$$COMMON_DIR/regiontracker.cpp \
+ $$COMMON_DIR/simplefilelog.cpp \
INCLUDEPATH += $$COMMON_DIR
DEPENDPATH += $$COMMON_DIR
-
--- m-keyboard/common/keyboarddata.cpp
+++ m-keyboard/common/keyboarddata.cpp
@@ -22,95 +22,96 @@
#include <QDir>
#include <QDomDocument>
#include <QFile>
+#include <QSet>
namespace
{
// TODO: Support Windows paths too.
- const QString VKBConfigurationPath = "/usr/share/meegotouch/virtual-keyboard/layouts/";
-
- const QString VKBTagKeyboard = QString("keyboard");
- const QString VKBTagVersion = QString("version");
- const QString VKBTagCatalog = QString("catalog");
- const QString VKBTagAutoCapitalization = QString("autocapitalization");
- const QString VKBTagLayout = QString("layout");
- const QString VKBTagTitle = QString("title");
- const QString VKBTagLanguage = QString("language");
- const QString VKBTagBoolTrue = QString("true");
- const QString VKBTagBoolFalse = QString("false");
- const QString VKBTagType = QString("type");
- const QString VKBTagTypeGeneral = QString("general");
- const QString VKBTagTypeUrl = QString("url");
- const QString VKBTagTypeEmail = QString("email");
- const QString VKBTagTypeNumber = QString("number");
- const QString VKBTagTypePhoneNumber = QString("phonenumber");
- const QString VKBTagTypeCommon = QString("common");
- const QString VKBTagOrientation = QString("orientation");
- const QString VKBTagOrientationLandscape = QString("landscape");
- const QString VKBTagOrientationPortrait = QString("portrait");
-
- const QString VKBTagID = QString("id");
- const QString VKBTagWidth = QString("width");
- const QString VKBTagHeight = QString("height");
-
- const QString VKBTagTypeNonsloppy = QString("non-sloppy");
- const QString VKBTagHorizontalAlignment = QString("horizontal_alignment");
- const QString VKBTagVerticalAlignment = QString("vertical_alignment");
- const QString VKBTagAlignFull = QString("full");
- const QString VKBTagAlignLeft = QString("left");
- const QString VKBTagAlignRight = QString("right");
- const QString VKBTagAlignBottom = QString("bottom");
- const QString VKBTagAlignTop = QString("top");
- const QString VKBTagAlignCenter = QString("center");
-
- const QString VKBTagRow = QString("row");
- const QString VKBTagSection = QString("section");
- const QString VKBTagMovable = QString("movable");
-
- const QString VKBTagBinding = QString("binding");
- const QString VKBTagKey = QString("key");
- const QString VKBTagSpacer = QString("spacer");
-
- const QString VKBTagKeyAction = QString("action");
- const QString VKBTagShift = QString("shift");
- const QString VKBTagLabel = QString("label");
- const QString VKBTagSecondaryLabel = QString("secondary_label");
- const QString VKBTagAccents = QString("accents");
- const QString VKBTagAccentedLabels = QString("accented_labels");
- const QString VKBTagExtendedLabels = QString("extended_labels");
- const QString VKBTagCycleSet = QString("cycleset");
- const QString VKBTagDead = QString("dead");
- const QString VKBTagQuickPick = QString("quickpick");
-
- const QString ActionStrInsert = QString("insert");
- const QString ActionStrShift = QString("shift");
- const QString ActionStrBackspace = QString("backspace");
- const QString ActionStrSpace = QString("space");
- const QString ActionStrCycle = QString("cycle");
- const QString ActionStrLayoutMenu = QString("layout_menu");
- const QString ActionStrSym = QString("sym");
- const QString ActionStrReturn = QString("return");
- const QString ActionStrDecimalSeparator = QString("decimal_separator");
- const QString ActionStrPlusMinusToggle = QString("plus_minus_toggle");
- const QString ActionStrTab = QString("tab");
- const QString ActionStrCommit = QString("commit");
- const QString ActionStrSwitch = QString("switch");
-
- const QString VKBTagImport = QString("import");
- const QString VKBTagFile = QString("file");
-
- const QString RtlString = QString("rtl");
- const QString RtlStringDefValue = QString("false");
-
- const QString StyleString = QString("style");
- const QString StyleStringDefValue = QString("normal");
- const QString WidthTypeString = QString("width");
- const QString WidthTypeStringDefValue = QString("medium");
- const QString FixedString = QString("fixed");
- const QString FixedStringDefValue = QString("false");
- const QString HeightTypeString = QString("height");
- const QString HeightTypeStringDefValue = QString("medium");
+ const char * const VKBConfigurationPath = "/usr/share/meegotouch/virtual-keyboard/layouts/";
+ const char * const VKBTagKeyboard = "keyboard";
+ const char * const VKBTagVersion = "version";
+ const char * const VKBTagCatalog = "catalog";
+ const char * const VKBTagAutoCapitalization = "autocapitalization";
+ const char * const VKBTagLayout = "layout";
+ const char * const VKBTagTitle = "title";
+ const char * const VKBTagLanguage = "language";
+ const char * const VKBTagBoolTrue = "true";
+ const char * const VKBTagBoolFalse = "false";
+ const char * const VKBTagType = "type";
+ const char * const VKBTagTypeGeneral = "general";
+ const char * const VKBTagTypeUrl = "url";
+ const char * const VKBTagTypeEmail = "email";
+ const char * const VKBTagTypeNumber = "number";
+ const char * const VKBTagTypePhoneNumber = "phonenumber";
+ const char * const VKBTagTypeCommon = "common";
+ const char * const VKBTagOrientation = "orientation";
+ const char * const VKBTagOrientationLandscape = "landscape";
+ const char * const VKBTagOrientationPortrait = "portrait";
+
+ const char * const VKBTagID = "id";
+ const char * const VKBTagWidth = "width";
+ const char * const VKBTagHeight = "height";
+
+ const char * const VKBTagTypeNonsloppy = "non-sloppy";
+ const char * const VKBTagHorizontalAlignment = "horizontal_alignment";
+ const char * const VKBTagVerticalAlignment = "vertical_alignment";
+ const char * const VKBTagAlignFull = "full";
+ const char * const VKBTagAlignLeft = "left";
+ const char * const VKBTagAlignRight = "right";
+ const char * const VKBTagAlignBottom = "bottom";
+ const char * const VKBTagAlignTop = "top";
+ const char * const VKBTagAlignCenter = "center";
+
+ const char * const VKBTagRow = "row";
+ const char * const VKBTagSection = "section";
+ const char * const VKBTagMovable = "movable";
+
+ const char * const VKBTagBinding = "binding";
+ const char * const VKBTagKey = "key";
+ const char * const VKBTagSpacer = "spacer";
+
+ const char * const VKBTagKeyAction = "action";
+ const char * const VKBTagShift = "shift";
+ const char * const VKBTagLabel = "label";
+ const char * const VKBTagSecondaryLabel = "secondary_label";
+ const char * const VKBTagAccents = "accents";
+ const char * const VKBTagAccentedLabels = "accented_labels";
+ const char * const VKBTagExtendedLabels = "extended_labels";
+ const char * const VKBTagCycleSet = "cycleset";
+ const char * const VKBTagDead = "dead";
+ const char * const VKBTagQuickPick = "quickpick";
+
+ const char * const ActionStrInsert = "insert";
+ const char * const ActionStrShift = "shift";
+ const char * const ActionStrBackspace = "backspace";
+ const char * const ActionStrSpace = "space";
+ const char * const ActionStrCycle = "cycle";
+ const char * const ActionStrLayoutMenu = "layout_menu";
+ const char * const ActionStrSym = "sym";
+ const char * const ActionStrReturn = "return";
+ const char * const ActionStrDecimalSeparator = "decimal_separator";
+ const char * const ActionStrPlusMinusToggle = "plus_minus_toggle";
+ const char * const ActionStrTab = "tab";
+ const char * const ActionStrCommit = "commit";
+ const char * const ActionStrSwitch = "switch";
+
+ const char * const VKBTagImport = "import";
+ const char * const VKBTagFile = "file";
+
+ const char * const RtlString = "rtl";
+ const char * const RtlStringDefValue = "false";
+
+ const char * const StyleString = "style";
+ const char * const StyleStringDefValue = "normal";
+ const char * const WidthTypeString = "width";
+ const char * const WidthTypeStringDefValue = "medium";
+ const char * const FixedString = "fixed";
+ const char * const FixedStringDefValue = "false";
+ const char * const HeightTypeString = "height";
+ const char * const HeightTypeStringDefValue = "medium";
+ const char * const KeyIdString = "id";
}
struct ParseParameters {
@@ -125,6 +126,9 @@
//! Contains true if current XML tag was successfully parsed
bool validTag;
+ //! Contains key identifiers for current section
+ QSet<QString> keyIds;
+
const QString *fileName;
ParseParameters();
@@ -328,8 +332,8 @@
keyboardAutoCapsEnabled = toBoolean(root.attribute(VKBTagAutoCapitalization, "true"));
}
- parseChildren(root, params, &VKBTagImport, &KeyboardData::parseTagImport,
- &VKBTagLayout, &KeyboardData::parseTagLayout);
+ parseChildren(root, params, VKBTagImport, &KeyboardData::parseTagImport,
+ VKBTagLayout, &KeyboardData::parseTagLayout);
valid = params.validTag;
}
@@ -342,7 +346,7 @@
* change this to accept an array of (tagname, parser) structures.
*/
void KeyboardData::parseChildren(const QDomElement &element, ParseParameters ¶ms,
- const QString *tag1, TagParser parser1, const QString *tag2,
+ const char * const tag1, TagParser parser1, const char * const tag2,
TagParser parser2)
{
Q_ASSERT(tag1);
@@ -352,9 +356,9 @@
child = child.nextSibling()) {
if (child.isElement()) {
const QDomElement childElement = child.toElement();
- if (childElement.tagName() == *tag1) {
+ if (childElement.tagName() == tag1) {
(this->*parser1)(childElement, params);
- } else if ((tag2 != NULL) && (childElement.tagName() == *tag2)) {
+ } else if ((tag2 != NULL) && (childElement.tagName() == tag2)) {
Q_ASSERT(parser2 != 0);
(this->*parser2)(childElement, params);
} else {
@@ -362,9 +366,9 @@
<< childElement.lineNumber() << "column" << childElement.columnNumber()
<< "in layout file" << *params.fileName;
if (tag2) {
- qWarning() << "Allowed tags are" << *tag1 << "and" << *tag2;
+ qWarning() << "Allowed tags are" << tag1 << "and" << tag2;
} else {
- qWarning() << "The only allowed tag is" << *tag1;
+ qWarning() << "The only allowed tag is" << tag1;
}
params.validTag = false;
}
@@ -440,7 +444,7 @@
currentLayout = layoutModel;
- parseChildren(element, params, &VKBTagSection, &KeyboardData::parseTagSection);
+ parseChildren(element, params, VKBTagSection, &KeyboardData::parseTagSection);
currentLayout->sections = currentLayout->sectionMap.values();
}
@@ -470,8 +474,9 @@
section->sectionName = element.attribute(VKBTagID);
section->sectionType = (element.attribute(VKBTagType) == VKBTagTypeNonsloppy) ? LayoutSection::NonSloppy : LayoutSection::Sloppy;
params.currentSection = section;
+ params.keyIds.clear();
currentLayout->sectionMap.insert(section->sectionName, section);
- parseChildren(element, params, &VKBTagRow, &KeyboardData::parseTagRow);
+ parseChildren(element, params, VKBTagRow, &KeyboardData::parseTagRow);
}
void KeyboardData::parseTagRow(const QDomElement &element, ParseParameters ¶ms)
@@ -482,8 +487,8 @@
params.currentRow = row;
parseChildren(element, params,
- &VKBTagKey, &KeyboardData::parseTagKey,
- &VKBTagSpacer, &KeyboardData::parseTagSpacer);
+ VKBTagKey, &KeyboardData::parseTagKey,
+ VKBTagSpacer, &KeyboardData::parseTagSpacer);
params.currentSection->mMaxColumns = qMax(params.currentSection->maxColumns(),
row->keys.size());
@@ -525,12 +530,23 @@
MImKeyModel::WidthType widthType = toWidthType(element.attribute(WidthTypeString, WidthTypeStringDefValue));
const bool isRtl = toBoolean(element.attribute(RtlString, RtlStringDefValue));
const bool isFixed = toBoolean(element.attribute(FixedString, FixedStringDefValue));
+ const QString keyId = element.attribute(KeyIdString);
+
+ if (!keyId.isEmpty()) {
+ if (params.keyIds.contains(keyId)) {
+ qWarning() << "Invalid virtual keyboard layout file" << *params.fileName
+ << "contains key id" << keyId
+ << "more than one time. Only last key will be registered with this id.";
+ } else {
+ params.keyIds.insert(keyId);
+ }
+ }
- MImKeyModel *key = new MImKeyModel(type, widthType, isFixed, isRtl);
+ MImKeyModel *key = new MImKeyModel(type, widthType, isFixed, isRtl, keyId);
params.currentKey = key;
params.currentRow->keys.append(key);
- parseChildren(element, params, &VKBTagBinding, &KeyboardData::parseTagBinding);
+ parseChildren(element, params, VKBTagBinding, &KeyboardData::parseTagBinding);
if (key->bindings[1] == NULL) {
key->bindings[1] = key->bindings[0];
--- m-keyboard/common/keyboarddata.h
+++ m-keyboard/common/keyboarddata.h
@@ -140,7 +140,7 @@
* \param parser2 compulsory with tag2, parser for the tag2
*/
void parseChildren(const QDomElement &element, ParseParameters ¶ms,
- const QString *tag1, TagParser parser1, const QString *tag2 = NULL,
+ const char * const tag1, TagParser parser1, const char * const tag2 = NULL,
TagParser parser2 = NULL);
//! Parse XML tag for import
--- m-keyboard/common/mhardwarekeyboard.cpp
+++ m-keyboard/common/mhardwarekeyboard.cpp
@@ -234,6 +234,7 @@
}
inputMethodHost.setRedirectKeys(true);
+ emit enabled();
}
@@ -533,7 +534,7 @@
bool MHardwareKeyboard::filterKeyPress(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
QString text, bool autoRepeat, int count,
- quint32 nativeScanCode, quint32 nativeModifiers)
+ quint32 nativeScanCode, quint32 nativeModifiers, unsigned long time)
{
bool eaten = false;
@@ -620,6 +621,8 @@
preeditFormats << preeditFormat;
inputMethodHost.sendPreeditString(text, preeditFormats);
preedit = text;
+ preeditTime = time; // event time is needed by long press undo
+ preeditBeforeLongPress = preedit;
preeditScanCode = nativeScanCode;
} else if (!eaten) {
if (longPressTimer.isActive()) {
@@ -662,7 +665,8 @@
bool MHardwareKeyboard::filterKeyRelease(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
QString text,
- quint32 nativeScanCode, quint32 nativeModifiers)
+ quint32 nativeScanCode, quint32 nativeModifiers,
+ unsigned long time)
{
bool eaten = false;
@@ -715,12 +719,34 @@
eaten = true;
} else if (!eaten && !passKeyOnPress(keyCode, text, nativeScanCode, nativeModifiers)
&& !(pressNativeModifiers & ControlMask)) {
- const bool deadKey(preedit == deadKeyMapper.currentDeadKey());
+ bool deadKey(preedit == deadKeyMapper.currentDeadKey());
+ if (keyWasPressed) {
+ // If there are delays in passing events to us, long press timer may hit even
+ // though the real time difference between press and release actions was
+ // smaller than the long press time. We detect that case here and undo the
+ // long press effect.
+ const bool longPressUndo((preedit != preeditBeforeLongPress)
+ && ((preeditTime + longPressTime) > time)
+ // to make unit tests easier:
+ && !((preeditTime == 0) && (time == 0)));
+ if (longPressUndo) {
+ Q_ASSERT(!longPressTimer.isActive());
+ preedit = preeditBeforeLongPress;
+ (void)deadKeyMapper.filterKeyPress(preedit, true);
+ deadKey = preedit == deadKeyMapper.currentDeadKey();
+ }
- if (keyWasPressed && !deadKey) {
- inputMethodHost.sendCommitString(preedit);
- preedit.clear();
+ if (!deadKey) {
+ inputMethodHost.sendCommitString(preedit);
+ preedit.clear();
+ } else if (longPressUndo) {
+ QList<MInputMethod::PreeditTextFormat> preeditFormats;
+ MInputMethod::PreeditTextFormat preeditFormat(0, preedit.length(), MInputMethod::PreeditKeyPress);
+ preeditFormats << preeditFormat;
+ inputMethodHost.sendPreeditString(text, preeditFormats);
+ }
}
+
eaten = true;
if (!autoCaps && !deadKey && !(pressNativeModifiers & ShiftMask)) {
@@ -753,15 +779,16 @@
bool MHardwareKeyboard::filterKeyEvent(QEvent::Type eventType,
Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
const QString &text, bool autoRepeat, int count,
- quint32 nativeScanCode, quint32 nativeModifiers)
+ quint32 nativeScanCode, quint32 nativeModifiers,
+ unsigned long time)
{
bool eaten = false;
if (eventType == QEvent::KeyPress) {
eaten = filterKeyPress(keyCode, modifiers, text, autoRepeat, count,
- nativeScanCode, nativeModifiers);
+ nativeScanCode, nativeModifiers, time);
} else {
- eaten = filterKeyRelease(keyCode, modifiers, text, nativeScanCode, nativeModifiers);
+ eaten = filterKeyRelease(keyCode, modifiers, text, nativeScanCode, nativeModifiers, time);
}
lastEventType = eventType;
--- m-keyboard/common/mhardwarekeyboard.h
+++ m-keyboard/common/mhardwarekeyboard.h
@@ -115,7 +115,7 @@
bool filterKeyEvent(QEvent::Type eventType, Qt::Key keyCode,
Qt::KeyboardModifiers modifiers, const QString &text,
bool autoRepeat, int count, quint32 nativeScanCode,
- quint32 nativeModifiers);
+ quint32 nativeModifiers, unsigned long time);
//! \return whether the symbol view is available for the current layout.
bool symViewAvailable() const;
@@ -149,6 +149,9 @@
//! \brief Emitted when the script is changed.
void scriptChanged() const;
+ //! \brief Emitted when the hardware keyboard is enabled.
+ void enabled();
+
private slots:
//! Called when long press timer started on key press timeouts.
void handleLongPressTimeout();
@@ -264,12 +267,12 @@
//! Helper for filterKeyEvent, handles press events
bool filterKeyPress(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
QString text, bool autoRepeat, int count,
- quint32 nativeScanCode, quint32 nativeModifiers);
+ quint32 nativeScanCode, quint32 nativeModifiers, unsigned long time);
//! Helper for filterKeyEvent, handles release events
bool filterKeyRelease(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
QString text,
- quint32 nativeScanCode, quint32 nativeModifiers);
+ quint32 nativeScanCode, quint32 nativeModifiers, unsigned long time);
//! Helper for filterKeyRelease and filterKeyPress, handle arrow keys with Fn
bool filterArrowKeys(QEvent::Type eventType, Qt::Key keyCode,
@@ -357,6 +360,10 @@
//! What we've last sent as the preedit string
QString preedit;
+ //! Preedit not touched by long press handling
+ QString preeditBeforeLongPress;
+ //! Time of press event that updated \a preedit (not changed by long press processing or similar)
+ unsigned long preeditTime;
//! Native X keycode of the event that caused \a preedit to be set
quint32 preeditScanCode;
--- m-keyboard/common/mimkeymodel.cpp
+++ m-keyboard/common/mimkeymodel.cpp
@@ -129,11 +129,16 @@
}
-MImKeyModel::MImKeyModel(MImKeyModel::StyleType style, MImKeyModel::WidthType widthType, bool isFixed, bool isRtl)
+MImKeyModel::MImKeyModel(MImKeyModel::StyleType style,
+ MImKeyModel::WidthType widthType,
+ bool isFixed,
+ bool isRtl,
+ const QString &id)
: mStyle(style),
mWidthType(widthType),
isFixed(isFixed),
- isRtl(isRtl)
+ isRtl(isRtl),
+ keyId(id)
{
bindings[NoShift] = 0;
bindings[Shift] = 0;
@@ -187,3 +192,8 @@
return isRtl;
}
+QString MImKeyModel::id() const
+{
+ return keyId;
+}
+
--- m-keyboard/common/mimkeymodel.h
+++ m-keyboard/common/mimkeymodel.h
@@ -194,7 +194,8 @@
* \param isRtl Contains true if button should use RTL icon.
*/
explicit MImKeyModel(StyleType type = NormalStyle, WidthType widthType = Medium,
- bool isFixed = false, bool isRtl = false);
+ bool isFixed = false, bool isRtl = false,
+ const QString &id = QString());
~MImKeyModel();
@@ -231,6 +232,9 @@
//! Returns true if button uses RTL icon.
bool rtl() const;
+ //! Returns key's identifier
+ QString id() const;
+
private:
enum {
NoShift = 0,
@@ -252,6 +256,9 @@
//! Contains true if button uses RTL icon.
bool isRtl;
+ //! Contains key's identifier
+ QString keyId;
+
friend class KeyboardData;
friend class Ut_MImKeyModel;
friend class Ut_MImKey;
--- m-keyboard/common/mimreactionmap.h
+++ m-keyboard/common/mimreactionmap.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef MIMREACTIONMAP_H
+#define MIMREACTIONMAP_H
+
+#include <QString>
+
+namespace MImReactionMap
+{
+const static QString Press = "vkb-press";
+const static QString Release = "vkb-release";
+};
+
+#endif
--- m-keyboard/common/reactionmappainter.cpp
+++ m-keyboard/common/reactionmappainter.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "reactionmappainter.h"
+#include "reactionmappainter_p.h"
+
+#include <mplainwindow.h>
+#include <mreactionmap.h>
+#include <mscene.h>
+
+#include "reactionmappaintable.h"
+
+// ReactionMapPainterPrivate......................................................
+
+ReactionMapPainterPrivate::ReactionMapPainterPrivate()
+{
+ repaintTimer.setSingleShot(true);
+ connect(&repaintTimer, SIGNAL(timeout()), this, SLOT(repaint()));
+}
+
+void ReactionMapPainterPrivate::addWidget(ReactionMapPaintable &widget)
+{
+ connect(&widget.signalForwarder, SIGNAL(requestRepaint()),
+ this, SLOT(requestRepaint()), Qt::UniqueConnection);
+ connect(&widget.signalForwarder, SIGNAL(requestClear()),
+ this, SLOT(clear()), Qt::UniqueConnection);
+ widgets.push_back(&widget);
+}
+
+void ReactionMapPainterPrivate::removeWidget(const ReactionMapPaintable &widget)
+{
+ const int pos(widgets.indexOf(const_cast<ReactionMapPaintable*>(&widget)));
+
+ if (pos >= 0) {
+ widgets.remove(pos);
+ }
+}
+
+void ReactionMapPainterPrivate::clear()
+{
+ const QList<QGraphicsView *> views = MPlainWindow::instance()->scene()->views();
+
+ // Draw invisible color to all reaction maps
+ foreach (QGraphicsView *view, views) {
+ MReactionMap *reactionMap = MReactionMap::instance(view);
+
+ if (reactionMap) {
+ reactionMap->setDrawingValue(MReactionMap::Transparent, MReactionMap::Transparent);
+ reactionMap->setTransform(QTransform());
+ reactionMap->fillRectangle(0, 0, reactionMap->width(), reactionMap->height());
+ }
+ }
+}
+
+
+void ReactionMapPainterPrivate::requestRepaint()
+{
+ if (repaintTimer.isActive())
+ return;
+
+ // The reaction map painting is queued because if it is scheduled too early then
+ // the widget geometries are not ready yet and wrong reaction maps will be
+ // painted.
+ repaintTimer.start(30);
+}
+
+void ReactionMapPainterPrivate::repaint()
+{
+ const QList<QGraphicsView *> views = MPlainWindow::instance()->scene()->views();
+
+ clear();
+ // Draw all reaction maps
+ foreach (QGraphicsView *view, views) {
+ MReactionMap *reactionMap = MReactionMap::instance(view);
+
+ if (!reactionMap) {
+ continue;
+ }
+
+ // Draw the first full-screen and paintable widget and go to the
+ // next reaction map
+ bool fullScreenWidget = false;
+
+ foreach (ReactionMapPaintable *widget, widgets) {
+
+ if (widget->isFullScreen() && widget->isPaintable())
+ {
+ widget->paintReactionMap(reactionMap, view);
+ fullScreenWidget = true;
+ break;
+ }
+ }
+ // Don't draw non-fullscreen widgets and go to the next reaction map
+ if (fullScreenWidget)
+ continue;
+ // Draw the non-fullscreen and paintable widgets
+ foreach (ReactionMapPaintable *widget, widgets) {
+
+ if (widget->isPaintable()) {
+ widget->paintReactionMap(reactionMap, view);
+ }
+ }
+ }
+}
+
+
+// ReactionMapPainter.............................................................
+
+ReactionMapPainter *ReactionMapPainter::singleton = 0;
+
+ReactionMapPainter::ReactionMapPainter()
+ : d_ptr(new ReactionMapPainterPrivate)
+{
+}
+
+ReactionMapPainter::~ReactionMapPainter()
+{
+ delete d_ptr;
+}
+
+void ReactionMapPainter::createInstance()
+{
+ Q_ASSERT(!singleton);
+ if (!singleton) {
+ singleton = new ReactionMapPainter();
+ }
+}
+
+void ReactionMapPainter::destroyInstance()
+{
+ Q_ASSERT(singleton);
+ delete singleton;
+ singleton = 0;
+}
+
+void ReactionMapPainter::addWidget(ReactionMapPaintable &widget)
+{
+ Q_D(ReactionMapPainter);
+ d->addWidget(widget);
+}
+
+void ReactionMapPainter::removeWidget(const ReactionMapPaintable &widget)
+{
+ Q_D(ReactionMapPainter);
+ d->removeWidget(widget);
+}
+
+void ReactionMapPainter::clear()
+{
+ Q_D(ReactionMapPainter);
+ d->clear();
+}
+
+void ReactionMapPainter::repaint()
+{
+ Q_D(ReactionMapPainter);
+ d->requestRepaint();
+}
--- m-keyboard/common/reactionmappainter.h
+++ m-keyboard/common/reactionmappainter.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef REACTIONMAPPAINTER_H
+#define REACTIONMAPPAINTER_H
+
+#include <QObject>
+
+class ReactionMapPainterPrivate;
+class ReactionMapPaintable;
+
+//! \brief A class that does the job of the centralised reaction map painting.
+//!
+//! This class is public and can be used by pop-up plug-ins.
+class ReactionMapPainter : public QObject
+{
+ Q_OBJECT
+
+ //! \brief Constructor.
+ ReactionMapPainter();
+
+public:
+ //! Destructor
+ virtual ~ReactionMapPainter();
+
+ //! \brief Get singleton instance
+ //! \return singleton instance
+ static ReactionMapPainter &instance();
+
+ //! \brief Create singleton
+ static void createInstance();
+
+ //! \brief Destroy singleton
+ static void destroyInstance();
+
+ //! \brief Add \a widget to the reaction map painter
+ void addWidget(ReactionMapPaintable &widget);
+
+ //! \brief Remove \a widget from the reaction map painter
+ void removeWidget(const ReactionMapPaintable &widget);
+
+public slots:
+ //! \brief Clear the reaction maps
+ void clear();
+
+ //! \brief Repaint the reaction maps
+ void repaint();
+private:
+ //! Singleton instance
+ static ReactionMapPainter *singleton;
+
+ ReactionMapPainterPrivate *const d_ptr;
+
+ Q_DECLARE_PRIVATE(ReactionMapPainter)
+};
+
+inline ReactionMapPainter &ReactionMapPainter::instance()
+{
+ Q_ASSERT(singleton);
+ return *singleton;
+}
+
+#endif
--- m-keyboard/common/reactionmappainter_p.h
+++ m-keyboard/common/reactionmappainter_p.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef REACTIONMAPPAINTER_P_H
+#define REACTIONMAPPAINTER_P_H
+
+#include <QObject>
+#include <QTimer>
+#include <QVector>
+
+class ReactionMapPainter;
+class ReactionMapPaintable;
+
+class ReactionMapPainterPrivate : public QObject
+{
+ Q_OBJECT
+ friend class ReactionMapPainter;
+
+public:
+ ReactionMapPainterPrivate();
+
+private:
+ //! \brief Add \a widget to the reaction map painter
+ void addWidget(ReactionMapPaintable &widget);
+
+ //! \brief Remove \a widget from the reaction map painter
+ void removeWidget(const ReactionMapPaintable &widget);
+
+private slots:
+ //! \brief Clear the reaction maps
+ void clear();
+
+ //! \brief Request repainting the reaction maps
+ void requestRepaint();
+
+ //! \brief Repaint the reaction maps
+ void repaint();
+
+private:
+ //! List of paintable widgets
+ QVector<ReactionMapPaintable*> widgets;
+ //! Timer for repainting
+ QTimer repaintTimer;
+
+ Q_DISABLE_COPY(ReactionMapPainterPrivate)
+};
+
+#endif
--- m-keyboard/common/regiontracker.cpp
+++ m-keyboard/common/regiontracker.cpp
@@ -40,8 +40,10 @@
if (!regions.contains(&widget)) {
return;
}
- regions[&widget] = region;
- dirty = true;
+ if (!(regions[&widget] ^ region).isEmpty()) {
+ regions[&widget] = region;
+ dirty = true;
+ }
maybeNotify();
}
@@ -49,7 +51,7 @@
{
if (enabled && dirty) {
const QRegion newRegion(combineRegions());
- if (newRegion != lastRegion) {
+ if (!(newRegion ^ lastRegion).isEmpty()) {
lastRegion = newRegion;
emit regionChanged(newRegion);
}
@@ -60,8 +62,13 @@
QRegion RegionStore::combineRegions() const
{
QRegion combinedRegion;
- foreach (const QRegion &partialRegion, regions) {
- combinedRegion |= partialRegion;
+
+ for (RegionMap::iterator i(regions.begin()); i != regions.end(); ++i) {
+ const QGraphicsWidget &widget(dynamic_cast<const QGraphicsWidget &>(*i.key()));
+ const QRegion region(widget.isVisible() ? widget.mapRectToScene(widget.rect()).toRect()
+ : QRect());
+ combinedRegion |= region;
+ i.value() = region;
}
return combinedRegion;
@@ -94,17 +101,17 @@
{
changeGeometry(widget);
connect(&widget, SIGNAL(geometryChanged()),
- this, SLOT(handleGeometryChange()), Qt::UniqueConnection);
+ this, SLOT(handleGeometryChange()), Qt::QueuedConnection);
connect(&widget, SIGNAL(destroyed(QObject *)),
this, SLOT(handleDestroy(QObject *)), Qt::UniqueConnection);
connect(&widget, SIGNAL(visibleChanged()),
- this, SLOT(handleVisibilityChange()), Qt::UniqueConnection);
+ this, SLOT(handleVisibilityChange()), Qt::QueuedConnection);
}
void RegionTrackerPrivate::handleGeometryChange()
{
const QGraphicsWidget *widget(dynamic_cast<const QGraphicsWidget *>(QObject::sender()));
- if (!widget->isVisible()) {
+ if (!widget || !widget->isVisible()) {
return;
}
changeGeometry(*widget);
@@ -128,6 +135,9 @@
void RegionTrackerPrivate::handleVisibilityChange()
{
const QGraphicsWidget *widget(dynamic_cast<const QGraphicsWidget *>(QObject::sender()));
+ if (!widget) {
+ return;
+ }
changeGeometry(*widget);
}
@@ -146,8 +156,6 @@
this, SIGNAL(regionChanged(const QRegion &)));
connect(&d->inputMethodAreaWidgetRegions, SIGNAL(regionChanged(const QRegion &)),
this, SIGNAL(inputMethodAreaChanged(const QRegion &)));
- connect(this, SIGNAL(regionChanged(const QRegion &)),
- this, SIGNAL(reactionMapUpdateNeeded()));
}
RegionTracker::~RegionTracker()
@@ -196,11 +204,6 @@
return wasEnabled;
}
-void RegionTracker::requestReactionMapUpdate()
-{
- emit reactionMapUpdateNeeded();
-}
-
void RegionTracker::sendInputMethodAreaEstimate(const QRegion ®ion)
{
Q_D(RegionTracker);
--- m-keyboard/common/regiontracker.h
+++ m-keyboard/common/regiontracker.h
@@ -62,9 +62,6 @@
//! signaled if \a flush is true.
bool enableSignals(bool newEnabled, bool flush = true);
- //! \brief Request \a reactionMapUpdateNeeded to be emitted.
- void requestReactionMapUpdate();
-
//! \brief Request given \a region to be emitted via \a inputMethodAreaChanged
//! regardless of signals being enabled or disabled
void sendInputMethodAreaEstimate(const QRegion ®ion);
@@ -80,12 +77,6 @@
//! \brief Screen area covered by widgets registered with \a addInputMethodArea was changed
void inputMethodAreaChanged(const QRegion ®ion);
- //! \brief Emitted whenever reaction map update is needed.
- //!
- //! \a regionChanged emission implies \a reactionMapUpdateNeeded emission, but not the
- //! other way around.
- void reactionMapUpdateNeeded();
-
private:
//! \brief Constructor.
RegionTracker();
--- m-keyboard/common/simplefilelog.cpp
+++ m-keyboard/common/simplefilelog.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "simplefilelog.h"
+
+#include <QDir>
+#include <QCoreApplication>
+
+namespace {
+ const char *const MImUserDirectory = ".meego-im";
+}
+
+SimpleFileLog::SimpleFileLog(const QString &fileName)
+ : mFile()
+ , mStream(&mFile)
+{
+ QString logFilePath = QString("%1/%2/%3-%4").arg(QDir::homePath())
+ .arg(MImUserDirectory)
+ .arg(QCoreApplication::applicationPid())
+ .arg(fileName);
+ mFile.setFileName(logFilePath);
+
+ mStream.setCodec("utf-8");
+
+ if (!QDir::home().exists(MImUserDirectory)) {
+ QDir::home().mkdir(MImUserDirectory);
+ }
+ mFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
+}
+
+QTextStream & SimpleFileLog::stream()
+{
+ return mStream;
+}
+
+void SimpleFileLog::flush()
+{
+ mStream << "\n";
+ mStream.flush();
+}
--- m-keyboard/common/simplefilelog.h
+++ m-keyboard/common/simplefilelog.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef SIMPLEFILELOG_H
+#define SIMPLEFILELOG_H
+
+#include <QFile>
+#include <QTextStream>
+
+//! \internal
+class SimpleFileLog
+{
+public:
+ //! \brief Constructor. File will be opened under the meego-im home directory,
+ //! and be prefixed with the current PID. Ex: /home/user/.meego-im/4912-file.cvs
+ explicit SimpleFileLog(const QString &fileName);
+
+ //! \brief The stream to log to.
+ QTextStream & stream();
+
+ //! \brief Insert a marker (\n), and flush the textstream to file.
+ void flush();
+
+private:
+ QFile mFile;
+ QTextStream mStream;
+};
+
+#endif // SIMPLEFILELOG_H
--- m-keyboard/layouts/VirtualKeyboardLayout.dtd
+++ m-keyboard/layouts/VirtualKeyboardLayout.dtd
@@ -34,7 +34,9 @@
style (normal | special | deadkey) "normal"
width (small | medium | large | x-large | xx-large | stretched) "medium"
fixed (true | false) "false"
- rtl (true | false) "false">
+ rtl (true | false) "false"
+ id CDATA #IMPLIED
+>
<!ATTLIST binding
action (insert | shift | backspace | space | cycle | layout_menu | sym
--- m-keyboard/layouts/ar.xml
+++ m-keyboard/layouts/ar.xml
@@ -117,8 +117,8 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
<key><binding label="ذ"/></key>
@@ -131,7 +131,7 @@
<key><binding label="."/></key>
<key><binding label="ط"/></key>
- <key style="special" width="x-large" rtl="false">
+ <key style="special" width="x-large" rtl="false" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/layouts/cs.xml
+++ m-keyboard/layouts/cs.xml
@@ -86,7 +86,8 @@
<key>
<binding label="ů"/>
<binding shift="true" label="Ů"/>
- </key>
+ </key>
+
</row>
<row>
@@ -121,7 +122,7 @@
<binding label="m"/>
<binding shift="true" label="M"/>
</key>
- <key>
+ <key>
<binding dead="true" label="´"/>
</key>
<key style="special">
@@ -130,22 +131,22 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
<key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key><binding label="."/></key>
- <key>
+ <key>
<binding dead="true" label="ˇ"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
@@ -153,5 +154,5 @@
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/da.xml
+++ m-keyboard/layouts/da.xml
@@ -133,28 +133,28 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
<key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key><binding label="."/></key>
<key>
<binding label="ø" extended_labels="ö"/>
<binding shift="true" label="Ø" extended_labels="Ö"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/de.xml
+++ m-keyboard/layouts/de.xml
@@ -133,28 +133,28 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
<key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key><binding label="."/></key>
<key>
<binding label="ö"/>
<binding shift="true" label="Ö"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/en_gb_default.xml
+++ m-keyboard/layouts/en_gb_default.xml
@@ -134,18 +134,18 @@
<row>
<key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <binding action="sym" label="?123"/>
</key>
<spacer/>
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
+ <key><binding label="."/></key>
<spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/layouts/es.xml
+++ m-keyboard/layouts/es.xml
@@ -133,32 +133,28 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="CAR"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <key>
- <binding dead="true" label="´"/>
- <binding shift="true" dead="true" label="´"/>
- </key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
<key>
- <binding label=","/>
- </key>
- <key>
- <binding label="."/>
+ <binding dead="true" label="´"/>
+ <binding shift="true" dead="true" label="´"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/fi.xml
+++ m-keyboard/layouts/fi.xml
@@ -132,28 +132,28 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
<key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key><binding label="."/></key>
<key>
<binding label="å"/>
<binding shift="true" label="Å"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/fr.xml
+++ m-keyboard/layouts/fr.xml
@@ -148,24 +148,20 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <spacer/>
-
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-38.xml"/>
</keyboard>
--- m-keyboard/layouts/fr_ca.xml
+++ m-keyboard/layouts/fr_ca.xml
@@ -148,19 +148,15 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <spacer/>
-
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large"><binding action="space" label=""/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
@@ -168,5 +164,5 @@
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-38.xml"/>
</keyboard>
--- m-keyboard/layouts/hu.xml
+++ m-keyboard/layouts/hu.xml
@@ -132,31 +132,25 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <key>
- <binding label=","/>
- </key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key>
- <binding label="."/>
- </key>
- <key>
- <binding dead="true" label="¨"/>
- </key>
+ <key><binding dead="true" label="¨"/></key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/id.xml
+++ m-keyboard/layouts/id.xml
@@ -134,18 +134,18 @@
<row>
<key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <binding action="sym" label="?123"/>
</key>
<spacer/>
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
+ <key><binding label="."/></key>
<spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/layouts/it.xml
+++ m-keyboard/layouts/it.xml
@@ -133,24 +133,21 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <spacer/>
-
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
+ <key><binding label="'"/></key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/ms.xml
+++ m-keyboard/layouts/ms.xml
@@ -134,18 +134,18 @@
<row>
<key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <binding action="sym" label="?123"/>
</key>
<spacer/>
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
+ <key><binding label="."/></key>
<spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/layouts/nl.xml
+++ m-keyboard/layouts/nl.xml
@@ -128,18 +128,18 @@
<row>
<key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <binding action="sym" label="?123"/>
</key>
<spacer/>
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
+ <key><binding label="."/></key>
<spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/layouts/no.xml
+++ m-keyboard/layouts/no.xml
@@ -133,27 +133,23 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <key>
- <binding label=","/>
- </key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
<key>
- <binding label="."/>
- </key>
- <key>
<binding label="ø" extended_labels="ö"/>
<binding shift="true" label="Ø" extended_labels="Ö"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return" label=""/>
</key>
</row>
@@ -161,5 +157,5 @@
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/number.xml
+++ m-keyboard/layouts/number.xml
@@ -92,10 +92,10 @@
<row>
<key>
- <binding label="0"/>
+ <binding label="+/-" action="plus_minus_toggle"/>
</key>
<key>
- <binding label="+/-" action="plus_minus_toggle"/>
+ <binding label="0"/>
</key>
<key>
<binding action="decimal_separator"/>
--- m-keyboard/layouts/number_ar.xml
+++ m-keyboard/layouts/number_ar.xml
@@ -91,10 +91,10 @@
<row>
<key>
- <binding label="٠"/>
+ <binding label="+/-" action="plus_minus_toggle"/>
</key>
<key>
- <binding label="+/-" action="plus_minus_toggle"/>
+ <binding label="٠"/>
</key>
<key>
<binding action="decimal_separator"/>
--- m-keyboard/layouts/phonenumber.xml
+++ m-keyboard/layouts/phonenumber.xml
@@ -92,10 +92,10 @@
<row>
<key>
- <binding label="0"/>
+ <binding label="*+" cycleset="*+p" action="cycle"/>
</key>
<key>
- <binding label="*+" cycleset="*+p" action="cycle"/>
+ <binding label="0"/>
</key>
<key>
<binding label="#"/>
--- m-keyboard/layouts/phonenumber_ar.xml
+++ m-keyboard/layouts/phonenumber_ar.xml
@@ -92,10 +92,10 @@
<row>
<key>
- <binding label="٠"/>
+ <binding label="*+" cycleset="*+p" action="cycle"/>
</key>
<key>
- <binding label="*+" cycleset="*+p" action="cycle"/>
+ <binding label="٠"/>
</key>
<key>
<binding label="#"/>
--- m-keyboard/layouts/phonenumber_ru.xml
+++ m-keyboard/layouts/phonenumber_ru.xml
@@ -92,10 +92,10 @@
<row>
<key>
- <binding label="0"/>
+ <binding label="*+" cycleset="*+p" action="cycle"/>
</key>
<key>
- <binding label="*+" cycleset="*+p" action="cycle"/>
+ <binding label="0"/>
</key>
<key>
<binding label="#"/>
--- m-keyboard/layouts/pl.xml
+++ m-keyboard/layouts/pl.xml
@@ -146,24 +146,20 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <spacer/>
-
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-38.xml"/>
</keyboard>
--- m-keyboard/layouts/pt.xml
+++ m-keyboard/layouts/pt.xml
@@ -148,24 +148,20 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="CAR"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <spacer/>
-
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large"><binding action="space" label=""/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-38.xml"/>
</keyboard>
--- m-keyboard/layouts/pt_br.xml
+++ m-keyboard/layouts/pt_br.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Português-Brazil" version="1.0" catalog="pt_br" language="pt_br">
+<keyboard title="Português- Brasil" version="1.0" catalog="pt_br" language="pt_br">
<import file="pt.xml"/>
</keyboard>
--- m-keyboard/layouts/ro.xml
+++ m-keyboard/layouts/ro.xml
@@ -145,24 +145,20 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <spacer/>
-
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-38.xml"/>
</keyboard>
--- m-keyboard/layouts/ru.xml
+++ m-keyboard/layouts/ru.xml
@@ -21,8 +21,8 @@
<binding shift="true" label="К"/>
</key>
<key>
- <binding label="е" extended_labels="ë"/>
- <binding shift="true" label="Е" extended_labels="Ë"/>
+ <binding label="е" extended_labels="ё"/>
+ <binding shift="true" label="Е" extended_labels="Ё"/>
</key>
<key>
<binding label="н"/>
@@ -145,25 +145,24 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
<key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key>
- <binding label="."/>
- </key>
+ <key><binding label="-"/></key>
<key>
<binding label="ъ"/>
<binding shift="true" label="Ъ"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/layouts/sk.xml
+++ m-keyboard/layouts/sk.xml
@@ -133,33 +133,25 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
- </key>
- <key>
- <binding dead="true" label="´"/>
- </key>
- <key>
- <binding dead="true" label="ˇ"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key>
- <binding label=","/>
- </key>
- <key>
- <binding label="."/>
- </key>
+ <key><binding dead="true" label="´"/></key>
+ <key><binding dead="true" label="ˇ"/></key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-36.xml"/>
</keyboard>
--- m-keyboard/layouts/symbols-36.xml
+++ m-keyboard/layouts/symbols-36.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
+<keyboard version="1.0" catalog="symbols">
+ <layout type="general">
+ <section id="symbols0" type="non-sloppy">
+ <row>
+ <key>
+ <binding label="1"/>
+ </key>
+ <key>
+ <binding label="2"/>
+ </key>
+ <key>
+ <binding label="3"/>
+ </key>
+ <key>
+ <binding label="4"/>
+ </key>
+ <key>
+ <binding label="5"/>
+ </key>
+ <key>
+ <binding label="6"/>
+ </key>
+ <key>
+ <binding label="7"/>
+ </key>
+ <key>
+ <binding label="8"/>
+ </key>
+ <key>
+ <binding label="9"/>
+ </key>
+ <key>
+ <binding label="0"/>
+ </key>
+ </row>
+
+ <row>
+ <key>
+ <binding label="*"/>
+ </key>
+ <key>
+ <binding label="#"/>
+ </key>
+ <key>
+ <binding label="+"/>
+ </key>
+ <key>
+ <binding label="-"/>
+ </key>
+ <key>
+ <binding label="_"/>
+ </key>
+ <key>
+ <binding label="="/>
+ </key>
+ <key>
+ <binding label="("/>
+ </key>
+ <key>
+ <binding label=")"/>
+ </key>
+ <key>
+ <binding label="<"/>
+ </key>
+ <key>
+ <binding label=">"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special">
+ <binding action="switch" label="1/2"/>
+ </key>
+ <key>
+ <binding label="@" quickpick="true"/>
+ </key>
+ <key>
+ <binding label="~"/>
+ </key>
+ <key>
+ <binding label="/"/>
+ </key>
+ <key>
+ <binding label="\"/>
+ </key>
+ <key>
+ <binding label="'" quickpick="true"/>
+ </key>
+ <key>
+ <binding label="""/>
+ </key>
+ <key>
+ <binding label="&"/>
+ </key>
+ <key>
+ <binding label="!"/>
+ </key>
+ <key style="special">
+ <binding action="backspace"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special" width="large">
+ <binding action="sym" label="ABC"/>
+ </key>
+
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
+
+ <key width="xx-large">
+ <binding action="space"/>
+ </key>
+
+ <key><binding label="?"/></key>
+
+ <key style="special" width="x-large" id="actionKey">
+ <binding action="return"/>
+ </key>
+
+ </row>
+ </section>
+
+ <section id="symbols1" type="non-sloppy">
+ <row>
+ <key>
+ <binding label="1"/>
+ </key>
+ <key>
+ <binding label="2"/>
+ </key>
+ <key>
+ <binding label="3"/>
+ </key>
+ <key>
+ <binding label="4"/>
+ </key>
+ <key>
+ <binding label="5"/>
+ </key>
+ <key>
+ <binding label="6"/>
+ </key>
+ <key>
+ <binding label="7"/>
+ </key>
+ <key>
+ <binding label="8"/>
+ </key>
+ <key>
+ <binding label="9"/>
+ </key>
+ <key>
+ <binding label="0"/>
+ </key>
+ </row>
+
+ <row>
+ <key>
+ <binding label="€"/>
+ </key>
+ <key>
+ <binding label="£"/>
+ </key>
+ <key>
+ <binding label="$"/>
+ </key>
+ <key>
+ <binding label="¥"/>
+ </key>
+ <key>
+ <binding label="§"/>
+ </key>
+ <key>
+ <binding label="%"/>
+ </key>
+ <key>
+ <binding label="["/>
+ </key>
+ <key>
+ <binding label="]"/>
+ </key>
+ <key>
+ <binding label="«"/>
+ </key>
+ <key>
+ <binding label="»"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special">
+ <binding action="switch" label="2/2"/>
+ </key>
+ <key>
+ <binding label="`"/>
+ </key>
+ <key>
+ <binding label="^"/>
+ </key>
+ <key>
+ <binding label="|"/>
+ </key>
+ <key>
+ <binding label="°"/>
+ </key>
+ <key>
+ <binding label="“"/>
+ </key>
+ <key>
+ <binding label="”"/>
+ </key>
+ <key>
+ <binding label="„"/>
+ </key>
+ <key>
+ <binding label="¡"/>
+ </key>
+ <key style="special">
+ <binding action="backspace"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special" width="large">
+ <binding action="sym" label="ABC"/>
+ </key>
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
+ <key width="xx-large">
+ <binding action="space"/>
+ </key>
+
+ <key><binding label="¿"/></key>
+
+ <key style="special" width="x-large" id="actionKey">
+ <binding action="return"/>
+ </key>
+ </row>
+ </section>
+ </layout>
+</keyboard>
--- m-keyboard/layouts/symbols-38.xml
+++ m-keyboard/layouts/symbols-38.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
+<keyboard version="1.0" catalog="symbols">
+ <layout type="general">
+ <section id="symbols0" type="non-sloppy">
+ <row>
+ <key>
+ <binding label="1"/>
+ </key>
+ <key>
+ <binding label="2"/>
+ </key>
+ <key>
+ <binding label="3"/>
+ </key>
+ <key>
+ <binding label="4"/>
+ </key>
+ <key>
+ <binding label="5"/>
+ </key>
+ <key>
+ <binding label="6"/>
+ </key>
+ <key>
+ <binding label="7"/>
+ </key>
+ <key>
+ <binding label="8"/>
+ </key>
+ <key>
+ <binding label="9"/>
+ </key>
+ <key>
+ <binding label="0"/>
+ </key>
+ <key>
+ <binding label="%"/>
+ </key>
+ </row>
+
+ <row>
+ <key>
+ <binding label="*"/>
+ </key>
+ <key>
+ <binding label="#"/>
+ </key>
+ <key>
+ <binding label="+"/>
+ </key>
+ <key>
+ <binding label="-"/>
+ </key>
+ <key>
+ <binding label="_"/>
+ </key>
+ <key>
+ <binding label="="/>
+ </key>
+ <key>
+ <binding label="&"/>
+ </key>
+ <key>
+ <binding label="("/>
+ </key>
+ <key>
+ <binding label=")"/>
+ </key>
+ <key>
+ <binding label="<"/>
+ </key>
+ <key>
+ <binding label=">"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special">
+ <binding action="switch" label="1/2"/>
+ </key>
+ <key>
+ <binding label="@" quickpick="true"/>
+ </key>
+ <key>
+ <binding label="~"/>
+ </key>
+ <key>
+ <binding label="/"/>
+ </key>
+ <key>
+ <binding label="\"/>
+ </key>
+ <key>
+ <binding label="'" quickpick="true"/>
+ </key>
+ <key>
+ <binding label="""/>
+ </key>
+ <key>
+ <binding label="°"/>
+ </key>
+ <key>
+ <binding label="?"/>
+ </key>
+ <key>
+ <binding label="!"/>
+ </key>
+ <key style="special">
+ <binding action="backspace"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special" width="large">
+ <binding action="sym" label="ABC"/>
+ </key>
+
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
+
+ <key width="xx-large">
+ <binding action="space"/>
+ </key>
+
+ <key style="special" width="x-large" id="actionKey">
+ <binding action="return"/>
+ </key>
+
+ </row>
+ </section>
+
+ <section id="symbols1" type="non-sloppy">
+ <row>
+ <key>
+ <binding label="1"/>
+ </key>
+ <key>
+ <binding label="2"/>
+ </key>
+ <key>
+ <binding label="3"/>
+ </key>
+ <key>
+ <binding label="4"/>
+ </key>
+ <key>
+ <binding label="5"/>
+ </key>
+ <key>
+ <binding label="6"/>
+ </key>
+ <key>
+ <binding label="7"/>
+ </key>
+ <key>
+ <binding label="8"/>
+ </key>
+ <key>
+ <binding label="9"/>
+ </key>
+ <key>
+ <binding label="0"/>
+ </key>
+ <key>
+ <binding label="‰"/>
+ </key>
+ </row>
+
+ <row>
+ <key>
+ <binding label="€"/>
+ </key>
+ <key>
+ <binding label="£"/>
+ </key>
+ <key>
+ <binding label="$"/>
+ </key>
+ <key>
+ <binding label="¥"/>
+ </key>
+ <key>
+ <binding label="§"/>
+ </key>
+ <key>
+ <binding label="{"/>
+ </key>
+ <key>
+ <binding label="}"/>
+ </key>
+ <key>
+ <binding label="["/>
+ </key>
+ <key>
+ <binding label="]"/>
+ </key>
+ <key>
+ <binding label="«"/>
+ </key>
+ <key>
+ <binding label="»"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special">
+ <binding action="switch" label="2/2"/>
+ </key>
+ <key>
+ <binding label="`"/>
+ </key>
+ <key>
+ <binding label="^"/>
+ </key>
+ <key>
+ <binding label="|"/>
+ </key>
+ <key>
+ <binding label="“"/>
+ </key>
+ <key>
+ <binding label="”"/>
+ </key>
+ <key>
+ <binding label="„"/>
+ </key>
+ <key>
+ <binding label="©"/>
+ </key>
+ <key>
+ <binding label="¿"/>
+ </key>
+ <key>
+ <binding label="¡"/>
+ </key>
+ <key style="special">
+ <binding action="backspace"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special" width="large">
+ <binding action="sym" label="ABC"/>
+ </key>
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
+ <key width="xx-large">
+ <binding action="space"/>
+ </key>
+
+ <key style="special" width="x-large" id="actionKey">
+ <binding action="return"/>
+ </key>
+ </row>
+ </section>
+ </layout>
+</keyboard>
--- m-keyboard/layouts/symbols.xml
+++ m-keyboard/layouts/symbols.xml
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard version="1.0" catalog="symbols">
- <layout type="general">
- <section id="symbols0" type="non-sloppy">
- <row>
- <key>
- <binding label="1" quickpick="true"/>
- </key>
- <key>
- <binding label="2"/>
- </key>
- <key>
- <binding label="3"/>
- </key>
- <key>
- <binding label="4"/>
- </key>
- <key>
- <binding label="5"/>
- </key>
- <key>
- <binding label="6"/>
- </key>
- <key>
- <binding label="7"/>
- </key>
- <key>
- <binding label="8"/>
- </key>
- <key>
- <binding label="9"/>
- </key>
- <key>
- <binding label="0"/>
- </key>
- </row>
-
- <row>
- <key>
- <binding label="*"/>
- </key>
- <key>
- <binding label="#"/>
- </key>
- <key>
- <binding label="+"/>
- </key>
- <key>
- <binding label="-"/>
- </key>
- <key>
- <binding label="_"/>
- </key>
- <key>
- <binding label="="/>
- </key>
- <key>
- <binding label="("/>
- </key>
- <key>
- <binding label=")"/>
- </key>
- <key>
- <binding label=";"/>
- </key>
- <key>
- <binding label=":"/>
- </key>
- </row>
-
- <row>
- <key style="special">
- <binding action="switch" label="1/2"/>
- </key>
- <key>
- <binding label="@" quickpick="true"/>
- </key>
- <key>
- <binding label="~"/>
- </key>
- <key>
- <binding label="/"/>
- </key>
- <key>
- <binding label="\"/>
- </key>
- <key>
- <binding label="'" quickpick="true"/>
- </key>
- <key>
- <binding label="""/>
- </key>
- <key>
- <binding label="?"/>
- </key>
- <key>
- <binding label="!"/>
- </key>
- <key style="special">
- <binding action="backspace"/>
- </key>
- </row>
-
- <row>
- <key style="special" width="x-large">
- <binding action="sym" label="ABC"/>
- </key>
-
- <spacer/>
-
- <key width="large"><binding label=","/></key>
- <key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
-
- <key style="special" width="x-large">
- <binding action="return"/>
- </key>
-
- </row>
- </section>
-
- <section id="symbols1" type="non-sloppy">
- <row>
- <key>
- <binding label="1"/>
- </key>
- <key>
- <binding label="2"/>
- </key>
- <key>
- <binding label="3"/>
- </key>
- <key>
- <binding label="4"/>
- </key>
- <key>
- <binding label="5"/>
- </key>
- <key>
- <binding label="6"/>
- </key>
- <key>
- <binding label="7"/>
- </key>
- <key>
- <binding label="8"/>
- </key>
- <key>
- <binding label="9"/>
- </key>
- <key>
- <binding label="0"/>
- </key>
- </row>
-
- <row>
- <key>
- <binding label="€"/>
- </key>
- <key>
- <binding label="£"/>
- </key>
- <key>
- <binding label="$"/>
- </key>
- <key>
- <binding label="¥"/>
- </key>
- <key>
- <binding label="§"/>
- </key>
- <key>
- <binding label="%"/>
- </key>
- <key>
- <binding label="["/>
- </key>
- <key>
- <binding label="]"/>
- </key>
- <key>
- <binding label="<"/>
- </key>
- <key>
- <binding label=">"/>
- </key>
- </row>
-
- <row>
- <key style="special">
- <binding action="switch" label="2/2"/>
- </key>
- <key>
- <binding label="`"/>
- </key>
- <key>
- <binding label="^"/>
- </key>
- <key>
- <binding label="|"/>
- </key>
- <key>
- <binding label="&"/>
- </key>
- <key>
- <binding label="”"/>
- </key>
- <key>
- <binding label="„"/>
- </key>
- <key>
- <binding label="¿"/>
- </key>
- <key>
- <binding label="¡"/>
- </key>
- <key style="special">
- <binding action="backspace"/>
- </key>
- </row>
-
- <row>
- <key style="special" width="x-large">
- <binding action="sym" label="ABC"/>
- </key>
-
- <spacer/>
-
- <key width="large"><binding label="«"/></key>
- <key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="»"/></key>
-
- <spacer/>
-
- <key style="special" width="x-large">
- <binding action="return"/>
- </key>
- </row>
- </section>
- </layout>
-</keyboard>
--- m-keyboard/layouts/symbols_ar.xml
+++ m-keyboard/layouts/symbols_ar.xml
@@ -1,266 +1,266 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
<keyboard version="1.0" catalog="symbols">
- <layout type="general">
- <section id="symbols0" type="non-sloppy">
- <row>
- <key>
- <binding label="1"/>
- </key>
- <key>
- <binding label="2"/>
- </key>
- <key>
- <binding label="3"/>
- </key>
- <key>
- <binding label="4"/>
- </key>
- <key>
- <binding label="5"/>
- </key>
- <key>
- <binding label="6"/>
- </key>
- <key>
- <binding label="7"/>
- </key>
- <key>
- <binding label="8"/>
- </key>
- <key>
- <binding label="9"/>
- </key>
- <key>
- <binding label="0"/>
- </key>
- </row>
-
- <row>
- <key>
- <binding label="*"/>
- </key>
- <key>
- <binding label="#"/>
- </key>
- <key>
- <binding label="+"/>
- </key>
- <key>
- <binding label="-"/>
- </key>
- <key>
- <binding label="_"/>
- </key>
- <key>
- <binding label="%"/>
- </key>
- <key>
- <binding label="="/>
- </key>
- <key>
- <binding label="&"/>
- </key>
- <key>
- <binding label="("/>
- </key>
- <key>
- <binding label=")"/>
- </key>
- </row>
-
- <row>
- <key style="special">
- <binding action="switch" label="1/2"/>
- </key>
-
- <key>
- <binding label="@" quickpick="true"/>
- </key>
- <key>
- <binding label="~"/>
- </key>
- <key>
- <binding label="/"/>
- </key>
- <key>
- <binding label="\"/>
- </key>
- <key>
- <binding label="'" quickpick="true"/>
- </key>
- <key>
- <binding label="""/>
- </key>
- <key>
- <binding label="؟"/>
- </key>
- <key>
- <binding label="!"/>
- </key>
- <key style="special" rtl="true">
- <binding action="backspace"/>
- </key>
- </row>
-
- <row>
- <key style="special" width="xx-large">
- <binding action="sym" label="ا‌ب‌ت"/>
- </key>
-
- <key>
- <binding label="؛"/>
- </key>
- <key>
- <binding label=","/>
- </key>
-
- <key width="xx-large">
- <binding action="space"/>
- </key>
-
- <key>
- <binding label="."/>
- </key>
- <key>
- <binding label=":"/>
- </key>
-
- <key style="special" width="xx-large" rtl="false">
- <binding action="return"/>
- </key>
- </row>
- </section>
-
- <section id="symbols1" type="non-sloppy">
- <row>
- <key>
- <binding label="١"/>
- </key>
- <key>
- <binding label="٢"/>
- </key>
- <key>
- <binding label="٣"/>
- </key>
- <key>
- <binding label="٤"/>
- </key>
- <key>
- <binding label="٥"/>
- </key>
- <key>
- <binding label="٦"/>
- </key>
- <key>
- <binding label="٧"/>
- </key>
- <key>
- <binding label="٨"/>
- </key>
- <key>
- <binding label="٩"/>
- </key>
- <key>
- <binding label="٠"/>
- </key>
- </row>
-
- <row>
- <key>
- <binding label="€"/>
- </key>
- <key>
- <binding label="£"/>
- </key>
- <key>
- <binding label="$"/>
- </key>
- <key>
- <binding label="¥"/>
- </key>
- <key>
- <binding label="§"/>
- </key>
- <key>
- <binding label="٪"/>
- </key>
- <key>
- <binding label="<"/>
- </key>
- <key>
- <binding label=">"/>
- </key>
- <key>
- <binding label="["/>
- </key>
- <key>
- <binding label="]"/>
- </key>
- </row>
-
- <row>
- <key style="special">
- <binding action="switch" label="2/2"/>
- </key>
-
- <key>
- <binding label="`"/>
- </key>
- <key>
- <binding label="^"/>
- </key>
- <key>
- <binding label="|"/>
- </key>
- <key>
- <binding label="“"/>
- </key>
- <key>
- <binding label="”"/>
- </key>
- <key>
- <binding label="„"/>
- </key>
- <key>
- <binding label="٫"/>
- </key>
- <key>
- <binding label="٬"/>
- </key>
- <key style="special" rtl="true">
- <binding action="backspace"/>
- </key>
- </row>
-
- <row>
- <key style="special" width="xx-large">
- <binding action="sym" label="ا‌ب‌ت"/>
- </key>
-
- <key>
- <binding label="«"/>
- </key>
- <key>
- <binding label="،"/>
- </key>
-
- <key width="xx-large">
- <binding action="space"/>
- </key>
-
- <key>
- <binding label="."/>
- </key>
- <key>
- <binding label="»"/>
- </key>
-
- <key style="special" width="xx-large" rtl="false">
- <binding action="return"/>
- </key>
- </row>
- </section>
- </layout>
+ <layout type="general">
+ <section id="symbols0" type="non-sloppy">
+ <row>
+ <key>
+ <binding label="١"/>
+ </key>
+ <key>
+ <binding label="٢"/>
+ </key>
+ <key>
+ <binding label="٣"/>
+ </key>
+ <key>
+ <binding label="٤"/>
+ </key>
+ <key>
+ <binding label="٥"/>
+ </key>
+ <key>
+ <binding label="٦"/>
+ </key>
+ <key>
+ <binding label="٧"/>
+ </key>
+ <key>
+ <binding label="٨"/>
+ </key>
+ <key>
+ <binding label="٩"/>
+ </key>
+ <key>
+ <binding label="٠"/>
+ </key>
+ <key>
+ <binding label="%"/>
+ </key>
+ </row>
+
+ <row>
+ <key>
+ <binding label="*"/>
+ </key>
+ <key>
+ <binding label="#"/>
+ </key>
+ <key>
+ <binding label="+"/>
+ </key>
+ <key>
+ <binding label="-"/>
+ </key>
+ <key>
+ <binding label="_"/>
+ </key>
+ <key>
+ <binding label="="/>
+ </key>
+ <key>
+ <binding label="&"/>
+ </key>
+ <key>
+ <binding label="("/>
+ </key>
+ <key>
+ <binding label=")"/>
+ </key>
+ <key>
+ <binding label="<"/>
+ </key>
+ <key>
+ <binding label=">"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special">
+ <binding action="switch" label="1/2"/>
+ </key>
+ <key>
+ <binding label="@" quickpick="true"/>
+ </key>
+ <key>
+ <binding label="~"/>
+ </key>
+ <key>
+ <binding label="/"/>
+ </key>
+ <key>
+ <binding label="\"/>
+ </key>
+ <key>
+ <binding label="'" quickpick="true"/>
+ </key>
+ <key>
+ <binding label="""/>
+ </key>
+ <key>
+ <binding label="?"/>
+ </key>
+ <key>
+ <binding label="!"/>
+ </key>
+ <key>
+ <binding label="°"/>
+ </key>
+ <key style="special" rtl="true">
+ <binding action="backspace"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special" width="large">
+ <binding action="sym" label="ا‌ب‌ت"/>
+ </key>
+
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
+
+ <key width="xx-large">
+ <binding action="space"/>
+ </key>
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
+ <key style="special" width="x-large" id="actionKey">
+ <binding action="return"/>
+ </key>
+
+ </row>
+ </section>
+
+ <section id="symbols1" type="non-sloppy">
+ <row>
+ <key>
+ <binding label="1"/>
+ </key>
+ <key>
+ <binding label="2"/>
+ </key>
+ <key>
+ <binding label="3"/>
+ </key>
+ <key>
+ <binding label="4"/>
+ </key>
+ <key>
+ <binding label="5"/>
+ </key>
+ <key>
+ <binding label="6"/>
+ </key>
+ <key>
+ <binding label="7"/>
+ </key>
+ <key>
+ <binding label="8"/>
+ </key>
+ <key>
+ <binding label="9"/>
+ </key>
+ <key>
+ <binding label="0"/>
+ </key>
+ <key>
+ <binding label="‰"/>
+ </key>
+ </row>
+
+ <row>
+ <key>
+ <binding label="€"/>
+ </key>
+ <key>
+ <binding label="£"/>
+ </key>
+ <key>
+ <binding label="$"/>
+ </key>
+ <key>
+ <binding label="¥"/>
+ </key>
+ <key>
+ <binding label="§"/>
+ </key>
+ <key>
+ <binding label="{"/>
+ </key>
+ <key>
+ <binding label="}"/>
+ </key>
+ <key>
+ <binding label="["/>
+ </key>
+ <key>
+ <binding label="]"/>
+ </key>
+ <key>
+ <binding label="«"/>
+ </key>
+ <key>
+ <binding label="»"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special">
+ <binding action="switch" label="2/2"/>
+ </key>
+ <key>
+ <binding label="`"/>
+ </key>
+ <key>
+ <binding label="^"/>
+ </key>
+ <key>
+ <binding label="|"/>
+ </key>
+ <key>
+ <binding label="“"/>
+ </key>
+ <key>
+ <binding label="”"/>
+ </key>
+ <key>
+ <binding label="„"/>
+ </key>
+ <key>
+ <binding label="№"/>
+ </key>
+ <key>
+ <binding label="©"/>
+ </key>
+ <key>
+ <binding label="®"/>
+ </key>
+ <key style="special" rtl="true">
+ <binding action="backspace"/>
+ </key>
+ </row>
+
+ <row>
+ <key style="special" width="large">
+ <binding action="sym" label="ا‌ب‌ت"/>
+ </key>
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
+ <key width="xx-large">
+ <binding action="space"/>
+ </key>
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
+ <key style="special" width="x-large" id="actionKey">
+ <binding action="return"/>
+ </key>
+ </row>
+ </section>
+ </layout>
</keyboard>
-
--- m-keyboard/layouts/symbols_en.xml
+++ m-keyboard/layouts/symbols_en.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
<keyboard version="1.0" catalog="symbols">
- <layout type="general" orientation="landscape">
+ <layout type="general">
<section id="symbols0" type="non-sloppy">
<row>
<key>
@@ -55,10 +55,10 @@
<binding label="="/>
</key>
<key>
- <binding label="("/>
+ <binding label="("/>
</key>
<key>
- <binding label=")"/>
+ <binding label=")"/>
</key>
<key>
<binding label="?"/>
@@ -94,10 +94,10 @@
<binding label="'" quickpick="true"/>
</key>
<key>
- <binding label=";"/>
+ <binding label=";"/>
</key>
<key>
- <binding label=":"/>
+ <binding label=":"/>
</key>
<spacer/>
@@ -114,13 +114,13 @@
<spacer/>
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
+ <key><binding label="."/></key>
<spacer/>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
@@ -238,261 +238,13 @@
<spacer/>
- <key width="large"><binding label=","/></key>
+ <key><binding label=","/></key>
<key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
-
- <key style="special" width="x-large">
- <binding action="return"/>
- </key>
- </row>
- </section>
- </layout>
-
- <layout type="general" orientation="portrait">
- <section id="symbols0" type="non-sloppy">
- <row>
- <key>
- <binding label="1"/>
- </key>
- <key>
- <binding label="2"/>
- </key>
- <key>
- <binding label="3"/>
- </key>
- <key>
- <binding label="4"/>
- </key>
- <key>
- <binding label="5"/>
- </key>
- <key>
- <binding label="6"/>
- </key>
- <key>
- <binding label="7"/>
- </key>
- <key>
- <binding label="8"/>
- </key>
- <key>
- <binding label="9"/>
- </key>
- <key>
- <binding label="0"/>
- </key>
- </row>
+ <key><binding label="."/></key>
- <row>
<spacer/>
- <key>
- <binding label="*"/>
- </key>
- <key>
- <binding label="#"/>
- </key>
- <key>
- <binding label="+"/>
- </key>
- <key>
- <binding label="-"/>
- </key>
- <key>
- <binding label="="/>
- </key>
- <key>
- <binding label="("/>
- </key>
- <key>
- <binding label=")"/>
- </key>
- <key>
- <binding label="?"/>
- </key>
- <key>
- <binding label="!"/>
- </key>
-
- <spacer/>
- </row>
-
- <row>
- <key style="special" width="large">
- <binding action="switch" label="1/2"/>
- </key>
-
- <spacer/>
-
- <key>
- <binding label="@"/>
- </key>
- <key>
- <binding label="~"/>
- </key>
- <key>
- <binding label="/"/>
- </key>
- <key>
- <binding label="\"/>
- </key>
- <key>
- <binding label="'"/>
- </key>
- <key>
- <binding label=";"/>
- </key>
- <key>
- <binding label=":"/>
- </key>
-
- <spacer/>
-
- <key style="special" width="large">
- <binding action="backspace"/>
- </key>
- </row>
-
- <row>
- <key style="special" width="x-large">
- <binding action="sym" label="ABC"/>
- </key>
-
- <spacer/>
-
- <key width="large"><binding label=","/></key>
- <key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
-
- <key style="special" width="x-large">
- <binding action="return"/>
- </key>
- </row>
- </section>
-
- <section id="symbols1" type="non-sloppy">
- <row>
- <key>
- <binding label="€"/>
- </key>
- <key>
- <binding label="£"/>
- </key>
- <key>
- <binding label="$"/>
- </key>
- <key>
- <binding label="¥"/>
- </key>
- <key>
- <binding label="%"/>
- </key>
- <key>
- <binding label="‰"/>
- </key>
- <key>
- <binding label="<"/>
- </key>
- <key>
- <binding label=">"/>
- </key>
- <key>
- <binding label="["/>
- </key>
- <key>
- <binding label="]"/>
- </key>
- </row>
-
- <row>
- <spacer/>
-
- <key>
- <binding label="`"/>
- </key>
- <key>
- <binding label="^"/>
- </key>
- <key>
- <binding label="|"/>
- </key>
- <key>
- <binding label="_"/>
- </key>
- <key>
- <binding label="§"/>
- </key>
- <key>
- <binding label="{"/>
- </key>
- <key>
- <binding label="}"/>
- </key>
- <key>
- <binding label="¿"/>
- </key>
- <key>
- <binding label="¡"/>
- </key>
-
- <spacer/>
- </row>
-
- <row>
- <key style="special" width="large">
- <binding action="switch" label="2/2"/>
- </key>
-
- <spacer/>
-
- <key>
- <binding label="«"/>
- </key>
- <key>
- <binding label="»"/>
- </key>
- <key>
- <binding label="""/>
- </key>
- <key>
- <binding label="“"/>
- </key>
- <key>
- <binding label="”"/>
- </key>
- <key>
- <binding label="„"/>
- </key>
- <key>
- <binding label="&"/>
- </key>
-
- <spacer/>
-
- <key style="special" width="large">
- <binding action="backspace"/>
- </key>
- </row>
-
- <row>
- <key style="special" width="x-large">
- <binding action="sym" label="ABC"/>
- </key>
-
- <spacer/>
-
- <key width="large"><binding label=","/></key>
- <key width="xx-large"><binding action="space"/></key>
- <key width="large"><binding label="."/></key>
-
- <spacer/>
-
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/layouts/symbols_ru_uk.xml
+++ m-keyboard/layouts/symbols_ru_uk.xml
@@ -34,6 +34,9 @@
<key>
<binding label="0"/>
</key>
+ <key>
+ <binding label="%"/>
+ </key>
</row>
<row>
@@ -53,10 +56,7 @@
<binding label="_"/>
</key>
<key>
- <binding label="%"/>
- </key>
- <key>
- <binding label="="/>
+ <binding label="="/>
</key>
<key>
<binding label="&"/>
@@ -67,6 +67,12 @@
<key>
<binding label=")"/>
</key>
+ <key>
+ <binding label="<"/>
+ </key>
+ <key>
+ <binding label=">"/>
+ </key>
</row>
<row>
@@ -92,10 +98,13 @@
<binding label="""/>
</key>
<key>
- <binding label="?"/>
+ <binding label="?"/>
+ </key>
+ <key>
+ <binding label="!"/>
</key>
<key>
- <binding label="!"/>
+ <binding label="°"/>
</key>
<key style="special">
<binding action="backspace"/>
@@ -103,29 +112,21 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="АБВ"/>
- </key>
-
- <key>
- <binding label=";"/>
+ <key style="special" width="large">
+ <binding action="sym" label="АБВ"/>
</key>
- <key>
- <binding label=","/>
- </key>
-
+
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
+
<key width="xx-large">
<binding action="space"/>
</key>
-
- <key>
- <binding label="."/>
- </key>
- <key>
- <binding label=":"/>
- </key>
-
- <key style="special" width="x-large">
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
@@ -164,6 +165,9 @@
<key>
<binding label="0"/>
</key>
+ <key>
+ <binding label="‰"/>
+ </key>
</row>
<row>
@@ -183,13 +187,10 @@
<binding label="§"/>
</key>
<key>
- <binding label="‰"/>
- </key>
- <key>
- <binding label="<"/>
+ <binding label="{"/>
</key>
<key>
- <binding label=">"/>
+ <binding label="}"/>
</key>
<key>
<binding label="["/>
@@ -197,6 +198,12 @@
<key>
<binding label="]"/>
</key>
+ <key>
+ <binding label="«"/>
+ </key>
+ <key>
+ <binding label="»"/>
+ </key>
</row>
<row>
@@ -227,38 +234,33 @@
<key>
<binding label="©"/>
</key>
+ <key>
+ <binding label="®"/>
+ </key>
<key style="special">
<binding action="backspace"/>
</key>
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="АБВ"/>
+ <key style="special" width="large">
+ <binding action="sym" label="АБВ"/>
</key>
- <key>
- <binding label="«"/>
- </key>
- <key>
- <binding label=","/>
- </key>
-
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
<key width="xx-large">
<binding action="space"/>
</key>
-
- <key>
- <binding label="."/>
- </key>
- <key>
- <binding label="»"/>
- </key>
-
- <key style="special" width="x-large">
+
+ <key><binding label=";"/></key>
+ <key><binding label=":"/></key>
+
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
</keyboard>
-
--- m-keyboard/layouts/tr.xml
+++ m-keyboard/layouts/tr.xml
@@ -145,28 +145,28 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
<key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
</key>
- <key><binding label="."/></key>
<key>
<binding label="ğ"/>
<binding shift="true" label="Ğ"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
</section>
</layout>
- <import file="symbols.xml"/>
+ <import file="symbols-38.xml"/>
</keyboard>
--- m-keyboard/layouts/uk.xml
+++ m-keyboard/layouts/uk.xml
@@ -145,16 +145,12 @@
</row>
<row>
- <key style="special" width="x-large">
- <binding action="sym" label="SYM"/>
+ <key style="special" width="large">
+ <binding action="sym" label="?123"/>
</key>
- <key>
- <binding label=","/>
- </key>
- <key>
- <binding label="."/>
- </key>
+ <key><binding label=","/></key>
+ <key><binding label="."/></key>
<key width="xx-large">
<binding action="space" label=""/>
@@ -169,7 +165,7 @@
<binding shift="true" label="Ї"/>
</key>
- <key style="special" width="x-large">
+ <key style="special" width="x-large" id="actionKey">
<binding action="return"/>
</key>
</row>
--- m-keyboard/mkeyboardhost.cpp
+++ m-keyboard/mkeyboardhost.cpp
@@ -27,7 +27,9 @@
#include "symbolview.h"
#include "mimtoolbar.h"
#include "sharedhandlearea.h"
+#include "reactionmappainter.h"
#include "regiontracker.h"
+#include "simplefilelog.h"
#include <mimenginefactory.h>
#include <mabstractinputmethodhost.h>
@@ -37,11 +39,9 @@
#include <QDebug>
#include <QKeyEvent>
-#include <QFile>
#include <QRegExp>
#include <QEasingCurve>
-#include <mreactionmap.h>
#include <MScene>
#include <MSceneManager>
#include <MSceneWindow>
@@ -56,7 +56,9 @@
const QString DefaultInputLanguage("en_GB");
// TODO: check that these paths still hold
const QString CorrectionSetting("/meegotouch/inputmethods/virtualkeyboard/correctionenabled");
+ const QString CorrectionSettingWithSpace("/meegotouch/inputmethods/virtualkeyboard/correctwithspace");
const bool DefaultCorrectionSettingOption = true;
+ const bool DefaultCorrectionSettingAcceptedWithSpaceOption = true;
const QString InputMethodCorrectionEngine("/meegotouch/inputmethods/correctionengine");
const QRegExp AutoCapsTrigger("[.?!¡¿] +$");
const QString AutoPunctuationTriggers(".,?!");
@@ -72,9 +74,10 @@
const char * const NotificationObjectName = "ModifierLockNotification";
const int KeysRequiredForFastTypingMode = 3;
const int FastTypingTimeout = 700; //! Milliseconds to idle before leaving fast typing mode.
+ MKeyboardHost *currentInstance = 0;
+ const char *const MImTouchPointsLogfile = "touchpoints.csv";
}
-
MKeyboardHost::SlideUpAnimation::SlideUpAnimation(QObject *parent)
: QPropertyAnimation(parent)
{
@@ -187,8 +190,11 @@
symbolView(0),
imCorrectionEngine(0),
inputMethodCorrectionSettings(new MGConfItem(CorrectionSetting)),
+ inputMethodCorrectionSettingsSpace(new MGConfItem(CorrectionSettingWithSpace)),
inputMethodCorrectionEngine(new MGConfItem(InputMethodCorrectionEngine)),
+ rotationInProgress(false),
correctionEnabled(false),
+ correctionAcceptedWithSpaceEnabled(false),
autoCapsEnabled(true),
autoCapsTriggered(false),
cursorPos(-1),
@@ -196,7 +202,6 @@
hasSelection(false),
inputMethodMode(M::InputMethodModeNormal),
backspaceTimer(),
- rotationTimer(),
shiftHeldDown(false),
activeState(MInputMethod::OnScreen),
modifierLockOnBanner(0),
@@ -212,16 +217,17 @@
fastTypingKeyCount(0),
fastTypingEnabled(false),
vkbFadeInAnimation(*new QPropertyAnimation(this)),
- toolbarFadeInAnimation(*new QPropertyAnimation(this))
+ toolbarFadeInAnimation(*new QPropertyAnimation(this)),
+ touchPointLogHandle(0)
{
RegionTracker::createInstance();
connect(&RegionTracker::instance(), SIGNAL(regionChanged(const QRegion &)),
imHost, SLOT(setScreenRegion(const QRegion &)));
connect(&RegionTracker::instance(), SIGNAL(inputMethodAreaChanged(const QRegion &)),
imHost, SLOT(setInputMethodArea(const QRegion &)));
- connect(&RegionTracker::instance(), SIGNAL(reactionMapUpdateNeeded()),
- this, SLOT(updateReactionMaps()));
- RegionTracker::instance().enableSignals(false);
+
+ // Create the reaction map painter
+ ReactionMapPainter::createInstance();
displayHeight = MPlainWindow::instance()->visibleSceneSize(M::Landscape).height();
displayWidth = MPlainWindow::instance()->visibleSceneSize(M::Landscape).width();
@@ -229,8 +235,10 @@
sceneWindow = new MSceneWindow;
sceneWindow->setManagedManually(true); // we want the scene window to remain in origin
- // Enforcing full viewport updates helps to paint correctly in software mode.
- MPlainWindow::instance()->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ MPlainWindow::instance()->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
+
+ // our paint methods are accurate enough, so we can disable painter saving
+ MPlainWindow::instance()->setOptimizationFlags(QGraphicsView::DontSavePainterState);
// Because we set vkbWidget as a child of sceneWindow the vkb
// will always be in correct orientation. However the animation will be
@@ -276,6 +284,8 @@
hardwareKeyboard = new MHardwareKeyboard(*imHost, this);
connect(hardwareKeyboard, SIGNAL(symbolKeyClicked()),
this, SLOT(handleSymbolKeyClick()));
+ // Trigger a reaction map when the hardware keyboard is opened
+ connect(hardwareKeyboard, SIGNAL(enabled()), &ReactionMapPainter::instance(), SLOT(repaint()));
bool ok = connect(vkbWidget, SIGNAL(copyPasteClicked(CopyPasteState)),
this, SLOT(sendCopyPaste(CopyPasteState)));
@@ -305,10 +315,8 @@
// Set z value below default level (0.0) so popup will be on top of shared handle area.
sharedHandleArea->setZValue(-1.0);
-
sharedHandleArea->watchOnWidget(vkbWidget);
-
createCorrectionCandidateWidget();
// Don't listen to device orientation. Applications can be in different orientation
@@ -352,6 +360,8 @@
initializeInputEngine();
connect(inputMethodCorrectionSettings, SIGNAL(valueChanged()),
this, SLOT(synchronizeCorrectionSetting()));
+ connect(inputMethodCorrectionSettingsSpace, SIGNAL(valueChanged()),
+ this, SLOT(synchronizeCorrectionSettingSpace()));
} else {
qDebug() << __PRETTY_FUNCTION__ << "Failed to load correction engine"
<< inputMethodCorrectionEngine->value().toString();
@@ -361,9 +371,6 @@
backspaceTimer.setSingleShot(true);
connect(&backspaceTimer, SIGNAL(timeout()), this, SLOT(autoBackspace()));
- rotationTimer.setSingleShot(true);
- connect(&rotationTimer, SIGNAL(timeout()), this, SLOT(finalizeOrientationChange()));
-
fastTypingTimeout.setSingleShot(true);
fastTypingTimeout.setInterval(FastTypingTimeout);
connect(&fastTypingTimeout, SIGNAL(timeout()),
@@ -393,8 +400,12 @@
connect(&slideUpAnimation, SIGNAL(finished()), this, SLOT(handleAnimationFinished()));
connect(&toolbarAndVkbFadeInAnimation, SIGNAL(finished()), this, SLOT(handleAnimationFinished()));
+ // Trigger a reaction map update
+ connect(&slideUpAnimation, SIGNAL(finished()), &ReactionMapPainter::instance(), SLOT(repaint()));
+ connect(&toolbarAndVkbFadeInAnimation, SIGNAL(finished()), &ReactionMapPainter::instance(), SLOT(repaint()));
- RegionTracker::instance().enableSignals(true, false);
+ Q_ASSERT(currentInstance == 0); // Several instances of this class is invalid.
+ currentInstance = this;
}
MKeyboardHost::~MKeyboardHost()
@@ -415,17 +426,27 @@
sceneWindow = 0;
delete vkbStyleContainer;
vkbStyleContainer = 0;
+ delete inputMethodCorrectionSettingsSpace;
+ inputMethodCorrectionSettingsSpace = 0;
delete inputMethodCorrectionSettings;
inputMethodCorrectionSettings = 0;
+ delete touchPointLogHandle;
+ touchPointLogHandle = 0;
if (imCorrectionEngine) {
MImEngineFactory::instance()->deleteEngine(imCorrectionEngine);
imCorrectionEngine = 0;
}
backspaceMode = NormalBackspaceMode;
backspaceTimer.stop();
- rotationTimer.stop();
LayoutsManager::destroyInstance();
+ ReactionMapPainter::destroyInstance();
RegionTracker::destroyInstance();
+ currentInstance = 0;
+}
+
+MKeyboardHost* MKeyboardHost::instance()
+{
+ return currentInstance;
}
void MKeyboardHost::createCorrectionCandidateWidget()
@@ -437,6 +458,13 @@
this, SLOT(commitString(const QString &)));
}
+QTextStream &MKeyboardHost::touchPointLog()
+{
+ if (!touchPointLogHandle) {
+ touchPointLogHandle = new SimpleFileLog(MImTouchPointsLogfile);
+ }
+ return touchPointLogHandle->stream();
+}
// TODO: it would seem that application focus state is passed to all plugins by
// MInputContextGlibDBusConnection::updateWidgetInformation, including nonactive ones. If
@@ -472,14 +500,27 @@
// something else changes during the animation. But normally the region should be
// the same as the one we send now.
- QRectF vkbRect(vkbWidget->rect());
- vkbRect.translate(0, -vkbRect.y()
- + MPlainWindow::instance()->visibleSceneSize().height()
- - vkbRect.height());
- QRectF toolbarRect(sharedHandleArea->rect());
- toolbarRect.translate(0, -toolbarRect.y() + vkbRect.y() - toolbarRect.height());
+ // Region is calculated from widget geometries so this method assumes relevant layouts
+ // to have been activated beforehand. A QGraphicsItem::show() will do, for example.
+
+ QRectF stackedRects(0.0f, MPlainWindow::instance()->visibleSceneSize().height(),
+ 0.0f, 0.0f);
+
+ // Add vkb rect if vkb is visible.
+ if (vkbWidget->isVisible()) {
+ QRectF vkbRect(vkbWidget->rect());
+ vkbRect.moveBottom(stackedRects.top());
+ stackedRects |= vkbRect;
+ }
+
+ // Add toolbar rect if it is visible.
+ if (sharedHandleArea->isVisible()) {
+ QRectF toolbarRect(sharedHandleArea->rect());
+ toolbarRect.moveBottom(stackedRects.top());
+ stackedRects |= toolbarRect;
+ }
- const QRegion region((sceneWindow->mapRectToScene(vkbRect) | sceneWindow->mapRectToScene(toolbarRect)).toRect());
+ const QRegion region(sceneWindow->mapRectToScene(stackedRects).toRect());
RegionTracker::instance().sendInputMethodAreaEstimate(region);
RegionTracker::instance().sendRegionEstimate(region);
@@ -512,8 +553,21 @@
updateEngineKeyboardLayout();
updateCorrectionState();
- sharedHandleArea->show();
+ if (imToolbar->currentToolbarData())
+ sharedHandleArea->show();
+
+ prepareHideShowAnimation();
+ if (activeState == MInputMethod::OnScreen) {
+ vkbWidget->show();
+ }
+ sendRegionEstimate();
+ slideUpAnimation.setDirection(QAbstractAnimation::Forward);
+ slideUpAnimation.start();
+}
+
+void MKeyboardHost::prepareHideShowAnimation()
+{
if (activeState == MInputMethod::Hardware) {
slideUpAnimation.setDuration(HardwareAnimationTime);
vkbFadeInAnimation.setDuration(HardwareAnimationTime);
@@ -529,11 +583,7 @@
slideUpAnimation.setTargetObject(vkbWidget);
slideUpAnimation.setStartValue(QPointF(0, MPlainWindow::instance()->visibleSceneSize().height()
+ sharedHandleArea->size().height()));
- vkbWidget->show();
}
- sendRegionEstimate();
- slideUpAnimation.setDirection(QAbstractAnimation::Forward);
- slideUpAnimation.start();
}
@@ -545,10 +595,15 @@
correctionHost->hideCorrectionWidget();
symbolView->hideSymbolView(); // TODO: transition?
+ prepareHideShowAnimation();
slideUpAnimation.setDirection(QAbstractAnimation::Backward);
slideUpAnimation.start();
sipRequested = false;
+
+ if (touchPointLogHandle) {
+ touchPointLogHandle->flush();
+ }
}
@@ -567,7 +622,6 @@
}
RegionTracker::instance().enableSignals(true);
- updateReactionMaps();
}
@@ -777,23 +831,23 @@
void MKeyboardHost::prepareOrientationChange()
{
- if (rotationTimer.isActive()) {
+ if (rotationInProgress) {
return;
}
+ rotationInProgress = true;
+
// Saves states then hide
symbolView->prepareToOrientationChange();
vkbWidget->prepareToOrientationChange();
correctionHost->prepareToOrientationChange();
MPlainWindow::instance()->sceneManager()->disappearSceneWindowNow(sceneWindow);
-
- // TODO: this is only a workaround for fixing the orientaton change bug.
- // The correct fix need a notification from application, to tell keyboard
- // when the orientation is finished for calling finalizeOrientationChange.
- rotationTimer.start(1000);
}
void MKeyboardHost::finalizeOrientationChange()
{
+ if (!rotationInProgress)
+ return;
+
MPlainWindow::instance()->sceneManager()->appearSceneWindowNow(sceneWindow);
if (imToolbar) {
@@ -805,6 +859,9 @@
symbolView->finalizeOrientationChange();
if (sharedHandleArea) {
sharedHandleArea->finalizeOrientationChange();
+ if (activeState == MInputMethod::Hardware) {
+ sharedHandleArea->setPos(0, MPlainWindow::instance()->visibleSceneSize().height() - sharedHandleArea->size().height());
+ }
}
// Finalize candidate list after so its region will apply.
@@ -827,7 +884,7 @@
if (vkbWidget->isVisible()) {
updateEngineKeyboardLayout();
}
- rotationTimer.stop();
+ rotationInProgress = false;
}
void MKeyboardHost::handleMouseClickOnPreedit(const QPoint &mousePos, const QRect &preeditRect)
@@ -853,24 +910,19 @@
// TODO: hide/show by fading?
if (sipRequested) {
- const bool wasEnabled(RegionTracker::instance().enableSignals(false));
if (priority) {
MPlainWindow::instance()->sceneManager()->disappearSceneWindowNow(sceneWindow);
} else {
MPlainWindow::instance()->sceneManager()->appearSceneWindowNow(sceneWindow);
}
- RegionTracker::instance().enableSignals(wasEnabled);
}
}
-
-void MKeyboardHost::handleAppOrientationChange(int angle)
+void MKeyboardHost::handleAppOrientationAboutToChange(int angle)
{
if (MPlainWindow::instance()->sceneManager()->orientationAngle()== static_cast<M::OrientationAngle>(angle))
return;
- if (rotationTimer.isActive()) {
- rotationTimer.stop();
- }
+
// The application receiving input has changed its orientation. Let's change ours.
// Disable the transition animation for rotation.
MPlainWindow::instance()->sceneManager()->setOrientationAngle(static_cast<M::OrientationAngle>(angle),
@@ -878,6 +930,16 @@
prepareOrientationChange();
}
+void MKeyboardHost::handleAppOrientationChanged(int angle)
+{
+ const M::OrientationAngle orientationAngle = static_cast<M::OrientationAngle>(angle);
+ if (orientationAngle != MPlainWindow::instance()->orientationAngle()) {
+ handleAppOrientationAboutToChange(angle);
+ }
+
+ finalizeOrientationChange();
+}
+
void MKeyboardHost::commitString(const QString &updatedString)
{
@@ -965,11 +1027,13 @@
void MKeyboardHost::handleKeyPress(const KeyEvent &event)
{
+#if 0 // Disabled because of bug NB#223996.
// update fast typing mode
if (++fastTypingKeyCount >= KeysRequiredForFastTypingMode) {
turnOnFastTyping();
}
fastTypingTimeout.start(); // restart
+#endif
if (event.qtKey() == Qt::Key_Shift) {
if (shiftHeldDown) {
@@ -1037,62 +1101,6 @@
}
}
-void MKeyboardHost::updateReactionMaps()
-{
- if (rotationTimer.isActive()) {
- return;
- }
-
- // Start by making everything transparent
- clearReactionMaps(MReactionMap::Transparent);
-
- QList<QGraphicsView *> views = MPlainWindow::instance()->scene()->views();
- foreach (QGraphicsView *view, views) {
- MReactionMap *reactionMap = MReactionMap::instance(view);
-
- if (!reactionMap) {
- continue;
- }
-
- // Candidates widget
- if (correctionHost && correctionHost->isActive()) {
- correctionHost->paintReactionMap(reactionMap, view);
-
- // Correction candidate widget occupies whole screen when it is WordListMode.
- if (correctionHost->candidateMode() == MImCorrectionHost::WordListMode)
- continue;
- }
-
- // Paint either symview or vkb widget reactive areas.
- if (symbolView && symbolView->isVisible()) {
- symbolView->paintReactionMap(reactionMap, view);
- } else if (vkbWidget && vkbWidget->isVisible()) {
- vkbWidget->paintReactionMap(reactionMap, view);
- }
-
- // Toolbar
- if (imToolbar && imToolbar->isVisible()) {
- imToolbar->paintReactionMap(reactionMap, view);
- }
- }
-}
-
-void MKeyboardHost::clearReactionMaps(const QString &clearValue)
-{
- if (!MPlainWindow::instance()->scene()) {
- return;
- }
-
- foreach (QGraphicsView *view, MPlainWindow::instance()->scene()->views()) {
- MReactionMap *reactionMap = MReactionMap::instance(view);
- if (reactionMap) {
- reactionMap->setDrawingValue(clearValue, clearValue);
- reactionMap->setTransform(QTransform()); // Identity
- reactionMap->fillRectangle(0, 0, reactionMap->width(), reactionMap->height());
- }
- }
-}
-
void MKeyboardHost::handleKeyClick(const KeyEvent &event)
{
// Don't need send key events for Direct input mode here.
@@ -1103,9 +1111,9 @@
// modifiers may not be correct (depending on the current hwkbd modifier
// state) but that doesn't matter.
processKeyEvent(QEvent::KeyPress, event.qtKey(), event.modifiers(),
- event.text(), false, 1, 0, 0);
+ event.text(), false, 1, 0, 0, 0);
processKeyEvent(QEvent::KeyRelease, event.qtKey(), event.modifiers(),
- event.text(), false, 1, 0, 0);
+ event.text(), false, 1, 0, 0, 0);
} else if ((inputMethodMode != M::InputMethodModeDirect)) {
handleTextInputKeyClick(event);
}
@@ -1269,7 +1277,8 @@
// or ignore it if correction widget is visible and with suggestionlist mode
// otherwise commit preedit
if (event.qtKey() == Qt::Key_Space
- && correctionHost->isActive()) {
+ && correctionHost->isActive()
+ && correctionAcceptedWithSpaceEnabled) {
if (correctionHost->candidateMode() == MImCorrectionHost::WordTrackerMode) {
wordTrackerSuggestionAcceptedWithSpace = true;
inputMethodHost()->sendCommitString(correctionHost->suggestion());
@@ -1286,10 +1295,7 @@
&& preeditCursorPos != preedit.length()
&& inputMethodHost()->surroundingText(surroundingText, cursorPos)
&& (cursorPos >= 0);
- inputMethodHost()->sendCommitString(preedit);
- if (needRepositionCursor) {
- inputMethodHost()->setSelection(cursorPos + preeditCursorPos, 0);
- }
+ inputMethodHost()->sendCommitString(preedit, 0, 0, needRepositionCursor ? (cursorPos + preeditCursorPos) : -1);
}
}
@@ -1382,6 +1388,7 @@
engineLayoutDirty = true;
updateEngineKeyboardLayout();
synchronizeCorrectionSetting();
+ synchronizeCorrectionSettingSpace();
imCorrectionEngine->disablePrediction();
imCorrectionEngine->setMaximumCandidates(MaximumErrorCorrectionCandidate);
imCorrectionEngine->setExactWordPositionInList(MImEngine::ExactInListFirst);
@@ -1403,6 +1410,11 @@
updateCorrectionState();
}
+void MKeyboardHost::synchronizeCorrectionSettingSpace()
+{
+ correctionAcceptedWithSpaceEnabled
+ = inputMethodCorrectionSettingsSpace->value(DefaultCorrectionSettingAcceptedWithSpaceOption).toBool();
+}
void MKeyboardHost::updateCorrectionState()
{
@@ -1415,14 +1427,28 @@
correctionEnabled = false;
return;
}
- bool val = false;
- bool enabled = inputMethodHost()->correctionEnabled(val);
- if (val)
- correctionEnabled = enabled && imCorrectionEngine->correctionEnabled()
- && imCorrectionEngine->completionEnabled();
- else
- correctionEnabled = imCorrectionEngine->correctionEnabled()
- && imCorrectionEngine->completionEnabled();
+
+ // Don't use correction for certain types.
+ bool enabledByContent = true, ctValid;
+ int contentType = inputMethodHost()->contentType(ctValid);
+ if (ctValid && (contentType == M::NumberContentType
+ || contentType == M::PhoneNumberContentType
+ || contentType == M::EmailContentType
+ || contentType == M::UrlContentType)) {
+ enabledByContent = false;
+ }
+
+ // Enable correction if correction is enabled from MTextEdit and prediction
+ // is not disabled (Qt::ImhNoPredictiveText hint not set). Ignore either
+ // value if value is not set.
+ bool ecValid = false, pValid = false;
+ bool ecEnabled = inputMethodHost()->correctionEnabled(ecValid);
+ bool pEnabled = inputMethodHost()->predictionEnabled(pValid);
+ correctionEnabled = enabledByContent
+ && (!ecValid || ecEnabled)
+ && (!pValid || pEnabled)
+ && imCorrectionEngine->correctionEnabled()
+ && imCorrectionEngine->completionEnabled();
// info context the global correction option
// TODO: should not put setGlobalCorrectionEnabled here, it will send correction setting
@@ -1493,21 +1519,30 @@
void MKeyboardHost::setToolbar(QSharedPointer<const MToolbarData> toolbar)
{
if (toolbar && toolbar->isVisible()) {
+ const MToolbarData *oldToolbar = imToolbar->currentToolbarData();
+ sharedHandleArea->show();
imToolbar->showToolbarWidget(toolbar);
+ // if current is in Hardware state, and no toolbar being visible before,
+ // start animation to show new toolbar.
+ if (!oldToolbar && activeState == MInputMethod::Hardware) {
+ prepareHideShowAnimation();
+ slideUpAnimation.start();
+ }
} else {
imToolbar->hideToolbarWidget();
+ sharedHandleArea->hide();
}
}
void MKeyboardHost::processKeyEvent(QEvent::Type keyType, Qt::Key keyCode,
Qt::KeyboardModifiers modifiers, const QString &text,
bool autoRepeat, int count, quint32 nativeScanCode,
- quint32 nativeModifiers)
+ quint32 nativeModifiers, unsigned long time)
{
if ((activeState != MInputMethod::Hardware) ||
!hardwareKeyboard->filterKeyEvent(keyType, keyCode, modifiers, text,
autoRepeat, count, nativeScanCode,
- nativeModifiers)) {
+ nativeModifiers, time)) {
inputMethodHost()->sendKeyEvent(QKeyEvent(keyType, keyCode, modifiers, text,
autoRepeat, count),
MInputMethod::EventRequestEventOnly);
@@ -1564,8 +1599,8 @@
}
if (sipRequested) {
slideUpAnimation.stop();
- vkbWidget->show();
vkbWidget->setPos(0, MPlainWindow::instance()->visibleSceneSize().height() - vkbWidget->size().height());
+ vkbWidget->show();
}
} else {
currentIndicatorDeadKey = false;
@@ -1603,9 +1638,6 @@
return;
}
- // TODO: make RegionTracker do this kind of optimization automatically
- const bool wasEnabled(RegionTracker::instance().enableSignals(false));
-
// Toggle SymbolView.
if (!symbolView->isVisible()) {
symbolView->setPos(0, MPlainWindow::instance()->visibleSceneSize().height() - symbolView->size().height());
@@ -1615,8 +1647,6 @@
} else {
symbolView->hideSymbolView();
}
-
- RegionTracker::instance().enableSignals(wasEnabled);
}
void MKeyboardHost::updateSymbolViewLevel()
@@ -1635,13 +1665,10 @@
void MKeyboardHost::showSymbolView()
{
- // TODO: make RegionTracker do this kind of optimization automatically
- const bool wasEnabled(RegionTracker::instance().enableSignals(false));
symbolView->setPos(0, MPlainWindow::instance()->visibleSceneSize().height() - symbolView->size().height());
symbolView->showSymbolView(SymbolView::FollowMouseShowMode);
//give the symbolview right shift level(for hardware state)
updateSymbolViewLevel();
- RegionTracker::instance().enableSignals(wasEnabled);
}
MInputMethod::InputModeIndicator MKeyboardHost::deadKeyToIndicator(const QChar &key)
--- m-keyboard/mkeyboardhost.h
+++ m-keyboard/mkeyboardhost.h
@@ -28,6 +28,7 @@
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include <QParallelAnimationGroup>
+#include <QTextStream>
class MGConfItem;
class MImCorrectionHost;
@@ -42,7 +43,7 @@
class SharedHandleArea;
class MImToolbar;
class MAbstractInputMethodHost;
-
+class SimpleFileLog;
//! Logic class for virtual keyboard
class MKeyboardHost: public MAbstractInputMethod
@@ -53,6 +54,11 @@
MKeyboardHost(MAbstractInputMethodHost *imHost, QObject *parent = 0);
virtual ~MKeyboardHost();
+ //! \brief Return the current instance, or 0 if none.
+ static MKeyboardHost* instance();
+ //! \brief Return the logger for touchpoints. Created if neccesary.
+ QTextStream &touchPointLog();
+
//! reimp
virtual void handleFocusChange(bool focusIn);
virtual void show();
@@ -65,13 +71,14 @@
virtual void reset();
virtual void handleMouseClickOnPreedit(const QPoint &mousePos, const QRect &preeditRect);
virtual void handleVisualizationPriorityChange(bool priority);
- virtual void handleAppOrientationChange(int angle);
+ virtual void handleAppOrientationAboutToChange(int angle);
+ virtual void handleAppOrientationChanged(int angle);
virtual void setToolbar(QSharedPointer<const MToolbarData> toolbar);
virtual void setState(const QSet<MInputMethod::HandlerState> &state);
virtual void processKeyEvent(QEvent::Type keyType, Qt::Key keyCode,
Qt::KeyboardModifiers modifiers,
const QString &text, bool autoRepeat, int count,
- quint32 nativeScanCode, quint32 nativeModifiers);
+ quint32 nativeScanCode, quint32 nativeModifiers, unsigned long time);
virtual void handleClientChange();
virtual void switchContext(MInputMethod::SwitchDirection direction, bool enableAnimation);
virtual QList<MAbstractInputMethod::MInputMethodSubView> subViews(MInputMethod::HandlerState state
@@ -116,9 +123,6 @@
*/
void handleLongKeyPress(const KeyEvent &event);
- //! \brief Draws reaction maps for the topmost widget.
- void updateReactionMaps();
-
/*!
* \brief Commits \a string.
*
@@ -141,6 +145,9 @@
//! Synchronize correction setting
void synchronizeCorrectionSetting();
+ //! Synchronize the correction setting whether the correction suggestion should be accepted by space.
+ void synchronizeCorrectionSettingSpace();
+
//! handles user initiated hiding of the keyboard
void userHide();
@@ -197,6 +204,9 @@
void handleAnimationFinished();
private:
+ //! Configures the parts that may change dynamically.
+ void prepareHideShowAnimation();
+
void sendRegionEstimate();
//! \brief Reset internal state, used by reset() and others
@@ -241,11 +251,6 @@
*/
void handleTextInputKeyClick(const KeyEvent &event);
- /*! \brief Clears reaction maps with given MReactionMap color value.
- * \param clearValue A MReactionMap color value such as MReactionMap::Inactive.
- */
- void clearReactionMaps(const QString &clearValue);
-
//! initialize input engine
void initializeInputEngine();
@@ -331,6 +336,7 @@
MImEngineWordsInterface *imCorrectionEngine;
//! default input method error correction setting
MGConfItem *inputMethodCorrectionSettings;
+ MGConfItem *inputMethodCorrectionSettingsSpace;
MGConfItem *inputMethodCorrectionEngine;
QStringList candidates;
@@ -338,8 +344,11 @@
int displayWidth;
int displayHeight;
+ bool rotationInProgress;
+
//! error correction flag
bool correctionEnabled;
+ bool correctionAcceptedWithSpaceEnabled;
//! FIXME: should we provide such a flag to on/off auto caps
bool autoCapsEnabled;
@@ -354,8 +363,6 @@
QTimer backspaceTimer;
- QTimer rotationTimer;
-
KeyEvent lastClickEvent;
//! Keeps track of shift up/down status.
@@ -407,6 +414,8 @@
QPropertyAnimation& toolbarFadeInAnimation;
QParallelAnimationGroup toolbarAndVkbFadeInAnimation;
+ SimpleFileLog *touchPointLogHandle;
+
#ifdef UNIT_TEST
friend class Ut_MKeyboardHost;
#endif
--- m-keyboard/theme/haptic-press
+++ m-keyboard/theme/haptic-press
+(directory)
--- m-keyboard/theme/haptic-press/haptic-press.pri
+++ m-keyboard/theme/haptic-press/haptic-press.pri
+
+haptic_press_data.path = /usr/share/themes/base/meegotouch/meego-im-uiserver/feedbacks/vkb-press
+haptic_press_data.files = theme/haptic-press/vibra.ivt
+
+INSTALLS += \
+ haptic_press_data \
--- m-keyboard/theme/haptic-release
+++ m-keyboard/theme/haptic-release
+(directory)
--- m-keyboard/theme/haptic-release/haptic-release.pri
+++ m-keyboard/theme/haptic-release/haptic-release.pri
+
+haptic_release_data.path = /usr/share/themes/base/meegotouch/meego-im-uiserver/feedbacks/vkb-release
+haptic_release_data.files = theme/haptic-release/vibra.ivt
+
+INSTALLS += \
+ haptic_release_data \
--- m-keyboard/theme/libmeego-keyboard.css
+++ m-keyboard/theme/libmeego-keyboard.css
@@ -30,7 +30,7 @@
MImAbstractKeyAreaStyle {
/*** Font Settings ***/
font: $FONT_KEYBOARD;
- font-color: $COLOR_FOREGROUND;
+ font-color: $FONT_COLOR_KEYBOARD;
secondary-font: $FONT_SMALL;
/*** Graphical assets ***/
@@ -46,7 +46,7 @@
key-background-special-pressed-selected: "meegotouch-keyboard-function-key-pressed-selected" 15 15 15 15;
key-background-deadkey: "meegotouch-keyboard-key" 15 15 15 15;
- key-background-deadkey-pressed: "meegotouch-keyboard-pressed" 15 15 15 15;
+ key-background-deadkey-pressed: "meegotouch-keyboard-key-pressed" 15 15 15 15;
key-background-deadkey-selected: "meegotouch-keyboard-key-selected" 15 15 15 15;
key-background-deadkey-pressed-selected: "meegotouch-keyboard-key-pressed-selected" 15 15 15 15;
@@ -76,6 +76,8 @@
flick-gesture-timeout: 500;
flick-gesture-threshold-ratio: 0.5;
+ touchpoint-vertical-offset: 0mm;
+
/*** Key Geometry ***/
use-fixed-key-width: false;
key-width-small: 0.5;
@@ -117,27 +119,27 @@
/*** Key Geometry ***/
key-height-small: -1; /* unused */
- key-height-medium: 48px;
+ key-height-medium: 46px;
key-height-large: 66px;
key-height-x-large: 82px;
key-height-xx-large: -1; /* unused */
key-width-small-fixed: -1; /* unused */
key-width-medium-fixed: 76px;
- key-width-large-fixed: 94px;
- key-width-x-large-fixed: 160px;
+ key-width-large-fixed: 93px;
+ key-width-x-large-fixed: 178px;
key-width-xx-large-fixed: 244px;
key-width-stretched-fixed: -1; /* unused */
key-margin-left: 4px;
key-margin-top: 0px;
key-margin-right: 4px;
- key-margin-bottom: 8px;
+ key-margin-bottom: 12px;
padding-left: 11px;
- padding-top: 12px;
+ padding-top: 8px;
padding-right: 11px;
- padding-bottom: 12px;
+ padding-bottom: 8px;
/*** Key Area Geometry ***/
size: 854 -1;
@@ -153,6 +155,8 @@
touchpoint-horizontal-gravity: 17px;
touchpoint-vertical-gravity: 26px;
+ touchpoint-vertical-offset: 1.7mm;
+
/*** Key Geometry ***/
key-height-small: -1; /* unused */
key-height-medium: 62px;
@@ -161,21 +165,21 @@
key-height-xx-large: -1; /* unused */
key-width-small-fixed: -1; /* unused */
- key-width-medium-fixed: 46px;
- key-width-large-fixed: 70px;
- key-width-x-large-fixed: 94px;
- key-width-xx-large-fixed: 142px;
+ key-width-medium-fixed: 40px;
+ key-width-large-fixed: 56px;
+ key-width-x-large-fixed: 104px;
+ key-width-xx-large-fixed: 136px;
key-width-stretched-fixed: -1; /* unused */
- key-margin-left: 1px;
+ key-margin-left: 4px;
key-margin-top: 0px;
- key-margin-right: 1px;
- key-margin-bottom: 16px;
+ key-margin-right: 4px;
+ key-margin-bottom: 18px;
- padding-left: 1px;
- padding-top: 12px;
- padding-right: 1px;
- padding-bottom: 12px;
+ padding-left: 4px;
+ padding-top: 8px;
+ padding-right: 4px;
+ padding-bottom: 8px;
/*** Key Area Geometry ***/
size: 480 -1;
@@ -204,31 +208,35 @@
use-fixed-key-width: true;
}
-MImAbstractKeyAreaStyle.Landscape:keys35 {
- use-fixed-key-width: true;
-}
-
-MImAbstractKeyAreaStyle.Portrait:keys35 {
- use-fixed-key-width: true;
-}
-
MImAbstractKeyAreaStyle.Landscape:keys36 {
use-fixed-key-width: true;
+
+ key-width-large-fixed: 118px;
+ key-width-x-large-fixed: 160px;
+ key-width-xx-large-fixed: 286px;
}
MImAbstractKeyAreaStyle.Portrait:keys36 {
use-fixed-key-width: true;
+
+ key-width-large-fixed: 88px;
+ key-width-x-large-fixed: 112px;
+ key-width-xx-large-fixed: 112px;
}
MImAbstractKeyAreaStyle.Landscape:keys37 {
use-fixed-key-width: true;
- key-width-xx-large-fixed: 160px;
+ key-width-large-fixed: 118px;
+ key-width-x-large-fixed: 160px;
+ key-width-xx-large-fixed: 202px;
}
MImAbstractKeyAreaStyle.Portrait:keys37 {
use-fixed-key-width: true;
+ key-width-large-fixed: 64px;
+ key-width-x-large-fixed: 112px;
key-width-xx-large-fixed: 88px;
}
@@ -236,9 +244,9 @@
use-fixed-key-width: true;
key-width-medium-fixed: 72px;
- key-width-large-fixed: 87px;
+ key-width-large-fixed: 150px;
key-width-x-large-fixed: 150px;
- key-width-xx-large-fixed: 306px;
+ key-width-xx-large-fixed: 384px;
key-margin-left: 3px;
key-margin-right: 3px;
@@ -250,25 +258,25 @@
MImAbstractKeyAreaStyle.Portrait:keys38 {
use-fixed-key-width: true;
- key-width-medium-fixed: 42px;
- key-width-large-fixed: 66px;
- key-width-x-large-fixed: 85px;
+ key-width-medium-fixed: 38px;
+ key-width-large-fixed: 82px;
+ key-width-x-large-fixed: 126px;
key-width-xx-large-fixed: 170px;
- key-margin-left: 1px;
- key-margin-right: 1px;
+ key-margin-left: 3px;
+ key-margin-right: 3px;
- padding-left: 0px;
- padding-right: 0px;
+ padding-left: 1px;
+ padding-right: 1px;
}
MImAbstractKeyAreaStyle.Landscape:keys39 {
use-fixed-key-width: true;
key-width-medium-fixed: 72px;
- key-width-large-fixed: 87px;
+ key-width-large-fixed: 111px;
key-width-x-large-fixed: 150px;
- key-width-xx-large-fixed: 306px;
+ key-width-xx-large-fixed: 345px;
key-margin-left: 3px;
key-margin-right: 3px;
@@ -280,25 +288,25 @@
MImAbstractKeyAreaStyle.Portrait:keys39 {
use-fixed-key-width: true;
- key-width-medium-fixed: 42px;
- key-width-large-fixed: 66px;
- key-width-x-large-fixed: 85px;
- key-width-xx-large-fixed: 174px;
+ key-width-medium-fixed: 38px;
+ key-width-large-fixed: 82px;
+ key-width-x-large-fixed: 126px;
+ key-width-xx-large-fixed: 126px;
- key-margin-left: 1px;
- key-margin-right: 1px;
+ key-margin-left: 3px;
+ key-margin-right: 3px;
- padding-left: 0px;
- padding-right: 0px;
+ padding-left: 1px;
+ padding-right: 1px;
}
MImAbstractKeyAreaStyle.Landscape:keys40 {
use-fixed-key-width: true;
key-width-medium-fixed: 72px;
- key-width-large-fixed: 87px;
+ key-width-large-fixed: 111px;
key-width-x-large-fixed: 150px;
- key-width-xx-large-fixed: 228px;
+ key-width-xx-large-fixed: 267px;
key-margin-left: 3px;
key-margin-right: 3px;
@@ -310,16 +318,16 @@
MImAbstractKeyAreaStyle.Portrait:keys40 {
use-fixed-key-width: true;
- key-width-medium-fixed: 42px;
- key-width-large-fixed: 66px;
- key-width-x-large-fixed: 85px;
- key-width-xx-large-fixed: 130px;
+ key-width-medium-fixed: 38px;
+ key-width-large-fixed: 60px;
+ key-width-x-large-fixed: 126px;
+ key-width-xx-large-fixed: 104px;
- key-margin-left: 1px;
- key-margin-right: 1px;
+ key-margin-left: 3px;
+ key-margin-right: 3px;
- padding-left: 0px;
- padding-right: 0px;
+ padding-left: 1px;
+ padding-right: 1px;
}
#InvisibleHandle.Portrait {
@@ -329,25 +337,9 @@
}
#InvisibleHandle.Landscape {
- preferred-size: 864 2.5mm;
+ preferred-size: 854 2.5mm;
minimum-size: 480 2.5mm;
- maximum-size: 864 2.5mm;
-}
-
-#KeyboardToolbarHandle {
- background-image: "meegotouch-keyboard-border-top";
-}
-
-#KeyboardToolbarHandle.Portrait {
- preferred-size: 480 0.6mm;
- minimum-size: 480 0.6mm;
- maximum-size: 480 0.6mm;
-}
-
-#KeyboardToolbarHandle.Landscape {
- preferred-size: 864 0.6mm;
- minimum-size: 480 0.6mm;
- maximum-size: 864 0.6mm;
+ maximum-size: 854 2.5mm;
}
#KeyboardHandle {
@@ -355,9 +347,9 @@
}
#KeyboardHandle.Landscape {
- preferred-size: 864 0;
+ preferred-size: 854 0;
minimum-size: 480 0;
- maximum-size: 864 0;
+ maximum-size: 854 0;
}
#KeyboardHandle.Portrait {
@@ -366,34 +358,6 @@
maximum-size: 480 0;
}
-#MenuToggleButton {
- background-image: "Toggle-btn-normal" 0 0 0 0;
- background-opacity: 1.0;
- background-color: #000000;
- text-color: #FFFFFF;
-}
-
-
-#MenuToggleButton:pressed {
- background-image: "Toggle-btn-selected" 0 0 0 0;
- background-opacity: 1.0;
- background-color: #F9A427;
- text-color: #555555;
-}
-
-
-#MenuLanguageList {
- background-image: "Single-line-input-field" 0 0 0 0;
- text-left-offset: 12;
- text-right-offset: 12;
-
- font: $FONT_SMALL_REGULAR;
- text-color: $COLOR_FOREGROUND;
-
- preferred-size: 414 56;
- minimum-size: 414 56;
- maximum-size: 414 56;
-}
MToolbarLabelStyle {
margin-left: 0;
--- m-keyboard/theme/theme.pri
+++ m-keyboard/theme/theme.pri
@@ -1,3 +1,7 @@
+
+include(haptic-press/haptic-press.pri)
+include(haptic-release/haptic-release.pri)
+
IMAGES_DATA = theme/meegotouch-keyboard.svg
images_data.path = /usr/share/themes/base/meegotouch/svg
images_data.files = $$IMAGES_DATA
@@ -9,4 +13,3 @@
INSTALLS += \
images_data \
css_data \
-
--- m-keyboard/widgets/mimabstractkey.h
+++ m-keyboard/widgets/mimabstractkey.h
@@ -25,6 +25,7 @@
class QRect;
class QPainter;
class MImAbstractKey;
+class MScalableImage;
//! Visitor interface that can be used for MImAbstractKey::visitActiveKeys
class MImAbstractKeyVisitor
@@ -114,6 +115,9 @@
//! \brief Returns whether gravity is active.
virtual bool isGravityActive() const = 0;
+ //! \brief Return background image according to current mode and style.
+ virtual const MScalableImage *backgroundImage() const = 0;
+
//! \brief Returns most recent key that became active, and wasn't released yet.
//! If no key is active, returns 0.
static MImAbstractKey* lastActiveKey();
--- m-keyboard/widgets/mimabstractkeyarea.cpp
+++ m-keyboard/widgets/mimabstractkeyarea.cpp
@@ -18,8 +18,10 @@
#include "flickgesturerecognizer.h"
#include "mimabstractkeyarea.h"
#include "mimkeyvisitor.h"
+#include "mimreactionmap.h"
#include "popupbase.h"
#include "popupfactory.h"
+#include "mkeyboardhost.h"
#include <MFeedback>
#include <MGConfItem>
@@ -45,9 +47,6 @@
// This GConf item defines whether multitouch is enabled or disabled
const char *const MultitouchSettings = "/meegotouch/inputmethods/multitouch/enabled";
- const char *const MImUserDirectory = ".meego-im";
- const char *const MImTouchPointsLogfile = "touchpoints.csv";
-
// Minimal distance (in px) for touch point from key button edge.
const int CorrectionDistanceThreshold = 2;
@@ -72,41 +71,6 @@
return pos;
}
- //! Handles destruction order of internal QFile and QTextStream correctly
- //! and extends lifetime of QFile to QTextStream.
- class StreamHandle
- {
- public:
- explicit StreamHandle(const QString &fileName)
- : mFile(fileName)
- , mStream(&mFile)
- {
- mStream.setCodec("utf-8");
- lastAccess.start();
- }
-
- QFile &file()
- {
- return mFile;
- }
-
- QTextStream &stream()
- {
- // Just make sure we don't lose too much in case of a uiserver crash:
- if (lastAccess.elapsed() > 10000) {
- mStream.flush();
- lastAccess.restart();
- }
-
- return mStream;
- }
-
- private:
- QFile mFile;
- QTextStream mStream;
- QTime lastAccess;
- };
-
QString toString(const QPointF &p, const QString &separator = ", ")
{
return QString("%1%2%3").arg(p.x())
@@ -167,8 +131,7 @@
mPopup(usePopup ? PopupFactory::instance()->createPopup(this) : 0),
wasGestureTriggered(false),
enableMultiTouch(MGConfItem(MultitouchSettings).value().toBool()),
- feedbackPress(MFeedback::Press),
- feedbackCancel(MFeedback::Cancel),
+ feedbackSliding(MImReactionMap::Release),
section(newSection)
{
// By default multi-touch is disabled
@@ -253,11 +216,11 @@
void
MImAbstractKeyArea::handleVisibilityChanged(bool visible)
{
- if (mPopup) {
- mPopup->setVisible(visible);
- }
-
if (!visible) {
+ if (mPopup) {
+ mPopup->setVisible(false);
+ }
+
MImKeyVisitor::SpecialKeyFinder finder(MImKeyVisitor::SpecialKeyFinder::FindDeadKey);
MImAbstractKey::visitActiveKeys(&finder);
@@ -533,7 +496,7 @@
ungrabGesture(FlickGestureRecognizer::sharedGestureType());
}
- const QPoint pos = mapFromScene(tp.scenePos()).toPoint();
+ const QPoint pos = correctedTouchPoint(tp.scenePos());
MImAbstractKey *key = keyAt(pos);
@@ -596,9 +559,8 @@
mTimestamp("MImAbstractKeyArea", "start");
- const QPoint pos = mapFromScene(tp.scenePos()).toPoint();
- const QPoint lastPos = mapFromScene(tp.lastScenePos()).toPoint();
- const QPoint startPos = mapFromScene(tp.startScenePos()).toPoint();
+ const QPoint pos = correctedTouchPoint(tp.scenePos());
+ const QPoint lastPos = correctedTouchPoint(tp.lastScenePos());
const GravitationalLookupResult lookup = gravitationalKeyAt(pos, lastPos);
MImKeyVisitor::SpecialKeyFinder finder;
@@ -616,7 +578,7 @@
// Reaction map cannot discover when we move from one key
// (= reactive area) to another
// slot is called asynchronously to get screen update as fast as possible
- QMetaObject::invokeMethod(&feedbackPress, "play", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&feedbackSliding, "play", Qt::QueuedConnection);
longPressTimer.start(style()->longPressTimeout());
emit keyPressed(lookup.key,
(finder.deadKey() ? finder.deadKey()->label() : QString()),
@@ -627,10 +589,6 @@
if (lookup.lastKey
&& lookup.lastKey->decreaseTouchPointCount()
&& lookup.lastKey->touchPointCount() == 0) {
- // Reaction map cannot discover when we move from one key
- // (= reactive area) to another
- // slot is called asynchronously to get screen update as fast as possible
- QMetaObject::invokeMethod(&feedbackCancel, "play", Qt::QueuedConnection);
emit keyReleased(lookup.lastKey,
(finder.deadKey() ? finder.deadKey()->label() : QString()),
hasActiveShiftKeys || level() % 2);
@@ -656,9 +614,8 @@
idleVkbTimer.start(style()->idleVkbTimeout());
- const QPoint pos = mapFromScene(tp.scenePos()).toPoint();
- const QPoint lastPos = mapFromScene(tp.lastScenePos()).toPoint();
- const QPoint startPos = mapFromScene(tp.startScenePos()).toPoint();
+ const QPoint pos = correctedTouchPoint(tp.scenePos());
+ const QPoint lastPos = correctedTouchPoint(tp.lastScenePos());
const GravitationalLookupResult lookup = gravitationalKeyAt(pos, lastPos);
MImKeyVisitor::SpecialKeyFinder finder;
@@ -779,20 +736,10 @@
const MImAbstractKey *key,
const MImAbstractKey *lastKey) const
{
- if (!QDir::home().exists(MImUserDirectory)) {
- QDir::home().mkdir(MImUserDirectory);
- }
-
- static StreamHandle handle(QString("%1/%2/%3-%4").arg(QDir::homePath())
- .arg(MImUserDirectory)
- .arg(QCoreApplication::applicationPid())
- .arg(MImTouchPointsLogfile));
+ static bool headerWritten = false;
+ QTextStream &out = MKeyboardHost::instance()->touchPointLog();
- QFile &file = handle.file();
- QTextStream &out = handle.stream();
-
- if (!file.isOpen()) {
- file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
+ if (!headerWritten) {
out << "time (sec.msec)\t"
<< "tp_id\t"
<< "tp_state\t"
@@ -804,6 +751,7 @@
<< "label\t"
<< "label_last\t"
<< "br_x\t" << "br_y\t" << "br_w\t" << "br_h\n";
+ headerWritten = true;
}
out << timeStamp() << "\t"
@@ -987,3 +935,30 @@
}
update();
}
+
+QPoint MImAbstractKeyArea::correctedTouchPoint(const QPointF &scenePos) const
+{
+ QPointF pos = mapFromScene(scenePos);
+
+ if (pos.y() >= baseStyle()->touchpointVerticalOffset()) {
+ pos.ry() -= baseStyle()->touchpointVerticalOffset();
+ }
+
+ return pos.toPoint();
+}
+
+QRectF MImAbstractKeyArea::correctedReactionRect(const QRectF &originalRect) const
+{
+ QRectF rect = originalRect;
+ const qreal offset = baseStyle()->touchpointVerticalOffset();
+
+ if (rect.top() >= offset) {
+ rect.setTop(rect.top() + offset);
+ }
+ const qreal newBottom(rect.bottom() + offset);
+ if (newBottom <= size().height()) {
+ rect.setBottom(newBottom);
+ }
+
+ return rect;
+}
--- m-keyboard/widgets/mimabstractkeyarea.h
+++ m-keyboard/widgets/mimabstractkeyarea.h
@@ -72,6 +72,9 @@
//! \brief Returns all keys from this key area.
virtual QList<const MImAbstractKey *> keys() const = 0;
+ //! \brief Returns key with given \a id
+ virtual MImAbstractKey * findKey(const QString &id) = 0;
+
//! \brief Notification for derived classes about button modifier change.
//!
//! Derived classes should not change the level of selected dead keys. This is to
@@ -192,9 +195,6 @@
//! \param visible the new visbility status
virtual void handleVisibilityChanged(bool visible);
- //! \brief Invalidates the current background cache.
- virtual void invalidateBackgroundCache() = 0;
-
//! Shows popup and updates its content and position.
//! \param key current key
void updatePopup(MImAbstractKey *key = 0);
@@ -236,6 +236,16 @@
qreal mRelativeKeyBaseWidth; //!< Relative key base width in currently active layout
bool debugTouchPoints; //!< Whether touch point debugging is enabled
+ //! Correct the vertical offset of a touchpoint
+ //! \param scenePos Input position in scene coordinates.
+ //! \returns the corrected position in item coordinates.
+ QPoint correctedTouchPoint(const QPointF &scenePos) const;
+
+ //! Correct the reaction rects for the vertical offset of a touchpoint
+ //! \param originalRect Original rectangle in item coordinates.
+ //! \returns the corrected rectangle in item coordinates.
+ QRectF correctedReactionRect(const QRectF &originalRect) const;
+
protected slots:
//! Update background images, text layouts, etc. when the theme changed.
virtual void onThemeChangeCompleted();
@@ -314,8 +324,7 @@
QList<QStringList> accentLabels; //!< list of accent labels
bool wasGestureTriggered; //!< whether a gesture was already triggered for any active touch point
bool enableMultiTouch; //!< whether this key area operates in multitouch mode
- MFeedback feedbackPress; //!< Press feedback
- MFeedback feedbackCancel; //!< Cancel feedback
+ MFeedback feedbackSliding; //!< Sliding feedback
const LayoutData::SharedLayoutSection section; //!< layout section shown by this key area
static M::InputMethodMode InputMethodMode; //!< used input method mode (same for all key areas)
QTimer longPressTimer; //!< used to recognize long press
--- m-keyboard/widgets/mimabstractkeyareastyle.h
+++ m-keyboard/widgets/mimabstractkeyareastyle.h
@@ -42,6 +42,7 @@
M_STYLE_ATTRIBUTE(qreal, flickGestureThresholdRatio, FlickGestureThresholdRatio)
M_STYLE_ATTRIBUTE(qreal, touchpointHorizontalGravity, TouchpointHorizontalGravity)
M_STYLE_ATTRIBUTE(qreal, touchpointVerticalGravity, TouchpointVerticalGravity)
+ M_STYLE_ATTRIBUTE(qreal, touchpointVerticalOffset, TouchpointVerticalOffset)
M_STYLE_ATTRIBUTE(QSize, size, Size)
M_STYLE_ATTRIBUTE(qreal, keyHeightSmall, KeyHeightSmall)
--- m-keyboard/widgets/mimcorrectionhost.cpp
+++ m-keyboard/widgets/mimcorrectionhost.cpp
@@ -23,6 +23,7 @@
MImCorrectionHost::MImCorrectionHost(MSceneWindow *parentWindow)
: QObject(parentWindow),
+ ReactionMapPaintable(),
rotationInProgress(false),
currentMode(MImCorrectionHost::WordTrackerMode),
pendingCandidatesUpdate(false),
@@ -31,8 +32,17 @@
{
connect(wordTracker, SIGNAL(candidateClicked(QString)), this, SLOT(handleCandidateClicked(QString)));
connect(wordTracker, SIGNAL(longTapped()), this, SLOT(longTap()));
+ // The word tracker changed -> Repaint the reaction maps
+ // TODO: The reaction map repainting can be optimized here to clear/repaint only the
+ // reaction map of the word tracker.
+ connect(wordTracker, SIGNAL(geometryChanged()), &signalForwarder, SIGNAL(requestRepaint()));
+ connect(wordTracker, SIGNAL(displayExited()), &signalForwarder, SIGNAL(requestRepaint()));
connect(wordList, SIGNAL(candidateClicked(QString)), this, SLOT(handleCandidateClicked(QString)));
+ // The word list goes on top -> Clear the reaction maps
+ connect(wordList, SIGNAL(displayEntered()), &signalForwarder, SIGNAL(requestClear()));
+ // The word list disappears -> Repaint the reaction maps
+ connect(wordList, SIGNAL(displayExited()), &signalForwarder, SIGNAL(requestRepaint()));
}
@@ -176,6 +186,17 @@
hideCorrectionWidget();
}
+bool MImCorrectionHost::isPaintable() const
+{
+ return isActive();
+}
+
+bool MImCorrectionHost::isFullScreen() const
+{
+ // Correction candidate widget occupies whole screen when it is WordListMode.
+ return candidateMode() == MImCorrectionHost::WordListMode;
+}
+
void MImCorrectionHost::longTap()
{
qDebug() << __PRETTY_FUNCTION__;
--- m-keyboard/widgets/mimcorrectionhost.h
+++ m-keyboard/widgets/mimcorrectionhost.h
@@ -17,6 +17,8 @@
#ifndef MIMCORRECTIONHOST_H
#define MIMCORRECTIONHOST_H
+#include "reactionmappaintable.h"
+
#include <QObject>
#include <QString>
#include <QStringList>
@@ -34,7 +36,7 @@
\brief The MImCorrectionHost class is used to show error correction
candidate word tracker or word list.
*/
-class MImCorrectionHost : public QObject
+class MImCorrectionHost : public QObject, public ReactionMapPaintable
{
Q_OBJECT
@@ -113,6 +115,10 @@
//! Clear stored suggestion and hide candidate widget.
void reset();
+ /*! \reimp */
+ bool isPaintable() const;
+ bool isFullScreen() const;
+ /*! \reimp_end */
signals:
//! Updates the preedit word
void candidateClicked(const QString &);
--- m-keyboard/widgets/mimkey.cpp
+++ m-keyboard/widgets/mimkey.cpp
@@ -21,8 +21,12 @@
#include "mvirtualkeyboardstyle.h"
#include "getcssproperty.h"
+#include <mplainwindow.h>
+
#include <MTheme>
-#include <QGraphicsItem>
+#include <MScalableImage>
+#include <MTimestamp>
+
#include <QPainter>
namespace {
@@ -31,6 +35,46 @@
const qreal scaling = qMax<qreal>(0.0, newScaling);
return ((scaling * unit) + (qMax<qreal>(0.0, scaling - 1) * spacing));
}
+
+ // Modify font to make text fit into boundingRect
+ // TODO: Could be optimized to use a binary search.
+ void scaleDownFont(QFont *font, const QString& text, const QRect& boundingRect)
+ {
+ // Fonts can either be specified in points or pixels
+ int fontSize = font->pixelSize();
+ const bool usesPixelSize = (fontSize == -1) ? false : true;
+
+ if (!usesPixelSize) {
+ fontSize = font->pointSize();
+ Q_ASSERT(fontSize != -1);
+ }
+
+ // Minimum font size is 1
+ while (fontSize > 1) {
+ if (usesPixelSize) {
+ font->setPixelSize(fontSize);
+ }
+ else {
+ font->setPointSize(fontSize);
+ }
+
+ const QFontMetrics fontMetrics(*font);
+ const QRect textBounds = fontMetrics.boundingRect(text);
+
+ if (textBounds.width() <= boundingRect.width()
+ && textBounds.height() <= boundingRect.height()) {
+ break;
+ }
+ --fontSize;
+ }
+
+ }
+}
+
+MImKey::StylingCache::StylingCache()
+ : primary(QFont()),
+ secondary(QFont())
+{
}
MImKey::IconInfo::IconInfo()
@@ -46,8 +90,7 @@
}
MImKey::Geometry::Geometry()
- : pos()
- , width(0.0)
+ : width(0.0)
, height(0.0)
, marginLeft(0.0)
, marginTop(0.0)
@@ -55,15 +98,13 @@
, marginBottom(0.0)
{}
-MImKey::Geometry::Geometry(const QPointF &newPos,
- qreal newWidth,
+MImKey::Geometry::Geometry(qreal newWidth,
qreal newHeight,
qreal newMarginLeft,
qreal newMarginTop,
qreal newMarginRight,
qreal newMarginBottom)
- : pos(newPos)
- , width(newWidth)
+ : width(newWidth)
, height(newHeight)
, marginLeft(newMarginLeft)
, marginTop(newMarginTop)
@@ -73,8 +114,10 @@
MImKey::MImKey(const MImKeyModel &newModel,
const MImAbstractKeyAreaStyleContainer &style,
- QGraphicsItem &parent)
- : width(0),
+ QGraphicsItem &parent,
+ const QSharedPointer<StylingCache> &newStylingCache)
+ : QGraphicsItem(&parent),
+ width(0),
mModel(newModel),
shift(false),
currentLabel(mModel.binding(false)->label()),
@@ -83,7 +126,9 @@
styleContainer(style),
parentItem(parent),
currentTouchPointCount(0),
- hasGravity(false)
+ hasGravity(false),
+ rowHasSecondaryLabel(false),
+ stylingCache(newStylingCache)
{
if (mModel.binding(false)) {
loadIcon(false);
@@ -91,6 +136,11 @@
if (mModel.binding(true)) {
loadIcon(true);
}
+
+ labelFont = style->font();
+ hide();
+
+ //label position should be computed later, when geometry will be known
}
MImKey::~MImKey()
@@ -117,16 +167,83 @@
return cachedButtonBoundingRect;
}
-void MImKey::updateButtonRects()
+void MImKey::updateGeometryCache()
{
const Geometry &g = currentGeometry;
- cachedButtonBoundingRect = QRectF(g.pos.x(), g.pos.y(),
+ cachedButtonBoundingRect = QRectF(pos().x(), pos().y(),
g.width + g.marginLeft + g.marginRight,
g.height + g.marginTop + g.marginBottom);
cachedButtonRect = cachedButtonBoundingRect.adjusted( g.marginLeft, g.marginTop,
-g.marginRight, -g.marginBottom);
}
+void MImKey::invalidateLabelPos()
+{
+ labelArea = QRectF();
+ secondaryLabelArea = QRectF();
+
+ updateLabelFont();
+}
+
+void MImKey::updateLabelFont()
+{
+ // Use a maximum label rectangle that is a bit smaller than the button
+ const QRect maximumLabelRect = buttonRect().adjusted(0, 0, -10, -5).toRect();
+ labelFont = styleContainer->font();
+ scaleDownFont(&labelFont, label(), maximumLabelRect);
+}
+
+void MImKey::updateLabelPos() const
+{
+ const QRectF paintingArea(currentGeometry.marginLeft,
+ currentGeometry.marginTop,
+ currentGeometry.width,
+ currentGeometry.height);
+
+ if (!rowHasSecondaryLabel) {
+ labelArea = paintingArea;
+ } else {
+ const int labelHeight = stylingCache->primary.height();
+ const int secondaryLabelHeight = stylingCache->secondary.height();
+ const int topMargin = styleContainer->labelMarginTop();
+ const int labelLeftWithSecondary = styleContainer->labelMarginLeftWithSecondary();
+ const int secondarySeparation = styleContainer->secondaryLabelSeparation();
+ const bool landscape = (MPlainWindow::instance()->orientation() == M::Landscape);
+
+ // In landscape the secondary labels are below the primary ones. In portrait,
+ // secondary labels are horizontally next to primary labels.
+ if (landscape) {
+ // primary label: horizontally centered, top margin defines y
+ // secondary: horizontally centered, primary bottom + separation margin defines y
+ const int primaryY = paintingArea.top() + topMargin;
+ labelArea = QRectF(paintingArea.left(),
+ primaryY,
+ paintingArea.width(),
+ labelHeight);
+ if (!secondaryLabel().isEmpty()) {
+ secondaryLabelArea = QRectF(paintingArea.left(),
+ labelArea.bottom() + secondarySeparation,
+ paintingArea.width(),
+ secondaryLabelHeight);
+ }
+ } else {
+ // primary label: horizontally according to left margin, vertically centered
+ // secondary: horizontally on right of primary + separation margin, vertically centered
+ const int primaryX = paintingArea.left() + labelLeftWithSecondary;
+ labelArea = QRectF(primaryX,
+ paintingArea.top(),
+ stylingCache->primary.width(label()),
+ paintingArea.height());
+ if (!secondaryLabel().isEmpty()) {
+ secondaryLabelArea = QRectF(labelArea.right() + secondarySeparation,
+ paintingArea.top(),
+ stylingCache->secondary.width(secondaryLabel()),
+ paintingArea.height());
+ }
+ }
+ }
+}
+
void MImKey::setModifiers(bool shift, QChar accent)
{
if (this->shift != shift || this->accent != accent) {
@@ -134,6 +251,7 @@
this->accent = accent;
currentLabel = binding().accented(accent);
+ invalidateLabelPos();
update();
}
}
@@ -160,7 +278,7 @@
hasGravity = false;
}
- update();
+ setVisible(currentState != Normal);
}
}
@@ -265,6 +383,104 @@
return hasGravity;
}
+const MScalableImage * MImKey::backgroundImage() const
+{
+ const MScalableImage *background = 0;
+
+ switch (state()) {
+
+ case MImAbstractKey::Normal:
+ switch (model().style()) {
+ case MImKeyModel::SpecialStyle:
+ background = styleContainer->keyBackgroundSpecial();
+ break;
+ case MImKeyModel::DeadkeyStyle:
+ background = styleContainer->keyBackgroundDeadkey();
+ break;
+ case MImKeyModel::NormalStyle:
+ default:
+ background = styleContainer->keyBackground();
+ break;
+ }
+ break;
+
+ case MImAbstractKey::Pressed:
+ switch (model().style()) {
+ case MImKeyModel::SpecialStyle:
+ background = styleContainer->keyBackgroundSpecialPressed();
+ break;
+ case MImKeyModel::DeadkeyStyle:
+ background = styleContainer->keyBackgroundDeadkeyPressed();
+ break;
+ case MImKeyModel::NormalStyle:
+ default:
+ background = styleContainer->keyBackgroundPressed();
+ break;
+ }
+ break;
+
+ case MImAbstractKey::Selected:
+ switch (model().style()) {
+ case MImKeyModel::SpecialStyle:
+ background = styleContainer->keyBackgroundSpecialSelected();
+ break;
+ case MImKeyModel::DeadkeyStyle:
+ background = styleContainer->keyBackgroundDeadkeySelected();
+ break;
+ case MImKeyModel::NormalStyle:
+ default:
+ background = styleContainer->keyBackgroundSelected();
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return background;
+}
+
+QRectF MImKey::boundingRect() const
+{
+ return QRectF(QPointF(), buttonBoundingRect().size());
+}
+
+void MImKey::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ mTimestamp("MImKey", "start");
+
+ // We use QGraphicsView::DontSavePainterState, so save/restore state manually
+ // Not strictly needed at the moment, but prevents subtle breakage later
+ painter->save();
+ const MScalableImage *background = backgroundImage();
+ const QRectF paintingArea(currentGeometry.marginLeft,
+ currentGeometry.marginTop,
+ currentGeometry.width,
+ currentGeometry.height);
+ const QPixmap *iconPixmap(icon());
+
+ if (background) {
+ background->draw(paintingArea, painter);
+ }
+
+ if (iconPixmap) {
+ QPointF iconPos(paintingArea.left() + (paintingArea.width() - iconPixmap->width()) / 2,
+ paintingArea.top() + (paintingArea.height() - iconPixmap->height()) / 2);
+ painter->drawPixmap(iconPos, *iconPixmap);
+ } else {
+ painter->setFont(font());
+ painter->setPen(styleContainer->fontColor());
+ painter->drawText(labelArea, Qt::AlignCenter, label());
+ if (!secondaryLabel().isEmpty()) {
+ painter->setFont(styleContainer->secondaryFont());
+ painter->drawText(secondaryLabelArea, Qt::AlignCenter, secondaryLabel());
+ }
+ }
+ painter->restore();
+ mTimestamp("MImKey", "end");
+}
+
const QPixmap *MImKey::icon() const
{
return iconInfo().pixmap;
@@ -287,12 +503,6 @@
}
}
-void MImKey::update()
-{
- // Invalidate this button's area.
- parentItem.update(buttonRect());
-}
-
int MImKey::preferredFixedWidth() const
{
switch(mModel.width()) {
@@ -373,25 +583,20 @@
void MImKey::setGeometry(const MImKey::Geometry &geometry)
{
currentGeometry = geometry;
- updateButtonRects();
-}
-
-void MImKey::setPos(const QPointF &pos)
-{
- currentGeometry.pos = pos;
- updateButtonRects();
+ updateGeometryCache();
+ invalidateLabelPos();
}
void MImKey::setWidth(qreal width)
{
currentGeometry.width = width;
- updateButtonRects();
+ updateGeometryCache();
}
void MImKey::setHeight(qreal height)
{
currentGeometry.height = height;
- updateButtonRects();
+ updateGeometryCache();
}
void MImKey::setMargins(qreal left,
@@ -403,7 +608,33 @@
currentGeometry.marginTop = top;
currentGeometry.marginRight = right;
currentGeometry.marginBottom = bottom;
- updateButtonRects();
+ updateGeometryCache();
+}
+
+void MImKey::setSecondaryLabelEnabled(bool enable)
+{
+ if (rowHasSecondaryLabel != enable) {
+ rowHasSecondaryLabel = enable;
+ invalidateLabelPos();
+ }
+}
+
+const QRectF & MImKey::labelRect() const
+{
+ if (labelArea.isNull()) {
+ updateLabelPos();
+ }
+
+ return labelArea;
+}
+
+const QRectF & MImKey::secondaryLabelRect() const
+{
+ if (labelArea.isNull()) {
+ updateLabelPos();
+ }
+
+ return secondaryLabelArea;
}
void MImKey::loadIcon(bool shift)
@@ -458,3 +689,7 @@
return (shift ? upperCaseIcon : lowerCaseIcon);
}
+const QFont &MImKey::font() const
+{
+ return labelFont;
+}
--- m-keyboard/widgets/mimkey.h
+++ m-keyboard/widgets/mimkey.h
@@ -16,23 +16,36 @@
-#ifndef SINGLEWIDGETBUTTON_H
-#define SINGLEWIDGETBUTTON_H
+#ifndef MIMKEY_H
+#define MIMKEY_H
#include "mimabstractkey.h"
#include <QPointF>
+#include <QGraphicsItem>
+#include <QRectF>
+#include <QFontMetrics>
+#include <QSharedPointer>
class MImAbstractKeyAreaStyleContainer;
-class QGraphicsItem;
class MImKeyArea;
+class MScalableImage;
//! Represents a key model with the key's current binding state, and also contains its visible area.
class MImKey
- : public MImAbstractKey
+ : public QGraphicsItem,
+ public MImAbstractKey
{
public:
+ //! Contains cached font information for current style
+ struct StylingCache
+ {
+ QFontMetrics primary;
+ QFontMetrics secondary;
+
+ StylingCache();
+ };
+
struct Geometry {
- QPointF pos;
qreal width;
qreal height;
qreal marginLeft;
@@ -41,8 +54,7 @@
qreal marginBottom;
Geometry();
- Geometry(const QPointF &newPos,
- qreal newWidth,
+ Geometry(qreal newWidth,
qreal newHeight,
qreal newMarginLeft,
qreal newMarginTop,
@@ -52,7 +64,8 @@
explicit MImKey(const MImKeyModel &mModel,
const MImAbstractKeyAreaStyleContainer &style,
- QGraphicsItem &parent);
+ QGraphicsItem &parent,
+ const QSharedPointer<StylingCache> &newStylingCache);
virtual ~MImKey();
@@ -78,6 +91,9 @@
virtual int touchPointCount() const;
virtual void activateGravity();
virtual bool isGravityActive() const;
+ virtual const MScalableImage *backgroundImage() const;
+ virtual QRectF boundingRect() const;
+ virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
//! \reimp_end
//! Return limit for active touchpoints
@@ -91,8 +107,6 @@
//! \brief Draws the icon of this key, if available.
virtual void drawIcon(QPainter *painter) const;
- //! \brief Calls parent item's QGraphicsItem::update() who actually draws the button.
- void update();
//! Returns preferred fixed witdth
int preferredFixedWidth() const;
@@ -111,10 +125,6 @@
//! \param geometry the new geometry
void setGeometry(const MImKey::Geometry &geometry);
- //! \brief Set position (relative to parent item).
- //! \param pos the new position
- void setPos(const QPointF &pos);
-
//! \brief Set the key width.
//! \param width the new width
void setWidth(qreal width);
@@ -133,11 +143,33 @@
qreal right,
qreal bottom);
+ //! \brief This parameter defines text alignment: we use primary label only if \a enable is false
+ //! and both primary and secondary labels if \a enable is false.
+ void setSecondaryLabelEnabled(bool enable);
+
+ //! \brief Return rectangle where we should draw primary label
+ const QRectF & labelRect() const;
+
+ //! \brief Return rectangle where we should draw secondary label.
+ const QRectF & secondaryLabelRect() const;
+
+ //! \brief Invalidates cached position, so next call to getter will calculate it again
+ void invalidateLabelPos();
+
+ //! \brief Updates cached geometry.
+ //! This method must be called when position or size of this key is changed.
+ void updateGeometryCache();
+
+ //! \brief Return the font of this key.
+ const QFont &font() const;
+
//! The width for this button. Not managed by this class.
//! It is used by MImKeyArea to store the correct button size.
qreal width;
private:
+ Q_DISABLE_COPY(MImKey);
+
//! Contains information about icon
struct IconInfo
{
@@ -152,7 +184,10 @@
void loadIcon(bool shift);
const IconInfo &iconInfo() const;
- void updateButtonRects();
+ //! \brief Update cached label position.
+ void updateLabelPos() const;
+ //! \brief Update label font.
+ void updateLabelFont();
const MImKeyModel &mModel;
@@ -178,7 +213,20 @@
QRectF cachedButtonBoundingRect;
bool hasGravity;
+
+ //! Some key in the same row has secondary label
+ bool rowHasSecondaryLabel;
+
+ //! Cached position of primary label
+ mutable QRectF labelArea;
+ //! Cached position of secondary label
+ mutable QRectF secondaryLabelArea;
+
+ //! Primary label font
+ QFont labelFont;
+
+ const QSharedPointer<StylingCache> stylingCache;
};
-#endif // SINGLEWIDGETBUTTON_H
+#endif // MIMKEY_H
--- m-keyboard/widgets/mimkeyarea.cpp
+++ m-keyboard/widgets/mimkeyarea.cpp
@@ -28,6 +28,8 @@
#include <mreactionmap.h>
#include <MTimestamp>
+#include "mimreactionmap.h"
+
namespace {
template<class T>
int binaryRangeFind(T value,
@@ -63,7 +65,7 @@
//! PaintMode can be used to optimize drawing for HW acceleration
enum PaintMode {
PaintBackground, //!< Only draw background of given keys, fills up iconKeys
- PaintBackgroundAndIcon //!< Draw both, background and icon, in one go
+ PaintBackgroundAndIcon //!< Draw both, background and icon, in one go
};
private:
@@ -138,58 +140,7 @@
return;
}
- const MScalableImage *background = 0;
-
- switch (key->state()) {
-
- case MImAbstractKey::Normal:
- switch (key->model().style()) {
- case MImKeyModel::SpecialStyle:
- background = keyArea->baseStyle()->keyBackgroundSpecial();
- break;
- case MImKeyModel::DeadkeyStyle:
- background = keyArea->baseStyle()->keyBackgroundDeadkey();
- break;
- case MImKeyModel::NormalStyle:
- default:
- background = keyArea->baseStyle()->keyBackground();
- break;
- }
- break;
-
- case MImAbstractKey::Pressed:
- switch (key->model().style()) {
- case MImKeyModel::SpecialStyle:
- background = keyArea->baseStyle()->keyBackgroundSpecialPressed();
- break;
- case MImKeyModel::DeadkeyStyle:
- background = keyArea->baseStyle()->keyBackgroundDeadkeyPressed();
- break;
- case MImKeyModel::NormalStyle:
- default:
- background = keyArea->baseStyle()->keyBackgroundPressed();
- break;
- }
- break;
-
- case MImAbstractKey::Selected:
- switch (key->model().style()) {
- case MImKeyModel::SpecialStyle:
- background = keyArea->baseStyle()->keyBackgroundSpecialSelected();
- break;
- case MImKeyModel::DeadkeyStyle:
- background = keyArea->baseStyle()->keyBackgroundDeadkeySelected();
- break;
- case MImKeyModel::NormalStyle:
- default:
- background = keyArea->baseStyle()->keyBackgroundSelected();
- break;
- }
- break;
-
- default:
- break;
- }
+ const MScalableImage *background = key->backgroundImage();
if (background) {
background->draw(key->buttonRect().toRect(), painter);
@@ -360,6 +311,7 @@
foreach (MImKey *const key, row) {
key->setPos(currentPos);
+ key->updateGeometryCache();
const qreal nextPosX = currentPos.x() + key->buttonBoundingRect().width();
mKeyOffsets.append(QPair<qreal, qreal>(currentPos.x(), nextPosX));
@@ -380,16 +332,15 @@
cachedWidgetHeight(computeWidgetHeight()),
mMaxNormalizedWidth(computeMaxNormalizedWidth()),
shiftKey(0),
- textDirty(false),
- cachedBackgroundDirty(true),
- hasCachedBackground(false),
equalWidthKeys(true),
- WidthCorrection(0)
+ WidthCorrection(0),
+ stylingCache(new MImKey::StylingCache)
{
- textLayout.setCacheEnabled(true);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
loadKeys();
+
+ setCacheMode(QGraphicsItem::DeviceCoordinateCache);
}
MImKeyArea::~MImKeyArea()
@@ -398,6 +349,7 @@
qDeleteAll(rowIter->keys);
rowIter->keys.clear();
}
+ clearKeyIds();
}
QSizeF MImKeyArea::sizeHint(Qt::SizeHint which,
@@ -416,12 +368,28 @@
QGraphicsView *view)
{
reactionMap->setTransform(this, view);
- reactionMap->setReactiveDrawingValue();
+ reactionMap->setDrawingValue(MImReactionMap::Press, MImReactionMap::Release);
foreach (const KeyRow &row, rowList) {
+ // 'area' is used for key bounding rect coalescing, to improve
+ // downsampling to reaction map resolution (usually display_size / 4).
+ QRectF area;
+ qreal lastRightBorder = 0.0f;
+
foreach (const MImKey *const key, row.keys) {
- reactionMap->fillRectangle(key->buttonBoundingRect());
+ const QRectF rect = correctedReactionRect(key->buttonBoundingRect());
+
+ // Check for spacers. If found, we draw the accummulated area and start from scratch.
+ if (lastRightBorder < rect.left()) {
+ reactionMap->fillRectangle(area);
+ area = QRectF();
+ }
+
+ area |= rect;
+ lastRightBorder = rect.right();
}
+
+ reactionMap->fillRectangle(area);
}
}
@@ -438,7 +406,11 @@
for (int col = 0; col < numColumns; ++col) {
// Parameters to fetch from base class.
MImKeyModel *dataKey = sectionModel()->keyModel(row, col);
- MImKey *key = new MImKey(*dataKey, baseStyle(), *this);
+ MImKey *key = new MImKey(*dataKey, baseStyle(), *this, stylingCache);
+
+ if (!key->model().id().isEmpty()) {
+ registerKeyId(key);
+ }
// Temporary, dirty workaround-hack to detect Arabic layouts
// because the QTextLayout rendering is broken with Arabic characters and
@@ -467,153 +439,6 @@
updateGeometry();
}
-void MImKeyArea::buildTextLayout()
-{
- textDirty = false;
-
- textLayout.clearLayout();
-
- QList<QTextLayout::FormatRange> formatList;
- QTextCharFormat secondaryFormat;
- secondaryFormat.setFont(baseStyle()->secondaryFont());
-
- // QTextLayout requires text content to be set before creating QTextLines.
- // While concatenating the text, also build 'additional formats' used for secondary
- // labels. This must be done before QTextLayout::beginLayout().
- QString labelContent;
-
- foreach (const KeyRow &row, rowList) {
- foreach (const MImKey *key, row.keys) {
- // primary label
- QString label = key->label();
-
- if (!label.isEmpty()) {
- // Add whitespace for QTextLine to be able to cut.
- labelContent += label + " ";
-
- // try secondary label
- label = key->secondaryLabel();
-
- if (!label.isEmpty()) {
- // Add formatting for this secondary label.
- QTextLayout::FormatRange formatRange = {labelContent.length(),
- label.length(),
- secondaryFormat};
- formatList.append(formatRange);
- labelContent += label + " ";
- }
- }
- }
- }
-
- // Apply the formats
- if (!formatList.isEmpty()) {
- textLayout.setAdditionalFormats(formatList);
- }
-
- QFontMetrics fm(baseStyle()->font());
- QFontMetrics secondaryFm(secondaryFormat.font());
- const int labelHeight = fm.height();
- const int secondaryLabelHeight = secondaryFm.height();
- const int topMargin = baseStyle()->labelMarginTop();
- const int labelLeftWithSecondary = baseStyle()->labelMarginLeftWithSecondary();
- const int secondarySeparation = baseStyle()->secondaryLabelSeparation();
- const bool landscape = (MPlainWindow::instance()->orientation() == M::Landscape);
-
- textLayout.setFont(baseStyle()->font());
- textLayout.setText(labelContent);
-
- textLayout.beginLayout();
-
- for (RowIterator row(rowList.begin()); row != rowList.end(); ++row) {
- // rowHasSecondaryLabel is needed for the vertical alignment of
- // secondary label purposes.
- bool rowHasSecondaryLabel = false;
-
- foreach (const MImKey *key, row->keys) {
- if (!key->secondaryLabel().isEmpty()) {
- rowHasSecondaryLabel = true;
- }
- }
-
- foreach (const MImKey *key, row->keys) {
- const QString &label(key->label());
- const QString &secondary(key->secondaryLabel());
- QPoint labelPos;
- QPoint secondaryLabelPos;
-
- // We must not create a new QTextLine if there is no label.
- if (label.isEmpty()) {
- continue;
- }
-
- const QRectF &keyRect = key->buttonRect();
-
- if (!rowHasSecondaryLabel) {
- // All horizontally centered.
- labelPos = fm.boundingRect(keyRect.x(),
- keyRect.y(),
- keyRect.width(),
- keyRect.height(),
- Qt::AlignCenter,
- label).topLeft();
- } else {
- // Calculate position for both primary and secondary label.
- // We only have secondary labels in phone number layouts (with sym being exception)
- // so this follows their styling.
-
- // In landscape the secondary labels are below the primary ones. In portrait,
- // secondary labels are horizontally next to primary labels.
- if (landscape) {
- // primary label: horizontally centered, top margin defines y
- // secondary: horizontally centered, primary bottom + separation margin defines y
- const int primaryY = keyRect.top() + topMargin;
- labelPos.setX(keyRect.center().x() - fm.width(label) / 2);
- labelPos.setY(primaryY);
- if (!secondary.isEmpty()) {
- secondaryLabelPos.setX(keyRect.center().x() - secondaryFm.width(secondary) / 2);
- secondaryLabelPos.setY(primaryY + labelHeight + secondarySeparation);
- }
- } else {
- // primary label: horizontally according to left margin, vertically centered
- // secondary: horizontally on right of primary + separation margin, vertically centered
- const int primaryX = keyRect.left() + labelLeftWithSecondary;
- labelPos.setX(primaryX);
- labelPos.setY(keyRect.center().y() - labelHeight / 2);
- if (!secondary.isEmpty()) {
- secondaryLabelPos.setX(primaryX + fm.width(label) + secondarySeparation);
- secondaryLabelPos.setY(keyRect.center().y() - secondaryLabelHeight / 2);
- }
- }
- }
-
- // We now have positions, let's create some QTextLines.
-
- // Create the primary label
- QTextLine line = textLayout.createLine();
- if (!line.isValid()) {
- // We are getting out of sync anyway so no point in continuing.
- goto endLayout;
- }
- line.setNumColumns(label.length()); // will be seeked forward until next whitespace
- line.setPosition(labelPos);
-
- // Same for secondary label
- if (!secondary.isEmpty()) {
- line = textLayout.createLine();
- if (!line.isValid()) {
- goto endLayout;
- }
- line.setNumColumns(secondary.length());
- line.setPosition(secondaryLabelPos);
- }
- }
- }
-
-endLayout:
- textLayout.endLayout();
-}
-
qreal MImKeyArea::computeWidgetHeight() const
{
qreal height = baseStyle()->size().height();
@@ -632,79 +457,77 @@
return qMax<qreal>(0.0, height);
}
-void MImKeyArea::paint(QPainter *onScreenPainter,
+void MImKeyArea::paint(QPainter *painter,
const QStyleOptionGraphicsItem *,
QWidget *)
{
mTimestamp("MImKeyArea", "start");
const MImAbstractKeyAreaStyleContainer &style(baseStyle());
- // Key areas are disabled during animations. Once we are animated, it
- // makes no sense to maintain the offscreen cache (especially when
- // HW-accelerated). Therefore, we draw directly to the screen.
- // However, we need to remember whether we drew a current version of the
- // key area to the offscreen cache at all (that's what hasCachedBackground
- // is for).
- QPainter *currentPainter = onScreenPainter;
- if (cachedBackgroundDirty
- || !isEnabled()
- || !hasCachedBackground) {
+ const MScalableImage *background = style->backgroundImage();
- // TODO: find out why size()'s height is incorrect for popup.
- initCachedBackground(QSize(size().width(), cachedWidgetHeight));
- QPainter offScreenPainter(cachedBackground.get());
+ if (background) {
+ background->draw(boundingRect().toRect(), painter);
+ }
- if (isEnabled()) {
- currentPainter = &offScreenPainter;
- hasCachedBackground = true;
- }
+ const bool drawButtonBoundingRects(style->drawButtonBoundingRects());
+ const bool drawButtonRects(style->drawButtonRects());
- const MScalableImage *background = style->backgroundImage();
+ // In case of HW acceleration, we want to avoid switching between textures, if possible
+ // Draw backgrounds first, icons later:
+ const KeyPainter kp(this, painter, KeyPainter::PaintBackground);
- if (background) {
- background->draw(boundingRect().toRect(), currentPainter);
+ foreach (const KeyRow &row, rowList) {
+ foreach (const MImKey *key, row.keys) {
+ kp(key);
+ drawDebugRects(painter, key,
+ drawButtonBoundingRects,
+ drawButtonRects);
}
+ }
- const bool drawButtonBoundingRects(style->drawButtonBoundingRects());
- const bool drawButtonRects(style->drawButtonRects());
+ kp.drawIcons();
- // In case of HW acceleration, we want to avoid switching between textures, if possible
- // Draw backgrounds first, icons later:
- const KeyPainter kp(this, currentPainter, KeyPainter::PaintBackground);
+ if (style->drawReactiveAreas()) {
+ drawDebugReactiveAreas(painter);
+ }
- foreach (const KeyRow &row, rowList) {
- foreach (const MImKey *key, row.keys) {
- kp(key);
- drawDebugRects(currentPainter, key,
- drawButtonBoundingRects,
- drawButtonRects);
+ // Draw text next.
+ // We use QGraphicsView::DontSavePainterState, so save/restore state manually
+ // Not strictly needed at the moment, but prevents subtle breakage later
+ painter->save();
+ painter->setPen(style->fontColor());
+ foreach (const KeyRow &row, rowList) {
+ // rowHasSecondaryLabel is needed for the vertical alignment of
+ // secondary label purposes.
+ bool rowHasSecondaryLabel = false;
+ foreach (const MImKey *key, row.keys) {
+ if (!key->secondaryLabel().isEmpty()) {
+ rowHasSecondaryLabel = true;
+ break;
}
}
- kp.drawIcons();
+ foreach (MImKey *key, row.keys) {
+ painter->setFont(key->font());
+ key->setSecondaryLabelEnabled(rowHasSecondaryLabel);
- if (style->drawReactiveAreas()) {
- drawDebugReactiveAreas(currentPainter);
+ QRectF rect = mapFromItem(key, key->labelRect()).boundingRect();
+ painter->drawText(rect, Qt::AlignCenter, key->label());
}
}
- if (hasCachedBackground) {
- onScreenPainter->drawPixmap(boundingRect().toRect(), *cachedBackground.get());
- }
-
- KeyPainter kp(this, onScreenPainter, KeyPainter::PaintBackground);
- MImAbstractKey::visitActiveKeys(&kp);
- kp.drawIcons();
-
- if (textDirty) {
- buildTextLayout();
+ painter->setFont(style->secondaryFont());
+ foreach (const KeyRow &row, rowList) {
+ foreach (const MImKey *key, row.keys) {
+ if (!key->secondaryLabel().isEmpty()) {
+ QRectF rect = mapFromItem(key, key->secondaryLabelRect()).boundingRect();
+ painter->drawText(rect, Qt::AlignCenter, key->secondaryLabel());
+ }
+ }
}
+ painter->restore();
- // Draw text next.
- onScreenPainter->setPen(style->fontColor());
- textLayout.draw(onScreenPainter, QPoint(WidthCorrection, 0));
-
- cachedBackgroundDirty = false;
mTimestamp("MImKeyArea", "end");
}
@@ -740,44 +563,23 @@
{
painter->save();
- for (int rowIdx = 0; rowIdx < rowList.size(); ++rowIdx) {
- QPair<qreal, qreal> rowPair = rowOffsets[rowIdx];
- painter->setPen(Qt::darkMagenta);
- painter->drawLine(QPointF(0, rowPair.first),
- QPointF(size().width(), rowPair.first));
-
- painter->setPen(Qt::magenta);
- painter->drawLine(QPointF(0, rowPair.second),
- QPointF(size().width(), rowPair.second));
+ foreach (const KeyRow &row, rowList) {
+ foreach (const MImKey *const key, row.keys) {
+ const QRectF rect = correctedReactionRect(key->buttonBoundingRect());
- const QVector<QPair<qreal, qreal> > &keyOffsets = rowList[rowIdx].keyOffsets;
+ painter->setPen(Qt::magenta);
+ painter->drawLine(rect.topLeft(), rect.topRight());
+ painter->drawLine(rect.bottomLeft(), rect.bottomRight());
- for(int colIdx = 0; colIdx < keyOffsets.size(); ++colIdx) {
- QPair<qreal, qreal> colPair = keyOffsets[colIdx];
painter->setPen(Qt::cyan);
- painter->drawLine(QPointF(colPair.first, rowPair.first),
- QPointF(colPair.first, rowPair.second));
-
- painter->setPen(Qt::darkCyan);
- painter->drawLine(QPointF(colPair.second, rowPair.first),
- QPointF(colPair.second, rowPair.second));
+ painter->drawLine(rect.topLeft(), rect.bottomLeft());
+ painter->drawLine(rect.topRight(), rect.bottomRight());
}
}
painter->restore();
}
-void MImKeyArea::initCachedBackground(const QSize &newSize)
-{
- if (cachedBackground.get() && newSize == cachedBackground->size()) {
- return; // already initialized
- }
-
- cachedBackground.reset(new QPixmap(newSize));
- cachedBackground->fill(Qt::transparent);
- hasCachedBackground = false;
-}
-
MImAbstractKey *MImKeyArea::keyAt(const QPoint &pos) const
{
const int numRows = rowList.count();
@@ -823,7 +625,7 @@
}
}
- textDirty = true;
+ update();
}
void MImKeyArea::updateKeyGeometries(const int newAvailableWidth)
@@ -838,7 +640,6 @@
: newAvailableWidth);
cachedWidgetHeight = computeWidgetHeight();
- initCachedBackground(QSize(effectiveWidth, cachedWidgetHeight));
KeyGeometryUpdater updater = KeyGeometryUpdater(baseStyle(), effectiveWidth,
computeMaxNormalizedWidth());
@@ -868,7 +669,7 @@
mRelativeKeyBaseWidth = updater.relativeKeyWidth();
// Positions may have changed, rebuild text layout.
- textDirty = true;
+ update();
}
QRectF MImKeyArea::boundingRect() const
@@ -953,20 +754,25 @@
{
mMaxNormalizedWidth = computeMaxNormalizedWidth();
cachedWidgetHeight = computeWidgetHeight();
+ stylingCache->primary = QFontMetrics(baseStyle()->font());
+ stylingCache->secondary = QFontMetrics(baseStyle()->secondaryFont());
- MImAbstractKeyArea::onThemeChangeCompleted();
- buildTextLayout();
-}
+ foreach (const KeyRow &row, rowList) {
+ foreach (MImKey *key, row.keys) {
+ if (key) {
+ key->invalidateLabelPos();
+ }
+ }
+ }
-void MImKeyArea::handleVisibilityChanged(bool)
-{
- invalidateBackgroundCache();
+ MImAbstractKeyArea::onThemeChangeCompleted();
+ update();
}
-void MImKeyArea::invalidateBackgroundCache()
+void MImKeyArea::applyStyle()
{
- cachedBackgroundDirty = true;
- hasCachedBackground = false;
+ stylingCache->primary = QFontMetrics(baseStyle()->font());
+ stylingCache->secondary = QFontMetrics(baseStyle()->secondaryFont());
}
QList<const MImAbstractKey *> MImKeyArea::keys() const
@@ -981,3 +787,38 @@
return keyList;
}
+
+MImAbstractKey * MImKeyArea::findKey(const QString &id)
+{
+ MImKey *key = 0;
+
+ for (QList<MImKey *>::const_iterator iterator = idToKey.begin();
+ iterator != idToKey.end();
+ ++iterator) {
+ if ((*iterator)->model().id() == id) {
+ key = *iterator;
+ break;
+ }
+ }
+
+ return key;
+}
+
+void MImKeyArea::clearKeyIds()
+{
+ idToKey.clear();
+}
+
+void MImKeyArea::registerKeyId(MImKey *key)
+{
+ for (QList<MImKey *>::iterator iterator = idToKey.begin();
+ iterator != idToKey.end();
+ ++iterator) {
+ if ((*iterator)->model().id() == key->model().id()) {
+ *iterator = key;
+ return;
+ }
+ }
+ idToKey.append(key);
+}
+
--- m-keyboard/widgets/mimkeyarea.h
+++ m-keyboard/widgets/mimkeyarea.h
@@ -20,10 +20,9 @@
#include "mimabstractkeyarea.h"
#include "mimkey.h"
-#include <QTextLayout>
-#include <QPixmap>
#include <QSize>
-#include <memory>
+#include <QFontMetrics>
+#include <QSharedPointer>
//! \brief MImKeyArea reimplements MImAbstractKeyArea and is optimized for drawing.
class MImKeyArea
@@ -49,6 +48,7 @@
virtual QRectF boundingRect() const;
virtual void setShiftState(ModifierState newShiftState);
virtual QList<const MImAbstractKey *> keys() const;
+ virtual MImAbstractKey * findKey(const QString &id);
//! \reimp_end
protected:
@@ -60,17 +60,13 @@
virtual void updateKeyGeometries(int availableWidth);
virtual MImAbstractKey *keyAt(const QPoint &pos) const;
virtual void onThemeChangeCompleted();
- virtual void handleVisibilityChanged(bool visible);
- virtual void invalidateBackgroundCache();
+ virtual void applyStyle();
//! \reimp_end
private:
//! \brief Creates buttons for key data models.
void loadKeys();
- //! \brief Builds QTextLayout representation of current button labels for faster drawing.
- void buildTextLayout();
-
//! \brief Returns the new height of the key area.
qreal computeWidgetHeight() const;
@@ -99,9 +95,12 @@
//! \param painter the painter to be used
void drawDebugReactiveAreas(QPainter *painter);
- //! \brief Initializes the pixmap used for background caching
- //! \param size the new size
- void initCachedBackground(const QSize &size);
+ //! \brief Clears all information about key identifiers
+ void clearKeyIds();
+
+ //! \brief Register new key having identifier
+ //! \param key Pointer to key which id should be registered
+ void registerKeyId(MImKey *key);
//! \brief Helper struct to store a row of keys.
struct KeyRow {
@@ -118,13 +117,10 @@
qreal mMaxNormalizedWidth; //!< maximal normalized width, for all rows
QVector<QPair<qreal, qreal> > rowOffsets; //!< cached offsets for faster key lookups
MImKey *shiftKey; //!< stores shift key, if available in this key area
- QTextLayout textLayout; //!< used to draw key labels onto key area
- bool textDirty; //!< dirty text cache flag
- std::auto_ptr<QPixmap> cachedBackground; //!< cached background, containing all keys in inactive state
- bool cachedBackgroundDirty; //!< dirty background cache flag
- bool hasCachedBackground; //!< stores whether we already cached the background
bool equalWidthKeys; //!< whether to assume equal width for all keys
int WidthCorrection; //!< width correction for Arabic layouts
+ QSharedPointer<MImKey::StylingCache> stylingCache; //!< Cached information about current styling
+ QList<MImKey *> idToKey; //!< Contains information about keys which have identifiers
#ifdef UNIT_TEST
friend class Ut_MImAbstractKeyArea;
--- m-keyboard/widgets/mimtoolbar.cpp
+++ m-keyboard/widgets/mimtoolbar.cpp
@@ -19,6 +19,7 @@
#include "mimtoolbar.h"
#include "mtoolbarbutton.h"
#include "mtoolbarlabel.h"
+#include "mimreactionmap.h"
#include <mtoolbardata.h>
#include <mtoolbaritem.h>
@@ -42,6 +43,7 @@
MImToolbar::MImToolbar(QGraphicsWidget *parent)
: MStylableWidget(parent),
+ ReactionMapPaintable(),
textSelected(false),
leftBar(this),
rightBar(this),
@@ -59,6 +61,9 @@
connect(this, SIGNAL(visibleChanged()), this, SLOT(arrangeWidgets()));
connect(MTheme::instance(), SIGNAL(themeChangeCompleted()),
this, SLOT(updateFromStyle()));
+
+ // Request a reaction map painting if it appears
+ connect(this, SIGNAL(displayEntered()), &signalForwarder, SIGNAL(requestRepaint()));
}
MImToolbar::~MImToolbar()
@@ -193,19 +198,20 @@
const M::Orientation orientation = MPlainWindow::instance()->sceneManager()->orientation();
QSharedPointer<const MToolbarLayout> layout = currentToolbar->layout(orientation);
- QGraphicsLinearLayout *mainLayout = static_cast<QGraphicsLinearLayout*>(this->layout());
- if (!mainLayout) {
- qCritical() << __PRETTY_FUNCTION__ << "Layout does not exist";
+ if (layout.isNull()) {
+ qWarning() << __PRETTY_FUNCTION__
+ << "Could not find layout in current toolbar. Orientation was:"
+ << orientation;
+ return;
}
-
foreach (QSharedPointer<MToolbarItem> item, layout->items()) {
createAndAppendWidget(item);
}
}
-void MImToolbar::createAndAppendWidget(QSharedPointer<MToolbarItem> item)
+void MImToolbar::createAndAppendWidget(const QSharedPointer<MToolbarItem> &item)
{
MWidget *widget = 0;
WidgetBar *sidebar = 0;
@@ -229,6 +235,13 @@
widget = new MToolbarLabel(item, sidebar);
}
customWidgets.append(widget);
+ // We should update the reaction map if the custom toolbar elements are changing.
+ connect(widget, SIGNAL(geometryChanged()),
+ &signalForwarder, SIGNAL(requestRepaint()), Qt::UniqueConnection);
+ connect(widget, SIGNAL(displayEntered()),
+ &signalForwarder, SIGNAL(requestRepaint()), Qt::UniqueConnection);
+ connect(widget, SIGNAL(displayExited()),
+ &signalForwarder, SIGNAL(requestRepaint()), Qt::UniqueConnection);
if (sidebar->count() == 0) {
// must be done before appending so that isVisible() tells the truth
sidebar->show();
@@ -238,12 +251,6 @@
void MImToolbar::unloadCustomWidgets()
{
- QGraphicsLinearLayout *mainLayout = static_cast<QGraphicsLinearLayout*>(layout());
-
- if (!mainLayout) {
- qCritical() << __PRETTY_FUNCTION__ << "Layout does not exist";
- }
-
qDeleteAll(customWidgets);
customWidgets.clear();
leftBar.cleanup();
@@ -363,8 +370,11 @@
currentToolbar = toolbar;
loadCustomWidgets();
- if (isVisible())
+ if (isVisible()) {
updateVisibility();
+ // The content has been changed -> Repaint the reaction maps
+ signalForwarder.emitRequestRepaint();
+ }
arrangeWidgets();
}
@@ -388,7 +398,7 @@
reactionMap->fillRectangle(boundingRect());
// Draw all widgets geometries.
- reactionMap->setReactiveDrawingValue();
+ reactionMap->setDrawingValue(MImReactionMap::Press, MImReactionMap::Release);
QGraphicsLinearLayout *mainLayout = static_cast<QGraphicsLinearLayout*>(layout());
@@ -407,7 +417,7 @@
// Buttons sometimes require this.
sidebar->layout()->activate();
- reactionMap->setReactiveDrawingValue();
+ reactionMap->setDrawingValue(MImReactionMap::Press, MImReactionMap::Release);
for (int i = 0; i < sidebar->count(); ++i) {
QGraphicsWidget *widget = sidebar->widgetAt(i);
@@ -443,3 +453,12 @@
size().height() + style()->marginTop() + style()->marginBottom());
}
+bool MImToolbar::isPaintable() const
+{
+ return isVisible();
+}
+
+const MToolbarData *MImToolbar::currentToolbarData() const
+{
+ return currentToolbar.data();
+}
--- m-keyboard/widgets/mimtoolbar.h
+++ m-keyboard/widgets/mimtoolbar.h
@@ -23,6 +23,7 @@
#include "widgetbar.h"
#include "mkeyboardcommon.h"
#include "mimtoolbarstyle.h"
+#include "reactionmappaintable.h"
#include <QPointer>
#include <QSharedPointer>
@@ -48,7 +49,7 @@
will be placed into left or right side WidgetBar widget. Toolbar
takes all available space horizontally.
*/
-class MImToolbar : public MStylableWidget
+class MImToolbar : public MStylableWidget, public ReactionMapPaintable
{
Q_OBJECT
@@ -69,14 +70,19 @@
QRegion region() const;
/*!
- * \brief Shows a custom toolbar with unique \a id.
- * Loads a custom toolbar according \a id, if successfuly loads,
+ * \brief Shows a custom toolbar with toolbar definition \a toolbar.
+ * Loads a custom toolbar according \a toolbar, if successfuly loads,
* the toolbar will be visible when show().
- * \param id Unique identifier of the custom toolbar.
+ * \param toolbar The pointer of toolbar definition.
*/
void showToolbarWidget(QSharedPointer<const MToolbarData> toolbar);
/*!
+ * \brief Returns the pointer of current toolbar definition.
+ */
+ const MToolbarData *currentToolbarData() const;
+
+ /*!
* \brief Hides all custom toolbars, this also means they are removed from visible virtual keyboard.
*/
void hideToolbarWidget();
@@ -94,6 +100,7 @@
//! \reimp
virtual QRectF boundingRect() const;
+ bool isPaintable() const;
//! \reimp_end
public slots:
@@ -165,7 +172,7 @@
Qt::KeyboardModifiers keyModifiers(int key) const;
- void createAndAppendWidget(QSharedPointer<MToolbarItem> item);
+ void createAndAppendWidget(const QSharedPointer<MToolbarItem> &item);
bool textSelected;
--- m-keyboard/widgets/mimwordlist.cpp
+++ m-keyboard/widgets/mimwordlist.cpp
@@ -18,17 +18,11 @@
#include "regiontracker.h"
#include "mimwordlist.h"
#include "mimwordlistitem.h"
-#include <mplainwindow.h>
#include <QGraphicsLinearLayout>
#include <QDebug>
#include <QString>
-#include <MSceneManager>
-#include <MScene>
-#include <MGConfItem>
-#include <MContentItem>
-#include <MTheme>
#include <mreactionmap.h>
#include <mwidgetcreator.h>
@@ -39,39 +33,11 @@
const char * const WordListObjectName = "CorrectionWordList";
};
-MIMWordListWindow::MIMWordListWindow(MImWordList *widget)
- : MImOverlay(),
- listWidget(widget)
-{
- setVisible(false);
-}
-
-bool MIMWordListWindow::sceneEvent(QEvent *e)
-{
- // TODO: below hiding list widget could be removed when meegotouch
- // decide not hiding dialog when tap outside.
- if (e->type() == QEvent::GraphicsSceneMouseRelease) {
- listWidget->disappear();
- }
- return MImOverlay::sceneEvent(e);
-}
-
-void MIMWordListWindow::handleListAppeared()
-{
- setVisible(true);
- listWidget->setParentItem(this);
-}
-
-void MIMWordListWindow::handleListDisappeared()
-{
- setVisible(false);
-}
MImWordList::MImWordList()
- : MDialog(),
- parentWindow(new MIMWordListWindow(this))
+ : MDialog()
{
- RegionTracker::instance().addRegion(*this);
+ RegionTracker::instance().addRegion(*this);
// for MATTI
setObjectName(WordListObjectName);
@@ -89,18 +55,10 @@
}
setCentralWidget(contentWidget);
hide();
-
- connect(this, SIGNAL(appeared()),
- parentWindow, SLOT(handleListAppeared()));
- connect(this, SIGNAL(disappeared()),
- parentWindow, SLOT(handleListDisappeared()));
}
MImWordList::~MImWordList()
{
- setParentItem(0);
- delete parentWindow;
- parentWindow = 0;
}
void MImWordList::setCandidates(const QStringList &candidates)
--- m-keyboard/widgets/mimwordlist.h
+++ m-keyboard/widgets/mimwordlist.h
@@ -19,48 +19,12 @@
#define MIMWORDLIST_H
#include <MDialog>
-#include "mimoverlay.h"
class QGraphicsLinearLayout;
-class MContentItem;
class MImWordListItem;
-class MImWordList;
class MReactionMap;
/*!
- * \brief MIMWordListWindow is used as the plain translucent parent window for word list dialog.
- *
- * MIMWordListWindow prevents mouse and touch events from reaching the virtual keyboard or the application.
- * \sa MImOverlay.
- */
-class MIMWordListWindow : public MImOverlay
-{
- Q_OBJECT
-public:
- //! Constructor
- explicit MIMWordListWindow(MImWordList *widget);
-
-public slots:
- /*
- * \brief This slot is connected with word list widget's appeared() signal.
- */
- void handleListAppeared();
-
- /*
- * \brief This slot is connected with word list widget's disappeared() signal.
- */
- void handleListDisappeared();
-
-protected:
- /*! \reimp */
- virtual bool sceneEvent(QEvent *event);
- /*! \reimp_end */
-
-private:
- MImWordList *listWidget;
-};
-
-/*!
* \brief MIMWordList is used for word list dialog.
*
* MImWordList shows a dialog which list the suggested candidates.
@@ -116,7 +80,6 @@
QStringList mCandidates;
QGraphicsLinearLayout *mainLayout;
MImWordListItem *candidateItems[MaxCandidateCount];
- MIMWordListWindow *parentWindow;
};
#endif
--- m-keyboard/widgets/mimwordtracker.cpp
+++ m-keyboard/widgets/mimwordtracker.cpp
@@ -19,6 +19,7 @@
#include "regiontracker.h"
#include "mimwordtracker.h"
#include "mimcorrectioncandidateitem.h"
+#include "mimreactionmap.h"
#include <QGraphicsLinearLayout>
#include <QDebug>
@@ -280,6 +281,6 @@
reactionMap->fillRectangle(geometry());
// Draw the actual word tracker area.
- reactionMap->setReactiveDrawingValue();
+ reactionMap->setDrawingValue(MImReactionMap::Press, MImReactionMap::Release);
reactionMap->fillRectangle(geometry());
}
--- m-keyboard/widgets/mkeyboardsettingswidget.cpp
+++ m-keyboard/widgets/mkeyboardsettingswidget.cpp
@@ -154,10 +154,10 @@
correctionSpaceSwitch->setViewType(MButton::switchType);
correctionSpaceSwitch->setCheckable(true);
correctionSpaceContentItem = new MContentItem(MContentItem::TwoTextLabels, this);
- //% "Select with space"
- correctionSpaceContentItem->setTitle(qtTrId("qtn_txts_select_with_space"));
- //% "Select with space description"
- correctionSpaceContentItem->setSubtitle(qtTrId("qtn_txts_select_with_space_description"));
+ //% "Insert with space"
+ correctionSpaceContentItem->setTitle(qtTrId("qtn_txts_insert_with_space"));
+ //% "Insert with space description"
+ correctionSpaceContentItem->setSubtitle(qtTrId("qtn_txts_insert_with_space_description"));
QGraphicsLinearLayout *wCLayout = new QGraphicsLinearLayout(Qt::Horizontal);
wCLayout->addItem(correctionSpaceContentItem);
wCLayout->addItem(correctionSpaceSwitch);
@@ -186,8 +186,8 @@
errorCorrectionContentItem->setTitle(qtTrId("qtn_txts_error_correction"));
errorCorrectionContentItem->setSubtitle(qtTrId("qtn_txts_error_correction_description"));
- correctionSpaceContentItem->setTitle(qtTrId("qtn_txts_select_with_space"));
- correctionSpaceContentItem->setSubtitle(qtTrId("qtn_txts_select_with_space_description"));
+ correctionSpaceContentItem->setTitle(qtTrId("qtn_txts_insert_with_space"));
+ correctionSpaceContentItem->setSubtitle(qtTrId("qtn_txts_insert_with_space_description"));
QStringList keyboards = settingsObject->selectedKeyboards().values();
//% "Installed keyboards (%1)"
QString title = qtTrId("qtn_txts_installed_keyboards")
@@ -228,18 +228,25 @@
connect(settingsObject, SIGNAL(correctionSpaceChanged()),
this, SLOT(syncCorrectionSpaceState()));
connect(settingsObject, SIGNAL(selectedKeyboardsChanged()),
- this, SLOT(updateTitle()));
- connect(settingsObject, SIGNAL(selectedKeyboardsChanged()),
this, SLOT(updateKeyboardSelectionModel()));
}
void MKeyboardSettingsWidget::showKeyboardList()
{
- if (!settingsObject || !keyboardDialog) {
- QStringList keyboards = settingsObject->selectedKeyboards().values();
- QString keyboardTitle = qtTrId("qtn_txts_installed_keyboards")
- .arg(keyboards.count());
- keyboardDialog = new MDialog(keyboardTitle, M::NoStandardButton);
+ if (!settingsObject)
+ return;
+
+ QStringList keyboards = settingsObject->selectedKeyboards().values();
+
+ // This is the ugly hack to avoid the crash of the VKB settings since the
+ // toolkit fixes and releases NB#230358.
+ // The basic problem is that the model selection update crashes second time
+ // when we try to reuse the same keyboard list to show the dialog again.
+ delete keyboardDialog;
+ keyboardDialog = 0;
+
+ if (!keyboardDialog) {
+ keyboardDialog = new MDialog();
keyboardList = new MList(keyboardDialog);
MKeyboardCellCreator *cellCreator = new MKeyboardCellCreator;
@@ -250,11 +257,19 @@
keyboardList->setSelectionMode(MList::MultiSelection);
keyboardList->setSelectionModel(new QItemSelectionModel(model, this));
keyboardDialog->setCentralWidget(keyboardList);
+ keyboardDialog->addButton(M::DoneButton);
connect(keyboardList, SIGNAL(itemClicked(const QModelIndex &)),
this, SLOT(updateSelectedKeyboards(const QModelIndex &)));
+ connect(keyboardDialog, SIGNAL(accepted()),
+ this, SLOT(selectKeyboards()));
}
updateKeyboardModel();
+ // We need to update the title every time because probably the dialog was
+ // cancelled/closed without tapping on the Done button.
+ QString keyboardTitle = qtTrId("qtn_txts_installed_keyboards")
+ .arg(keyboards.count());
+ keyboardDialog->setTitle(keyboardTitle);
keyboardDialog->exec();
}
@@ -296,18 +311,35 @@
void MKeyboardSettingsWidget::updateSelectedKeyboards(const QModelIndex &index)
{
- if (!settingsObject || !index.isValid() || !keyboardList
+ if (!index.isValid() || !keyboardDialog || !keyboardList
|| !keyboardList->selectionModel())
return;
+ QModelIndexList indexList = keyboardList->selectionModel()->selectedIndexes();
+
+ // Update the dialog title
+ QString title = qtTrId("qtn_txts_installed_keyboards")
+ .arg(indexList.size());
+
+ keyboardDialog->setTitle(title);
+}
+
+void MKeyboardSettingsWidget::selectKeyboards()
+{
+ if (!settingsObject || !keyboardDialog)
+ return;
+
QStringList updatedKeyboardLayouts;
- foreach (const QModelIndex &i, keyboardList->selectionModel()->selectedIndexes()) {
+ QModelIndexList indexList = keyboardList->selectionModel()->selectedIndexes();
+
+ foreach (const QModelIndex &i, indexList) {
updatedKeyboardLayouts << i.data(MKeyboardLayoutRole).toString();
}
- if (updatedKeyboardLayouts.isEmpty()) {
+ settingsObject->setSelectedKeyboards(updatedKeyboardLayouts);
+ // "No keyboard is selected" notification
+ if (indexList.isEmpty()) {
notifyNoKeyboards();
}
- settingsObject->setSelectedKeyboards(updatedKeyboardLayouts);
//update titles
retranslateUi();
}
--- m-keyboard/widgets/mkeyboardsettingswidget.h
+++ m-keyboard/widgets/mkeyboardsettingswidget.h
@@ -48,6 +48,7 @@
void updateTitle();
void updateKeyboardSelectionModel();
void updateSelectedKeyboards(const QModelIndex &);
+ void selectKeyboards();
void setErrorCorrectionState(bool enabled);
void syncErrorCorrectionState();
void setCorrectionSpaceState(bool enabled);
--- m-keyboard/widgets/mvirtualkeyboard.cpp
+++ m-keyboard/widgets/mvirtualkeyboard.cpp
@@ -28,6 +28,7 @@
#include "mimabstractkey.h"
#include "keyevent.h"
#include "grip.h"
+#include "reactionmappainter.h"
#include "regiontracker.h"
#include <mtoolbardata.h>
@@ -60,6 +61,7 @@
const MVirtualKeyboardStyleContainer *styleContainer,
QGraphicsWidget *parent)
: MWidget(parent),
+ ReactionMapPaintable(),
styleContainer(styleContainer),
mainLayout(new QGraphicsLinearLayout(Qt::Vertical, this)),
currentLevel(0),
@@ -123,6 +125,9 @@
keyboardsReset(); // creates keyboard widgets
organizeContent(currentOrientation);
+
+ // Request a reaction map painting if it appears
+ connect(this, SIGNAL(displayEntered()), &signalForwarder, SIGNAL(requestRepaint()));
}
@@ -249,6 +254,10 @@
return MWidget::itemChange(change, value);
}
+bool MVirtualKeyboard::isPaintable() const
+{
+ return isVisible();
+}
void MVirtualKeyboard::resetState()
{
@@ -481,9 +490,6 @@
void MVirtualKeyboard::onSectionSwitched(QGraphicsWidget */*previous*/, QGraphicsWidget */*current*/)
{
organizeContent(currentOrientation);
- // We (probably) need to redraw reaction map even if the region doesn't
- // change, buttons may be positioned differently
- RegionTracker::instance().requestReactionMapUpdate();
}
@@ -501,6 +507,9 @@
this, SLOT(onSectionSwitchStarting(int, int)));
connect(mainKeyboardSwitcher, SIGNAL(switchDone(QGraphicsWidget *, QGraphicsWidget *)),
this, SLOT(onSectionSwitched(QGraphicsWidget *, QGraphicsWidget *)));
+ // Repaint the reaction maps if the keyboard is changed
+ connect(mainKeyboardSwitcher, SIGNAL(switchDone(QGraphicsWidget *, QGraphicsWidget *)),
+ &signalForwarder, SIGNAL(requestRepaint()));
}
@@ -725,6 +734,13 @@
// resize and update keyboards if needed
organizeContent(currentOrientation);
+
+ // Request a reaction map repainting when the first keyboard is loaded or
+ // the keyboard is changed between normal, phone and number layouts.
+ if (previousWidget != newWidget) {
+ signalForwarder.emitRequestRepaint();
+ }
+
}
QList<MImEngine::KeyboardLayoutKey> MVirtualKeyboard::mainLayoutKeys() const
--- m-keyboard/widgets/mvirtualkeyboard.h
+++ m-keyboard/widgets/mvirtualkeyboard.h
@@ -23,6 +23,7 @@
#include "mkeyboardcommon.h"
#include "mimkeyarea.h"
#include "layoutdata.h"
+#include "reactionmappaintable.h"
#include <minputmethodnamespace.h>
#include <MWidget>
@@ -61,7 +62,7 @@
It also provides interfaces to get keystatus
*/
-class MVirtualKeyboard : public MWidget
+class MVirtualKeyboard : public MWidget, public ReactionMapPaintable
{
Q_OBJECT
Q_PROPERTY(QString layoutLanguage READ layoutLanguage)
@@ -147,6 +148,7 @@
//! reimp
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+ bool isPaintable() const;
//! reimp_end
//! \return region occupied by keyboard in scene coordinates
@@ -376,8 +378,8 @@
Notification *notification;
- QGraphicsWidget *numberKeyboard;
- QGraphicsWidget *phoneNumberKeyboard;
+ MImAbstractKeyArea *numberKeyboard;
+ MImAbstractKeyArea *phoneNumberKeyboard;
QSharedPointer<QPixmap> backgroundPixmap;
--- m-keyboard/widgets/popupfactory.cpp
+++ m-keyboard/widgets/popupfactory.cpp
@@ -28,15 +28,15 @@
}
// dummy popup to be used if no plugin is found
-class DummyPopup: public PopupBase
+class MockPopup: public PopupBase
{
public:
- explicit DummyPopup(MImAbstractKeyArea *mainArea)
+ explicit MockPopup(MImAbstractKeyArea *mainArea)
: PopupBase(mainArea),
visible(false)
{}
- virtual ~DummyPopup()
+ virtual ~MockPopup()
{}
//! \reimp
@@ -86,8 +86,12 @@
PopupBase *PopupFactory::createPopup(MImAbstractKeyArea *mainArea) const
{
+#ifdef UNIT_TEST
+ return new MockPopup(mainArea);
+#else
return (plugin ? plugin->createPopup(mainArea)
- : new DummyPopup(mainArea));
+ : new MockPopup(mainArea));
+#endif
}
PopupFactory::PopupFactory()
--- m-keyboard/widgets/reactionmappaintable.cpp
+++ m-keyboard/widgets/reactionmappaintable.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "reactionmappaintable.h"
+
+#include "reactionmappainter.h"
+
+void ReactionMapPaintableSignaler::emitRequestRepaint()
+{
+ emit requestRepaint();
+}
+
+ReactionMapPaintable::ReactionMapPaintable()
+{
+ ReactionMapPainter::instance().addWidget(*this);
+}
+
+ReactionMapPaintable::~ReactionMapPaintable()
+{
+ ReactionMapPainter::instance().removeWidget(*this);
+}
+
+bool ReactionMapPaintable::isFullScreen() const
+{
+ // Most of the widgets do not occupy the full screen.
+ return false;
+};
--- m-keyboard/widgets/reactionmappaintable.h
+++ m-keyboard/widgets/reactionmappaintable.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef REACTIONMAPPAINTABLE_H
+#define REACTIONMAPPAINTABLE_H
+
+#include <QObject>
+
+class MReactionMap;
+class QGraphicsView;
+
+//! \brief A helper class for reaction map painting to enable signals in ReactionMapPaintable
+class ReactionMapPaintableSignaler : public QObject
+{
+ Q_OBJECT
+
+public:
+ //! \brief Emit a request for reaction map repainting
+ void emitRequestRepaint();
+
+signals:
+ //! \brief Request a reaction map repainting
+ void requestRepaint();
+
+ //! \brief Request a reaction map clearing
+ void requestClear();
+};
+
+//! \brief A class for widgets with reaction map painting
+class ReactionMapPaintable
+{
+public:
+ //! \brief Ctor
+ ReactionMapPaintable();
+ //! \brief Dtor
+ virtual ~ReactionMapPaintable();
+
+ //! \brief Paint the reaction map of the widget
+ virtual void paintReactionMap(MReactionMap *, QGraphicsView *) = 0;
+
+ //! \brief Is the widget paintable
+ virtual bool isPaintable() const = 0;
+
+ //! \brief Is the widget full screen
+ virtual bool isFullScreen() const;
+
+ ReactionMapPaintableSignaler signalForwarder;
+};
+
+#endif
--- m-keyboard/widgets/sharedhandlearea.cpp
+++ m-keyboard/widgets/sharedhandlearea.cpp
@@ -55,7 +55,6 @@
mainLayout.addItem(&toolbar);
mainLayout.setAlignment(&toolbar, Qt::AlignCenter);
- connect(&toolbar, SIGNAL(regionUpdated()), this, SLOT(updatePosition()));
connect(this, SIGNAL(visibleChanged()), this, SLOT(updatePosition()));
}
@@ -147,3 +146,12 @@
updatePosition();
}
+bool SharedHandleArea::event(QEvent *e)
+{
+ if (e->type() == QEvent::GraphicsSceneResize) {
+ // when share handler area is resized,need to call updatePosition
+ // to make sure the toolbar in the proper position.
+ updatePosition();
+ }
+ return MWidget::event(e);
+}
--- m-keyboard/widgets/sharedhandlearea.h
+++ m-keyboard/widgets/sharedhandlearea.h
@@ -69,6 +69,11 @@
void flickLeft(const FlickGesture &gesture);
void flickRight(const FlickGesture &gesture);
+protected:
+ // \reimp
+ virtual bool event(QEvent *);
+ // \reimp_end
+
private:
//! Connect signals from a \a handle widget
void connectHandle(const Handle &handle);
--- m-keyboard/widgets/symbolview.cpp
+++ m-keyboard/widgets/symbolview.cpp
@@ -22,6 +22,8 @@
#include "symbolview.h"
#include "grip.h"
#include "mimkeyarea.h"
+#include "reactionmappainter.h"
+#include "mimreactionmap.h"
#include "regiontracker.h"
#include <MSceneManager>
@@ -46,6 +48,7 @@
SymbolView::SymbolView(const LayoutsManager &layoutsManager, const MVirtualKeyboardStyleContainer *style,
const QString &layout, QGraphicsWidget *parent)
: MWidget(parent),
+ ReactionMapPaintable(),
styleContainer(style),
sceneManager(*MPlainWindow::instance()->sceneManager()),
activity(Inactive),
@@ -83,6 +86,9 @@
hide();
setupLayout();
reloadContent();
+
+ // Request a reaction map painting if it appears
+ connect(this, SIGNAL(displayEntered()), &signalForwarder, SIGNAL(requestRepaint()));
}
@@ -358,11 +364,8 @@
void SymbolView::organizeContent()
{
const M::Orientation orientation(sceneManager.orientation());
- const int sceneWidth = sceneManager.visibleSceneSize().width();
- setPreferredWidth(sceneWidth);
- setMaximumWidth(sceneWidth);
- setMinimumWidth(sceneWidth);
+ resize(sceneManager.visibleSceneSize().width(), size().height());
if (currentOrientation != orientation) {
currentOrientation = orientation;
@@ -452,7 +455,7 @@
// after we've been hidden.
if (isVisible()) {
layout()->activate();
- RegionTracker::instance().requestReactionMapUpdate();
+ signalForwarder.emitRequestRepaint();
}
if (pageSwitcher) {
activePage = pageSwitcher->current();
@@ -493,7 +496,7 @@
reactionMap->fillRectangle(mapRectFromScene(rect));
}
- reactionMap->setReactiveDrawingValue();
+ reactionMap->setDrawingValue(MImReactionMap::Press, MImReactionMap::Release);
// Draw current character view.
if (pageSwitcher->currentWidget()) {
@@ -549,6 +552,11 @@
}
}
+bool SymbolView::isPaintable() const
+{
+ return isVisible();
+}
+
void SymbolView::resetCurrentKeyArea(bool resetCapsLock)
{
MImAbstractKeyArea *mainKba = static_cast<MImAbstractKeyArea *>(pageSwitcher->currentWidget());
--- m-keyboard/widgets/symbolview.h
+++ m-keyboard/widgets/symbolview.h
@@ -20,6 +20,7 @@
#include "keyeventhandler.h"
#include "mkeyboardcommon.h"
#include "layoutdata.h"
+#include "reactionmappaintable.h"
#include <minputmethodnamespace.h>
#include <MWidget>
@@ -39,7 +40,7 @@
/*!
* \brief SymbolView is used to show different layouts symbols/upper case/lower case
*/
-class SymbolView : public MWidget
+class SymbolView : public MWidget, public ReactionMapPaintable
{
Q_OBJECT
@@ -95,6 +96,10 @@
*/
void setTemporarilyHidden(bool hidden);
+ /*! \reimp */
+ bool isPaintable() const;
+ /*! \reimp_end */
+
public slots:
/*!
* Handler to show the page.
--- m-keyboard/widgets/widgets.pri
+++ m-keyboard/widgets/widgets.pri
@@ -9,6 +9,7 @@
$$WIDGETS_DIR/mimkeyvisitor.h \
$$WIDGETS_DIR/mimkey.h \
$$WIDGETS_DIR/mimkeyarea.h \
+ $$WIDGETS_DIR/reactionmappaintable.h \
PUBLIC_STYLE_HEADERS += \
$$WIDGETS_DIR/mvirtualkeyboardstyle.h \
@@ -81,6 +82,7 @@
$$WIDGETS_DIR/mkeyboardsettingswidget.cpp \
$$WIDGETS_DIR/mimoverlay.cpp \
$$WIDGETS_DIR/mtoolbarlabelview.cpp \
+ $$WIDGETS_DIR/reactionmappaintable.cpp \
INCLUDEPATH += $$WIDGETS_DIR
DEPENDPATH += $$WIDGETS_DIR
--- tests/ut_mhardwarekeyboard/ut_mhardwarekeyboard.cpp
+++ tests/ut_mhardwarekeyboard/ut_mhardwarekeyboard.cpp
@@ -210,18 +210,20 @@
bool Ut_MHardwareKeyboard::filterKeyRelease(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
const QString &text,
- quint32 nativeScanCode, quint32 nativeModifiers) const
+ quint32 nativeScanCode, quint32 nativeModifiers,
+ unsigned long time) const
{
return m_hkb->filterKeyEvent(QEvent::KeyRelease, keyCode, modifiers, text, false, 1, nativeScanCode,
- nativeModifiers);
+ nativeModifiers, time);
}
bool Ut_MHardwareKeyboard::filterKeyPress(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
const QString &text,
- quint32 nativeScanCode, quint32 nativeModifiers) const
+ quint32 nativeScanCode, quint32 nativeModifiers,
+ unsigned long time) const
{
return m_hkb->filterKeyEvent(QEvent::KeyPress, keyCode, modifiers, text, false, 1, nativeScanCode,
- nativeModifiers);
+ nativeModifiers, time);
}
bool Ut_MHardwareKeyboard::checkLatchedState(const unsigned int mask, const unsigned int value) const
@@ -1045,6 +1047,7 @@
QCOMPARE(inputMethodHost->lastPreeditString(), QString("1"));
QCOMPARE(inputMethodHost->lastCommitString().length(), 0);
m_hkb->handleLongPressTimeout();
+ m_hkb->longPressTimer.stop();
QCOMPARE(inputMethodHost->lastPreeditString().length(), 1);
QCOMPARE(inputMethodHost->lastPreeditString(), QString("1"));
QVERIFY(filterKeyRelease(Qt::Key_Q, Qt::GroupSwitchModifier, "1", KeycodeCharacter1, FnModifierMask));
@@ -1067,6 +1070,7 @@
QCOMPARE(inputMethodHost->lastPreeditString().length(), 1);
QCOMPARE(inputMethodHost->lastPreeditString(), QString("1"));
m_hkb->handleLongPressTimeout();
+ m_hkb->longPressTimer.stop();
QCOMPARE(inputMethodHost->lastPreeditString().length(), 1);
QCOMPARE(inputMethodHost->lastPreeditString(), QString("1"));
QVERIFY(filterKeyRelease(Qt::Key_Q, Qt::GroupSwitchModifier, "1", KeycodeCharacter1, FnModifierMask));
@@ -1090,6 +1094,7 @@
QCOMPARE(inputMethodHost->lastPreeditString().length(), 1);
QCOMPARE(inputMethodHost->lastPreeditString(), QString("0"));
m_hkb->handleLongPressTimeout();
+ m_hkb->longPressTimer.stop();
QCOMPARE(inputMethodHost->lastPreeditString().length(), 1);
QCOMPARE(inputMethodHost->lastPreeditString(), QString("p"));
QVERIFY(filterKeyRelease(Qt::Key_P, Qt::GroupSwitchModifier, "1", KeycodeCharacter0, FnModifierMask));
@@ -1460,4 +1465,23 @@
QCOMPARE(inputMethodHost->lastCommitString(), QString("1"));
}
+
+void Ut_MHardwareKeyboard::testLongPressUndo()
+{
+ // Simulate press and release actions/events at times 0 and 100 (the last parameter),
+ // which implies a time difference less than the long press time (so the end result
+ // must be "f"), but with a delivery time difference of 1500ms, which is more than the
+ // long press time (so long press processing is done and we temporarily get "1" as the
+ // pre-edit).
+ QVERIFY(filterKeyPress(Qt::Key_F, Qt::NoModifier, "f", KeycodeCharacterF, 0, 0));
+ QCOMPARE(inputMethodHost->lastPreeditString().length(), 1);
+ QCOMPARE(inputMethodHost->lastPreeditString(), QString("f"));
+ QTest::qWait(1500); // more than long press time
+ QCOMPARE(inputMethodHost->lastPreeditString().length(), 1);
+ QCOMPARE(inputMethodHost->lastPreeditString(), QString("1"));
+ QVERIFY(filterKeyRelease(Qt::Key_F, Qt::NoModifier, "f", KeycodeCharacterF, 0, 100));
+ QCOMPARE(inputMethodHost->lastCommitString().length(), 1);
+ QCOMPARE(inputMethodHost->lastCommitString(), QString("f"));
+}
+
QTEST_APPLESS_MAIN(Ut_MHardwareKeyboard);
--- tests/ut_mhardwarekeyboard/ut_mhardwarekeyboard.h
+++ tests/ut_mhardwarekeyboard/ut_mhardwarekeyboard.h
@@ -80,6 +80,8 @@
void testPressTwoKeys();
void testPressTwoKeysWithLatch();
+ void testLongPressUndo();
+
private:
bool checkLatchedState(unsigned int mask, unsigned int value) const;
bool checkLockedState(unsigned int mask, unsigned int value) const;
@@ -87,9 +89,11 @@
// Wrappers for MHardwareKeyboard::filterKeyEvent() to make calls shorter
bool filterKeyRelease(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
- const QString &text, quint32 nativeScanCode, quint32 nativeModifiers) const;
+ const QString &text, quint32 nativeScanCode, quint32 nativeModifiers,
+ unsigned long time = 0) const;
bool filterKeyPress(Qt::Key keyCode, Qt::KeyboardModifiers modifiers,
- const QString &text, quint32 nativeScanCode, quint32 nativeModifiers) const;
+ const QString &text, quint32 nativeScanCode, quint32 nativeModifiers,
+ unsigned long time = 0) const;
};
#endif
--- tests/ut_mimabstractkeyarea/layouts/test-layout.xml
+++ tests/ut_mimabstractkeyarea/layouts/test-layout.xml
@@ -42,7 +42,7 @@
<binding accented_labels="óö" accents="´¨" label="o"/>
<binding shift="true" accented_labels="ÓÖ" accents="´¨" label="O"/>
</key>
- <key>
+ <key id="actionKey">
<binding label="p"/>
<binding shift="true" label="P"/>
</key>
@@ -153,7 +153,7 @@
<binding label="."/>
<binding shift="true" label=","/>
</key>
- <key>
+ <key id="actionKey">
<binding action="return" label=""/>
</key>
</row>
--- tests/ut_mimabstractkeyarea/ut_mimabstractkeyarea.cpp
+++ tests/ut_mimabstractkeyarea/ut_mimabstractkeyarea.cpp
@@ -77,6 +77,7 @@
{
return new MImKeyArea(section, usePopup, parent);
}
+
}
void Ut_MImAbstractKeyArea::initTestCase()
@@ -510,6 +511,27 @@
QCOMPARE(eKey->model().binding(true)->extendedLabels(), QString("%1%2").arg(QChar(0xca)).arg(QChar(0xc8)));
}
+void Ut_MImAbstractKeyArea::testKeyId()
+{
+ keyboard = new KeyboardData;
+ QVERIFY(keyboard->loadNokiaKeyboard("test-layout.xml"));
+ subject = createKeyArea(keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
+ false, 0);
+
+ const MImAbstractKey *enterKey(keyAt(3, 6));
+ QCOMPARE(enterKey->model().binding(false)->action(), MImKeyBinding::ActionReturn);
+ QCOMPARE(enterKey->model().id(), QString("actionKey"));
+
+ const MImAbstractKey *dotKey(keyAt(3, 5));
+ QCOMPARE(dotKey->model().id(), QString());
+
+ MImAbstractKey *found = subject->findKey("invalid-id");
+ QVERIFY(found == 0);
+
+ found = subject->findKey("actionKey");
+ QVERIFY(found == enterKey);
+}
+
void Ut_MImAbstractKeyArea::testImportedLayouts_data()
{
QTest::addColumn<KBACreator>("createKba");
@@ -876,7 +898,7 @@
{
const int margin = 5;
const QSize size(50, 50);
- subject = Ut_MImAbstractKeyArea::createArea(false, "Q", size, QSize(size.width() - 2 * margin,
+ subject = Ut_MImAbstractKeyArea::createArea("Q", size, QSize(size.width() - 2 * margin,
size.height() - 2 * margin));
MImAbstractKeyAreaStyle *s = const_cast<MImAbstractKeyAreaStyle *>(subject->style().operator->());
@@ -1062,7 +1084,7 @@
QFETCH(TpList, touchPoints);
QFETCH(TpButtonStateMatrix, expectedStates);
- subject = Ut_MImAbstractKeyArea::createArea(false, labels, kbaSize);
+ subject = Ut_MImAbstractKeyArea::createArea(labels, kbaSize);
QSignalSpy spy(subject, SIGNAL(keyClicked(const MImAbstractKey*, QString, bool, QPoint)));
ButtonList tracedButtons;
@@ -1103,8 +1125,9 @@
{
const int margin = 5;
const QSize size(50, 50);
- subject = Ut_MImAbstractKeyArea::createArea(true, "Q", size, QSize(size.width() - 2 * margin,
- size.height() - 2 * margin));
+ subject = Ut_MImAbstractKeyArea::createArea("Q", size, QSize(size.width() - 2 * margin,
+ size.height() - 2 * margin),
+ true);
TpCreator createTp = &MImAbstractKeyArea::createTouchPoint;
@@ -1126,11 +1149,6 @@
subject->reset();
QCOMPARE(key->touchPointCount(), 0);
- // FIXME: the timeout for popup become invisible after cancel
- // depends on popop implementation. And if we use dummpy popup,
- // the popup will become invisible immediately. But here we don't
- // know what the popup plugin is used.
- QTest::qWait(200);
QVERIFY(!subject->popup().isVisible());
}
@@ -1169,10 +1187,10 @@
return key;
}
-MImAbstractKeyArea *Ut_MImAbstractKeyArea::createArea(bool usePopup,
- const QString &labels,
+MImAbstractKeyArea *Ut_MImAbstractKeyArea::createArea(const QString &labels,
const QSize &size,
- const QSize &fixedNormalKeySize)
+ const QSize &fixedNormalKeySize,
+ bool usePopup)
{
LayoutData::SharedLayoutSection section;
section = LayoutData::SharedLayoutSection(new LayoutSection(labels));
--- tests/ut_mimabstractkeyarea/ut_mimabstractkeyarea.h
+++ tests/ut_mimabstractkeyarea/ut_mimabstractkeyarea.h
@@ -60,6 +60,7 @@
void testTwoDeadInOne_data();
void testTwoDeadInOne();
void testExtendedLabels();
+ void testKeyId();
void testImportedLayouts_data();
void testImportedLayouts();
void testPopup_data();
@@ -85,10 +86,10 @@
MImAbstractKey *keyAt(unsigned int row,
unsigned int column) const;
- static MImAbstractKeyArea *createArea(bool usePopup,
- const QString &labels,
+ static MImAbstractKeyArea *createArea(const QString &labels,
const QSize &size,
- const QSize &fixedNormalKeySize = QSize(48, 48));
+ const QSize &fixedNormalKeySize = QSize(48, 48),
+ bool usePopup = false);
public:
enum TestOperation {
--- tests/ut_mimabstractkeyarea/ut_mimabstractkeyarea.pro
+++ tests/ut_mimabstractkeyarea/ut_mimabstractkeyarea.pro
@@ -10,8 +10,13 @@
# Input
-HEADERS += ut_mimabstractkeyarea.h
-SOURCES += ut_mimabstractkeyarea.cpp
+HEADERS += ut_mimabstractkeyarea.h \
+ ../../m-keyboard/widgets/popupfactory.h \
+ ../../m-keyboard/widgets/mimabstractkeyarea.h \
+
+SOURCES += ut_mimabstractkeyarea.cpp \
+ ../../m-keyboard/widgets/popupfactory.cpp \
+ ../../m-keyboard/widgets/mimabstractkeyarea.cpp \
VKB_TEST_DATA = layouts/*.xml
vkb_test_data.path = /usr/share/meegotouch/virtual-keyboard/layouts
--- tests/ut_mimcorrectionhost/ut_mimcorrectionhost.cpp
+++ tests/ut_mimcorrectionhost/ut_mimcorrectionhost.cpp
@@ -19,8 +19,10 @@
#include "ut_mimcorrectionhost.h"
#include "mimwordtracker.h"
#include "mimwordlist.h"
-#include <mplainwindow.h>
+#include "reactionmappainter.h"
#include "utils.h"
+
+#include <mplainwindow.h>
#include <QtTest/QTest>
#include <QObject>
#include <QDebug>
@@ -40,6 +42,7 @@
disableQtPlugins();
app = new MApplication(dummyArgc, dummyArgv);
RegionTracker::createInstance();
+ ReactionMapPainter::createInstance();
// MImCorrectionHost uses this internally
new MPlainWindow;
@@ -75,6 +78,7 @@
delete parentWindow;
delete MPlainWindow::instance();
RegionTracker::destroyInstance();
+ ReactionMapPainter::destroyInstance();
delete app;
app = 0;
}
--- tests/ut_mimkey/ut_mimkey.cpp
+++ tests/ut_mimkey/ut_mimkey.cpp
@@ -30,6 +30,8 @@
#include <QSignalSpy>
#include <QDebug>
+#include <memory>
+
Q_DECLARE_METATYPE(QList<Ut_MImKey::DirectionPair>)
Q_DECLARE_METATYPE(Ut_MImKey::KeyList)
Q_DECLARE_METATYPE(QList<Ut_MImKey::KeyTriple>)
@@ -83,6 +85,10 @@
style = new MImAbstractKeyAreaStyleContainer;
style->initialize("", "", 0);
+ stylingCache = QSharedPointer<MImKey::StylingCache>(new MImKey::StylingCache);
+ stylingCache->primary = QFontMetrics((*style)->font());
+ stylingCache->secondary = QFontMetrics((*style)->secondaryFont());
+
parent = new QGraphicsWidget;
dataKey = createKeyModel();
}
@@ -98,7 +104,7 @@
void Ut_MImKey::init()
{
- subject = new MImKey(*dataKey, *style, *parent);
+ subject = new MImKey(*dataKey, *style, *parent, stylingCache);
}
void Ut_MImKey::cleanup()
@@ -158,7 +164,7 @@
MImKeyBinding *binding = new MImKeyBinding;
key->bindings[MImKeyModel::NoShift] = binding;
- MImAbstractKey *subject = new MImKey(*key, *style, *parent);
+ MImAbstractKey *subject = new MImKey(*key, *style, *parent, stylingCache);
for (int i = 0; i < 2; ++i) {
bool isDead = (i != 0);
@@ -341,7 +347,7 @@
b->keyAction = MImKeyBinding::ActionShift;
MImKeyModel *model = new MImKeyModel;
model->bindings[MImKeyModel::NoShift] = b;
- MImKey *shift = new MImKey(*model, *style, *parent);
+ MImKey *shift = new MImKey(*model, *style, *parent, stylingCache);
shift->setDownState(true);
keys << shift;
@@ -359,6 +365,7 @@
const QPointF topLeft(50, 50);
key->setPos(topLeft);
+ key->updateGeometryCache();
QCOMPARE(key->buttonRect().topLeft(), topLeft);
QCOMPARE(key->buttonBoundingRect().topLeft(), topLeft);
@@ -384,7 +391,9 @@
QCOMPARE(key->buttonBoundingRect(), expectedBoundingRect);
key.reset(createKey());
- key->setGeometry(MImKey::Geometry(topLeft, width, height, margin0, margin1, margin1, margin0));
+ key->setGeometry(MImKey::Geometry(width, height, margin0, margin1, margin1, margin0));
+ key->setPos(topLeft);
+ key->updateGeometryCache();
QCOMPARE(key->buttonRect(), expectedRect);
QCOMPARE(key->buttonBoundingRect(), expectedBoundingRect);
}
@@ -405,7 +414,7 @@
MImKey *Ut_MImKey::createKey(bool state)
{
- MImKey *key = new MImKey(*dataKey, *style, *parent);
+ MImKey *key = new MImKey(*dataKey, *style, *parent, stylingCache);
key->setDownState(state);
return key;
}
--- tests/ut_mimkey/ut_mimkey.h
+++ tests/ut_mimkey/ut_mimkey.h
@@ -20,6 +20,7 @@
#define UT_MIMKEY_H
#include <mimabstractkey.h>
+#include <mimkey.h>
#include <QtTest/QTest>
#include <QObject>
@@ -102,6 +103,7 @@
private:
MImKey *createKey(bool state = false);
MImKeyModel *createKeyModel();
+ QSharedPointer<MImKey::StylingCache> stylingCache;
};
Q_DECLARE_METATYPE(Ut_MImKey::DirectionPair)
--- tests/ut_mimtoolbar/ut_mimtoolbar.cpp
+++ tests/ut_mimtoolbar/ut_mimtoolbar.cpp
@@ -25,6 +25,7 @@
#include "layoutsmanager.h"
#include "mreactionmaptester.h"
#include "utils.h"
+#include "reactionmappainter.h"
#include <mplainwindow.h>
#include <mtoolbardata.h>
#include <mtoolbarlayout.h>
@@ -78,6 +79,7 @@
disableQtPlugins();
app = new MApplication(dummyArgc, dummyArgv);
+ ReactionMapPainter::createInstance();
qRegisterMetaType<CopyPasteState>("CopyPasteState");
LayoutsManager::createInstance();
@@ -113,6 +115,7 @@
{
toolbarData.clear();
LayoutsManager::destroyInstance();
+ ReactionMapPainter::destroyInstance();
delete sceneWindow;
delete MPlainWindow::instance();
delete app;
--- tests/ut_mkeyboardhost/minputmethodhoststub.cpp
+++ tests/ut_mkeyboardhost/minputmethodhoststub.cpp
@@ -22,7 +22,9 @@
MInputMethodHostStub::MInputMethodHostStub()
{
clear();
+ predictionValid_ = true;
predictionEnabled_ = true;
+ correctionValid_ = true;
correctionEnabled_ = true;
autoCapitalizationEnabled_ = true;
contentType_ = 0;
@@ -117,13 +119,13 @@
bool MInputMethodHostStub::correctionEnabled(bool &val)
{
- val = true;
+ val = correctionValid_;
return correctionEnabled_;
}
bool MInputMethodHostStub::predictionEnabled(bool &val)
{
- val = true;
+ val = predictionValid_;
return predictionEnabled_;
}
--- tests/ut_mkeyboardhost/minputmethodhoststub.h
+++ tests/ut_mkeyboardhost/minputmethodhoststub.h
@@ -94,7 +94,9 @@
int setInputMethodAreaCalls;
QList<QRegion> inputMethodAreas;
+ bool predictionValid_;
bool predictionEnabled_;
+ bool correctionValid_;
bool correctionEnabled_;
bool autoCapitalizationEnabled_;
int contentType_;
--- tests/ut_mkeyboardhost/ut_mkeyboardhost.cpp
+++ tests/ut_mkeyboardhost/ut_mkeyboardhost.cpp
@@ -56,6 +56,7 @@
const char * const XkbVariantSettingName("/meegotouch/inputmethods/hwkeyboard/variant");
const QString CorrectionSetting("/meegotouch/inputmethods/virtualkeyboard/correctionenabled");
+ const QString CorrectionSettingWithSpace("/meegotouch/inputmethods/virtualkeyboard/correctwithspace");
const QString InputMethodCorrectionEngine("/meegotouch/inputmethods/correctionengine");
const int SceneRotationTime = 1400; // in ms
bool gAutoCapsEnabled = true;
@@ -362,6 +363,7 @@
{
subject->show();
MGConfItem configCorrection(CorrectionSetting);
+ MGConfItem configCorrectionSpace(CorrectionSettingWithSpace);
QVERIFY(subject->imCorrectionEngine != 0);
@@ -379,7 +381,117 @@
QCOMPARE(subject->imCorrectionEngine->completionEnabled(), false);
QCOMPARE(subject->correctionEnabled, false);
+ // Test the correction accepted with space option
+ configCorrectionSpace.set(QVariant(true));
+ QTest::qWait(100);
+ QCOMPARE(subject->correctionAcceptedWithSpaceEnabled, true);
+ configCorrectionSpace.set(QVariant(false));
+ QTest::qWait(100);
+ QCOMPARE(subject->correctionAcceptedWithSpaceEnabled, false);
+
+ subject->hide();
+}
+
+void Ut_MKeyboardHost::testCorrectionSettings_data()
+{
+ QTest::addColumn<bool>("correctionValid");
+ QTest::addColumn<bool>("correctionEnabled");
+ QTest::addColumn<bool>("predictionValid");
+ QTest::addColumn<bool>("predictionEnabled");
+ QTest::addColumn<bool>("result");
+
+ QTest::newRow("Correction and prediction invalid")
+ << false << false << false << false << true;
+ QTest::newRow("Correction invalid, prediction enabled")
+ << false << false << true << true << true;
+ QTest::newRow("Correction invalid, prediction disabled")
+ << false << false << true << false << false;
+ QTest::newRow("Correction enabled, prediction invalid")
+ << true << true << false << false << true;
+ QTest::newRow("Correction disabled, prediction invalid")
+ << true << false << false << false << false;
+ QTest::newRow("Correction disabled, prediction disabled")
+ << true << false << true << false << false;
+ QTest::newRow("Correction disabled, prediction enabled")
+ << true << false << true << true << false;
+ QTest::newRow("Correction enabled, prediction disabled")
+ << true << true << true << false << false;
+ QTest::newRow("Correction enabled, prediction enabled")
+ << true << true << true << true << true;
+}
+
+void Ut_MKeyboardHost::testCorrectionSettings()
+{
+ QFETCH(bool, correctionValid);
+ QFETCH(bool, correctionEnabled);
+ QFETCH(bool, predictionValid);
+ QFETCH(bool, predictionEnabled);
+ QFETCH(bool, result);
+
+ DummyDriverMkh *engine(new DummyDriverMkh);
+ subject->imCorrectionEngine = engine;
+ engine->enableCompletion();
+ engine->enableCorrection();
+
+ subject->show();
+
+ QVERIFY(subject->imCorrectionEngine != 0);
+
+ // Correction comes from MTextEdit inputMethodCorrectionEnabled property.
+ // Prediction comes from Qt::InputMethodHint: Qt::ImhNoPredictiveText.
+ inputMethodHost->correctionValid_ = correctionValid;
+ inputMethodHost->correctionEnabled_ = correctionEnabled;
+ inputMethodHost->predictionValid_ = predictionValid;
+ inputMethodHost->predictionEnabled_ = predictionEnabled;
+ subject->updateCorrectionState();
+ QCOMPARE(subject->correctionEnabled, result);
+
+ subject->hide();
+ delete engine;
+ subject->imCorrectionEngine = 0;
+}
+
+void Ut_MKeyboardHost::testCorrectionContentTypes_data()
+{
+ QTest::addColumn<M::TextContentType>("contentType");
+ QTest::addColumn<bool>("result");
+
+ QTest::newRow("Number field")
+ << M::NumberContentType << false;
+ QTest::newRow("Phone number field")
+ << M::PhoneNumberContentType << false;
+ QTest::newRow("Email field")
+ << M::EmailContentType << false;
+ QTest::newRow("URL field")
+ << M::UrlContentType << false;
+ QTest::newRow("Free text field")
+ << M::FreeTextContentType << true;
+ QTest::newRow("Custom field")
+ << M::CustomContentType << true;
+
+}
+
+void Ut_MKeyboardHost::testCorrectionContentTypes()
+{
+ QFETCH(M::TextContentType, contentType);
+ QFETCH(bool, result);
+
+ DummyDriverMkh *engine(new DummyDriverMkh);
+ subject->imCorrectionEngine = engine;
+ engine->enableCompletion();
+ engine->enableCorrection();
+
+ subject->show();
+
+ QVERIFY(subject->imCorrectionEngine != 0);
+
+ inputMethodHost->contentType_ = contentType;
+ subject->updateCorrectionState();
+ QCOMPARE(subject->correctionEnabled, result);
+
subject->hide();
+ delete engine;
+ subject->imCorrectionEngine = 0;
}
void Ut_MKeyboardHost::testAutoCaps()
@@ -628,7 +740,7 @@
for (int i = 0; i < 5; ++i) {
M::OrientationAngle currentAngle = angles[i % 4];
- im->handleAppOrientationChange(static_cast<int>(currentAngle));
+ im->handleAppOrientationChanged(static_cast<int>(currentAngle));
QTest::qWait(1500);
QCOMPARE(currentAngle, MPlainWindow::instance()->orientationAngle());
}
@@ -779,11 +891,13 @@
subject->correctionHost->setCandidates((QStringList() << "abc" << "def"));
subject->correctionHost->showCorrectionWidget();
++c1;
+ qApp->processEvents();
QCOMPARE(inputMethodHost->setScreenRegionCalls, c1);
QCOMPARE(inputMethodHost->setInputMethodAreaCalls, c2);
subject->correctionHost->hideCorrectionWidget();
++c1;
+ qApp->processEvents();
QCOMPARE(inputMethodHost->setScreenRegionCalls, c1);
QCOMPARE(inputMethodHost->setInputMethodAreaCalls, c2);
QCOMPARE(region(ScreenRegion, c1 - 1), region(InputMethodArea, c2 - 1));
@@ -891,6 +1005,109 @@
#endif
}
+void Ut_MKeyboardHost::testOptimizedRegionCallCounts_data()
+{
+ QTest::addColumn<MInputMethod::HandlerState>("beforeShowState");
+ QTest::addColumn<MInputMethod::HandlerState>("afterShowState");
+
+ // Use -1 to not to care (yet to be optimized).
+ QTest::addColumn<int>("imAreaUpdatesAfterShow");
+ QTest::addColumn<int>("regionUpdatesAfterShow");
+ QTest::addColumn<int>("imAreaUpdatesAfterStateChange");
+ QTest::addColumn<int>("regionUpdatesAfterStateChange");
+
+ QTest::newRow("onscreen -> hardware produces only one update")
+ << MInputMethod::OnScreen
+ << MInputMethod::Hardware
+ << -1 << -1
+ << 1 << 1;
+
+ QTest::newRow("hardware -> onscreen produces only one update")
+ << MInputMethod::OnScreen
+ << MInputMethod::Hardware
+ << -1 << -1
+ << 1 << 1;
+
+ // This basically tests that the region estimate sent is correct and final.
+ QTest::newRow("onscreen state show produces only one update")
+ << MInputMethod::OnScreen
+ << MInputMethod::OnScreen
+ << 1 << 1
+ << -1 << -1;
+
+ QTest::newRow("hardware state show produces only one update")
+ << MInputMethod::Hardware
+ << MInputMethod::Hardware
+ << 1 << 1
+ << -1 << -1;
+}
+
+void Ut_MKeyboardHost::testOptimizedRegionCallCounts()
+{
+ QFETCH(MInputMethod::HandlerState, beforeShowState);
+ QFETCH(MInputMethod::HandlerState, afterShowState);
+ QFETCH(int, imAreaUpdatesAfterShow);
+ QFETCH(int, regionUpdatesAfterShow);
+ QFETCH(int, imAreaUpdatesAfterStateChange);
+ QFETCH(int, regionUpdatesAfterStateChange);
+
+ // This test does not test validity of regions. It tests only
+ // that unnecessary region or input method area updates are not
+ // triggered and forwarded to input method host.
+
+ // On state change we basically have two components affecting region,
+ // vkb widget and shared handle area.
+ // Set minimum height for both so they will affect region.
+ subject->sharedHandleArea->setMinimumHeight(10);
+ subject->vkbWidget->setMinimumHeight(10);
+
+ // Set to inital state.
+ QSet<MInputMethod::HandlerState> state;
+ state << beforeShowState;
+ subject->setState(state);
+
+ inputMethodHost->setInputMethodAreaCalls = 0;
+ inputMethodHost->setScreenRegionCalls = 0;
+
+ // Show plugin in OnScreen state.
+ // Skip animation and update positions directly.
+ subject->show();
+
+ // Speed things up.. animation has to be run because it updates widget positions.
+ subject->slideUpAnimation.pause();
+ subject->slideUpAnimation.setDuration(0);
+ subject->slideUpAnimation.resume();
+ // We need to wait here 200 ms otherwise the test case can fail in lower delays (e.g. 100 ms).
+ QTest::qWait(200);
+ QVERIFY(subject->slideUpAnimation.state() == QAbstractAnimation::Stopped);
+
+ // Check call counts.
+ if (imAreaUpdatesAfterShow >= 0) {
+ QCOMPARE(inputMethodHost->setInputMethodAreaCalls, imAreaUpdatesAfterShow);
+ }
+ if (regionUpdatesAfterShow >= 0) {
+ QCOMPARE(inputMethodHost->setScreenRegionCalls, regionUpdatesAfterShow);
+ }
+
+ // Clear call counts.
+ inputMethodHost->setInputMethodAreaCalls = 0;
+ inputMethodHost->setScreenRegionCalls = 0;
+
+ // Switch to final state.
+ state.clear();
+ state << afterShowState;
+ subject->setState(state);
+
+ // Check call counts.
+ qApp->processEvents();
+ if (imAreaUpdatesAfterStateChange >= 0) {
+ QCOMPARE(inputMethodHost->setInputMethodAreaCalls, imAreaUpdatesAfterStateChange);
+ }
+ if (regionUpdatesAfterStateChange >= 0) {
+ QCOMPARE(inputMethodHost->setScreenRegionCalls, regionUpdatesAfterStateChange);
+ }
+}
+
void Ut_MKeyboardHost::testSetState_data()
{
QSet<MInputMethod::HandlerState> state;
@@ -971,20 +1188,20 @@
spy.clear();
//! first shift key press+release will latch the shift modifier, and then switch the symbolview level to 1
// Note that the native modifier parameters are not correct but that doesn't matter for this test.
- subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0);
- subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0);
+ subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0, 0);
+ subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0, 0);
QCOMPARE(spy.count(), 1);
QCOMPARE(subject->hardwareKeyboard->modifierState(Qt::ShiftModifier), ModifierLatchedState);
QCOMPARE(subject->symbolView->currentLevel(), 1);
// second shift key press+release will lock the shift modifier, shift state changes but symbolview level stays 1
- subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0);
- subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0);
+ subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0, 0);
+ subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0, 0);
QCOMPARE(spy.count(), 3);
QCOMPARE(subject->hardwareKeyboard->modifierState(Qt::ShiftModifier), ModifierLockedState);
QCOMPARE(subject->symbolView->currentLevel(), 1);
//! third shift key press+release will clear the shift modifier, and switch the symbolview level back to 0
- subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0);
- subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0);
+ subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0, 0);
+ subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0, 0);
QCOMPARE(spy.count(), 4);
QCOMPARE(subject->hardwareKeyboard->modifierState(Qt::ShiftModifier), ModifierClearState);
QCOMPARE(subject->symbolView->currentLevel(), 0);
@@ -1324,7 +1541,7 @@
void Ut_MKeyboardHost::rotateToAngle(M::OrientationAngle angle)
{
- subject->handleAppOrientationChange(angle);
+ subject->handleAppOrientationChanged(angle);
QTest::qWait(SceneRotationTime); // wait until rotation animation is finished
}
@@ -1459,13 +1676,13 @@
gShowLockOnInfoBannerCallCount = 0;
for (int i = 0; i < shiftClickedCount; i++) {
- subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0);
- subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0);
+ subject->processKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, QString(""), false, 1, 0, 0, 0);
+ subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_Shift, Qt::ShiftModifier, QString(""), false, 1, 0, 0, 0);
}
for (int i = 0; i < fnClickedCount; i++) {
- subject->processKeyEvent(QEvent::KeyPress, FnLevelKey, Qt::NoModifier, QString(""), false, 1, 0, 0);
- subject->processKeyEvent(QEvent::KeyRelease, FnLevelKey, FnLevelModifier, QString(""), false, 1, 0, 0);
+ subject->processKeyEvent(QEvent::KeyPress, FnLevelKey, Qt::NoModifier, QString(""), false, 1, 0, 0, 0);
+ subject->processKeyEvent(QEvent::KeyRelease, FnLevelKey, FnLevelModifier, QString(""), false, 1, 0, 0, 0);
}
if (deadKeyCharacterCode) {
@@ -1475,9 +1692,9 @@
variantConfig.set(xkbVariant);
subject->processKeyEvent(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier,
- QString(QChar(deadKeyCharacterCode)), false, 1, 0, 0);
+ QString(QChar(deadKeyCharacterCode)), false, 1, 0, 0, 0);
subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_unknown, Qt::NoModifier,
- QString(QChar(deadKeyCharacterCode)), false, 1, 0, 0);
+ QString(QChar(deadKeyCharacterCode)), false, 1, 0, 0, 0);
}
QCOMPARE(inputMethodHost->indicator, expectIndicator);
@@ -1486,9 +1703,9 @@
if (deadKeyCharacterCode) {
// When state is changed from locked -> dead key -> locked, we don't want a notification
subject->processKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier,
- QString("A"), false, 1, 0, 0);
+ QString("A"), false, 1, 0, 0, 0);
subject->processKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier,
- QString("A"), false, 1, 0, 0);
+ QString("A"), false, 1, 0, 0, 0);
QCOMPARE(inputMethodHost->indicator, MInputMethod::LatinLockedIndicator);
QCOMPARE(gShowLockOnInfoBannerCallCount, 1);
}
@@ -1651,6 +1868,20 @@
void Ut_MKeyboardHost::testAutoPunctuation()
{
+ MGConfItem configCorrection(CorrectionSetting);
+ MGConfItem configCorrectionSpace(CorrectionSettingWithSpace);
+
+ QVERIFY(subject->imCorrectionEngine != 0);
+
+ // We need to be sure that the correction is enabled before the test
+ configCorrection.set(QVariant(true));
+ configCorrectionSpace.set(QVariant(true));
+ QTest::qWait(100);
+ QVERIFY(subject->imCorrectionEngine->correctionEnabled());
+ QVERIFY(subject->imCorrectionEngine->completionEnabled());
+ QVERIFY(subject->correctionAcceptedWithSpaceEnabled);
+
+ // Real test case
QFETCH(QChar, character);
QFETCH(bool, autopunctuated);
@@ -1689,6 +1920,9 @@
void Ut_MKeyboardHost::testFastTypingState()
{
+ QSKIP("Skipping fast typing test because the feature is disabled",
+ SkipSingle);
+
// Set timeout to zero for easier testing.
subject->fastTypingTimeout.setInterval(0);
@@ -1702,5 +1936,21 @@
QCOMPARE(inputMethodHost->orientationAngleLocked, false);
}
-QTEST_APPLESS_MAIN(Ut_MKeyboardHost);
+void Ut_MKeyboardHost::testToolbarPosition()
+{
+ // Position after portrait vkb -> hwkb (landscape) transition
+ rotateToAngle(M::Angle90);
+ subject->show();
+
+ QSet<MInputMethod::HandlerState> states;
+ states << MInputMethod::Hardware;
+ subject->setState(states);
+
+ rotateToAngle(M::Angle0);
+ QCOMPARE(subject->sharedHandleArea->pos(),
+ QPointF(0, (MPlainWindow::instance()->visibleSceneSize().height()
+ - subject->sharedHandleArea->size().height())));
+}
+
+QTEST_APPLESS_MAIN(Ut_MKeyboardHost);
--- tests/ut_mkeyboardhost/ut_mkeyboardhost.h
+++ tests/ut_mkeyboardhost/ut_mkeyboardhost.h
@@ -52,6 +52,10 @@
void testDirectMode();
void testNotCrash();
void testCorrectionOptions();
+ void testCorrectionSettings_data();
+ void testCorrectionSettings();
+ void testCorrectionContentTypes_data();
+ void testCorrectionContentTypes();
void testAutoCaps();
void testApplicationOrientationChanged();
@@ -63,6 +67,8 @@
void testSendStringFromToolbar();
void testRegionSignals();
+ void testOptimizedRegionCallCounts_data();
+ void testOptimizedRegionCallCounts();
void testSetState_data();
void testSetState();
@@ -107,6 +113,8 @@
void testFastTypingState();
+ void testToolbarPosition();
+
private:
void rotateToAngle(M::OrientationAngle);
void triggerAutoCaps();
--- tests/ut_mkeyboardhost/ut_mkeyboardhost.pro
+++ tests/ut_mkeyboardhost/ut_mkeyboardhost.pro
@@ -17,11 +17,15 @@
dummydriver_mkh.h \
../stubs/mgconfitem_stub.h \
../stubs/fakegconf.h \
+ $$WIDGETS_DIR/popupfactory.h \
+# PopupFactory needs to be compiled to have a mocked functionality
+# otherwise the unit test crashes
SOURCES += ut_mkeyboardhost.cpp \
minputmethodhoststub.cpp \
dummydriver_mkh.cpp \
../stubs/fakegconf.cpp \
+ $$WIDGETS_DIR/popupfactory.cpp \
target.files += $$TARGET \
toolbar1.xml \
--- tests/ut_mkeyboardsettingswidget/ut_mkeyboardsettingswidget.cpp
+++ tests/ut_mkeyboardsettingswidget/ut_mkeyboardsettingswidget.cpp
@@ -106,6 +106,18 @@
bool firstItemIsSelected = subject->keyboardList->selectionModel()->selectedRows().contains(subject->keyboardList->itemModel()->index(0,0));
subject->keyboardList->selectItem(subject->keyboardList->itemModel()->index(0,0));
QMap<QString, QString> newSelectedKeyboards = settingsObject->selectedKeyboards();
+ // The changes are not committed if the dialog is rejected
+ QCOMPARE(newSelectedKeyboards.count(), selectedKeyboards.count());
+ subject->keyboardDialog->reject();
+ newSelectedKeyboards = settingsObject->selectedKeyboards();
+ QCOMPARE(newSelectedKeyboards.count(), selectedKeyboards.count());
+ // Open the dialog again
+ subject->selectedKeyboardsItem->click();
+ // Select the item again
+ subject->keyboardList->selectItem(subject->keyboardList->itemModel()->index(0,0));
+ // Accept the dialog content
+ subject->keyboardDialog->accept();
+ newSelectedKeyboards = settingsObject->selectedKeyboards();
if (firstItemIsSelected) {
QCOMPARE(newSelectedKeyboards.count(), selectedKeyboards.count() - 1);
} else {
--- tests/ut_mvirtualkeyboard/ut_mvirtualkeyboard.cpp
+++ tests/ut_mvirtualkeyboard/ut_mvirtualkeyboard.cpp
@@ -30,6 +30,7 @@
#include "mplainwindow.h"
#include "utils.h"
#include "regiontracker.h"
+#include "reactionmappainter.h"
#include <minputmethodnamespace.h>
#include <MScene>
@@ -93,6 +94,7 @@
app = new MApplication(argc, argv);
RegionTracker::createInstance();
+ ReactionMapPainter::createInstance();
QString InputMethodSetting(InputMethodSettingName);
MGConfItem item1(InputMethodSetting);
@@ -131,6 +133,7 @@
delete app;
app = 0;
RegionTracker::destroyInstance();
+ ReactionMapPainter::destroyInstance();
}
void Ut_MVirtualKeyboard::init()
@@ -776,13 +779,13 @@
QVERIFY(tester.testChildButtonReactiveAreas(view, m_vkb));
// Switch layout, the chosen kb layouts are all different in terms of reaction maps they generate.
- QSignalSpy updateSignal(&RegionTracker::instance(), SIGNAL(reactionMapUpdateNeeded()));
+ QSignalSpy updateSignal(&m_vkb->signalForwarder, SIGNAL(requestRepaint()));
m_vkb->setLayout(1);
QTest::qWait(600);
// Currently updating is done via kbhost when it receives region updates.
// Kbhost is not present so we paint reaction map explicitly.
- QVERIFY(updateSignal.count() > 0);
+ QVERIFY(updateSignal.count() == 1);
m_vkb->paintReactionMap(MReactionMap::instance(view), view);
QVERIFY(tester.testReactionMapGrid(view, 40, 50, m_vkb->mapRectToScene(m_vkb->rect()).toRect(), m_vkb));
--- tests/ut_notification/test.css
+++ tests/ut_notification/test.css
-MVirtualKeyboardStyle {
- background-image: "keyboard-qwerty-background" 0 0 0 0;
- divider: "keyboard-divider-vertical";
- font: "Nokia Sans Light" 24;
- font-opacity: 0.9;
- font-color: #FFFFFF;
- secondaryFont: "Nokia Sans Light" 14;
-
- sym-background : "keyboard-sym-background";
- sym-highlight-opacity: 0.6;
- sym-highlight-color: #505050;
-
- accurate-background:"keyboard-acc-thumb";
-
- candidate-background:"textinput-candidates-background";
- candidate-highlight-opacity: 1.0;
- candidate-highlight-color:#BA55D3;
-
- close-button-margin : 10;
-
- notification-font: $FONT_KEYBOARD;
- notification-font-size: 42;
- notification-border-color: #00FF00;
- notification-background-color: #FF0000;
- notification-text-color: #0000FF;
- notification-opacity: 1.0;
-}
-
-MVirtualKeyboardStyle.Portrait {
- size: 280 864;
- left-margin:6;
- top-margin:4;
- divider-width:4;
- divider-height:58;
- spacebar-width:91;
-
- keyboard-area-size: 480 280;
- layout-size: 480 210;
-
- tab-button-size: 91 70;
- function-button-size: 96 70;
- sym-size: 480 425;
-
- menu-size: 470 342;
- baseline-margin:19;
-
- menu-margin: 20;
- menu-margin-box: 10;
- menu-max-opacity-frame: 500;
- menu-max-title-text-width: 200;
-}
-
-MVirtualKeyboardStyle.Landscape {
- size: 864 280;
- left-margin: 6;
- top-margin: 4;
- divider-width: 4;
- divider-height: 58;
- spacebar-width: 216;
-
- keyboard-area-size: 864 280;
- layout-size: 864 210;
-
- function-button-size: 108 70;
- tab-button-size: 108 70;
- sym-size: 864 355;
-
- menu-size: 790 342;
- baseline-margin:19;
-
- menu-margin: 20;
- menu-margin-box: 10;
- menu-max-opacity-frame: 500;
- menu-max-title-text-width: 200;
-}
-
--- tests/ut_notification/ut_notification.cpp
+++ tests/ut_notification/ut_notification.cpp
@@ -64,13 +64,6 @@
disableQtPlugins();
app = new MApplication(argc, app_name);
- QString cssFile("./test.css");
- if (!QFile::exists(cssFile)) {
- cssFile = "/usr/share/meego-keyboard-tests/ut_notification/test.css";
- QVERIFY(QFile::exists(cssFile));
- }
- QVERIFY(MTheme::instance()->loadCSS(cssFile));
-
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
@@ -146,15 +139,5 @@
QVERIFY(!subject->isVisible());
}
-//This test depends on values in test.css
-void Ut_Notification::testCSS()
-{
- QCOMPARE(subject->background, QColor(Qt::red));
- QCOMPARE(subject->border, QColor(Qt::green));
- QCOMPARE(subject->textColor, QColor(Qt::blue));
- QCOMPARE(subject->opacity, 1.0);
- QCOMPARE(subject->font.pixelSize(), 42);
-}
-
QTEST_APPLESS_MAIN(Ut_Notification);
--- tests/ut_notification/ut_notification.h
+++ tests/ut_notification/ut_notification.h
@@ -44,7 +44,6 @@
void testCreate();
void testSetMessageAndGeometry();
void testFadeInFadeOut();
- void testCSS();
};
#endif
--- tests/ut_notification/ut_notification.pro
+++ tests/ut_notification/ut_notification.pro
@@ -12,10 +12,3 @@
SOURCES += ut_notification.cpp
include(../common_check.pri)
-
-CSS_DATA = test.css
-css_data.path = /usr/share/meego-keyboard-tests/ut_notification/
-css_data.files = $$CSS_DATA
-
-INSTALLS += css_data
-
--- tests/ut_sharedhandlearea/ut_sharedhandlearea.cpp
+++ tests/ut_sharedhandlearea/ut_sharedhandlearea.cpp
@@ -15,6 +15,8 @@
*/
#include "ut_sharedhandlearea.h"
+
+#include "reactionmappainter.h"
#include <utils.h>
#include <sharedhandlearea.h>
#include <mgconfitem_stub.h>
@@ -42,6 +44,7 @@
disableQtPlugins();
app = new MApplication(dummyArgc, dummyArgv);
RegionTracker::createInstance();
+ ReactionMapPainter::createInstance();
sceneWindow = createMSceneWindow(new MPlainWindow); // also create singleton
@@ -55,6 +58,7 @@
delete sceneWindow;
delete MPlainWindow::instance();
RegionTracker::destroyInstance();
+ ReactionMapPainter::destroyInstance();
delete app;
}
--- tests/ut_symbolview/ut_symbolview.cpp
+++ tests/ut_symbolview/ut_symbolview.cpp
@@ -26,6 +26,7 @@
#include "mimabstractkeyarea.h"
#include "layoutsmanager.h"
#include "regiontracker.h"
+#include "reactionmappainter.h"
#include "symbolview.h"
#include "ut_symbolview.h"
#include "mplainwindow.h"
@@ -83,6 +84,8 @@
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
+ ReactionMapPainter::createInstance();
+
MGConfItem inputMethodSetting(InputMethodSettingName);
QStringList langlist;
@@ -100,6 +103,7 @@
void Ut_SymbolView::cleanupTestCase()
{
RegionTracker::destroyInstance();
+ ReactionMapPainter::destroyInstance();
delete MPlainWindow::instance();
LayoutsManager::destroyInstance();
delete style;
@@ -164,13 +168,9 @@
QVERIFY(tester.testChildButtonReactiveAreas(view, subject));
// Test the next tab also.
- QSignalSpy reactionMapUpdate(&RegionTracker::instance(),
- SIGNAL(reactionMapUpdateNeeded()));
subject->switchToNextPage();
QTest::qWait(600);
QVERIFY(!subject->pageSwitcher->isRunning());
- // After the switch the reactive areas should be updated.
- QVERIFY(reactionMapUpdate.count() >= 1);
// However since we don't have MKeyboardHost here we call this directly again.
gMReactionMapStub->setTransparentDrawingValue();
--- tests/ut_symbolview/ut_symbolview.pro
+++ tests/ut_symbolview/ut_symbolview.pro
@@ -11,11 +11,15 @@
../stubs/mgconfitem_stub.h \
../stubs/fakegconf.h \
../stubs/mreactionmaptester.h \
- $$WIDGETS_DIR/symbolview.h
+ $$WIDGETS_DIR/popupfactory.h \
+ $$WIDGETS_DIR/symbolview.h \
+# PopupFactory needs to be compiled to have a mocked functionality
+# otherwise the unit test crashes
SOURCES += ut_symbolview.cpp \
../stubs/fakegconf.cpp \
- $$WIDGETS_DIR/symbolview.cpp
+ $$WIDGETS_DIR/popupfactory.cpp \
+ $$WIDGETS_DIR/symbolview.cpp \
include(../common_check.pri)
++++++ meegotouch-inputmethodkeyboard.yaml
--- meegotouch-inputmethodkeyboard.yaml
+++ meegotouch-inputmethodkeyboard.yaml
@@ -1,6 +1,6 @@
Name: meegotouch-inputmethodkeyboard
Summary: MeeGo Virtual Keyboard
-Version: 0.5.25
+Version: 0.5.28
Release: 1
Group: System/GUI/Other
License: LGPLv2.1
@@ -12,8 +12,8 @@
PkgConfigBR:
- QtGui >= 4.6.0
- MeegoImEngine >= 0.4.1
- - MeegoImFramework >= 0.19.40
- - meegotouch >= 0.20
+ - MeegoImFramework >= 0.19.41
+ - meegotouch >= 0.20.77
- meegotouch-feedbackreactionmaps
- x11
- xkbfile >= 1.0.6
More information about the MeeGo-commits
mailing list