summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qt-lightdm-greeter.qrc1
-rw-r--r--resources/gnome-face-tired.svg376
-rw-r--r--src/main.cpp243
-rw-r--r--src/mainwindow.cpp186
-rw-r--r--src/mainwindow.h42
-rw-r--r--src/snake.cpp4
6 files changed, 273 insertions, 579 deletions
diff --git a/qt-lightdm-greeter.qrc b/qt-lightdm-greeter.qrc
index eed73f9..aa7accd 100644
--- a/qt-lightdm-greeter.qrc
+++ b/qt-lightdm-greeter.qrc
@@ -4,6 +4,5 @@
<file>resources/backIcon.svg</file>
<file>resources/leaveIcon.svg</file>
<file>resources/bwlp.svg</file>
- <file>resources/gnome-face-tired.svg</file>
</qresource>
</RCC>
diff --git a/resources/gnome-face-tired.svg b/resources/gnome-face-tired.svg
deleted file mode 100644
index de43b1a..0000000
--- a/resources/gnome-face-tired.svg
+++ /dev/null
@@ -1,376 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- viewBox="0 0 47.001228 49.000003"
- version="1.0"
- id="svg2"
- height="52.26667"
- width="50.134644">
- <defs
- id="defs4">
- <linearGradient
- id="linearGradient8431">
- <stop
- id="stop8433"
- offset="0"
- style="stop-color:#ffffff;stop-opacity:1;" />
- <stop
- id="stop8435"
- offset="1"
- style="stop-color:#ffffff;stop-opacity:0;" />
- </linearGradient>
- <linearGradient
- id="linearGradient4487">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop4489" />
- <stop
- id="stop4491"
- offset="0.58888888"
- style="stop-color:#ffffff;stop-opacity:1;" />
- <stop
- style="stop-color:#ffffff;stop-opacity:0;"
- offset="1"
- id="stop4493" />
- </linearGradient>
- <linearGradient
- id="linearGradient3752">
- <stop
- style="stop-color:white;stop-opacity:1"
- offset="0"
- id="stop3754" />
- <stop
- id="stop3756"
- offset="0.80000001"
- style="stop-color:#fce94f;stop-opacity:1;" />
- <stop
- style="stop-color:#edd400;stop-opacity:1"
- offset="1"
- id="stop3758" />
- </linearGradient>
- <linearGradient
- id="linearGradient3734">
- <stop
- id="stop3736"
- offset="0"
- style="stop-color:black;stop-opacity:1;" />
- <stop
- id="stop3738"
- offset="1"
- style="stop-color:black;stop-opacity:0;" />
- </linearGradient>
- <linearGradient
- id="linearGradient3712">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop3714" />
- <stop
- style="stop-color:white;stop-opacity:0.50570345"
- offset="1"
- id="stop3716" />
- </linearGradient>
- <linearGradient
- id="linearGradient3704">
- <stop
- id="stop3706"
- offset="0"
- style="stop-color:white;stop-opacity:1;" />
- <stop
- id="stop3708"
- offset="1"
- style="stop-color:white;stop-opacity:0;" />
- </linearGradient>
- <radialGradient
- r="10.049342"
- fy="7.8025141"
- fx="9.3747082"
- cy="7.8025141"
- cx="9.3747082"
- gradientTransform="matrix(1.200799,0,0,1.200799,-1.921023,-1.565398)"
- gradientUnits="userSpaceOnUse"
- id="radialGradient4412"
- xlink:href="#linearGradient3752" />
- <radialGradient
- r="10.108456"
- fy="3.2659137"
- fx="5.3851099"
- cy="3.2659137"
- cx="5.3851099"
- gradientTransform="matrix(1.242401,0,0,1.242401,-1.281477,-0.839422)"
- gradientUnits="userSpaceOnUse"
- id="radialGradient4414"
- xlink:href="#linearGradient3712" />
- <linearGradient
- y2="-134.38734"
- x2="19.23638"
- y1="-140.43388"
- x1="18.825819"
- gradientUnits="userSpaceOnUse"
- id="linearGradient8741"
- xlink:href="#linearGradient8431" />
- <radialGradient
- r="9.546875"
- fy="10.046875"
- fx="12.046875"
- cy="10.046875"
- cx="12.046875"
- gradientUnits="userSpaceOnUse"
- id="radialGradient7956"
- xlink:href="#linearGradient3734" />
- <radialGradient
- r="7.0416665"
- fy="50.736225"
- fx="-84.320526"
- cy="50.736225"
- cx="-84.320526"
- gradientTransform="matrix(0.86849,0,0,0.86849,-11.05505,6.701792)"
- gradientUnits="userSpaceOnUse"
- id="radialGradient2230"
- xlink:href="#linearGradient4487" />
- <radialGradient
- r="7.0416665"
- fy="50.736225"
- fx="-84.320526"
- cy="50.736225"
- cx="-84.320526"
- gradientTransform="matrix(0.86849,0,0,0.86849,-11.05505,6.701792)"
- gradientUnits="userSpaceOnUse"
- id="radialGradient2232"
- xlink:href="#linearGradient4487" />
- <radialGradient
- r="11.89852"
- fy="66.5"
- fx="-79.065781"
- cy="66.5"
- cx="-79.065781"
- gradientTransform="matrix(1.172092,0,0,0.779118,114.2479,-215.3113)"
- gradientUnits="userSpaceOnUse"
- id="radialGradient2234"
- xlink:href="#linearGradient3704" />
- <linearGradient
- id="linearGradient2967">
- <stop
- style="stop-color:#729fcf;stop-opacity:1;"
- offset="0"
- id="stop2969" />
- <stop
- style="stop-color:white;stop-opacity:1"
- offset="1"
- id="stop2971" />
- </linearGradient>
- <linearGradient
- id="linearGradient2982">
- <stop
- style="stop-color:#8db1d8;stop-opacity:1;"
- offset="0"
- id="stop2984" />
- <stop
- style="stop-color:#3465a4;stop-opacity:1;"
- offset="1"
- id="stop2986" />
- </linearGradient>
- <linearGradient
- y2="-1.7008253"
- x2="16"
- y1="4.5018396"
- x1="17.763865"
- gradientTransform="translate(12,15)"
- gradientUnits="userSpaceOnUse"
- id="linearGradient3394"
- xlink:href="#linearGradient2967" />
- <linearGradient
- y2="9.2939177"
- x2="46.404255"
- y1="1.9139081"
- x1="40.416721"
- gradientTransform="scale(1.032655,0.968377)"
- gradientUnits="userSpaceOnUse"
- id="linearGradient3397"
- xlink:href="#linearGradient2982" />
- <linearGradient
- y2="5.7135463"
- x2="31.59153"
- y1="13.15625"
- x1="32.875"
- gradientUnits="userSpaceOnUse"
- id="linearGradient3399"
- xlink:href="#linearGradient2967" />
- </defs>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- <dc:creator>
- <cc:Agent>
- <dc:title>Lapo Calamandrei</dc:title>
- </cc:Agent>
- </dc:creator>
- <cc:license
- rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
- <dc:relation>emoticon, emots, smiley, saint, angel, smile</dc:relation>
- </cc:Work>
- <cc:License
- rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Reproduction" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Distribution" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/Notice" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/ShareAlike" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/SourceCode" />
- </cc:License>
- </rdf:RDF>
- </metadata>
- <g
- transform="translate(-1.0000003)"
- style="display:inline"
- id="layer1">
- <g
- transform="translate(-106,-6)"
- id="g7909" />
- <g
- id="g3901">
- <circle
- style="display:inline;opacity:0.4;fill:url(#radialGradient7956);fill-opacity:1;stroke:none;stroke-width:0.46570092;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path7954"
- transform="matrix(2.4091653,0,0,1.2045827,-5.022913,25.39771)"
- cx="12.046875"
- cy="10.046875"
- r="9.546875" />
- <circle
- style="display:inline;fill:url(#radialGradient4412);fill-opacity:1;stroke:#c4a000;stroke-width:0.46570092;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4380"
- transform="matrix(2.1473,0,0,2.1473,-1.8687,3.4268)"
- cx="12.046875"
- cy="10.046875"
- r="9.546875" />
- <ellipse
- style="display:inline;fill:url(#linearGradient8741);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.69999993;stroke-opacity:1"
- id="path8739"
- transform="matrix(2.2078305,-0.5915864,0.4553048,1.6992208,40.743051,260.37364)"
- cx="19.5625"
- cy="-135.96875"
- rx="6.125"
- ry="5.96875" />
- <circle
- style="display:inline;fill:none;fill-opacity:1;stroke:url(#radialGradient4414);stroke-width:0.48958337;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4382"
- transform="matrix(2.042553,0,0,2.042553,-0.6064,4.4787)"
- cx="12.046875"
- cy="10.046875"
- r="9.546875" />
- <g
- id="g4499"
- transform="translate(0,-22)"
- style="opacity:0.65">
- <circle
- transform="matrix(0.923077,0,0,0.923077,95.6154,0.57692)"
- id="path4481"
- style="display:inline;opacity:1;fill:url(#radialGradient2230);fill-opacity:1;stroke:none;stroke-width:1.08333337;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- cx="-83"
- cy="53"
- r="6.5" />
- <circle
- transform="matrix(0.923077,0,0,0.923077,105.6154,0.57692)"
- id="path4495"
- style="display:inline;opacity:1;fill:url(#radialGradient2232);fill-opacity:1;stroke:none;stroke-width:1.08333337;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- cx="-83"
- cy="53"
- r="6.5" />
- </g>
- <g
- id="g7846"
- transform="translate(0,205)">
- <path
- id="path4515"
- d="m 15.5,-176.5 c 1.962489,1.29412 3.958976,1.41533 6,0"
- style="display:inline;opacity:0.81226059;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
- <path
- id="path4517"
- d="m 31.5,-176.5 c -1.962489,1.29412 -3.958976,1.41533 -6,0"
- style="display:inline;opacity:0.81226059;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
- <path
- id="path4509"
- d="m 15.5,-175.5 c 1.962489,1.29412 3.958976,1.41533 6,0"
- style="fill:none;fill-rule:evenodd;stroke:#888a85;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
- <path
- id="path4513"
- d="m 31.5,-175.5 c -1.962489,1.29412 -3.958976,1.41533 -6,0"
- style="display:inline;fill:none;fill-rule:evenodd;stroke:#888a85;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
- </g>
- <g
- id="g4531"
- transform="matrix(0.3112951,0,0,1,17.520421,204)">
- <path
- id="path4527"
- d="M 15.557761,-163.5 H 32.435777"
- style="display:inline;opacity:0.8;fill:none;fill-rule:evenodd;stroke:url(#radialGradient2234);stroke-width:1.79231215px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
- </g>
- <path
- style="fill:none;fill-rule:evenodd;stroke:#c4a000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- d="m 22.5,39.5 h 5"
- id="path5373" />
- <path
- id="path2898"
- d="m 28.5,15.5 v 2 h 2 l -2,2.5 v 1.5 h 5 v -2 h -2 l 2,-2.5 v -1.5 z"
- style="fill:url(#linearGradient3394);fill-opacity:1;stroke:#3465a4;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <g
- id="g1975"
- transform="translate(3.000005)">
- <path
- id="path2946"
- d="m 31,9 4.999995,2e-6 v 1.053572 L 32.79543,14 H 36 l -5e-6,1.000004 h -5 L 31,13.946429 34.210006,10.000002 31,10 Z"
- style="font-style:normal;font-weight:bold;font-size:11.05665684px;font-family:'Bitstream Vera Sans Mono';fill:#729fcf;fill-opacity:1;stroke:#3465a4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- id="text2929"
- d="m 31,9 4.999995,2e-6 v 1.053572 L 32.79543,14 H 36 l -5e-6,1.000004 h -5 L 31,13.946429 34.210006,10.000002 31,10 V 9"
- style="font-style:normal;font-weight:bold;font-size:11.05665684px;font-family:'Bitstream Vera Sans Mono';fill:url(#linearGradient3399);fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
- </g>
- <g
- id="g1967"
- transform="translate(-0.005991)">
- <path
- id="path2949"
- d="m 40,1 7.000003,-6.5e-7 0.006,2.07142925 L 43,7 h 4 l 3e-6,2.0000161 h -7.000019 l -2e-6,-2.0714448 L 44,3 l -3.994011,7e-7 z"
- style="font-style:normal;font-weight:bold;font-size:15.10630894px;font-family:'Bitstream Vera Sans Mono';fill:#729fcf;fill-opacity:1;stroke:#3465a4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- id="text2933"
- d="m 40,1 7.000003,-6.5e-7 0.006,2.07142925 L 43,7 h 4 l 3e-6,2.0000161 h -7.000019 l -2e-6,-2.0714448 L 44,3 l -3.994011,7e-7 L 40,1"
- style="font-style:normal;font-weight:bold;font-size:15.10630894px;font-family:'Bitstream Vera Sans Mono';fill:url(#linearGradient3397);fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
- <g
- style="opacity:0.5"
- id="g3008">
- <path
- style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
- d="m 40.5,2.5 v -1 h 6"
- id="path2951" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- d="M 43.0625,7 C 42.786358,7.0258883 42.583487,7.2707326 42.609375,7.546875 42.635263,7.8230174 42.880108,8.0258883 43.15625,8 H 47 V 7 H 43.15625 C 43.12507,6.99706 43.09368,6.99706 43.0625,7 Z"
- id="path2953" />
- <path
- style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
- d="M 44.09375,3 C 44.00794,3.03114 43.932288,3.085176 43.875,3.15625 L 40.15625,6.78125 40,6.9375 V 7.15625 9 h 1 V 7.34375 l 3.5625,-3.5 C 44.724254,3.6862744 44.760437,3.4399497 44.650803,3.2426093 44.54117,3.0452688 44.31291,2.9458567 44.09375,3 Z"
- id="path2955" />
- </g>
- </g>
- </g>
- </g>
-</svg>
diff --git a/src/main.cpp b/src/main.cpp
index d248718..17d07bc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -14,6 +14,7 @@
#include <QPainter>
#include <QMap>
#include <QSocketNotifier>
+#include <QScreen>
#include <fcntl.h> /* Obtain O_* constant definitions */
#include <unistd.h>
@@ -32,9 +33,15 @@ Settings *s_settings = new Settings();
static int sockets[2];
+static QMap<int, MainWindow*> currentWindows;
+
+static QTimer setupDelay;
+
static void createSimpleBackground();
-static void sigUsr1(int);
+static void watch(const QScreen *scrn);
+
+static void setupScreens();
static void messageHandler(QtMsgType type, const QMessageLogContext&, const QString& msg)
{
@@ -43,16 +50,16 @@ static void messageHandler(QtMsgType type, const QMessageLogContext&, const QStr
static inline int size(const QRect& r)
{
- return r.width() * r.height();
+ return r.width() * r.height();
}
int main(int argc, char *argv[])
{
- if (argc > 1 && QString(argv[1]) == QString("--test")) {
- Global::enableTestMode();
- }
+ if (argc > 1 && QString(argv[1]) == QString("--test")) {
+ Global::enableTestMode();
+ }
- QApplication a(argc, argv);
+ QApplication a(argc, argv);
// I have no idea why, but Qt's stock qWarning() output never makes it
// to /var/log/lightdm/x-0-greeter.log, so we use std::cerr instead..
@@ -63,36 +70,85 @@ int main(int argc, char *argv[])
}
if (!Global::testMode() && !Settings::autoLoginCheckCmd().isEmpty()) {
- QProcess p;
+ QProcess p;
int ret = QProcess::execute(Settings::autoLoginCheckCmd());
- if (ret == 0) {
- if (Global::autoLoginGuest()) {
- qWarning() << "Guest login ok";
+ if (ret == 0) {
+ if (Global::autoLoginGuest()) {
+ qWarning() << "Guest login ok";
createSimpleBackground();
return a.exec();
- } else {
- qWarning() << "Guest login failed";
- // TODO: Set error message, display somewhere
- }
- }
+ } else {
+ qWarning() << "Guest login failed";
+ // TODO: Set error message, display somewhere
+ }
+ }
}
- // Build background for X server, in case we start a session that
- // doesn't set one on its own this will make sure it's not simply
- // black
- QImage entire;
+ QObject::connect(&setupDelay, &QTimer::timeout, []() {
+ setupScreens();
+ });
+ setupDelay.setInterval(100);
+ setupDelay.setSingleShot(true);
+ setupDelay.start();
- // Get a list of non-overlapping screens, as this might lead to a broken
- // greeter with main windows covering other login forms
- QMap<int, QRect> screens;
+ if (!Global::testMode()) {
+ for (const auto scrn : QGuiApplication::screens()) {
+ watch(scrn);
+ }
+ QObject::connect(qApp, &QGuiApplication::screenAdded, [](const QScreen *scrn) {
+ setupDelay.start();
+ watch(scrn);
+ });
+ auto cb = [](const QScreen *) {
+ setupDelay.start();
+ };
+ QObject::connect(qApp, &QGuiApplication::screenRemoved, cb);
+ QObject::connect(qApp, &QGuiApplication::primaryScreenChanged, cb);
+ }
+
+ /*
+ if (!entire.isNull()) {
+ qWarning() << "Setting x background";
+ AddPixmapToBackground(entire.constBits(), entire.width(), entire.height(),
+ 24, entire.bytesPerLine(), entire.byteCount());
+ }
+ */
+
+ return a.exec();
+}
+
+static void watch(const QScreen *scrn)
+{
+ QObject::connect(scrn, &QScreen::geometryChanged, [](const QRect &geom) {
+ setupDelay.start();
+ });
+}
+
+static void createSimpleBackground()
+{
+ QImage img = Global::getConfigGradient();
+ if (img.isNull())
+ return;
+ img = img.scaled(QApplication::desktop()->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ AddPixmapToBackground(img.constBits(), img.width(), img.height(),
+ 24, img.bytesPerLine(), img.byteCount());
+}
+
+static QList<QRect> allOld;
+static int primaryOld = -1;
+
+void setupScreens()
+{
+ // Get a list of non-overlapping screens, as this might lead to a broken
+ // greeter with main windows covering other login forms
+ QMap<int, QRect> screens;
+ QList<QRect> allNew;
if (Global::testMode()) {
screens.insert(0, QRect(0, 0, 1024, 768));
} else {
- QSize desktopSize = QApplication::desktop()->size();
- qWarning() << "Desktop full size is " << desktopSize;
- entire = QImage(desktopSize, QImage::Format_RGB32);
for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) {
QRect r = QApplication::desktop()->screenGeometry(i);
+ allNew.append(r);
QMutableMapIterator<int, QRect>it(screens);
while (it.hasNext()) {
it.next();
@@ -112,79 +168,82 @@ int main(int argc, char *argv[])
}
}
- // Determine primary screen
- int primary;
- if (screens.contains(QApplication::desktop()->primaryScreen())) {
- // Primary screen still in selection
- primary = QApplication::desktop()->primaryScreen();
- } else {
- // Fallback to first one
- primary = screens.begin().key();
- }
-
- struct sigaction usr1;
-
- usr1.sa_handler = &sigUsr1;
- sigemptyset(&usr1.sa_mask);
- usr1.sa_flags = SA_RESTART;
-
- QSocketNotifier *sn = nullptr;
- if (sigaction(SIGUSR1, &usr1, nullptr) == 0 && ::socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0) {
- sn = new QSocketNotifier(sockets[1], QSocketNotifier::Read);
- QObject::connect(sn, &QSocketNotifier::activated, [](int fd) {
- char tmp[1000];
- read(fd, tmp, sizeof tmp);
- });
- }
-
- // Now set up all the screens
- QPainter painter(&entire);
- MainWindow *focusWindow = nullptr;
+ // Spurious event?
+ int primaryNew = QApplication::desktop()->primaryScreen();
+ if (primaryNew == primaryOld && allOld == allNew)
+ return;
+ primaryOld = primaryNew;
+ allOld = allNew;
+
+ // Determine primary screen
+ int primary;
+ if (screens.contains(primaryNew)) {
+ // Primary screen still in selection
+ primary = primaryNew;
+ } else {
+ // Fallback to first one
+ primary = screens.begin().key();
+ }
+
+ // Try to reuse as many mainwindows as possible
+ QMap<int, MainWindow*> remaining = currentWindows;
+ do {
+ currentWindows.clear();
+ QMutableMapIterator<int, QRect> it(screens);
+ while (it.hasNext()) {
+ it.next();
+ MainWindow *old = remaining.take(it.key());
+ if (old != nullptr) {
+ // Existing
+ qDebug() << "Re-using existing window";
+ old->setGeometry(it.value());
+ if (old->showLoginForm() && primary != it.key()) {
+ qDebug() << "Destroying old login form";
+ LoginForm *logForm = old->stealLoginForm();
+ if (logForm != nullptr) {
+ logForm->setParent(nullptr);
+ logForm->deleteLater();
+ }
+ }
+ currentWindows.insert(it.key(), old);
+ it.remove();
+ }
+ }
+ } while(0);
+
+ // Now set up remaining screens
QMapIterator<int, QRect> it(screens);
while (it.hasNext()) {
- it.next();
- MainWindow *w = new MainWindow(primary == it.key(), it.key(), it.value());
- w->show();
- if (sn != nullptr) {
- QObject::connect(sn, SIGNAL(activated(int)), w, SLOT(showStandby()));
- }
- if (w->showLoginForm()) {
- focusWindow = w;
+ it.next();
+ MainWindow *old = nullptr;
+ if (!remaining.empty()) {
+ qDebug() << "This should never happen, reusing old window II";
+ old = remaining.take(remaining.firstKey());
+ if (old != nullptr) {
+ if (old->showLoginForm() && primary != it.key()) {
+ LoginForm *logForm = old->stealLoginForm();
+ if (logForm != nullptr) {
+ logForm->setParent(nullptr);
+ logForm->deleteLater();
+ }
+ }
+ old->setGeometry(it.value());
+ }
}
- if (!entire.isNull()) {
- QPoint p = it.value().topLeft();
- painter.drawImage(p, w->getBackground());
+ if (old == nullptr) {
+ qDebug() << "Adding a window";
+ old = new MainWindow(primary == it.key(), it.key(), it.value());
+ old->show();
+ }
+ currentWindows.insert(it.key(), old);
+ if (old->showLoginForm()) {
+ old->setFocus(Qt::OtherFocusReason);
+ old->activateWindow();
}
}
- if (!entire.isNull()) {
- qWarning() << "Setting x background";
- AddPixmapToBackground(entire.constBits(), entire.width(), entire.height(),
- 24, entire.bytesPerLine(), entire.byteCount());
- }
-
- // Ensure we set the primary screen's widget as active when there
- // are more screens
- if (focusWindow) {
- focusWindow->setFocus(Qt::OtherFocusReason);
- focusWindow->activateWindow();
+ for (MainWindow *old : remaining) {
+ old->deleteLater();
}
-
- return a.exec();
-}
-
-static void createSimpleBackground()
-{
- QImage img = Global::getConfigGradient();
- if (img.isNull())
- return;
- img = img.scaled(QApplication::desktop()->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- AddPixmapToBackground(img.constBits(), img.width(), img.height(),
- 24, img.bytesPerLine(), img.byteCount());
}
-static void sigUsr1(int)
-{
- char a = 1;
- ::write(sockets[0], &a, sizeof(a));
-}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 1e08f0f..7c75489 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -32,106 +32,138 @@
MainWindow::MainWindow(bool primary, int screen, const QRect &screenRect, QWidget *parent) :
QWidget(parent),
m_ScreenRect(screenRect),
- m_Primary(primary),
m_LoginForm(nullptr),
m_messages(nullptr),
m_Clock(nullptr),
- m_Snake(nullptr)
+ m_Snake(nullptr),
+ m_Banner(nullptr),
+ m_News(nullptr)
{
setObjectName(QString("MainWindow_%1").arg(screen));
- setGeometry(screenRect);
-
- setBackground();
-
// TODO: Check if testMode == false and greeter == NULL, if so display big error message
// instead of exiting/crashing
// display login dialog only in the main screen
+ if (primary) {
+ m_LoginForm = new LoginForm(this);
+ // This hack ensures that the primary screen will have focus
+ // if there are more screens (move the mouse cursor in the center
+ // of primary screen - not in the center of all X area). It
+ // won't affect single-screen environments.
+ int centerX = screenRect.width()/2 + screenRect.x();
+ int centerY = screenRect.height()/2 + screenRect.y();
+ QCursor::setPos(centerX, centerY);
+ }
+ // Banner
+ if (!Settings::bannerImageFile().isEmpty()) {
+ qWarning() << "Have banner " << Settings::bannerImageFile();
+ m_Banner = new QSvgWidget(Settings::bannerImageFile(), this);
+ }
+
+ createLogWindow();
+ createClock();
+ createNewsWindow();
+
+ setGeometry(screenRect);
+}
+
+void MainWindow::resizeEvent(QResizeEvent *event)
+{
+ if (m_Snake != nullptr) {
+ delete m_Snake;
+ m_Snake = nullptr;
+ }
+
+ QWidget::resizeEvent(event);
+ m_ScreenRect = QRect(this->pos(), event->size());
+ setBackground();
/*
* Everything is layed out manually here, since I don't know how to represent the size constraints
* and interactions of everything using layout classes. You're welcome to improve this, but I double
* dare you to not break any combination of having/not having certain logos or elements displayed.
*/
-
int newsY = 100;
- int newsX = screenRect.width() / 2;
- int newsBottom = screenRect.height();
+ int newsX = m_ScreenRect.width() / 2;
+ int newsBottom = m_ScreenRect.height();
- int spaceY = screenRect.height() / 2;
-
- if (showLoginForm()) {
- m_LoginForm = new LoginForm(this);
+ int spaceY = m_ScreenRect.height() / 2;
+
+ if (m_LoginForm != nullptr) {
spaceY -= m_LoginForm->height() / 2;
- int maxX = screenRect.width() - m_LoginForm->width();
- int maxY = screenRect.height() - m_LoginForm->height();
+ int maxX = m_ScreenRect.width() - m_LoginForm->width();
+ int maxY = m_ScreenRect.height() - m_LoginForm->height();
int defaultX = 50*maxX/100;
int defaultY = 50*maxY/100;
int offsetX = getOffset(Settings::offsetX(), maxX, defaultX);
int offsetY = getOffset(Settings::offsetY(), maxY, defaultY);
-
+
m_LoginForm->move(offsetX, offsetY);
m_LoginForm->show();
-
- // This hack ensures that the primary screen will have focus
- // if there are more screens (move the mouse cursor in the center
- // of primary screen - not in the center of all X area). It
- // won't affect single-screen environments.
- int centerX = screenRect.width()/2 + screenRect.x();
- int centerY = screenRect.height()/2 + screenRect.y();
- QCursor::setPos(centerX, centerY);
newsX = m_LoginForm->geometry().right() + 5;
}
// Banner
- if (!Settings::bannerImageFile().isEmpty()) {
- qWarning() << "Have banner " << Settings::bannerImageFile();
- QSvgWidget *banner = new QSvgWidget(Settings::bannerImageFile(), this);
- qWarning() << banner->sizeHint();
- if (banner->renderer()->isValid()) {
+ if (m_Banner != nullptr) {
+ qWarning() << m_Banner->sizeHint();
+ if (m_Banner->renderer()->isValid()) {
QSize sh;
int offs = 0;
do {
offs += 20;
- sh = banner->sizeHint().scaled(screenRect.width() - offs, spaceY - offs - 50, Qt::KeepAspectRatio);
- } while (offs < 200 && sh.width() > screenRect.width() / 2 && sh.height() > spaceY / 2);
+ sh = m_Banner->sizeHint().scaled(m_ScreenRect.width() - offs, spaceY - offs - 50, Qt::KeepAspectRatio);
+ } while (offs < 200 && sh.width() > m_ScreenRect.width() / 2 && sh.height() > spaceY / 2);
int yoff = (spaceY - sh.height());
if (yoff < 100) {
yoff = 100;
}
- banner->setGeometry((screenRect.width() - sh.width()) / 2, yoff / 2, sh.width(), sh.height());
- newsY = banner->geometry().bottom() + 10;
+ m_Banner->setGeometry((m_ScreenRect.width() - sh.width()) / 2, yoff / 2, sh.width(), sh.height());
+ newsY = m_Banner->geometry().bottom() + 10;
}
}
+ for (QWidget *w : m_DecoItems) {
+ w->setParent(nullptr);
+ w->deleteLater();
+ }
+ // Distro and custom icons left/right bottom
+ m_DecoItems.clear();
int ls = (spaceY > 500 ? 500 : spaceY);
- if (ls > screenRect.height() / 5) ls = screenRect.height() / 5;
- if (ls > screenRect.width() / 5) ls = screenRect.width() / 5;
- QRect logoRect(QPoint(0, screenRect.height() / 3), QSize(ls, screenRect.height() * 2 / 3));
+ if (ls > m_ScreenRect.height() / 5) ls = m_ScreenRect.height() / 5;
+ if (ls > m_ScreenRect.width() / 5) ls = m_ScreenRect.width() / 5;
+ QRect logoRect(QPoint(0, m_ScreenRect.height() / 3), QSize(ls, m_ScreenRect.height() * 2 / 3));
QSize logoSize = createLogo(logoRect);
- QRect distroRect(QPoint(screenRect.width() - ls, screenRect.height() - ls), QSize(ls, ls));
+ QRect distroRect(QPoint(m_ScreenRect.width() - ls, m_ScreenRect.height() - ls), QSize(ls, ls));
QSize distroSize = createDistro(distroRect);
if (distroSize.height() > 0) {
newsBottom -= distroSize.height() - 10;
}
- if (showLoginForm()) {
- // Log window
- QRect lwSize(QPoint(logoSize.width(), screenRect.height() * 3/4), QPoint(screenRect.width() - distroSize.width(), screenRect.height()));
+ // Log window
+ if (m_messages != nullptr) {
+ QRect lwSize(QPoint(logoSize.width(), m_ScreenRect.height() * 3/4), QPoint(m_ScreenRect.width() - distroSize.width(), m_ScreenRect.height()));
lwSize.adjust(10, 10, -10, -10);
- if (createLogWindow(lwSize)) {
- newsBottom = lwSize.top();
- }
+ m_messages->setGeometry(lwSize);
+ int ps = lwSize.height() / 20;
+ if (ps > 20) ps = 20;
+ m_messages->setFontPointSize(ps);
+ newsBottom = lwSize.top();
+ }
+ if (m_Clock != nullptr) {
+ m_Clock->setFixedWidth(m_ScreenRect.width());
+ m_Clock->parentWidget()->setFixedWidth(m_ScreenRect.width());
}
- createClock();
// News widget
- QRect newsSize(QPoint(newsX, newsY), QPoint(screenRect.width() - 10, newsBottom - 10));
- createNewsWindow(newsSize);
-}
-
-MainWindow::~MainWindow()
-{
+ if (m_News != nullptr) {
+ QRect newsSize(QPoint(newsX, newsY), QPoint(m_ScreenRect.width() - 10, newsBottom - 10));
+ if (newsSize.width() < 200 || newsSize.height() < 80) {
+ m_News->hide();
+ } else {
+ m_News->setGeometry(newsSize);
+ m_News->show();
+ }
+ }
}
void MainWindow::paintEvent(QPaintEvent *event)
@@ -194,14 +226,19 @@ void MainWindow::createNextLogo(QRect &max, QSize &retval, const QString &path)
if (max.height() <= 0)
return;
QSvgWidget *img = new QSvgWidget(path, this);
- if (!img->renderer()->isValid())
+ if (!img->renderer()->isValid()) {
+ img->deleteLater();
return;
+ }
QSize virtualSize = img->sizeHint().scaled(max.width(), max.height(), Qt::KeepAspectRatio);
QSize realSize = img->sizeHint().scaled(max.width() - 20, max.height() - 20, Qt::KeepAspectRatio);
- if (virtualSize.width() == 0 || virtualSize.height() == 0)
+ if (virtualSize.width() == 0 || virtualSize.height() == 0) {
+ img->deleteLater();
return;
+ }
QRect c(max.left() + 10, max.bottom() - realSize.height() - 10, realSize.width(), realSize.height());
img->setGeometry(c);
+ m_DecoItems.append(img);
max.setHeight(max.height() - virtualSize.height());
retval.setWidth(qMax(retval.width(), virtualSize.width()));
retval.setHeight(retval.height() + virtualSize.height());
@@ -222,13 +259,14 @@ QSize MainWindow::createDistro(const QRect &max)
}
QPixmap pixmap(QPixmap::fromImage(img));
QLabel *lbl = new QLabel(this);
+ m_DecoItems.append(lbl);
lbl->setPixmap(pixmap);
QRect c(max.right() - realSize.width() - 10, max.bottom() - realSize.height() - 10, realSize.width(), realSize.height());
lbl->setGeometry(c);
return virtualSize;
}
-bool MainWindow::createLogWindow(const QRect& geom)
+bool MainWindow::createLogWindow()
{
QString path = Settings::logMessageFile();
if (path.isEmpty())
@@ -237,10 +275,6 @@ bool MainWindow::createLogWindow(const QRect& geom)
if (f.size() == 0 || !f.open(QFile::ReadOnly))
return false;
m_messages = new QTextEdit(this);
- m_messages->setGeometry(geom);
- int ps = geom.height() / 20;
- if (ps > 20) ps = 20;
- m_messages->setFontPointSize(ps);
QTextStream stream(&f);
const QColor black(Qt::black);
while (!stream.atEnd()) {
@@ -265,21 +299,18 @@ bool MainWindow::createLogWindow(const QRect& geom)
return true;
}
-void MainWindow::createNewsWindow(const QRect &size)
+void MainWindow::createNewsWindow()
{
- if (size.width() < 100 || size.height() < 100)
- return;
QString path = Settings::newsHtmlFile();
if (path.isEmpty())
return;
QFile f(path);
if (f.size() == 0 || !f.open(QFile::ReadOnly))
return;
- QTextEdit *news = new QTextEdit(this);
- news->setReadOnly(true);
- news->setStyleSheet("border:none; background:rgba(255,255,255,.33); border-radius:5px");
- news->setHtml(QString::fromUtf8(f.readAll()));
- news->setGeometry(size);
+ m_News = new QTextEdit(this);
+ m_News->setReadOnly(true);
+ m_News->setStyleSheet("border:none; background:rgba(255,255,255,.33); border-radius:5px");
+ m_News->setHtml(QString::fromUtf8(f.readAll()));
}
void MainWindow::createClock()
@@ -329,7 +360,7 @@ void MainWindow::createClock()
bool MainWindow::showLoginForm()
{
- return m_Primary;
+ return m_LoginForm != nullptr;
}
void MainWindow::setFocus(Qt::FocusReason reason)
@@ -368,6 +399,7 @@ int MainWindow::getOffset(QString settingsOffset, int maxVal, int defaultVal)
void MainWindow::setBackground()
{
+ m_background = QImage();
Qt::AspectRatioMode arMode = Qt::KeepAspectRatioByExpanding;
QString bgPath = Settings::backgrundImageFile();
if (bgPath.length() != 0) {
@@ -407,28 +439,6 @@ void MainWindow::setBackground()
this->setPalette(palette);
}
-void MainWindow::showStandby()
-{
- if (m_LoginForm != nullptr) {
- m_LoginForm->hide();
- }
- QSvgWidget *img = new QSvgWidget(":/resources/gnome-face-tired.svg", this);
- if (img->renderer()->isValid()) {
- QSize sh = img->sizeHint().scaled(this->width() / 2, this->height() / 2, Qt::KeepAspectRatio);
- img->setGeometry((this->width() - sh.width()) / 2, (this->height() - sh.height()) / 2, sh.width(), sh.height());
- img->show();
- } else {
- qWarning() << "Shice!";
- }
- QTimer::singleShot(4000, [this, img]() {
- img->hide();
- img->deleteLater();
- if (this->m_LoginForm != nullptr) {
- m_LoginForm->show();
- }
- });
-}
-
void MainWindow::updateClock()
{
int next = drawClock();
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 8f9245e..fc0249b 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -14,6 +14,7 @@
#include <QRect>
#include <QSize>
#include <QLabel>
+#include <QList>
#include "loginform.h"
@@ -22,6 +23,7 @@ namespace Ui {
}
class QTextEdit;
+class QSvgWidget;
class GameCore;
@@ -30,51 +32,51 @@ class MainWindow : public QWidget
Q_OBJECT
public:
- explicit MainWindow(bool primary, int screen, const QRect &rect, QWidget *parent = 0);
- ~MainWindow();
+ explicit MainWindow(bool primary, int screen, const QRect &rect, QWidget *parent = nullptr);
void setFocus(Qt::FocusReason reason);
- QSize createLogo(QRect max);
+ bool showLoginForm();
- void createNextLogo(QRect &max, QSize &retval, const QString &path);
+ LoginForm* stealLoginForm() { LoginForm *p = m_LoginForm; m_LoginForm = nullptr; return p; }
- QSize createDistro(const QRect &max);
+protected:
+ virtual void paintEvent(QPaintEvent *event) override;
- bool createLogWindow(const QRect& geom);
+ virtual void mouseDoubleClickEvent(QMouseEvent *) override;
- void createNewsWindow(const QRect &size);
+ virtual void keyPressEvent(QKeyEvent *) override;
- void createClock();
+ virtual void resizeEvent(QResizeEvent *) override;
- bool showLoginForm();
+public slots:
+ void updateClock();
- QImage& getBackground() { return m_background; }
+private:
- LoginForm* loginForm() { return m_LoginForm; }
+ QSize createLogo(QRect max);
-protected:
- virtual void paintEvent(QPaintEvent *event);
+ void createNextLogo(QRect &max, QSize &retval, const QString &path);
- virtual void mouseDoubleClickEvent(QMouseEvent *);
+ QSize createDistro(const QRect &max);
- virtual void keyPressEvent(QKeyEvent *);
+ bool createLogWindow();
-public slots:
- void showStandby();
- void updateClock();
+ void createNewsWindow();
-private:
+ void createClock();
int getOffset(QString offset, int maxVal, int defaultVal);
void setBackground();
int drawClock();
QRect m_ScreenRect;
- bool m_Primary;
LoginForm* m_LoginForm;
QImage m_background;
QTextEdit *m_messages;
QLabel *m_Clock;
GameCore *m_Snake;
+ QSvgWidget *m_Banner;
+ QList<QWidget*> m_DecoItems;
+ QTextEdit *m_News;
};
#endif // MAINWINDOW_H
diff --git a/src/snake.cpp b/src/snake.cpp
index 9c7fefa..2ce1a0d 100644
--- a/src/snake.cpp
+++ b/src/snake.cpp
@@ -215,7 +215,7 @@ GameCore::GameCore(QWidget *widget)
snake->parts.append(QPoint(snake->x, snake->y));
}
// If no food was picked up within a minute, spawn more
- if (QDateTime::currentMSecsSinceEpoch() - _lastMeal > 60000) {
+ if (!_snakes.isEmpty() && QDateTime::currentMSecsSinceEpoch() - _lastMeal > 60000) {
_lastMeal = QDateTime::currentMSecsSinceEpoch();
addFood();
}
@@ -424,7 +424,7 @@ void GameCore::addSnake()
int x = qrand() % _width;
int y = qrand() % _height;
if (FIELD(x, y)->isFree()) {
- if (qrand() % 2 == 0) {
+ if (_snakes.count() <= _balls.count()) {
qDebug() << "Adding Snake at" << x << y;
_snakes.append(new Snake(x, y));
} else {