forked from quickshell/quickshell
wayland/screencopy: add screencopy
This commit is contained in:
parent
918dd2392d
commit
cd429142a4
37 changed files with 3149 additions and 3 deletions
91
src/wayland/buffer/shm.cpp
Normal file
91
src/wayland/buffer/shm.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "shm.hpp"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <private/qwaylanddisplay_p.h>
|
||||
#include <private/qwaylandintegration_p.h>
|
||||
#include <private/qwaylandshm_p.h>
|
||||
#include <private/qwaylandshmbackingstore_p.h>
|
||||
#include <qdebug.h>
|
||||
#include <qlogging.h>
|
||||
#include <qloggingcategory.h>
|
||||
#include <qquickwindow.h>
|
||||
#include <qsize.h>
|
||||
#include <wayland-client-protocol.h>
|
||||
|
||||
#include "manager.hpp"
|
||||
|
||||
namespace qs::wayland::buffer::shm {
|
||||
|
||||
Q_LOGGING_CATEGORY(logShm, "quickshell.wayland.buffer.shm", QtWarningMsg);
|
||||
|
||||
bool WlShmBuffer::isCompatible(const WlBufferRequest& request) const {
|
||||
if (QSize(static_cast<int>(request.width), static_cast<int>(request.height)) != this->size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto matchingFormat = std::ranges::find(request.shm.formats, this->format);
|
||||
return matchingFormat != request.shm.formats.end();
|
||||
}
|
||||
|
||||
QDebug& operator<<(QDebug& debug, const WlShmBuffer* buffer) {
|
||||
auto saver = QDebugStateSaver(debug);
|
||||
debug.nospace();
|
||||
|
||||
if (buffer) {
|
||||
auto fmt = QtWaylandClient::QWaylandShm::formatFrom(
|
||||
static_cast<::wl_shm_format>(buffer->format) // NOLINT
|
||||
);
|
||||
|
||||
debug << "WlShmBuffer(" << static_cast<const void*>(buffer) << ", size=" << buffer->size()
|
||||
<< ", format=" << fmt << ')';
|
||||
} else {
|
||||
debug << "WlShmBuffer(0x0)";
|
||||
}
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
WlShmBuffer::~WlShmBuffer() { qCDebug(logShm) << "Destroyed" << this; }
|
||||
|
||||
WlBufferQSGTexture* WlShmBuffer::createQsgTexture(QQuickWindow* window) const {
|
||||
auto* texture = new WlShmBufferQSGTexture();
|
||||
|
||||
// If the QWaylandShmBuffer is destroyed before the QSGTexture, we'll hit a UAF
|
||||
// in the render thread.
|
||||
texture->shmBuffer = this->shmBuffer;
|
||||
|
||||
texture->qsgTexture.reset(window->createTextureFromImage(*this->shmBuffer->image()));
|
||||
texture->sync(this, window);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void WlShmBufferQSGTexture::sync(const WlBuffer* /*unused*/, QQuickWindow* window) {
|
||||
// This is both dumb and expensive. We should use an RHI texture and render images into
|
||||
// it more intelligently, but shm buffers are already a horribly slow fallback path,
|
||||
// to the point where it barely matters.
|
||||
this->qsgTexture.reset(window->createTextureFromImage(*this->shmBuffer->image()));
|
||||
}
|
||||
|
||||
WlBuffer* ShmbufManager::createShmbuf(const WlBufferRequest& request) {
|
||||
if (request.shm.formats.isEmpty()) return nullptr;
|
||||
|
||||
static const auto* waylandIntegration = QtWaylandClient::QWaylandIntegration::instance();
|
||||
auto* display = waylandIntegration->display();
|
||||
|
||||
// Its probably fine...
|
||||
auto format = request.shm.formats[0];
|
||||
|
||||
auto* buffer = new WlShmBuffer(
|
||||
new QtWaylandClient::QWaylandShmBuffer(
|
||||
display,
|
||||
QSize(static_cast<int>(request.width), static_cast<int>(request.height)),
|
||||
QtWaylandClient::QWaylandShm::formatFrom(static_cast<::wl_shm_format>(format)) // NOLINT
|
||||
),
|
||||
format
|
||||
);
|
||||
|
||||
qCDebug(logShm) << "Created shmbuf" << buffer;
|
||||
return buffer;
|
||||
}
|
||||
} // namespace qs::wayland::buffer::shm
|
Loading…
Add table
Add a link
Reference in a new issue