~timo-jyrinki/ubuntu/trusty/maliit-framework/fix_qt52

« back to all changes in this revision

Viewing changes to src/mimpluginmanager.cpp

  • Committer: Package Import Robot
  • Author(s): Ricardo Salveti de Araujo, Sergio Schvezov, Ricardo Salveti de Araujo
  • Date: 2013-07-23 19:47:04 UTC
  • mfrom: (1.1.2) (1.2.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130723194704-1lsy1kmlda069cea
Tags: 0.99.0+git20130615+97e8335-0ubuntu1
[ Sergio Schvezov ]
* New build from HEAD 97e8335.
* Packaging import from lp:phablet-extras/maliit-framework.

[ Ricardo Salveti de Araujo ]
* debian/control: adding vcs and fixing dependencies
* General package cleanup

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *
6
6
 * Contact: maliit-discuss@lists.maliit.org
7
7
 *
8
 
 * Copyright (C) 2012 Openismus GmbH
 
8
 * Copyright (C) 2012 Canonical Ltd
9
9
 *
10
10
 * This library is free software; you can redistribute it and/or
11
11
 * modify it under the terms of the GNU Lesser General Public
17
17
#include "mimpluginmanager.h"
18
18
#include "mimpluginmanager_p.h"
19
19
#include <maliit/plugins/inputmethodplugin.h>
20
 
#include <maliit/plugins/abstractpluginfactory.h>
21
20
#include "mattributeextensionmanager.h"
22
21
#include "msharedattributeextensionmanager.h"
23
22
#include <maliit/plugins/abstractinputmethod.h>
27
26
#include "mimsubviewoverride.h"
28
27
#include "maliit/namespaceinternal.h"
29
28
#include <maliit/settingdata.h>
 
29
#include "windowgroup.h"
 
30
 
 
31
#include <quick/inputmethodquickplugin.h>
30
32
 
31
33
#include <QDir>
32
34
#include <QPluginLoader>
33
35
#include <QSignalMapper>
34
 
#include <QGraphicsLinearLayout>
35
 
#include <QStandardItemModel>
36
36
#include <QWeakPointer>
37
 
#include <QWidget>
38
37
 
39
38
#include <QDebug>
40
39
#include <deque>
42
41
namespace
43
42
{
44
43
    const QString DefaultPluginLocation(MALIIT_PLUGINS_DIR);
45
 
    const QString DefaultFactoryPluginLocation(MALIIT_FACTORY_PLUGINS_DIR);
46
44
 
47
45
    const char * const VisualizationAttribute = "visualizationPriority";
48
46
    const char * const FocusStateAttribute = "focusState";
50
48
    const QString ConfigRoot           = MALIIT_CONFIG_ROOT;
51
49
    const QString MImPluginPaths       = ConfigRoot + "paths";
52
50
    const QString MImPluginDisabled    = ConfigRoot + "disabledpluginfiles";
53
 
    const QString MImPluginFactories   = ConfigRoot + "factories";
54
51
 
55
52
    const QString PluginRoot           = MALIIT_CONFIG_ROOT"plugins";
56
53
    const QString PluginSettings       = MALIIT_CONFIG_ROOT"pluginsettings";
57
54
    const QString MImAccesoryEnabled   = MALIIT_CONFIG_ROOT"accessoryenabled";
58
55
 
59
 
    const int MaxPluginHideTransitionTime(2*1000);
60
 
 
61
56
    const char * const InputMethodItem = "inputMethod";
62
57
    const char * const LoadAll = "loadAll";
63
 
 
64
 
    // this function is used to detect the file suffix used to associate with specific factory
65
 
    static QString getFileMimeType(const QString& fileName)
66
 
    {
67
 
        QFileInfo fi(fileName);
68
 
        return fi.suffix();
69
 
    }
70
58
}
71
59
 
72
60
MIMPluginManagerPrivate::MIMPluginManagerPrivate(const QSharedPointer<MInputContextConnection> &connection,
73
 
                                                 const QSharedPointer<AbstractSurfaceGroupFactory> &surfaceGroupFactory,
 
61
                                                 const QSharedPointer<Maliit::AbstractPlatform> &platform,
74
62
                                                 MIMPluginManager *p)
75
63
    : parent(p),
76
64
      mICConnection(connection),
77
65
      imAccessoryEnabledConf(0),
78
66
      q_ptr(0),
79
 
      acceptRegionUpdates(false),
80
67
      visible(false),
81
 
      indicatorService(),
82
68
      onScreenPlugins(),
83
 
      mSurfaceGroupFactory(surfaceGroupFactory),
84
69
      lastOrientation(0),
85
70
      attributeExtensionManager(new MAttributeExtensionManager),
86
 
      sharedAttributeExtensionManager(new MSharedAttributeExtensionManager)
 
71
      sharedAttributeExtensionManager(new MSharedAttributeExtensionManager),
 
72
      m_platform(platform)
87
73
{
88
74
    inputSourceToNameMap[Maliit::Hardware] = "hardware";
89
75
    inputSourceToNameMap[Maliit::Accessory] = "accessory";
90
 
 
91
 
    ensureEmptyRegionWhenHiddenTimer.setSingleShot(true);
92
 
    ensureEmptyRegionWhenHiddenTimer.setInterval(MaxPluginHideTransitionTime);
93
 
    QObject::connect(&ensureEmptyRegionWhenHiddenTimer, SIGNAL(timeout()),
94
 
                     parent, SLOT(_q_ensureEmptyRegionWhenHidden()));
95
76
}
96
77
 
97
78
 
100
81
    qDeleteAll(handlerToPluginConfs);
101
82
}
102
83
 
