~michael-sheldon/ubuntu-keyboard/fix-oxide-dismiss-test

« back to all changes in this revision

Viewing changes to src/view/renderer.cpp

  • Committer: Thomas Moenicke
  • Date: 2013-07-19 12:05:07 UTC
  • Revision ID: thomas.moenicke@canonical.com-20130719120507-lzw5oq50xm567x0j
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of Maliit Plugins
 
3
 *
 
4
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 
5
 * Copyright (C) 2012 Openismus GmbH
 
6
 *
 
7
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 
8
 *
 
9
 * Redistribution and use in source and binary forms, with or without modification,
 
10
 * are permitted provided that the following conditions are met:
 
11
 *
 
12
 * Redistributions of source code must retain the above copyright notice, this list
 
13
 * of conditions and the following disclaimer.
 
14
 * Redistributions in binary form must reproduce the above copyright notice, this list
 
15
 * of conditions and the following disclaimer in the documentation and/or other materials
 
16
 * provided with the distribution.
 
17
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 
18
 * used to endorse or promote products derived from this software without specific
 
19
 * prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 
22
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
23
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 
24
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
25
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
26
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
28
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
30
 *
 
31
 */
 
32
 
 
33
#include "renderer.h"
 
34
#include "keyareaitem.h"
 
35
#include "keyitem.h"
 
36
#include "wordribbonitem.h"
 
37
#include "utils.h"
 
38
 
 
39
#include "models/keyarea.h"
 
40
#include "models/wordribbon.h"
 
41
 
 
42
#ifdef MALIIT_KEYBOARD_HAVE_OPENGL
 
43
#include <QGLWidget>
 
44
#endif
 
45
 
 
46
#include <maliit/plugins/abstractwidgetssurface.h>
 
47
 
 
48
using Maliit::Plugins::AbstractGraphicsViewSurface;
 
49
using Maliit::Plugins::AbstractSurface;
 
50
using Maliit::Plugins::AbstractSurfaceFactory;
 
