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