Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Fix foreign surface with qtwayland #1

Open
wants to merge 3 commits into
base: 5.11
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/client/qwaylanddisplay.cpp
Expand Up @@ -84,6 +84,7 @@ Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorize
struct wl_surface *QWaylandDisplay::createSurface(void *handle)
{
struct wl_surface *surface = mCompositor.create_surface();
mAllSurfaces.push_back(surface);
wl_surface_set_user_data(surface, handle);
return surface;
}
Expand Down Expand Up @@ -440,6 +441,15 @@ void QWaylandDisplay::handleWindowDestroyed(QWaylandWindow *window)
{
if (mActiveWindows.contains(window))
handleWindowDeactivated(window);

::wl_surface *surface = static_cast<::wl_surface *>(window);
int index = mAllSurfaces.indexOf(surface);

if (index != -1) {
// swap-erase
mAllSurfaces.replace(index, mAllSurfaces.back());
mAllSurfaces.pop_back();
}
}

void QWaylandDisplay::handleWaylandSync()
Expand Down Expand Up @@ -498,6 +508,11 @@ void QWaylandDisplay::setCursor(const QSharedPointer<QWaylandBuffer> &buffer, co
}
#endif // QT_CONFIG(cursor)

bool QWaylandDisplay::ownSurface(struct wl_surface *surface)
{
return mAllSurfaces.indexOf(surface) != -1;
}

}

QT_END_NAMESPACE
3 changes: 3 additions & 0 deletions src/client/qwaylanddisplay_p.h
Expand Up @@ -181,6 +181,8 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland
void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
void handleWindowDestroyed(QWaylandWindow *window);

bool ownSurface(struct wl_surface *surface);

public slots:
void blockingReadEvents();
void flushRequests();
Expand Down Expand Up @@ -225,6 +227,7 @@ public slots:
QPointer<QWaylandWindow> mLastInputWindow;
QPointer<QWaylandWindow> mLastKeyboardFocus;
QVector<QWaylandWindow *> mActiveWindows;
QVector<::wl_surface *> mAllSurfaces;
struct wl_callback *mSyncCallback = nullptr;
static const wl_callback_listener syncCallbackListener;

Expand Down
36 changes: 31 additions & 5 deletions src/client/qwaylandinputdevice.cpp
Expand Up @@ -443,6 +443,13 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
if (!surface)
return;

// If we don't own the surface, we just lost focus to a foreign surface
if (!mDisplay->ownSurface(surface)) {
// TODO: should we store the fact that we met a foreign surface?
mFocus = nullptr;
return;
}

QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
#if QT_CONFIG(cursor)
window->window()->setCursor(window->window()->cursor());
Expand All @@ -469,6 +476,11 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
if (!surface)
return;

// In case we have to share the wayland display with an external user of
// wayland API, we might find a surface that doesn't belong to us.
if (!mDisplay->ownSurface(surface))
return;

if (!QWaylandWindow::mouseGrab()) {
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
window->handleMouseLeave(mParent);
Expand All @@ -493,8 +505,10 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf
QWaylandWindow *window = mFocus;

if (!window) {
// We destroyed the pointer focus surface, but the server
// didn't get the message yet.
// Either:
// + we destroyed the pointer focus surface, but the server
// didn't get the message yet.
// + the surface on which the movement happens doesn't belong to us.
return;
}

Expand Down Expand Up @@ -559,6 +573,7 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
if (state)
mParent->mQDisplay->setLastInputDevice(mParent, serial, window);

// TODO: what to do when the focus is lost to a foreign window?
QWaylandWindow *grab = QWaylandWindow::mouseGrab();
if (grab && grab != mFocus) {
QPointF pos = QPointF(-1, -1);
Expand Down Expand Up @@ -595,8 +610,10 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
QPoint angleDelta;

if (!window) {
// We destroyed the pointer focus surface, but the server
// didn't get the message yet.
// Either:
// + we destroyed the pointer focus surface, but the server
// didn't get the message yet.
// + the surface on which the movement happens doesn't belong to us.
return;
}

Expand Down Expand Up @@ -657,6 +674,11 @@ void QWaylandInputDevice::Keyboard::keyboard_enter(uint32_t time, struct wl_surf
if (!surface)
return;

// If we don't own the surface, we don't handle the message.
if (!mDisplay->ownSurface(surface)) {
mFocus = nullptr;
return;
}

QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
mFocus = window;
Expand All @@ -669,7 +691,8 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf
Q_UNUSED(time);
Q_UNUSED(surface);

if (surface) {
if (surface && !mDisplay->ownSurface(surface))
{
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
window->unfocus();
}
Expand Down Expand Up @@ -833,6 +856,9 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial,
if (!surface)
return;

if (!mDisplay->ownSurface(surface))
return;

mParent->mTime = time;
mParent->mSerial = serial;
mFocus = QWaylandWindow::fromWlSurface(surface);
Expand Down