~gerboland/qtubuntu/enable-debug-mode

« back to all changes in this revision

Viewing changes to src/ubuntumirclient/input.cpp

  • Committer: Gerry Boland
  • Date: 2016-04-12 13:10:43 UTC
  • mfrom: (280.2.34 enable-debug-mode)
  • Revision ID: gerry.boland@canonical.com-20160412131043-t14zmcbheuxclmhr
Merge lp:~dandrader/qtubuntu/enable-debug-mode, he kindly fixed merging this with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include "orientationchangeevent_p.h"
25
25
 
26
26
// Qt
27
 
#if !defined(QT_NO_DEBUG)
28
27
#include <QtCore/QThread>
29
 
#endif
30
28
#include <QtCore/qglobal.h>
31
29
#include <QtCore/QCoreApplication>
32
30
#include <private/qguiapplication_p.h>
33
31
#include <qpa/qplatforminputcontext.h>
34
32
#include <qpa/qwindowsysteminterface.h>
 
33
#include <QTextCodec>
35
34
 
36
35
#include <xkbcommon/xkbcommon.h>
37
36
#include <xkbcommon/xkbcommon-keysyms.h>
38
37
 
39
38
#include <mir_toolkit/mir_client_library.h>
40
39
 
41
 
#define LOG_EVENTS 0
 
40
Q_LOGGING_CATEGORY(ubuntumirclientInput, "ubuntumirclient.input", QtWarningMsg)
 
41
 
 
42
namespace
 
43
{
42
44
 
43
45
// XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
44
46
static const uint32_t KeyTable[] = {
110
112
    XKB_KEY_MultipleCandidate,       Qt::Key_MultipleCandidate,
111
113
    XKB_KEY_PreviousCandidate,       Qt::Key_PreviousCandidate,
112
114
 
 
115
    // dead keys
 
116
    XKB_KEY_dead_grave,              Qt::Key_Dead_Grave,
 
117
    XKB_KEY_dead_acute,              Qt::Key_Dead_Acute,
 
118
    XKB_KEY_dead_circumflex,         Qt::Key_Dead_Circumflex,
 
119
    XKB_KEY_dead_tilde,              Qt::Key_Dead_Tilde,
 
120
    XKB_KEY_dead_macron,             Qt::Key_Dead_Macron,
 
121
    XKB_KEY_dead_breve,              Qt::Key_Dead_Breve,
 
122
    XKB_KEY_dead_abovedot,           Qt::Key_Dead_Abovedot,
 
123
    XKB_KEY_dead_diaeresis,          Qt::Key_Dead_Diaeresis,
 
124
    XKB_KEY_dead_abovering,          Qt::Key_Dead_Abovering,
 
125
    XKB_KEY_dead_doubleacute,        Qt::Key_Dead_Doubleacute,
 
126
    XKB_KEY_dead_caron,              Qt::Key_Dead_Caron,
 
127
    XKB_KEY_dead_cedilla,            Qt::Key_Dead_Cedilla,
 
128
    XKB_KEY_dead_ogonek,             Qt::Key_Dead_Ogonek,
 
129
    XKB_KEY_dead_iota,               Qt::Key_Dead_Iota,
 
130
    XKB_KEY_dead_voiced_sound,       Qt::Key_Dead_Voiced_Sound,
 
131
    XKB_KEY_dead_semivoiced_sound,   Qt::Key_Dead_Semivoiced_Sound,
 
132
    XKB_KEY_dead_belowdot,           Qt::Key_Dead_Belowdot,
 
133
    XKB_KEY_dead_hook,               Qt::Key_Dead_Hook,
 
134
    XKB_KEY_dead_horn,               Qt::Key_Dead_Horn,
 
135
 
113
136
    XKB_KEY_Mode_switch,             Qt::Key_Mode_switch,
114
137
    XKB_KEY_script_switch,           Qt::Key_Mode_switch,
115
138
    XKB_KEY_XF86AudioRaiseVolume,    Qt::Key_VolumeUp,
120
143
    0,                          0
121
144
};
122
145
 
 
146
Qt::WindowState mirSurfaceStateToWindowState(MirSurfaceState state)
 
147
{
 
148
    switch (state) {
 
149
    case mir_surface_state_fullscreen:
 
150
        return Qt::WindowFullScreen;
 
151
    case mir_surface_state_maximized:
 
152
    case mir_surface_state_vertmaximized:
 
153
    case mir_surface_state_horizmaximized:
 
154
        return Qt::WindowMaximized;
 
155
    case mir_surface_state_minimized:
 
156
        return Qt::WindowMinimized;
 
157
    case mir_surface_state_hidden:
 
158
        // We should be handling this state separately.
 
159
        Q_ASSERT(false);
 
160
    case mir_surface_state_restored:
 
161
    case mir_surface_state_unknown:
 
162
    default:
 
163
        return Qt::WindowNoState;
 
164
    }
 
165
}
 
166
 
 
167
} // namespace
 