51
 
 
52
namespace MaliitKeyboard {
 
53
 
 
54
namespace {
 
55
 
 
56
const qreal WordRibbonZIndex = 0.0f;
 
57
const qreal CenterPanelZIndex = 1.0f;
 
58
const qreal ExtendedPanelZIndex = 20.0f;
 
59
const qreal ActiveKeyZIndex = 0.0f;
 
60
 
 
61
void recycleKeyItem(QVector<KeyItem *> *key_items,
 
62
                    int index,
 
63
                    const Key &key,
 
64
                    QGraphicsItem *parent)
 
65
{
 
66
    KeyItem *item = 0;
 
67
 
 
68
    if (index >= key_items->count()) {
 
69
        item = new KeyItem;
 
70
        item->setZValue(ActiveKeyZIndex);
 
71
        key_items->append(item);
 
72
    } else {
 
73
        item = key_items->at(index);
 
74
    }
 
75
 
 
76
    item->setParentItem(parent);
 
77
    item->setKey(key);
 
78
    item->show();
 
79
}
 
80
 
 
81
void updateActiveKeys(const QVector<Key> &active_keys,
 
82
                      QVector<KeyItem *> *key_items,
 
83
                      QGraphicsItem *parent,
 
84
                      const Logic::KeyOverrides& overrides)
 
85
{
 
86
    int index = 0;
 
87
 
 
88
    for (; index < active_keys.count(); ++index) {
 
89
        Key key(Utils::applyOverride(active_keys.at(index), overrides));
 
90
 
 
91
        recycleKeyItem(key_items, index, key, parent);
 
92
    }
 
93
 
 
94
    // Hide remaining, currently unneeded key items:
 
95
    for (; index < key_items->count(); ++index) {
 
96
        key_items->at(index)->hide();
 
97
    }
 
98
}
 
99
 
 
100
void loadFontFiles(const QString &fonts_dir,
 
101
                   const QStringList &font_files)
 
102
{
 
103
    Q_FOREACH (const QString &font_file, font_files) {
 
104
        const QString full_font_path(fonts_dir + "/" + font_file);
 
105
 
 
106
        if (QFontDatabase::addApplicationFont(full_font_path) < 0) {
 
107
            qCritical() << __PRETTY_FUNCTION__
 
108
                        << "Could not load a font file" << full_font_path;
 
109
        }
 
110
    }
 
111
}
 
112
 
 
113
} // namespace
 
114
 
 
115
class RendererPrivate
 
116
{
 
117
public:
 
118
    Maliit::Plugins::AbstractSurfaceFactory *factory;
 
119
    QSharedPointer<Maliit::Plugins::AbstractGraphicsViewSurface> surface;
 
120
    QSharedPointer<Maliit::Plugins::AbstractGraphicsViewSurface> extended_surface;
 
121
    QSharedPointer<Maliit::Plugins::AbstractGraphicsViewSurface> magnifier_surface;
 
122
    SharedStyle style;
 
123
    KeyAreaItem *center_item;
 
124
    KeyAreaItem *extended_item;
 
125
    WordRibbonItem *ribbon_item;
 
126
    QVector<KeyItem *> key_items;
 
127
    QVector<KeyItem *> extended_key_items;
 
128
    QVector<KeyItem *> magnifier_key_items;
 
129
    QString images_directory_path;
 
130
 
 
131
    explicit RendererPrivate()
 
132
        : factory(0)
 
133
        , surface()
 
134
        , extended_surface()
 
135
        , magnifier_surface()
 
136
        , center_item(new KeyAreaItem)
 
137
        , extended_item(new KeyAreaItem)
 
138
        , ribbon_item(new WordRibbonItem)
 
139
        , key_items()
 
140
        , extended_key_items()
 
141
        , magnifier_key_items()
 
142
    {
 
143
        center_item->setZValue(CenterPanelZIndex);
 
144
        extended_item->setZValue(ExtendedPanelZIndex);
 
145
        ribbon_item->setZValue(WordRibbonZIndex);
 
146
    }
 
147
};
 
148
 
 
149
Renderer::Renderer(QObject *parent)
 
150
    : QObject(parent)
 
151
    , d_ptr(new RendererPrivate)
 
152
{}
 
153
 
 
154
Renderer::~Renderer()
 
155
{}
 
156
 
 
157
void Renderer::setSurfaceFactory(AbstractSurfaceFactory *factory)
 
158
{
 
159
    Q_D(Renderer);
 
160
    d->factory = factory;
 
161
 
 
162
    // Assuming that factory == 0 means reset:
 
163
    if (not d->factory) {
 
164
        // Drop references => shared surface instances are eventually deleted:
 
165
        d->surface.clear();
 
166
        d->extended_surface.clear();
 
167
        d->magnifier_surface.clear();
 
168
        return;
 
169
    }
 
170
 
 
171
    d->surface = qSharedPointerDynamicCast<AbstractGraphicsViewSurface>(
 
172
        factory->create(AbstractSurface::PositionCenterBottom | AbstractSurface::TypeGraphicsView));
 
173
 
 
174
    d->extended_surface = qSharedPointerDynamicCast<AbstractGraphicsViewSurface>(
 
175
        factory->create(AbstractSurface::PositionOverlay | AbstractSurface::TypeGraphicsView, d->surface));
 
176
 
 
177
    d->magnifier_surface = qSharedPointerDynamicCast<AbstractGraphicsViewSurface>(
 
178
        factory->create(AbstractSurface::PositionOverlay | AbstractSurface::TypeGraphicsView, d->surface));
 
179
}
 
180
 
 
181
const QSharedPointer<Maliit::Plugins::AbstractGraphicsViewSurface> Renderer::surface() const
 
182
{
 
183
    Q_D(const Renderer);
 
184
 
 
185
    return d->surface;
 
186
}
 
187
 
 
188
const QSharedPointer<Maliit::Plugins::AbstractGraphicsViewSurface> Renderer::extendedSurface() const
 
189
{
 
190
    Q_D(const Renderer);
 
191
 
 
192
    return d->extended_surface;
 
193
}
 
194
 
 
195
void Renderer::setStyle(const SharedStyle &style)
 
196
{
 
197
    Q_D(Renderer);
 
198
    if (d->style != style) {
 
199
        if (d->style) {
 
200
            disconnect(d->style.data(), SIGNAL(profileChanged()),
 
201
                       this,            SLOT(applyProfile()));
 
202
        }
 
203
        d->style = style;
 
204
        connect(d->style.data(), SIGNAL(profileChanged()),
 
205
                this,            SLOT(applyProfile()));
 
206
        applyProfile();
 
207
    }
 
208
}
 
209
 
 
210
void Renderer::show()
 
211
{
 
212
    Q_D(Renderer);
 
213
 
 
214
    if (d->surface.isNull()
 
215
        || d->extended_surface.isNull()
 
216
        || d->magnifier_surface.isNull()) {
 
217
        qCritical() << __PRETTY_FUNCTION__
 
218
                    << "Some surfaces not available, cannot show keyboard!"
 
219
                    << "Discarding show request.";
 
220
        return;
 
221
    }
 
222
 
 
223
    d->surface->show();
 
224
    d->extended_surface->show();
 
225
 
 
226
    // The root item of a surface only becomes valid after being shown (for
 
227
    // the first time):
 
228
    d->center_item->setParentItem(d->surface->root());
 
229
    d->extended_item->setParentItem(d->extended_surface->root());
 
230
    d->ribbon_item->setParentItem(d->surface->root());
 
231
}
 
232
 
 
233
void Renderer::hide()
 
234
{
 
235
    Q_D(Renderer);
 
236
 
 
237
    if (d->surface.isNull()
 
238
        || d->extended_surface.isNull()
 
239
        || d->magnifier_surface.isNull()) {
 
240
        qCritical() << __PRETTY_FUNCTION__
 
241
                    << "Some surfaces not available, cannot hide keyboard!"
 
242
                    << "Discarding hide request.";
 
243
        return;
 
244
    }
 
245
 
 
246
    d->surface->hide();
 
247
    d->extended_surface->hide();
 
248
    d->extended_surface->view()->viewport()->releaseMouse();
 
249
    d->magnifier_surface->hide();
 
250
}
 
251
 
 
252
void Renderer::onActiveKeysChanged(const QVector<Key> &active_keys,
 
253
                                   const Logic::KeyOverrides &overrides)
 
254
{
 
255
    Q_D(Renderer);
 
256
    updateActiveKeys(active_keys, &d->key_items, d->center_item, overrides);
 
257
}
 
258
 
 
259
void Renderer::onActiveExtendedKeysChanged(const QVector<Key> &active_keys,
 
260
                                           const Logic::KeyOverrides &overrides)
 
261
{
 
262
    Q_D(Renderer);
 
263
    updateActiveKeys(active_keys, &d->extended_key_items, d->extended_item, overrides);
 
264
}
 
265
 
 
266
void Renderer::onMagnifierKeyChanged(const Key &key,
 
267
                                     const Logic::KeyOverrides &overrides)
 
268
{
 
269
    Q_D(Renderer);
 
270
 
 
271
    if (key.valid()) {
 
272
        Key magnifier_key(Utils::applyOverride(key, overrides));
 
273
        d->magnifier_surface->setSize(magnifier_key.area().size());
 
274
        d->magnifier_surface->setRelativePosition(magnifier_key.origin());
 
275
        magnifier_key.setOrigin(QPoint());
 
276
        d->magnifier_surface->show();
 
277
        recycleKeyItem(&d->magnifier_key_items, 0, magnifier_key, d->magnifier_surface->root());
 
278
    } else {
 
279
        d->magnifier_surface->hide();
 
280
    }
 
281
}
 
282
 
 
283
void Renderer::onCenterPanelChanged(const KeyArea &key_area,
 
284
                                    const Logic::KeyOverrides &overrides)
 
285
{
 
286
    Q_D(Renderer);
 
287
 
 
288
    const QSize &ka_size(key_area.area().size());
 
289
    const QPoint &origin(key_area.origin());
 
290
 
 
291
    d->center_item->setKeyArea(key_area);
 
292
    d->center_item->setKeyOverrides(overrides);
 
293
    d->center_item->setVisible(ka_size.isValid());
 
294
 
 
295
    if (d->center_item->isVisible()) {
 
296
        d->surface->setSize(QSize(ka_size.width() + origin.x(),
 
297
                                  ka_size.height() + origin.y()));
 
298
        d->surface->show();
 
299
    } else {
 
300
        d->surface->hide();
 
301
    }
 
302
}
 
303
 
 
304
void Renderer::onExtendedPanelChanged(const KeyArea &key_area,
 
305
                                      const Logic::KeyOverrides &overrides)
 
306
{
 
307
    Q_D(Renderer);
 
308
 
 
309
    const QSize &ka_size(key_area.area().size());
 
310
    const QPoint &origin(key_area.origin());
 
311
 
 
312
    // For extended keys, we move the surface itself, not the key area:
 
313
    KeyArea extended_key_area(key_area);
 
314
    extended_key_area.setOrigin(QPoint());
 
315
 
 
316
    d->extended_item->setKeyArea(extended_key_area);
 
317
    d->extended_item->setKeyOverrides(overrides);
 
318
    d->extended_item->setVisible(ka_size.isValid());
 
319
 
 
320
    if (d->extended_item->isVisible()) {
 
321
        d->extended_surface->setSize(ka_size);
 
322
        d->extended_surface->setRelativePosition(origin);
 
323
        d->extended_surface->show();
 
324
        // TODO: Check how mouse grabbing affects touch events, because we'd
 
325
        // want the same follow-mouse/follow-touchpint behaviour in that case.
 
326
        d->extended_surface->view()->viewport()->grabMouse();
 
327
    } else {
 
328
        d->extended_surface->view()->viewport()->releaseMouse();
 
329
        d->extended_surface->hide();
 
330
    }
 
331
}
 
332
 
 
333
void Renderer::onWordRibbonChanged(const WordRibbon &ribbon)
 
334
{
 
335
    Q_D(Renderer);
 
336
 
 
337
    d->ribbon_item->setWordRibbon(ribbon);
 
338
    d->ribbon_item->setVisible(ribbon.rect().isValid());
 
339
}
 
340
 
 
341
void Renderer::applyProfile()
 
342
{
 
343
    Q_D(Renderer);
 
344
    Utils::setImagesDirectoryPath(d->style->directoryPath(Style::Images));
 
345
 
 
346
    const QStringList font_files(d->style->attributes()->fontFiles());
 
347
    const QString fonts_dir(d->style->directoryPath(Style::Fonts));
 
348
 
 
349
    loadFontFiles(fonts_dir, d->style->attributes()->fontFiles());
 
350
    loadFontFiles(fonts_dir, d->style->extendedKeysAttributes()->fontFiles());
 
351
}
 
352
 
 
353
} // namespace MaliitKeyboard