29 case QWaylandOutput::SubpixelUnknown:
30 return QtWaylandServer::wl_output::subpixel_unknown;
31 case QWaylandOutput::SubpixelNone:
32 return QtWaylandServer::wl_output::subpixel_none;
33 case QWaylandOutput::SubpixelHorizontalRgb:
34 return QtWaylandServer::wl_output::subpixel_horizontal_rgb;
35 case QWaylandOutput::SubpixelHorizontalBgr:
36 return QtWaylandServer::wl_output::subpixel_horizontal_bgr;
37 case QWaylandOutput::SubpixelVerticalRgb:
38 return QtWaylandServer::wl_output::subpixel_vertical_rgb;
39 case QWaylandOutput::SubpixelVerticalBgr:
40 return QtWaylandServer::wl_output::subpixel_vertical_bgr;
45 return QtWaylandServer::wl_output::subpixel_unknown;
51 case QWaylandOutput::Transform90:
52 return QtWaylandServer::wl_output::transform_90;
53 case QWaylandOutput::Transform180:
54 return QtWaylandServer::wl_output::transform_180;
55 case QWaylandOutput::Transform270:
56 return QtWaylandServer::wl_output::transform_270;
57 case QWaylandOutput::TransformFlipped:
58 return QtWaylandServer::wl_output::transform_flipped;
59 case QWaylandOutput::TransformFlipped90:
60 return QtWaylandServer::wl_output::transform_flipped_90;
61 case QWaylandOutput::TransformFlipped180:
62 return QtWaylandServer::wl_output::transform_flipped_180;
63 case QWaylandOutput::TransformFlipped270:
64 return QtWaylandServer::wl_output::transform_flipped_270;
69 return QtWaylandServer::wl_output::transform_normal;
80void QWaylandOutputPrivate::output_bind_resource(Resource *resource)
82 sendGeometry(resource);
84 for (
const QWaylandOutputMode &mode : std::as_const(modes))
85 sendMode(resource, mode);
87 maybeSendScale(resource, scaleFactor);
88 maybeSendDone(resource);
112void QWaylandOutputPrivate::sendGeometry(
const Resource *resource)
114 send_geometry(resource->handle,
115 position.x(), position.y(),
116 physicalSize.width(), physicalSize.height(),
117 toWlSubpixel(subpixel), manufacturer, model,
118 toWlTransform(transform));
130void QWaylandOutputPrivate::sendMode(
const Resource *resource,
const QWaylandOutputMode &mode)
133 if (currentMode == modes.indexOf(mode))
134 flags |= QtWaylandServer::wl_output::mode_current;
135 if (preferredMode == modes.indexOf(mode))
136 flags |= QtWaylandServer::wl_output::mode_preferred;
138 send_mode(resource->handle, flags,
139 mode.size().width(), mode.size().height(),
143void QWaylandOutputPrivate::sendModesInfo()
145 const auto resources = resourceMap().values();
146 for (
const Resource *resource : resources) {
147 for (
const QWaylandOutputMode &mode : std::as_const(modes))
148 sendMode(resource, mode);
149 maybeSendDone(resource);
166void QWaylandOutputPrivate::handleWindowPixelSizeChanged()
170 if (sizeFollowsWindow && currentMode < modes.size()) {
171 if (currentMode >= 0) {
172 QWaylandOutputMode &mode = modes[currentMode];
173 mode.setSize(windowPixelSize);
174 emit q->geometryChanged();
175 if (!availableGeometry.isValid())
176 emit q->availableGeometryChanged();
181 int mHzRefreshRate = qFloor(window->screen()->refreshRate() * 1000);
182 QWaylandOutputMode mode(windowPixelSize, mHzRefreshRate);
183 if (mode.isValid()) {
185 q->addMode(mode,
true);
186 q->setCurrentMode(mode);
192void QWaylandOutputPrivate::addView(QWaylandView *view, QWaylandSurface *surface)
194 for (
int i = 0; i < surfaceViews.size(); i++) {
195 if (surface == surfaceViews.at(i).surface) {
196 if (!surfaceViews.at(i).views.contains(view)) {
197 surfaceViews[i].views.append(view);
203 surfaceViews.append(QWaylandSurfaceViewMapper(surface,view));
206void QWaylandOutputPrivate::removeView(QWaylandView *view, QWaylandSurface *surface)
209 for (
int i = 0; i < surfaceViews.size(); i++) {
210 if (surface == surfaceViews.at(i).surface) {
211 bool removed = surfaceViews[i].views.removeOne(view);
212 if (removed && surfaceViews.at(i).views.isEmpty()) {
213 if (surfaceViews.at(i).has_entered)
214 q->surfaceLeave(surface);
215 surfaceViews.remove(i);
220 qWarning(
"%s Could not find view %p for surface %p to remove. Possible invalid state", Q_FUNC_INFO, view, surface);
280QWaylandOutput::~QWaylandOutput()
284 const auto surfaceViews = d->surfaceViews;
285 for (
const QWaylandSurfaceViewMapper &surfacemapper : surfaceViews) {
286 for (QWaylandView *view : surfacemapper.views) {
287 if (view->output() ==
this)
288 view->setOutput(
nullptr);
293 QWaylandCompositorPrivate::get(d->compositor)->removeOutput(
this);
299void QWaylandOutput::initialize()
303 Q_ASSERT(!d->initialized);
304 Q_ASSERT(d->compositor);
305 Q_ASSERT(d->compositor->isCreated());
307 if (!d->window && d->sizeFollowsWindow) {
308 qWarning(
"Setting QWaylandOutput::sizeFollowsWindow without a window has no effect");
313 if (d->window && d->sizeFollowsWindow) {
314 QWaylandOutputMode mode(d->window->size() * d->window->devicePixelRatio(),
315 qFloor(d->window->screen()->refreshRate() * 1000));
316 if (mode.isValid()) {
319 setCurrentMode(mode);
323 QWaylandCompositorPrivate::get(d->compositor)->addOutput(
this);
326 QObjectPrivate::connect(d->window, &QWindow::widthChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
327 QObjectPrivate::connect(d->window, &QWindow::heightChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
328 QObjectPrivate::connect(d->window, &QWindow::screenChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
329 QObjectPrivate::connect(d->window, &QObject::destroyed, d, &QWaylandOutputPrivate::_q_handleWindowDestroyed);
332 d->init(d->compositor->display(), 2);
334 d->initialized =
true;
402void QWaylandOutput::setCompositor(QWaylandCompositor *compositor)
406 if (d->compositor == compositor)
409 if (d->initialized) {
410 qWarning(
"Setting QWaylandCompositor %p on QWaylandOutput %p is not supported after QWaylandOutput has been initialized\n", compositor,
this);
413 if (d->compositor && d->compositor != compositor) {
414 qWarning(
"Possible initialization error. Moving QWaylandOutput %p between compositor instances.\n",
this);
417 d->compositor = compositor;
419 QWaylandCompositorPrivate::get(compositor)->addPolishObject(
this);
568void QWaylandOutput::setCurrentMode(
const QWaylandOutputMode &mode)
572 int index = d->modes.indexOf(mode);
574 qWarning(
"Cannot set an unknown QWaylandOutput mode as current");
578 d->currentMode = index;
580 Q_EMIT currentModeChanged();
581 Q_EMIT geometryChanged();
582 if (!d->availableGeometry.isValid())
583 emit availableGeometryChanged();
636void QWaylandOutput::setAvailableGeometry(
const QRect &availableGeometry)
639 if (d->availableGeometry == availableGeometry)
642 if (availableGeometry.topLeft().x() < 0 || availableGeometry.topLeft().y() < 0)
643 qWarning(
"Available geometry should be a portion of the output");
645 d->availableGeometry = availableGeometry;
647 Q_EMIT availableGeometryChanged();
836void QWaylandOutput::setScaleFactor(
int scale)
839 if (d->scaleFactor == scale)
842 d->scaleFactor = scale;
844 const auto resMap = d->resourceMap();
845 for (QWaylandOutputPrivate::Resource *resource : resMap) {
846 d->maybeSendScale(resource, scale);
847 d->maybeSendDone(resource);
850 Q_EMIT scaleFactorChanged();
926void QWaylandOutput::frameStarted()
930 d->canSendFrameCallbacks =
true;
932 for (
const QWaylandSurfaceViewMapper &surfacemapper : std::as_const(d->surfaceViews)) {
933 if (QWaylandView *primaryView = surfacemapper.maybePrimaryView()) {
934 if (Q_LIKELY(!QWaylandViewPrivate::get(primaryView)->independentFrameCallback))
935 surfacemapper.surface->frameStarted();
943void QWaylandOutput::sendFrameCallbacks()
947 if (Q_UNLIKELY(!d->canSendFrameCallbacks))
950 d->canSendFrameCallbacks =
false;
952 for (
int i = 0; i < d->surfaceViews.size(); i++) {
953 const QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews.at(i);
954 if (surfacemapper.surface && surfacemapper.surface->hasContent()) {
955 if (!surfacemapper.has_entered) {
956 surfaceEnter(surfacemapper.surface);
957 d->surfaceViews[i].has_entered =
true;
959 if (
auto primaryView = surfacemapper.maybePrimaryView()) {
960 if (!QWaylandViewPrivate::get(primaryView)->independentFrameCallback)
961 surfacemapper.surface->sendFrameCallbacks();
965 wl_display_flush_clients(d->compositor->display());