From a69a0e8254b79c62fad7372e8c14f66d440ad744 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 23 Jan 2018 10:21:49 +0100 Subject: glx: Avoid losing the stereo flag in QSurfaceFormat Task-number: QTBUG-59636 Change-Id: I38394009993e92ab9db853a1450687fc48e471f5 Reviewed-by: Andy Nichols --- src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index e2e573f0e1..fc1806f982 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -134,7 +134,11 @@ static void updateFormatFromContext(QSurfaceFormat &format) } format.setProfile(QSurfaceFormat::NoProfile); + const bool isStereo = format.testOption(QSurfaceFormat::StereoBuffers); format.setOptions(QSurfaceFormat::FormatOptions()); + // Restore flags that come from the VisualInfo/FBConfig. + if (isStereo) + format.setOption(QSurfaceFormat::StereoBuffers); if (format.renderableType() == QSurfaceFormat::OpenGL) { if (format.version() < qMakePair(3, 0)) { -- cgit v1.2.3 From 57f4521c99df1e4e2c1fd321a41019ae4e0c17b1 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 2 Feb 2018 08:06:04 +0100 Subject: Fix QXcbWindow::mapFrom/ToGlobal() Call the base class implementations to avoid returning an unmapped values for non-embedded windows. Task-number: QTBUG-55251 Change-Id: Ib05fd530498dd4d72d3d4ef37caf4e2f0ebcd2e4 Reviewed-by: Friedemann Kleint Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index c4649ac818..37d6336a72 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2157,7 +2157,7 @@ bool QXcbWindow::isEmbedded() const QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const { if (!m_embedded) - return pos; + return QPlatformWindow::mapToGlobal(pos); QPoint ret; xcb_translate_coordinates_cookie_t cookie = @@ -2177,7 +2177,7 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const { if (!m_embedded) - return pos; + return QPlatformWindow::mapFromGlobal(pos); QPoint ret; xcb_translate_coordinates_cookie_t cookie = -- cgit v1.2.3 From 2a80c04d3bbc45b5d1293a5141839c0b4719f772 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 15 Feb 2018 11:02:07 +0100 Subject: Fix crash when reading window titles with XCB This is a regression introduced with commit cb142954c54b7a6e391950d9209b5cea9252092b that changed the code from using QString:fromUtf8(name, propertyLength) to QString::fromUtf8(name), assuming that the property name is a zero-terminated string. That however is not correct. ASAN trace: ==4039==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60400001e0b4 at pc 0x7f3383c7d66e bp 0x7ffdc8e3d9b0 sp 0x7ffdc8e3d158 READ of size 5 at 0x60400001e0b4 thread T0 #0 0x7f3383c7d66d (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5166d) #1 0x7f337602f32a in QString::fromUtf8(char const*, int) ../../../../include/QtCore/../../src/corelib/tools/qstring.h:569 #2 0x7f337602f32a in QXcbWindow::windowTitle(QXcbConnection const*, unsigned int) /home/simon/dev/qt-5.11/qtbase/src/plugins/platforms/xcb/qxcbwindow.cpp:2861 [...] 0x60400001e0b4 is located 0 bytes to the right of 36-byte region [0x60400001e090,0x60400001e0b4) allocated by thread T1 (QXcbEventReader) here: #0 0x7f3383d0ab50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50) #1 0x7f337b397e2b (/usr/lib/x86_64-linux-gnu/libxcb.so.1+0xde2b) Change-Id: Ia5024602d3aacb924b5dcd3956672da2a8f10feb Reviewed-by: Friedemann Kleint --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 61cfed4db7..e9a6e536a7 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2857,7 +2857,7 @@ QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window) utf8Atom, 0, 1024); if (reply && reply->format == 8 && reply->type == utf8Atom) { const char *name = reinterpret_cast(xcb_get_property_value(reply.get())); - return QString::fromUtf8(name); + return QString::fromUtf8(name, xcb_get_property_value_length(reply.get())); } return QString(); } -- cgit v1.2.3 From 8db9e33997a8fbe3e13eab1ca62ae2d5ac39abef Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 6 Feb 2018 01:28:20 +0300 Subject: xcb: Enhance SHM management code - extract the creation of a shared memory segment into a separate function - do extra checks for errors - check that MIT-SHM extension is present once in QXcbConnection Change-Id: I956bdf76b879ec5c95a7ed219a59ae722dc5afba Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 103 +++++++++++++++---------- src/plugins/platforms/xcb/qxcbconnection.cpp | 28 +++++-- src/plugins/platforms/xcb/qxcbconnection.h | 4 + 3 files changed, 91 insertions(+), 44 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 1cf45c96d1..e69bc5cba5 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -85,6 +85,9 @@ public: void preparePaint(const QRegion ®ion); private: + void createShmSegment(size_t segmentSize); + void destroyShmSegment(); + void destroy(); void ensureGC(xcb_drawable_t dst); @@ -173,39 +176,13 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI XCB_IMAGE_ORDER_MSB_FIRST, 0, ~0, 0); - const int segmentSize = m_xcb_image->stride * m_xcb_image->height; + const size_t segmentSize = static_cast(m_xcb_image->stride) * m_xcb_image->height; if (!segmentSize) return; - int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); - if (id == -1) { - qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %d (%dx%d)", - errno, strerror(errno), segmentSize, size.width(), size.height()); - } else { - m_shm_info.shmaddr = m_xcb_image->data = (quint8 *)shmat(id, 0, 0); - } - m_shm_info.shmid = id; - m_shm_info.shmseg = xcb_generate_id(xcb_connection()); - - const xcb_query_extension_reply_t *shm_reply = xcb_get_extension_data(xcb_connection(), &xcb_shm_id); - bool shm_present = shm_reply != NULL && shm_reply->present; - xcb_generic_error_t *error = NULL; - if (shm_present) - error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false)); - if (!shm_present || error || id == -1) { - free(error); + createShmSegment(segmentSize); - if (id != -1) { - shmdt(m_shm_info.shmaddr); - shmctl(m_shm_info.shmid, IPC_RMID, 0); - } - m_shm_info.shmaddr = 0; - - m_xcb_image->data = (uint8_t *)malloc(segmentSize); - } else { - if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1) - qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed"); - } + m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize); m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; if (!m_hasAlpha) @@ -270,6 +247,60 @@ void QXcbShmImage::flushScrolledRegion(bool clientSideScroll) } } +void QXcbShmImage::createShmSegment(size_t segmentSize) +{ + m_shm_info.shmaddr = nullptr; + if (!connection()->hasShm()) + return; + + const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); + if (id == -1) { + qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %zu", + errno, strerror(errno), segmentSize); + return; + } + + void *addr = shmat(id, 0, 0); + if (addr == (void *)-1) { + qWarning("QXcbShmImage: shmat() failed (%d: %s) for id %d", + errno, strerror(errno), id); + return; + } + + if (shmctl(id, IPC_RMID, 0) == -1) + qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed"); + + const auto seg = xcb_generate_id(xcb_connection()); + auto cookie = xcb_shm_attach_checked(xcb_connection(), seg, id, false); + auto *error = xcb_request_check(xcb_connection(), cookie); + if (error) { + connection()->printXcbError("QXcbShmImage: xcb_shm_attach() failed with error", error); + free(error); + if (shmdt(addr) == -1) { + qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", + errno, strerror(errno), addr); + } + return; + } + + m_shm_info.shmseg = seg; + m_shm_info.shmid = id; // unused + m_shm_info.shmaddr = static_cast(addr); +} + +void QXcbShmImage::destroyShmSegment() +{ + auto cookie = xcb_shm_detach_checked(xcb_connection(), m_shm_info.shmseg); + xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie); + if (error) + connection()->printXcbError("QXcbShmImage: xcb_shm_detach() failed with error", error); + + if (shmdt(m_shm_info.shmaddr) == -1) { + qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", + errno, strerror(errno), m_shm_info.shmaddr); + } +} + extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy) @@ -318,17 +349,11 @@ bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy) void QXcbShmImage::destroy() { - const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0; - if (segmentSize && m_shm_info.shmaddr) - xcb_shm_detach(xcb_connection(), m_shm_info.shmseg); - - if (segmentSize) { - if (m_shm_info.shmaddr) { - shmdt(m_shm_info.shmaddr); - shmctl(m_shm_info.shmid, IPC_RMID, 0); - } else { + if (m_xcb_image->data) { + if (m_shm_info.shmaddr) + destroyShmSegment(); + else free(m_xcb_image->data); - } } xcb_image_destroy(m_xcb_image); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index c5eae20266..e8bb97c6af 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -582,6 +582,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeAllAtoms(); + initializeShm(); if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR")) initializeXRandr(); if (!has_randr_extension) @@ -961,14 +962,20 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error) if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), error, &result)) return; + printXcbError("QXcbConnection: XCB error", error); +} + +void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *error) +{ uint clamped_error_code = qMin(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); uint clamped_major_code = qMin(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); - qWarning("QXcbConnection: XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", - int(error->error_code), xcb_errors[clamped_error_code], - int(error->sequence), int(error->resource_id), - int(error->major_code), xcb_protocol_request_codes[clamped_major_code], - int(error->minor_code)); + qWarning("%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", + message, + int(error->error_code), xcb_errors[clamped_error_code], + int(error->sequence), int(error->resource_id), + int(error->major_code), xcb_protocol_request_codes[clamped_major_code], + int(error->minor_code)); } static Qt::MouseButtons translateMouseButtons(int s) @@ -2087,6 +2094,17 @@ void QXcbConnection::sync() free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0)); } +void QXcbConnection::initializeShm() +{ + const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_shm_id); + if (!reply || !reply->present) { + qWarning("QXcbConnection: MIT-SHM extension is not present on the X server."); + return; + } + + has_shm = true; +} + void QXcbConnection::initializeXFixes() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id); diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 07df963ec5..b2713b8ac7 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -441,6 +441,7 @@ public: void sync(); void handleXcbError(xcb_generic_error_t *error); + void printXcbError(const char *message, xcb_generic_error_t *error); void handleXcbEvent(xcb_generic_event_t *event); void printXcbEvent(const QLoggingCategory &log, const char *message, xcb_generic_event_t *event) const; @@ -478,6 +479,7 @@ public: bool hasXKB() const { return has_xkb; } bool hasXRender() const { return has_render_extension; } bool hasXInput2() const { return m_xi2Enabled; } + bool hasShm() const { return has_shm; } bool threadedEventHandling() const { return m_reader->isRunning(); } @@ -545,6 +547,7 @@ private slots: private: void initializeAllAtoms(); void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0); + void initializeShm(); void initializeXFixes(); void initializeXRender(); void initializeXRandr(); @@ -699,6 +702,7 @@ private: bool has_input_shape; bool has_xkb = false; bool has_render_extension = false; + bool has_shm = false; Qt::MouseButtons m_buttonState = 0; Qt::MouseButton m_button = Qt::NoButton; -- cgit v1.2.3 From 24adaa9a742e6f95ff897d0eb9a2bce0527dd042 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 6 Feb 2018 13:49:42 +0300 Subject: xcb: Fix access to shm for X server running from another user Use ShmCreateSegment call, that was added in MIT-SHM 1.2, to create shared memory segments on the server side. It returns a POSIX shared memory object that is used to mmap memory. It's in effect a file descriptor that is passed through the X server socket and thus avoids permission checks. On the other hand this scheme is more secure, because the file descriptor, and thus the shared memory, are accessible only by the X server and the application. Task-number: QTBUG-46017 Change-Id: I202eead9d01aee2ab5b65f4f74f4c13da7cb2239 Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 133 ++++++++++++++++++------- src/plugins/platforms/xcb/qxcbconnection.cpp | 9 ++ src/plugins/platforms/xcb/qxcbconnection.h | 2 + 3 files changed, 109 insertions(+), 35 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index e69bc5cba5..eae0ee7613 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -48,9 +48,11 @@ #include #include +#include #include #include +#include #include #include @@ -61,6 +63,11 @@ #include #include + +#if (XCB_SHM_MAJOR_VERSION == 1 && XCB_SHM_MINOR_VERSION >= 2) || XCB_SHM_MAJOR_VERSION > 1 +#define XCB_USE_SHM_FD +#endif + QT_BEGIN_NAMESPACE class QXcbShmImage : public QXcbObject @@ -86,7 +93,7 @@ public: private: void createShmSegment(size_t segmentSize); - void destroyShmSegment(); + void destroyShmSegment(size_t segmentSize); void destroy(); @@ -157,6 +164,11 @@ private: QImage *m_image; }; +static inline size_t imageDataSize(const xcb_image_t *image) +{ + return static_cast(image->stride) * image->height; +} + QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format) : QXcbObject(screen->connection()) , m_graphics_buffer(nullptr) @@ -176,7 +188,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI XCB_IMAGE_ORDER_MSB_FIRST, 0, ~0, 0); - const size_t segmentSize = static_cast(m_xcb_image->stride) * m_xcb_image->height; + const size_t segmentSize = imageDataSize(m_xcb_image); if (!segmentSize) return; @@ -250,54 +262,105 @@ void QXcbShmImage::flushScrolledRegion(bool clientSideScroll) void QXcbShmImage::createShmSegment(size_t segmentSize) { m_shm_info.shmaddr = nullptr; + if (!connection()->hasShm()) return; - const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); - if (id == -1) { - qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %zu", - errno, strerror(errno), segmentSize); - return; - } +#ifdef XCB_USE_SHM_FD + if (connection()->hasShmFd()) { + if (Q_UNLIKELY(segmentSize > std::numeric_limits::max())) { + qWarning("QXcbShmImage: xcb_shm_create_segment() can't be called for size %zu, maximum allowed size is %u", + segmentSize, std::numeric_limits::max()); + return; + } + const auto seg = xcb_generate_id(xcb_connection()); + auto reply = Q_XCB_REPLY(xcb_shm_create_segment, + xcb_connection(), seg, segmentSize, false); + if (!reply) { + qWarning("QXcbShmImage: xcb_shm_create_segment() failed for size %zu", segmentSize); + return; + } - void *addr = shmat(id, 0, 0); - if (addr == (void *)-1) { - qWarning("QXcbShmImage: shmat() failed (%d: %s) for id %d", - errno, strerror(errno), id); - return; - } + int *fds = xcb_shm_create_segment_reply_fds(xcb_connection(), reply.get()); + if (reply->nfd != 1) { + for (int i = 0; i < reply->nfd; i++) + close(fds[i]); - if (shmctl(id, IPC_RMID, 0) == -1) - qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed"); + qWarning("QXcbShmImage: failed to get file descriptor for shm segment of size %zu", segmentSize); + return; + } - const auto seg = xcb_generate_id(xcb_connection()); - auto cookie = xcb_shm_attach_checked(xcb_connection(), seg, id, false); - auto *error = xcb_request_check(xcb_connection(), cookie); - if (error) { - connection()->printXcbError("QXcbShmImage: xcb_shm_attach() failed with error", error); - free(error); - if (shmdt(addr) == -1) { - qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", - errno, strerror(errno), addr); + void *addr = mmap(nullptr, segmentSize, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0], 0); + if (addr == MAP_FAILED) { + qWarning("QXcbShmImage: failed to mmap segment from X server (%d: %s) for size %zu", + errno, strerror(errno), segmentSize); + close(fds[0]); + xcb_shm_detach(xcb_connection(), seg); + return; + } + + close(fds[0]); + m_shm_info.shmseg = seg; + m_shm_info.shmaddr = static_cast(addr); + } else +#endif + { + const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); + if (id == -1) { + qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %zu", + errno, strerror(errno), segmentSize); + return; + } + + void *addr = shmat(id, 0, 0); + if (addr == (void *)-1) { + qWarning("QXcbShmImage: shmat() failed (%d: %s) for id %d", + errno, strerror(errno), id); + return; + } + + if (shmctl(id, IPC_RMID, 0) == -1) + qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed"); + + const auto seg = xcb_generate_id(xcb_connection()); + auto cookie = xcb_shm_attach_checked(xcb_connection(), seg, id, false); + auto *error = xcb_request_check(xcb_connection(), cookie); + if (error) { + connection()->printXcbError("QXcbShmImage: xcb_shm_attach() failed with error", error); + free(error); + if (shmdt(addr) == -1) { + qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", + errno, strerror(errno), addr); + } + return; } - return; - } - m_shm_info.shmseg = seg; - m_shm_info.shmid = id; // unused - m_shm_info.shmaddr = static_cast(addr); + m_shm_info.shmseg = seg; + m_shm_info.shmid = id; // unused + m_shm_info.shmaddr = static_cast(addr); + } } -void QXcbShmImage::destroyShmSegment() +void QXcbShmImage::destroyShmSegment(size_t segmentSize) { auto cookie = xcb_shm_detach_checked(xcb_connection(), m_shm_info.shmseg); xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie); if (error) connection()->printXcbError("QXcbShmImage: xcb_shm_detach() failed with error", error); - if (shmdt(m_shm_info.shmaddr) == -1) { - qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", - errno, strerror(errno), m_shm_info.shmaddr); +#ifdef XCB_USE_SHM_FD + if (connection()->hasShmFd()) { + if (munmap(m_shm_info.shmaddr, segmentSize) == -1) { + qWarning("QXcbShmImage: munmap() failed (%d: %s) for %p with size %zu", + errno, strerror(errno), m_shm_info.shmaddr, segmentSize); + } + } else +#endif + { + if (shmdt(m_shm_info.shmaddr) == -1) { + qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", + errno, strerror(errno), m_shm_info.shmaddr); + } } } @@ -351,7 +414,7 @@ void QXcbShmImage::destroy() { if (m_xcb_image->data) { if (m_shm_info.shmaddr) - destroyShmSegment(); + destroyShmSegment(imageDataSize(m_xcb_image)); else free(m_xcb_image->data); } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index e8bb97c6af..d0868f44c0 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -2103,6 +2103,15 @@ void QXcbConnection::initializeShm() } has_shm = true; + + auto shm_query = Q_XCB_REPLY(xcb_shm_query_version, m_connection); + if (!shm_query) { + qWarning("QXcbConnection: Failed to request MIT-SHM version"); + return; + } + + has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) || + shm_query->major_version > 1; } void QXcbConnection::initializeXFixes() diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index b2713b8ac7..dbc1c4561d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -480,6 +480,7 @@ public: bool hasXRender() const { return has_render_extension; } bool hasXInput2() const { return m_xi2Enabled; } bool hasShm() const { return has_shm; } + bool hasShmFd() const { return has_shm_fd; } bool threadedEventHandling() const { return m_reader->isRunning(); } @@ -703,6 +704,7 @@ private: bool has_xkb = false; bool has_render_extension = false; bool has_shm = false; + bool has_shm_fd = false; Qt::MouseButtons m_buttonState = 0; Qt::MouseButton m_button = Qt::NoButton; -- cgit v1.2.3