168
 
123
169
class UbuntuEvent : public QEvent
124
170
{
125
171
public:
158
204
  // Qt will take care of deleting mTouchDevice.
159
205
}
160
206
 
161
 
#if (LOG_EVENTS != 0)
162
207
static const char* nativeEventTypeToStr(MirEventType t)
163
208
{
164
209
    switch (t)
180
225
    case mir_event_type_input:
181
226
        return "mir_event_type_input";
182
227
    default:
183
 
        DLOG("Invalid event type %d", t);
184
228
        return "invalid";
185
229
    }
186
230
}
187
 
#endif // LOG_EVENTS != 0
188
231
 
189
232
void UbuntuInput::customEvent(QEvent* event)
190
233
{
191
 
    DASSERT(QThread::currentThread() == thread());
 
234
    Q_ASSERT(QThread::currentThread() == thread());
192
235
    UbuntuEvent* ubuntuEvent = static_cast<UbuntuEvent*>(event);
193
236
    const MirEvent *nativeEvent = ubuntuEvent->nativeEvent;
194
237
 
195
238
    if ((ubuntuEvent->window == nullptr) || (ubuntuEvent->window->window() == nullptr)) {
196
 
        qWarning() << "Attempted to deliver an event to a non-existent window, ignoring.";
 
239
        qCWarning(ubuntumirclient) << "Attempted to deliver an event to a non-existent window, ignoring.";
197
240
        return;
198
241
    }
199
242
 
202
245
    if (QWindowSystemInterface::handleNativeEvent(
203
246
            ubuntuEvent->window->window(), mEventFilterType,
204
247
            const_cast<void *>(static_cast<const void *>(nativeEvent)), &result) == true) {
205
 
        DLOG("event filtered out by native interface");
 
248
        qCDebug(ubuntumirclient, "event filtered out by native interface");
206
249
        return;
207
250
    }
208
251
 
209
 
    #if (LOG_EVENTS != 0)
210
 
    LOG("UbuntuInput::customEvent(type=%s)", nativeEventTypeToStr(mir_event_get_type(nativeEvent)));
211
 
    #endif
 
252
    qCDebug(ubuntumirclientInput, "customEvent(type=%s)", nativeEventTypeToStr(mir_event_get_type(nativeEvent)));
212
253
 
213
254
    // Event dispatching.
214
255
    switch (mir_event_get_type(nativeEvent))
233
274
    case mir_event_type_surface:
234
275
    {
235
276
        auto surfaceEvent = mir_event_get_surface_event(nativeEvent);
236
 
        if (mir_surface_event_get_attribute(surfaceEvent) == mir_surface_attrib_focus) {
 
277
        auto surfaceEventAttribute = mir_surface_event_get_attribute(surfaceEvent);
 
278
        
 
279
        if (surfaceEventAttribute == mir_surface_attrib_focus) {
237
280
            const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused;
238
281
            // Mir may have sent a pair of focus lost/gained events, so we need to "peek" into the queue
239
282
            // so that we don't deactivate windows prematurely.
240
283
            if (focused) {
241
284
                mPendingFocusGainedEvents--;
242
285
                ubuntuEvent->window->handleSurfaceFocused();
 
286
                QWindowSystemInterface::handleWindowActivated(ubuntuEvent->window->window(), Qt::ActiveWindowFocusReason);
 
287
 
 
288
                // NB: Since processing of system events is queued, never check qGuiApp->applicationState()
 
289
                //     as it might be outdated. Always call handleApplicationStateChanged() with the latest
 
290
                //     state regardless.
 
291
                QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
 
292
 
243
293
            } else if(!mPendingFocusGainedEvents) {
244
 
                DLOG("[ubuntumirclient QPA] No windows have focus");
 
294
                qCDebug(ubuntumirclient, "No windows have focus");
245
295
                QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
 
296
                QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
 
297
            }
 
298
        } else if (surfaceEventAttribute == mir_surface_attrib_state) {
 
299
            MirSurfaceState state = static_cast<MirSurfaceState>(mir_surface_event_get_attribute_value(surfaceEvent));
 
300
 
 
301
            if (state == mir_surface_state_hidden) {
 
302
                ubuntuEvent->window->handleSurfaceVisibilityChanged(false);
 
303
            } else {
 
304
                // it's visible!
 
305
                ubuntuEvent->window->handleSurfaceVisibilityChanged(true);
 
306
                ubuntuEvent->window->handleSurfaceStateChanged(mirSurfaceStateToWindowState(state));
246
307
            }
247
308
        }
248
309
        break;
254
315
        QWindowSystemInterface::handleCloseEvent(ubuntuEvent->window->window());
255
316
        break;
256
317
    default:
257
 
        DLOG("unhandled event type: %d", static_cast<int>(mir_event_get_type(nativeEvent)));
 
318
        qCDebug(ubuntumirclient, "unhandled event type: %d", static_cast<int>(mir_event_get_type(nativeEvent)));
258
319
    }
259
320
}
260
321
 
351
412
            mTouchDevice, touchPoints);
