12#include <QtWaylandCompositor/qwaylandcompositor.h>
13#include <QtWaylandCompositor/qwaylandseat.h>
14#include <QtWaylandCompositor/qwaylandbufferref.h>
15#if QT_CONFIG(draganddrop)
16#include <QtWaylandCompositor/QWaylandDrag>
18#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h>
19#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
22# include <QtOpenGL/QOpenGLTexture>
23# include <QtGui/QOpenGLFunctions>
26#include <QtGui/QKeyEvent>
27#include <QtGui/QGuiApplication>
28#include <QtGui/QScreen>
30#include <QtQuick/QSGSimpleTextureNode>
31#include <QtQuick/QQuickWindow>
32#include <QtQuick/qsgtexture.h>
34#include <QtCore/QFile>
35#include <QtCore/QMutexLocker>
36#include <QtCore/QMutex>
38#include <wayland-server-core.h>
42#include <QtGui/private/qshaderdescription_p.h>
45#ifndef GL_TEXTURE_EXTERNAL_OES
46#define GL_TEXTURE_EXTERNAL_OES 0x8D65
53 const char *
const vertexShaderSourceFile;
54 const char *
const fragmentShaderSourceFile;
56 bool canProvideTexture;
57 QSGMaterial::Flags materialFlags;
58 QSGMaterialType materialType;
61 {
"",
"", 0,
false, {}, {} },
65 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
66 ":/qt-project.org/wayland/compositor/shaders/surface_rgbx.frag.qsb",
68 QSGMaterial::Blending,
74 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
75 ":/qt-project.org/wayland/compositor/shaders/surface_rgba.frag.qsb",
77 QSGMaterial::Blending,
83 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
84 ":/qt-project.org/wayland/compositor/shaders/surface_oes_external.frag",
86 QSGMaterial::Blending,
92 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
93 ":/qt-project.org/wayland/compositor/shaders/surface_y_u_v.frag.qsb",
95 QSGMaterial::Blending,
101 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
102 ":/qt-project.org/wayland/compositor/shaders/surface_y_uv.frag.qsb",
104 QSGMaterial::Blending,
110 ":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
111 ":/qt-project.org/wayland/compositor/shaders/surface_y_xuxv.frag.qsb",
113 QSGMaterial::Blending,
118QWaylandBufferMaterialShader::QWaylandBufferMaterialShader(QWaylandBufferRef::BufferFormatEgl format)
121 setShaderFileName(VertexStage, QString::fromLatin1(bufferTypes[format].vertexShaderSourceFile));
122 auto fragmentShaderSourceFile = QString::fromLatin1(bufferTypes[format].fragmentShaderSourceFile);
124 if (format == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES)
125 setupExternalOESShader(fragmentShaderSourceFile);
127 setShaderFileName(FragmentStage, fragmentShaderSourceFile);
130void QWaylandBufferMaterialShader::setupExternalOESShader(
const QString &shaderFilename)
133 QFile shaderFile(shaderFilename);
134 if (!shaderFile.open(QIODevice::ReadOnly)) {
135 qCWarning(qLcWaylandCompositor) <<
"Cannot find external OES shader file:" << shaderFilename;
138 QByteArray FS = shaderFile.readAll();
140 static const char *FS_GLES_PREAMBLE =
141 "#extension GL_OES_EGL_image_external : require\n"
142 "precision highp float;\n";
143 static const char *FS_GL_PREAMBLE =
145 "#extension GL_OES_EGL_image_external : require\n";
146 QByteArray fsGLES = FS_GLES_PREAMBLE + FS;
147 QByteArray fsGL = FS_GL_PREAMBLE + FS;
149 QShaderDescription desc;
150 QShaderDescriptionPrivate *descData = QShaderDescriptionPrivate::get(&desc);
152 QShaderDescription::InOutVariable texCoordInput;
153 texCoordInput.name =
"v_texcoord";
154 texCoordInput.type = QShaderDescription::Vec2;
155 texCoordInput.location = 0;
157 descData->inVars = { texCoordInput };
159 QShaderDescription::InOutVariable fragColorOutput;
160 fragColorOutput.name =
"gl_FragColor";
161 fragColorOutput.type = QShaderDescription::Vec4;
162 fragColorOutput.location = 0;
164 descData->outVars = { fragColorOutput };
166 QShaderDescription::BlockVariable matrixBlockVar;
167 matrixBlockVar.name =
"qt_Matrix";
168 matrixBlockVar.type = QShaderDescription::Mat4;
169 matrixBlockVar.offset = 0;
170 matrixBlockVar.size = 64;
172 QShaderDescription::BlockVariable opacityBlockVar;
173 opacityBlockVar.name =
"qt_Opacity";
174 opacityBlockVar.type = QShaderDescription::Float;
175 opacityBlockVar.offset = 64;
176 opacityBlockVar.size = 4;
178 QShaderDescription::UniformBlock ubufStruct;
179 ubufStruct.blockName =
"buf";
180 ubufStruct.structName =
"ubuf";
181 ubufStruct.size = 64 + 4;
182 ubufStruct.binding = 0;
183 ubufStruct.members = { matrixBlockVar, opacityBlockVar };
185 descData->uniformBlocks = { ubufStruct };
187 QShaderDescription::InOutVariable samplerTex0;
188 samplerTex0.name =
"tex0";
189 samplerTex0.type = QShaderDescription::SamplerExternalOES;
190 samplerTex0.binding = 1;
192 descData->combinedImageSamplers = { samplerTex0 };
195 shaderPack.setStage(QShader::FragmentStage);
196 shaderPack.setDescription(desc);
197 shaderPack.setShader(QShaderKey(QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs)), QShaderCode(fsGLES));
198 shaderPack.setShader(QShaderKey(QShader::GlslShader, QShaderVersion(120)), QShaderCode(fsGL));
200 setShader(FragmentStage, shaderPack);
202 Q_UNUSED(shaderFilename);
206bool QWaylandBufferMaterialShader::updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *)
208 bool changed =
false;
209 QByteArray *buf = state.uniformData();
210 Q_ASSERT(buf->size() >= 68);
212 if (state.isMatrixDirty()) {
213 const QMatrix4x4 m = state.combinedMatrix();
214 memcpy(buf->data(), m.constData(), 64);
218 if (state.isOpacityDirty()) {
219 const float opacity = state.opacity();
220 memcpy(buf->data() + 64, &opacity, 4);
227void QWaylandBufferMaterialShader::updateSampledImage(RenderState &state,
int binding, QSGTexture **texture,
228 QSGMaterial *newMaterial, QSGMaterial *)
232 QWaylandBufferMaterial *material =
static_cast<QWaylandBufferMaterial *>(newMaterial);
235 *texture = material->m_scenegraphTextures.at(0);
238 *texture = material->m_scenegraphTextures.at(1);
241 *texture = material->m_scenegraphTextures.at(2);
251 (*texture)->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
254QWaylandBufferMaterial::QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEgl format)
257 setFlag(bufferTypes[m_format].materialFlags);
260QWaylandBufferMaterial::~QWaylandBufferMaterial()
262 qDeleteAll(m_scenegraphTextures);
265void QWaylandBufferMaterial::setTextureForPlane(
int plane,
266 QOpenGLTexture *texture,
267 QSGTexture *scenegraphTexture)
269 if (plane < 0 || plane >= bufferTypes[m_format].planeCount) {
270 qWarning(
"plane index is out of range");
275 setTextureParameters(texture->target());
277 ensureTextures(plane - 1);
279 if (m_textures.size() <= plane) {
280 m_textures << texture;
281 m_scenegraphTextures << scenegraphTexture;
283 delete m_scenegraphTextures[plane];
285 m_textures[plane] = texture;
286 m_scenegraphTextures[plane] = scenegraphTexture;
290void QWaylandBufferMaterial::bind()
292 ensureTextures(bufferTypes[m_format].planeCount);
294 switch (m_textures.size()) {
297 m_textures[2]->bind(2);
301 m_textures[1]->bind(1);
305 m_textures[0]->bind(0);
309QSGMaterialType *QWaylandBufferMaterial::type()
const
311 return const_cast<QSGMaterialType *>(&bufferTypes[m_format].materialType);
314QSGMaterialShader *QWaylandBufferMaterial::createShader(QSGRendererInterface::RenderMode renderMode)
const
316 Q_UNUSED(renderMode);
317 return new QWaylandBufferMaterialShader(m_format);
321void QWaylandBufferMaterial::setTextureParameters(GLenum target)
323 QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
324 gl->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
325 gl->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
326 gl->glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
327 gl->glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
331void QWaylandBufferMaterial::ensureTextures(
int count)
333 for (
int plane = m_textures.size(); plane < count; plane++) {
334 m_textures <<
nullptr;
335 m_scenegraphTextures <<
nullptr;
339void QWaylandBufferMaterial::setBufferRef(QWaylandQuickItem *surfaceItem,
const QWaylandBufferRef &ref)
342 for (
int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++) {
343 if (
auto texture = ref.toOpenGLTexture(plane)) {
344 QQuickWindow::CreateTextureOptions opt;
345 QWaylandQuickSurface *waylandSurface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
346 if (waylandSurface !=
nullptr && waylandSurface->useTextureAlpha() && !waylandSurface->isOpaque())
347 opt |= QQuickWindow::TextureHasAlphaChannel;
348 QSGTexture *scenegraphTexture;
349 if (ref.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES) {
350 scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNativeExternalOES(texture->textureId(),
351 surfaceItem->window(),
355 scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNative(texture->textureId(),
356 surfaceItem->window(),
360 scenegraphTexture->setFiltering(surfaceItem->smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
361 setTextureForPlane(plane, texture, scenegraphTexture);
369QMutex *QWaylandQuickItemPrivate::mutex =
nullptr;
389 if (m_compositorDestroyed.loadAcquire() && m_ref.hasBuffer())
390 m_ref.buffer()->setDestroyed();
395 void setBufferRef(QWaylandQuickItem *surfaceItem,
const QWaylandBufferRef &buffer)
397 Q_ASSERT(QThread::currentThread() == thread());
401 if (m_ref.hasBuffer()) {
402 if (buffer.isSharedMemory()) {
403 m_sgTex = surfaceItem->window()->createTextureFromImage(buffer.image());
406 QQuickWindow::CreateTextureOptions opt;
407 QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
408 if (surface && surface->useTextureAlpha() && !surface->isOpaque()) {
409 opt |= QQuickWindow::TextureHasAlphaChannel;
412 auto texture = buffer.toOpenGLTexture();
413 GLuint textureId = texture->textureId();
414 auto size = surface->bufferSize();
415 m_sgTex = QNativeInterface::QSGOpenGLTexture::fromNative(textureId, surfaceItem->window(), size, opt);
417 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
421 emit textureChanged();
427 m_sgTex->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
435 m_compositorDestroyed.storeRelease(1);
440 bool m_smooth =
false;
441 QSGTexture *m_sgTex =
nullptr;
443 QAtomicInt m_compositorDestroyed;
444 QWaylandBufferRef m_ref;
449#if QT_CONFIG(draganddrop)
450 Q_Q(QWaylandQuickItem);
451 QWaylandQuickOutput *currentOutput = qobject_cast<QWaylandQuickOutput *>(q->view()->output());
453 QWaylandQuickItem *targetItem = qobject_cast<QWaylandQuickItem *>(currentOutput->pickClickableItem(q->mapToScene(globalPosition)));
454 QWaylandSurface *targetSurface = targetItem ? targetItem->surface() :
nullptr;
456 QPointF position = q->mapToItem(targetItem, globalPosition);
457 QPointF surfacePosition = targetItem->mapToSurface(position);
458 seat->drag()->dragMove(targetSurface, surfacePosition);
462 Q_UNUSED(globalPosition);
468#if QT_CONFIG(draganddrop)
470 seat->drag()->drop();
477
478
479
480
481
482
483
484
485
486
489
490
491
492
493
494
495
496
497
500
501
502QWaylandQuickItem::QWaylandQuickItem(QQuickItem *parent)
503 : QWaylandQuickItem(*
new QWaylandQuickItemPrivate(), parent)
508
509
510QWaylandQuickItem::QWaylandQuickItem(QWaylandQuickItemPrivate &dd, QQuickItem *parent)
511 : QQuickItem(dd, parent)
514 connect(
this, &QQuickItem::activeFocusChanged,
this, &QWaylandQuickItem::updateFocus);
518
519
520QWaylandQuickItem::~QWaylandQuickItem()
522 Q_D(QWaylandQuickItem);
523 disconnect(
this, &QQuickItem::windowChanged,
this, &QWaylandQuickItem::updateWindow);
524 disconnect(
this, &QQuickItem::activeFocusChanged,
this, &QWaylandQuickItem::updateFocus);
525 QMutexLocker locker(d->mutex);
527 disconnect(d->texProviderConnection);
528 d->provider->deleteLater();
533
534
535
536
539
540
541
542
543QWaylandCompositor *QWaylandQuickItem::compositor()
const
545 Q_D(
const QWaylandQuickItem);
546 return d->view->surface() ? d->view->surface()->compositor() :
nullptr;
550
551
552QWaylandView *QWaylandQuickItem::view()
const
554 Q_D(
const QWaylandQuickItem);
555 return d->view.data();
559
560
561
562
565
566
567
568
570QWaylandSurface *QWaylandQuickItem::surface()
const
572 Q_D(
const QWaylandQuickItem);
573 return d->view->surface();
576void QWaylandQuickItem::setSurface(QWaylandSurface *surface)
578 Q_D(QWaylandQuickItem);
579 QWaylandSurface *oldSurf = d->view->surface();
580 if (oldSurf == surface)
583 QWaylandCompositor *oldComp = oldSurf ? oldSurf->compositor() :
nullptr;
584 QWaylandCompositor *newComp = surface ? surface->compositor() :
nullptr;
585 if (oldComp != newComp)
586 emit compositorChanged();
588 d->view->setSurface(surface);
595
596
597
598
601
602
603
604
605QWaylandSurface::Origin QWaylandQuickItem::origin()
const
607 Q_D(
const QWaylandQuickItem);
611bool QWaylandQuickItem::isTextureProvider()
const
613 Q_D(
const QWaylandQuickItem);
614 return QQuickItem::isTextureProvider() || d->provider;
618
619
620QSGTextureProvider *QWaylandQuickItem::textureProvider()
const
622 Q_D(
const QWaylandQuickItem);
624 if (QQuickItem::isTextureProvider())
625 return QQuickItem::textureProvider();
631
632
633void QWaylandQuickItem::mousePressEvent(QMouseEvent *event)
635 Q_D(QWaylandQuickItem);
636 if (!d->shouldSendInputEvents()) {
641 if (!inputRegionContains(event->position())) {
646 QWaylandSeat *seat = compositor()->seatFor(event);
651 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), event->scenePosition());
652 seat->sendMousePressEvent(event->button());
653 d->hoverPos = event->position();
657
658
659void QWaylandQuickItem::mouseMoveEvent(QMouseEvent *event)
661 Q_D(QWaylandQuickItem);
662 if (d->shouldSendInputEvents()) {
663 QWaylandSeat *seat = compositor()->seatFor(event);
665 d->handleDragUpdate(seat, event->position());
667 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), event->scenePosition());
668 d->hoverPos = event->position();
671 emit mouseMove(event->scenePosition());
677
678
679void QWaylandQuickItem::mouseReleaseEvent(QMouseEvent *event)
681 Q_D(QWaylandQuickItem);
682 if (d->shouldSendInputEvents()) {
683 QWaylandSeat *seat = compositor()->seatFor(event);
685 d->handleDragEnded(seat);
687 seat->sendMouseReleaseEvent(event->button());
695
696
697void QWaylandQuickItem::hoverEnterEvent(QHoverEvent *event)
699 Q_D(QWaylandQuickItem);
700 if (!inputRegionContains(event->position())) {
704 if (d->shouldSendInputEvents()) {
705 QWaylandSeat *seat = compositor()->seatFor(event);
706 seat->sendMouseMoveEvent(d->view.data(), event->position(), mapToScene(event->position()));
707 d->hoverPos = event->position();
714
715
716void QWaylandQuickItem::hoverMoveEvent(QHoverEvent *event)
718 Q_D(QWaylandQuickItem);
720 if (!inputRegionContains(event->position())) {
725 if (d->shouldSendInputEvents()) {
726 QWaylandSeat *seat = compositor()->seatFor(event);
727 if (event->position() != d->hoverPos) {
728 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), mapToScene(event->position()));
729 d->hoverPos = event->position();
737
738
739void QWaylandQuickItem::hoverLeaveEvent(QHoverEvent *event)
741 Q_D(QWaylandQuickItem);
742 if (d->shouldSendInputEvents()) {
743 QWaylandSeat *seat = compositor()->seatFor(event);
744 if (d->view.data() == seat->mouseFocus()) {
745 seat->setMouseFocus(
nullptr);
753#if QT_CONFIG(wheelevent)
755
756
757void QWaylandQuickItem::wheelEvent(QWheelEvent *event)
759 Q_D(QWaylandQuickItem);
760 if (d->shouldSendInputEvents()) {
761 if (!inputRegionContains(event->position())) {
766 QWaylandSeat *seat = compositor()->seatFor(event);
768 if (event->angleDelta().x() != 0)
769 seat->sendMouseWheelEvent(Qt::Horizontal, event->angleDelta().x());
770 if (event->angleDelta().y() != 0)
771 seat->sendMouseWheelEvent(Qt::Vertical, event->angleDelta().y());
779
780
781void QWaylandQuickItem::keyPressEvent(QKeyEvent *event)
783 Q_D(QWaylandQuickItem);
784 if (d->shouldSendInputEvents()) {
785 QWaylandSeat *seat = compositor()->seatFor(event);
786 if (seat->setKeyboardFocus(d->view->surface()))
787 seat->sendFullKeyEvent(event);
789 qWarning() <<
"Unable to set keyboard focus, cannot send key press event";
796
797
798void QWaylandQuickItem::keyReleaseEvent(QKeyEvent *event)
800 Q_D(QWaylandQuickItem);
801 if (d->shouldSendInputEvents()) {
802 QWaylandSeat *seat = compositor()->seatFor(event);
803 seat->sendFullKeyEvent(event);
810
811
812void QWaylandQuickItem::touchEvent(QTouchEvent *event)
814 Q_D(QWaylandQuickItem);
815 if (d->shouldSendInputEvents() && d->touchEventsEnabled) {
816 QWaylandSeat *seat = compositor()->seatFor(event);
819 const QList<QTouchEvent::TouchPoint> &points = event->points();
820 if (!points.isEmpty())
821 pointPos = points.at(0).position();
823 if (event->type() == QEvent::TouchBegin && !inputRegionContains(pointPos)) {
828 if (event->type() == QEvent::TouchUpdate && d->isDragging)
829 d->handleDragUpdate(seat, pointPos);
832 if (seat->mouseFocus() != d->view.data()) {
833 seat->sendMouseMoveEvent(d->view.data(), pointPos, mapToScene(pointPos));
835 seat->sendFullTouchEvent(surface(), event);
837 if (event->type() == QEvent::TouchBegin) {
838 d->touchingSeats.append(seat);
839 }
else if (event->type() == QEvent::TouchEnd || event->type() == QEvent::TouchCancel) {
841 d->handleDragEnded(seat);
842 d->touchingSeats.removeOne(seat);
845 if (event->type() == QEvent::TouchBegin && d->focusOnClick)
852void QWaylandQuickItem::touchUngrabEvent()
854 Q_D(QWaylandQuickItem);
856 if (d->shouldSendInputEvents())
857 for (
auto seat : d->touchingSeats)
858 seat->sendTouchCancelEvent(surface()->client());
860 d->touchingSeats.clear();
865
866
867void QWaylandQuickItem::inputMethodEvent(QInputMethodEvent *event)
869 Q_D(QWaylandQuickItem);
870 if (d->shouldSendInputEvents()) {
871 d->oldSurface->inputMethodControl()->inputMethodEvent(event);
879
880
881void QWaylandQuickItem::surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface)
883 Q_UNUSED(newSurface);
884 Q_UNUSED(oldSurface);
887void QWaylandQuickItem::handleSubsurfaceAdded(QWaylandSurface *childSurface)
889 Q_D(QWaylandQuickItem);
890 if (d->subsurfaceHandler.isNull()) {
891 QWaylandQuickItem *childItem =
new QWaylandQuickItem;
892 childItem->setSurface(childSurface);
893 childItem->setVisible(
true);
894 childItem->setParentItem(
this);
895 childItem->setParent(
this);
896 childItem->setPosition(QWaylandSurfacePrivate::get(childSurface)->subsurfacePosition() * d->scaleFactor());
897 connect(childSurface, &QWaylandSurface::subsurfacePositionChanged, childItem, &QWaylandQuickItem::handleSubsurfacePosition);
898 connect(childSurface, &QWaylandSurface::destroyed, childItem, &QObject::deleteLater);
900 bool success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded", Q_ARG(QWaylandSurface *, childSurface));
902 success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded",
903 Q_ARG(QVariant, QVariant::fromValue(childSurface)));
906 qWarning(
"QWaylandQuickItem: subsurfaceHandler does not implement handleSubsurfaceAdded()");
910void QWaylandQuickItem::handlePlaceAbove(QWaylandSurface *referenceSurface)
912 Q_D(QWaylandQuickItem);
913 auto *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
917 if (parent->surface() == referenceSurface) {
918 d->placeAboveParent();
919 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
920 d->placeAboveSibling(sibling);
922 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
923 <<
"when handling wl_subsurface.place_above";
927void QWaylandQuickItem::handlePlaceBelow(QWaylandSurface *referenceSurface)
929 Q_D(QWaylandQuickItem);
930 QWaylandQuickItem *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
934 if (parent->surface() == referenceSurface) {
935 d->placeBelowParent();
936 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
937 d->placeBelowSibling(sibling);
939 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
940 <<
"when handling wl_subsurface.place_below";
944void QWaylandQuickItem::updateFocus()
946 Q_D(
const QWaylandQuickItem);
947 if (hasActiveFocus() && compositor())
948 compositor()->defaultSeat()->setKeyboardFocus(d->view->surface());
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
975
976
977
978
979
980
981
982
983
984
985
986
987
988QObject *QWaylandQuickItem::subsurfaceHandler()
const
990 Q_D(
const QWaylandQuickItem);
991 return d->subsurfaceHandler.data();
994void QWaylandQuickItem::setSubsurfaceHandler(QObject *handler)
996 Q_D(QWaylandQuickItem);
997 if (d->subsurfaceHandler.data() != handler) {
998 d->subsurfaceHandler = handler;
999 emit subsurfaceHandlerChanged();
1004
1005
1006
1007
1009
1010
1011
1012
1013QWaylandOutput *QWaylandQuickItem::output()
const
1015 Q_D(
const QWaylandQuickItem);
1016 return d->view->output();
1019void QWaylandQuickItem::setOutput(QWaylandOutput *output)
1021 Q_D(QWaylandQuickItem);
1022 d->view->setOutput(output);
1026
1027
1028
1029
1030
1031
1032
1034
1035
1036
1037
1038
1039
1040
1041bool QWaylandQuickItem::isBufferLocked()
const
1043 Q_D(
const QWaylandQuickItem);
1044 return d->view->isBufferLocked();
1047void QWaylandQuickItem::setBufferLocked(
bool locked)
1049 Q_D(QWaylandQuickItem);
1050 d->view->setBufferLocked(locked);
1054
1055
1056
1057
1058
1059
1060
1061bool QWaylandQuickItem::allowDiscardFrontBuffer()
const
1063 Q_D(
const QWaylandQuickItem);
1064 return d->view->allowDiscardFrontBuffer();
1067void QWaylandQuickItem::setAllowDiscardFrontBuffer(
bool discard)
1069 Q_D(QWaylandQuickItem);
1070 d->view->setAllowDiscardFrontBuffer(discard);
1074
1075
1076
1077
1080
1081
1082
1083
1084void QWaylandQuickItem::setPrimary()
1086 Q_D(QWaylandQuickItem);
1087 d->view->setPrimary();
1091
1092
1093void QWaylandQuickItem::handleSurfaceChanged()
1095 Q_D(QWaylandQuickItem);
1096 if (d->oldSurface) {
1097 disconnect(d->oldSurface.data(), &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1098 disconnect(d->oldSurface.data(), &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1099 disconnect(d->oldSurface.data(), &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1100 disconnect(d->oldSurface.data(), &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1101 disconnect(d->oldSurface.data(), &QWaylandSurface::redraw,
this, &QQuickItem::update);
1102 disconnect(d->oldSurface.data(), &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1103 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1104 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1105#if QT_CONFIG(draganddrop)
1106 disconnect(d->oldSurface.data(), &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1109 disconnect(d->oldSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1112 if (QWaylandSurface *newSurface = d->view->surface()) {
1113 connect(newSurface, &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1114 connect(newSurface, &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1115 connect(newSurface, &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1116 connect(newSurface, &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1117 connect(newSurface, &QWaylandSurface::redraw,
this, &QQuickItem::update);
1118 connect(newSurface, &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1119 connect(newSurface, &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1120 connect(newSurface, &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1121#if QT_CONFIG(draganddrop)
1122 connect(newSurface, &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1125 connect(newSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1128 if (newSurface->origin() != d->origin) {
1129 d->origin = newSurface->origin();
1130 emit originChanged();
1133 QWaylandOutput *output = newSurface->compositor()->outputFor(window());
1134 d->view->setOutput(output);
1136 for (
auto subsurface : QWaylandSurfacePrivate::get(newSurface)->subsurfaceChildren) {
1137 if (!subsurface.isNull())
1138 handleSubsurfaceAdded(subsurface.data());
1143 surfaceChangedEvent(d->view->surface(), d->oldSurface);
1144 d->oldSurface = d->view->surface();
1146 updateInputMethod(Qt::ImQueryInput);
1151
1152
1153
1154void QWaylandQuickItem::takeFocus(QWaylandSeat *device)
1158 if (!surface() || !surface()->client())
1161 QWaylandSeat *target = device;
1163 target = compositor()->defaultSeat();
1165 target->setKeyboardFocus(surface());
1167 qCDebug(qLcWaylandCompositorInputMethods) << Q_FUNC_INFO <<
" surface:" << surface()
1168 <<
", client:" << surface()->client()
1169 <<
", textinputprotocol:" << (
int)(surface()->client()->textInputProtocols());
1170 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
1171 QWaylandTextInput *textInput = QWaylandTextInput::findIn(target);
1173 textInput->setFocus(surface());
1176 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
1177 QWaylandTextInputV3 *textInputV3 = QWaylandTextInputV3::findIn(target);
1179 textInputV3->setFocus(surface());
1182 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) {
1183 QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(target);
1184 if (textInputMethod)
1185 textInputMethod->setFocus(surface());
1190
1191
1192void QWaylandQuickItem::handleBufferLockedChanged()
1194 Q_D(QWaylandQuickItem);
1197 if (!d->view->isBufferLocked()) {
1203#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
1204void QWaylandQuickItem::surfaceMappedChanged()
1211
1212
1213void QWaylandQuickItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
1215 Q_UNUSED(oldParent);
1218 setPaintEnabled(
true);
1226
1227
1228void QWaylandQuickItem::updateSize()
1230 Q_D(QWaylandQuickItem);
1233 if (isBufferLocked()) {
1234 qWarning() <<
"No update on item size as the buffer is currently locked";
1240 size = surface()->destinationSize() * d->scaleFactor();
1242 setImplicitSize(size.width(), size.height());
1246
1247
1248
1249
1250
1251
1252
1255
1256
1257
1258
1259
1260
1261
1262bool QWaylandQuickItem::focusOnClick()
const
1264 Q_D(
const QWaylandQuickItem);
1265 return d->focusOnClick;
1268void QWaylandQuickItem::setFocusOnClick(
bool focus)
1270 Q_D(QWaylandQuickItem);
1271 if (d->focusOnClick == focus)
1274 d->focusOnClick = focus;
1275 emit focusOnClickChanged();
1279
1280
1281
1282bool QWaylandQuickItem::inputRegionContains(
const QPointF &localPosition)
const
1284 if (QWaylandSurface *s = surface())
1285 return s->inputRegionContains(mapToSurface(localPosition));
1290
1291
1292
1293
1294
1295
1298
1299
1300
1301
1302QPointF QWaylandQuickItem::mapToSurface(
const QPointF &point)
const
1304 Q_D(
const QWaylandQuickItem);
1305 if (!surface() || surface()->destinationSize().isEmpty())
1306 return point / d->scaleFactor();
1308 qreal xScale = width() / surface()->destinationSize().width();
1309 qreal yScale = height() / surface()->destinationSize().height();
1311 return QPointF(point.x() / xScale, point.y() / yScale);
1315
1316
1317
1318
1319
1320
1323
1324
1325
1326
1327
1328QPointF QWaylandQuickItem::mapFromSurface(
const QPointF &point)
const
1330 Q_D(
const QWaylandQuickItem);
1331 if (!surface() || surface()->destinationSize().isEmpty())
1332 return point * d->scaleFactor();
1334 qreal xScale = width() / surface()->destinationSize().width();
1335 qreal yScale = height() / surface()->destinationSize().height();
1337 return QPointF(point.x() * xScale, point.y() * yScale);
1341QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query)
const
1343 return inputMethodQuery(query, QVariant());
1346QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument)
const
1348 Q_D(
const QWaylandQuickItem);
1350 if (query == Qt::ImEnabled)
1351 return QVariant((flags() & ItemAcceptsInputMethod) != 0);
1354 return d->oldSurface->inputMethodControl()->inputMethodQuery(query, argument);
1361
1362
1363
1364
1365
1366
1367
1370
1371
1372
1373
1374
1375
1376
1377bool QWaylandQuickItem::isPaintEnabled()
const
1379 Q_D(
const QWaylandQuickItem);
1380 return d->paintEnabled;
1383void QWaylandQuickItem::setPaintEnabled(
bool enabled)
1385 Q_D(QWaylandQuickItem);
1387 if (enabled != d->paintEnabled) {
1388 d->paintEnabled = enabled;
1389 emit paintEnabledChanged();
1396
1397
1398
1399
1400
1403
1404
1405
1406
1407
1408bool QWaylandQuickItem::touchEventsEnabled()
const
1410 Q_D(
const QWaylandQuickItem);
1411 return d->touchEventsEnabled;
1414void QWaylandQuickItem::updateBuffer(
bool hasBuffer)
1416 Q_D(QWaylandQuickItem);
1417 Q_UNUSED(hasBuffer);
1418 if (d->origin != surface()->origin()) {
1419 d->origin = surface()->origin();
1420 emit originChanged();
1424void QWaylandQuickItem::updateWindow()
1426 Q_D(QWaylandQuickItem);
1428 QQuickWindow *newWindow = window();
1429 if (newWindow == d->connectedWindow)
1432 if (d->connectedWindow) {
1433 disconnect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync);
1434 disconnect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1437 d->connectedWindow = newWindow;
1439 if (d->connectedWindow) {
1440 connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection);
1441 connect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1444 QWaylandOutput *output = compositor()->outputFor(d->connectedWindow);
1446 d->view->setOutput(output);
1453void QWaylandQuickItem::updateOutput()
1455 Q_D(QWaylandQuickItem);
1456 if (d->view->output() == d->connectedOutput)
1459 if (d->connectedOutput)
1460 disconnect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1462 d->connectedOutput = d->view->output();
1464 if (d->connectedOutput)
1465 connect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1470void QWaylandQuickItem::beforeSync()
1472 Q_D(QWaylandQuickItem);
1473 if (d->view->advance()) {
1474 d->newTexture =
true;
1480void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
1482 Q_D(QWaylandQuickItem);
1484 setFlag(QQuickItem::ItemAcceptsInputMethod,
1485 d->oldSurface ? d->oldSurface->inputMethodControl()->enabled() :
false);
1486 QQuickItem::updateInputMethod(queries | Qt::ImEnabled);
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1516QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1518 Q_D(QWaylandQuickItem);
1519 d->lastMatrix = data->transformNode->combinedMatrix();
1520 const bool bufferHasContent = d->view->currentBuffer().hasContent();
1522 if (d->view->isBufferLocked() && d->paintEnabled)
1525 if (!bufferHasContent || !d->paintEnabled || !surface()) {
1530 QWaylandBufferRef ref = d->view->currentBuffer();
1531 const bool invertY = ref.origin() == QWaylandSurface::OriginBottomLeft;
1532 const QRectF rect = invertY ? QRectF(0, height(), width(), -height())
1533 : QRectF(0, 0, width(), height());
1535 if (ref.isSharedMemory()
1536#if QT_CONFIG(opengl)
1537 || bufferTypes[ref.bufferFormatEgl()].canProvideTexture
1540#if QT_CONFIG(opengl)
1541 if (oldNode && !d->paintByProvider) {
1546 d->paintByProvider =
true;
1549 QSGSimpleTextureNode *node =
static_cast<QSGSimpleTextureNode *>(oldNode);
1552 node =
new QSGSimpleTextureNode();
1554 node->setFiltering(QSGTexture::Linear);
1555 d->newTexture =
true;
1559 d->provider =
new QWaylandSurfaceTextureProvider();
1560 if (
auto *c = compositor()) {
1561 d->texProviderConnection =
1562 QObject::connect(c, &QObject::destroyed,
this, [d = d] {
1564 d->provider->reportCompositorDestroyed();
1565 d->provider =
nullptr;
1567 QObject::disconnect(d->texProviderConnection);
1572 if (d->newTexture) {
1573 d->newTexture =
false;
1574 d->provider->setBufferRef(
this, ref);
1575 node->setTexture(d->provider->texture());
1578 d->provider->setSmooth(smooth());
1579 node->setRect(rect);
1581 qreal scale = surface()->bufferScale();
1582 QRectF source = surface()->sourceGeometry();
1583 node->setSourceRect(QRectF(source.topLeft() * scale, source.size() * scale));
1588#if QT_CONFIG(opengl)
1589 Q_ASSERT(!d->provider);
1591 if (oldNode && d->paintByProvider) {
1596 d->paintByProvider =
false;
1598 QSGGeometryNode *node =
static_cast<QSGGeometryNode *>(oldNode);
1601 node =
new QSGGeometryNode;
1602 d->newTexture =
true;
1605 QSGGeometry *geometry = node->geometry();
1606 QWaylandBufferMaterial *material =
static_cast<QWaylandBufferMaterial *>(node->material());
1609 geometry =
new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
1612 material =
new QWaylandBufferMaterial(ref.bufferFormatEgl());
1614 if (d->newTexture) {
1615 d->newTexture =
false;
1616 material->setBufferRef(
this, ref);
1619 const QSize surfaceSize = ref.size() / surface()->bufferScale();
1620 const QRectF sourceGeometry = surface()->sourceGeometry();
1621 const QRectF normalizedCoordinates =
1622 sourceGeometry.isValid()
1623 ? QRectF(sourceGeometry.x() / surfaceSize.width(),
1624 sourceGeometry.y() / surfaceSize.height(),
1625 sourceGeometry.width() / surfaceSize.width(),
1626 sourceGeometry.height() / surfaceSize.height())
1627 : QRectF(0, 0, 1, 1);
1629 QSGGeometry::updateTexturedRectGeometry(geometry, rect, normalizedCoordinates);
1631 node->setGeometry(geometry);
1632 node->setFlag(QSGNode::OwnsGeometry,
true);
1634 node->setMaterial(material);
1635 node->setFlag(QSGNode::OwnsMaterial,
true);
1639 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
1644void QWaylandQuickItem::setTouchEventsEnabled(
bool enabled)
1646 Q_D(QWaylandQuickItem);
1647 if (d->touchEventsEnabled != enabled) {
1648 d->touchEventsEnabled = enabled;
1649 emit touchEventsEnabledChanged();
1654
1655
1656
1657
1658
1659
1660
1663
1664
1665
1666
1667
1668
1669
1670bool QWaylandQuickItem::inputEventsEnabled()
const
1672 Q_D(
const QWaylandQuickItem);
1673 return d->inputEventsEnabled;
1676void QWaylandQuickItem::setInputEventsEnabled(
bool enabled)
1678 Q_D(QWaylandQuickItem);
1679 if (d->inputEventsEnabled != enabled) {
1682 d->setInputEventsEnabled(enabled);
1683 emit inputEventsEnabledChanged();
1687void QWaylandQuickItem::lower()
1689 Q_D(QWaylandQuickItem);
1695 Q_Q(QWaylandQuickItem);
1696 QQuickItem *parent = q->parentItem();
1698 QQuickItem *bottom = parent->childItems().constFirst();
1700 q->stackBefore(bottom);
1703void QWaylandQuickItem::raise()
1705 Q_D(QWaylandQuickItem);
1711 Q_Q(QWaylandQuickItem);
1712 QQuickItem *parent = q->parentItem();
1714 QQuickItem *top = parent->childItems().constLast();
1719void QWaylandQuickItem::sendMouseMoveEvent(
const QPointF &position, QWaylandSeat *seat)
1721 if (seat ==
nullptr)
1722 seat = compositor()->defaultSeat();
1725 qWarning() <<
"No seat, can't send mouse event";
1729 seat->sendMouseMoveEvent(view(), position);
1733
1734
1735
1736
1737void QWaylandQuickItem::handleSubsurfacePosition(
const QPoint &pos)
1739 Q_D(QWaylandQuickItem);
1740 QQuickItem::setPosition(pos * d->scaleFactor());
1743#if QT_CONFIG(draganddrop)
1744void QWaylandQuickItem::handleDragStarted(QWaylandDrag *drag)
1746 Q_D(QWaylandQuickItem);
1747 Q_ASSERT(drag->origin() == surface());
1748 drag->seat()->setMouseFocus(
nullptr);
1749 d->isDragging =
true;
1755 qreal f = view->output() ? view->output()->scaleFactor() : 1;
1756#if !defined(Q_OS_MACOS)
1758 f /= window->devicePixelRatio();
1765 Q_Q(
const QWaylandQuickItem);
1766 auto *parent = q->parentItem();
1770 const auto siblings = q->parentItem()->childItems();
1771 for (
auto *sibling : siblings) {
1772 auto *waylandItem = qobject_cast<QWaylandQuickItem *>(sibling);
1773 if (waylandItem && waylandItem->surface() == surface)
1781 Q_Q(QWaylandQuickItem);
1782 q->stackAfter(sibling);
1783 q->setZ(sibling->z());
1784 belowParent = sibling->d_func()->belowParent;
1789 Q_Q(QWaylandQuickItem);
1790 q->stackBefore(sibling);
1791 q->setZ(sibling->z());
1792 belowParent = sibling->d_func()->belowParent;
1798 Q_Q(QWaylandQuickItem);
1799 const auto siblings = q->parentItem()->childItems();
1802 bool foundSibling =
false;
1803 for (
auto it = siblings.cbegin(); it != siblings.cend(); ++it) {
1804 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1805 if (sibling && !sibling->d_func()->belowParent) {
1806 q->stackBefore(sibling);
1807 foundSibling =
true;
1813 if (!foundSibling && siblings.last() != q)
1814 q->stackAfter(siblings.last());
1816 q->setZ(q->parentItem()->z());
1823 Q_Q(QWaylandQuickItem);
1824 const auto siblings = q->parentItem()->childItems();
1827 bool foundSibling =
false;
1828 for (
auto it = siblings.crbegin(); it != siblings.crend(); ++it) {
1829 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1830 if (sibling && sibling->d_func()->belowParent) {
1831 q->stackAfter(sibling);
1832 foundSibling =
true;
1838 if (!foundSibling && siblings.first() != q)
1839 q->stackBefore(siblings.first());
1841 q->setZ(q->parentItem()->z() - 1.0);
1847#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()