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
951QObject *QWaylandQuickItem::subsurfaceHandler()
const
953 Q_D(
const QWaylandQuickItem);
954 return d->subsurfaceHandler.data();
957void QWaylandQuickItem::setSubsurfaceHandler(QObject *handler)
959 Q_D(QWaylandQuickItem);
960 if (d->subsurfaceHandler.data() != handler) {
961 d->subsurfaceHandler = handler;
962 emit subsurfaceHandlerChanged();
967
968
969
970
972
973
974
975
976QWaylandOutput *QWaylandQuickItem::output()
const
978 Q_D(
const QWaylandQuickItem);
979 return d->view->output();
982void QWaylandQuickItem::setOutput(QWaylandOutput *output)
984 Q_D(QWaylandQuickItem);
985 d->view->setOutput(output);
989
990
991
992
993
994
995
997
998
999
1000
1001
1002
1003
1004bool QWaylandQuickItem::isBufferLocked()
const
1006 Q_D(
const QWaylandQuickItem);
1007 return d->view->isBufferLocked();
1010void QWaylandQuickItem::setBufferLocked(
bool locked)
1012 Q_D(QWaylandQuickItem);
1013 d->view->setBufferLocked(locked);
1021
1022
1023
1024
1025
1026
1027
1028bool QWaylandQuickItem::allowDiscardFrontBuffer()
const
1030 Q_D(
const QWaylandQuickItem);
1031 return d->view->allowDiscardFrontBuffer();
1034void QWaylandQuickItem::setAllowDiscardFrontBuffer(
bool discard)
1036 Q_D(QWaylandQuickItem);
1037 d->view->setAllowDiscardFrontBuffer(discard);
1041
1042
1043
1044
1047
1048
1049
1050
1051void QWaylandQuickItem::setPrimary()
1053 Q_D(QWaylandQuickItem);
1054 d->view->setPrimary();
1058
1059
1060void QWaylandQuickItem::handleSurfaceChanged()
1062 Q_D(QWaylandQuickItem);
1063 if (d->oldSurface) {
1064 disconnect(d->oldSurface.data(), &QWaylandSurface::hasContentChanged,
this, &QWaylandQuickItem::surfaceMappedChanged);
1065 disconnect(d->oldSurface.data(), &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1066 disconnect(d->oldSurface.data(), &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1067 disconnect(d->oldSurface.data(), &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1068 disconnect(d->oldSurface.data(), &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1069 disconnect(d->oldSurface.data(), &QWaylandSurface::redraw,
this, &QQuickItem::update);
1070 disconnect(d->oldSurface.data(), &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1071 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1072 disconnect(d->oldSurface.data(), &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1073#if QT_CONFIG(draganddrop)
1074 disconnect(d->oldSurface.data(), &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1077 disconnect(d->oldSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1080 if (QWaylandSurface *newSurface = d->view->surface()) {
1081 connect(newSurface, &QWaylandSurface::hasContentChanged,
this, &QWaylandQuickItem::surfaceMappedChanged);
1082 connect(newSurface, &QWaylandSurface::parentChanged,
this, &QWaylandQuickItem::parentChanged);
1083 connect(newSurface, &QWaylandSurface::destinationSizeChanged,
this, &QWaylandQuickItem::updateSize);
1084 connect(newSurface, &QWaylandSurface::bufferScaleChanged,
this, &QWaylandQuickItem::updateSize);
1085 connect(newSurface, &QWaylandSurface::configure,
this, &QWaylandQuickItem::updateBuffer);
1086 connect(newSurface, &QWaylandSurface::redraw,
this, &QQuickItem::update);
1087 connect(newSurface, &QWaylandSurface::childAdded,
this, &QWaylandQuickItem::handleSubsurfaceAdded);
1088 connect(newSurface, &QWaylandSurface::subsurfacePlaceAbove,
this, &QWaylandQuickItem::handlePlaceAbove);
1089 connect(newSurface, &QWaylandSurface::subsurfacePlaceBelow,
this, &QWaylandQuickItem::handlePlaceBelow);
1090#if QT_CONFIG(draganddrop)
1091 connect(newSurface, &QWaylandSurface::dragStarted,
this, &QWaylandQuickItem::handleDragStarted);
1094 connect(newSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod,
this, &QWaylandQuickItem::updateInputMethod);
1097 if (newSurface->origin() != d->origin) {
1098 d->origin = newSurface->origin();
1099 emit originChanged();
1102 QWaylandOutput *output = newSurface->compositor()->outputFor(window());
1103 d->view->setOutput(output);
1105 for (
auto subsurface : QWaylandSurfacePrivate::get(newSurface)->subsurfaceChildren) {
1106 if (!subsurface.isNull())
1107 handleSubsurfaceAdded(subsurface.data());
1112 surfaceChangedEvent(d->view->surface(), d->oldSurface);
1113 d->oldSurface = d->view->surface();
1115 updateInputMethod(Qt::ImQueryInput);
1120
1121
1122
1123void QWaylandQuickItem::takeFocus(QWaylandSeat *device)
1127 if (!surface() || !surface()->client())
1130 QWaylandSeat *target = device;
1132 target = compositor()->defaultSeat();
1134 target->setKeyboardFocus(surface());
1136 qCDebug(qLcWaylandCompositorInputMethods) << Q_FUNC_INFO <<
" surface:" << surface()
1137 <<
", client:" << surface()->client()
1138 <<
", textinputprotocol:" << (
int)(surface()->client()->textInputProtocols());
1139 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
1140 QWaylandTextInput *textInput = QWaylandTextInput::findIn(target);
1142 textInput->setFocus(surface());
1145 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
1146 QWaylandTextInputV3 *textInputV3 = QWaylandTextInputV3::findIn(target);
1148 textInputV3->setFocus(surface());
1151 if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) {
1152 QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(target);
1153 if (textInputMethod)
1154 textInputMethod->setFocus(surface());
1159
1160
1161void QWaylandQuickItem::surfaceMappedChanged()
1167
1168
1169void QWaylandQuickItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
1171 Q_UNUSED(oldParent);
1174 setPaintEnabled(
true);
1182
1183
1184void QWaylandQuickItem::updateSize()
1186 Q_D(QWaylandQuickItem);
1189 if (isBufferLocked()) {
1190 qWarning() <<
"No update on item size as the buffer is currently locked";
1196 size = surface()->destinationSize() * d->scaleFactor();
1198 setImplicitSize(size.width(), size.height());
1202
1203
1204
1205
1206
1207
1208
1211
1212
1213
1214
1215
1216
1217
1218bool QWaylandQuickItem::focusOnClick()
const
1220 Q_D(
const QWaylandQuickItem);
1221 return d->focusOnClick;
1224void QWaylandQuickItem::setFocusOnClick(
bool focus)
1226 Q_D(QWaylandQuickItem);
1227 if (d->focusOnClick == focus)
1230 d->focusOnClick = focus;
1231 emit focusOnClickChanged();
1235
1236
1237
1238bool QWaylandQuickItem::inputRegionContains(
const QPointF &localPosition)
const
1240 if (QWaylandSurface *s = surface())
1241 return s->inputRegionContains(mapToSurface(localPosition));
1246
1247
1248
1249
1250
1251
1254
1255
1256
1257
1258QPointF QWaylandQuickItem::mapToSurface(
const QPointF &point)
const
1260 Q_D(
const QWaylandQuickItem);
1261 if (!surface() || surface()->destinationSize().isEmpty())
1262 return point / d->scaleFactor();
1264 qreal xScale = width() / surface()->destinationSize().width();
1265 qreal yScale = height() / surface()->destinationSize().height();
1267 return QPointF(point.x() / xScale, point.y() / yScale);
1271
1272
1273
1274
1275
1276
1279
1280
1281
1282
1283
1284QPointF QWaylandQuickItem::mapFromSurface(
const QPointF &point)
const
1286 Q_D(
const QWaylandQuickItem);
1287 if (!surface() || surface()->destinationSize().isEmpty())
1288 return point * d->scaleFactor();
1290 qreal xScale = width() / surface()->destinationSize().width();
1291 qreal yScale = height() / surface()->destinationSize().height();
1293 return QPointF(point.x() * xScale, point.y() * yScale);
1297QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query)
const
1299 return inputMethodQuery(query, QVariant());
1302QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument)
const
1304 Q_D(
const QWaylandQuickItem);
1306 if (query == Qt::ImEnabled)
1307 return QVariant((flags() & ItemAcceptsInputMethod) != 0);
1310 return d->oldSurface->inputMethodControl()->inputMethodQuery(query, argument);
1317
1318
1319
1320
1321
1322
1323
1326
1327
1328
1329
1330
1331
1332
1333bool QWaylandQuickItem::isPaintEnabled()
const
1335 Q_D(
const QWaylandQuickItem);
1336 return d->paintEnabled;
1339void QWaylandQuickItem::setPaintEnabled(
bool enabled)
1341 Q_D(QWaylandQuickItem);
1343 if (enabled != d->paintEnabled) {
1344 d->paintEnabled = enabled;
1345 emit paintEnabledChanged();
1352
1353
1354
1355
1356
1359
1360
1361
1362
1363
1364bool QWaylandQuickItem::touchEventsEnabled()
const
1366 Q_D(
const QWaylandQuickItem);
1367 return d->touchEventsEnabled;
1370void QWaylandQuickItem::updateBuffer(
bool hasBuffer)
1372 Q_D(QWaylandQuickItem);
1373 Q_UNUSED(hasBuffer);
1374 if (d->origin != surface()->origin()) {
1375 d->origin = surface()->origin();
1376 emit originChanged();
1380void QWaylandQuickItem::updateWindow()
1382 Q_D(QWaylandQuickItem);
1384 QQuickWindow *newWindow = window();
1385 if (newWindow == d->connectedWindow)
1388 if (d->connectedWindow) {
1389 disconnect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync);
1390 disconnect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1393 d->connectedWindow = newWindow;
1395 if (d->connectedWindow) {
1396 connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing,
this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection);
1397 connect(d->connectedWindow, &QQuickWindow::screenChanged,
this, &QWaylandQuickItem::updateSize);
1400 QWaylandOutput *output = compositor()->outputFor(d->connectedWindow);
1402 d->view->setOutput(output);
1409void QWaylandQuickItem::updateOutput()
1411 Q_D(QWaylandQuickItem);
1412 if (d->view->output() == d->connectedOutput)
1415 if (d->connectedOutput)
1416 disconnect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1418 d->connectedOutput = d->view->output();
1420 if (d->connectedOutput)
1421 connect(d->connectedOutput, &QWaylandOutput::scaleFactorChanged,
this, &QWaylandQuickItem::updateSize);
1426void QWaylandQuickItem::beforeSync()
1428 Q_D(QWaylandQuickItem);
1429 if (d->view->advance()) {
1430 d->newTexture =
true;
1436void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
1438 Q_D(QWaylandQuickItem);
1440 setFlag(QQuickItem::ItemAcceptsInputMethod,
1441 d->oldSurface ? d->oldSurface->inputMethodControl()->enabled() :
false);
1442 QQuickItem::updateInputMethod(queries | Qt::ImEnabled);
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1472QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1474 Q_D(QWaylandQuickItem);
1475 d->lastMatrix = data->transformNode->combinedMatrix();
1476 const bool bufferHasContent = d->view->currentBuffer().hasContent();
1478 if (d->view->isBufferLocked() && d->paintEnabled)
1481 if (!bufferHasContent || !d->paintEnabled || !surface()) {
1486 QWaylandBufferRef ref = d->view->currentBuffer();
1487 const bool invertY = ref.origin() == QWaylandSurface::OriginBottomLeft;
1488 const QRectF rect = invertY ? QRectF(0, height(), width(), -height())
1489 : QRectF(0, 0, width(), height());
1491 if (ref.isSharedMemory()
1492#if QT_CONFIG(opengl)
1493 || bufferTypes[ref.bufferFormatEgl()].canProvideTexture
1496#if QT_CONFIG(opengl)
1497 if (oldNode && !d->paintByProvider) {
1502 d->paintByProvider =
true;
1505 QSGSimpleTextureNode *node =
static_cast<QSGSimpleTextureNode *>(oldNode);
1508 node =
new QSGSimpleTextureNode();
1510 node->setFiltering(QSGTexture::Linear);
1511 d->newTexture =
true;
1515 d->provider =
new QWaylandSurfaceTextureProvider();
1517 d->texProviderConnection =
1520 &QObject::destroyed,
1523 auto *itemPriv = QWaylandQuickItemPrivate::get(
this);
1524 if (itemPriv->provider) {
1525 itemPriv->provider->deleteLater();
1526 itemPriv->provider =
nullptr;
1528 disconnect(itemPriv->texProviderConnection); }
1533 if (d->newTexture) {
1534 d->newTexture =
false;
1535 d->provider->setBufferRef(
this, ref);
1536 node->setTexture(d->provider->texture());
1539 d->provider->setSmooth(smooth());
1540 node->setRect(rect);
1542 qreal scale = surface()->bufferScale();
1543 QRectF source = surface()->sourceGeometry();
1544 node->setSourceRect(QRectF(source.topLeft() * scale, source.size() * scale));
1549#if QT_CONFIG(opengl)
1550 Q_ASSERT(!d->provider);
1552 if (oldNode && d->paintByProvider) {
1557 d->paintByProvider =
false;
1559 QSGGeometryNode *node =
static_cast<QSGGeometryNode *>(oldNode);
1562 node =
new QSGGeometryNode;
1563 d->newTexture =
true;
1566 QSGGeometry *geometry = node->geometry();
1567 QWaylandBufferMaterial *material =
static_cast<QWaylandBufferMaterial *>(node->material());
1570 geometry =
new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
1573 material =
new QWaylandBufferMaterial(ref.bufferFormatEgl());
1575 if (d->newTexture) {
1576 d->newTexture =
false;
1577 material->setBufferRef(
this, ref);
1580 const QSize surfaceSize = ref.size() / surface()->bufferScale();
1581 const QRectF sourceGeometry = surface()->sourceGeometry();
1582 const QRectF normalizedCoordinates =
1583 sourceGeometry.isValid()
1584 ? QRectF(sourceGeometry.x() / surfaceSize.width(),
1585 sourceGeometry.y() / surfaceSize.height(),
1586 sourceGeometry.width() / surfaceSize.width(),
1587 sourceGeometry.height() / surfaceSize.height())
1588 : QRectF(0, 0, 1, 1);
1590 QSGGeometry::updateTexturedRectGeometry(geometry, rect, normalizedCoordinates);
1592 node->setGeometry(geometry);
1593 node->setFlag(QSGNode::OwnsGeometry,
true);
1595 node->setMaterial(material);
1596 node->setFlag(QSGNode::OwnsMaterial,
true);
1600 qCWarning(qLcWaylandCompositor) <<
"Without OpenGL support only shared memory textures are supported";
1605void QWaylandQuickItem::setTouchEventsEnabled(
bool enabled)
1607 Q_D(QWaylandQuickItem);
1608 if (d->touchEventsEnabled != enabled) {
1609 d->touchEventsEnabled = enabled;
1610 emit touchEventsEnabledChanged();
1614bool QWaylandQuickItem::inputEventsEnabled()
const
1616 Q_D(
const QWaylandQuickItem);
1617 return d->inputEventsEnabled;
1620void QWaylandQuickItem::setInputEventsEnabled(
bool enabled)
1622 Q_D(QWaylandQuickItem);
1623 if (d->inputEventsEnabled != enabled) {
1626 d->setInputEventsEnabled(enabled);
1627 emit inputEventsEnabledChanged();
1631void QWaylandQuickItem::lower()
1633 Q_D(QWaylandQuickItem);
1639 Q_Q(QWaylandQuickItem);
1640 QQuickItem *parent = q->parentItem();
1642 QQuickItem *bottom = parent->childItems().constFirst();
1644 q->stackBefore(bottom);
1647void QWaylandQuickItem::raise()
1649 Q_D(QWaylandQuickItem);
1655 Q_Q(QWaylandQuickItem);
1656 QQuickItem *parent = q->parentItem();
1658 QQuickItem *top = parent->childItems().constLast();
1663void QWaylandQuickItem::sendMouseMoveEvent(
const QPointF &position, QWaylandSeat *seat)
1665 if (seat ==
nullptr)
1666 seat = compositor()->defaultSeat();
1669 qWarning() <<
"No seat, can't send mouse event";
1673 seat->sendMouseMoveEvent(view(), position);
1677
1678
1679
1680
1681void QWaylandQuickItem::handleSubsurfacePosition(
const QPoint &pos)
1683 Q_D(QWaylandQuickItem);
1684 QQuickItem::setPosition(pos * d->scaleFactor());
1687#if QT_CONFIG(draganddrop)
1688void QWaylandQuickItem::handleDragStarted(QWaylandDrag *drag)
1690 Q_D(QWaylandQuickItem);
1691 Q_ASSERT(drag->origin() == surface());
1692 drag->seat()->setMouseFocus(
nullptr);
1693 d->isDragging =
true;
1699 qreal f = view->output() ? view->output()->scaleFactor() : 1;
1700#if !defined(Q_OS_MACOS)
1702 f /= window->devicePixelRatio();
1709 Q_Q(
const QWaylandQuickItem);
1710 auto *parent = q->parentItem();
1714 const auto siblings = q->parentItem()->childItems();
1715 for (
auto *sibling : siblings) {
1716 auto *waylandItem = qobject_cast<QWaylandQuickItem *>(sibling);
1717 if (waylandItem && waylandItem->surface() == surface)
1725 Q_Q(QWaylandQuickItem);
1726 q->stackAfter(sibling);
1727 q->setZ(sibling->z());
1728 belowParent = sibling->d_func()->belowParent;
1733 Q_Q(QWaylandQuickItem);
1734 q->stackBefore(sibling);
1735 q->setZ(sibling->z());
1736 belowParent = sibling->d_func()->belowParent;
1742 Q_Q(QWaylandQuickItem);
1743 const auto siblings = q->parentItem()->childItems();
1746 bool foundSibling =
false;
1747 for (
auto it = siblings.cbegin(); it != siblings.cend(); ++it) {
1748 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1749 if (sibling && !sibling->d_func()->belowParent) {
1750 q->stackBefore(sibling);
1751 foundSibling =
true;
1757 if (!foundSibling && siblings.last() != q)
1758 q->stackAfter(siblings.last());
1760 q->setZ(q->parentItem()->z());
1767 Q_Q(QWaylandQuickItem);
1768 const auto siblings = q->parentItem()->childItems();
1771 bool foundSibling =
false;
1772 for (
auto it = siblings.crbegin(); it != siblings.crend(); ++it) {
1773 QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it);
1774 if (sibling && sibling->d_func()->belowParent) {
1775 q->stackAfter(sibling);
1776 foundSibling =
true;
1782 if (!foundSibling && siblings.first() != q)
1783 q->stackBefore(siblings.first());
1785 q->setZ(q->parentItem()->z() - 1.0);
1791#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