352
413
}
353
414
 
354
 
static uint32_t translateKeysym(uint32_t sym, char *string, size_t size)
355
 
{
356
 
    Q_UNUSED(size);
357
 
    string[0] = '\0';
 
415
static uint32_t translateKeysym(uint32_t sym, const QString &text) {
 
416
    int code = 0;
358
417
 
359
 
    if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35)
 
418
    QTextCodec *systemCodec = QTextCodec::codecForLocale();
 
419
    if (sym < 128 || (sym < 256 && systemCodec->mibEnum() == 4)) {
 
420
        // upper-case key, if known
 
421
        code = isprint((int)sym) ? toupper((int)sym) : 0;
 
422
    } else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35) {
360
423
        return Qt::Key_F1 + (int(sym) - XKB_KEY_F1);
361
 
 
362
 
    for (int i = 0; KeyTable[i]; i += 2) {
363
 
        if (sym == KeyTable[i])
364
 
            return KeyTable[i + 1];
 
424
    } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
 
425
               && text.unicode()->unicode() != 0x7f
 
426
               && !(sym >= XKB_KEY_dead_grave && sym <= XKB_KEY_dead_currency)) {
 
427
        code = text.unicode()->toUpper().unicode();
 
428
    } else {
 
429
        for (int i = 0; KeyTable[i]; i += 2)
 
430
            if (sym == KeyTable[i])
 
431
                code = KeyTable[i + 1];
365
432
    }
366
433
 
367
 
    string[0] = sym;
368
 
    string[1] = '\0';
369
 
    return toupper(sym);
 
434
    return code;
370
435
}
371
436
 
372
437
namespace
386
451
    if (modifiers & mir_input_event_modifier_meta) {
387
452
        q_modifiers |= Qt::MetaModifier;
388
453
    }
 
454
    if (modifiers & mir_input_event_modifier_alt_right) {
 
455
        q_modifiers |= Qt::GroupSwitchModifier;
 
456
    }
389
457
    return q_modifiers;
390
458
}
391
459
}
396
464
 
397
465
    ulong timestamp = mir_input_event_get_event_time(event) / 1000000;
398
466
    xkb_keysym_t xk_sym = mir_keyboard_event_key_code(key_event);
 
467
    quint32 scan_code = mir_keyboard_event_scan_code(key_event);
 
468
    quint32 native_modifiers = mir_keyboard_event_modifiers(key_event);
399
469
 
400
470
    // Key modifier and unicode index mapping.
401
471
    auto modifiers = qt_modifiers_from_mir(mir_keyboard_event_modifiers(key_event));
407
477
    if (action == mir_keyboard_action_down)
408
478
        mLastFocusedWindow = window;
409
479
 
410
 
    char s[2];
411
 
    int sym = translateKeysym(xk_sym, s, sizeof(s));
412
 
    QString text = QString::fromLatin1(s);
 
480
    QString text;
 
481
    QVarLengthArray<char, 32> chars(32);
 
