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
|
@ -0,0 +1,122 @@
|
|||
#include "hyprland_screencopy.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
#include <qlogging.h>
|
||||
#include <qloggingcategory.h>
|
||||
#include <qobject.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qwaylandclientextension.h>
|
||||
#include <wayland-hyprland-toplevel-export-v1-client-protocol.h>
|
||||
|
||||
#include "../../toplevel_management/handle.hpp"
|
||||
#include "../manager.hpp"
|
||||
#include "hyprland_screencopy_p.hpp"
|
||||
|
||||
namespace qs::wayland::screencopy::hyprland {
|
||||
|
||||
namespace {
|
||||
Q_LOGGING_CATEGORY(logScreencopy, "quickshell.wayland.screencopy.hyprland", QtWarningMsg);
|
||||
}
|
||||
|
||||
HyprlandScreencopyManager::HyprlandScreencopyManager(): QWaylandClientExtensionTemplate(2) {
|
||||
this->initialize();
|
||||
}
|
||||
|
||||
HyprlandScreencopyManager* HyprlandScreencopyManager::instance() {
|
||||
static auto* instance = new HyprlandScreencopyManager();
|
||||
return instance;
|
||||
}
|
||||
|
||||
ScreencopyContext* HyprlandScreencopyManager::captureToplevel(
|
||||
toplevel_management::impl::ToplevelHandle* handle,
|
||||
bool paintCursors
|
||||
) {
|
||||
return new HyprlandScreencopyContext(this, handle, paintCursors);
|
||||
}
|
||||
|
||||
HyprlandScreencopyContext::HyprlandScreencopyContext(
|
||||
HyprlandScreencopyManager* manager,
|
||||
toplevel_management::impl::ToplevelHandle* handle,
|
||||
bool paintCursors
|
||||
)
|
||||
: manager(manager)
|
||||
, handle(handle)
|
||||
, paintCursors(paintCursors) {
|
||||
QObject::connect(
|
||||
handle,
|
||||
&QObject::destroyed,
|
||||
this,
|
||||
&HyprlandScreencopyContext::onToplevelDestroyed
|
||||
);
|
||||
}
|
||||
|
||||
HyprlandScreencopyContext::~HyprlandScreencopyContext() {
|
||||
if (this->object()) this->destroy();
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::onToplevelDestroyed() {
|
||||
qCWarning(logScreencopy) << "Toplevel destroyed while recording. Stopping" << this;
|
||||
if (this->object()) this->destroy();
|
||||
emit this->stopped();
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::captureFrame() {
|
||||
if (this->object()) return;
|
||||
|
||||
this->init(this->manager->capture_toplevel_with_wlr_toplevel_handle(
|
||||
this->paintCursors ? 1 : 0,
|
||||
this->handle->object()
|
||||
));
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::hyprland_toplevel_export_frame_v1_buffer(
|
||||
uint32_t format,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t /*stride*/
|
||||
) {
|
||||
// While different sizes can technically be requested, that would be insane.
|
||||
this->request.width = width;
|
||||
this->request.height = height;
|
||||
this->request.shm.formats.push(format);
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::hyprland_toplevel_export_frame_v1_linux_dmabuf(
|
||||
uint32_t format,
|
||||
uint32_t width,
|
||||
uint32_t height
|
||||
) {
|
||||
// While different sizes can technically be requested, that would be insane.
|
||||
this->request.width = width;
|
||||
this->request.height = height;
|
||||
this->request.dmabuf.formats.push(format);
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::hyprland_toplevel_export_frame_v1_flags(uint32_t flags) {
|
||||
if (flags & HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_FLAGS_Y_INVERT) {
|
||||
this->mSwapchain.backbuffer()->transform = buffer::WlBufferTransform::Flipped180;
|
||||
}
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::hyprland_toplevel_export_frame_v1_buffer_done() {
|
||||
auto* backbuffer = this->mSwapchain.createBackbuffer(this->request);
|
||||
this->copy(backbuffer->buffer(), this->copiedFirstFrame ? 0 : 1);
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::hyprland_toplevel_export_frame_v1_ready(
|
||||
uint32_t /*tvSecHi*/,
|
||||
uint32_t /*tvSecLo*/,
|
||||
uint32_t /*tvNsec*/
|
||||
) {
|
||||
this->destroy();
|
||||
this->copiedFirstFrame = true;
|
||||
this->mSwapchain.swapBuffers();
|
||||
emit this->frameCaptured();
|
||||
}
|
||||
|
||||
void HyprlandScreencopyContext::hyprland_toplevel_export_frame_v1_failed() {
|
||||
qCWarning(logScreencopy) << "Ending recording due to screencopy failure for" << this;
|
||||
emit this->stopped();
|
||||
}
|
||||
|
||||
} // namespace qs::wayland::screencopy::hyprland
|
Loading…
Add table
Add a link
Reference in a new issue