From 053765ac7a1800a3e1e8efc2cdef5fc696ea01af Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Thu, 15 Oct 2015 12:44:47 +0200 Subject: [PATCH 1/2] Always create a window for each screen Clone mode is something that should be dealt with xrandr from a custom Xsetup script, depending on user configuration. What we want here is to always create a window for each screen otherwise we might end up having the greeter only on the primary screen. Also, set window geometry to the whole screen geometry like we do for the screen model. --- src/greeter/GreeterApp.cpp | 13 ++++++------- src/greeter/ScreenModel.cpp | 4 ---- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/greeter/GreeterApp.cpp b/src/greeter/GreeterApp.cpp index 59a48a0f3..3a7db277e 100644 --- a/src/greeter/GreeterApp.cpp +++ b/src/greeter/GreeterApp.cpp @@ -130,7 +130,8 @@ namespace SDDM { m_proxy->setSessionModel(m_sessionModel); // create views - Q_FOREACH (QScreen *screen, screens()) + QList screens = primaryScreen()->virtualSiblings(); + Q_FOREACH (QScreen *screen, screens) addViewForScreen(screen); // handle screens @@ -138,15 +139,12 @@ namespace SDDM { } void GreeterApp::addViewForScreen(QScreen *screen) { - // heuristic to detect clone mode, in that case only add a view for the primary screen - if (screen->virtualGeometry() == primaryScreen()->geometry() && screen != primaryScreen()) - return; - // create view QQuickView *view = new QQuickView(); view->setScreen(screen); view->setResizeMode(QQuickView::SizeRootObjectToView); - view->setGeometry(QRect(QPoint(0, 0), screen->availableGeometry().size())); + //view->setGeometry(QRect(QPoint(0, 0), screen->geometry().size())); + view->setGeometry(screen->geometry()); // remove the view when the screen is removed, but we // need to be careful here since Qt will move the view to @@ -165,7 +163,7 @@ namespace SDDM { #if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)) // always resize when the screen geometry changes - connect(screen, &QScreen::availableGeometryChanged, this, [view](const QRect &r) { + connect(screen, &QScreen::geometryChanged, this, [view](const QRect &r) { view->setGeometry(r); }); #endif @@ -190,6 +188,7 @@ namespace SDDM { view->setSource(QUrl::fromLocalFile(mainScript)); // show + qDebug() << "Adding view for" << screen->name() << screen->geometry(); view->show(); } diff --git a/src/greeter/ScreenModel.cpp b/src/greeter/ScreenModel.cpp index 392bf4c4e..a49f31dd0 100644 --- a/src/greeter/ScreenModel.cpp +++ b/src/greeter/ScreenModel.cpp @@ -120,13 +120,9 @@ namespace SDDM { return; #endif - QScreen *primaryScreen = QGuiApplication::primaryScreen(); QList screens = QGuiApplication::screens(); for (int i = 0; i < screens.size(); ++i) { QScreen *screen = screens.at(i); - // heuristic to detect clone mode, in that case only consider the primary screen - if (screen->virtualGeometry() == primaryScreen->geometry() && screen != primaryScreen) - continue; // add to the screens list d->screens << ScreenPtr { new Screen { QStringLiteral("Screen %1").arg(i + 1), screen->geometry() } }; // extend available geometry From 1185a7b87c4002ab421056b15cdee8d150f09f99 Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Thu, 15 Oct 2015 18:26:36 +0200 Subject: [PATCH 2/2] A screen model for each window 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. --- src/greeter/GreeterApp.cpp | 14 +++++- src/greeter/GreeterApp.h | 2 - src/greeter/ScreenModel.cpp | 89 +++++-------------------------------- src/greeter/ScreenModel.h | 8 +--- 4 files changed, 23 insertions(+), 90 deletions(-) diff --git a/src/greeter/GreeterApp.cpp b/src/greeter/GreeterApp.cpp index 3a7db277e..e9a582cf9 100644 --- a/src/greeter/GreeterApp.cpp +++ b/src/greeter/GreeterApp.cpp @@ -109,7 +109,6 @@ namespace SDDM { // create models m_sessionModel = new SessionModel(); - m_screenModel = new ScreenModel(); m_userModel = new UserModel(); m_proxy = new GreeterProxy(socket); m_keyboard = new KeyboardModel(); @@ -173,9 +172,20 @@ namespace SDDM { // 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"), m_screenModel); + 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); diff --git a/src/greeter/GreeterApp.h b/src/greeter/GreeterApp.h index 945e0417e..91fc1a9a0 100644 --- a/src/greeter/GreeterApp.h +++ b/src/greeter/GreeterApp.h @@ -33,7 +33,6 @@ namespace SDDM { class ThemeConfig; class SessionModel; class ScreenModel; - class ScreenModel; class UserModel; class GreeterProxy; class KeyboardModel; @@ -63,7 +62,6 @@ namespace SDDM { ThemeMetadata *m_metadata { nullptr }; ThemeConfig *m_themeConfig { nullptr }; SessionModel *m_sessionModel { nullptr }; - ScreenModel *m_screenModel { nullptr }; UserModel *m_userModel { nullptr }; GreeterProxy *m_proxy { nullptr }; KeyboardModel *m_keyboard { nullptr }; diff --git a/src/greeter/ScreenModel.cpp b/src/greeter/ScreenModel.cpp index a49f31dd0..7faad9979 100644 --- a/src/greeter/ScreenModel.cpp +++ b/src/greeter/ScreenModel.cpp @@ -25,24 +25,13 @@ #include namespace SDDM { - class Screen { - public: - QString name; - QRect geometry; - }; - - typedef std::shared_ptr ScreenPtr; - class ScreenModelPrivate { public: - QList screens; - QRect geometry; - int primary { 0 }; + QScreen *screen { nullptr }; }; - ScreenModel::ScreenModel(QObject *parent) : QAbstractListModel(parent), d(new ScreenModelPrivate()) { - connect(QGuiApplication::instance(), SIGNAL(screenAdded(QScreen*)), this, SLOT(onScreenAdded(QScreen*))); - initScreens(true); + ScreenModel::ScreenModel(QScreen *screen, QObject *parent) : QAbstractListModel(parent), d(new ScreenModelPrivate()) { + d->screen = screen; } ScreenModel::~ScreenModel() { @@ -58,87 +47,29 @@ namespace SDDM { } int ScreenModel::primary() const { - return d->primary; + return d->screen == QGuiApplication::primaryScreen(); } const QRect ScreenModel::geometry(int index) const { - // return total geometry - if (index == -1) - return d->geometry; - - if (index < 0 || index >= d->screens.count()) - return QRect(); - - return d->screens.at(index)->geometry; - } - - void ScreenModel::onScreenAdded(QScreen *scrn) { - // Recive screen updates - connect(scrn, SIGNAL(geometryChanged(const QRect &)), this, SLOT(onScreenChanged())); - onScreenChanged(); - } - - void ScreenModel::onScreenChanged() { - initScreens(false); + Q_UNUSED(index); + return QRect(QPoint(0, 0), d->screen->geometry().size()); } int ScreenModel::rowCount(const QModelIndex &parent) const { - return d->screens.length(); + return 1; } QVariant ScreenModel::data(const QModelIndex &index, int role) const { - if (index.row() < 0 || index.row() >= d->screens.count()) + if (index.row() < 0 || index.row() >= 1) return QVariant(); - // get screen - ScreenPtr screen = d->screens[index.row()]; - // return correct value if (role == NameRole) - return screen->name; + return d->screen->name(); if (role == GeometryRole) - return screen->geometry; + return QRect(QPoint(0, 0), d->screen->geometry().size()); // return empty value return QVariant(); } - - void ScreenModel::initScreens(bool first) { - // Clear - beginResetModel(); - d->geometry = QRect(); - d->primary = 0; - d->screens.clear(); - -#if 0 - // fake model for testing - d->geometry = QRect(0, 0, 1920, 1080); - d->primary = 1; - d->screens << ScreenPtr { new Screen { "First", QRect(0, 0, 300, 300) } } - << ScreenPtr { new Screen { "Second", QRect(300, 0, 1320, 742) } } - << ScreenPtr { new Screen { "Third", QRect(1620, 0, 300, 300) } }; - return; -#endif - - QList screens = QGuiApplication::screens(); - for (int i = 0; i < screens.size(); ++i) { - QScreen *screen = screens.at(i); - // add to the screens list - d->screens << ScreenPtr { new Screen { QStringLiteral("Screen %1").arg(i + 1), screen->geometry() } }; - // extend available geometry - d->geometry = d->geometry.united(screen->geometry()); - // check if primary - if (screen == QGuiApplication::primaryScreen()) - d->primary = i; - - if (first) { - // Recive screen updates - connect(screen, SIGNAL(geometryChanged(const QRect &)), this, SLOT(onScreenChanged())); - } - } - endResetModel(); - - emit primaryChanged(); - } - } diff --git a/src/greeter/ScreenModel.h b/src/greeter/ScreenModel.h index 82b96f514..16284f236 100644 --- a/src/greeter/ScreenModel.h +++ b/src/greeter/ScreenModel.h @@ -41,7 +41,7 @@ namespace SDDM { GeometryRole }; - ScreenModel(QObject *parent = 0); + ScreenModel(QScreen *screen, QObject *parent = 0); ~ScreenModel(); QHash roleNames() const override; @@ -53,16 +53,10 @@ namespace SDDM { public slots: const QRect geometry(int index = -1) const; - private slots: - void onScreenAdded(QScreen *scrn); - void onScreenChanged(); - signals: void primaryChanged(); private: - void initScreens(bool first); - ScreenModelPrivate *d { nullptr }; }; }