103
 
void MIMPluginManagerPrivate::autoDetectEnabledSubViews(const QString &plugin)
104
 
{
105
 
    QList<MImOnScreenPlugins::SubView> to_enable;
106
 
 
107
 
    // Try to auto-detect subviews for the selected plugin by looking for
108
 
    // subviews that coincide with the languages selected for use on the
109
 
    // system.
110
 
    // FIXME: This works for the keyboard plugin, but won't work everywhere.
111
 
    // The methodology for auto-configuring subviews should be somehow
112
 
    // plugin-dictated.
113
 
    QStringList langs = QLocale::system().uiLanguages();
114
 
    Q_FOREACH (QString lang, langs) {
115
 
        // Convert to lower case, remove any .utf8 suffix, and use _ as
116
 
        // the separator between language and country.
117
 
        lang = lang.split('.')[0].toLower().replace("-", "_");
118
 
 
119
 
        MImOnScreenPlugins::SubView subView(plugin, lang);
120
 
 
121
 
        // First try the language code as-is
122
 
        if (onScreenPlugins.isSubViewAvailable(subView) && !to_enable.contains(subView)) {
123
 
            to_enable << subView;
124
 
            continue;
125
 
        }
126
 
 
127
 
        // See if we get a match if we expand "de" to "de_de"
128
 
        if (!lang.contains('_')) {
129
 
            subView.id = lang + "_" + lang;
130
 
            if (onScreenPlugins.isSubViewAvailable(subView) && !to_enable.contains(subView)) {
131
 
                to_enable << subView;
132
 
            }
133
 
            continue;
134
 
        }
135
 
 
136
 
        // See if we get a match if we trim "de_at" to "de"
137
 
        subView.id = lang.split("_").first();
138
 
        if (onScreenPlugins.isSubViewAvailable(subView) && !to_enable.contains(subView)) {
139
 
            to_enable << subView;
140
 
        }
141
 
    }
142
 
 
143
 
    if (!to_enable.isEmpty()) {
144
 
        onScreenPlugins.setAutoEnabledSubViews(to_enable);
145
 
    }
146
 
}
147
 
 
148
84
void MIMPluginManagerPrivate::loadPlugins()
149
85
{
150
86
    Q_Q(MIMPluginManager);
151
87
 
152
88
    MImOnScreenPlugins::SubView activeSubView = onScreenPlugins.activeSubView();
153
89
 
154
 
    //load factories
155
 
    const QDir &dir(DefaultFactoryPluginLocation);
156
 
    Q_FOREACH (QString factoryName, dir.entryList(QDir::Files))
157
 
        loadFactoryPlugin(dir, factoryName);
158
 
 
159
90
    // Load active plugin first
160
91
    Q_FOREACH (QString path, paths) {
161
92
        const QDir &dir(path);
185
116
    const QList<MImOnScreenPlugins::SubView> &availableSubViews = availablePluginsAndSubViews();
186
117
    onScreenPlugins.updateAvailableSubViews(availableSubViews);
187
118
 
188
 
    // If no subviews are enabled by the configuration, try to auto-detect
189
 
    // them.
190
 
    if (onScreenPlugins.enabledSubViews().empty()) {
191
 
        autoDetectEnabledSubViews(activeSubView.plugin);
192
 
    }
193
 
 
194
 
    // If we still don't have an enabled subview, enable the first available
195
 
    // one.
196
 
    if (onScreenPlugins.enabledSubViews().empty()) {
197
 
        MImOnScreenPlugins::SubView subView = availableSubViews.first();
198
 
        onScreenPlugins.setAutoEnabledSubViews(QList<MImOnScreenPlugins::SubView>() << subView);
199
 
    }
200
 
 
201
 
    // If we have an active subview in the configuration, check that it is
202
 
    // enabled. If it's not, drop the active subview.
203
 
    if (!activeSubView.id.isEmpty() && !onScreenPlugins.isSubViewEnabled(activeSubView)) {
204
 
        activeSubView.id = "";
205
 
    }
206
 
 
207
 
    // If we don't have an active subview, auto-activate the first enabled
208
 
    // one.
209
 
    if (activeSubView.id.isEmpty()) {
210
 
        MImOnScreenPlugins::SubView subView = onScreenPlugins.enabledSubViews().first();
211
 
        onScreenPlugins.setAutoActiveSubView(subView);
212
 
    }
213
 
 
214
119
    Q_EMIT q->pluginsChanged();
215
120
}
216
121
 
217
 
bool MIMPluginManagerPrivate::loadFactoryPlugin(const QDir &dir, const QString &fileName)
218
 
{
219
 
    if (blacklist.contains(fileName)) {
220
 
        qWarning() << __PRETTY_FUNCTION__ << fileName << "is on the blacklist, skipped.";
221
 
        return false;
222
 
    }
223
 
 
224
 
    // TODO: skip already loaded plugin ids (fileName)
225
 
    QPluginLoader load(dir.absoluteFilePath(fileName));
226
 
 
227
 
    QObject *pluginInstance = load.instance();
228
 
    if (!pluginInstance) {
229
 
        qWarning() << __PRETTY_FUNCTION__
230
 
                   << "Error loading factory plugin from" << dir.absoluteFilePath(fileName) << load.errorString();
231
 
        return false;
232
 
    }
233
 
 
234
 
    // check if the plugin is a factory
235
 
    MImAbstractPluginFactory *factory = qobject_cast<MImAbstractPluginFactory *>(pluginInstance);
236
 
    if (!factory) {
237
 
        qWarning() << __PRETTY_FUNCTION__
238
 
                   << "Could not cast" << pluginInstance->metaObject()->className() << "into MImAbstractPluginFactory.";
239
 
        return false;
240
 
    }
241
 
    factories.insert(factory->fileExtension(), factory);
242
 
    return true;
243
 
}
244
 
 
245
122
bool MIMPluginManagerPrivate::loadPlugin(const QDir &dir, const QString &fileName)
246
123
{
247
124
    Q_Q(MIMPluginManager);
253
130
 
254
131
    Maliit::Plugins::InputMethodPlugin *plugin = 0;
255
132
 
256
 
    QSharedPointer<AbstractSurfaceGroup> surfaceGroup(mSurfaceGroupFactory->createSurfaceGroup());
257
 
 
258
 
    // Check if we have a specific factory for this plugin
259
 
    QString mimeType = getFileMimeType(fileName);
260
 
    if (factories.contains(mimeType)) {
261
 
        plugin = factories[mimeType]->create(dir.filePath(fileName));
 
133
    if (QFileInfo(fileName).suffix() == "qml") {
 
134
        plugin = new Maliit::InputMethodQuickPlugin(dir.filePath(fileName), m_platform);
262
135
        if (!plugin) {
263
136
            qWarning() << __PRETTY_FUNCTION__
264
137
                       << "Could not create a plugin for: " << fileName;
288
161
        return false;
289
162
    }
290
163
 
291
 
    MInputMethodHost *host = new MInputMethodHost(mICConnection, q, indicatorService, surfaceGroup->factory(),
 
164
    QSharedPointer<Maliit::WindowGroup> windowGroup(new Maliit::WindowGroup(m_platform));
 
165
    MInputMethodHost *host = new MInputMethodHost(mICConnection, q, windowGroup,
292
166
                                                  fileName, plugin->name());
293
167
 
294
168
    MAbstractInputMethod *im = plugin->createInputMethod(host);
304
178
    }
305
179
 
306
180
    PluginDescription desc = { im, host, PluginState(),
307
 
                               Maliit::SwitchUndefined, fileName, surfaceGroup };
 
181
                               Maliit::SwitchUndefined, fileName, windowGroup };
308
182
 
309
183
    // Connect surface group signals
310
 
    QObject::connect(surfaceGroup.data(), SIGNAL(inputMethodAreaChanged(QRegion)),
 
184
    QObject::connect(windowGroup.data(), SIGNAL(inputMethodAreaChanged(QRegion)),
311
185
                     mICConnection.data(), SLOT(updateInputMethodArea(QRegion)));
312
186
 
313
187
    plugins.insert(plugin, desc);
1093
967
    }
1094
968
}
1095
969
 
1096
 
 
1097
 
void MIMPluginManagerPrivate::_q_ensureEmptyRegionWhenHidden()
1098
 
{
1099
 
    Q_Q(MIMPluginManager);
1100
 
    // Do not accept region updates from hidden plugins. Emit an empty region
1101
 
    // update, because we cannot trust that a plugin sends a region update
1102
 
    // after it's hidden.
1103
 
    acceptRegionUpdates = false;
1104
 
    Q_EMIT q->regionUpdated(QRegion());
1105
 
}
1106
 
 
1107
970
void MIMPluginManagerPrivate::showActivePlugins()
1108
971
{
1109
 
    ensureEmptyRegionWhenHiddenTimer.stop();
1110
 
    acceptRegionUpdates = true;
1111
972
    visible = true;
1112
 
 
1113
973
    ensureActivePluginsVisible(ShowInputMethod);
1114
974
}
1115
975
 
1118
978
    visible = false;
1119
979
    Q_FOREACH (Maliit::Plugins::InputMethodPlugin *plugin, activePlugins) {
1120
980
        plugins.value(plugin).inputMethod->hide();
1121
 
        plugins.value(plugin).surfaceGroup->deactivate();
 
981
        plugins.value(plugin).windowGroup->deactivate(Maliit::WindowGroup::HideDelayed);
1122
982
    }
1123
 
 
1124
 
    ensureEmptyRegionWhenHiddenTimer.start();
1125
983
}
1126
984
 
1127
985
void MIMPluginManagerPrivate::ensureActivePluginsVisible(ShowInputMethodRequest request)
1130
988
 
1131
989
    for (; iterator != plugins.end(); ++iterator) {
1132
990
        if (activePlugins.contains(iterator.key())) {
1133
 
            iterator.value().surfaceGroup->activate();
 
991
            iterator.value().windowGroup->activate();
1134
992
            if (request == ShowInputMethod) {
1135
993
                iterator.value().inputMethod->show();
1136
994
            }
1137
995
        } else {
1138
 
            iterator.value().surfaceGroup->deactivate();
 
996
            iterator.value().windowGroup->deactivate(Maliit::WindowGroup::HideImmediate);
1139
997
        }
1140
998
    }
1141
999
}
1232
1090
// actual class
1233
1091
 
