PointerLockerWayland::PointerLockerWayland(QObject *parent)
: AbstractPointerLocker(parent)
{
m_pointerConstraints = new PointerConstraints;
}
PointerLockerWayland::~PointerLockerWayland()
{
delete m_pointerConstraints;
}
bool PointerLockerWayland::isLockEffective() const
{
return m_lockedPointer;
}
wl_pointer *PointerLockerWayland::getPointer()
{
QPlatformNativeInterface *native = qGuiApp->platformNativeInterface();
if (!native) {
return nullptr;
}
window()->create();
return reinterpret_cast(native->nativeResourceForIntegration(QByteArrayLiteral("wl_pointer")));
}
void PointerLockerWayland::enforceLock()
{
if (!m_isLocked) {
return;
}
wl_surface *wlSurface = [](QWindow *window) -> wl_surface * {
if (!window) {
return nullptr;
}
QPlatformNativeInterface *native = qGuiApp->platformNativeInterface();
if (!native) {
return nullptr;
}
window->create();
return reinterpret_cast(native->nativeResourceForWindow(QByteArrayLiteral("surface"), window));
}(m_window);
m_lockedPointer =
new LockedPointer(m_pointerConstraints->lock_pointer(wlSurface, getPointer(), nullptr, PointerConstraints::lifetime::lifetime_persistent), this);
if (!m_lockedPointer) {
qDebug() << "ERROR when receiving locked pointer!";
return;
}
connect(m_lockedPointer, &LockedPointer::locked, this, [this] {
Q_EMIT lockEffectiveChanged(true);
});
connect(m_lockedPointer, &LockedPointer::unlocked, this, [this] {
Q_EMIT lockEffectiveChanged(false);
});
}
void PointerLockerWayland::setLocked(bool lock)
{
if (m_isLocked == lock) {
return;
}
if (!isSupported()) {
qWarning() << "Locking before having our interfaces announced";
return;
}
m_isLocked = lock;
if (lock) {
enforceLock();
} else {
cleanupLock();
}
Q_EMIT lockedChanged(lock);
}
void PointerLockerWayland::cleanupLock()
{
if (!m_lockedPointer) {
return;
}
m_lockedPointer->destroy();
m_lockedPointer->deleteLater();
m_lockedPointer = nullptr;
Q_EMIT lockEffectiveChanged(false);
}
void PointerLockerWayland::setWindow(QWindow *window)
{
if (m_window == window) {
return;
}
cleanupLock();
if (m_window) {
disconnect(m_window, &QWindow::visibleChanged, this, &PointerLockerWayland::enforceLock);
}
AbstractPointerLocker::setWindow(window);
connect(m_window, &QWindow::visibleChanged, this, &PointerLockerWayland::enforceLock);
if (m_isLocked) {
enforceLock();
}
}