summaryrefslogtreecommitdiffstats
path: root/src/client/qwaylandshmbackingstore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/qwaylandshmbackingstore.cpp')
-rw-r--r--src/client/qwaylandshmbackingstore.cpp51
1 files changed, 32 insertions, 19 deletions
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
index 045748a16..2085bc597 100644
--- a/src/client/qwaylandshmbackingstore.cpp
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -44,6 +44,8 @@
#include "qwaylandabstractdecoration_p.h"
#include <QtCore/qdebug.h>
+#include <QtCore/qstandardpaths.h>
+#include <QtCore/qtemporaryfile.h>
#include <QtGui/QPainter>
#include <QMutexLocker>
#include <QLoggingCategory>
@@ -52,10 +54,14 @@
#include <wayland-client-protocol.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
#include <sys/mman.h>
+#ifdef Q_OS_LINUX
+# include <sys/syscall.h>
+// from linux/memfd.h:
+# define MFD_CLOEXEC 0x0001U
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -72,28 +78,36 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
{
int stride = size.width() * 4;
int alloc = stride * size.height();
- char filename[] = "/tmp/wayland-shm-XXXXXX";
- int fd = mkstemp(filename);
- if (fd < 0) {
- qWarning("mkstemp %s failed: %s", filename, strerror(errno));
- return;
+ int fd = -1;
+
+#ifdef SYS_memfd_create
+ fd = syscall(SYS_memfd_create, "wayland-shm", MFD_CLOEXEC);
+#endif
+
+ QScopedPointer<QFile> filePointer;
+
+ if (fd == -1) {
+ auto tmpFile = new QTemporaryFile (QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) +
+ QLatin1String("/wayland-shm-XXXXXX"));
+ tmpFile->open();
+ filePointer.reset(tmpFile);
+ } else {
+ auto file = new QFile;
+ file->open(fd, QIODevice::ReadWrite | QIODevice::Unbuffered, QFile::AutoCloseHandle);
+ filePointer.reset(file);
}
- int flags = fcntl(fd, F_GETFD);
- if (flags != -1)
- fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
-
- if (ftruncate(fd, alloc) < 0) {
- qWarning("ftruncate failed: %s", strerror(errno));
- close(fd);
+ if (!filePointer->isOpen() || !filePointer->resize(alloc)) {
+ qWarning("QWaylandShmBuffer: failed: %s", qUtf8Printable(filePointer->errorString()));
return;
}
+ fd = filePointer->handle();
+
+ // map ourselves: QFile::map() will unmap when the object is destroyed,
+ // but we want this mapping to persist (unmapping in destructor)
uchar *data = (uchar *)
mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- unlink(filename);
-
if (data == (uchar *) MAP_FAILED) {
- qWarning("mmap /dev/zero failed: %s", strerror(errno));
- close(fd);
+ qErrnoWarning("QWaylandShmBuffer: mmap failed");
return;
}
@@ -105,7 +119,6 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
mShmPool = wl_shm_create_pool(shm->object(), fd, alloc);
init(wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
stride, wl_format));
- close(fd);
}
QWaylandShmBuffer::~QWaylandShmBuffer(void)