13#include <QtWaylandCompositor/qwaylandcompositor.h>
14#include <QtWaylandCompositor/qwaylandseat.h>
15#include <QtWaylandCompositor/qwaylandbufferref.h>
16#if QT_CONFIG(draganddrop)
17#include <QtWaylandCompositor/QWaylandDrag>
19#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h>
20#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
23# include <QtOpenGL/QOpenGLTexture>
24# include <QtGui/QOpenGLFunctions>
27#include <QtGui/QKeyEvent>
28#include <QtGui/QGuiApplication>
29#include <QtGui/QScreen>
31#include <QtQuick/QSGSimpleTextureNode>
32#include <QtQuick/QQuickWindow>
33#include <QtQuick/qsgtexture.h>
35#include <QtCore/QFile>
36#include <QtCore/QMutexLocker>
37#include <QtCore/QMutex>
39#include <wayland-server-core.h>
43#include <QtGui/private/qshaderdescription_p.h>
46#ifndef GL_TEXTURE_EXTERNAL_OES
47#define GL_TEXTURE_EXTERNAL_OES 0x8D65
54 const char *
const vertexShaderSourceFile;
55 const char *
const fragmentShaderSourceFile;
57 bool canProvideTexture;
58 QSGMaterial::Flags materialFlags;
59 QSGMaterialType materialType;
62 {
"",
"", 0,
false, {}, {} },
66 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
67 ":/qt-project.org/wayland/compositor/shaders/surface_rgbx.frag.qsb",
69 QSGMaterial::Blending,
75 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
76 ":/qt-project.org/wayland/compositor/shaders/surface_rgba.frag.qsb",
78 QSGMaterial::Blending,
84 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
85 ":/qt-project.org/wayland/compositor/shaders/surface_oes_external.frag",
87 QSGMaterial::Blending,
93 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
94 ":/qt-project.org/wayland/compositor/shaders/surface_y_u_v.frag.qsb",
96 QSGMaterial::Blending,
102 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
103 ":/qt-project.org/wayland/compositor/shaders/surface_y_uv.frag.qsb",
105 QSGMaterial::Blending,
111 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
112 ":/qt-project.org/wayland/compositor/shaders/surface_y_xuxv.frag.qsb",
114 QSGMaterial::Blending,
119QWaylandBufferMaterialShader::QWaylandBufferMaterialShader(QWaylandBufferRef::BufferFormatEgl format)
122 setShaderFileName(VertexStage, QString::fromLatin1(bufferTypes[format].vertexShaderSourceFile));
123 auto fragmentShaderSourceFile = QString::fromLatin1(bufferTypes[format].fragmentShaderSourceFile);
125 if (format == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES)
126 setupExternalOESShader(fragmentShaderSourceFile);
128 setShaderFileName(FragmentStage, fragmentShaderSourceFile);
131void QWaylandBufferMaterialShader::setupExternalOESShader(
const QString &shaderFilename)
134 QFile shaderFile(shaderFilename);
135 if (!shaderFile.open(QIODevice::ReadOnly)) {
136 qCWarning(qLcWaylandCompositor) <<
"Cannot find external OES shader file:" << shaderFilename;
139 QByteArray FS = shaderFile.readAll();
141 static const char *FS_GLES_PREAMBLE =
142 "#extension GL_OES_EGL_image_external : require\n"
143 "precision highp float;\n";
144 static const char *FS_GL_PREAMBLE =
146 "#extension GL_OES_EGL_image_external : require\n";
147 QByteArray fsGLES = FS_GLES_PREAMBLE + FS;
148 QByteArray fsGL = FS_GL_PREAMBLE + FS;
150 QShaderDescription desc;
151 QShaderDescriptionPrivate *descData = QShaderDescriptionPrivate::get(&desc);
153 QShaderDescription::InOutVariable texCoordInput;
154 texCoordInput.name =
"v_texcoord";
155 texCoordInput.type = QShaderDescription::Vec2;
156 texCoordInput.location = 0;
158 descData->inVars = { texCoordInput };
160 QShaderDescription::InOutVariable fragColorOutput;
161 fragColorOutput.name =
"gl_FragColor";
162 fragColorOutput.type = QShaderDescription::Vec4;
163 fragColorOutput.location = 0;
165 descData->outVars = { fragColorOutput };
167 QShaderDescription::BlockVariable matrixBlockVar;
168 matrixBlockVar.name =
"qt_Matrix";
169 matrixBlockVar.type = QShaderDescription::Mat4;
170 matrixBlockVar.offset = 0;
171 matrixBlockVar.size = 64;
173 QShaderDescription::BlockVariable opacityBlockVar;
174 opacityBlockVar.name =
"qt_Opacity";
175 opacityBlockVar.type = QShaderDescription::Float;
176 opacityBlockVar.offset = 64;
177 opacityBlockVar.size = 4;
179 QShaderDescription::UniformBlock ubufStruct;
180 ubufStruct.blockName =
"buf";
181 ubufStruct.structName =
"ubuf";
182 ubufStruct.size = 64 + 4;
183 ubufStruct.binding = 0;
184 ubufStruct.members = { matrixBlockVar, opacityBlockVar };
186 descData->uniformBlocks = { ubufStruct };
188 QShaderDescription::InOutVariable samplerTex0;
189 samplerTex0.name =
"tex0";
190 samplerTex0.type = QShaderDescription::SamplerExternalOES;
191 samplerTex0.binding = 1;
193 descData->combinedImageSamplers = { samplerTex0 };
196 shaderPack.setStage(QShader::FragmentStage);
197 shaderPack.setDescription(desc);
198 shaderPack.setShader(QShaderKey(QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs)), QShaderCode(fsGLES));
199 shaderPack.setShader(QShaderKey(QShader::GlslShader, QShaderVersion(120)), QShaderCode(fsGL));
201 setShader(FragmentStage, shaderPack);
203 Q_UNUSED(shaderFilename);
207bool QWaylandBufferMaterialShader::updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *)
209 bool changed =
false;
210 QByteArray *buf = state.uniformData();
211 Q_ASSERT(buf->size() >= 68);
213 if (state.isMatrixDirty()) {
214 const QMatrix4x4 m = state.combinedMatrix();
215 memcpy(buf->data(), m.constData(), 64);
219 if (state.isOpacityDirty()) {
220 const float opacity = state.opacity();
221 memcpy(buf->data() + 64, &opacity, 4);
228void QWaylandBufferMaterialShader::updateSampledImage(RenderState &state,
int binding, QSGTexture **texture,
229 QSGMaterial *newMaterial, QSGMaterial *)
233 QWaylandBufferMaterial *material =
static_cast<QWaylandBufferMaterial *>(newMaterial);
236 *texture = material->m_scenegraphTextures.at(0);
239 *texture = material->m_scenegraphTextures.at(1);
242 *texture = material->m_scenegraphTextures.at(2);
252 (*texture)->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
255QWaylandBufferMaterial::QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEgl format)
258 setFlag(bufferTypes[m_format].materialFlags);
261QWaylandBufferMaterial::~QWaylandBufferMaterial()
263 qDeleteAll(m_scenegraphTextures);
266void QWaylandBufferMaterial::setTextureForPlane(
int plane,
267 QOpenGLTexture *texture,
268 QSGTexture *scenegraphTexture)
270 if (plane < 0 || plane >= bufferTypes[m_format].planeCount) {
271 qWarning(
"plane index is out of range");
276 setTextureParameters(texture->target());
278 ensureTextures(plane - 1);
280 if (m_textures.size() <= plane) {
281 m_textures << texture;
282 m_scenegraphTextures << scenegraphTexture;
284 delete m_scenegraphTextures[plane];
286 m_textures[plane] = texture;
287 m_scenegraphTextures[plane] = scenegraphTexture;
291void QWaylandBufferMaterial::bind()
293 ensureTextures(bufferTypes[m_format].planeCount);
295 switch (m_textures.size()) {
298 m_textures[2]->bind(2);
302 m_textures[1]->bind(1);
306 m_textures[0]->bind(0);
310QSGMaterialType *QWaylandBufferMaterial::type()
const
312 return const_cast<QSGMaterialType *>(&bufferTypes[m_format].materialType);
315QSGMaterialShader *QWaylandBufferMaterial::createShader(QSGRendererInterface::RenderMode renderMode)
const
317 Q_UNUSED(renderMode);
318 return new QWaylandBufferMaterialShader(m_format);
322void QWaylandBufferMaterial::setTextureParameters(GLenum target)
324 QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
325 gl->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
326 gl->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
327 gl->glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
328 gl->glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
332void QWaylandBufferMaterial::ensureTextures(
int count)
334 for (
int plane = m_textures.size(); plane < count; plane++) {
335 m_textures <<
nullptr;
336 m_scenegraphTextures <<
nullptr;
340void QWaylandBufferMaterial::setBufferRef(QWaylandQuickItem *surfaceItem,
const QWaylandBufferRef &ref)
343 for (
int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++) {
344 if (
auto texture = ref.toOpenGLTexture(plane)) {
345 QQuickWindow::CreateTextureOptions opt;
346 QWaylandQuickSurface *waylandSurface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
347 if (waylandSurface !=
nullptr && waylandSurface->useTextureAlpha() && !waylandSurface->isOpaque())
348 opt |= QQuickWindow::TextureHasAlphaChannel;
349 QSGTexture *scenegraphTexture;
350 if (ref.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES) {
351 scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNativeExternalOES(texture->textureId(),
352 surfaceItem->window(),
356 scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNative(texture->textureId(),
357 surfaceItem->window(),
361 scenegraphTexture->setFiltering(surfaceItem->smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
362 setTextureForPlane(plane, texture, scenegraphTexture);
370QMutex *QWaylandQuickItemPrivate::mutex =
nullptr;
390 if (m_compositorDestroyed.loadAcquire() && m_ref.hasBuffer())
391 m_ref.buffer()->setDestroyed();
396 void setBufferRef(QWaylandQuickItem *surfaceItem,
const QWaylandBufferRef &buffer)
398 Q_ASSERT(QThread::currentThread() == thread());
402 if (m_ref.hasBuffer()) {
403 if (buffer.isSharedMemory()) {
404 m_sgTex = surfaceItem->window()->createTextureFromImage(buffer.image());
407 QQuickWindow::CreateTextureOptions opt;
408 QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
409 if (surface && surface->useTextureAlpha() && !surface->isOpaque()) {
410 opt |= QQuickWindow::TextureHasAlphaChannel;
413 auto texture = buffer.toOpenGLTexture();
414 GLuint textureId = texture->textureId();
415 auto size = surface->bufferSize();
416 m_sgTex = QNativeInterface::QSGOpenGLTexture::fromNative(textureId, surfaceItem->window(), size, opt);
418 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
422 emit textureChanged();
428 m_sgTex->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
436 m_compositorDestroyed.storeRelease(1);
441 bool m_smooth =
false;
442 QSGTexture *m_sgTex =
nullptr;
444 QAtomicInt m_compositorDestroyed;
445 QWaylandBufferRef m_ref;
450#if QT_CONFIG(draganddrop)
451 Q_Q(QWaylandQuickItem);
452 QWaylandQuickOutput *currentOutput = qobject_cast<QWaylandQuickOutput *>(q->view()->output());
454 QWaylandQuickItem *targetItem = qobject_cast<QWaylandQuickItem *>(currentOutput->pickClickableItem(q->mapToScene(globalPosition)));
455 QWaylandSurface *targetSurface = targetItem ? targetItem->surface() :
nullptr;
457 QPointF position = q->mapToItem(targetItem, globalPosition);
458 QPointF surfacePosition = targetItem->mapToSurface(position);
459 seat->drag()->dragMove(targetSurface, surfacePosition);
463 Q_UNUSED(globalPosition);
469#if QT_CONFIG(draganddrop)
471 seat->drag()->drop();
478
479
480
481
482
483
484
485
486
487
490
491
492
493
494
495
496
497
498
501
502
503QWaylandQuickItem::QWaylandQuickItem(QQuickItem *parent)
504 : QWaylandQuickItem(*
new QWaylandQuickItemPrivate(), parent)
509
510
511QWaylandQuickItem::QWaylandQuickItem(QWaylandQuickItemPrivate &dd, QQuickItem *parent)
512 : QQuickItem(dd, parent)
515 connect(
this, &QQuickItem::activeFocusChanged,
this, &QWaylandQuickItem::updateFocus);
519
520
521QWaylandQuickItem::~QWaylandQuickItem()
523 Q_D(QWaylandQuickItem);
524 disconnect(
this, &QQuickItem::windowChanged,
this, &QWaylandQuickItem::updateWindow);
525 disconnect(
this, &QQuickItem::activeFocusChanged,
this, &QWaylandQuickItem::updateFocus);
526 QMutexLocker locker(d->mutex);
528 disconnect(d->texProviderConnection);
529 d->provider->deleteLater();
534
535
536
537
540
541
542
543
544QWaylandCompositor *QWaylandQuickItem::compositor()
const
546 Q_D(
const QWaylandQuickItem);
547 return d->view->surface() ? d->view->surface()->compositor() :
nullptr;
551
552
553QWaylandView *QWaylandQuickItem::view()
const
555 Q_D(
const QWaylandQuickItem);
556 return d->view.data();
560
561
562
563
566
567
568
569
571QWaylandSurface *QWaylandQuickItem::surface()
const
573 Q_D(
const QWaylandQuickItem);
574 return d->view->surface();
577void QWaylandQuickItem::setSurface(QWaylandSurface *surface)
579 Q_D(QWaylandQuickItem);
580 QWaylandSurface *oldSurf = d->view->surface();
581 if (oldSurf == surface)
584 QWaylandCompositor *oldComp = oldSurf ? oldSurf->compositor() :
nullptr;
585 QWaylandCompositor *newComp = surface ? surface->compositor() :
nullptr;
586 if (oldComp != newComp)
587 emit compositorChanged();
589 d->view->setSurface(surface);
596
597
598
599
600
601
602
605
606
607
608
609
610
611
612QWaylandSurface::Origin QWaylandQuickItem::origin()
const
614 Q_D(
const QWaylandQuickItem);
618bool QWaylandQuickItem::isTextureProvider()
const
620 Q_D(
const QWaylandQuickItem);
621 return QQuickItem::isTextureProvider() || d->provider;
625
626
627QSGTextureProvider *QWaylandQuickItem::textureProvider()
const
629 Q_D(
const QWaylandQuickItem);
631 if (QQuickItem::isTextureProvider())
632 return QQuickItem::textureProvider();
638
639
640void QWaylandQuickItem::mousePressEvent(QMouseEvent *event)
642 Q_D(QWaylandQuickItem);
643 if (!d->shouldSendInputEvents()) {
648 if (!inputRegionContains(event->position())) {
653 QWaylandSeat *seat = compositor()->seatFor(event);
658 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), event->scenePosition());
659 seat->sendMousePressEvent(event->button());
660 d->hoverPos = event->position();
664
665
666void QWaylandQuickItem::mouseMoveEvent(QMouseEvent *event)
668 Q_D(QWaylandQuickItem);
669 if (d->shouldSendInputEvents()) {
670 QWaylandSeat *seat = compositor()->seatFor(event);
672 d->handleDragUpdate(seat, event->position());
674 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), event->scenePosition());
675 d->hoverPos = event->position();
678 emit mouseMove(event->scenePosition());
684
685
686void QWaylandQuickItem::mouseReleaseEvent(QMouseEvent *event)
688 Q_D(QWaylandQuickItem);
689 if (d->shouldSendInputEvents()) {
690 QWaylandSeat *seat = compositor()->seatFor(event);
692 d->handleDragEnded(seat);
694 seat->sendMouseReleaseEvent(event->button());
702
703
704void QWaylandQuickItem::hoverEnterEvent(QHoverEvent *event)
706 Q_D(QWaylandQuickItem);
707 if (!inputRegionContains(event->position())) {
711 if (d->shouldSendInputEvents()) {
712 QWaylandSeat *seat = compositor()->seatFor(event);
713 seat->sendMouseMoveEvent(d->view.data(), event->position(), mapToScene(event->position()));
714 d->hoverPos = event->position();
721
722
723void QWaylandQuickItem::hoverMoveEvent(QHoverEvent *event)
725 Q_D(QWaylandQuickItem);
727 if (!inputRegionContains(event->position())) {
732 if (d->shouldSendInputEvents()) {
733 QWaylandSeat *seat = compositor()->seatFor(event);
734 if (event->position() != d->hoverPos) {
735 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), mapToScene(event->position()));
736 d->hoverPos = event->position();
744
745
746void QWaylandQuickItem::hoverLeaveEvent(QHoverEvent *event)
748 Q_D(QWaylandQuickItem);
749 if (d->shouldSendInputEvents()) {
750 QWaylandSeat *seat = compositor()->seatFor(event);
751 if (d->view.data() == seat->mouseFocus()) {
752 seat->setMouseFocus(
nullptr);
760#if QT_CONFIG(wheelevent)
762
763
764void QWaylandQuickItem::wheelEvent(QWheelEvent *event)
766 Q_D(QWaylandQuickItem);
767 if (d->shouldSendInputEvents()) {
768 if (!inputRegionContains(event->position())) {
773 QWaylandSeat *seat = compositor()->seatFor(event);
775 if (event->angleDelta().x() != 0)
776 seat->sendMouseWheelEvent(Qt::Horizontal, event->angleDelta().x());
777 if (event->angleDelta().y() != 0)
778 seat->sendMouseWheelEvent(Qt::Vertical, event->angleDelta().y());
786
787
788void QWaylandQuickItem::keyPressEvent(QKeyEvent *event)
790 Q_D(QWaylandQuickItem);
791 if (d->shouldSendInputEvents()) {
792 QWaylandSeat *seat = compositor()->seatFor(event);
793 if (seat->setKeyboardFocus(d->view->surface()))
794 seat->sendFullKeyEvent(event);
796 qWarning() <<
"Unable to set keyboard focus, cannot send key press event";
803
804
805void QWaylandQuickItem::keyReleaseEvent(QKeyEvent *event)
807 Q_D(QWaylandQuickItem);
808 if (d->shouldSendInputEvents()) {
809 QWaylandSeat *seat = compositor()->seatFor(event);
810 seat->sendFullKeyEvent(event);
817
818
819void QWaylandQuickItem::touchEvent(QTouchEvent *event)
821 Q_D(QWaylandQuickItem);
822 if (d->shouldSendInputEvents() && d->touchEventsEnabled) {
823 QWaylandSeat *seat = compositor()->seatFor(event);
826 const QList<QTouchEvent::TouchPoint> &points = event->points();
827 if (!points.isEmpty())
828 pointPos = points.at(0).position();
830 if (event->type() == QEvent::TouchBegin && !inputRegionContains(pointPos)) {
835 if (event->type() == QEvent::TouchUpdate && d->isDragging)
836 d->handleDragUpdate(seat, pointPos);
839 if (seat->mouseFocus() != d->view.data()) {
840 seat->sendMouseMoveEvent(d->view.data(), pointPos, mapToScene(pointPos));
842 seat->sendFullTouchEvent(surface(), event);
844 if (event->type() == QEvent::TouchBegin) {
845 d->touchingSeats.append(seat);
846 }
else if (event->type() == QEvent::TouchEnd || event->type() == QEvent::TouchCancel) {
848 d->handleDragEnded(seat);
849 d->touchingSeats.removeOne(seat);
852 if (event->type() == QEvent::TouchBegin && d->focusOnClick)
859void QWaylandQuickItem::touchUngrabEvent()
861 Q_D(QWaylandQuickItem);
863 if (d->shouldSendInputEvents()) {
864 for (
auto seat : std::as_const(d->touchingSeats))
865 seat->sendTouchCancelEvent(surface()->client());
868 d->touchingSeats.clear();
873
874
875void QWaylandQuickItem::inputMethodEvent(QInputMethodEvent *event)
877 Q_D(QWaylandQuickItem);
878 if (d->shouldSendInputEvents()) {
879 d->oldSurface->inputMethodControl()->inputMethodEvent(event);
887
888
889void QWaylandQuickItem::surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface)
891 Q_UNUSED(newSurface);
892 Q_UNUSED(oldSurface);
895void QWaylandQuickItem::handleSubsurfaceAdded(QWaylandSurface *childSurface)
897 Q_D(QWaylandQuickItem);
898 if (d->subsurfaceHandler.isNull()) {
899 QWaylandQuickItem *childItem =
new QWaylandQuickItem;
900 childItem->setSurface(childSurface);
901 childItem->setVisible(
true);
902 childItem->setParentItem(
this);
903 childItem->setParent(
this);
904 childItem->setPosition(QWaylandSurfacePrivate::get(childSurface)->subsurfacePosition() * d->scaleFactor());
905 connect(childSurface, &QWaylandSurface::subsurfacePositionChanged, childItem, &QWaylandQuickItem::handleSubsurfacePosition);
906 connect(childSurface, &QWaylandSurface::destroyed, childItem, &QObject::deleteLater);
908 bool success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded", Q_ARG(QWaylandSurface *, childSurface));
910 success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded",
911 Q_ARG(QVariant, QVariant::fromValue(childSurface)));
914 qWarning(
"QWaylandQuickItem: subsurfaceHandler does not implement handleSubsurfaceAdded()");
918void QWaylandQuickItem::handlePlaceAbove(QWaylandSurface *referenceSurface)
920 Q_D(QWaylandQuickItem);
921 auto *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
925 if (parent->surface() == referenceSurface) {
926 d->placeAboveParent();
927 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
928 d->placeAboveSibling(sibling);
930 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
931 <<
"when handling wl_subsurface.place_above";
935void QWaylandQuickItem::handlePlaceBelow(QWaylandSurface *referenceSurface)
937 Q_D(QWaylandQuickItem);
938 QWaylandQuickItem *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
942 if (parent->surface() == referenceSurface) {
943 d->placeBelowParent();
944 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
945 d->placeBelowSibling(sibling);
947 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
948 <<
"when handling wl_subsurface.place_below";
952void QWaylandQuickItem::updateFocus()
954 Q_D(
const QWaylandQuickItem);
955 if (hasActiveFocus() && compositor())
956 compositor()->defaultSeat()->setKeyboardFocus(d->view->surface());
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
983
984
985
986
987
988
989
990
991
992
993
994
995
996QObject *QWaylandQuickItem::subsurfaceHandler()
const
998 Q_D(
const QWaylandQuickItem);
999 return d->subsurfaceHandler.data();
1002void QWaylandQuickItem::setSubsurfaceHandler(QObject *handler)
1004 Q_D(QWaylandQuickItem);
1005 if (d->subsurfaceHandler.data() != handler) {
1006 d->subsurfaceHandler = handler;
1007 emit subsurfaceHandlerChanged();
1012
1013
1014
1015
1017
1018
1019
1020
1021QWaylandOutput *QWaylandQuickItem::output()
const
1023 Q_D(
const QWaylandQuickItem);
1024 return d->view->output();
1027void QWaylandQuickItem::setOutput(QWaylandOutput *output)
1029 Q_D(QWaylandQuickItem);
1030 d->view->setOutput(output);
1034
1035
1036
1037
1038
1039
1040
1042
1043
1044
1045
1046
1047
1048
1049bool QWaylandQuickItem::isBufferLocked()
const
1051 Q_D(
const QWaylandQuickItem);
1052 return d->view->isBufferLocked();
1055void QWaylandQuickItem::setBufferLocked(
bool locked)
1057 Q_D(QWaylandQuickItem);
1058 d->view->setBufferLocked(locked);
1062
1063
1064
1065
1066
1067
1068
1069bool QWaylandQuickItem::allowDiscardFrontBuffer()
const
1071 Q_D(
const QWaylandQuickItem);
1072 return d->view->allowDiscardFrontBuffer();
1075void QWaylandQuickItem::setAllowDiscardFrontBuffer(
bool discard)
1077 Q_D(QWaylandQuickItem);
1078 d->view->setAllowDiscardFrontBuffer(discard);
1082
1083
1084
1085
1088
1089
1090
1091
1092void QWaylandQuickItem::setPrimary()
1094 Q_D(QWaylandQuickItem);
1095 d->view->setPrimary();
1099
1100
1101void QWaylandQuickItem::handleSurfaceChanged()
1103 Q_D(QWaylandQuickItem);
1104 if (d->oldSurface) {
1105 disconnect(d->oldSurface.data(), &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1106 disconnect(d->oldSurface.data(), &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1107 disconnect(d->oldSurface.data(), &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1108 disconnect(d->oldSurface.data(), &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1109 disconnect(d->oldSurface.data(), &QWaylandSurface::redraw,
this, &QQuickItem::update);
1110 disconnect(d->oldSurface.data(), &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1111 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1112 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1113#if QT_CONFIG(draganddrop)
1114 disconnect(d->oldSurface.data(), &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1117 disconnect(d->oldSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1120 if (QWaylandSurface *newSurface = d->view->surface()) {
1121 connect(newSurface, &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1122 connect(newSurface, &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1123 connect(newSurface, &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1124 connect(newSurface, &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1125 connect(newSurface, &QWaylandSurface::redraw,
this, &QQuickItem::update);
1126 connect(newSurface, &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1127 connect(newSurface, &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1128 connect(newSurface, &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1129#if QT_CONFIG(draganddrop)
1130 connect(newSurface, &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1133 connect(newSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1136 if (newSurface->origin() != d->origin) {
1137 d->origin = newSurface->origin();
1138 emit originChanged();
1141 QWaylandOutput *output = newSurface->compositor()->outputFor(window());
1142 d->view->setOutput(output);
1144 for (
const auto &subsurface : std::as_const(QWaylandSurfacePrivate::get(newSurface)->subsurfaceChildren)) {
1145 if (!subsurface.isNull())
1146 handleSubsurfaceAdded(subsurface.data());
1151 surfaceChangedEvent(d->view->surface(), d->oldSurface);
1152 d->oldSurface = d->view->surface();
1154 updateInputMethod(Qt::ImQueryInput);
1159
1160
1161
1162void QWaylandQuickItem::takeFocus(QWaylandSeat *device)
1166 if (!surface() || !surface()->client())
1169 QWaylandSeat *target = device;
1171 target = compositor()->defaultSeat();
1173 target->setKeyboardFocus(surface());
1175 qCDebug(qLcWaylandCompositorInputMethods) << Q_FUNC_INFO <<
" surface:" << surface()
1176 <<
", client:" << surface()->client()
1177 <<
", textinputprotocol:" << (
int)(surface()->client()->textInputProtocols());
1178 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
1179 QWaylandTextInput *textInput = QWaylandTextInput::findIn(target);
1181 textInput->setFocus(surface());
1184 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
1185 QWaylandTextInputV3 *textInputV3 = QWaylandTextInputV3::findIn(target);
1187 textInputV3->setFocus(surface());
1190 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) {
1191 QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(target);
1192 if (textInputMethod)
1193 textInputMethod->setFocus(surface());
1198
1199
1200void QWaylandQuickItem::handleBufferLockedChanged()
1202 Q_D(QWaylandQuickItem);
1205 if (!d->view->isBufferLocked()) {
1211#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
1212void QWaylandQuickItem::surfaceMappedChanged()
1219
1220
1221void QWaylandQuickItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
1223 Q_UNUSED(oldParent);
1226 setPaintEnabled(
true);
1234
1235
1236void QWaylandQuickItem::updateSize()
1238 Q_D(QWaylandQuickItem);
1241 if (isBufferLocked()) {
1242 qWarning() <<
"No update on item size as the buffer is currently locked";
1248 size = surface()->destinationSize() * d->scaleFactor();
1250 setImplicitSize(size.width(), size.height());
1254
1255
1256
1257
1258
1259
1260
1263
1264
1265
1266
1267
1268
1269
1270bool QWaylandQuickItem::focusOnClick()
const
1272 Q_D(
const QWaylandQuickItem);
1273 return d->focusOnClick;
1276void QWaylandQuickItem::setFocusOnClick(
bool focus)
1278 Q_D(QWaylandQuickItem);
1279 if (d->focusOnClick == focus)
1282 d->focusOnClick = focus;
1283 emit focusOnClickChanged();
1287
1288
1289
1290bool QWaylandQuickItem::inputRegionContains(
const QPointF &localPosition)
const
1292 if (QWaylandSurface *s = surface())
1293 return s->inputRegionContains(mapToSurface(localPosition));
1298
1299
1300
1301
1302
1303
1306
1307
1308
1309
1310QPointF QWaylandQuickItem::mapToSurface(
const QPointF &point)
const
1312 Q_D(
const QWaylandQuickItem);
1313 if (!surface() || surface()->destinationSize().isEmpty())
1314 return point / d->scaleFactor();
1316 qreal xScale = width() / surface()->destinationSize().width();
1317 qreal yScale = height() / surface()->destinationSize().height();
1319 return QPointF(point.x() / xScale, point.y() / yScale);
1323
1324
1325
1326
1327
1328
1331
1332
1333
1334
1335
1336QPointF QWaylandQuickItem::mapFromSurface(
const QPointF &point)
const
1338 Q_D(
const QWaylandQuickItem);
1339 if (!surface() || surface()->destinationSize().isEmpty())
1340 return point * d->scaleFactor();
1342 qreal xScale = width() / surface()->destinationSize().width();
1343 qreal yScale = height() / surface()->destinationSize().height();
1345 return QPointF(point.x() * xScale, point.y() * yScale);
1349QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query)
const
1351 return inputMethodQuery(query, QVariant());
1354QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument)
const
1356 Q_D(
const QWaylandQuickItem);
1358 if (query == Qt::ImEnabled)
1359 return QVariant((flags() & ItemAcceptsInputMethod) != 0);
1362 return d->oldSurface->inputMethodControl()->inputMethodQuery(query, argument);
1369
1370
1371
1372
1373
1374
1375
1378
1379
1380
1381
1382
1383
1384bool QWaylandQuickItem::isPaintEnabled()
const
1386 Q_D(
const QWaylandQuickItem);
1387 return d->paintEnabled;
1390void QWaylandQuickItem::setPaintEnabled(
bool enabled)
1392 Q_D(QWaylandQuickItem);
1394 if (enabled != d->paintEnabled) {
1395 d->paintEnabled = enabled;
1396 emit paintEnabledChanged();
1403
1404
1405
1406
1407
1410
1411
1412
1413
1414
1415bool QWaylandQuickItem::touchEventsEnabled()
const
1417 Q_D(
const QWaylandQuickItem);
1418 return d->touchEventsEnabled;
1421void QWaylandQuickItem::updateBuffer(
bool hasBuffer)
1423 Q_D(QWaylandQuickItem);
1424 Q_UNUSED(hasBuffer);
1425 if (d->origin != surface()->origin()) {
1426 d->origin = surface()->origin();
1427 emit originChanged();
1431void QWaylandQuickItem::updateWindow()
1433 Q_D(QWaylandQuickItem);
1435 QQuickWindow *newWindow = window();
1436 if (newWindow == d->connectedWindow)
1439 if (d->connectedWindow) {
1440 disconnect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync);
1441 disconnect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1444 d->connectedWindow = newWindow;
1446 if (d->connectedWindow) {
1447 connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection);
1448 connect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1451 QWaylandOutput *output = compositor()->outputFor(d->connectedWindow);
1453 d->view->setOutput(output);
1460void QWaylandQuickItem::updateOutput()
1462 Q_D(QWaylandQuickItem);
1463 if (d->view->output() == d->connectedOutput)
1466 if (d->connectedOutput)
1467 disconnect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1469 d->connectedOutput = d->view->output();
1471 if (d->connectedOutput)
1472 connect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1477void QWaylandQuickItem::beforeSync()
1479 Q_D(QWaylandQuickItem);
1480 if (d->view->advance()) {
1481 d->newTexture =
true;
1487void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
1489 Q_D(QWaylandQuickItem);
1491 setFlag(QQuickItem::ItemAcceptsInputMethod,
1492 d->oldSurface ? d->oldSurface->inputMethodControl()->enabled() :
false);
1493 QQuickItem::updateInputMethod(queries | Qt::ImEnabled);
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1523QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1525 Q_D(QWaylandQuickItem);
1526 d->lastMatrix = data->transformNode->combinedMatrix();
1527 const bool bufferHasContent = d->view->currentBuffer().hasContent();
1529 if (d->view->isBufferLocked() && d->paintEnabled)
1532 if (!bufferHasContent || !d->paintEnabled || !surface()) {
1537 QWaylandBufferRef ref = d->view->currentBuffer();
1538 const bool invertY = ref.origin() == QWaylandSurface::OriginBottomLeft;
1539 const QRectF rect = invertY ? QRectF(0, height(), width(), -height())
1540 : QRectF(0, 0, width(), height());
1542 if (ref.isSharedMemory()
1543#if QT_CONFIG(opengl)
1544 || bufferTypes[ref.bufferFormatEgl()].canProvideTexture
1547#if QT_CONFIG(opengl)
1548 if (oldNode && !d->paintByProvider) {
1553 d->paintByProvider =
true;
1556 QSGSimpleTextureNode *node =
static_cast<QSGSimpleTextureNode *>(oldNode);
1559 node =
new QSGSimpleTextureNode();
1561 node->setFiltering(QSGTexture::Linear);
1562 d->newTexture =
true;
1566 d->provider =
new QWaylandSurfaceTextureProvider();
1567 if (
auto *c = compositor()) {
1568 d->texProviderConnection =
1569 QObject::connect(c, &QObject::destroyed,
this, [d = d] {
1571 d->provider->reportCompositorDestroyed();
1572 d->provider =
nullptr;
1574 QObject::disconnect(d->texProviderConnection);
1579 if (d->newTexture) {
1580 d->newTexture =
false;
1581 d->provider->setBufferRef(
this, ref);
1582 node->setTexture(d->provider->texture());
1585 d->provider->setSmooth(smooth());
1586 node->setRect(rect);
1588 qreal scale = surface()->bufferScale();
1589 QRectF source = surface()->sourceGeometry();
1590 node->setSourceRect(QRectF(source.topLeft() * scale, source.size() * scale));
1595#if QT_CONFIG(opengl)
1596 Q_ASSERT(!d->provider);
1598 if (oldNode && d->paintByProvider) {
1603 d->paintByProvider =
false;
1605 QSGGeometryNode *node =
static_cast<QSGGeometryNode *>(oldNode);
1608 node =
new QSGGeometryNode;
1609 d->newTexture =
true;
1612 QSGGeometry *geometry = node->geometry();
1613 QWaylandBufferMaterial *material =
static_cast<QWaylandBufferMaterial *>(node->material());
1616 geometry =
new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
1619 material =
new QWaylandBufferMaterial(ref.bufferFormatEgl());
1621 if (d->newTexture) {
1622 d->newTexture =
false;
1623 material->setBufferRef(
this, ref);
1626 const QSize surfaceSize = ref.size() / surface()->bufferScale();
1627 const QRectF sourceGeometry = surface()->sourceGeometry();
1628 const QRectF normalizedCoordinates =
1629 sourceGeometry.isValid()
1630 ? QRectF(sourceGeometry.x() / surfaceSize.width(),
1631 sourceGeometry.y() / surfaceSize.height(),
1632 sourceGeometry.width() / surfaceSize.width(),
1633 sourceGeometry.height() / surfaceSize.height())
1634 : QRectF(0, 0, 1, 1);
1636 QSGGeometry::updateTexturedRectGeometry(geometry, rect, normalizedCoordinates);
1638 node->setGeometry(geometry);
1639 node->setFlag(QSGNode::OwnsGeometry,
true);
1641 node->setMaterial(material);
1642 node->setFlag(QSGNode::OwnsMaterial,
true);
1646 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
1651void QWaylandQuickItem::setTouchEventsEnabled(
bool enabled)
1653 Q_D(QWaylandQuickItem);
1654 if (d->touchEventsEnabled != enabled) {
1655 d->touchEventsEnabled = enabled;
1656 emit touchEventsEnabledChanged();
1661
1662
1663
1664
1665
1666
1667
1670
1671
1672
1673
1674
1675
1676
1677bool QWaylandQuickItem::inputEventsEnabled()
const
1679 Q_D(
const QWaylandQuickItem);
1680 return d->inputEventsEnabled;
1683void QWaylandQuickItem::setInputEventsEnabled(
bool enabled)
1685 Q_D(QWaylandQuickItem);
1686 if (d->inputEventsEnabled != enabled) {
1689 d->setInputEventsEnabled(enabled);
1690 emit inputEventsEnabledChanged();
1694void QWaylandQuickItem::lower()
1696 Q_D(QWaylandQuickItem);
1702 Q_Q(QWaylandQuickItem);
1703 QQuickItem *parent = q->parentItem();
1705 QQuickItem *bottom = parent->childItems().constFirst();
1707 q->stackBefore(bottom);
1710void QWaylandQuickItem::raise()
1712 Q_D(QWaylandQuickItem);
1718 Q_Q(QWaylandQuickItem);
1719 QQuickItem *parent = q->parentItem();
1721 QQuickItem *top = parent->childItems().constLast();
1726void QWaylandQuickItem::sendMouseMoveEvent(
const QPointF &position, QWaylandSeat *seat)
1728 if (seat ==
nullptr)
1729 seat = compositor()->defaultSeat();
1732 qWarning() <<
"No seat, can't send mouse event";
1736 seat->sendMouseMoveEvent(view(), position);
1740
1741
1742
1743
1744void QWaylandQuickItem::handleSubsurfacePosition(
const QPoint &pos)
1746 Q_D(QWaylandQuickItem);
1747 QQuickItem::setPosition(pos * d->scaleFactor());
1750#if QT_CONFIG(draganddrop)
1751void QWaylandQuickItem::handleDragStarted(QWaylandDrag *drag)
1753 Q_D(QWaylandQuickItem);
1754 Q_ASSERT(drag->origin() == surface());
1755 drag->seat()->setMouseFocus(
nullptr);
1756 d->isDragging =
true;
1762 qreal f = view->output() ? view->output()->scaleFactor() : 1;
1763#if !defined(Q_OS_MACOS)
1765 f /= window->devicePixelRatio();
1772 Q_Q(
const QWaylandQuickItem);
1773 auto *parent = q->parentItem();
1777 const auto siblings = q->parentItem()->childItems();
1778 for (
auto *sibling : siblings) {
1779 auto *waylandItem = qobject_cast<QWaylandQuickItem *>(sibling);
1780 if (waylandItem && waylandItem->surface() == surface)
1788 Q_Q(QWaylandQuickItem);
1789 q->stackAfter(sibling);
1790 q->setZ(sibling->z());
1791 belowParent = sibling->d_func()->belowParent;
1796 Q_Q(QWaylandQuickItem);
1797 q->stackBefore(sibling);
1798 q->setZ(sibling->z());
1799 belowParent = sibling->d_func()->belowParent;
1805 Q_Q(QWaylandQuickItem);
1806 const auto siblings = q->parentItem()->childItems();
1809 bool foundSibling =
false;
1810 for (
auto it = siblings.cbegin(); it != siblings.cend(); ++it) {
1811 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1812 if (sibling && !sibling->d_func()->belowParent) {
1813 q->stackBefore(sibling);
1814 foundSibling =
true;
1820 if (!foundSibling && siblings.last() != q)
1821 q->stackAfter(siblings.last());
1823 q->setZ(q->parentItem()->z());
1830 Q_Q(QWaylandQuickItem);
1831 const auto siblings = q->parentItem()->childItems();
1834 bool foundSibling =
false;
1835 for (
auto it = siblings.crbegin(); it != siblings.crend(); ++it) {
1836 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1837 if (sibling && sibling->d_func()->belowParent) {
1838 q->stackAfter(sibling);
1839 foundSibling =
true;
1845 if (!foundSibling && siblings.first() != q)
1846 q->stackBefore(siblings.first());
1848 q->setZ(q->parentItem()->z() - 1.0);
1854#include "moc_qwaylandquickitem.cpp"
qreal scaleFactor() const
QWaylandSurfaceTextureProvider()
QSGTexture * texture() const override
Returns a pointer to the texture object.
void setBufferRef(QWaylandQuickItem *surfaceItem, const QWaylandBufferRef &buffer)
void setSmooth(bool smooth)
~QWaylandSurfaceTextureProvider() override
void reportCompositorDestroyed()