static QQuickView *addView(QScreen *screen, int screenIdx) { qDebug("Creating new QQuickView for screen %p", screen); QQuickView *v = new QQuickView; v->setScreen(screen); v->setResizeMode(QQuickView::SizeRootObjectToView); v->rootContext()->setContextProperty("screenIdx", screenIdx); v->rootContext()->setContextProperty("screenGeom", screen->geometry()); v->rootContext()->setContextProperty("screenAvailGeom", screen->availableGeometry()); v->rootContext()->setContextProperty("screenVirtGeom", screen->virtualGeometry()); v->rootContext()->setContextProperty("screenAvailVirtGeom", screen->availableVirtualGeometry()); v->rootContext()->setContextProperty("screenPhysSizeMm", screen->physicalSize()); v->rootContext()->setContextProperty("screenRefresh", screen->refreshRate()); v->setSource(QUrl("qrc:/screen.qml")); QObject::connect(v->engine(), &QQmlEngine::quit, qGuiApp, &QCoreApplication::quit); return v; }
void GreeterApp::addViewForScreen(QScreen *screen) { // create view QQuickView *view = new QQuickView(); view->setScreen(screen); view->setResizeMode(QQuickView::SizeRootObjectToView); //view->setGeometry(QRect(QPoint(0, 0), screen->geometry().size())); view->setGeometry(screen->geometry()); m_views.append(view); // remove the view when the screen is removed, but we // need to be careful here since Qt will move the view to // another screen before this signal is emitted so we // pass a pointer to the view to our slot connect(this, &GreeterApp::screenRemoved, this, [view, this](QScreen *) { removeViewForScreen(view); }); // always resize when the screen geometry changes connect(screen, &QScreen::geometryChanged, this, [view](const QRect &r) { view->setGeometry(r); }); view->engine()->addImportPath(QStringLiteral(IMPORTS_INSTALL_DIR)); // connect proxy signals connect(m_proxy, SIGNAL(loginSucceeded()), view, SLOT(close())); // we used to have only one window as big as the virtual desktop, // QML took care of creating an item for each screen by iterating on // the screen model. However we now have a better approach: we create // a view for each screen that compose the virtual desktop and thus // the QML code for each screen is responsible for drawing only its // screen. By doing so we actually make the screen model useless, but // we want to keep it for compatibility reasons, we do however create // one for each view and expose only the screen that the view belongs to // in order to avoid creating items with different sizes. ScreenModel *screenModel = new ScreenModel(screen, view); // set context properties view->rootContext()->setContextProperty(QStringLiteral("sessionModel"), m_sessionModel); view->rootContext()->setContextProperty(QStringLiteral("screenModel"), screenModel); view->rootContext()->setContextProperty(QStringLiteral("userModel"), m_userModel); view->rootContext()->setContextProperty(QStringLiteral("config"), *m_themeConfig); view->rootContext()->setContextProperty(QStringLiteral("sddm"), m_proxy); view->rootContext()->setContextProperty(QStringLiteral("keyboard"), m_keyboard); view->rootContext()->setContextProperty(QStringLiteral("primaryScreen"), QGuiApplication::primaryScreen() == screen); view->rootContext()->setContextProperty(QStringLiteral("__sddm_errors"), QString()); // get theme main script QString mainScript = QStringLiteral("%1/%2").arg(m_themePath).arg(m_metadata->mainScript()); QUrl mainScriptUrl; if (m_themePath.startsWith(QLatin1String("qrc:/"))) mainScriptUrl = QUrl(mainScript); else mainScriptUrl = QUrl::fromLocalFile(mainScript); // load theme from resources when an error has occurred connect(view, &QQuickView::statusChanged, this, [view](QQuickView::Status status) { if (status != QQuickView::Error) return; QString errors; Q_FOREACH(const QQmlError &e, view->errors()) { qWarning() << e; errors += QLatin1String("\n") + e.toString(); } qWarning() << "Fallback to embedded theme"; view->rootContext()->setContextProperty(QStringLiteral("__sddm_errors"), errors); view->setSource(QUrl(QStringLiteral("qrc:/theme/Main.qml"))); });