6#include <QtWaylandCompositor/QWaylandCompositor>
7#include <QtWaylandCompositor/QWaylandWlShellSurface>
8#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem>
9#include <QtWaylandCompositor/QWaylandSeat>
16 : QWaylandQuickShellIntegration(item)
18 , m_shellSurface(qobject_cast<QWaylandWlShellSurface *>(item->shellSurface()))
20 m_item->setSurface(m_shellSurface->surface());
21 connect(m_shellSurface.data(), &QWaylandWlShellSurface::startMove,
this, &WlShellIntegration::handleStartMove);
22 connect(m_shellSurface.data(), &QWaylandWlShellSurface::startResize,
this, &WlShellIntegration::handleStartResize);
23 connect(m_shellSurface->surface(), &QWaylandSurface::redraw,
this, &WlShellIntegration::handleRedraw);
24 connect(m_shellSurface->surface(), &QWaylandSurface::offsetForNextFrame,
this, &WlShellIntegration::adjustOffsetForNextFrame);
25 connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged,
this, &WlShellIntegration::handleSurfaceHasContentChanged);
26 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setDefaultToplevel,
this, &WlShellIntegration::handleSetDefaultTopLevel);
27 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setTransient,
this, &WlShellIntegration::handleSetTransient);
28 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setMaximized,
this, &WlShellIntegration::handleSetMaximized);
29 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setFullScreen,
this, &WlShellIntegration::handleSetFullScreen);
30 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setPopup,
this, &WlShellIntegration::handleSetPopup);
31 connect(m_shellSurface.data(), &QWaylandWlShellSurface::destroyed,
this, &WlShellIntegration::handleShellSurfaceDestroyed);
36 m_item->setSurface(
nullptr);
41 grabberState = GrabberState::Move;
42 moveState.seat = seat;
43 moveState.initialized =
false;
46void WlShellIntegration::handleStartResize(QWaylandSeat *seat, QWaylandWlShellSurface::ResizeEdge edges)
48 grabberState = GrabberState::Resize;
49 resizeState.seat = seat;
50 resizeState.resizeEdges = edges;
51 resizeState.initialSize = m_shellSurface->surface()->destinationSize();
52 resizeState.initialized =
false;
58 if (m_shellSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus)
64 nextState = State::Windowed;
69 nonwindowedState.output =
nullptr;
70 disconnect(nonwindowedState.sizeChangedConnection);
73void WlShellIntegration::handleSetTransient(QWaylandSurface *parentSurface,
const QPoint &relativeToParent,
bool inactive)
75 Q_UNUSED(parentSurface);
76 Q_UNUSED(relativeToParent);
79 if (m_shellSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus && !inactive)
85 if (!m_item->view()->isPrimary())
88 if (currentState == State::Maximized)
91 QWaylandOutput *designatedOutput = output ? output : m_item->view()->output();
92 if (!designatedOutput)
95 if (currentState == State::Windowed)
96 normalPosition = m_item->moveItem()->position();
98 nextState = State::Maximized;
99 finalPosition = designatedOutput->position() + designatedOutput->availableGeometry().topLeft();
102 disconnect(nonwindowedState.sizeChangedConnection);
103 nonwindowedState.output = designatedOutput;
104 nonwindowedState.sizeChangedConnection = connect(designatedOutput, &QWaylandOutput::availableGeometryChanged,
this, &WlShellIntegration::handleMaximizedSizeChanged);
105 handleMaximizedSizeChanged();
113 if (nextState == State::Maximized) {
114 QWaylandOutput *designatedOutput = nonwindowedState.output;
115 auto scaleFactor = designatedOutput->scaleFactor();
116 m_shellSurface->sendConfigure(designatedOutput->availableGeometry().size() / scaleFactor, QWaylandWlShellSurface::NoneEdge);
120void WlShellIntegration::handleSetFullScreen(QWaylandWlShellSurface::FullScreenMethod method, uint framerate, QWaylandOutput *output)
125 if (!m_item->view()->isPrimary())
128 if (currentState == State::FullScreen)
131 QWaylandOutput *designatedOutput = output ? output : m_item->view()->output();
132 if (!designatedOutput)
135 if (currentState == State::Windowed)
136 normalPosition = m_item->moveItem()->position();
138 nextState = State::FullScreen;
139 finalPosition = designatedOutput->position();
142 disconnect(nonwindowedState.sizeChangedConnection);
143 nonwindowedState.output = designatedOutput;
144 nonwindowedState.sizeChangedConnection = connect(designatedOutput, &QWaylandOutput::geometryChanged,
this, &WlShellIntegration::handleFullScreenSizeChanged);
145 handleFullScreenSizeChanged();
153 if (nextState == State::FullScreen) {
154 QWaylandOutput *designatedOutput = nonwindowedState.output;
155 m_shellSurface->sendConfigure(designatedOutput->geometry().size(), QWaylandWlShellSurface::NoneEdge);
159void WlShellIntegration::handleSetPopup(QWaylandSeat *seat, QWaylandSurface *parent,
const QPoint &relativeToParent)
164 QWaylandQuickShellSurfaceItem *parentItem =
nullptr;
165 const auto views = parent->views();
166 for (QWaylandView *view : views) {
167 if (view->output() == m_item->view()->output()) {
168 QWaylandQuickShellSurfaceItem *item = qobject_cast<QWaylandQuickShellSurfaceItem*>(view->renderObject());
180 QQmlListProperty<QQuickTransform> t = m_item->transform();
182 m_item->setRotation(0);
183 m_item->setScale(1.0);
184 m_item->setPosition(m_item->mapFromSurface(relativeToParent));
185 m_item->setParentItem(parentItem);
189 auto shell = m_shellSurface->shell();
190 QWaylandQuickShellEventFilter::startFilter(m_shellSurface->surface()->client(), [shell]() {
191 shell->closeAllPopups();
194 QObject::connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged,
195 this, &WlShellIntegration::handleSurfaceHasContentChanged);
200 handlePopupRemoved();
202 QObject::disconnect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged,
203 this, &WlShellIntegration::handleSurfaceHasContentChanged);
208 if (!m_shellSurface || m_shellSurface->shell()->mappedPopups().isEmpty())
209 QWaylandQuickShellEventFilter::cancelFilter();
215 return m_item->window() ? m_item->window()->devicePixelRatio() : 1;
221 handlePopupRemoved();
224 nonwindowedState.output =
nullptr;
225 disconnect(nonwindowedState.sizeChangedConnection);
227 m_shellSurface =
nullptr;
232 if (m_shellSurface && m_shellSurface->surface()->destinationSize().isEmpty()
233 && m_shellSurface->windowType() == Qt::WindowType::Popup) {
240 if (currentState == nextState)
243 m_item->moveItem()->setPosition(nextState == State::Windowed ? normalPosition : finalPosition);
244 currentState = nextState;
249 if (!m_item->view()->isPrimary())
252 QQuickItem *moveItem = m_item->moveItem();
253 moveItem->setPosition(moveItem->position() + m_item->mapFromSurface(offset));
258 if (event->type() == QEvent::MouseMove) {
259 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *>(event);
260 return filterMouseMoveEvent(mouseEvent);
261 }
else if (event->type() == QEvent::MouseButtonRelease) {
262 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *>(event);
263 return filterMouseReleaseEvent(mouseEvent);
265 return QWaylandQuickShellIntegration::eventFilter(object, event);
270 if (grabberState == GrabberState::Resize) {
271 Q_ASSERT(resizeState.seat == m_item->compositor()->seatFor(event));
272 if (!resizeState.initialized) {
273 resizeState.initialMousePos = event->scenePosition();
274 resizeState.initialized =
true;
277 float scaleFactor = m_item->view()->output()->scaleFactor();
278 QPointF delta = (event->scenePosition() - resizeState.initialMousePos) / scaleFactor * devicePixelRatio();
279 QSize newSize = m_shellSurface->sizeForResize(resizeState.initialSize, delta, resizeState.resizeEdges);
280 m_shellSurface->sendConfigure(newSize, resizeState.resizeEdges);
281 }
else if (grabberState == GrabberState::Move) {
282 Q_ASSERT(moveState.seat == m_item->compositor()->seatFor(event));
283 QQuickItem *moveItem = m_item->moveItem();
284 if (!moveState.initialized) {
285 moveState.initialOffset = moveItem->mapFromItem(
nullptr, event->scenePosition());
286 moveState.initialized =
true;
289 if (!moveItem->parentItem())
291 QPointF parentPos = moveItem->parentItem()->mapFromItem(
nullptr, event->scenePosition());
292 moveItem->setPosition(parentPos - moveState.initialOffset);
300 if (grabberState != GrabberState::Default) {
301 grabberState = GrabberState::Default;
311#include "moc_qwaylandwlshellintegration_p.cpp"
~WlShellIntegration() override
bool eventFilter(QObject *object, QEvent *event) override
Filters events if this object has been installed as an event filter for the watched object.