summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--src/loginform.cpp1
-rw-r--r--src/main.cpp74
-rw-r--r--src/mainwindow.cpp38
-rw-r--r--src/mainwindow.h10
-rw-r--r--src/x11util.cpp62
-rw-r--r--src/x11util.h9
7 files changed, 177 insertions, 25 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2fd0179..55282d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,6 +14,7 @@ file(GLOB_RECURSE UIS src/*.ui)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Svg REQUIRED)
+FIND_PACKAGE(X11 REQUIRED)
QT5_ADD_RESOURCES(RSCS qt-lightdm-greeter.qrc)
@@ -29,7 +30,12 @@ include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}
add_executable ( qt-lightdm-greeter ${SRCS} ${RSCS} ${UI_HEADERS} )
-target_link_libraries ( qt-lightdm-greeter Qt5::Widgets Qt5::Svg ${LIGHTDM_QT_LIBRARIES} )
+target_link_libraries ( qt-lightdm-greeter
+ Qt5::Widgets
+ Qt5::Svg
+ ${LIGHTDM_QT_LIBRARIES}
+ ${X11_LIBRARIES}
+)
install(TARGETS ${PROJECT} RUNTIME DESTINATION bin)
diff --git a/src/loginform.cpp b/src/loginform.cpp
index ced5f1e..930c7a6 100644
--- a/src/loginform.cpp
+++ b/src/loginform.cpp
@@ -37,6 +37,7 @@ LoginForm::LoginForm(QWidget *parent) :
LoginForm::~LoginForm()
{
+
delete ui;
}
diff --git a/src/main.cpp b/src/main.cpp
index c0ce7bc..50a8d38 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,18 +11,23 @@
#include <QtDebug>
#include <QSettings>
#include <QIcon>
+#include <QPainter>
+#include <QMap>
#include <iostream>
#include "settings.h"
#include "mainwindow.h"
+#include "x11util.h"
-QFile logfile;
-QTextStream ts;
+static void messageHandler(QtMsgType type, const QMessageLogContext&, const QString& msg)
+{
+ std::cerr << type << ": " << msg.toUtf8().constData() << '\n';
+}
-void messageHandler(QtMsgType type, const QMessageLogContext&, const QString& msg)
+static inline int size(const QRect& r)
{
- std::cerr << type << ": " << msg.toLatin1().data() << "\n";
+ return r.width() * r.height();
}
int main(int argc, char *argv[])
@@ -38,12 +43,66 @@ int main(int argc, char *argv[])
QIcon::setThemeName(Settings().iconThemeName());
}
+ // 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;
+ QSize desktopSize = QApplication::desktop()->size();
+ qDebug() << "Desktop full size is " << desktopSize;
+ entire = QImage(desktopSize, QImage::Format_RGB32);
+ QPainter painter(&entire);
+
+ // 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;
+ for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) {
+ QRect r = QApplication::desktop()->screenGeometry(i);
+ QMutableMapIterator<int, QRect>it(screens);
+ while (it.hasNext()) {
+ it.next();
+ if (!it.value().intersects(r))
+ continue;
+ // Overlap, bigger wins
+ if (size(it.value()) >= size(r)) {
+ // Existing is bigger
+ goto skip_rect;
+ }
+ // New is bigger, remove existing and keep going
+ it.remove();
+ }
+ // We reached here, so add new window
+ screens.insert(i, r);
+ skip_rect: ; // Do nothing
+ }
+ // 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();
+ }
+
+ // Now set up all the screens
MainWindow *focusWindow = 0;
- for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) {
- MainWindow *w = new MainWindow(i);
+ QMapIterator<int, QRect> it(screens);
+ while (it.hasNext()) {
+ it.next();
+ MainWindow *w = new MainWindow(primary == it.key(), it.key(), it.value());
w->show();
- if (w->showLoginForm())
+ if (w->showLoginForm()) {
focusWindow = w;
+ }
+ if (!entire.isNull()) {
+ QPoint p = it.value().topLeft();
+ painter.drawImage(p, w->getBackground());
+ }
+ }
+
+ if (!entire.isNull()) {
+ qDebug() << "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
@@ -55,3 +114,4 @@ int main(int argc, char *argv[])
return a.exec();
}
+
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 56f927f..314493c 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -16,14 +16,13 @@
#include "loginform.h"
#include "settings.h"
-MainWindow::MainWindow(int screen, QWidget *parent) :
+MainWindow::MainWindow(bool primary, int screen, const QRect &screenRect, QWidget *parent) :
QWidget(parent),
- m_Screen(screen)
+ m_Screen(screen),
+ m_Primary(primary)
{
setObjectName(QString("MainWindow_%1").arg(screen));
-
- QRect screenRect = QApplication::desktop()->screenGeometry(screen);
setGeometry(screenRect);
setBackground();
@@ -59,7 +58,7 @@ MainWindow::~MainWindow()
bool MainWindow::showLoginForm()
{
- return m_Screen == QApplication::desktop()->primaryScreen();
+ return m_Primary;
}
void MainWindow::setFocus(Qt::FocusReason reason)
@@ -98,29 +97,38 @@ int MainWindow::getOffset(QString settingsOffset, int maxVal, int defaultVal)
void MainWindow::setBackground()
{
- QImage backgroundImage;
QSettings greeterSettings(CONFIG_FILE, QSettings::IniFormat);
if (greeterSettings.contains(BACKGROUND_IMAGE_KEY)) {
- QString pathToBackgroundImage = greeterSettings.value(BACKGROUND_IMAGE_KEY).toString();
+ QString pathTom_background = greeterSettings.value(BACKGROUND_IMAGE_KEY).toString();
- backgroundImage = QImage(pathToBackgroundImage);
- if (backgroundImage.isNull()) {
- qWarning() << "Not able to read" << pathToBackgroundImage << "as image";
+ m_background = QImage(pathTom_background);
+ if (m_background.isNull()) {
+ qWarning() << "Not able to read" << pathTom_background << "as image";
}
}
+ if (m_background.isNull()) {
+ m_background = QImage(2, 2, QImage::Format_RGB32);
+ m_background.setPixel(0, 0, 0xffffffff);
+ m_background.setPixel(1, 0, 0xff888687);
+ m_background.setPixel(0, 1, 0xff888687);
+ m_background.setPixel(1, 1, 0xfff9a72b);
+ }
QPalette palette;
QRect rect = QApplication::desktop()->screenGeometry(m_Screen);
- if (backgroundImage.isNull()) {
+ if (m_background.isNull()) {
palette.setColor(QPalette::Background, Qt::black);
}
else {
- backgroundImage = backgroundImage.scaled(rect.width(), rect.height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
- int xoff = (backgroundImage.width() - rect.width()) / 2;
- int yoff = (backgroundImage.height() - rect.height()) / 2;
- QBrush brush(backgroundImage.copy(xoff, yoff, backgroundImage.width(), backgroundImage.height()));
+ m_background = m_background.scaled(rect.width(), rect.height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
+ int xoff = (m_background.width() - rect.width()) / 2;
+ int yoff = (m_background.height() - rect.height()) / 2;
+ if (xoff != 0 || yoff != 0) {
+ m_background = m_background.copy(xoff, yoff, m_background.width(), m_background.height());
+ }
+ QBrush brush(m_background);
palette.setBrush(this->backgroundRole(), brush);
}
this->setPalette(palette);
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 738d423..7d20a6e 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -11,6 +11,8 @@
#include <QWidget>
#include <QLightDM/Greeter>
+#include <QImage>
+#include <QRect>
#include "loginform.h"
@@ -23,19 +25,23 @@ class MainWindow : public QWidget
Q_OBJECT
public:
- explicit MainWindow(int screen, QWidget *parent = 0);
+ explicit MainWindow(bool primary, int screen, const QRect &rect, QWidget *parent = 0);
~MainWindow();
void setFocus(Qt::FocusReason reason);
bool showLoginForm();
- LoginForm* loginForm() { return m_LoginForm;}
+ QImage& getBackground() { return m_background; }
+
+ LoginForm* loginForm() { return m_LoginForm; }
private:
int getOffset(QString offset, int maxVal, int defaultVal);
void setBackground();
int m_Screen;
+ bool m_Primary;
LoginForm* m_LoginForm;
+ QImage m_background;
};
#endif // MAINWINDOW_H
diff --git a/src/x11util.cpp b/src/x11util.cpp
new file mode 100644
index 0000000..f56d31e
--- /dev/null
+++ b/src/x11util.cpp
@@ -0,0 +1,62 @@
+#include "x11util.h"
+extern "C" {
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+}
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+
+static int eHandler(Display* dpy, XErrorEvent* e)
+{
+ char buf[1000];
+ XGetErrorText(dpy, e->error_code, buf, 1000);
+ fprintf(stderr, "X ERROR %d: %s\n", (int)e->error_code, buf);
+ return 0;
+}
+
+extern "C"
+void AddPixmapToBackground(unsigned const char* imgData, int width, int height, int depth, int bytesPerLine, int byteCount)
+{
+ Pixmap pix = 0;
+ GC gc = NULL;
+ XImage *xi = NULL;
+ XGCValues gc_init;
+ memset(&gc_init, 0, sizeof(gc_init));
+ Display* dpy = XOpenDisplay(NULL);
+ if (dpy == NULL)
+ return;
+ XSetErrorHandler(&eHandler);
+ int screen = DefaultScreen(dpy);
+ Window root = RootWindow(dpy, screen);
+ char *data = (char*)malloc(byteCount);
+ memcpy(data, imgData, byteCount);
+ xi = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, data, width, height, 32, bytesPerLine);
+ if (xi == NULL)
+ goto cleanup;
+ pix = XCreatePixmap(dpy, root, width, height, (unsigned int)DefaultDepth(dpy, screen));
+ if (pix == 0)
+ goto cleanup;
+ gc_init.foreground = BlackPixel(dpy, screen);
+ gc_init.background = WhitePixel(dpy, screen);
+ gc = XCreateGC(dpy, pix, GCForeground|GCBackground, &gc_init);
+ if (gc == NULL)
+ goto cleanup;
+ int res1, res2, res3;
+ res1 = XPutImage(dpy, pix, gc, xi, 0, 0, 0, 0, width, height);
+ res2 = XSetWindowBackgroundPixmap(dpy, root, pix);
+ res3 = XClearWindow(dpy, root);
+cleanup:
+ if (gc != NULL) {
+ XFreeGC(dpy, gc);
+ }
+ if (pix != 0) {
+ XFreePixmap(dpy, pix);
+ }
+ if (xi != NULL) {
+ XDestroyImage(xi);
+ }
+ if (dpy != NULL) {
+ XCloseDisplay(dpy);
+ }
+}
diff --git a/src/x11util.h b/src/x11util.h
new file mode 100644
index 0000000..81ac0c0
--- /dev/null
+++ b/src/x11util.h
@@ -0,0 +1,9 @@
+#ifndef X11UTIL_H_
+#define X11UTIL_H_
+
+extern "C" {
+ #include <X11/X.h>
+ void AddPixmapToBackground(unsigned const char* imgData, int width, int height, int depth, int bytesPerLine, int byteCount);
+}
+
+#endif /* X11UTIL_H_ */