wayland: Introduce surface state locking capabilities
In certain cases it can be useful to delay applying a surface commit. As an example, the compositor may wait until the committed graphics buffer is ready for reading to avoid stalling its graphics pipeline. This change introduces basic surface state locking capabilities and ports some surface extensions to new helpers to manage associated state.
This commit is contained in:
parent
60251bc1e4
commit
dcadf24e64
19 changed files with 548 additions and 418 deletions
|
@ -62,16 +62,16 @@ void ContentTypeV1Interface::wp_content_type_v1_set_content_type(Resource *, uin
|
|||
return;
|
||||
}
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(m_surface);
|
||||
surfacePrivate->pending.contentType = waylandToKwinContentType(content_type);
|
||||
surfacePrivate->pending.contentTypeIsSet = true;
|
||||
surfacePrivate->pending->contentType = waylandToKwinContentType(content_type);
|
||||
surfacePrivate->pending->contentTypeIsSet = true;
|
||||
}
|
||||
|
||||
void ContentTypeV1Interface::wp_content_type_v1_destroy(Resource *resource)
|
||||
{
|
||||
if (m_surface) {
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(m_surface);
|
||||
surfacePrivate->pending.contentType = KWin::ContentType::None;
|
||||
surfacePrivate->pending.contentTypeIsSet = true;
|
||||
surfacePrivate->pending->contentType = KWin::ContentType::None;
|
||||
surfacePrivate->pending->contentTypeIsSet = true;
|
||||
}
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
|
|
@ -22,36 +22,33 @@ namespace KWaylandServer
|
|||
class DragAndDropIconPrivate : public SurfaceRole
|
||||
{
|
||||
public:
|
||||
explicit DragAndDropIconPrivate(DragAndDropIcon *q, SurfaceInterface *surface);
|
||||
explicit DragAndDropIconPrivate(SurfaceInterface *surface);
|
||||
|
||||
void commit() override;
|
||||
|
||||
DragAndDropIcon *q;
|
||||
QPoint position;
|
||||
};
|
||||
|
||||
DragAndDropIconPrivate::DragAndDropIconPrivate(DragAndDropIcon *q, SurfaceInterface *surface)
|
||||
DragAndDropIconPrivate::DragAndDropIconPrivate(SurfaceInterface *surface)
|
||||
: SurfaceRole(surface, QByteArrayLiteral("dnd_icon"))
|
||||
, q(q)
|
||||
{
|
||||
}
|
||||
|
||||
void DragAndDropIconPrivate::commit()
|
||||
{
|
||||
position += surface()->offset();
|
||||
Q_EMIT q->changed();
|
||||
}
|
||||
|
||||
DragAndDropIcon::DragAndDropIcon(SurfaceInterface *surface)
|
||||
: QObject(surface)
|
||||
, d(new DragAndDropIconPrivate(this, surface))
|
||||
, d(new DragAndDropIconPrivate(surface))
|
||||
{
|
||||
connect(surface, &SurfaceInterface::committed, this, &DragAndDropIcon::commit);
|
||||
}
|
||||
|
||||
DragAndDropIcon::~DragAndDropIcon()
|
||||
{
|
||||
}
|
||||
|
||||
void DragAndDropIcon::commit()
|
||||
{
|
||||
d->position += d->surface()->offset();
|
||||
Q_EMIT changed();
|
||||
}
|
||||
|
||||
QPoint DragAndDropIcon::position() const
|
||||
{
|
||||
return d->position;
|
||||
|
|
|
@ -55,6 +55,8 @@ Q_SIGNALS:
|
|||
void changed();
|
||||
|
||||
private:
|
||||
void commit();
|
||||
|
||||
explicit DragAndDropIcon(SurfaceInterface *surface);
|
||||
friend class DataDeviceInterfacePrivate;
|
||||
std::unique_ptr<DragAndDropIconPrivate> d;
|
||||
|
|
|
@ -327,10 +327,6 @@ public:
|
|||
Q_EMIT q->topLevel(OutputInterface::get(output), InputPanelSurfaceV1Interface::Position(position));
|
||||
}
|
||||
|
||||
void commit() override
|
||||
{
|
||||
}
|
||||
|
||||
void zwp_input_panel_surface_v1_destroy_resource(Resource *) override
|
||||
{
|
||||
delete q;
|
||||
|
|
|
@ -39,38 +39,45 @@ protected:
|
|||
void zwlr_layer_shell_v1_destroy(Resource *resource) override;
|
||||
};
|
||||
|
||||
class LayerSurfaceV1State
|
||||
struct LayerSurfaceV1Commit
|
||||
{
|
||||
public:
|
||||
std::optional<LayerSurfaceV1Interface::Layer> layer;
|
||||
std::optional<Qt::Edges> anchor;
|
||||
std::optional<QMargins> margins;
|
||||
std::optional<QSize> desiredSize;
|
||||
std::optional<int> exclusiveZone;
|
||||
std::optional<quint32> acknowledgedConfigure;
|
||||
std::optional<bool> acceptsFocus;
|
||||
};
|
||||
|
||||
struct LayerSurfaceV1State
|
||||
{
|
||||
QQueue<quint32> serials;
|
||||
LayerSurfaceV1Interface::Layer layer = LayerSurfaceV1Interface::BottomLayer;
|
||||
Qt::Edges anchor;
|
||||
QMargins margins;
|
||||
QSize desiredSize = QSize(0, 0);
|
||||
int exclusiveZone = 0;
|
||||
quint32 acknowledgedConfigure;
|
||||
bool acknowledgedConfigureIsSet = false;
|
||||
bool acceptsFocus = false;
|
||||
bool configured = false;
|
||||
bool closed = false;
|
||||
bool committed = false;
|
||||
bool firstBufferAttached = false;
|
||||
};
|
||||
|
||||
class LayerSurfaceV1InterfacePrivate : public SurfaceRole, public QtWaylandServer::zwlr_layer_surface_v1
|
||||
class LayerSurfaceV1InterfacePrivate : public SurfaceRole, public SurfaceExtension<LayerSurfaceV1Commit>, public QtWaylandServer::zwlr_layer_surface_v1
|
||||
{
|
||||
public:
|
||||
LayerSurfaceV1InterfacePrivate(LayerSurfaceV1Interface *q, SurfaceInterface *surface);
|
||||
|
||||
void commit() override;
|
||||
void apply(LayerSurfaceV1Commit *commit) override;
|
||||
|
||||
LayerSurfaceV1Interface *q;
|
||||
LayerShellV1Interface *shell;
|
||||
QPointer<SurfaceInterface> surface;
|
||||
QPointer<OutputInterface> output;
|
||||
LayerSurfaceV1State current;
|
||||
LayerSurfaceV1State pending;
|
||||
QQueue<quint32> serials;
|
||||
QString scope;
|
||||
bool isClosed = false;
|
||||
bool isConfigured = false;
|
||||
bool isCommitted = false;
|
||||
bool firstBufferAttached = false;
|
||||
LayerSurfaceV1State state;
|
||||
|
||||
protected:
|
||||
void zwlr_layer_surface_v1_destroy_resource(Resource *resource) override;
|
||||
|
@ -150,6 +157,7 @@ Display *LayerShellV1Interface::display() const
|
|||
|
||||
LayerSurfaceV1InterfacePrivate::LayerSurfaceV1InterfacePrivate(LayerSurfaceV1Interface *q, SurfaceInterface *surface)
|
||||
: SurfaceRole(surface, QByteArrayLiteral("layer_surface_v1"))
|
||||
, SurfaceExtension(surface)
|
||||
, q(q)
|
||||
, surface(surface)
|
||||
{
|
||||
|
@ -177,19 +185,19 @@ void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_anchor(Resource *
|
|||
pending.anchor = Qt::Edges();
|
||||
|
||||
if (anchor & anchor_top) {
|
||||
pending.anchor |= Qt::TopEdge;
|
||||
*pending.anchor |= Qt::TopEdge;
|
||||
}
|
||||
|
||||
if (anchor & anchor_right) {
|
||||
pending.anchor |= Qt::RightEdge;
|
||||
*pending.anchor |= Qt::RightEdge;
|
||||
}
|
||||
|
||||
if (anchor & anchor_bottom) {
|
||||
pending.anchor |= Qt::BottomEdge;
|
||||
*pending.anchor |= Qt::BottomEdge;
|
||||
}
|
||||
|
||||
if (anchor & anchor_left) {
|
||||
pending.anchor |= Qt::LeftEdge;
|
||||
*pending.anchor |= Qt::LeftEdge;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,19 +231,18 @@ void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_get_popup(Resource *r
|
|||
|
||||
void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_ack_configure(Resource *resource, uint32_t serial)
|
||||
{
|
||||
if (!serials.contains(serial)) {
|
||||
if (!state.serials.contains(serial)) {
|
||||
wl_resource_post_error(resource->handle, error_invalid_surface_state, "invalid configure serial %d", serial);
|
||||
return;
|
||||
}
|
||||
while (!serials.isEmpty()) {
|
||||
const quint32 head = serials.takeFirst();
|
||||
while (!state.serials.isEmpty()) {
|
||||
const quint32 head = state.serials.takeFirst();
|
||||
if (head == serial) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isClosed) {
|
||||
if (!state.closed) {
|
||||
pending.acknowledgedConfigure = serial;
|
||||
pending.acknowledgedConfigureIsSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,19 +260,17 @@ void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_layer(Resource *r
|
|||
pending.layer = LayerSurfaceV1Interface::Layer(layer);
|
||||
}
|
||||
|
||||
void LayerSurfaceV1InterfacePrivate::commit()
|
||||
void LayerSurfaceV1InterfacePrivate::apply(LayerSurfaceV1Commit *commit)
|
||||
{
|
||||
if (isClosed) {
|
||||
if (state.closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending.acknowledgedConfigureIsSet) {
|
||||
current.acknowledgedConfigure = pending.acknowledgedConfigure;
|
||||
pending.acknowledgedConfigureIsSet = false;
|
||||
Q_EMIT q->configureAcknowledged(pending.acknowledgedConfigure);
|
||||
if (commit->acknowledgedConfigure.has_value()) {
|
||||
Q_EMIT q->configureAcknowledged(commit->acknowledgedConfigure.value());
|
||||
}
|
||||
|
||||
if (Q_UNLIKELY(surface->isMapped() && !isConfigured)) {
|
||||
if (Q_UNLIKELY(surface->isMapped() && !state.configured)) {
|
||||
wl_resource_post_error(resource()->handle,
|
||||
error_invalid_surface_state,
|
||||
"a buffer has been attached to a layer surface prior "
|
||||
|
@ -273,57 +278,79 @@ void LayerSurfaceV1InterfacePrivate::commit()
|
|||
return;
|
||||
}
|
||||
|
||||
if (Q_UNLIKELY(pending.desiredSize.width() == 0 && (!(pending.anchor & Qt::LeftEdge) || !(pending.anchor & Qt::RightEdge)))) {
|
||||
wl_resource_post_error(resource()->handle,
|
||||
error_invalid_size,
|
||||
"the layer surface has a width of 0 but its anchor "
|
||||
"doesn't include the left and the right screen edge");
|
||||
return;
|
||||
if (commit->desiredSize && commit->desiredSize->width() == 0) {
|
||||
const Qt::Edges anchor = commit->anchor.value_or(state.anchor);
|
||||
if (!(anchor & Qt::LeftEdge) || !(anchor & Qt::RightEdge)) {
|
||||
wl_resource_post_error(resource()->handle,
|
||||
error_invalid_size,
|
||||
"the layer surface has a width of 0 but its anchor "
|
||||
"doesn't include the left and the right screen edge");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Q_UNLIKELY(pending.desiredSize.height() == 0 && (!(pending.anchor & Qt::TopEdge) || !(pending.anchor & Qt::BottomEdge)))) {
|
||||
wl_resource_post_error(resource()->handle,
|
||||
error_invalid_size,
|
||||
"the layer surface has a height of 0 but its anchor "
|
||||
"doesn't include the top and the bottom screen edge");
|
||||
return;
|
||||
if (commit->desiredSize && commit->desiredSize->height() == 0) {
|
||||
const Qt::Edges anchor = commit->anchor.value_or(state.anchor);
|
||||
if (!(anchor & Qt::TopEdge) || !(anchor & Qt::BottomEdge)) {
|
||||
wl_resource_post_error(resource()->handle,
|
||||
error_invalid_size,
|
||||
"the layer surface has a height of 0 but its anchor "
|
||||
"doesn't include the top and the bottom screen edge");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// detect reset
|
||||
if (!surface->isMapped() && firstBufferAttached) {
|
||||
isCommitted = false;
|
||||
firstBufferAttached = false;
|
||||
isConfigured = false;
|
||||
|
||||
current = LayerSurfaceV1State();
|
||||
pending = LayerSurfaceV1State();
|
||||
if (!surface->isMapped() && state.firstBufferAttached) {
|
||||
state = LayerSurfaceV1State();
|
||||
pending = LayerSurfaceV1Commit();
|
||||
stashed.clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const LayerSurfaceV1State previous = std::exchange(current, pending);
|
||||
const LayerSurfaceV1State previous = state;
|
||||
|
||||
isCommitted = true; // Must set the committed state before emitting any signals.
|
||||
state.committed = true; // Must set the committed state before emitting any signals.
|
||||
if (surface->isMapped()) {
|
||||
firstBufferAttached = true;
|
||||
state.firstBufferAttached = true;
|
||||
}
|
||||
|
||||
if (previous.acceptsFocus != current.acceptsFocus) {
|
||||
if (commit->layer.has_value()) {
|
||||
state.layer = commit->layer.value();
|
||||
}
|
||||
if (commit->anchor.has_value()) {
|
||||
state.anchor = commit->anchor.value();
|
||||
}
|
||||
if (commit->margins.has_value()) {
|
||||
state.margins = commit->margins.value();
|
||||
}
|
||||
if (commit->desiredSize.has_value()) {
|
||||
state.desiredSize = commit->desiredSize.value();
|
||||
}
|
||||
if (commit->exclusiveZone.has_value()) {
|
||||
state.exclusiveZone = commit->exclusiveZone.value();
|
||||
}
|
||||
if (commit->acceptsFocus.has_value()) {
|
||||
state.acceptsFocus = commit->acceptsFocus.value();
|
||||
}
|
||||
|
||||
if (previous.acceptsFocus != state.acceptsFocus) {
|
||||
Q_EMIT q->acceptsFocusChanged();
|
||||
}
|
||||
if (previous.layer != current.layer) {
|
||||
if (previous.layer != state.layer) {
|
||||
Q_EMIT q->layerChanged();
|
||||
}
|
||||
if (previous.anchor != current.anchor) {
|
||||
if (previous.anchor != state.anchor) {
|
||||
Q_EMIT q->anchorChanged();
|
||||
}
|
||||
if (previous.desiredSize != current.desiredSize) {
|
||||
if (previous.desiredSize != state.desiredSize) {
|
||||
Q_EMIT q->desiredSizeChanged();
|
||||
}
|
||||
if (previous.exclusiveZone != current.exclusiveZone) {
|
||||
if (previous.exclusiveZone != state.exclusiveZone) {
|
||||
Q_EMIT q->exclusiveZoneChanged();
|
||||
}
|
||||
if (previous.margins != current.margins) {
|
||||
if (previous.margins != state.margins) {
|
||||
Q_EMIT q->marginsChanged();
|
||||
}
|
||||
}
|
||||
|
@ -336,8 +363,7 @@ LayerSurfaceV1Interface::LayerSurfaceV1Interface(LayerShellV1Interface *shell,
|
|||
wl_resource *resource)
|
||||
: d(new LayerSurfaceV1InterfacePrivate(this, surface))
|
||||
{
|
||||
d->current.layer = layer;
|
||||
d->pending.layer = layer;
|
||||
d->state.layer = layer;
|
||||
|
||||
d->shell = shell;
|
||||
d->output = output;
|
||||
|
@ -352,7 +378,7 @@ LayerSurfaceV1Interface::~LayerSurfaceV1Interface()
|
|||
|
||||
bool LayerSurfaceV1Interface::isCommitted() const
|
||||
{
|
||||
return d->isCommitted;
|
||||
return d->state.committed;
|
||||
}
|
||||
|
||||
SurfaceInterface *LayerSurfaceV1Interface::surface() const
|
||||
|
@ -362,52 +388,52 @@ SurfaceInterface *LayerSurfaceV1Interface::surface() const
|
|||
|
||||
Qt::Edges LayerSurfaceV1Interface::anchor() const
|
||||
{
|
||||
return d->current.anchor;
|
||||
return d->state.anchor;
|
||||
}
|
||||
|
||||
QSize LayerSurfaceV1Interface::desiredSize() const
|
||||
{
|
||||
return d->current.desiredSize;
|
||||
return d->state.desiredSize;
|
||||
}
|
||||
|
||||
bool LayerSurfaceV1Interface::acceptsFocus() const
|
||||
{
|
||||
return d->current.acceptsFocus;
|
||||
return d->state.acceptsFocus;
|
||||
}
|
||||
|
||||
LayerSurfaceV1Interface::Layer LayerSurfaceV1Interface::layer() const
|
||||
{
|
||||
return d->current.layer;
|
||||
return d->state.layer;
|
||||
}
|
||||
|
||||
QMargins LayerSurfaceV1Interface::margins() const
|
||||
{
|
||||
return d->current.margins;
|
||||
return d->state.margins;
|
||||
}
|
||||
|
||||
int LayerSurfaceV1Interface::leftMargin() const
|
||||
{
|
||||
return d->current.margins.left();
|
||||
return d->state.margins.left();
|
||||
}
|
||||
|
||||
int LayerSurfaceV1Interface::topMargin() const
|
||||
{
|
||||
return d->current.margins.top();
|
||||
return d->state.margins.top();
|
||||
}
|
||||
|
||||
int LayerSurfaceV1Interface::rightMargin() const
|
||||
{
|
||||
return d->current.margins.right();
|
||||
return d->state.margins.right();
|
||||
}
|
||||
|
||||
int LayerSurfaceV1Interface::bottomMargin() const
|
||||
{
|
||||
return d->current.margins.bottom();
|
||||
return d->state.margins.bottom();
|
||||
}
|
||||
|
||||
int LayerSurfaceV1Interface::exclusiveZone() const
|
||||
{
|
||||
return d->current.exclusiveZone;
|
||||
return d->state.exclusiveZone;
|
||||
}
|
||||
|
||||
Qt::Edge LayerSurfaceV1Interface::exclusiveEdge() const
|
||||
|
@ -442,25 +468,25 @@ QString LayerSurfaceV1Interface::scope() const
|
|||
|
||||
quint32 LayerSurfaceV1Interface::sendConfigure(const QSize &size)
|
||||
{
|
||||
if (d->isClosed) {
|
||||
if (d->state.closed) {
|
||||
qCWarning(KWIN_CORE) << "Cannot configure a closed layer shell surface";
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t serial = d->shell->display()->nextSerial();
|
||||
d->serials << serial;
|
||||
d->state.serials << serial;
|
||||
|
||||
d->send_configure(serial, size.width(), size.height());
|
||||
d->isConfigured = true;
|
||||
d->state.configured = true;
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
void LayerSurfaceV1Interface::sendClosed()
|
||||
{
|
||||
if (!d->isClosed) {
|
||||
if (!d->state.closed) {
|
||||
d->send_closed();
|
||||
d->isClosed = true;
|
||||
d->state.closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,27 +138,28 @@ LockedPointerV1InterfacePrivate::LockedPointerV1InterfacePrivate(LockedPointerV1
|
|||
const QRegion ®ion,
|
||||
::wl_resource *resource)
|
||||
: QtWaylandServer::zwp_locked_pointer_v1(resource)
|
||||
, SurfaceExtension(surface)
|
||||
, q(q)
|
||||
, surface(surface)
|
||||
, lifeTime(lifeTime)
|
||||
, pendingRegion(region)
|
||||
, hasPendingRegion(true)
|
||||
{
|
||||
commit();
|
||||
pending.region = region;
|
||||
|
||||
apply(&pending);
|
||||
|
||||
pending = LockedPointerV1Commit{};
|
||||
}
|
||||
|
||||
void LockedPointerV1InterfacePrivate::commit()
|
||||
void LockedPointerV1InterfacePrivate::apply(LockedPointerV1Commit *commit)
|
||||
{
|
||||
const QRegion oldRegion = effectiveRegion;
|
||||
const QPointF oldHint = hint;
|
||||
|
||||
if (hasPendingRegion) {
|
||||
region = mapScaleOverride(pendingRegion, surface->scaleOverride());
|
||||
hasPendingRegion = false;
|
||||
if (commit->region.has_value()) {
|
||||
region = mapScaleOverride(commit->region.value(), surface->scaleOverride());
|
||||
}
|
||||
if (hasPendingHint) {
|
||||
hint = pendingHint / surface->scaleOverride();
|
||||
hasPendingHint = false;
|
||||
if (commit->hint.has_value()) {
|
||||
hint = commit->hint.value() / surface->scaleOverride();
|
||||
}
|
||||
|
||||
effectiveRegion = surface->input();
|
||||
|
@ -187,17 +188,18 @@ void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy(Resource *re
|
|||
|
||||
void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y)
|
||||
{
|
||||
pendingHint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
|
||||
hasPendingHint = true;
|
||||
pending.hint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
|
||||
}
|
||||
|
||||
void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
|
||||
{
|
||||
pendingRegion = regionFromResource(region_resource);
|
||||
hasPendingRegion = true;
|
||||
pending.region = regionFromResource(region_resource);
|
||||
}
|
||||
|
||||
LockedPointerV1Interface::LockedPointerV1Interface(SurfaceInterface *surface, LifeTime lifeTime, const QRegion ®ion, ::wl_resource *resource)
|
||||
LockedPointerV1Interface::LockedPointerV1Interface(SurfaceInterface *surface,
|
||||
LifeTime lifeTime,
|
||||
const QRegion ®ion,
|
||||
::wl_resource *resource)
|
||||
: d(new LockedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource))
|
||||
{
|
||||
SurfaceInterfacePrivate::get(surface)->installPointerConstraint(this);
|
||||
|
@ -255,22 +257,24 @@ ConfinedPointerV1InterfacePrivate::ConfinedPointerV1InterfacePrivate(ConfinedPoi
|
|||
const QRegion ®ion,
|
||||
::wl_resource *resource)
|
||||
: QtWaylandServer::zwp_confined_pointer_v1(resource)
|
||||
, SurfaceExtension(surface)
|
||||
, q(q)
|
||||
, surface(surface)
|
||||
, lifeTime(lifeTime)
|
||||
, pendingRegion(region)
|
||||
, hasPendingRegion(true)
|
||||
{
|
||||
commit();
|
||||
pending.region = region;
|
||||
|
||||
apply(&pending);
|
||||
|
||||
pending = ConfinedPointerV1Commit{};
|
||||
}
|
||||
|
||||
void ConfinedPointerV1InterfacePrivate::commit()
|
||||
void ConfinedPointerV1InterfacePrivate::apply(ConfinedPointerV1Commit *commit)
|
||||
{
|
||||
const QRegion oldRegion = effectiveRegion;
|
||||
|
||||
if (hasPendingRegion) {
|
||||
region = mapScaleOverride(pendingRegion, surface->scaleOverride());
|
||||
hasPendingRegion = false;
|
||||
if (commit->region.has_value()) {
|
||||
region = mapScaleOverride(commit->region.value(), surface->scaleOverride());
|
||||
}
|
||||
|
||||
effectiveRegion = surface->input();
|
||||
|
@ -295,11 +299,13 @@ void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy(Resource
|
|||
|
||||
void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
|
||||
{
|
||||
pendingRegion = regionFromResource(region_resource);
|
||||
hasPendingRegion = true;
|
||||
pending.region = regionFromResource(region_resource);
|
||||
}
|
||||
|
||||
ConfinedPointerV1Interface::ConfinedPointerV1Interface(SurfaceInterface *surface, LifeTime lifeTime, const QRegion ®ion, ::wl_resource *resource)
|
||||
ConfinedPointerV1Interface::ConfinedPointerV1Interface(SurfaceInterface *surface,
|
||||
LifeTime lifeTime,
|
||||
const QRegion ®ion,
|
||||
::wl_resource *resource)
|
||||
: d(new ConfinedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource))
|
||||
{
|
||||
SurfaceInterfacePrivate::get(surface)->installPointerConstraint(this);
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "pointerconstraints_v1_interface.h"
|
||||
#include "surface_interface.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
#include "qwayland-server-pointer-constraints-unstable-v1.h"
|
||||
|
@ -35,25 +37,27 @@ protected:
|
|||
void zwp_pointer_constraints_v1_destroy(Resource *resource) override;
|
||||
};
|
||||
|
||||
class LockedPointerV1InterfacePrivate : public QtWaylandServer::zwp_locked_pointer_v1
|
||||
struct LockedPointerV1Commit
|
||||
{
|
||||
std::optional<QRegion> region;
|
||||
std::optional<QPointF> hint;
|
||||
};
|
||||
|
||||
class LockedPointerV1InterfacePrivate final : public QtWaylandServer::zwp_locked_pointer_v1, public SurfaceExtension<LockedPointerV1Commit>
|
||||
{
|
||||
public:
|
||||
static LockedPointerV1InterfacePrivate *get(LockedPointerV1Interface *pointer);
|
||||
|
||||
LockedPointerV1InterfacePrivate(LockedPointerV1Interface *q, SurfaceInterface *surface, LockedPointerV1Interface::LifeTime lifeTime, const QRegion ®ion, ::wl_resource *resource);
|
||||
|
||||
void commit();
|
||||
void apply(LockedPointerV1Commit *commit) override;
|
||||
|
||||
LockedPointerV1Interface *q;
|
||||
QPointer<SurfaceInterface> surface;
|
||||
LockedPointerV1Interface::LifeTime lifeTime;
|
||||
QRegion effectiveRegion;
|
||||
QRegion region;
|
||||
QRegion pendingRegion;
|
||||
QPointF hint = QPointF(-1, -1);
|
||||
QPointF pendingHint;
|
||||
bool hasPendingRegion = false;
|
||||
bool hasPendingHint = false;
|
||||
bool isLocked = false;
|
||||
|
||||
protected:
|
||||
|
@ -63,25 +67,29 @@ protected:
|
|||
void zwp_locked_pointer_v1_set_region(Resource *resource, struct ::wl_resource *region_resource) override;
|
||||
};
|
||||
|
||||
class ConfinedPointerV1InterfacePrivate : public QtWaylandServer::zwp_confined_pointer_v1
|
||||
struct ConfinedPointerV1Commit
|
||||
{
|
||||
std::optional<QRegion> region;
|
||||
};
|
||||
|
||||
class ConfinedPointerV1InterfacePrivate final : public QtWaylandServer::zwp_confined_pointer_v1, public SurfaceExtension<ConfinedPointerV1Commit>
|
||||
{
|
||||
public:
|
||||
static ConfinedPointerV1InterfacePrivate *get(ConfinedPointerV1Interface *pointer);
|
||||
|
||||
ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q, SurfaceInterface *surface,
|
||||
ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q,
|
||||
SurfaceInterface *surface,
|
||||
ConfinedPointerV1Interface::LifeTime lifeTime,
|
||||
const QRegion ®ion,
|
||||
::wl_resource *resource);
|
||||
|
||||
void commit();
|
||||
void apply(ConfinedPointerV1Commit *commit) override;
|
||||
|
||||
ConfinedPointerV1Interface *q;
|
||||
QPointer<SurfaceInterface> surface;
|
||||
ConfinedPointerV1Interface::LifeTime lifeTime;
|
||||
QRegion effectiveRegion;
|
||||
QRegion region;
|
||||
QRegion pendingRegion;
|
||||
bool hasPendingRegion = false;
|
||||
bool isConfined = false;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -109,8 +109,8 @@ void SubSurfaceInterfacePrivate::subsurface_set_position(Resource *resource, int
|
|||
|
||||
SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent);
|
||||
|
||||
parentPrivate->pending.subsurface.position[q] = QPoint(x, y);
|
||||
parentPrivate->pending.subsurfacePositionChanged = true;
|
||||
parentPrivate->pending->subsurface.position[q] = QPoint(x, y);
|
||||
parentPrivate->pending->subsurfacePositionChanged = true;
|
||||
}
|
||||
|
||||
void SubSurfaceInterfacePrivate::subsurface_place_above(Resource *resource, struct ::wl_resource *sibling_resource)
|
||||
|
@ -166,20 +166,19 @@ void SubSurfaceInterfacePrivate::subsurface_set_desync(Resource *)
|
|||
mode = SubSurfaceInterface::Mode::Desynchronized;
|
||||
if (!q->isSynchronized()) {
|
||||
auto surfacePrivate = SurfaceInterfacePrivate::get(surface);
|
||||
surfacePrivate->commitFromCache();
|
||||
while (!locks.isEmpty()) {
|
||||
SubSurfaceStateLock lock = locks.takeFirst();
|
||||
surfacePrivate->unlockState(lock.serial);
|
||||
}
|
||||
}
|
||||
Q_EMIT q->modeChanged(SubSurfaceInterface::Mode::Desynchronized);
|
||||
}
|
||||
|
||||
void SubSurfaceInterfacePrivate::commit()
|
||||
{
|
||||
}
|
||||
|
||||
void SubSurfaceInterfacePrivate::parentCommit()
|
||||
void SubSurfaceInterfacePrivate::parentApplyState(quint32 serial)
|
||||
{
|
||||
auto parentPrivate = SurfaceInterfacePrivate::get(parent);
|
||||
if (parentPrivate->current.subsurfacePositionChanged) {
|
||||
const QPoint &pos = parentPrivate->current.subsurface.position[q];
|
||||
if (parentPrivate->current->subsurfacePositionChanged) {
|
||||
const QPoint &pos = parentPrivate->current->subsurface.position[q];
|
||||
if (position != pos) {
|
||||
position = pos;
|
||||
Q_EMIT q->positionChanged(pos);
|
||||
|
@ -188,7 +187,10 @@ void SubSurfaceInterfacePrivate::parentCommit()
|
|||
|
||||
if (mode == SubSurfaceInterface::Mode::Synchronized) {
|
||||
auto surfacePrivate = SurfaceInterfacePrivate::get(surface);
|
||||
surfacePrivate->commitFromCache();
|
||||
while (!locks.isEmpty() && locks[0].parentSerial == serial) {
|
||||
SubSurfaceStateLock lock = locks.takeFirst();
|
||||
surfacePrivate->unlockState(lock.serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,6 +268,24 @@ SurfaceInterface *SubSurfaceInterface::mainSurface() const
|
|||
return d->parent;
|
||||
}
|
||||
|
||||
void SubSurfaceInterface::commit()
|
||||
{
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(d->surface);
|
||||
if (isSynchronized()) {
|
||||
const quint32 serial = surfacePrivate->lockState(surfacePrivate->pending.get());
|
||||
const quint32 parentSerial = SurfaceInterfacePrivate::get(d->parent)->pending->serial;
|
||||
d->locks.append(SubSurfaceStateLock{
|
||||
.serial = serial,
|
||||
.parentSerial = parentSerial,
|
||||
});
|
||||
} else {
|
||||
while (!d->locks.isEmpty()) {
|
||||
SubSurfaceStateLock lock = d->locks.takeFirst();
|
||||
surfacePrivate->unlockState(lock.serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWaylandServer
|
||||
|
||||
#include "moc_subcompositor_interface.cpp"
|
||||
|
|
|
@ -116,7 +116,11 @@ Q_SIGNALS:
|
|||
|
||||
private:
|
||||
SubSurfaceInterface(SurfaceInterface *surface, SurfaceInterface *parent, wl_resource *resource);
|
||||
|
||||
void commit();
|
||||
|
||||
std::unique_ptr<SubSurfaceInterfacePrivate> d;
|
||||
friend class SurfaceInterfacePrivate;
|
||||
friend class SubSurfaceInterfacePrivate;
|
||||
friend class SubCompositorInterfacePrivate;
|
||||
};
|
||||
|
|
|
@ -29,6 +29,12 @@ protected:
|
|||
void subcompositor_get_subsurface(Resource *resource, uint32_t id, struct ::wl_resource *surface_resource, struct ::wl_resource *parent_resource) override;
|
||||
};
|
||||
|
||||
struct SubSurfaceStateLock
|
||||
{
|
||||
const quint32 serial;
|
||||
const quint32 parentSerial;
|
||||
};
|
||||
|
||||
class SubSurfaceInterfacePrivate : public SurfaceRole, public QtWaylandServer::wl_subsurface
|
||||
{
|
||||
public:
|
||||
|
@ -36,14 +42,14 @@ public:
|
|||
|
||||
SubSurfaceInterfacePrivate(SubSurfaceInterface *q, SurfaceInterface *surface, SurfaceInterface *parent, ::wl_resource *resource);
|
||||
|
||||
void commit() override;
|
||||
void parentCommit();
|
||||
void parentApplyState(quint32 serial);
|
||||
|
||||
SubSurfaceInterface *q;
|
||||
QPoint position = QPoint(0, 0);
|
||||
SubSurfaceInterface::Mode mode = SubSurfaceInterface::Mode::Synchronized;
|
||||
QPointer<SurfaceInterface> surface;
|
||||
QPointer<SurfaceInterface> parent;
|
||||
QList<SubSurfaceStateLock> locks;
|
||||
|
||||
protected:
|
||||
void subsurface_destroy_resource(Resource *resource) override;
|
||||
|
|
|
@ -40,10 +40,9 @@ static QRegion map_helper(const QMatrix4x4 &matrix, const QRegion ®ion)
|
|||
|
||||
SurfaceInterfacePrivate::SurfaceInterfacePrivate(SurfaceInterface *q)
|
||||
: q(q)
|
||||
, current(std::make_unique<SurfaceState>())
|
||||
, pending(std::make_unique<SurfaceState>())
|
||||
{
|
||||
wl_list_init(¤t.frameCallbacks);
|
||||
wl_list_init(&pending.frameCallbacks);
|
||||
wl_list_init(&cached.frameCallbacks);
|
||||
}
|
||||
|
||||
SurfaceInterfacePrivate::~SurfaceInterfacePrivate()
|
||||
|
@ -51,23 +50,29 @@ SurfaceInterfacePrivate::~SurfaceInterfacePrivate()
|
|||
wl_resource *resource;
|
||||
wl_resource *tmp;
|
||||
|
||||
wl_resource_for_each_safe (resource, tmp, ¤t.frameCallbacks) {
|
||||
wl_resource_for_each_safe (resource, tmp, ¤t->frameCallbacks) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
wl_resource_for_each_safe (resource, tmp, &pending.frameCallbacks) {
|
||||
wl_resource_for_each_safe (resource, tmp, &pending->frameCallbacks) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
wl_resource_for_each_safe (resource, tmp, &cached.frameCallbacks) {
|
||||
wl_resource_destroy(resource);
|
||||
for (const auto &stash : std::as_const(stashed)) {
|
||||
wl_resource_for_each_safe (resource, tmp, &stash->frameCallbacks) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::addChild(SubSurfaceInterface *child)
|
||||
{
|
||||
// protocol is not precise on how to handle the addition of new sub surfaces
|
||||
pending.subsurface.above.append(child);
|
||||
cached.subsurface.above.append(child);
|
||||
current.subsurface.above.append(child);
|
||||
current->subsurface.above.append(child);
|
||||
pending->subsurface.above.append(child);
|
||||
|
||||
for (int i = 0; i < stashed.size(); ++i) {
|
||||
stashed[i]->subsurface.above.append(child);
|
||||
}
|
||||
|
||||
child->surface()->setOutputs(outputs);
|
||||
if (preferredBufferScale.has_value()) {
|
||||
child->surface()->setPreferredBufferScale(preferredBufferScale.value());
|
||||
|
@ -83,15 +88,17 @@ void SurfaceInterfacePrivate::addChild(SubSurfaceInterface *child)
|
|||
void SurfaceInterfacePrivate::removeChild(SubSurfaceInterface *child)
|
||||
{
|
||||
// protocol is not precise on how to handle the addition of new sub surfaces
|
||||
pending.subsurface.below.removeAll(child);
|
||||
pending.subsurface.above.removeAll(child);
|
||||
pending.subsurface.position.remove(child);
|
||||
cached.subsurface.below.removeAll(child);
|
||||
cached.subsurface.above.removeAll(child);
|
||||
cached.subsurface.position.remove(child);
|
||||
current.subsurface.below.removeAll(child);
|
||||
current.subsurface.above.removeAll(child);
|
||||
current.subsurface.position.remove(child);
|
||||
current->subsurface.below.removeAll(child);
|
||||
current->subsurface.above.removeAll(child);
|
||||
|
||||
pending->subsurface.below.removeAll(child);
|
||||
pending->subsurface.above.removeAll(child);
|
||||
|
||||
for (int i = 0; i < stashed.size(); ++i) {
|
||||
stashed[i]->subsurface.below.removeAll(child);
|
||||
stashed[i]->subsurface.above.removeAll(child);
|
||||
}
|
||||
|
||||
Q_EMIT q->childSubSurfaceRemoved(child);
|
||||
Q_EMIT q->childSubSurfacesChanged();
|
||||
}
|
||||
|
@ -103,23 +110,23 @@ bool SurfaceInterfacePrivate::raiseChild(SubSurfaceInterface *subsurface, Surfac
|
|||
QList<SubSurfaceInterface *> *anchorList;
|
||||
int anchorIndex;
|
||||
|
||||
pending.subsurface.below.removeOne(subsurface);
|
||||
pending.subsurface.above.removeOne(subsurface);
|
||||
pending->subsurface.below.removeOne(subsurface);
|
||||
pending->subsurface.above.removeOne(subsurface);
|
||||
|
||||
if (anchor == q) {
|
||||
// Pretend as if the parent surface were before the first child in the above list.
|
||||
anchorList = &pending.subsurface.above;
|
||||
anchorList = &pending->subsurface.above;
|
||||
anchorIndex = -1;
|
||||
} else if (anchorIndex = pending.subsurface.above.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending.subsurface.above;
|
||||
} else if (anchorIndex = pending.subsurface.below.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending.subsurface.below;
|
||||
} else if (anchorIndex = pending->subsurface.above.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending->subsurface.above;
|
||||
} else if (anchorIndex = pending->subsurface.below.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending->subsurface.below;
|
||||
} else {
|
||||
return false; // The anchor belongs to other sub-surface tree.
|
||||
}
|
||||
|
||||
anchorList->insert(anchorIndex + 1, subsurface);
|
||||
pending.subsurfaceOrderChanged = true;
|
||||
pending->subsurfaceOrderChanged = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -130,48 +137,48 @@ bool SurfaceInterfacePrivate::lowerChild(SubSurfaceInterface *subsurface, Surfac
|
|||
QList<SubSurfaceInterface *> *anchorList;
|
||||
int anchorIndex;
|
||||
|
||||
pending.subsurface.below.removeOne(subsurface);
|
||||
pending.subsurface.above.removeOne(subsurface);
|
||||
pending->subsurface.below.removeOne(subsurface);
|
||||
pending->subsurface.above.removeOne(subsurface);
|
||||
|
||||
if (anchor == q) {
|
||||
// Pretend as if the parent surface were after the last child in the below list.
|
||||
anchorList = &pending.subsurface.below;
|
||||
anchorIndex = pending.subsurface.below.count();
|
||||
} else if (anchorIndex = pending.subsurface.above.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending.subsurface.above;
|
||||
} else if (anchorIndex = pending.subsurface.below.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending.subsurface.below;
|
||||
anchorList = &pending->subsurface.below;
|
||||
anchorIndex = pending->subsurface.below.count();
|
||||
} else if (anchorIndex = pending->subsurface.above.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending->subsurface.above;
|
||||
} else if (anchorIndex = pending->subsurface.below.indexOf(anchor->subSurface()); anchorIndex != -1) {
|
||||
anchorList = &pending->subsurface.below;
|
||||
} else {
|
||||
return false; // The anchor belongs to other sub-surface tree.
|
||||
}
|
||||
|
||||
anchorList->insert(anchorIndex, subsurface);
|
||||
pending.subsurfaceOrderChanged = true;
|
||||
pending->subsurfaceOrderChanged = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::setShadow(const QPointer<ShadowInterface> &shadow)
|
||||
{
|
||||
pending.shadow = shadow;
|
||||
pending.shadowIsSet = true;
|
||||
pending->shadow = shadow;
|
||||
pending->shadowIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::setBlur(const QPointer<BlurInterface> &blur)
|
||||
{
|
||||
pending.blur = blur;
|
||||
pending.blurIsSet = true;
|
||||
pending->blur = blur;
|
||||
pending->blurIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::setSlide(const QPointer<SlideInterface> &slide)
|
||||
{
|
||||
pending.slide = slide;
|
||||
pending.slideIsSet = true;
|
||||
pending->slide = slide;
|
||||
pending->slideIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::setContrast(const QPointer<ContrastInterface> &contrast)
|
||||
{
|
||||
pending.contrast = contrast;
|
||||
pending.contrastIsSet = true;
|
||||
pending->contrast = contrast;
|
||||
pending->contrastIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::installPointerConstraint(LockedPointerV1Interface *lock)
|
||||
|
@ -263,23 +270,23 @@ void SurfaceInterfacePrivate::surface_attach(Resource *resource, struct ::wl_res
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
pending.offset = QPoint(x, y);
|
||||
pending->offset = QPoint(x, y);
|
||||
}
|
||||
|
||||
pending.bufferIsSet = true;
|
||||
pending->bufferIsSet = true;
|
||||
if (!buffer) {
|
||||
// got a null buffer, deletes content in next frame
|
||||
pending.buffer = nullptr;
|
||||
pending.damage = QRegion();
|
||||
pending.bufferDamage = QRegion();
|
||||
pending->buffer = nullptr;
|
||||
pending->damage = QRegion();
|
||||
pending->bufferDamage = QRegion();
|
||||
return;
|
||||
}
|
||||
pending.buffer = Display::bufferForResource(buffer);
|
||||
pending->buffer = Display::bufferForResource(buffer);
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_damage(Resource *, int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
pending.damage |= QRect(x, y, width, height);
|
||||
pending->damage |= QRect(x, y, width, height);
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_frame(Resource *resource, uint32_t callback)
|
||||
|
@ -297,30 +304,43 @@ void SurfaceInterfacePrivate::surface_frame(Resource *resource, uint32_t callbac
|
|||
wl_list_remove(wl_resource_get_link(resource));
|
||||
});
|
||||
|
||||
wl_list_insert(pending.frameCallbacks.prev, wl_resource_get_link(callbackResource));
|
||||
wl_list_insert(pending->frameCallbacks.prev, wl_resource_get_link(callbackResource));
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_set_opaque_region(Resource *resource, struct ::wl_resource *region)
|
||||
{
|
||||
RegionInterface *r = RegionInterface::get(region);
|
||||
pending.opaque = r ? r->region() : QRegion();
|
||||
pending.opaqueIsSet = true;
|
||||
pending->opaque = r ? r->region() : QRegion();
|
||||
pending->opaqueIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_set_input_region(Resource *resource, struct ::wl_resource *region)
|
||||
{
|
||||
RegionInterface *r = RegionInterface::get(region);
|
||||
pending.input = r ? r->region() : infiniteRegion();
|
||||
pending.inputIsSet = true;
|
||||
pending->input = r ? r->region() : infiniteRegion();
|
||||
pending->inputIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_commit(Resource *resource)
|
||||
{
|
||||
if (subSurface) {
|
||||
commitSubSurface();
|
||||
} else {
|
||||
applyState(&pending);
|
||||
subSurface->commit();
|
||||
}
|
||||
|
||||
// If there are already stashed states, this one will be applied when all the previous
|
||||
// states are applied.
|
||||
if (pending->locks || !stashed.empty()) {
|
||||
auto stash = std::make_unique<SurfaceState>();
|
||||
pending->mergeInto(stash.get());
|
||||
const quint32 serial = stash->serial;
|
||||
|
||||
stashed.push_back(std::move(stash));
|
||||
Q_EMIT q->stateStashed(serial);
|
||||
} else {
|
||||
applyState(pending.get());
|
||||
}
|
||||
|
||||
pending->serial++;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_set_buffer_transform(Resource *resource, int32_t transform)
|
||||
|
@ -329,8 +349,8 @@ void SurfaceInterfacePrivate::surface_set_buffer_transform(Resource *resource, i
|
|||
wl_resource_post_error(resource->handle, error_invalid_transform, "buffer transform must be a valid transform (%d specified)", transform);
|
||||
return;
|
||||
}
|
||||
pending.bufferTransform = KWin::OutputTransform::Kind(transform);
|
||||
pending.bufferTransformIsSet = true;
|
||||
pending->bufferTransform = KWin::OutputTransform::Kind(transform);
|
||||
pending->bufferTransformIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_set_buffer_scale(Resource *resource, int32_t scale)
|
||||
|
@ -339,18 +359,18 @@ void SurfaceInterfacePrivate::surface_set_buffer_scale(Resource *resource, int32
|
|||
wl_resource_post_error(resource->handle, error_invalid_scale, "buffer scale must be at least one (%d specified)", scale);
|
||||
return;
|
||||
}
|
||||
pending.bufferScale = scale;
|
||||
pending.bufferScaleIsSet = true;
|
||||
pending->bufferScale = scale;
|
||||
pending->bufferScaleIsSet = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_damage_buffer(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
pending.bufferDamage |= QRect(x, y, width, height);
|
||||
pending->bufferDamage |= QRect(x, y, width, height);
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::surface_offset(Resource *resource, int32_t x, int32_t y)
|
||||
{
|
||||
pending.offset = QPoint(x, y);
|
||||
pending->offset = QPoint(x, y);
|
||||
}
|
||||
|
||||
SurfaceInterface::SurfaceInterface(CompositorInterface *compositor, wl_resource *resource)
|
||||
|
@ -398,22 +418,22 @@ void SurfaceInterface::frameRendered(quint32 msec)
|
|||
wl_resource *resource;
|
||||
wl_resource *tmp;
|
||||
|
||||
wl_resource_for_each_safe (resource, tmp, &d->current.frameCallbacks) {
|
||||
wl_resource_for_each_safe (resource, tmp, &d->current->frameCallbacks) {
|
||||
wl_callback_send_done(resource, msec);
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(d->current.subsurface.below)) {
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.below)) {
|
||||
subsurface->surface()->frameRendered(msec);
|
||||
}
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(d->current.subsurface.above)) {
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.above)) {
|
||||
subsurface->surface()->frameRendered(msec);
|
||||
}
|
||||
}
|
||||
|
||||
bool SurfaceInterface::hasFrameCallbacks() const
|
||||
{
|
||||
return !wl_list_empty(&d->current.frameCallbacks);
|
||||
return !wl_list_empty(&d->current->frameCallbacks);
|
||||
}
|
||||
|
||||
QMatrix4x4 SurfaceInterfacePrivate::buildSurfaceToBufferMatrix()
|
||||
|
@ -422,56 +442,56 @@ QMatrix4x4 SurfaceInterfacePrivate::buildSurfaceToBufferMatrix()
|
|||
|
||||
QMatrix4x4 surfaceToBufferMatrix;
|
||||
|
||||
if (!current.buffer) {
|
||||
if (!current->buffer) {
|
||||
return surfaceToBufferMatrix;
|
||||
}
|
||||
|
||||
surfaceToBufferMatrix.scale(current.bufferScale, current.bufferScale);
|
||||
surfaceToBufferMatrix.scale(current->bufferScale, current->bufferScale);
|
||||
surfaceToBufferMatrix.scale(scaleOverride, scaleOverride);
|
||||
|
||||
switch (current.bufferTransform.kind()) {
|
||||
switch (current->bufferTransform.kind()) {
|
||||
case KWin::OutputTransform::Normal:
|
||||
case KWin::OutputTransform::Flipped:
|
||||
break;
|
||||
case KWin::OutputTransform::Rotated90:
|
||||
case KWin::OutputTransform::Flipped90:
|
||||
surfaceToBufferMatrix.translate(0, bufferSize.height() / current.bufferScale);
|
||||
surfaceToBufferMatrix.translate(0, bufferSize.height() / current->bufferScale);
|
||||
surfaceToBufferMatrix.rotate(-90, 0, 0, 1);
|
||||
break;
|
||||
case KWin::OutputTransform::Rotated180:
|
||||
case KWin::OutputTransform::Flipped180:
|
||||
surfaceToBufferMatrix.translate(bufferSize.width() / current.bufferScale, bufferSize.height() / current.bufferScale);
|
||||
surfaceToBufferMatrix.translate(bufferSize.width() / current->bufferScale, bufferSize.height() / current->bufferScale);
|
||||
surfaceToBufferMatrix.rotate(-180, 0, 0, 1);
|
||||
break;
|
||||
case KWin::OutputTransform::Rotated270:
|
||||
case KWin::OutputTransform::Flipped270:
|
||||
surfaceToBufferMatrix.translate(bufferSize.width() / current.bufferScale, 0);
|
||||
surfaceToBufferMatrix.translate(bufferSize.width() / current->bufferScale, 0);
|
||||
surfaceToBufferMatrix.rotate(-270, 0, 0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (current.bufferTransform.kind()) {
|
||||
switch (current->bufferTransform.kind()) {
|
||||
case KWin::OutputTransform::Flipped:
|
||||
case KWin::OutputTransform::Flipped180:
|
||||
surfaceToBufferMatrix.translate(bufferSize.width() / current.bufferScale, 0);
|
||||
surfaceToBufferMatrix.translate(bufferSize.width() / current->bufferScale, 0);
|
||||
surfaceToBufferMatrix.scale(-1, 1);
|
||||
break;
|
||||
case KWin::OutputTransform::Flipped90:
|
||||
case KWin::OutputTransform::Flipped270:
|
||||
surfaceToBufferMatrix.translate(bufferSize.height() / current.bufferScale, 0);
|
||||
surfaceToBufferMatrix.translate(bufferSize.height() / current->bufferScale, 0);
|
||||
surfaceToBufferMatrix.scale(-1, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (current.viewport.sourceGeometry.isValid()) {
|
||||
surfaceToBufferMatrix.translate(current.viewport.sourceGeometry.x(), current.viewport.sourceGeometry.y());
|
||||
if (current->viewport.sourceGeometry.isValid()) {
|
||||
surfaceToBufferMatrix.translate(current->viewport.sourceGeometry.x(), current->viewport.sourceGeometry.y());
|
||||
}
|
||||
|
||||
QSizeF sourceSize;
|
||||
if (current.viewport.sourceGeometry.isValid()) {
|
||||
sourceSize = current.viewport.sourceGeometry.size();
|
||||
if (current->viewport.sourceGeometry.isValid()) {
|
||||
sourceSize = current->viewport.sourceGeometry.size();
|
||||
} else {
|
||||
sourceSize = implicitSurfaceSize;
|
||||
}
|
||||
|
@ -485,21 +505,29 @@ QMatrix4x4 SurfaceInterfacePrivate::buildSurfaceToBufferMatrix()
|
|||
|
||||
QRectF SurfaceInterfacePrivate::computeBufferSourceBox() const
|
||||
{
|
||||
if (!current.viewport.sourceGeometry.isValid()) {
|
||||
if (!current->viewport.sourceGeometry.isValid()) {
|
||||
return QRectF(0, 0, bufferSize.width(), bufferSize.height());
|
||||
}
|
||||
|
||||
const QSizeF bounds = current.bufferTransform.map(bufferSize);
|
||||
const QRectF box(current.viewport.sourceGeometry.x() * current.bufferScale,
|
||||
current.viewport.sourceGeometry.y() * current.bufferScale,
|
||||
current.viewport.sourceGeometry.width() * current.bufferScale,
|
||||
current.viewport.sourceGeometry.height() * current.bufferScale);
|
||||
const QSizeF bounds = current->bufferTransform.map(bufferSize);
|
||||
const QRectF box(current->viewport.sourceGeometry.x() * current->bufferScale,
|
||||
current->viewport.sourceGeometry.y() * current->bufferScale,
|
||||
current->viewport.sourceGeometry.width() * current->bufferScale,
|
||||
current->viewport.sourceGeometry.height() * current->bufferScale);
|
||||
|
||||
return current.bufferTransform.inverted().map(box, bounds);
|
||||
return current->bufferTransform.inverted().map(box, bounds);
|
||||
}
|
||||
|
||||
SurfaceState::SurfaceState()
|
||||
{
|
||||
wl_list_init(&frameCallbacks);
|
||||
}
|
||||
|
||||
void SurfaceState::mergeInto(SurfaceState *target)
|
||||
{
|
||||
target->serial = serial;
|
||||
target->locks = locks;
|
||||
|
||||
target->bufferIsSet = bufferIsSet;
|
||||
if (target->bufferIsSet) {
|
||||
target->buffer = buffer;
|
||||
|
@ -580,6 +608,7 @@ void SurfaceState::mergeInto(SurfaceState *target)
|
|||
}
|
||||
|
||||
*this = SurfaceState{};
|
||||
serial = target->serial;
|
||||
subsurface = target->subsurface;
|
||||
wl_list_init(&frameCallbacks);
|
||||
}
|
||||
|
@ -588,13 +617,13 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
|
|||
{
|
||||
const bool bufferChanged = next->bufferIsSet;
|
||||
const bool opaqueRegionChanged = next->opaqueIsSet;
|
||||
const bool transformChanged = next->bufferTransformIsSet && (current.bufferTransform != next->bufferTransform);
|
||||
const bool transformChanged = next->bufferTransformIsSet && (current->bufferTransform != next->bufferTransform);
|
||||
const bool shadowChanged = next->shadowIsSet;
|
||||
const bool blurChanged = next->blurIsSet;
|
||||
const bool contrastChanged = next->contrastIsSet;
|
||||
const bool slideChanged = next->slideIsSet;
|
||||
const bool subsurfaceOrderChanged = next->subsurfaceOrderChanged;
|
||||
const bool visibilityChanged = bufferChanged && bool(current.buffer) != bool(next->buffer);
|
||||
const bool visibilityChanged = bufferChanged && bool(current->buffer) != bool(next->buffer);
|
||||
|
||||
const QSizeF oldSurfaceSize = surfaceSize;
|
||||
const QSize oldBufferSize = bufferSize;
|
||||
|
@ -602,17 +631,17 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
|
|||
const QMatrix4x4 oldSurfaceToBufferMatrix = surfaceToBufferMatrix;
|
||||
const QRegion oldInputRegion = inputRegion;
|
||||
|
||||
next->mergeInto(¤t);
|
||||
bufferRef = current.buffer;
|
||||
next->mergeInto(current.get());
|
||||
bufferRef = current->buffer;
|
||||
scaleOverride = pendingScaleOverride;
|
||||
|
||||
// TODO: Refactor the state management code because it gets more clumsy.
|
||||
if (current.buffer) {
|
||||
bufferSize = current.buffer->size();
|
||||
if (current->buffer) {
|
||||
bufferSize = current->buffer->size();
|
||||
bufferSourceBox = computeBufferSourceBox();
|
||||
|
||||
implicitSurfaceSize = current.buffer->size() / current.bufferScale;
|
||||
switch (current.bufferTransform.kind()) {
|
||||
implicitSurfaceSize = current->buffer->size() / current->bufferScale;
|
||||
switch (current->bufferTransform.kind()) {
|
||||
case KWin::OutputTransform::Rotated90:
|
||||
case KWin::OutputTransform::Rotated270:
|
||||
case KWin::OutputTransform::Flipped90:
|
||||
|
@ -626,21 +655,21 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
|
|||
break;
|
||||
}
|
||||
|
||||
if (current.viewport.destinationSize.isValid()) {
|
||||
surfaceSize = current.viewport.destinationSize;
|
||||
} else if (current.viewport.sourceGeometry.isValid()) {
|
||||
surfaceSize = current.viewport.sourceGeometry.size();
|
||||
if (current->viewport.destinationSize.isValid()) {
|
||||
surfaceSize = current->viewport.destinationSize;
|
||||
} else if (current->viewport.sourceGeometry.isValid()) {
|
||||
surfaceSize = current->viewport.sourceGeometry.size();
|
||||
} else {
|
||||
surfaceSize = implicitSurfaceSize;
|
||||
}
|
||||
|
||||
const QRectF surfaceRect(QPoint(0, 0), surfaceSize);
|
||||
inputRegion = current.input & surfaceRect.toAlignedRect();
|
||||
inputRegion = current->input & surfaceRect.toAlignedRect();
|
||||
|
||||
if (!current.buffer->hasAlphaChannel()) {
|
||||
if (!current->buffer->hasAlphaChannel()) {
|
||||
opaqueRegion = surfaceRect.toAlignedRect();
|
||||
} else {
|
||||
opaqueRegion = current.opaque & surfaceRect.toAlignedRect();
|
||||
opaqueRegion = current->opaque & surfaceRect.toAlignedRect();
|
||||
}
|
||||
|
||||
QMatrix4x4 scaleOverrideMatrix;
|
||||
|
@ -663,15 +692,6 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
|
|||
|
||||
surfaceToBufferMatrix = buildSurfaceToBufferMatrix();
|
||||
|
||||
if (lockedPointer) {
|
||||
auto lockedPointerPrivate = LockedPointerV1InterfacePrivate::get(lockedPointer);
|
||||
lockedPointerPrivate->commit();
|
||||
}
|
||||
if (confinedPointer) {
|
||||
auto confinedPointerPrivate = ConfinedPointerV1InterfacePrivate::get(confinedPointer);
|
||||
confinedPointerPrivate->commit();
|
||||
}
|
||||
|
||||
if (opaqueRegionChanged) {
|
||||
Q_EMIT q->opaqueChanged(opaqueRegion);
|
||||
}
|
||||
|
@ -679,7 +699,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
|
|||
Q_EMIT q->inputChanged(inputRegion);
|
||||
}
|
||||
if (transformChanged) {
|
||||
Q_EMIT q->bufferTransformChanged(current.bufferTransform);
|
||||
Q_EMIT q->bufferTransformChanged(current->bufferTransform);
|
||||
}
|
||||
if (visibilityChanged) {
|
||||
updateEffectiveMapped();
|
||||
|
@ -713,56 +733,56 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
|
|||
}
|
||||
|
||||
if (bufferChanged) {
|
||||
if (current.buffer && (!current.damage.isEmpty() || !current.bufferDamage.isEmpty())) {
|
||||
const QRect bufferRect = QRect(QPoint(0, 0), current.buffer->size());
|
||||
bufferDamage = current.bufferDamage
|
||||
.united(q->mapToBuffer(current.damage))
|
||||
if (current->buffer && (!current->damage.isEmpty() || !current->bufferDamage.isEmpty())) {
|
||||
const QRect bufferRect = QRect(QPoint(0, 0), current->buffer->size());
|
||||
bufferDamage = current->bufferDamage
|
||||
.united(q->mapToBuffer(current->damage))
|
||||
.intersected(bufferRect);
|
||||
Q_EMIT q->damaged(bufferDamage);
|
||||
}
|
||||
}
|
||||
|
||||
// The position of a sub-surface is applied when its parent is committed.
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current.subsurface.below)) {
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current->subsurface.below)) {
|
||||
auto subsurfacePrivate = SubSurfaceInterfacePrivate::get(subsurface);
|
||||
subsurfacePrivate->parentCommit();
|
||||
subsurfacePrivate->parentApplyState(next->serial);
|
||||
}
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current.subsurface.above)) {
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current->subsurface.above)) {
|
||||
auto subsurfacePrivate = SubSurfaceInterfacePrivate::get(subsurface);
|
||||
subsurfacePrivate->parentCommit();
|
||||
}
|
||||
if (role) {
|
||||
role->commit();
|
||||
subsurfacePrivate->parentApplyState(next->serial);
|
||||
}
|
||||
|
||||
Q_EMIT q->stateApplied(next->serial);
|
||||
Q_EMIT q->committed();
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::commitSubSurface()
|
||||
quint32 SurfaceInterfacePrivate::lockState(SurfaceState *state)
|
||||
{
|
||||
if (subSurface->isSynchronized()) {
|
||||
commitToCache();
|
||||
state->locks++;
|
||||
return state->serial;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::unlockState(quint32 serial)
|
||||
{
|
||||
if (pending->serial == serial) {
|
||||
Q_ASSERT(pending->locks > 0);
|
||||
pending->locks--;
|
||||
} else {
|
||||
if (hasCacheState) {
|
||||
commitToCache();
|
||||
commitFromCache();
|
||||
} else {
|
||||
applyState(&pending);
|
||||
for (const auto &state : stashed) {
|
||||
if (state->serial == serial) {
|
||||
Q_ASSERT(state->locks > 0);
|
||||
state->locks--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!stashed.empty() && !stashed[0]->locks) {
|
||||
auto stash = std::move(stashed.front());
|
||||
stashed.pop_front();
|
||||
applyState(stash.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::commitToCache()
|
||||
{
|
||||
pending.mergeInto(&cached);
|
||||
hasCacheState = true;
|
||||
}
|
||||
|
||||
void SurfaceInterfacePrivate::commitFromCache()
|
||||
{
|
||||
applyState(&cached);
|
||||
hasCacheState = false;
|
||||
}
|
||||
|
||||
bool SurfaceInterfacePrivate::computeEffectiveMapped() const
|
||||
{
|
||||
if (!bufferRef) {
|
||||
|
@ -789,11 +809,11 @@ void SurfaceInterfacePrivate::updateEffectiveMapped()
|
|||
Q_EMIT q->unmapped();
|
||||
}
|
||||
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current.subsurface.below)) {
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current->subsurface.below)) {
|
||||
auto surfacePrivate = SurfaceInterfacePrivate::get(subsurface->surface());
|
||||
surfacePrivate->updateEffectiveMapped();
|
||||
}
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current.subsurface.above)) {
|
||||
for (SubSurfaceInterface *subsurface : std::as_const(current->subsurface.above)) {
|
||||
auto surfacePrivate = SurfaceInterfacePrivate::get(subsurface->surface());
|
||||
surfacePrivate->updateEffectiveMapped();
|
||||
}
|
||||
|
@ -835,7 +855,7 @@ QRectF SurfaceInterface::bufferSourceBox() const
|
|||
|
||||
KWin::OutputTransform SurfaceInterface::bufferTransform() const
|
||||
{
|
||||
return d->current.bufferTransform;
|
||||
return d->current->bufferTransform;
|
||||
}
|
||||
|
||||
KWin::GraphicsBuffer *SurfaceInterface::buffer() const
|
||||
|
@ -845,7 +865,7 @@ KWin::GraphicsBuffer *SurfaceInterface::buffer() const
|
|||
|
||||
QPoint SurfaceInterface::offset() const
|
||||
{
|
||||
return d->current.offset / d->scaleOverride;
|
||||
return d->current->offset / d->scaleOverride;
|
||||
}
|
||||
|
||||
SurfaceInterface *SurfaceInterface::get(wl_resource *native)
|
||||
|
@ -866,12 +886,12 @@ SurfaceInterface *SurfaceInterface::get(quint32 id, const ClientConnection *clie
|
|||
|
||||
QList<SubSurfaceInterface *> SurfaceInterface::below() const
|
||||
{
|
||||
return d->current.subsurface.below;
|
||||
return d->current->subsurface.below;
|
||||
}
|
||||
|
||||
QList<SubSurfaceInterface *> SurfaceInterface::above() const
|
||||
{
|
||||
return d->current.subsurface.above;
|
||||
return d->current->subsurface.above;
|
||||
}
|
||||
|
||||
SubSurfaceInterface *SurfaceInterface::subSurface() const
|
||||
|
@ -888,11 +908,11 @@ QRectF SurfaceInterface::boundingRect() const
|
|||
{
|
||||
QRectF rect(QPoint(0, 0), size());
|
||||
|
||||
for (const SubSurfaceInterface *subSurface : std::as_const(d->current.subsurface.below)) {
|
||||
for (const SubSurfaceInterface *subSurface : std::as_const(d->current->subsurface.below)) {
|
||||
const SurfaceInterface *childSurface = subSurface->surface();
|
||||
rect |= childSurface->boundingRect().translated(subSurface->position());
|
||||
}
|
||||
for (const SubSurfaceInterface *subSurface : std::as_const(d->current.subsurface.above)) {
|
||||
for (const SubSurfaceInterface *subSurface : std::as_const(d->current->subsurface.above)) {
|
||||
const SurfaceInterface *childSurface = subSurface->surface();
|
||||
rect |= childSurface->boundingRect().translated(subSurface->position());
|
||||
}
|
||||
|
@ -902,22 +922,22 @@ QRectF SurfaceInterface::boundingRect() const
|
|||
|
||||
QPointer<ShadowInterface> SurfaceInterface::shadow() const
|
||||
{
|
||||
return d->current.shadow;
|
||||
return d->current->shadow;
|
||||
}
|
||||
|
||||
QPointer<BlurInterface> SurfaceInterface::blur() const
|
||||
{
|
||||
return d->current.blur;
|
||||
return d->current->blur;
|
||||
}
|
||||
|
||||
QPointer<ContrastInterface> SurfaceInterface::contrast() const
|
||||
{
|
||||
return d->current.contrast;
|
||||
return d->current->contrast;
|
||||
}
|
||||
|
||||
QPointer<SlideInterface> SurfaceInterface::slideOnShowHide() const
|
||||
{
|
||||
return d->current.slide;
|
||||
return d->current->slide;
|
||||
}
|
||||
|
||||
bool SurfaceInterface::isMapped() const
|
||||
|
@ -973,10 +993,10 @@ void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &outputs)
|
|||
}
|
||||
|
||||
d->outputs = outputs;
|
||||
for (auto child : std::as_const(d->current.subsurface.below)) {
|
||||
for (auto child : std::as_const(d->current->subsurface.below)) {
|
||||
child->surface()->setOutputs(outputs);
|
||||
}
|
||||
for (auto child : std::as_const(d->current.subsurface.above)) {
|
||||
for (auto child : std::as_const(d->current->subsurface.above)) {
|
||||
child->surface()->setOutputs(outputs);
|
||||
}
|
||||
}
|
||||
|
@ -987,7 +1007,7 @@ SurfaceInterface *SurfaceInterface::surfaceAt(const QPointF &position)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto it = d->current.subsurface.above.crbegin(); it != d->current.subsurface.above.crend(); ++it) {
|
||||
for (auto it = d->current->subsurface.above.crbegin(); it != d->current->subsurface.above.crend(); ++it) {
|
||||
const SubSurfaceInterface *current = *it;
|
||||
SurfaceInterface *surface = current->surface();
|
||||
if (auto s = surface->surfaceAt(position - current->position())) {
|
||||
|
@ -1000,7 +1020,7 @@ SurfaceInterface *SurfaceInterface::surfaceAt(const QPointF &position)
|
|||
return this;
|
||||
}
|
||||
|
||||
for (auto it = d->current.subsurface.below.crbegin(); it != d->current.subsurface.below.crend(); ++it) {
|
||||
for (auto it = d->current->subsurface.below.crbegin(); it != d->current->subsurface.below.crend(); ++it) {
|
||||
const SubSurfaceInterface *current = *it;
|
||||
SurfaceInterface *surface = current->surface();
|
||||
if (auto s = surface->surfaceAt(position - current->position())) {
|
||||
|
@ -1018,7 +1038,7 @@ SurfaceInterface *SurfaceInterface::inputSurfaceAt(const QPointF &position)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto it = d->current.subsurface.above.crbegin(); it != d->current.subsurface.above.crend(); ++it) {
|
||||
for (auto it = d->current->subsurface.above.crbegin(); it != d->current->subsurface.above.crend(); ++it) {
|
||||
const SubSurfaceInterface *current = *it;
|
||||
auto surface = current->surface();
|
||||
if (auto s = surface->inputSurfaceAt(position - current->position())) {
|
||||
|
@ -1031,7 +1051,7 @@ SurfaceInterface *SurfaceInterface::inputSurfaceAt(const QPointF &position)
|
|||
return this;
|
||||
}
|
||||
|
||||
for (auto it = d->current.subsurface.below.crbegin(); it != d->current.subsurface.below.crend(); ++it) {
|
||||
for (auto it = d->current->subsurface.below.crbegin(); it != d->current->subsurface.below.crend(); ++it) {
|
||||
const SubSurfaceInterface *current = *it;
|
||||
auto surface = current->surface();
|
||||
if (auto s = surface->inputSurfaceAt(position - current->position())) {
|
||||
|
@ -1064,7 +1084,7 @@ LinuxDmaBufV1Feedback *SurfaceInterface::dmabufFeedbackV1() const
|
|||
|
||||
KWin::ContentType SurfaceInterface::contentType() const
|
||||
{
|
||||
return d->current.contentType;
|
||||
return d->current->contentType;
|
||||
}
|
||||
|
||||
QPointF SurfaceInterface::mapToBuffer(const QPointF &point) const
|
||||
|
@ -1126,7 +1146,7 @@ QPointF SurfaceInterface::toSurfaceLocal(const QPointF &point) const
|
|||
|
||||
PresentationHint SurfaceInterface::presentationHint() const
|
||||
{
|
||||
return d->current.presentationHint;
|
||||
return d->current->presentationHint;
|
||||
}
|
||||
|
||||
void SurfaceInterface::setPreferredBufferScale(qreal scale)
|
||||
|
@ -1143,10 +1163,10 @@ void SurfaceInterface::setPreferredBufferScale(qreal scale)
|
|||
d->send_preferred_buffer_scale(std::ceil(scale));
|
||||
}
|
||||
|
||||
for (auto child : qAsConst(d->current.subsurface.below)) {
|
||||
for (auto child : qAsConst(d->current->subsurface.below)) {
|
||||
child->surface()->setPreferredBufferScale(scale);
|
||||
}
|
||||
for (auto child : qAsConst(d->current.subsurface.above)) {
|
||||
for (auto child : qAsConst(d->current->subsurface.above)) {
|
||||
child->surface()->setPreferredBufferScale(scale);
|
||||
}
|
||||
}
|
||||
|
@ -1162,10 +1182,10 @@ void SurfaceInterface::setPreferredBufferTransform(KWin::OutputTransform transfo
|
|||
d->send_preferred_buffer_transform(uint32_t(transform.kind()));
|
||||
}
|
||||
|
||||
for (auto child : qAsConst(d->current.subsurface.below)) {
|
||||
for (auto child : qAsConst(d->current->subsurface.below)) {
|
||||
child->surface()->setPreferredBufferTransform(transform);
|
||||
}
|
||||
for (auto child : qAsConst(d->current.subsurface.above)) {
|
||||
for (auto child : qAsConst(d->current->subsurface.above)) {
|
||||
child->surface()->setPreferredBufferTransform(transform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -430,11 +430,64 @@ Q_SIGNALS:
|
|||
*/
|
||||
void committed();
|
||||
|
||||
/**
|
||||
* This signal is emitted when a surface commit with the specified \a serial has been cached
|
||||
* to be applied later.
|
||||
*/
|
||||
void stateStashed(quint32 serial);
|
||||
|
||||
/**
|
||||
* This signal is emitted when the state in a surface commit with the specified \a serial
|
||||
* has been applied.
|
||||
*/
|
||||
void stateApplied(quint32 serial);
|
||||
|
||||
private:
|
||||
std::unique_ptr<SurfaceInterfacePrivate> d;
|
||||
friend class SurfaceInterfacePrivate;
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* The SurfaceExtension class is the base class for wl_surface extensions. The SurfaceExtension
|
||||
* helps with managing extension state and keeping it in sync with the surface state.
|
||||
*/
|
||||
template<typename Commit>
|
||||
class SurfaceExtension : public QObject
|
||||
{
|
||||
public:
|
||||
explicit SurfaceExtension(SurfaceInterface *surface)
|
||||
{
|
||||
connect(surface, &SurfaceInterface::stateStashed, this, &SurfaceExtension::stashState);
|
||||
connect(surface, &SurfaceInterface::stateApplied, this, &SurfaceExtension::applyState);
|
||||
}
|
||||
|
||||
virtual void apply(Commit *commit) = 0;
|
||||
|
||||
Commit pending;
|
||||
QMap<quint32, Commit> stashed;
|
||||
|
||||
private:
|
||||
void stashState(quint32 serial)
|
||||
{
|
||||
Commit stash = std::exchange(pending, Commit{});
|
||||
stashed.insert(serial, stash);
|
||||
}
|
||||
|
||||
void applyState(quint32 serial)
|
||||
{
|
||||
if (!stashed.isEmpty()) {
|
||||
if (stashed.firstKey() == serial) {
|
||||
Commit stash = stashed.take(serial);
|
||||
apply(&stash);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
apply(&pending);
|
||||
pending = Commit{};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace KWaylandServer
|
||||
|
||||
Q_DECLARE_METATYPE(KWaylandServer::SurfaceInterface *)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// Wayland
|
||||
#include "qwayland-server-wayland.h"
|
||||
// C++
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
|
||||
namespace KWaylandServer
|
||||
|
@ -28,8 +29,13 @@ class FractionalScaleV1Interface;
|
|||
|
||||
struct SurfaceState
|
||||
{
|
||||
SurfaceState();
|
||||
|
||||
void mergeInto(SurfaceState *target);
|
||||
|
||||
quint32 serial = 0;
|
||||
quint32 locks = 0;
|
||||
|
||||
QRegion damage = QRegion();
|
||||
QRegion bufferDamage = QRegion();
|
||||
QRegion opaque = QRegion();
|
||||
|
@ -103,14 +109,13 @@ public:
|
|||
void installPointerConstraint(ConfinedPointerV1Interface *confinement);
|
||||
void installIdleInhibitor(IdleInhibitorV1Interface *inhibitor);
|
||||
|
||||
void commitToCache();
|
||||
void commitFromCache();
|
||||
|
||||
void commitSubSurface();
|
||||
QMatrix4x4 buildSurfaceToBufferMatrix();
|
||||
QRectF computeBufferSourceBox() const;
|
||||
void applyState(SurfaceState *next);
|
||||
|
||||
quint32 lockState(SurfaceState *state);
|
||||
void unlockState(quint32 serial);
|
||||
|
||||
bool computeEffectiveMapped() const;
|
||||
void updateEffectiveMapped();
|
||||
|
||||
|
@ -124,9 +129,9 @@ public:
|
|||
CompositorInterface *compositor;
|
||||
SurfaceInterface *q;
|
||||
SurfaceRole *role = nullptr;
|
||||
SurfaceState current;
|
||||
SurfaceState pending;
|
||||
SurfaceState cached;
|
||||
std::unique_ptr<SurfaceState> current;
|
||||
std::unique_ptr<SurfaceState> pending;
|
||||
std::deque<std::unique_ptr<SurfaceState>> stashed;
|
||||
SubSurfaceInterface *subSurface = nullptr;
|
||||
QMatrix4x4 surfaceToBufferMatrix;
|
||||
QSize bufferSize = QSize(0, 0);
|
||||
|
@ -139,7 +144,6 @@ public:
|
|||
KWin::GraphicsBufferRef bufferRef;
|
||||
QRegion bufferDamage;
|
||||
bool mapped = false;
|
||||
bool hasCacheState = false;
|
||||
qreal scaleOverride = 1.;
|
||||
qreal pendingScaleOverride = 1.;
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ public:
|
|||
return m_surface;
|
||||
}
|
||||
|
||||
virtual void commit() = 0;
|
||||
|
||||
static SurfaceRole *get(SurfaceInterface *surface);
|
||||
|
||||
private:
|
||||
|
|
|
@ -74,8 +74,8 @@ TearingControlV1Interface::~TearingControlV1Interface()
|
|||
{
|
||||
if (m_surface) {
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(m_surface);
|
||||
surfacePrivate->pending.presentationHint = PresentationHint::VSync;
|
||||
surfacePrivate->pending.tearingIsSet = true;
|
||||
surfacePrivate->pending->presentationHint = PresentationHint::VSync;
|
||||
surfacePrivate->pending->tearingIsSet = true;
|
||||
surfacePrivate->tearing = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -85,11 +85,11 @@ void TearingControlV1Interface::wp_tearing_control_v1_set_presentation_hint(Reso
|
|||
if (m_surface) {
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(m_surface);
|
||||
if (hint == presentation_hint::presentation_hint_async) {
|
||||
surfacePrivate->pending.presentationHint = PresentationHint::Async;
|
||||
surfacePrivate->pending->presentationHint = PresentationHint::Async;
|
||||
} else {
|
||||
surfacePrivate->pending.presentationHint = PresentationHint::VSync;
|
||||
surfacePrivate->pending->presentationHint = PresentationHint::VSync;
|
||||
}
|
||||
surfacePrivate->pending.tearingIsSet = true;
|
||||
surfacePrivate->pending->tearingIsSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,10 +70,10 @@ void ViewportInterface::wp_viewport_destroy(Resource *resource)
|
|||
{
|
||||
if (surface) {
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface);
|
||||
surfacePrivate->pending.viewport.sourceGeometry = QRectF();
|
||||
surfacePrivate->pending.viewport.sourceGeometryIsSet = true;
|
||||
surfacePrivate->pending.viewport.destinationSize = QSize();
|
||||
surfacePrivate->pending.viewport.destinationSizeIsSet = true;
|
||||
surfacePrivate->pending->viewport.sourceGeometry = QRectF();
|
||||
surfacePrivate->pending->viewport.sourceGeometryIsSet = true;
|
||||
surfacePrivate->pending->viewport.destinationSize = QSize();
|
||||
surfacePrivate->pending->viewport.destinationSizeIsSet = true;
|
||||
}
|
||||
|
||||
wl_resource_destroy(resource->handle);
|
||||
|
@ -93,8 +93,8 @@ void ViewportInterface::wp_viewport_set_source(Resource *resource, wl_fixed_t x_
|
|||
|
||||
if (x == -1 && y == -1 && width == -1 && height == -1) {
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface);
|
||||
surfacePrivate->pending.viewport.sourceGeometry = QRectF();
|
||||
surfacePrivate->pending.viewport.sourceGeometryIsSet = true;
|
||||
surfacePrivate->pending->viewport.sourceGeometry = QRectF();
|
||||
surfacePrivate->pending->viewport.sourceGeometryIsSet = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,8 +104,8 @@ void ViewportInterface::wp_viewport_set_source(Resource *resource, wl_fixed_t x_
|
|||
}
|
||||
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface);
|
||||
surfacePrivate->pending.viewport.sourceGeometry = QRectF(x, y, width, height);
|
||||
surfacePrivate->pending.viewport.sourceGeometryIsSet = true;
|
||||
surfacePrivate->pending->viewport.sourceGeometry = QRectF(x, y, width, height);
|
||||
surfacePrivate->pending->viewport.sourceGeometryIsSet = true;
|
||||
}
|
||||
|
||||
void ViewportInterface::wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height)
|
||||
|
@ -117,8 +117,8 @@ void ViewportInterface::wp_viewport_set_destination(Resource *resource, int32_t
|
|||
|
||||
if (width == -1 && height == -1) {
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface);
|
||||
surfacePrivate->pending.viewport.destinationSize = QSize();
|
||||
surfacePrivate->pending.viewport.destinationSizeIsSet = true;
|
||||
surfacePrivate->pending->viewport.destinationSize = QSize();
|
||||
surfacePrivate->pending->viewport.destinationSizeIsSet = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -128,8 +128,8 @@ void ViewportInterface::wp_viewport_set_destination(Resource *resource, int32_t
|
|||
}
|
||||
|
||||
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface);
|
||||
surfacePrivate->pending.viewport.destinationSize = QSize(width, height);
|
||||
surfacePrivate->pending.viewport.destinationSizeIsSet = true;
|
||||
surfacePrivate->pending->viewport.destinationSize = QSize(width, height);
|
||||
surfacePrivate->pending->viewport.destinationSizeIsSet = true;
|
||||
}
|
||||
|
||||
ViewporterInterface::ViewporterInterface(Display *display, QObject *parent)
|
||||
|
|
|
@ -142,7 +142,6 @@ void XdgSurfaceInterfacePrivate::unassignRole()
|
|||
{
|
||||
toplevel = nullptr;
|
||||
popup = nullptr;
|
||||
current = nullptr;
|
||||
pending = nullptr;
|
||||
}
|
||||
|
||||
|
@ -150,46 +149,40 @@ void XdgSurfaceInterfacePrivate::assignRole(XdgToplevelInterface *toplevel)
|
|||
{
|
||||
this->toplevel = toplevel;
|
||||
|
||||
XdgSurfaceRole<XdgToplevelState> *role = XdgToplevelInterfacePrivate::get(toplevel);
|
||||
current = &role->current.base;
|
||||
pending = &role->pending.base;
|
||||
XdgSurfaceRole<XdgToplevelCommit> *role = XdgToplevelInterfacePrivate::get(toplevel);
|
||||
pending = &role->pending;
|
||||
}
|
||||
|
||||
void XdgSurfaceInterfacePrivate::assignRole(XdgPopupInterface *popup)
|
||||
{
|
||||
this->popup = popup;
|
||||
|
||||
XdgSurfaceRole<XdgPopupState> *role = XdgPopupInterfacePrivate::get(popup);
|
||||
current = &role->current.base;
|
||||
pending = &role->pending.base;
|
||||
XdgSurfaceRole<XdgPopupCommit> *role = XdgPopupInterfacePrivate::get(popup);
|
||||
pending = &role->pending;
|
||||
}
|
||||
|
||||
void XdgSurfaceInterfacePrivate::applyState(XdgSurfaceState *next)
|
||||
void XdgSurfaceInterfacePrivate::apply(XdgSurfaceCommit *commit)
|
||||
{
|
||||
if (surface->buffer()) {
|
||||
firstBufferAttached = true;
|
||||
}
|
||||
|
||||
if (next->acknowledgedConfigureIsSet) {
|
||||
current->acknowledgedConfigure = next->acknowledgedConfigure;
|
||||
next->acknowledgedConfigureIsSet = false;
|
||||
Q_EMIT q->configureAcknowledged(current->acknowledgedConfigure);
|
||||
if (commit->acknowledgedConfigure.has_value()) {
|
||||
Q_EMIT q->configureAcknowledged(commit->acknowledgedConfigure.value());
|
||||
}
|
||||
|
||||
if (next->windowGeometryIsSet) {
|
||||
current->windowGeometry = next->windowGeometry;
|
||||
next->windowGeometryIsSet = false;
|
||||
Q_EMIT q->windowGeometryChanged(current->windowGeometry);
|
||||
if (commit->windowGeometry.has_value()) {
|
||||
windowGeometry = commit->windowGeometry.value();
|
||||
Q_EMIT q->windowGeometryChanged(windowGeometry);
|
||||
}
|
||||
}
|
||||
|
||||
void XdgSurfaceInterfacePrivate::resetState()
|
||||
void XdgSurfaceInterfacePrivate::reset()
|
||||
{
|
||||
firstBufferAttached = false;
|
||||
isConfigured = false;
|
||||
isInitialized = false;
|
||||
*current = XdgSurfaceState{};
|
||||
*pending = XdgSurfaceState{};
|
||||
windowGeometry = QRect();
|
||||
Q_EMIT q->resetOccurred();
|
||||
}
|
||||
|
||||
|
@ -275,7 +268,6 @@ void XdgSurfaceInterfacePrivate::xdg_surface_set_window_geometry(Resource *resou
|
|||
}
|
||||
|
||||
pending->windowGeometry = QRect(x, y, width, height);
|
||||
pending->windowGeometryIsSet = true;
|
||||
}
|
||||
|
||||
void XdgSurfaceInterfacePrivate::xdg_surface_ack_configure(Resource *resource, uint32_t serial)
|
||||
|
@ -286,7 +278,6 @@ void XdgSurfaceInterfacePrivate::xdg_surface_ack_configure(Resource *resource, u
|
|||
}
|
||||
|
||||
pending->acknowledgedConfigure = serial;
|
||||
pending->acknowledgedConfigureIsSet = true;
|
||||
}
|
||||
|
||||
XdgSurfaceInterface::XdgSurfaceInterface(XdgShellInterface *shell, SurfaceInterface *surface, ::wl_resource *resource)
|
||||
|
@ -333,7 +324,7 @@ bool XdgSurfaceInterface::isConfigured() const
|
|||
|
||||
QRect XdgSurfaceInterface::windowGeometry() const
|
||||
{
|
||||
return d->current->windowGeometry;
|
||||
return d->windowGeometry;
|
||||
}
|
||||
|
||||
XdgSurfaceInterface *XdgSurfaceInterface::get(::wl_resource *resource)
|
||||
|
@ -351,7 +342,7 @@ XdgToplevelInterfacePrivate::XdgToplevelInterfacePrivate(XdgToplevelInterface *t
|
|||
{
|
||||
}
|
||||
|
||||
void XdgToplevelInterfacePrivate::commit()
|
||||
void XdgToplevelInterfacePrivate::apply(XdgToplevelCommit *commit)
|
||||
{
|
||||
auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface);
|
||||
if (xdgSurfacePrivate->firstBufferAttached && !xdgSurfacePrivate->surface->buffer()) {
|
||||
|
@ -359,15 +350,15 @@ void XdgToplevelInterfacePrivate::commit()
|
|||
return;
|
||||
}
|
||||
|
||||
xdgSurfacePrivate->applyState(&pending.base);
|
||||
xdgSurfacePrivate->apply(commit);
|
||||
|
||||
if (current.minimumSize != pending.minimumSize) {
|
||||
current.minimumSize = pending.minimumSize;
|
||||
Q_EMIT q->minimumSizeChanged(current.minimumSize);
|
||||
if (commit->minimumSize && commit->minimumSize != minimumSize) {
|
||||
minimumSize = commit->minimumSize.value();
|
||||
Q_EMIT q->minimumSizeChanged(minimumSize);
|
||||
}
|
||||
if (current.maximumSize != pending.maximumSize) {
|
||||
current.maximumSize = pending.maximumSize;
|
||||
Q_EMIT q->maximumSizeChanged(current.maximumSize);
|
||||
if (commit->maximumSize && commit->maximumSize != maximumSize) {
|
||||
maximumSize = commit->maximumSize.value();
|
||||
Q_EMIT q->maximumSizeChanged(maximumSize);
|
||||
}
|
||||
|
||||
if (!xdgSurfacePrivate->isInitialized) {
|
||||
|
@ -379,12 +370,14 @@ void XdgToplevelInterfacePrivate::commit()
|
|||
void XdgToplevelInterfacePrivate::reset()
|
||||
{
|
||||
auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface);
|
||||
xdgSurfacePrivate->resetState();
|
||||
xdgSurfacePrivate->reset();
|
||||
|
||||
windowTitle = QString();
|
||||
windowClass = QString();
|
||||
current = XdgToplevelState{};
|
||||
pending = XdgToplevelState{};
|
||||
minimumSize = QSize();
|
||||
maximumSize = QSize();
|
||||
pending = XdgToplevelCommit{};
|
||||
stashed.clear();
|
||||
|
||||
Q_EMIT q->resetOccurred();
|
||||
}
|
||||
|
@ -574,12 +567,12 @@ QString XdgToplevelInterface::windowClass() const
|
|||
|
||||
QSize XdgToplevelInterface::minimumSize() const
|
||||
{
|
||||
return d->current.minimumSize.isEmpty() ? QSize(0, 0) : d->current.minimumSize;
|
||||
return d->minimumSize.isEmpty() ? QSize(0, 0) : d->minimumSize;
|
||||
}
|
||||
|
||||
QSize XdgToplevelInterface::maximumSize() const
|
||||
{
|
||||
return d->current.maximumSize.isEmpty() ? QSize(INT_MAX, INT_MAX) : d->current.maximumSize;
|
||||
return d->maximumSize.isEmpty() ? QSize(INT_MAX, INT_MAX) : d->maximumSize;
|
||||
}
|
||||
|
||||
quint32 XdgToplevelInterface::sendConfigure(const QSize &size, const States &states)
|
||||
|
@ -693,7 +686,7 @@ XdgPopupInterfacePrivate::XdgPopupInterfacePrivate(XdgPopupInterface *popup, Xdg
|
|||
{
|
||||
}
|
||||
|
||||
void XdgPopupInterfacePrivate::commit()
|
||||
void XdgPopupInterfacePrivate::apply(XdgPopupCommit *commit)
|
||||
{
|
||||
if (!parentSurface) {
|
||||
auto shellPrivate = XdgShellInterfacePrivate::get(xdgSurface->shell());
|
||||
|
@ -709,7 +702,7 @@ void XdgPopupInterfacePrivate::commit()
|
|||
return;
|
||||
}
|
||||
|
||||
xdgSurfacePrivate->applyState(&pending.base);
|
||||
xdgSurfacePrivate->apply(commit);
|
||||
|
||||
if (!xdgSurfacePrivate->isInitialized) {
|
||||
Q_EMIT q->initializeRequested();
|
||||
|
@ -720,7 +713,9 @@ void XdgPopupInterfacePrivate::commit()
|
|||
void XdgPopupInterfacePrivate::reset()
|
||||
{
|
||||
auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface);
|
||||
xdgSurfacePrivate->resetState();
|
||||
pending = XdgPopupCommit{};
|
||||
stashed.clear();
|
||||
xdgSurfacePrivate->reset();
|
||||
}
|
||||
|
||||
void XdgPopupInterfacePrivate::xdg_popup_destroy_resource(Resource *resource)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "qwayland-server-xdg-shell.h"
|
||||
#include "xdgshell_interface.h"
|
||||
|
||||
#include "surface_interface.h"
|
||||
#include "surface_interface_p.h"
|
||||
#include "surfacerole_p.h"
|
||||
|
||||
namespace KWaylandServer
|
||||
|
@ -83,37 +83,31 @@ protected:
|
|||
void xdg_positioner_set_parent_configure(Resource *resource, uint32_t serial) override;
|
||||
};
|
||||
|
||||
struct XdgSurfaceState
|
||||
struct XdgSurfaceCommit
|
||||
{
|
||||
QRect windowGeometry;
|
||||
quint32 acknowledgedConfigure;
|
||||
bool acknowledgedConfigureIsSet = false;
|
||||
bool windowGeometryIsSet = false;
|
||||
std::optional<QRect> windowGeometry;
|
||||
std::optional<quint32> acknowledgedConfigure;
|
||||
};
|
||||
|
||||
struct XdgToplevelState
|
||||
struct XdgToplevelCommit : XdgSurfaceCommit
|
||||
{
|
||||
XdgSurfaceState base;
|
||||
QSize minimumSize;
|
||||
QSize maximumSize;
|
||||
std::optional<QSize> minimumSize;
|
||||
std::optional<QSize> maximumSize;
|
||||
};
|
||||
|
||||
struct XdgPopupState
|
||||
struct XdgPopupCommit : XdgSurfaceCommit
|
||||
{
|
||||
XdgSurfaceState base;
|
||||
};
|
||||
|
||||
template<typename State>
|
||||
class XdgSurfaceRole : public SurfaceRole
|
||||
template<typename Commit>
|
||||
class XdgSurfaceRole : public SurfaceRole, public SurfaceExtension<Commit>
|
||||
{
|
||||
public:
|
||||
XdgSurfaceRole(SurfaceInterface *surface, const QByteArray &name)
|
||||
: SurfaceRole(surface, name)
|
||||
, SurfaceExtension<Commit>(surface)
|
||||
{
|
||||
}
|
||||
|
||||
State pending;
|
||||
State current;
|
||||
};
|
||||
|
||||
class XdgSurfaceInterfacePrivate : public QtWaylandServer::xdg_surface
|
||||
|
@ -121,22 +115,22 @@ class XdgSurfaceInterfacePrivate : public QtWaylandServer::xdg_surface
|
|||
public:
|
||||
XdgSurfaceInterfacePrivate(XdgSurfaceInterface *xdgSurface);
|
||||
|
||||
void applyState(XdgSurfaceState *next);
|
||||
void resetState();
|
||||
void apply(XdgSurfaceCommit *commit);
|
||||
void reset();
|
||||
|
||||
void unassignRole();
|
||||
void assignRole(XdgToplevelInterface *toplevel);
|
||||
void assignRole(XdgPopupInterface *popup);
|
||||
|
||||
// These two point into XdgSurfaceRole's state and are valid as long as a role is assigned.
|
||||
XdgSurfaceState *current = nullptr;
|
||||
XdgSurfaceState *pending = nullptr;
|
||||
XdgSurfaceCommit *pending = nullptr;
|
||||
|
||||
XdgSurfaceInterface *q;
|
||||
XdgShellInterface *shell = nullptr;
|
||||
QPointer<XdgToplevelInterface> toplevel;
|
||||
QPointer<XdgPopupInterface> popup;
|
||||
QPointer<SurfaceInterface> surface;
|
||||
QRect windowGeometry;
|
||||
bool firstBufferAttached = false;
|
||||
bool isConfigured = false;
|
||||
bool isInitialized = false;
|
||||
|
@ -152,12 +146,12 @@ protected:
|
|||
void xdg_surface_ack_configure(Resource *resource, uint32_t serial) override;
|
||||
};
|
||||
|
||||
class XdgToplevelInterfacePrivate : public XdgSurfaceRole<XdgToplevelState>, public QtWaylandServer::xdg_toplevel
|
||||
class XdgToplevelInterfacePrivate : public XdgSurfaceRole<XdgToplevelCommit>, public QtWaylandServer::xdg_toplevel
|
||||
{
|
||||
public:
|
||||
XdgToplevelInterfacePrivate(XdgToplevelInterface *toplevel, XdgSurfaceInterface *surface);
|
||||
|
||||
void commit() override;
|
||||
void apply(XdgToplevelCommit *commit) override;
|
||||
void reset();
|
||||
|
||||
static XdgToplevelInterfacePrivate *get(XdgToplevelInterface *toplevel);
|
||||
|
@ -169,6 +163,8 @@ public:
|
|||
XdgSurfaceInterface *xdgSurface;
|
||||
QString windowTitle;
|
||||
QString windowClass;
|
||||
QSize minimumSize;
|
||||
QSize maximumSize;
|
||||
|
||||
protected:
|
||||
void xdg_toplevel_destroy_resource(Resource *resource) override;
|
||||
|
@ -188,14 +184,14 @@ protected:
|
|||
void xdg_toplevel_set_minimized(Resource *resource) override;
|
||||
};
|
||||
|
||||
class XdgPopupInterfacePrivate : public XdgSurfaceRole<XdgPopupState>, public QtWaylandServer::xdg_popup
|
||||
class XdgPopupInterfacePrivate : public XdgSurfaceRole<XdgPopupCommit>, public QtWaylandServer::xdg_popup
|
||||
{
|
||||
public:
|
||||
static XdgPopupInterfacePrivate *get(XdgPopupInterface *popup);
|
||||
|
||||
XdgPopupInterfacePrivate(XdgPopupInterface *popup, XdgSurfaceInterface *surface);
|
||||
|
||||
void commit() override;
|
||||
void apply(XdgPopupCommit *commit) override;
|
||||
void reset();
|
||||
|
||||
XdgPopupInterface *q;
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include "xwaylandshell_v1_interface.h"
|
||||
|
||||
#include "display.h"
|
||||
#include "surface_interface_p.h"
|
||||
#include "surfacerole_p.h"
|
||||
#include "surface_interface.h"
|
||||
|
||||
#include "qwayland-server-xwayland-shell-v1.h"
|
||||
|
||||
|
@ -30,23 +30,21 @@ protected:
|
|||
void xwayland_shell_v1_get_xwayland_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) override;
|
||||
};
|
||||
|
||||
struct XwaylandSurfaceV1State
|
||||
struct XwaylandSurfaceV1Commit
|
||||
{
|
||||
std::optional<uint64_t> serial;
|
||||
};
|
||||
|
||||
class XwaylandSurfaceV1InterfacePrivate : public SurfaceRole, public QtWaylandServer::xwayland_surface_v1
|
||||
class XwaylandSurfaceV1InterfacePrivate : public SurfaceRole, public SurfaceExtension<XwaylandSurfaceV1Commit>, public QtWaylandServer::xwayland_surface_v1
|
||||
{
|
||||
public:
|
||||
XwaylandSurfaceV1InterfacePrivate(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version, XwaylandSurfaceV1Interface *q);
|
||||
|
||||
void commit() override;
|
||||
void apply(XwaylandSurfaceV1Commit *commit) override;
|
||||
|
||||
XwaylandSurfaceV1Interface *q;
|
||||
XwaylandShellV1Interface *shell;
|
||||
|
||||
XwaylandSurfaceV1State current;
|
||||
XwaylandSurfaceV1State pending;
|
||||
std::optional<uint64_t> serial;
|
||||
|
||||
protected:
|
||||
void xwayland_surface_v1_destroy_resource(Resource *resource) override;
|
||||
|
@ -82,16 +80,17 @@ void XwaylandShellV1InterfacePrivate::xwayland_shell_v1_get_xwayland_surface(Res
|
|||
|
||||
XwaylandSurfaceV1InterfacePrivate::XwaylandSurfaceV1InterfacePrivate(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version, XwaylandSurfaceV1Interface *q)
|
||||
: SurfaceRole(surface, QByteArrayLiteral("xwayland_surface_v1"))
|
||||
, SurfaceExtension(surface)
|
||||
, QtWaylandServer::xwayland_surface_v1(client, id, version)
|
||||
, q(q)
|
||||
, shell(shell)
|
||||
{
|
||||
}
|
||||
|
||||
void XwaylandSurfaceV1InterfacePrivate::commit()
|
||||
void XwaylandSurfaceV1InterfacePrivate::apply(XwaylandSurfaceV1Commit *commit)
|
||||
{
|
||||
if (pending.serial.has_value()) {
|
||||
current.serial = std::exchange(pending.serial, std::nullopt);
|
||||
if (commit->serial.has_value()) {
|
||||
serial = commit->serial;
|
||||
Q_EMIT shell->surfaceAssociated(q);
|
||||
}
|
||||
}
|
||||
|
@ -109,9 +108,9 @@ void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_set_serial(Resource
|
|||
return;
|
||||
}
|
||||
|
||||
if (current.serial.has_value()) {
|
||||
if (this->serial.has_value()) {
|
||||
wl_resource_post_error(resource->handle, error_already_associated,
|
||||
"xwayland_surface_v1 already has a serial assigned to it: %" PRIu64, current.serial.value());
|
||||
"xwayland_surface_v1 already has a serial assigned to it: %" PRIu64, this->serial.value());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -159,7 +158,7 @@ SurfaceInterface *XwaylandSurfaceV1Interface::surface() const
|
|||
|
||||
std::optional<uint64_t> XwaylandSurfaceV1Interface::serial() const
|
||||
{
|
||||
return d->current.serial;
|
||||
return d->serial;
|
||||
}
|
||||
|
||||
} // namespace KWaylandServer
|
||||
|
|
Loading…
Reference in a new issue