482
    {
 
483
        int result = xkb_keysym_to_utf8(xk_sym, chars.data(), chars.size());
 
484
 
 
485
        if (result > 0) {
 
486
            text = QString::fromUtf8(chars.constData());
 
487
        }
 
488
    }
 
489
    int sym = translateKeysym(xk_sym, text);
413
490
 
414
491
    bool is_auto_rep = action == mir_keyboard_action_repeat;
415
492
 
416
493
    QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
417
494
    if (context) {
418
 
        QKeyEvent qKeyEvent(keyType, sym, modifiers, text, is_auto_rep);
 
495
        QKeyEvent qKeyEvent(keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep);
419
496
        qKeyEvent.setTimestamp(timestamp);
420
497
        if (context->filterEvent(&qKeyEvent)) {
421
 
            DLOG("key event filtered out by input context");
 
498
            qCDebug(ubuntumirclient, "key event filtered out by input context");
422
499
            return;
423
500
        }
424
501
    }
425
502
 
426
 
    QWindowSystemInterface::handleKeyEvent(window->window(), timestamp, keyType, sym, modifiers, text, is_auto_rep);
 
503
    QWindowSystemInterface::handleExtendedKeyEvent(window->window(), timestamp, keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep);
427
504
}
428
505
 
429
506
namespace
467
544
 
468
545
        if (hDelta != 0 || vDelta != 0) {
469
546
            const QPoint angleDelta = QPoint(hDelta * 15, vDelta * 15);
470
 
            QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, localPoint,
 
547
            QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, window->position() + localPoint,
471
548
                                                     QPoint(), angleDelta, modifiers, Qt::ScrollUpdate);
472
 
        } else {
473
 
            auto buttons = extract_buttons(pev);
474
 
            if (buttons != Qt::NoButton)
475
 
                mLastFocusedWindow = platformWindow;
476
 
            QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, localPoint /* Should we omit global point instead? */,
477
 
                                                     buttons, modifiers);
478
549
        }
 
550
        auto buttons = extract_buttons(pev);
 
551
        QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, window->position() + localPoint /* Should we omit global point instead? */,
 
552
                                                 buttons, modifiers);
479
553
        break;
480
554
    }
481
555
    case mir_pointer_action_enter:
482
 
        QWindowSystemInterface::handleEnterEvent(window, localPoint, localPoint);
 
556
        QWindowSystemInterface::handleEnterEvent(window, localPoint, window->position() + localPoint);
483
557
        break;
484
558
    case mir_pointer_action_leave:
485
559
        QWindowSystemInterface::handleLeaveEvent(window);
486
560
        break;
487
561
    default:
488
 
        DLOG("Unrecognized pointer event");
 
562
        qCDebug(ubuntumirclient, "Unrecognized pointer event");
489
563
    }
490
564
}
491
565
 
492
 
#if (LOG_EVENTS != 0)
493
566
static const char* nativeOrientationDirectionToStr(MirOrientation orientation)
494
567
{
495
568
    switch (orientation) {
509
582
        return "INVALID!";
510
583
    }
511
584
}
512
 
#endif
513
585
 
514
586
void UbuntuInput::dispatchOrientationEvent(QWindow *window, const MirOrientationEvent *event)
515
587
{
516
588
    MirOrientation mir_orientation = mir_orientation_event_get_direction(event);
517
 
    #if (LOG_EVENTS != 0)
518
 
    // Orientation event logging.
519
 
    LOG("ORIENTATION direction: %s", nativeOrientationDirectionToStr(mir_orientation));
520
 
    #endif
 
589
    qCDebug(ubuntumirclientInput, "orientation direction: %s", nativeOrientationDirectionToStr(mir_orientation));
521
590
 
522
591
    if (!window->screen()) {
523
 
        DLOG("Window has no associated screen, dropping orientation event");
 
592
        qCDebug(ubuntumirclient, "Window has no associated screen, dropping orientation event");
524
593
        return;
525
594
    }
526
595
 
539
608
        orientation = OrientationChangeEvent::RightUp;
540
609
        break;
541
610
    default:
542
 
        DLOG("No such orientation %d", mir_orientation);
 
611
        qCDebug(ubuntumirclient, "No such orientation %d", mir_orientation);
543
612
        return;
544
613
    }
545
614