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 connect(childSurface, &QWaylandSurface::subsurfacePositionChanged, childItem, &QWaylandQuickItem::handleSubsurfacePosition);
897 connect(childSurface, &QWaylandSurface::destroyed, childItem, &QObject::deleteLater);
899 bool success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded", Q_ARG(QWaylandSurface *, childSurface));
901 success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded",
902 Q_ARG(QVariant, QVariant::fromValue(childSurface)));
905 qWarning(
"QWaylandQuickItem: subsurfaceHandler does not implement handleSubsurfaceAdded()");
909void QWaylandQuickItem::handlePlaceAbove(QWaylandSurface *referenceSurface)
911 Q_D(QWaylandQuickItem);
912 auto *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
916 if (parent->surface() == referenceSurface) {
917 d->placeAboveParent();
918 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
919 d->placeAboveSibling(sibling);
921 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
922 <<
"when handling wl_subsurface.place_above";
926void QWaylandQuickItem::handlePlaceBelow(QWaylandSurface *referenceSurface)
928 Q_D(QWaylandQuickItem);
929 QWaylandQuickItem *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
933 if (parent->surface() == referenceSurface) {
934 d->placeBelowParent();
935 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
936 d->placeBelowSibling(sibling);
938 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
939 <<
"when handling wl_subsurface.place_below";
943void QWaylandQuickItem::updateFocus()
945 Q_D(
const QWaylandQuickItem);
946 if (hasActiveFocus() && compositor())
947 compositor()->defaultSeat()->setKeyboardFocus(d->view->surface());
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
974
975
976
977
978
979
980
981
982
983
984
985
986
987QObject *QWaylandQuickItem::subsurfaceHandler()
const
989 Q_D(
const QWaylandQuickItem);
990 return d->subsurfaceHandler.data();
993void QWaylandQuickItem::setSubsurfaceHandler(QObject *handler)
995 Q_D(QWaylandQuickItem);
996 if (d->subsurfaceHandler.data() != handler) {
997 d->subsurfaceHandler = handler;
998 emit subsurfaceHandlerChanged();
1003
1004
1005
1006
1008
1009
1010
1011
1012QWaylandOutput *QWaylandQuickItem::output()
const
1014 Q_D(
const QWaylandQuickItem);
1015 return d->view->output();
1018void QWaylandQuickItem::setOutput(QWaylandOutput *output)
1020 Q_D(QWaylandQuickItem);
1021 d->view->setOutput(output);
1025
1026
1027
1028
1029
1030
1031
1033
1034
1035
1036
1037
1038
1039
1040bool QWaylandQuickItem::isBufferLocked()
const
1042 Q_D(
const QWaylandQuickItem);
1043 return d->view->isBufferLocked();
1046void QWaylandQuickItem::setBufferLocked(
bool locked)
1048 Q_D(QWaylandQuickItem);
1049 d->view->setBufferLocked(locked);
1053
1054
1055
1056
1057
1058
1059
1060bool QWaylandQuickItem::allowDiscardFrontBuffer()
const
1062 Q_D(
const QWaylandQuickItem);
1063 return d->view->allowDiscardFrontBuffer();
1066void QWaylandQuickItem::setAllowDiscardFrontBuffer(
bool discard)
1068 Q_D(QWaylandQuickItem);
1069 d->view->setAllowDiscardFrontBuffer(discard);
1073
1074
1075
1076
1079
1080
1081
1082
1083void QWaylandQuickItem::setPrimary()
1085 Q_D(QWaylandQuickItem);
1086 d->view->setPrimary();
1090
1091
1092void QWaylandQuickItem::handleSurfaceChanged()
1094 Q_D(QWaylandQuickItem);
1095 if (d->oldSurface) {
1096 disconnect(d->oldSurface.data(), &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1097 disconnect(d->oldSurface.data(), &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1098 disconnect(d->oldSurface.data(), &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1099 disconnect(d->oldSurface.data(), &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1100 disconnect(d->oldSurface.data(), &QWaylandSurface::redraw,
this, &QQuickItem::update);
1101 disconnect(d->oldSurface.data(), &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1102 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1103 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1104#if QT_CONFIG(draganddrop)
1105 disconnect(d->oldSurface.data(), &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1108 disconnect(d->oldSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1111 if (QWaylandSurface *newSurface = d->view->surface()) {
1112 connect(newSurface, &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1113 connect(newSurface, &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1114 connect(newSurface, &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1115 connect(newSurface, &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1116 connect(newSurface, &QWaylandSurface::redraw,
this, &QQuickItem::update);
1117 connect(newSurface, &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1118 connect(newSurface, &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1119 connect(newSurface, &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1120#if QT_CONFIG(draganddrop)
1121 connect(newSurface, &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1124 connect(newSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1127 if (newSurface->origin() != d->origin) {
1128 d->origin = newSurface->origin();
1129 emit originChanged();
1132 QWaylandOutput *output = newSurface->compositor()->outputFor(window());
1133 d->view->setOutput(output);
1135 for (
auto subsurface : QWaylandSurfacePrivate::get(newSurface)->subsurfaceChildren) {
1136 if (!subsurface.isNull())
1137 handleSubsurfaceAdded(subsurface.data());
1142 surfaceChangedEvent(d->view->surface(), d->oldSurface);
1143 d->oldSurface = d->view->surface();
1145 updateInputMethod(Qt::ImQueryInput);
1150
1151
1152
1153void QWaylandQuickItem::takeFocus(QWaylandSeat *device)
1157 if (!surface() || !surface()->client())
1160 QWaylandSeat *target = device;
1162 target = compositor()->defaultSeat();
1164 target->setKeyboardFocus(surface());
1166 qCDebug(qLcWaylandCompositorInputMethods) << Q_FUNC_INFO <<
" surface:" << surface()
1167 <<
", client:" << surface()->client()
1168 <<
", textinputprotocol:" << (
int)(surface()->client()->textInputProtocols());
1169 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
1170 QWaylandTextInput *textInput = QWaylandTextInput::findIn(target);
1172 textInput->setFocus(surface());
1175 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
1176 QWaylandTextInputV3 *textInputV3 = QWaylandTextInputV3::findIn(target);
1178 textInputV3->setFocus(surface());
1181 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) {
1182 QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(target);
1183 if (textInputMethod)
1184 textInputMethod->setFocus(surface());
1189
1190
1191void QWaylandQuickItem::handleBufferLockedChanged()
1193 Q_D(QWaylandQuickItem);
1196 if (!d->view->isBufferLocked()) {
1202#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
1203void QWaylandQuickItem::surfaceMappedChanged()
1210
1211
1212void QWaylandQuickItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
1214 Q_UNUSED(oldParent);
1217 setPaintEnabled(
true);
1225
1226
1227void QWaylandQuickItem::updateSize()
1229 Q_D(QWaylandQuickItem);
1232 if (isBufferLocked()) {
1233 qWarning() <<
"No update on item size as the buffer is currently locked";
1239 size = surface()->destinationSize() * d->scaleFactor();
1241 setImplicitSize(size.width(), size.height());
1245
1246
1247
1248
1249
1250
1251
1254
1255
1256
1257
1258
1259
1260
1261bool QWaylandQuickItem::focusOnClick()
const
1263 Q_D(
const QWaylandQuickItem);
1264 return d->focusOnClick;
1267void QWaylandQuickItem::setFocusOnClick(
bool focus)
1269 Q_D(QWaylandQuickItem);
1270 if (d->focusOnClick == focus)
1273 d->focusOnClick = focus;
1274 emit focusOnClickChanged();
1278
1279
1280
1281bool QWaylandQuickItem::inputRegionContains(
const QPointF &localPosition)
const
1283 if (QWaylandSurface *s = surface())
1284 return s->inputRegionContains(mapToSurface(localPosition));
1289
1290
1291
1292
1293
1294
1297
1298
1299
1300
1301QPointF QWaylandQuickItem::mapToSurface(
const QPointF &point)
const
1303 Q_D(
const QWaylandQuickItem);
1304 if (!surface() || surface()->destinationSize().isEmpty())
1305 return point / d->scaleFactor();
1307 qreal xScale = width() / surface()->destinationSize().width();
1308 qreal yScale = height() / surface()->destinationSize().height();
1310 return QPointF(point.x() / xScale, point.y() / yScale);
1314
1315
1316
1317
1318
1319
1322
1323
1324
1325
1326
1327QPointF QWaylandQuickItem::mapFromSurface(
const QPointF &point)
const
1329 Q_D(
const QWaylandQuickItem);
1330 if (!surface() || surface()->destinationSize().isEmpty())
1331 return point * d->scaleFactor();
1333 qreal xScale = width() / surface()->destinationSize().width();
1334 qreal yScale = height() / surface()->destinationSize().height();
1336 return QPointF(point.x() * xScale, point.y() * yScale);
1340QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query)
const
1342 return inputMethodQuery(query, QVariant());
1345QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument)
const
1347 Q_D(
const QWaylandQuickItem);
1349 if (query == Qt::ImEnabled)
1350 return QVariant((flags() & ItemAcceptsInputMethod) != 0);
1353 return d->oldSurface->inputMethodControl()->inputMethodQuery(query, argument);
1360
1361
1362
1363
1364
1365
1366
1369
1370
1371
1372
1373
1374
1375
1376bool QWaylandQuickItem::isPaintEnabled()
const
1378 Q_D(
const QWaylandQuickItem);
1379 return d->paintEnabled;
1382void QWaylandQuickItem::setPaintEnabled(
bool enabled)
1384 Q_D(QWaylandQuickItem);
1386 if (enabled != d->paintEnabled) {
1387 d->paintEnabled = enabled;
1388 emit paintEnabledChanged();
1395
1396
1397
1398
1399
1402
1403
1404
1405
1406
1407bool QWaylandQuickItem::touchEventsEnabled()
const
1409 Q_D(
const QWaylandQuickItem);
1410 return d->touchEventsEnabled;
1413void QWaylandQuickItem::updateBuffer(
bool hasBuffer)
1415 Q_D(QWaylandQuickItem);
1416 Q_UNUSED(hasBuffer);
1417 if (d->origin != surface()->origin()) {
1418 d->origin = surface()->origin();
1419 emit originChanged();
1423void QWaylandQuickItem::updateWindow()
1425 Q_D(QWaylandQuickItem);
1427 QQuickWindow *newWindow = window();
1428 if (newWindow == d->connectedWindow)
1431 if (d->connectedWindow) {
1432 disconnect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync);
1433 disconnect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1436 d->connectedWindow = newWindow;
1438 if (d->connectedWindow) {
1439 connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection);
1440 connect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1443 QWaylandOutput *output = compositor()->outputFor(d->connectedWindow);
1445 d->view->setOutput(output);
1452void QWaylandQuickItem::updateOutput()
1454 Q_D(QWaylandQuickItem);
1455 if (d->view->output() == d->connectedOutput)
1458 if (d->connectedOutput)
1459 disconnect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1461 d->connectedOutput = d->view->output();
1463 if (d->connectedOutput)
1464 connect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1469void QWaylandQuickItem::beforeSync()
1471 Q_D(QWaylandQuickItem);
1472 if (d->view->advance()) {
1473 d->newTexture =
true;
1479void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
1481 Q_D(QWaylandQuickItem);
1483 setFlag(QQuickItem::ItemAcceptsInputMethod,
1484 d->oldSurface ? d->oldSurface->inputMethodControl()->enabled() :
false);
1485 QQuickItem::updateInputMethod(queries | Qt::ImEnabled);
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1515QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1517 Q_D(QWaylandQuickItem);
1518 d->lastMatrix = data->transformNode->combinedMatrix();
1519 const bool bufferHasContent = d->view->currentBuffer().hasContent();
1521 if (d->view->isBufferLocked() && d->paintEnabled)
1524 if (!bufferHasContent || !d->paintEnabled || !surface()) {
1529 QWaylandBufferRef ref = d->view->currentBuffer();
1530 const bool invertY = ref.origin() == QWaylandSurface::OriginBottomLeft;
1531 const QRectF rect = invertY ? QRectF(0, height(), width(), -height())
1532 : QRectF(0, 0, width(), height());
1534 if (ref.isSharedMemory()
1535#if QT_CONFIG(opengl)
1536 || bufferTypes[ref.bufferFormatEgl()].canProvideTexture
1539#if QT_CONFIG(opengl)
1540 if (oldNode && !d->paintByProvider) {
1545 d->paintByProvider =
true;
1548 QSGSimpleTextureNode *node =
static_cast<QSGSimpleTextureNode *>(oldNode);
1551 node =
new QSGSimpleTextureNode();
1553 node->setFiltering(QSGTexture::Linear);
1554 d->newTexture =
true;
1558 d->provider =
new QWaylandSurfaceTextureProvider();
1560 d->texProviderConnection =
1563 &QObject::destroyed,
1566 auto *itemPriv = QWaylandQuickItemPrivate::get(
this);
1567 if (itemPriv->provider) {
1568 itemPriv->provider->reportCompositorDestroyed();
1569 itemPriv->provider =
nullptr;
1571 disconnect(itemPriv->texProviderConnection); }
1576 if (d->newTexture) {
1577 d->newTexture =
false;
1578 d->provider->setBufferRef(
this, ref);
1579 node->setTexture(d->provider->texture());
1582 d->provider->setSmooth(smooth());
1583 node->setRect(rect);
1585 qreal scale = surface()->bufferScale();
1586 QRectF source = surface()->sourceGeometry();
1587 node->setSourceRect(QRectF(source.topLeft() * scale, source.size() * scale));
1592#if QT_CONFIG(opengl)
1593 Q_ASSERT(!d->provider);
1595 if (oldNode && d->paintByProvider) {
1600 d->paintByProvider =
false;
1602 QSGGeometryNode *node =
static_cast<QSGGeometryNode *>(oldNode);
1605 node =
new QSGGeometryNode;
1606 d->newTexture =
true;
1609 QSGGeometry *geometry = node->geometry();
1610 QWaylandBufferMaterial *material =
static_cast<QWaylandBufferMaterial *>(node->material());
1613 geometry =
new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
1616 material =
new QWaylandBufferMaterial(ref.bufferFormatEgl());
1618 if (d->newTexture) {
1619 d->newTexture =
false;
1620 material->setBufferRef(
this, ref);
1623 const QSize surfaceSize = ref.size() / surface()->bufferScale();
1624 const QRectF sourceGeometry = surface()->sourceGeometry();
1625 const QRectF normalizedCoordinates =
1626 sourceGeometry.isValid()
1627 ? QRectF(sourceGeometry.x() / surfaceSize.width(),
1628 sourceGeometry.y() / surfaceSize.height(),
1629 sourceGeometry.width() / surfaceSize.width(),
1630 sourceGeometry.height() / surfaceSize.height())
1631 : QRectF(0, 0, 1, 1);
1633 QSGGeometry::updateTexturedRectGeometry(geometry, rect, normalizedCoordinates);
1635 node->setGeometry(geometry);
1636 node->setFlag(QSGNode::OwnsGeometry,
true);
1638 node->setMaterial(material);
1639 node->setFlag(QSGNode::OwnsMaterial,
true);
1643 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
1648void QWaylandQuickItem::setTouchEventsEnabled(
bool enabled)
1650 Q_D(QWaylandQuickItem);
1651 if (d->touchEventsEnabled != enabled) {
1652 d->touchEventsEnabled = enabled;
1653 emit touchEventsEnabledChanged();
1658
1659
1660
1661
1662
1663
1664
1667
1668
1669
1670
1671
1672
1673
1674bool QWaylandQuickItem::inputEventsEnabled()
const
1676 Q_D(
const QWaylandQuickItem);
1677 return d->inputEventsEnabled;
1680void QWaylandQuickItem::setInputEventsEnabled(
bool enabled)
1682 Q_D(QWaylandQuickItem);
1683 if (d->inputEventsEnabled != enabled) {
1686 d->setInputEventsEnabled(enabled);
1687 emit inputEventsEnabledChanged();
1691void QWaylandQuickItem::lower()
1693 Q_D(QWaylandQuickItem);
1699 Q_Q(QWaylandQuickItem);
1700 QQuickItem *parent = q->parentItem();
1702 QQuickItem *bottom = parent->childItems().constFirst();
1704 q->stackBefore(bottom);
1707void QWaylandQuickItem::raise()
1709 Q_D(QWaylandQuickItem);
1715 Q_Q(QWaylandQuickItem);
1716 QQuickItem *parent = q->parentItem();
1718 QQuickItem *top = parent->childItems().constLast();
1723void QWaylandQuickItem::sendMouseMoveEvent(
const QPointF &position, QWaylandSeat *seat)
1725 if (seat ==
nullptr)
1726 seat = compositor()->defaultSeat();
1729 qWarning() <<
"No seat, can't send mouse event";
1733 seat->sendMouseMoveEvent(view(), position);
1737
1738
1739
1740
1741void QWaylandQuickItem::handleSubsurfacePosition(
const QPoint &pos)
1743 Q_D(QWaylandQuickItem);
1744 QQuickItem::setPosition(pos * d->scaleFactor());
1747#if QT_CONFIG(draganddrop)
1748void QWaylandQuickItem::handleDragStarted(QWaylandDrag *drag)
1750 Q_D(QWaylandQuickItem);
1751 Q_ASSERT(drag->origin() == surface());
1752 drag->seat()->setMouseFocus(
nullptr);
1753 d->isDragging =
true;
1759 qreal f = view->output() ? view->output()->scaleFactor() : 1;
1760#if !defined(Q_OS_MACOS)
1762 f /= window->devicePixelRatio();
1769 Q_Q(
const QWaylandQuickItem);
1770 auto *parent = q->parentItem();
1774 const auto siblings = q->parentItem()->childItems();
1775 for (
auto *sibling : siblings) {
1776 auto *waylandItem = qobject_cast<QWaylandQuickItem *>(sibling);
1777 if (waylandItem && waylandItem->surface() == surface)
1785 Q_Q(QWaylandQuickItem);
1786 q->stackAfter(sibling);
1787 q->setZ(sibling->z());
1788 belowParent = sibling->d_func()->belowParent;
1793 Q_Q(QWaylandQuickItem);
1794 q->stackBefore(sibling);
1795 q->setZ(sibling->z());
1796 belowParent = sibling->d_func()->belowParent;
1802 Q_Q(QWaylandQuickItem);
1803 const auto siblings = q->parentItem()->childItems();
1806 bool foundSibling =
false;
1807 for (
auto it = siblings.cbegin(); it != siblings.cend(); ++it) {
1808 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1809 if (sibling && !sibling->d_func()->belowParent) {
1810 q->stackBefore(sibling);
1811 foundSibling =
true;
1817 if (!foundSibling && siblings.last() != q)
1818 q->stackAfter(siblings.last());
1820 q->setZ(q->parentItem()->z());
1827 Q_Q(QWaylandQuickItem);
1828 const auto siblings = q->parentItem()->childItems();
1831 bool foundSibling =
false;
1832 for (
auto it = siblings.crbegin(); it != siblings.crend(); ++it) {
1833 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1834 if (sibling && sibling->d_func()->belowParent) {
1835 q->stackAfter(sibling);
1836 foundSibling =
true;
1842 if (!foundSibling && siblings.first() != q)
1843 q->stackBefore(siblings.first());
1845 q->setZ(q->parentItem()->z() - 1.0);
1851#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()