summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-04-08 13:51:28 +0200
committerJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-08-15 08:18:49 +0200
commit86b0d64b6c44fd8c3c3dd133bf52239f5520e524 (patch)
tree7033bf5ba0645ab6a60220dc70d61cef2dbccfa4
parent43d8a3091894ceb4ab934167b2f3eda27564eb6d (diff)
Client: Add safer fromObject function to scanner
Makes the scanner produce generated static functions such as QtWaylandClient::wl_surface *wl_surface::fromObject(struct ::wl_surface *object); Which casts from the wayland-scanner generated types, such as struct ::wl_surface *, to types types generated by qtwaylandscanner, but performs a check to see if the listener is set to the wrapper class first (at least for interfaces with events). This lets us easily fix crashes in a couple of places where we receive events with wayland objects that we didn't create. Also adds nullptr checks whenever we use the fromWlSurface() and fromWlOutput() functions to handle failed conversions. Task-number: QTBUG-73801 Fixes: QTBUG-74085 Change-Id: I9f33c31c7d1a939ccb3ebbbcb0eb67af10037237 Reviewed-by: Jaroslaw Kubik <jarek@froglogic.com> Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io> (cherry picked from commit 3eea45e31ef796ab6f1363f8fd2882c151becc20) Reviewed-by: Pier Luigi Fiorini <pierluigi.fiorini@liri.io>
-rw-r--r--src/client/qwaylanddatadevice.cpp8
-rw-r--r--src/client/qwaylandinputdevice.cpp13
-rw-r--r--src/client/qwaylandqtkey.cpp6
-rw-r--r--src/client/qwaylandscreen.cpp5
-rw-r--r--src/qtwaylandscanner/qtwaylandscanner.cpp11
5 files changed, 37 insertions, 6 deletions
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
index 11984f9d3..6b2a408eb 100644
--- a/src/client/qwaylanddatadevice.cpp
+++ b/src/client/qwaylanddatadevice.cpp
@@ -154,9 +154,13 @@ void QWaylandDataDevice::data_device_drop()
void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, wl_fixed_t x, wl_fixed_t y, wl_data_offer *id)
{
- m_enterSerial = serial;
- m_dragWindow = QWaylandWindow::fromWlSurface(surface)->window();
+ auto *dragWaylandWindow = QWaylandWindow::fromWlSurface(surface);
+ if (!dragWaylandWindow)
+ return; // Ignore foreign surfaces
+
+ m_dragWindow = dragWaylandWindow->window();
m_dragPoint = calculateDragPosition(x, y, m_dragWindow);
+ m_enterSerial = serial;
QMimeData *dragData = nullptr;
Qt::DropActions supportedActions;
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 90e138a3d..495f258de 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -451,6 +451,9 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
return;
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return; // Ignore foreign surfaces
+
mFocus = window;
mSurfacePos = QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy));
mGlobalPos = window->window()->mapToGlobal(mSurfacePos.toPoint());
@@ -477,6 +480,10 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
if (!surface)
return;
+ auto *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return; // Ignore foreign surfaces
+
if (!QWaylandWindow::mouseGrab()) {
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
window->handleMouseLeave(mParent);
@@ -852,9 +859,13 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial,
if (!surface)
return;
+ auto *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return; // Ignore foreign surfaces
+
mParent->mTime = time;
mParent->mSerial = serial;
- mFocus = QWaylandWindow::fromWlSurface(surface);
+ mFocus = window;
mParent->mQDisplay->setLastInputDevice(mParent, serial, mFocus);
mParent->handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointPressed);
}
diff --git a/src/client/qwaylandqtkey.cpp b/src/client/qwaylandqtkey.cpp
index a60185bd6..192619738 100644
--- a/src/client/qwaylandqtkey.cpp
+++ b/src/client/qwaylandqtkey.cpp
@@ -70,7 +70,11 @@ void QWaylandQtKeyExtension::zqt_key_v1_key(struct wl_surface *surface,
}
QWaylandInputDevice *dev = inputDevices.first();
- QWaylandWindow *win = surface ? QWaylandWindow::fromWlSurface(surface) : dev->keyboardFocus();
+
+ auto *win = surface ? QWaylandWindow::fromWlSurface(surface) : nullptr;
+
+ if (!win)
+ win = dev->keyboardFocus();
if (!win || !win->window()) {
qWarning("qt_key_extension: handle_qtkey: No keyboard focus");
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index 38d61f88c..1fe0125e6 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -199,8 +199,9 @@ QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
QWaylandScreen *QWaylandScreen::fromWlOutput(::wl_output *output)
{
- auto wlOutput = static_cast<QtWayland::wl_output *>(wl_output_get_user_data(output));
- return static_cast<QWaylandScreen *>(wlOutput);
+ if (auto *o = QtWayland::wl_output::fromObject(output))
+ return static_cast<QWaylandScreen *>(o);
+ return nullptr;
}
void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh)
diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp
index 6f4a33b5f..c617369ae 100644
--- a/src/qtwaylandscanner/qtwaylandscanner.cpp
+++ b/src/qtwaylandscanner/qtwaylandscanner.cpp
@@ -982,6 +982,7 @@ bool Scanner::process()
printf("\n");
printf(" struct ::%s *object() { return m_%s; }\n", interfaceName, interfaceName);
printf(" const struct ::%s *object() const { return m_%s; }\n", interfaceName, interfaceName);
+ printf(" static %s *fromObject(struct ::%s *object);\n", interfaceName, interfaceName);
printf("\n");
printf(" bool isInitialized() const;\n");
printf("\n");
@@ -1110,6 +1111,16 @@ bool Scanner::process()
printf(" }\n");
printf("\n");
+ printf(" %s *%s::fromObject(struct ::%s *object)\n", interfaceName, interfaceName, interfaceName);
+ printf(" {\n");
+ if (hasEvents) {
+ printf(" if (wl_proxy_get_listener((struct ::wl_proxy *)object) != (void *)&m_%s_listener)\n", interfaceName);
+ printf(" return nullptr;\n");
+ }
+ printf(" return static_cast<%s *>(%s_get_user_data(object));\n", interfaceName, interfaceName);
+ printf(" }\n");
+ printf("\n");
+
printf(" bool %s::isInitialized() const\n", interfaceName);
printf(" {\n");
printf(" return m_%s != nullptr;\n", interfaceName);