1234
1092
MIMPluginManager::MIMPluginManager(const QSharedPointer<MInputContextConnection>& icConnection,
1235
 
                                   const QSharedPointer<AbstractSurfaceGroupFactory>& surfacesFactory)
 
1093
                                   const QSharedPointer<Maliit::AbstractPlatform> &platform)
1236
1094
    : QObject(),
1237
 
      d_ptr(new MIMPluginManagerPrivate(icConnection, surfacesFactory, this))
 
1095
      d_ptr(new MIMPluginManagerPrivate(icConnection, platform, this))
1238
1096
{
1239
1097
    Q_D(MIMPluginManager);
1240
1098
    d->q_ptr = this;
1313
1171
    connect(d->mICConnection.data(), SIGNAL(pluginSettingsRequested(int,QString)),
1314
1172
            this, SLOT(pluginSettingsRequested(int,QString)));
1315
1173
 
 
1174
    connect(d->mICConnection.data(), SIGNAL(focusChanged(WId)),
 
1175
            this, SLOT(handleAppFocusChanged(WId)));
 
1176
 
1316
1177
    // Connect from MAttributeExtensionManager to our handlers
1317
1178
    connect(d->attributeExtensionManager.data(), SIGNAL(attributeExtensionIdChanged(const MAttributeExtensionId &)),
1318
1179
            this, SLOT(setToolbar(const MAttributeExtensionId &)));
1460
1321
    d->onScreenPlugins.setAllSubViewsEnabled(enable);
1461
1322
}
1462
1323
 
