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 if (resource->version() >= 2) {
87 send_scale(resource->handle, scaleFactor);
88 send_done(resource->handle);
113void QWaylandOutputPrivate::sendGeometry(
const Resource *resource)
115 send_geometry(resource->handle,
116 position.x(), position.y(),
117 physicalSize.width(), physicalSize.height(),
118 toWlSubpixel(subpixel), manufacturer, model,
119 toWlTransform(transform));
131void QWaylandOutputPrivate::sendMode(
const Resource *resource,
const QWaylandOutputMode &mode)
134 if (currentMode == modes.indexOf(mode))
135 flags |= QtWaylandServer::wl_output::mode_current;
136 if (preferredMode == modes.indexOf(mode))
137 flags |= QtWaylandServer::wl_output::mode_preferred;
139 send_mode(resource->handle, flags,
140 mode.size().width(), mode.size().height(),
144void QWaylandOutputPrivate::sendModesInfo()
146 for (
const Resource *resource : resourceMap().values()) {
147 for (
const QWaylandOutputMode &mode : modes)
148 sendMode(resource, mode);
149 if (resource->version() >= 2)
150 send_done(resource->handle);
163void QWaylandOutputPrivate::handleWindowPixelSizeChanged()
167 if (sizeFollowsWindow && currentMode <= modes.size() - 1) {
168 if (currentMode >= 0) {
169 QWaylandOutputMode mode = modes.at(currentMode);
170 mode.setSize(windowPixelSize);
171 modes.replace(currentMode, mode);
172 emit q->geometryChanged();
173 if (!availableGeometry.isValid())
174 emit q->availableGeometryChanged();
179 int mHzRefreshRate = qFloor(window->screen()->refreshRate() * 1000);
180 QWaylandOutputMode mode(windowPixelSize, mHzRefreshRate);
181 if (mode.isValid()) {
183 q->addMode(mode,
true);
184 q->setCurrentMode(mode);
190void QWaylandOutputPrivate::addView(QWaylandView *view, QWaylandSurface *surface)
192 for (
int i = 0; i < surfaceViews.size(); i++) {
193 if (surface == surfaceViews.at(i).surface) {
194 if (!surfaceViews.at(i).views.contains(view)) {
195 surfaceViews[i].views.append(view);
201 surfaceViews.append(QWaylandSurfaceViewMapper(surface,view));
204void QWaylandOutputPrivate::removeView(QWaylandView *view, QWaylandSurface *surface)
207 for (
int i = 0; i < surfaceViews.size(); i++) {
208 if (surface == surfaceViews.at(i).surface) {
209 bool removed = surfaceViews[i].views.removeOne(view);
210 if (surfaceViews.at(i).views.isEmpty() && removed) {
211 if (surfaceViews.at(i).has_entered)
212 q->surfaceLeave(surface);
213 surfaceViews.remove(i);
218 qWarning(
"%s Could not find view %p for surface %p to remove. Possible invalid state", Q_FUNC_INFO, view, surface);
288void QWaylandOutput::initialize()
292 Q_ASSERT(!d->initialized);
293 Q_ASSERT(d->compositor);
294 Q_ASSERT(d->compositor->isCreated());
296 if (!d->window && d->sizeFollowsWindow) {
297 qWarning(
"Setting QWaylandOutput::sizeFollowsWindow without a window has no effect");
302 if (d->window && d->sizeFollowsWindow) {
303 QWaylandOutputMode mode(d->window->size() * d->window->devicePixelRatio(),
304 qFloor(d->window->screen()->refreshRate() * 1000));
305 if (mode.isValid()) {
308 setCurrentMode(mode);
312 QWaylandCompositorPrivate::get(d->compositor)->addOutput(
this);
315 QObjectPrivate::connect(d->window, &QWindow::widthChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
316 QObjectPrivate::connect(d->window, &QWindow::heightChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
317 QObjectPrivate::connect(d->window, &QWindow::screenChanged, d, &QWaylandOutputPrivate::_q_handleMaybeWindowPixelSizeChanged);
318 QObjectPrivate::connect(d->window, &QObject::destroyed, d, &QWaylandOutputPrivate::_q_handleWindowDestroyed);
321 d->init(d->compositor->display(), 2);
323 d->initialized =
true;
382void QWaylandOutput::setCompositor(QWaylandCompositor *compositor)
386 if (d->compositor == compositor)
389 if (d->initialized) {
390 qWarning(
"Setting QWaylandCompositor %p on QWaylandOutput %p is not supported after QWaylandOutput has been initialized\n", compositor,
this);
393 if (d->compositor && d->compositor != compositor) {
394 qWarning(
"Possible initialization error. Moving QWaylandOutput %p between compositor instances.\n",
this);
397 d->compositor = compositor;
399 QWaylandCompositorPrivate::get(compositor)->addPolishObject(
this);
547void QWaylandOutput::setCurrentMode(
const QWaylandOutputMode &mode)
551 int index = d->modes.indexOf(mode);
553 qWarning(
"Cannot set an unknown QWaylandOutput mode as current");
557 d->currentMode = index;
559 Q_EMIT currentModeChanged();
560 Q_EMIT geometryChanged();
561 if (!d->availableGeometry.isValid())
562 emit availableGeometryChanged();
615void QWaylandOutput::setAvailableGeometry(
const QRect &availableGeometry)
618 if (d->availableGeometry == availableGeometry)
621 if (availableGeometry.topLeft().x() < 0 || availableGeometry.topLeft().y() < 0)
622 qWarning(
"Available geometry should be a portion of the output");
624 d->availableGeometry = availableGeometry;
626 Q_EMIT availableGeometryChanged();
808void QWaylandOutput::setScaleFactor(
int scale)
811 if (d->scaleFactor == scale)
814 d->scaleFactor = scale;
816 const auto resMap = d->resourceMap();
817 for (QWaylandOutputPrivate::Resource *resource : resMap) {
818 if (resource->version() >= 2) {
819 d->send_scale(resource->handle, scale);
820 d->send_done(resource->handle);
824 Q_EMIT scaleFactorChanged();
900void QWaylandOutput::frameStarted()
903 for (
int i = 0; i < d->surfaceViews.size(); i++) {
904 QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews[i];
905 if (surfacemapper.maybePrimaryView())
906 surfacemapper.surface->frameStarted();
913void QWaylandOutput::sendFrameCallbacks()
916 for (
int i = 0; i < d->surfaceViews.size(); i++) {
917 const QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews.at(i);
918 if (surfacemapper.surface && surfacemapper.surface->hasContent()) {
919 if (!surfacemapper.has_entered) {
920 surfaceEnter(surfacemapper.surface);
921 d->surfaceViews[i].has_entered =
true;
923 if (
auto primaryView = surfacemapper.maybePrimaryView()) {
924 if (!QWaylandViewPrivate::get(primaryView)->independentFrameCallback)
925 surfacemapper.surface->sendFrameCallbacks();
929 wl_display_flush_clients(d->compositor->display());