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;
383 void setBufferRef(QWaylandQuickItem *surfaceItem,
const QWaylandBufferRef &buffer)
385 Q_ASSERT(QThread::currentThread() == thread());
389 if (m_ref.hasBuffer()) {
390 if (buffer.isSharedMemory()) {
391 m_sgTex = surfaceItem->window()->createTextureFromImage(buffer.image());
394 QQuickWindow::CreateTextureOptions opt;
395 QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
396 if (surface && surface->useTextureAlpha() && !surface->isOpaque()) {
397 opt |= QQuickWindow::TextureHasAlphaChannel;
400 auto texture = buffer.toOpenGLTexture();
401 GLuint textureId = texture->textureId();
402 auto size = surface->bufferSize();
403 m_sgTex = QNativeInterface::QSGOpenGLTexture::fromNative(textureId, surfaceItem->window(), size, opt);
405 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
409 emit textureChanged();
415 m_sgTex->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
421 bool m_smooth =
false;
422 QSGTexture *m_sgTex =
nullptr;
423 QWaylandBufferRef m_ref;
428#if QT_CONFIG(draganddrop)
429 Q_Q(QWaylandQuickItem);
430 QWaylandQuickOutput *currentOutput = qobject_cast<QWaylandQuickOutput *>(q->view()->output());
432 QWaylandQuickItem *targetItem = qobject_cast<QWaylandQuickItem *>(currentOutput->pickClickableItem(q->mapToScene(globalPosition)));
433 QWaylandSurface *targetSurface = targetItem ? targetItem->surface() :
nullptr;
435 QPointF position = q->mapToItem(targetItem, globalPosition);
436 QPointF surfacePosition = targetItem->mapToSurface(position);
437 seat->drag()->dragMove(targetSurface, surfacePosition);
441 Q_UNUSED(globalPosition);
447#if QT_CONFIG(draganddrop)
449 seat->drag()->drop();
456
457
458
459
460
461
462
463
464
465
468
469
470
471
472
473
474
475
476
479
480
481QWaylandQuickItem::QWaylandQuickItem(QQuickItem *parent)
482 : QWaylandQuickItem(*
new QWaylandQuickItemPrivate(), parent)
487
488
489QWaylandQuickItem::QWaylandQuickItem(QWaylandQuickItemPrivate &dd, QQuickItem *parent)
490 : QQuickItem(dd, parent)
493 connect(
this, &QQuickItem::activeFocusChanged,
this, &QWaylandQuickItem::updateFocus);
497
498
499QWaylandQuickItem::~QWaylandQuickItem()
501 Q_D(QWaylandQuickItem);
502 disconnect(
this, &QQuickItem::windowChanged,
this, &QWaylandQuickItem::updateWindow);
503 disconnect(
this, &QQuickItem::activeFocusChanged,
this, &QWaylandQuickItem::updateFocus);
504 QMutexLocker locker(d->mutex);
506 disconnect(d->texProviderConnection);
507 d->provider->deleteLater();
512
513
514
515
518
519
520
521
522QWaylandCompositor *QWaylandQuickItem::compositor()
const
524 Q_D(
const QWaylandQuickItem);
525 return d->view->surface() ? d->view->surface()->compositor() :
nullptr;
529
530
531QWaylandView *QWaylandQuickItem::view()
const
533 Q_D(
const QWaylandQuickItem);
534 return d->view.data();
538
539
540
541
544
545
546
547
549QWaylandSurface *QWaylandQuickItem::surface()
const
551 Q_D(
const QWaylandQuickItem);
552 return d->view->surface();
555void QWaylandQuickItem::setSurface(QWaylandSurface *surface)
557 Q_D(QWaylandQuickItem);
558 QWaylandSurface *oldSurf = d->view->surface();
559 QWaylandCompositor *oldComp = d->view->surface() ? d->view->surface()->compositor() :
nullptr;
560 d->view->setSurface(surface);
561 QWaylandCompositor *newComp = d->view->surface() ? d->view->surface()->compositor() :
nullptr;
562 if (oldComp != newComp)
563 emit compositorChanged();
564 if (oldSurf != surface)
565 emit surfaceChanged();
572
573
574
575
578
579
580
581
582QWaylandSurface::Origin QWaylandQuickItem::origin()
const
584 Q_D(
const QWaylandQuickItem);
588bool QWaylandQuickItem::isTextureProvider()
const
590 Q_D(
const QWaylandQuickItem);
591 return QQuickItem::isTextureProvider() || d->provider;
595
596
597QSGTextureProvider *QWaylandQuickItem::textureProvider()
const
599 Q_D(
const QWaylandQuickItem);
601 if (QQuickItem::isTextureProvider())
602 return QQuickItem::textureProvider();
608
609
610void QWaylandQuickItem::mousePressEvent(QMouseEvent *event)
612 Q_D(QWaylandQuickItem);
613 if (!d->shouldSendInputEvents()) {
618 if (!inputRegionContains(event->position())) {
623 QWaylandSeat *seat = compositor()->seatFor(event);
628 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), event->scenePosition());
629 seat->sendMousePressEvent(event->button());
630 d->hoverPos = event->position();
634
635
636void QWaylandQuickItem::mouseMoveEvent(QMouseEvent *event)
638 Q_D(QWaylandQuickItem);
639 if (d->shouldSendInputEvents()) {
640 QWaylandSeat *seat = compositor()->seatFor(event);
642 d->handleDragUpdate(seat, event->position());
644 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), event->scenePosition());
645 d->hoverPos = event->position();
648 emit mouseMove(event->scenePosition());
654
655
656void QWaylandQuickItem::mouseReleaseEvent(QMouseEvent *event)
658 Q_D(QWaylandQuickItem);
659 if (d->shouldSendInputEvents()) {
660 QWaylandSeat *seat = compositor()->seatFor(event);
662 d->handleDragEnded(seat);
664 seat->sendMouseReleaseEvent(event->button());
672
673
674void QWaylandQuickItem::hoverEnterEvent(QHoverEvent *event)
676 Q_D(QWaylandQuickItem);
677 if (!inputRegionContains(event->position())) {
681 if (d->shouldSendInputEvents()) {
682 QWaylandSeat *seat = compositor()->seatFor(event);
683 seat->sendMouseMoveEvent(d->view.data(), event->position(), mapToScene(event->position()));
684 d->hoverPos = event->position();
691
692
693void QWaylandQuickItem::hoverMoveEvent(QHoverEvent *event)
695 Q_D(QWaylandQuickItem);
697 if (!inputRegionContains(event->position())) {
702 if (d->shouldSendInputEvents()) {
703 QWaylandSeat *seat = compositor()->seatFor(event);
704 if (event->position() != d->hoverPos) {
705 seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->position()), mapToScene(event->position()));
706 d->hoverPos = event->position();
714
715
716void QWaylandQuickItem::hoverLeaveEvent(QHoverEvent *event)
718 Q_D(QWaylandQuickItem);
719 if (d->shouldSendInputEvents()) {
720 QWaylandSeat *seat = compositor()->seatFor(event);
721 if (d->view.data() == seat->mouseFocus()) {
722 seat->setMouseFocus(
nullptr);
730#if QT_CONFIG(wheelevent)
732
733
734void QWaylandQuickItem::wheelEvent(QWheelEvent *event)
736 Q_D(QWaylandQuickItem);
737 if (d->shouldSendInputEvents()) {
738 if (!inputRegionContains(event->position())) {
743 QWaylandSeat *seat = compositor()->seatFor(event);
745 if (event->angleDelta().x() != 0)
746 seat->sendMouseWheelEvent(Qt::Horizontal, event->angleDelta().x());
747 if (event->angleDelta().y() != 0)
748 seat->sendMouseWheelEvent(Qt::Vertical, event->angleDelta().y());
756
757
758void QWaylandQuickItem::keyPressEvent(QKeyEvent *event)
760 Q_D(QWaylandQuickItem);
761 if (d->shouldSendInputEvents()) {
762 QWaylandSeat *seat = compositor()->seatFor(event);
763 if (seat->setKeyboardFocus(d->view->surface()))
764 seat->sendFullKeyEvent(event);
766 qWarning() <<
"Unable to set keyboard focus, cannot send key press event";
773
774
775void QWaylandQuickItem::keyReleaseEvent(QKeyEvent *event)
777 Q_D(QWaylandQuickItem);
778 if (d->shouldSendInputEvents()) {
779 QWaylandSeat *seat = compositor()->seatFor(event);
780 seat->sendFullKeyEvent(event);
787
788
789void QWaylandQuickItem::touchEvent(QTouchEvent *event)
791 Q_D(QWaylandQuickItem);
792 if (d->shouldSendInputEvents() && d->touchEventsEnabled) {
793 QWaylandSeat *seat = compositor()->seatFor(event);
796 const QList<QTouchEvent::TouchPoint> &points = event->points();
797 if (!points.isEmpty())
798 pointPos = points.at(0).position();
800 if (event->type() == QEvent::TouchBegin && !inputRegionContains(pointPos)) {
805 if (event->type() == QEvent::TouchUpdate && d->isDragging)
806 d->handleDragUpdate(seat, pointPos);
809 if (seat->mouseFocus() != d->view.data()) {
810 seat->sendMouseMoveEvent(d->view.data(), pointPos, mapToScene(pointPos));
812 seat->sendFullTouchEvent(surface(), event);
814 if (event->type() == QEvent::TouchBegin) {
815 d->touchingSeats.append(seat);
816 }
else if (event->type() == QEvent::TouchEnd || event->type() == QEvent::TouchCancel) {
818 d->handleDragEnded(seat);
819 d->touchingSeats.removeOne(seat);
822 if (event->type() == QEvent::TouchBegin && d->focusOnClick)
829void QWaylandQuickItem::touchUngrabEvent()
831 Q_D(QWaylandQuickItem);
833 if (d->shouldSendInputEvents())
834 for (
auto seat : d->touchingSeats)
835 seat->sendTouchCancelEvent(surface()->client());
837 d->touchingSeats.clear();
842
843
844void QWaylandQuickItem::inputMethodEvent(QInputMethodEvent *event)
846 Q_D(QWaylandQuickItem);
847 if (d->shouldSendInputEvents()) {
848 d->oldSurface->inputMethodControl()->inputMethodEvent(event);
856
857
858void QWaylandQuickItem::surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface)
860 Q_UNUSED(newSurface);
861 Q_UNUSED(oldSurface);
864void QWaylandQuickItem::handleSubsurfaceAdded(QWaylandSurface *childSurface)
866 Q_D(QWaylandQuickItem);
867 if (d->subsurfaceHandler.isNull()) {
868 QWaylandQuickItem *childItem =
new QWaylandQuickItem;
869 childItem->setSurface(childSurface);
870 childItem->setVisible(
true);
871 childItem->setParentItem(
this);
872 childItem->setParent(
this);
873 connect(childSurface, &QWaylandSurface::subsurfacePositionChanged, childItem, &QWaylandQuickItem::handleSubsurfacePosition);
874 connect(childSurface, &QWaylandSurface::destroyed, childItem, &QObject::deleteLater);
876 bool success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded", Q_ARG(QWaylandSurface *, childSurface));
878 success = QMetaObject::invokeMethod(d->subsurfaceHandler,
"handleSubsurfaceAdded",
879 Q_ARG(QVariant, QVariant::fromValue(childSurface)));
882 qWarning(
"QWaylandQuickItem: subsurfaceHandler does not implement handleSubsurfaceAdded()");
886void QWaylandQuickItem::handlePlaceAbove(QWaylandSurface *referenceSurface)
888 Q_D(QWaylandQuickItem);
889 auto *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
893 if (parent->surface() == referenceSurface) {
894 d->placeAboveParent();
895 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
896 d->placeAboveSibling(sibling);
898 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
899 <<
"when handling wl_subsurface.place_above";
903void QWaylandQuickItem::handlePlaceBelow(QWaylandSurface *referenceSurface)
905 Q_D(QWaylandQuickItem);
906 QWaylandQuickItem *parent = qobject_cast<QWaylandQuickItem*>(parentItem());
910 if (parent->surface() == referenceSurface) {
911 d->placeBelowParent();
912 }
else if (
auto *sibling = d->findSibling(referenceSurface)) {
913 d->placeBelowSibling(sibling);
915 qWarning() <<
"Couldn't find QWaylandQuickItem for surface" << referenceSurface
916 <<
"when handling wl_subsurface.place_below";
920void QWaylandQuickItem::updateFocus()
922 Q_D(
const QWaylandQuickItem);
923 if (hasActiveFocus() && compositor())
924 compositor()->defaultSeat()->setKeyboardFocus(d->view->surface());
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
951
952
953
954
955
956
957
958
959
960
961
962
963
964QObject *QWaylandQuickItem::subsurfaceHandler()
const
966 Q_D(
const QWaylandQuickItem);
967 return d->subsurfaceHandler.data();
970void QWaylandQuickItem::setSubsurfaceHandler(QObject *handler)
972 Q_D(QWaylandQuickItem);
973 if (d->subsurfaceHandler.data() != handler) {
974 d->subsurfaceHandler = handler;
975 emit subsurfaceHandlerChanged();
980
981
982
983
985
986
987
988
989QWaylandOutput *QWaylandQuickItem::output()
const
991 Q_D(
const QWaylandQuickItem);
992 return d->view->output();
995void QWaylandQuickItem::setOutput(QWaylandOutput *output)
997 Q_D(QWaylandQuickItem);
998 d->view->setOutput(output);
1002
1003
1004
1005
1006
1007
1008
1010
1011
1012
1013
1014
1015
1016
1017bool QWaylandQuickItem::isBufferLocked()
const
1019 Q_D(
const QWaylandQuickItem);
1020 return d->view->isBufferLocked();
1023void QWaylandQuickItem::setBufferLocked(
bool locked)
1025 Q_D(QWaylandQuickItem);
1026 d->view->setBufferLocked(locked);
1030
1031
1032
1033
1034
1035
1036
1037bool QWaylandQuickItem::allowDiscardFrontBuffer()
const
1039 Q_D(
const QWaylandQuickItem);
1040 return d->view->allowDiscardFrontBuffer();
1043void QWaylandQuickItem::setAllowDiscardFrontBuffer(
bool discard)
1045 Q_D(QWaylandQuickItem);
1046 d->view->setAllowDiscardFrontBuffer(discard);
1050
1051
1052
1053
1056
1057
1058
1059
1060void QWaylandQuickItem::setPrimary()
1062 Q_D(QWaylandQuickItem);
1063 d->view->setPrimary();
1067
1068
1069void QWaylandQuickItem::handleSurfaceChanged()
1071 Q_D(QWaylandQuickItem);
1072 if (d->oldSurface) {
1073 disconnect(d->oldSurface.data(), &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1074 disconnect(d->oldSurface.data(), &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1075 disconnect(d->oldSurface.data(), &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1076 disconnect(d->oldSurface.data(), &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1077 disconnect(d->oldSurface.data(), &QWaylandSurface::redraw,
this, &QQuickItem::update);
1078 disconnect(d->oldSurface.data(), &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1079 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1080 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1081#if QT_CONFIG(draganddrop)
1082 disconnect(d->oldSurface.data(), &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1085 disconnect(d->oldSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1088 if (QWaylandSurface *newSurface = d->view->surface()) {
1089 connect(newSurface, &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1090 connect(newSurface, &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1091 connect(newSurface, &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1092 connect(newSurface, &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1093 connect(newSurface, &QWaylandSurface::redraw,
this, &QQuickItem::update);
1094 connect(newSurface, &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1095 connect(newSurface, &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1096 connect(newSurface, &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1097#if QT_CONFIG(draganddrop)
1098 connect(newSurface, &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1101 connect(newSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1104 if (newSurface->origin() != d->origin) {
1105 d->origin = newSurface->origin();
1106 emit originChanged();
1109 QWaylandOutput *output = newSurface->compositor()->outputFor(window());
1110 d->view->setOutput(output);
1112 for (
auto subsurface : QWaylandSurfacePrivate::get(newSurface)->subsurfaceChildren) {
1113 if (!subsurface.isNull())
1114 handleSubsurfaceAdded(subsurface.data());
1119 surfaceChangedEvent(d->view->surface(), d->oldSurface);
1120 d->oldSurface = d->view->surface();
1122 updateInputMethod(Qt::ImQueryInput);
1127
1128
1129
1130void QWaylandQuickItem::takeFocus(QWaylandSeat *device)
1134 if (!surface() || !surface()->client())
1137 QWaylandSeat *target = device;
1139 target = compositor()->defaultSeat();
1141 target->setKeyboardFocus(surface());
1143 qCDebug(qLcWaylandCompositorInputMethods) << Q_FUNC_INFO <<
" surface:" << surface()
1144 <<
", client:" << surface()->client()
1145 <<
", textinputprotocol:" << (
int)(surface()->client()->textInputProtocols());
1146 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
1147 QWaylandTextInput *textInput = QWaylandTextInput::findIn(target);
1149 textInput->setFocus(surface());
1152 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
1153 QWaylandTextInputV3 *textInputV3 = QWaylandTextInputV3::findIn(target);
1155 textInputV3->setFocus(surface());
1158 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) {
1159 QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(target);
1160 if (textInputMethod)
1161 textInputMethod->setFocus(surface());
1166
1167
1168void QWaylandQuickItem::handleBufferLockedChanged()
1170 Q_D(QWaylandQuickItem);
1173 if (!d->view->isBufferLocked()) {
1179#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
1180void QWaylandQuickItem::surfaceMappedChanged()
1187
1188
1189void QWaylandQuickItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
1191 Q_UNUSED(oldParent);
1194 setPaintEnabled(
true);
1202
1203
1204void QWaylandQuickItem::updateSize()
1206 Q_D(QWaylandQuickItem);
1209 if (isBufferLocked()) {
1210 qWarning() <<
"No update on item size as the buffer is currently locked";
1216 size = surface()->destinationSize() * d->scaleFactor();
1218 setImplicitSize(size.width(), size.height());
1222
1223
1224
1225
1226
1227
1228
1231
1232
1233
1234
1235
1236
1237
1238bool QWaylandQuickItem::focusOnClick()
const
1240 Q_D(
const QWaylandQuickItem);
1241 return d->focusOnClick;
1244void QWaylandQuickItem::setFocusOnClick(
bool focus)
1246 Q_D(QWaylandQuickItem);
1247 if (d->focusOnClick == focus)
1250 d->focusOnClick = focus;
1251 emit focusOnClickChanged();
1255
1256
1257
1258bool QWaylandQuickItem::inputRegionContains(
const QPointF &localPosition)
const
1260 if (QWaylandSurface *s = surface())
1261 return s->inputRegionContains(mapToSurface(localPosition));
1266
1267
1268
1269
1270
1271
1274
1275
1276
1277
1278QPointF QWaylandQuickItem::mapToSurface(
const QPointF &point)
const
1280 Q_D(
const QWaylandQuickItem);
1281 if (!surface() || surface()->destinationSize().isEmpty())
1282 return point / d->scaleFactor();
1284 qreal xScale = width() / surface()->destinationSize().width();
1285 qreal yScale = height() / surface()->destinationSize().height();
1287 return QPointF(point.x() / xScale, point.y() / yScale);
1291
1292
1293
1294
1295
1296
1299
1300
1301
1302
1303
1304QPointF QWaylandQuickItem::mapFromSurface(
const QPointF &point)
const
1306 Q_D(
const QWaylandQuickItem);
1307 if (!surface() || surface()->destinationSize().isEmpty())
1308 return point * d->scaleFactor();
1310 qreal xScale = width() / surface()->destinationSize().width();
1311 qreal yScale = height() / surface()->destinationSize().height();
1313 return QPointF(point.x() * xScale, point.y() * yScale);
1317QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query)
const
1319 return inputMethodQuery(query, QVariant());
1322QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument)
const
1324 Q_D(
const QWaylandQuickItem);
1326 if (query == Qt::ImEnabled)
1327 return QVariant((flags() & ItemAcceptsInputMethod) != 0);
1330 return d->oldSurface->inputMethodControl()->inputMethodQuery(query, argument);
1337
1338
1339
1340
1341
1342
1343
1346
1347
1348
1349
1350
1351
1352
1353bool QWaylandQuickItem::isPaintEnabled()
const
1355 Q_D(
const QWaylandQuickItem);
1356 return d->paintEnabled;
1359void QWaylandQuickItem::setPaintEnabled(
bool enabled)
1361 Q_D(QWaylandQuickItem);
1363 if (enabled != d->paintEnabled) {
1364 d->paintEnabled = enabled;
1365 emit paintEnabledChanged();
1372
1373
1374
1375
1376
1379
1380
1381
1382
1383
1384bool QWaylandQuickItem::touchEventsEnabled()
const
1386 Q_D(
const QWaylandQuickItem);
1387 return d->touchEventsEnabled;
1390void QWaylandQuickItem::updateBuffer(
bool hasBuffer)
1392 Q_D(QWaylandQuickItem);
1393 Q_UNUSED(hasBuffer);
1394 if (d->origin != surface()->origin()) {
1395 d->origin = surface()->origin();
1396 emit originChanged();
1400void QWaylandQuickItem::updateWindow()
1402 Q_D(QWaylandQuickItem);
1404 QQuickWindow *newWindow = window();
1405 if (newWindow == d->connectedWindow)
1408 if (d->connectedWindow) {
1409 disconnect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync);
1410 disconnect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1413 d->connectedWindow = newWindow;
1415 if (d->connectedWindow) {
1416 connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection);
1417 connect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1420 QWaylandOutput *output = compositor()->outputFor(d->connectedWindow);
1422 d->view->setOutput(output);
1429void QWaylandQuickItem::updateOutput()
1431 Q_D(QWaylandQuickItem);
1432 if (d->view->output() == d->connectedOutput)
1435 if (d->connectedOutput)
1436 disconnect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1438 d->connectedOutput = d->view->output();
1440 if (d->connectedOutput)
1441 connect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1446void QWaylandQuickItem::beforeSync()
1448 Q_D(QWaylandQuickItem);
1449 if (d->view->advance()) {
1450 d->newTexture =
true;
1456void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
1458 Q_D(QWaylandQuickItem);
1460 setFlag(QQuickItem::ItemAcceptsInputMethod,
1461 d->oldSurface ? d->oldSurface->inputMethodControl()->enabled() :
false);
1462 QQuickItem::updateInputMethod(queries | Qt::ImEnabled);
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1492QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1494 Q_D(QWaylandQuickItem);
1495 d->lastMatrix = data->transformNode->combinedMatrix();
1496 const bool bufferHasContent = d->view->currentBuffer().hasContent();
1498 if (d->view->isBufferLocked() && d->paintEnabled)
1501 if (!bufferHasContent || !d->paintEnabled || !surface()) {
1506 QWaylandBufferRef ref = d->view->currentBuffer();
1507 const bool invertY = ref.origin() == QWaylandSurface::OriginBottomLeft;
1508 const QRectF rect = invertY ? QRectF(0, height(), width(), -height())
1509 : QRectF(0, 0, width(), height());
1511 if (ref.isSharedMemory()
1512#if QT_CONFIG(opengl)
1513 || bufferTypes[ref.bufferFormatEgl()].canProvideTexture
1516#if QT_CONFIG(opengl)
1517 if (oldNode && !d->paintByProvider) {
1522 d->paintByProvider =
true;
1525 QSGSimpleTextureNode *node =
static_cast<QSGSimpleTextureNode *>(oldNode);
1528 node =
new QSGSimpleTextureNode();
1530 node->setFiltering(QSGTexture::Linear);
1531 d->newTexture =
true;
1535 d->provider =
new QWaylandSurfaceTextureProvider();
1537 d->texProviderConnection =
1540 &QObject::destroyed,
1543 auto *itemPriv = QWaylandQuickItemPrivate::get(
this);
1544 if (itemPriv->provider) {
1545 itemPriv->provider->deleteLater();
1546 itemPriv->provider =
nullptr;
1548 disconnect(itemPriv->texProviderConnection); }
1553 if (d->newTexture) {
1554 d->newTexture =
false;
1555 d->provider->setBufferRef(
this, ref);
1556 node->setTexture(d->provider->texture());
1559 d->provider->setSmooth(smooth());
1560 node->setRect(rect);
1562 qreal scale = surface()->bufferScale();
1563 QRectF source = surface()->sourceGeometry();
1564 node->setSourceRect(QRectF(source.topLeft() * scale, source.size() * scale));
1569#if QT_CONFIG(opengl)
1570 Q_ASSERT(!d->provider);
1572 if (oldNode && d->paintByProvider) {
1577 d->paintByProvider =
false;
1579 QSGGeometryNode *node =
static_cast<QSGGeometryNode *>(oldNode);
1582 node =
new QSGGeometryNode;
1583 d->newTexture =
true;
1586 QSGGeometry *geometry = node->geometry();
1587 QWaylandBufferMaterial *material =
static_cast<QWaylandBufferMaterial *>(node->material());
1590 geometry =
new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
1593 material =
new QWaylandBufferMaterial(ref.bufferFormatEgl());
1595 if (d->newTexture) {
1596 d->newTexture =
false;
1597 material->setBufferRef(
this, ref);
1600 const QSize surfaceSize = ref.size() / surface()->bufferScale();
1601 const QRectF sourceGeometry = surface()->sourceGeometry();
1602 const QRectF normalizedCoordinates =
1603 sourceGeometry.isValid()
1604 ? QRectF(sourceGeometry.x() / surfaceSize.width(),
1605 sourceGeometry.y() / surfaceSize.height(),
1606 sourceGeometry.width() / surfaceSize.width(),
1607 sourceGeometry.height() / surfaceSize.height())
1608 : QRectF(0, 0, 1, 1);
1610 QSGGeometry::updateTexturedRectGeometry(geometry, rect, normalizedCoordinates);
1612 node->setGeometry(geometry);
1613 node->setFlag(QSGNode::OwnsGeometry,
true);
1615 node->setMaterial(material);
1616 node->setFlag(QSGNode::OwnsMaterial,
true);
1620 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
1625void QWaylandQuickItem::setTouchEventsEnabled(
bool enabled)
1627 Q_D(QWaylandQuickItem);
1628 if (d->touchEventsEnabled != enabled) {
1629 d->touchEventsEnabled = enabled;
1630 emit touchEventsEnabledChanged();
1635
1636
1637
1638
1639
1640
1641
1644
1645
1646
1647
1648
1649
1650
1651bool QWaylandQuickItem::inputEventsEnabled()
const
1653 Q_D(
const QWaylandQuickItem);
1654 return d->inputEventsEnabled;
1657void QWaylandQuickItem::setInputEventsEnabled(
bool enabled)
1659 Q_D(QWaylandQuickItem);
1660 if (d->inputEventsEnabled != enabled) {
1663 d->setInputEventsEnabled(enabled);
1664 emit inputEventsEnabledChanged();
1668void QWaylandQuickItem::lower()
1670 Q_D(QWaylandQuickItem);
1676 Q_Q(QWaylandQuickItem);
1677 QQuickItem *parent = q->parentItem();
1679 QQuickItem *bottom = parent->childItems().constFirst();
1681 q->stackBefore(bottom);
1684void QWaylandQuickItem::raise()
1686 Q_D(QWaylandQuickItem);
1692 Q_Q(QWaylandQuickItem);
1693 QQuickItem *parent = q->parentItem();
1695 QQuickItem *top = parent->childItems().constLast();
1700void QWaylandQuickItem::sendMouseMoveEvent(
const QPointF &position, QWaylandSeat *seat)
1702 if (seat ==
nullptr)
1703 seat = compositor()->defaultSeat();
1706 qWarning() <<
"No seat, can't send mouse event";
1710 seat->sendMouseMoveEvent(view(), position);
1714
1715
1716
1717
1718void QWaylandQuickItem::handleSubsurfacePosition(
const QPoint &pos)
1720 Q_D(QWaylandQuickItem);
1721 QQuickItem::setPosition(pos * d->scaleFactor());
1724#if QT_CONFIG(draganddrop)
1725void QWaylandQuickItem::handleDragStarted(QWaylandDrag *drag)
1727 Q_D(QWaylandQuickItem);
1728 Q_ASSERT(drag->origin() == surface());
1729 drag->seat()->setMouseFocus(
nullptr);
1730 d->isDragging =
true;
1736 qreal f = view->output() ? view->output()->scaleFactor() : 1;
1737#if !defined(Q_OS_MACOS)
1739 f /= window->devicePixelRatio();
1746 Q_Q(
const QWaylandQuickItem);
1747 auto *parent = q->parentItem();
1751 const auto siblings = q->parentItem()->childItems();
1752 for (
auto *sibling : siblings) {
1753 auto *waylandItem = qobject_cast<QWaylandQuickItem *>(sibling);
1754 if (waylandItem && waylandItem->surface() == surface)
1762 Q_Q(QWaylandQuickItem);
1763 q->stackAfter(sibling);
1764 q->setZ(sibling->z());
1765 belowParent = sibling->d_func()->belowParent;
1770 Q_Q(QWaylandQuickItem);
1771 q->stackBefore(sibling);
1772 q->setZ(sibling->z());
1773 belowParent = sibling->d_func()->belowParent;
1779 Q_Q(QWaylandQuickItem);
1780 const auto siblings = q->parentItem()->childItems();
1783 bool foundSibling =
false;
1784 for (
auto it = siblings.cbegin(); it != siblings.cend(); ++it) {
1785 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1786 if (sibling && !sibling->d_func()->belowParent) {
1787 q->stackBefore(sibling);
1788 foundSibling =
true;
1794 if (!foundSibling && siblings.last() != q)
1795 q->stackAfter(siblings.last());
1797 q->setZ(q->parentItem()->z());
1804 Q_Q(QWaylandQuickItem);
1805 const auto siblings = q->parentItem()->childItems();
1808 bool foundSibling =
false;
1809 for (
auto it = siblings.crbegin(); it != siblings.crend(); ++it) {
1810 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1811 if (sibling && sibling->d_func()->belowParent) {
1812 q->stackAfter(sibling);
1813 foundSibling =
true;
1819 if (!foundSibling && siblings.first() != q)
1820 q->stackBefore(siblings.first());
1822 q->setZ(q->parentItem()->z() - 1.0);
1828#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