1463
 
void MIMPluginManager::updateRegion(const QRegion &region)
1464
 
{
1465
 
    Q_D(MIMPluginManager);
1466
 
 
1467
 
    // Record input method object's region.
1468
 
    d->activeImRegion = region;
1469
 
 
1470
 
    // Don't update region when no region updates from the plugin side are
1471
 
    // expected.
1472
 
    if (d->acceptRegionUpdates) {
1473
 
        Q_EMIT regionUpdated(region);
1474
 
    }
1475
 
}
1476
 
 
1477
1324
void MIMPluginManager::setToolbar(const MAttributeExtensionId &id)
1478
1325
{
1479
1326
    Q_D(MIMPluginManager);
1577
1424
    }
1578
1425
}
1579
1426
 
 
1427
void MIMPluginManager::handleAppFocusChanged(WId id)
 
1428
{
 
1429
    Q_D(MIMPluginManager);
 
1430
 
 
1431
    MIMPluginManagerPrivate::Plugins::iterator i = d->plugins.begin();
 
1432
    while (i != d->plugins.end()) {
 
1433
        i.value().windowGroup.data()->setApplicationWindow(id);
 
1434
        ++i;
 
1435
    }
 
1436
}
 
1437
 
1580
1438
void MIMPluginManager::handleClientChange()
1581
1439
{
1582
1440
    // notify plugins
1645
1503
        }
1646
1504
        target->update();
1647
1505
    }
 
1506
 
 
1507
    // Make sure windows get hidden when no longer focus
 
1508
    if (not widgetFocusState) {
 
1509
        hideActivePlugins();
 
1510
    }
1648
1511
}
1649
1512
 
1650
1513
void MIMPluginManager::handleMouseClickOnPreedit(const QPoint &pos, const QRect &preeditRect)