Changeset View
Standalone View
src/server/surface_interface.cpp
Show All 22 Lines | |||||
23 | #include "clientconnection.h" | 23 | #include "clientconnection.h" | ||
24 | #include "compositor_interface.h" | 24 | #include "compositor_interface.h" | ||
25 | #include "idleinhibit_interface_p.h" | 25 | #include "idleinhibit_interface_p.h" | ||
26 | #include "pointerconstraints_interface_p.h" | 26 | #include "pointerconstraints_interface_p.h" | ||
27 | #include "region_interface.h" | 27 | #include "region_interface.h" | ||
28 | #include "subcompositor_interface.h" | 28 | #include "subcompositor_interface.h" | ||
29 | #include "subsurface_interface_p.h" | 29 | #include "subsurface_interface_p.h" | ||
30 | #include "surfacerole_p.h" | 30 | #include "surfacerole_p.h" | ||
31 | #include "viewporter_interface.h" | ||||
32 | | ||||
33 | #include <wayland-viewporter-server-protocol.h> | ||||
31 | // Qt | 34 | // Qt | ||
32 | #include <QListIterator> | 35 | #include <QListIterator> | ||
36 | | ||||
33 | // Wayland | 37 | // Wayland | ||
34 | #include <wayland-server.h> | 38 | #include <wayland-server.h> | ||
35 | // std | 39 | // std | ||
36 | #include <algorithm> | 40 | #include <algorithm> | ||
37 | 41 | | |||
38 | namespace KWayland | 42 | namespace KWayland | ||
39 | { | 43 | { | ||
40 | namespace Server | 44 | namespace Server | ||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Line(s) | |||||
172 | } | 176 | } | ||
173 | 177 | | |||
174 | void SurfaceInterface::Private::setContrast(const QPointer<ContrastInterface> &contrast) | 178 | void SurfaceInterface::Private::setContrast(const QPointer<ContrastInterface> &contrast) | ||
175 | { | 179 | { | ||
176 | pending.contrast = contrast; | 180 | pending.contrast = contrast; | ||
177 | pending.contrastIsSet = true; | 181 | pending.contrastIsSet = true; | ||
178 | } | 182 | } | ||
179 | 183 | | |||
184 | void SurfaceInterface::Private::setSourceRectangle(const QRectF &source) | ||||
185 | { | ||||
186 | pending.sourceRectangle = source; | ||||
187 | pending.sourceRectangleIsSet = true; | ||||
188 | } | ||||
189 | | ||||
190 | void SurfaceInterface::Private::setDestinationSize(const QSize &dest) | ||||
191 | { | ||||
192 | pending.destinationSize = dest; | ||||
193 | pending.destinationSizeIsSet = true; | ||||
194 | } | ||||
195 | | ||||
196 | void SurfaceInterface::Private::installViewport(ViewportInterface *vp) | ||||
197 | { | ||||
198 | Q_ASSERT(viewport.isNull()); | ||||
199 | viewport = QPointer<ViewportInterface>(vp); | ||||
200 | connect(viewport, &ViewportInterface::destinationSizeSet, q_func(), | ||||
201 | [this](const QSize &size) { | ||||
202 | setDestinationSize(size); | ||||
203 | } | ||||
204 | ); | ||||
205 | connect(viewport, &ViewportInterface::sourceRectangleSet, q_func(), | ||||
206 | [this](const QRectF &rect) { | ||||
207 | setSourceRectangle(rect); | ||||
208 | } | ||||
209 | ); | ||||
210 | connect(viewport, &ViewportInterface::unbound, q_func(), | ||||
211 | [this] { | ||||
212 | setDestinationSize(QSize()); | ||||
213 | setSourceRectangle(QRectF()); | ||||
214 | } | ||||
215 | ); | ||||
216 | } | ||||
217 | | ||||
180 | void SurfaceInterface::Private::installPointerConstraint(LockedPointerInterface *lock) | 218 | void SurfaceInterface::Private::installPointerConstraint(LockedPointerInterface *lock) | ||
181 | { | 219 | { | ||
182 | Q_ASSERT(lockedPointer.isNull()); | 220 | Q_ASSERT(lockedPointer.isNull()); | ||
183 | Q_ASSERT(confinedPointer.isNull()); | 221 | Q_ASSERT(confinedPointer.isNull()); | ||
184 | lockedPointer = QPointer<LockedPointerInterface>(lock); | 222 | lockedPointer = QPointer<LockedPointerInterface>(lock); | ||
185 | 223 | | |||
186 | auto cleanUp = [this]() { | 224 | auto cleanUp = [this]() { | ||
187 | lockedPointer.clear(); | 225 | lockedPointer.clear(); | ||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Line(s) | 351 | { | |||
324 | for (auto it = callbacksToDestroy.constBegin(), end = callbacksToDestroy.constEnd(); it != end; it++) { | 362 | for (auto it = callbacksToDestroy.constBegin(), end = callbacksToDestroy.constEnd(); it != end; it++) { | ||
325 | wl_resource_destroy(*it); | 363 | wl_resource_destroy(*it); | ||
326 | } | 364 | } | ||
327 | if (current.buffer) { | 365 | if (current.buffer) { | ||
328 | current.buffer->unref(); | 366 | current.buffer->unref(); | ||
329 | } | 367 | } | ||
330 | } | 368 | } | ||
331 | 369 | | |||
370 | void SurfaceInterface::Private::soureRectangleIntegerCheck(const QSize &destinationSize, | ||||
371 | const QRectF &sourceRectangle) const | ||||
372 | { | ||||
373 | if (destinationSize.isValid()) { | ||||
374 | // Source rectangle must be integer valued only when the destination size is not set. | ||||
375 | return; | ||||
376 | } | ||||
377 | if (!sourceRectangle.isValid()) { | ||||
378 | // When the source rectangle is unset there is no integer condition. | ||||
379 | return; | ||||
380 | } | ||||
381 | Q_ASSERT(viewport); | ||||
382 | | ||||
383 | const double width = sourceRectangle.width(); | ||||
384 | const double height = sourceRectangle.height(); | ||||
385 | if (!qFuzzyCompare(width, (int)width) || !qFuzzyCompare(height, (int)height)) { | ||||
386 | wl_resource_post_error(viewport->parentResource(), WP_VIEWPORT_ERROR_BAD_SIZE, | ||||
387 | "Source rectangle not integer valued"); | ||||
388 | } | ||||
389 | } | ||||
390 | | ||||
391 | void SurfaceInterface::Private::soureRectangleContainCheck(const BufferInterface *buffer, | ||||
392 | OutputInterface::Transform transform, | ||||
393 | qint32 scale, | ||||
394 | const QRectF &sourceRectangle) const | ||||
395 | { | ||||
396 | if (!buffer || !viewport || !sourceRectangle.isValid()) { | ||||
397 | return; | ||||
398 | } | ||||
399 | QSizeF bufferSize = buffer->size() / scale; | ||||
400 | | ||||
401 | if (transform == OutputInterface::Transform::Rotated90 || | ||||
402 | transform == OutputInterface::Transform::Rotated270 || | ||||
403 | transform == OutputInterface::Transform::Flipped90 || | ||||
404 | transform == OutputInterface::Transform::Flipped270) { | ||||
405 | bufferSize.transpose(); | ||||
406 | } | ||||
407 | if (!QRectF(QPointF(), bufferSize).contains(sourceRectangle)) { | ||||
408 | wl_resource_post_error(viewport->parentResource(), | ||||
409 | WP_VIEWPORT_ERROR_OUT_OF_BUFFER, | ||||
410 | "Source rectangle not contained in buffer"); | ||||
411 | } | ||||
412 | } | ||||
413 | | ||||
332 | void SurfaceInterface::Private::swapStates(State *source, State *target, bool emitChanged) | 414 | void SurfaceInterface::Private::swapStates(State *source, State *target, bool emitChanged) | ||
333 | { | 415 | { | ||
334 | Q_Q(SurfaceInterface); | 416 | Q_Q(SurfaceInterface); | ||
335 | bool bufferChanged = source->bufferIsSet; | 417 | bool bufferChanged = source->bufferIsSet; | ||
336 | const bool opaqueRegionChanged = source->opaqueIsSet; | 418 | const bool opaqueRegionChanged = source->opaqueIsSet; | ||
337 | const bool inputRegionChanged = source->inputIsSet; | 419 | const bool inputRegionChanged = source->inputIsSet; | ||
338 | const bool scaleFactorChanged = source->scaleIsSet && (target->scale != source->scale); | 420 | const bool scaleFactorChanged = source->scaleIsSet && (target->scale != source->scale); | ||
339 | const bool transformChanged = source->transformIsSet && (target->transform != source->transform); | 421 | const bool transformChanged = source->transformIsSet && (target->transform != source->transform); | ||
340 | const bool shadowChanged = source->shadowIsSet; | 422 | const bool shadowChanged = source->shadowIsSet; | ||
341 | const bool blurChanged = source->blurIsSet; | 423 | const bool blurChanged = source->blurIsSet; | ||
342 | const bool contrastChanged = source->contrastIsSet; | 424 | const bool contrastChanged = source->contrastIsSet; | ||
343 | const bool slideChanged = source->slideIsSet; | 425 | const bool slideChanged = source->slideIsSet; | ||
426 | const bool sourceRectangleChanged = source->sourceRectangleIsSet; | ||||
427 | const bool destinationSizeChanged = source->destinationSizeIsSet; | ||||
428 | | ||||
344 | const bool childrenChanged = source->childrenChanged; | 429 | const bool childrenChanged = source->childrenChanged; | ||
345 | bool sizeChanged = false; | 430 | bool sizeChanged = false; | ||
346 | auto buffer = target->buffer; | 431 | auto buffer = target->buffer; | ||
347 | if (bufferChanged) { | 432 | if (bufferChanged) { | ||
348 | // TODO: is the reffing correct for subsurfaces? | 433 | // TODO: is the reffing correct for subsurfaces? | ||
349 | QSize oldSize; | 434 | QSize oldSize; | ||
350 | if (target->buffer) { | 435 | if (target->buffer) { | ||
351 | oldSize = target->buffer->size(); | 436 | oldSize = target->buffer->size(); | ||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Line(s) | |||||
412 | if (scaleFactorChanged) { | 497 | if (scaleFactorChanged) { | ||
413 | target->scale = source->scale; | 498 | target->scale = source->scale; | ||
414 | target->scaleIsSet = true; | 499 | target->scaleIsSet = true; | ||
415 | } | 500 | } | ||
416 | if (transformChanged) { | 501 | if (transformChanged) { | ||
417 | target->transform = source->transform; | 502 | target->transform = source->transform; | ||
418 | target->transformIsSet = true; | 503 | target->transformIsSet = true; | ||
419 | } | 504 | } | ||
505 | if (destinationSizeChanged) { | ||||
506 | target->destinationSize = source->destinationSize; | ||||
507 | target->destinationSizeIsSet = true; | ||||
508 | sizeChanged |= static_cast<bool>(buffer); | ||||
509 | } | ||||
davidedmundson: C-style casts are frowned upon. | |||||
510 | if (sourceRectangleChanged) { | ||||
511 | if (buffer && !target->destinationSize.isValid() && source->sourceRectangle.isValid()) { | ||||
512 | // TODO: We should make this dependent on the previous size being different. | ||||
513 | // But looking at above sizeChanged calculation when setting the buffer | ||||
514 | // we need to do fix this there as well (does not look at buffer transform | ||||
515 | // and destination size). | ||||
516 | sizeChanged = true; | ||||
517 | } | ||||
518 | target->sourceRectangle = source->sourceRectangle; | ||||
519 | target->sourceRectangleIsSet = true; | ||||
520 | } | ||||
521 | | ||||
522 | // Now check that source rectangle is (still) well defined. | ||||
523 | soureRectangleIntegerCheck(target->destinationSize, target->sourceRectangle); | ||||
524 | soureRectangleContainCheck(buffer, target->transform, target->scale, target->sourceRectangle); | ||||
525 | | ||||
420 | if (!lockedPointer.isNull()) { | 526 | if (!lockedPointer.isNull()) { | ||
421 | lockedPointer->d_func()->commit(); | 527 | lockedPointer->d_func()->commit(); | ||
422 | } | 528 | } | ||
423 | if (!confinedPointer.isNull()) { | 529 | if (!confinedPointer.isNull()) { | ||
424 | confinedPointer->d_func()->commit(); | 530 | confinedPointer->d_func()->commit(); | ||
We're not testing this error in the case of: buffer is set then later this should be an error too. davidedmundson: We're not testing this error in the case of:
buffer is set
viewporter.sourceRect is set
then… | |||||
Good point. Same should be done for when the transform or scale changes. romangg: Good point. Same should be done for when the transform or scale changes. | |||||
425 | } | 531 | } | ||
426 | 532 | | |||
427 | *source = State{}; | 533 | *source = State{}; | ||
428 | source->children = target->children; | 534 | source->children = target->children; | ||
429 | if (opaqueRegionChanged) { | 535 | if (opaqueRegionChanged) { | ||
430 | emit q->opaqueChanged(target->opaque); | 536 | emit q->opaqueChanged(target->opaque); | ||
431 | } | 537 | } | ||
432 | if (inputRegionChanged) { | 538 | if (inputRegionChanged) { | ||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Line(s) | 605 | if (blurChanged) { | |||
500 | emit q->blurChanged(); | 606 | emit q->blurChanged(); | ||
501 | } | 607 | } | ||
502 | if (contrastChanged) { | 608 | if (contrastChanged) { | ||
503 | emit q->contrastChanged(); | 609 | emit q->contrastChanged(); | ||
504 | } | 610 | } | ||
505 | if (slideChanged) { | 611 | if (slideChanged) { | ||
506 | emit q->slideOnShowHideChanged(); | 612 | emit q->slideOnShowHideChanged(); | ||
507 | } | 613 | } | ||
614 | if (sourceRectangleChanged) { | ||||
615 | emit q->sourceRectangleChanged(); | ||||
616 | } | ||||
508 | if (childrenChanged) { | 617 | if (childrenChanged) { | ||
509 | emit q->subSurfaceTreeChanged(); | 618 | emit q->subSurfaceTreeChanged(); | ||
510 | } | 619 | } | ||
511 | } | 620 | } | ||
512 | 621 | | |||
513 | void SurfaceInterface::Private::commit() | 622 | void SurfaceInterface::Private::commit() | ||
514 | { | 623 | { | ||
515 | Q_Q(SurfaceInterface); | 624 | Q_Q(SurfaceInterface); | ||
▲ Show 20 Lines • Show All 226 Lines • ▼ Show 20 Line(s) | |||||
742 | } | 851 | } | ||
743 | 852 | | |||
744 | BufferInterface *SurfaceInterface::buffer() | 853 | BufferInterface *SurfaceInterface::buffer() | ||
745 | { | 854 | { | ||
746 | Q_D(); | 855 | Q_D(); | ||
747 | return d->current.buffer; | 856 | return d->current.buffer; | ||
748 | } | 857 | } | ||
749 | 858 | | |||
859 | BufferInterface *SurfaceInterface::buffer() const | ||||
860 | { | ||||
861 | Q_D(); | ||||
862 | return d->current.buffer; | ||||
863 | } | ||||
864 | | ||||
750 | QPoint SurfaceInterface::offset() const | 865 | QPoint SurfaceInterface::offset() const | ||
751 | { | 866 | { | ||
752 | Q_D(); | 867 | Q_D(); | ||
753 | return d->current.offset; | 868 | return d->current.offset; | ||
754 | } | 869 | } | ||
755 | 870 | | |||
871 | QRectF SurfaceInterface::sourceRectangle() const | ||||
872 | { | ||||
873 | Q_D(); | ||||
874 | return d->current.sourceRectangle; | ||||
875 | } | ||||
876 | | ||||
756 | SurfaceInterface *SurfaceInterface::get(wl_resource *native) | 877 | SurfaceInterface *SurfaceInterface::get(wl_resource *native) | ||
757 | { | 878 | { | ||
758 | return Private::get<SurfaceInterface>(native); | 879 | return Private::get<SurfaceInterface>(native); | ||
759 | } | 880 | } | ||
760 | 881 | | |||
761 | SurfaceInterface *SurfaceInterface::get(quint32 id, const ClientConnection *client) | 882 | SurfaceInterface *SurfaceInterface::get(quint32 id, const ClientConnection *client) | ||
762 | { | 883 | { | ||
763 | return Private::get<SurfaceInterface>(id, client); | 884 | return Private::get<SurfaceInterface>(id, client); | ||
Show All 9 Lines | |||||
773 | { | 894 | { | ||
774 | Q_D(); | 895 | Q_D(); | ||
775 | return d->subSurface; | 896 | return d->subSurface; | ||
776 | } | 897 | } | ||
777 | 898 | | |||
778 | QSize SurfaceInterface::size() const | 899 | QSize SurfaceInterface::size() const | ||
779 | { | 900 | { | ||
780 | Q_D(); | 901 | Q_D(); | ||
902 | if (!d->current.buffer) { | ||||
903 | return QSize(); | ||||
904 | } | ||||
905 | if (d->current.destinationSize.isValid()) { | ||||
906 | return d->current.destinationSize; | ||||
Should this be d->current.sourceRectangle.size()/ scale() It would be a somewhat weird case to use both viewporter and wl_buffer.scale, but it's what the spec implies and you seem to be assuming that in the kwin render path. destinationSize would be as-is. davidedmundson: Should this be
d->current.sourceRectangle.size()/ scale()
It would be a somewhat weird case… | |||||
How I read the spec: the source rectangle is always specified in coordinates after scale and transform. [1] SurfaceInterface::size() returns the scaled and transformed (not yet) buffer size so since viewporter coordinates are to this base we can just directly return them. romangg: How I read the spec: the source rectangle is always specified in coordinates after scale and… | |||||
Yeah, on re-reading I think your intepretation is right. Leave your stuff as-is. davidedmundson: Yeah, on re-reading I think your intepretation is right. Leave your stuff as-is. | |||||
907 | } | ||||
908 | if (d->current.sourceRectangle.isValid()) { | ||||
909 | return d->current.sourceRectangle.size().toSize(); | ||||
910 | } | ||||
781 | // TODO: apply transform to the buffer size | 911 | // TODO: apply transform to the buffer size | ||
782 | if (d->current.buffer) { | | |||
783 | return d->current.buffer->size() / scale(); | 912 | return d->current.buffer->size() / scale(); | ||
784 | } | 913 | } | ||
785 | return QSize(); | | |||
786 | } | | |||
787 | 914 | | |||
788 | QPointer< ShadowInterface > SurfaceInterface::shadow() const | 915 | QPointer< ShadowInterface > SurfaceInterface::shadow() const | ||
789 | { | 916 | { | ||
790 | Q_D(); | 917 | Q_D(); | ||
791 | return d->current.shadow; | 918 | return d->current.shadow; | ||
792 | } | 919 | } | ||
793 | 920 | | |||
794 | QPointer< BlurInterface > SurfaceInterface::blur() const | 921 | QPointer< BlurInterface > SurfaceInterface::blur() const | ||
▲ Show 20 Lines • Show All 176 Lines • Show Last 20 Lines |
C-style casts are frowned upon.