69
70
Q_DECLARE_FLAGS(DirtyStates, DirtyState)
72
qint64 msecsSinceReference()
74
static QElapsedTimer elapsedTimer;
76
return elapsedTimer.msecsSinceReference();
73
82
class MirSurface::SurfaceObserverImpl : public SurfaceObserver, public mir::scene::SurfaceObserver
410
419
m_focused = value;
411
420
Q_EMIT focusedChanged(value);
424
Ensure the window that got a key down also gets the corresponding key up
426
Otherwise it will be left in a inconsistent state (with a pressed key hanging around).
428
QQuickWindow's input dispatching doesn't guarantee that for its QQuickItems.
429
So we have to do it ourselves.
431
This can happen when qml active focus changes in response to a key press.
432
Eg: client creates a child window in response to a Ctrl+O. By the time the user
433
releases the Ctrl, active focus will already be in the child window, so the child window
434
will get the release event instead of the top-level one. To solve this, once the top-level
435
window gets active focus again, we synthesize KeyRelease events for all keys this window
436
thinks are still pressed.
438
releaseAllPressedKeys();
414
442
void MirSurface::setViewActiveFocus(qintptr viewId, bool value)
662
690
void MirSurface::keyPressEvent(QKeyEvent *qtEvent)
693
if (!qtEvent->isAutoRepeat()) {
694
Q_ASSERT(!isKeyPressed(qtEvent->nativeVirtualKey()));
695
PressedKey pressedKey(qtEvent, msecsSinceReference());
696
auto info = EventBuilder::instance()->findInfo(qtEvent->timestamp());
698
pressedKey.deviceId = info->deviceId;
700
m_pressedKeys.append(std::move(pressedKey));
664
704
auto ev = EventBuilder::instance()->makeMirEvent(qtEvent);
665
705
auto ev1 = reinterpret_cast<MirKeyboardEvent const*>(ev.get());
666
706
m_controller->deliverKeyboardEvent(m_window, ev1);
670
710
void MirSurface::keyReleaseEvent(QKeyEvent *qtEvent)
672
auto ev = EventBuilder::instance()->makeMirEvent(qtEvent);
673
auto ev1 = reinterpret_cast<MirKeyboardEvent const*>(ev.get());
674
m_controller->deliverKeyboardEvent(m_window, ev1);
712
if (isKeyPressed(qtEvent->nativeVirtualKey())) {
713
forgetPressedKey(qtEvent->nativeVirtualKey());
714
auto ev = EventBuilder::instance()->makeMirEvent(qtEvent);
715
auto ev1 = reinterpret_cast<MirKeyboardEvent const*>(ev.get());
716
m_controller->deliverKeyboardEvent(m_window, ev1);
718
// don't send a release event for a key for which we did not send a press in the first place
678
722
void MirSurface::touchEvent(Qt::KeyboardModifiers mods,
1264
1308
QPoint point(m_surface->top_left().x.as_int(),m_surface->top_left().y.as_int());
1265
1309
setPosition(point);
1312
bool MirSurface::isKeyPressed(quint32 nativeVirtualKey) const
1314
for (const auto &pressedKey : m_pressedKeys) {
1315
if (pressedKey.nativeVirtualKey == nativeVirtualKey) {
1322
void MirSurface::forgetPressedKey(quint32 nativeVirtualKey)
1324
for (int i = 0; i < m_pressedKeys.count(); ++i) {
1325
if (m_pressedKeys[i].nativeVirtualKey == nativeVirtualKey) {
1326
m_pressedKeys.removeAt(i);
1332
void MirSurface::releaseAllPressedKeys()
1334
for (auto &pressedKey : m_pressedKeys) {
1335
auto deltaMs = (ulong)(msecsSinceReference() - pressedKey.msecsSinceReference);
1336
ulong timestamp = pressedKey.timestamp + deltaMs;
1337
std::vector<uint8_t> cookie{};
1339
auto ev = mir::events::make_event(pressedKey.deviceId,
1340
uncompressTimestamp<qtmir::Timestamp>(qtmir::Timestamp(timestamp)),
1341
cookie, mir_keyboard_action_up, pressedKey.nativeVirtualKey, pressedKey.nativeScanCode,
1342
mir_input_event_modifier_none);
1344
auto ev1 = reinterpret_cast<MirKeyboardEvent const*>(ev.get());
1345
m_controller->deliverKeyboardEvent(m_window, ev1);
1347
m_pressedKeys.clear();
1350
MirSurface::PressedKey::PressedKey(QKeyEvent *qtEvent, qint64 msecsSinceReference)
1351
: nativeVirtualKey(qtEvent->nativeVirtualKey())
1352
, nativeScanCode(qtEvent->nativeScanCode())
1353
, timestamp(qtEvent->timestamp())
1354
, msecsSinceReference(msecsSinceReference)