7#include <QtWaylandCompositor/QWaylandCompositor>
8#include <QtWaylandCompositor/QWaylandWlShellSurface>
9#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem>
10#include <QtWaylandCompositor/QWaylandSeat>
17 : QWaylandQuickShellIntegration(item)
19 , m_shellSurface(qobject_cast<QWaylandWlShellSurface *>(item->shellSurface()))
21 m_item->setSurface(m_shellSurface->surface());
22 connect(m_shellSurface.data(), &QWaylandWlShellSurface::startMove,
this, &WlShellIntegration::handleStartMove);
23 connect(m_shellSurface.data(), &QWaylandWlShellSurface::startResize,
this, &WlShellIntegration::handleStartResize);
24 connect(m_shellSurface->surface(), &QWaylandSurface::redraw,
this, &
WlShellIntegration::handleRedraw);
25 connect(m_shellSurface->surface(), &QWaylandSurface::offsetForNextFrame,
this, &WlShellIntegration::adjustOffsetForNextFrame);
26 connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged,
this, &
WlShellIntegration::handleSurfaceHasContentChanged);
27 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setDefaultToplevel,
this, &
WlShellIntegration::handleSetDefaultTopLevel);
28 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setTransient,
this, &WlShellIntegration::handleSetTransient);
29 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setMaximized,
this, &WlShellIntegration::handleSetMaximized);
30 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setFullScreen,
this, &WlShellIntegration::handleSetFullScreen);
31 connect(m_shellSurface.data(), &QWaylandWlShellSurface::setPopup,
this, &WlShellIntegration::handleSetPopup);
32 connect(m_shellSurface.data(), &QWaylandWlShellSurface::destroyed,
this, &
WlShellIntegration::handleShellSurfaceDestroyed);
37 m_item->setSurface(
nullptr);
42 grabberState = GrabberState::Move;
43 moveState.seat = seat;
44 moveState.initialized =
false;
47void WlShellIntegration::handleStartResize(QWaylandSeat *seat, QWaylandWlShellSurface::ResizeEdge edges)
49 grabberState = GrabberState::Resize;
50 resizeState.seat = seat;
51 resizeState.resizeEdges = edges;
52 resizeState.initialSize = m_shellSurface->surface()->destinationSize();
53 resizeState.initialized =
false;
59 if (m_shellSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus)
65 nextState = State::Windowed;
70 nonwindowedState.output =
nullptr;
71 disconnect(nonwindowedState.sizeChangedConnection);
74void WlShellIntegration::handleSetTransient(QWaylandSurface *parentSurface,
const QPoint &relativeToParent,
bool inactive)
76 Q_UNUSED(parentSurface);
77 Q_UNUSED(relativeToParent);
80 if (m_shellSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus && !inactive)
86 if (!m_item->view()->isPrimary())
89 if (currentState == State::Maximized)
92 QWaylandOutput *designatedOutput = output ? output : m_item->view()->output();
93 if (!designatedOutput)
96 if (currentState == State::Windowed)
97 normalPosition = m_item->moveItem()->position();
99 nextState = State::Maximized;
100 finalPosition = designatedOutput->position() + designatedOutput->availableGeometry().topLeft();
103 disconnect(nonwindowedState.sizeChangedConnection);
104 nonwindowedState.output = designatedOutput;
105 nonwindowedState.sizeChangedConnection = connect(designatedOutput, &QWaylandOutput::availableGeometryChanged,
this, &WlShellIntegration::handleMaximizedSizeChanged);
106 handleMaximizedSizeChanged();
114 if (nextState == State::Maximized) {
115 QWaylandOutput *designatedOutput = nonwindowedState.output;
116 auto scaleFactor = designatedOutput->scaleFactor();
117 m_shellSurface->sendConfigure(designatedOutput->availableGeometry().size() / scaleFactor, QWaylandWlShellSurface::NoneEdge);
121void WlShellIntegration::handleSetFullScreen(QWaylandWlShellSurface::FullScreenMethod method, uint framerate, QWaylandOutput *output)
126 if (!m_item->view()->isPrimary())
129 if (currentState == State::FullScreen)
132 QWaylandOutput *designatedOutput = output ? output : m_item->view()->output();
133 if (!designatedOutput)
136 if (currentState == State::Windowed)
137 normalPosition = m_item->moveItem()->position();
139 nextState = State::FullScreen;
140 finalPosition = designatedOutput->position();
143 disconnect(nonwindowedState.sizeChangedConnection);
144 nonwindowedState.output = designatedOutput;
145 nonwindowedState.sizeChangedConnection = connect(designatedOutput, &QWaylandOutput::geometryChanged,
this, &WlShellIntegration::handleFullScreenSizeChanged);
146 handleFullScreenSizeChanged();
154 if (nextState == State::FullScreen) {
155 QWaylandOutput *designatedOutput = nonwindowedState.output;
156 m_shellSurface->sendConfigure(designatedOutput->geometry().size(), QWaylandWlShellSurface::NoneEdge);
160void WlShellIntegration::handleSetPopup(QWaylandSeat *seat, QWaylandSurface *parent,
const QPoint &relativeToParent)
165 QWaylandQuickShellSurfaceItem *parentItem =
nullptr;
166 const auto views = parent->views();
167 for (QWaylandView *view : views) {
168 if (view->output() == m_item->view()->output()) {
169 QWaylandQuickShellSurfaceItem *item = qobject_cast<QWaylandQuickShellSurfaceItem*>(view->renderObject());
181 QQmlListProperty<QQuickTransform> t = m_item->transform();
183 m_item->setRotation(0);
184 m_item->setScale(1.0);
185 m_item->setPosition(m_item->mapFromSurface(relativeToParent));
186 m_item->setParentItem(parentItem);
190 auto shell = m_shellSurface->shell();
191 QWaylandQuickShellEventFilter::startFilter(m_shellSurface->surface()->client(), [shell]() {
192 shell->closeAllPopups();
195 QObject::connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged,
196 this, &WlShellIntegration::handleSurfaceHasContentChanged);
201 handlePopupRemoved();
203 QObject::disconnect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged,
204 this, &WlShellIntegration::handleSurfaceHasContentChanged);
209 if (!m_shellSurface || m_shellSurface->shell()->mappedPopups().isEmpty())
210 QWaylandQuickShellEventFilter::cancelFilter();
216 return m_item->window() ? m_item->window()->devicePixelRatio() : 1;
222 handlePopupRemoved();
225 nonwindowedState.output =
nullptr;
226 disconnect(nonwindowedState.sizeChangedConnection);
228 m_shellSurface =
nullptr;
233 if (m_shellSurface && m_shellSurface->surface()->destinationSize().isEmpty()
234 && m_shellSurface->windowType() == Qt::WindowType::Popup) {
241 if (currentState == nextState)
244 m_item->moveItem()->setPosition(nextState == State::Windowed ? normalPosition : finalPosition);
245 currentState = nextState;
250 if (!m_item->view()->isPrimary())
253 QQuickItem *moveItem = m_item->moveItem();
254 moveItem->setPosition(moveItem->position() + m_item->mapFromSurface(offset));
259 if (event->type() == QEvent::MouseMove) {
260 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *>(event);
261 return filterMouseMoveEvent(mouseEvent);
262 }
else if (event->type() == QEvent::MouseButtonRelease) {
263 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *>(event);
264 return filterMouseReleaseEvent(mouseEvent);
266 return QWaylandQuickShellIntegration::eventFilter(object, event);
271 if (grabberState == GrabberState::Resize) {
272 Q_ASSERT(resizeState.seat == m_item->compositor()->seatFor(event));
273 if (!resizeState.initialized) {
274 resizeState.initialMousePos = event->scenePosition();
275 resizeState.initialized =
true;
278 float scaleFactor = m_item->view()->output()->scaleFactor();
279 QPointF delta = (event->scenePosition() - resizeState.initialMousePos) / scaleFactor * devicePixelRatio();
280 QSize newSize = m_shellSurface->sizeForResize(resizeState.initialSize, delta, resizeState.resizeEdges);
281 m_shellSurface->sendConfigure(newSize, resizeState.resizeEdges);
282 }
else if (grabberState == GrabberState::Move) {
283 Q_ASSERT(moveState.seat == m_item->compositor()->seatFor(event));
284 QQuickItem *moveItem = m_item->moveItem();
285 if (!moveState.initialized) {
286 moveState.initialOffset = moveItem->mapFromItem(
nullptr, event->scenePosition());
287 moveState.initialized =
true;
290 if (!moveItem->parentItem())
292 QPointF parentPos = moveItem->parentItem()->mapFromItem(
nullptr, event->scenePosition());
293 moveItem->setPosition(parentPos - moveState.initialOffset);
301 if (grabberState != GrabberState::Default) {
302 grabberState = GrabberState::Default;
312#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.
Combined button and popup list for selecting options.