28 case QWaylandOutput::SubpixelUnknown:
29 return QtWaylandServer::wl_output::subpixel_unknown;
30 case QWaylandOutput::SubpixelNone:
31 return QtWaylandServer::wl_output::subpixel_none;
32 case QWaylandOutput::SubpixelHorizontalRgb:
33 return QtWaylandServer::wl_output::subpixel_horizontal_rgb;
34 case QWaylandOutput::SubpixelHorizontalBgr:
35 return QtWaylandServer::wl_output::subpixel_horizontal_bgr;
36 case QWaylandOutput::SubpixelVerticalRgb:
37 return QtWaylandServer::wl_output::subpixel_vertical_rgb;
38 case QWaylandOutput::SubpixelVerticalBgr:
39 return QtWaylandServer::wl_output::subpixel_vertical_bgr;
44 return QtWaylandServer::wl_output::subpixel_unknown;
50 case QWaylandOutput::Transform90:
51 return QtWaylandServer::wl_output::transform_90;
52 case QWaylandOutput::Transform180:
53 return QtWaylandServer::wl_output::transform_180;
54 case QWaylandOutput::Transform270:
55 return QtWaylandServer::wl_output::transform_270;
56 case QWaylandOutput::TransformFlipped:
57 return QtWaylandServer::wl_output::transform_flipped;
58 case QWaylandOutput::TransformFlipped90:
59 return QtWaylandServer::wl_output::transform_flipped_90;
60 case QWaylandOutput::TransformFlipped180:
61 return QtWaylandServer::wl_output::transform_flipped_180;
62 case QWaylandOutput::TransformFlipped270:
63 return QtWaylandServer::wl_output::transform_flipped_270;
68 return QtWaylandServer::wl_output::transform_normal;
79void QWaylandOutputPrivate::output_bind_resource(Resource *resource)
81 sendGeometry(resource);
83 for (
const QWaylandOutputMode &mode : modes)
84 sendMode(resource, mode);
86 maybeSendScale(resource, scaleFactor);
87 maybeSendDone(resource);
111void QWaylandOutputPrivate::sendGeometry(
const Resource *resource)
113 send_geometry(resource->handle,
114 position.x(), position.y(),
115 physicalSize.width(), physicalSize.height(),
116 toWlSubpixel(subpixel), manufacturer, model,
117 toWlTransform(transform));
128void QWaylandOutputPrivate::sendMode(
const Resource *resource,
const QWaylandOutputMode &mode)
131 if (currentMode == modes.indexOf(mode))
132 flags |= QtWaylandServer::wl_output::mode_current;
133 if (preferredMode == modes.indexOf(mode))
134 flags |= QtWaylandServer::wl_output::mode_preferred;
136 send_mode(resource->handle, flags,
137 mode.size().width(), mode.size().height(),
141void QWaylandOutputPrivate::sendModesInfo()
143 for (
const Resource *resource : resourceMap().values()) {
144 for (
const QWaylandOutputMode &mode : modes)
145 sendMode(resource, mode);
146 maybeSendDone(resource);
163void QWaylandOutputPrivate::handleWindowPixelSizeChanged()
167 if (sizeFollowsWindow && currentMode < modes.size()) {
168 if (currentMode >= 0) {
169 QWaylandOutputMode &mode = modes[currentMode];
170 mode.setSize(windowPixelSize);
171 emit q->geometryChanged();
172 if (!availableGeometry.isValid())
173 emit q->availableGeometryChanged();
178 int mHzRefreshRate = qFloor(window->screen()->refreshRate() * 1000);
179 QWaylandOutputMode mode(windowPixelSize, mHzRefreshRate);
180 if (mode.isValid()) {
182 q->addMode(mode,
true);
183 q->setCurrentMode(mode);
189void QWaylandOutputPrivate::addView(QWaylandView *view, QWaylandSurface *surface)
191 for (
int i = 0; i < surfaceViews.size(); i++) {
192 if (surface == surfaceViews.at(i).surface) {
193 if (!surfaceViews.at(i).views.contains(view)) {
194 surfaceViews[i].views.append(view);
200 surfaceViews.append(QWaylandSurfaceViewMapper(surface,view));
203void QWaylandOutputPrivate::removeView(QWaylandView *view, QWaylandSurface *surface)
206 for (
int i = 0; i < surfaceViews.size(); i++) {
207 if (surface == surfaceViews.at(i).surface) {
208 bool removed = surfaceViews[i].views.removeOne(view);
209 if (removed && surfaceViews.at(i).views.isEmpty()) {
210 if (surfaceViews.at(i).has_entered)
211 q->surfaceLeave(surface);
212 surfaceViews.remove(i);
217 qWarning(
"%s Could not find view %p for surface %p to remove. Possible invalid state", Q_FUNC_INFO, view, surface);
277QWaylandOutput::~QWaylandOutput()
281 const auto surfaceViews = d->surfaceViews;
282 for (
const QWaylandSurfaceViewMapper &surfacemapper : surfaceViews) {
283 for (QWaylandView *view : surfacemapper.views) {
284 if (view->output() ==
this)
285 view->setOutput(
nullptr);
290 QWaylandCompositorPrivate::get(d->compositor)->removeOutput(
this);
296void QWaylandOutput::initialize()
300 Q_ASSERT(!d->initialized);
301 Q_ASSERT(d->compositor);
302 Q_ASSERT(d->compositor->isCreated());
304 if (!d->window && d->sizeFollowsWindow) {
305 qWarning(
"Setting QWaylandOutput::sizeFollowsWindow without a window has no effect");
310 if (d->window && d->sizeFollowsWindow) {
311 QWaylandOutputMode mode(d->window->size() * d->window->devicePixelRatio(),
312 qFloor(d->window->screen()->refreshRate() * 1000));
313 if (mode.isValid()) {
316 setCurrentMode(mode);
320 QWaylandCompositorPrivate::get(d->compositor)->addOutput(
this);
323 QObjectPrivate::connect(d->window, &QWindow::widthChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
324 QObjectPrivate::connect(d->window, &QWindow::heightChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
325 QObjectPrivate::connect(d->window, &QWindow::screenChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
326 QObjectPrivate::connect(d->window, &QObject::destroyed, d, &QWaylandOutputPrivate::_q_handleWindowDestroyed);
329 d->init(d->compositor->display(), 2);
331 d->initialized =
true;
399void QWaylandOutput::setCompositor(QWaylandCompositor *compositor)
403 if (d->compositor == compositor)
406 if (d->initialized) {
407 qWarning(
"Setting QWaylandCompositor %p on QWaylandOutput %p is not supported after QWaylandOutput has been initialized\n", compositor,
this);
410 if (d->compositor && d->compositor != compositor) {
411 qWarning(
"Possible initialization error. Moving QWaylandOutput %p between compositor instances.\n",
this);
414 d->compositor = compositor;
416 QWaylandCompositorPrivate::get(compositor)->addPolishObject(
this);
565void QWaylandOutput::setCurrentMode(
const QWaylandOutputMode &mode)
569 int index = d->modes.indexOf(mode);
571 qWarning(
"Cannot set an unknown QWaylandOutput mode as current");
575 d->currentMode = index;
577 Q_EMIT currentModeChanged();
578 Q_EMIT geometryChanged();
579 if (!d->availableGeometry.isValid())
580 emit availableGeometryChanged();
633void QWaylandOutput::setAvailableGeometry(
const QRect &availableGeometry)
636 if (d->availableGeometry == availableGeometry)
639 if (availableGeometry.topLeft().x() < 0 || availableGeometry.topLeft().y() < 0)
640 qWarning(
"Available geometry should be a portion of the output");
642 d->availableGeometry = availableGeometry;
644 Q_EMIT availableGeometryChanged();
833void QWaylandOutput::setScaleFactor(
int scale)
836 if (d->scaleFactor == scale)
839 d->scaleFactor = scale;
841 const auto resMap = d->resourceMap();
842 for (QWaylandOutputPrivate::Resource *resource : resMap) {
843 d->maybeSendScale(resource, scale);
844 d->maybeSendDone(resource);
847 Q_EMIT scaleFactorChanged();
923void QWaylandOutput::frameStarted()
927 d->canSendFrameCallbacks =
true;
929 for (
const QWaylandSurfaceViewMapper &surfacemapper : std::as_const(d->surfaceViews)) {
930 if (QWaylandView *primaryView = surfacemapper.maybePrimaryView()) {
931 if (Q_LIKELY(!QWaylandViewPrivate::get(primaryView)->independentFrameCallback))
932 surfacemapper.surface->frameStarted();
940void QWaylandOutput::sendFrameCallbacks()
944 if (Q_UNLIKELY(!d->canSendFrameCallbacks))
947 d->canSendFrameCallbacks =
false;
949 for (
int i = 0; i < d->surfaceViews.size(); i++) {
950 const QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews.at(i);
951 if (surfacemapper.surface && surfacemapper.surface->hasContent()) {
952 if (!surfacemapper.has_entered) {
953 surfaceEnter(surfacemapper.surface);
954 d->surfaceViews[i].has_entered =
true;
956 if (
auto primaryView = surfacemapper.maybePrimaryView()) {
957 if (!QWaylandViewPrivate::get(primaryView)->independentFrameCallback)
958 surfacemapper.surface->sendFrameCallbacks();
962 wl_display_flush_clients(d->compositor->display());