11#include " wlr_screencopy.hpp"
22#include < cstdint>
33
4+ #include < private/qwaylanddisplay_p.h>
45#include < private/qwaylandscreen_p.h>
56#include < qlogging.h>
67#include < qloggingcategory.h>
78#include < qobject.h>
89#include < qscreen.h>
910#include < qtmetamacros.h>
11+ #include < qtypes.h>
1012#include < qwaylandclientextension.h>
1113#include < wayland-wlr-screencopy-unstable-v1-client-protocol.h>
1214
@@ -45,6 +47,7 @@ WlrScreencopyContext::WlrScreencopyContext(
4547 , screen(dynamic_cast <QtWaylandClient::QWaylandScreen*>(screen->handle ()))
4648 , paintCursors(paintCursors)
4749 , region(region) {
50+ this ->transform .setScreen (this ->screen );
4851 QObject::connect (screen, &QObject::destroyed, this , &WlrScreencopyContext::onScreenDestroyed);
4952}
5053
@@ -99,9 +102,7 @@ void WlrScreencopyContext::zwlr_screencopy_frame_v1_linux_dmabuf(
99102}
100103
101104void WlrScreencopyContext::zwlr_screencopy_frame_v1_flags (uint32_t flags) {
102- if (flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT) {
103- this ->mSwapchain .backbuffer ()->transform = buffer::WlBufferTransform::Flipped180;
104- }
105+ this ->yInvert = flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT;
105106}
106107
107108void WlrScreencopyContext::zwlr_screencopy_frame_v1_buffer_done () {
@@ -119,15 +120,69 @@ void WlrScreencopyContext::zwlr_screencopy_frame_v1_ready(
119120 uint32_t /* tvSecLo*/ ,
120121 uint32_t /* tvNsec*/
121122) {
122- this ->destroy ();
123- this ->copiedFirstFrame = true ;
124- this ->mSwapchain .swapBuffers ();
125- emit this ->frameCaptured ();
123+ this ->submitFrame ();
126124}
127125
128126void WlrScreencopyContext::zwlr_screencopy_frame_v1_failed () {
129127 qCWarning (logScreencopy) << " Ending recording due to screencopy failure for" << this ;
130128 emit this ->stopped ();
131129}
132130
131+ void WlrScreencopyContext::updateTransform (bool previouslyUnset) {
132+ if (previouslyUnset && this ->copiedFirstFrame ) this ->submitFrame ();
133+ }
134+
135+ void WlrScreencopyContext::submitFrame () {
136+ this ->copiedFirstFrame = true ;
137+ if (this ->transform .transform == -1 ) return ;
138+
139+ auto flipTransform =
140+ this ->yInvert ? buffer::WlBufferTransform::Flipped180 : buffer::WlBufferTransform::Normal0;
141+
142+ this ->mSwapchain .backbuffer ()->transform = this ->transform .transform ^ flipTransform;
143+
144+ this ->destroy ();
145+ this ->mSwapchain .swapBuffers ();
146+ emit this ->frameCaptured ();
147+ }
148+
149+ WlrScreencopyContext::OutputTransformQuery::OutputTransformQuery (WlrScreencopyContext* context)
150+ : context(context) {}
151+
152+ WlrScreencopyContext::OutputTransformQuery::~OutputTransformQuery () {
153+ if (this ->isInitialized ()) this ->release ();
154+ }
155+
156+ void WlrScreencopyContext::OutputTransformQuery::setScreen (QtWaylandClient::QWaylandScreen* screen
157+ ) {
158+ // cursed hack
159+ class QWaylandScreenReflector : public QtWaylandClient ::QWaylandScreen {
160+ public:
161+ [[nodiscard]] int globalId () const { return this ->m_outputId ; }
162+ };
163+
164+ if (this ->isInitialized ()) this ->release ();
165+
166+ this ->init (
167+ screen->display ()->wl_registry (),
168+ static_cast <QWaylandScreenReflector*>(screen)->globalId (), // NOLINT
169+ 3
170+ );
171+ }
172+
173+ void WlrScreencopyContext::OutputTransformQuery::output_geometry (
174+ qint32 /* x*/ ,
175+ qint32 /* y*/ ,
176+ qint32 /* width*/ ,
177+ qint32 /* height*/ ,
178+ qint32 /* subpixel*/ ,
179+ const QString& /* make*/ ,
180+ const QString& /* model*/ ,
181+ qint32 transform
182+ ) {
183+ auto newTransform = this ->transform == -1 ;
184+ this ->transform = transform;
185+ this ->context ->updateTransform (newTransform);
186+ }
187+
133188} // namespace qs::wayland::screencopy::wlr
0 commit comments