Commit ed7b99f1 authored by Thomas Lübking's avatar Thomas Lübking
Browse files

fix screenlocker "hiding", event processing, screen adaptation

REVIEW: 108375
BUG: 311116
parent c74cc6e9
......@@ -69,7 +69,9 @@ UnlockApp::UnlockApp()
, m_showScreenSaver(false)
{
initialize();
QTimer::singleShot(0, this, SLOT(prepareShow()));
connect (desktop(), SIGNAL(resized(int)), SLOT(desktopResized()));
connect (desktop(), SIGNAL(screenCountChanged(int)), SLOT(desktopResized()));
QMetaObject::invokeMethod(this, "desktopResized", Qt::QueuedConnection);
}
UnlockApp::~UnlockApp()
......@@ -98,9 +100,6 @@ void UnlockApp::initialize()
KScreenSaverSettings::self()->readConfig();
m_showScreenSaver = KScreenSaverSettings::legacySaverEnabled();
const bool canLogout = KAuthorized::authorizeKAction("logout") && KAuthorized::authorize("logout");
const QSet<Solid::PowerManagement::SleepState> spdMethods = Solid::PowerManagement::supportedSleepStates();
m_structure = Plasma::PackageStructure::load("Plasma/Generic");
m_package = new Plasma::Package(KStandardDirs::locate("data", "ksmserver/screenlocker/"), KScreenSaverSettings::greeterQML(), m_structure);
m_mainQmlPath = m_package->filePath("mainscript");
......@@ -110,13 +109,46 @@ void UnlockApp::initialize()
m_mainQmlPath = m_package->filePath("mainscript");
}
for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) {
installEventFilter(this);
}
void UnlockApp::viewStatusChanged(const QDeclarativeView::Status &status)
{
// on error, if we did not load the default qml, try to do so now.
if (status == QDeclarativeView::Error &&
m_package->metadata().pluginName() != DEFAULT_MAIN_PACKAGE) {
if (QDeclarativeView *view = qobject_cast<QDeclarativeView *>(sender())) {
m_package = new Plasma::Package(KStandardDirs::locate("data", "ksmserver/screenlocker/"), DEFAULT_MAIN_PACKAGE, m_structure);
m_mainQmlPath = m_package->filePath("mainscript");
view->setSource(QUrl::fromLocalFile(m_mainQmlPath));
}
}
}
void UnlockApp::desktopResized()
{
const int nScreeens = QApplication::desktop()->screenCount();
// remove useless views and savers
while (m_views.count() > nScreeens) {
m_views.takeLast()->deleteLater();
}
while (m_screensaverWindows.count() > nScreeens) {
m_screensaverWindows.takeLast()->deleteLater();
}
Q_ASSERT(m_views.count() == m_screensaverWindows.count() && m_views.count() == nScreens);
// extend views and savers to current demand
const bool canLogout = KAuthorized::authorizeKAction("logout") && KAuthorized::authorize("logout");
const QSet<Solid::PowerManagement::SleepState> spdMethods = Solid::PowerManagement::supportedSleepStates();
for (int i = m_views.count(); i < nScreeens; ++i) {
// create the view
QDeclarativeView *view = new QDeclarativeView();
connect(view, SIGNAL(statusChanged(QDeclarativeView::Status)),
this, SLOT(viewStatusChanged(QDeclarativeView::Status)));
view->setWindowFlags(Qt::X11BypassWindowManagerHint);
view->setFrameStyle(QFrame::NoFrame);
view->installEventFilter(this);
// engine stuff
foreach (const QString &importPath, KGlobal::dirs()->findDirs("module", "imports")) {
......@@ -165,35 +197,10 @@ void UnlockApp::initialize()
}
}
installEventFilter(this);
}
void UnlockApp::viewStatusChanged(const QDeclarativeView::Status &status)
{
// on error, if we did not load the default qml, try to do so now.
if (status == QDeclarativeView::Error &&
m_package->metadata().pluginName() != DEFAULT_MAIN_PACKAGE) {
if (QDeclarativeView *view = qobject_cast<QDeclarativeView *>(sender())) {
m_package = new Plasma::Package(KStandardDirs::locate("data", "ksmserver/screenlocker/"), DEFAULT_MAIN_PACKAGE, m_structure);
m_mainQmlPath = m_package->filePath("mainscript");
view->setSource(QUrl::fromLocalFile(m_mainQmlPath));
}
}
}
void UnlockApp::prepareShow()
{
// mark as our window
Atom tag = XInternAtom(QX11Info::display(), "_KDE_SCREEN_LOCKER", False);
for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) {
if (i == m_views.size()) {
kError() << "Views and screens not in sync";
return;
}
// update geometry of all views and savers
for (int i = 0; i < nScreeens; ++i) {
QDeclarativeView *view = m_views.at(i);
XChangeProperty(QX11Info::display(), view->winId(), tag, tag, 32, PropModeReplace, 0, 0);
view->setGeometry(QApplication::desktop()->screenGeometry(i));
view->show();
view->activateWindow();
......@@ -201,7 +208,6 @@ void UnlockApp::prepareShow()
if (m_showScreenSaver) {
ScreenSaverWindow *screensaverWindow = m_screensaverWindows.at(i);
screensaverWindow->setGeometry(view->geometry());
XChangeProperty(QX11Info::display(), screensaverWindow->winId(), tag, tag, 32, PropModeReplace, 0, 0);
QPixmap backgroundPix(screensaverWindow->size());
QPainter p(&backgroundPix);
......@@ -213,7 +219,8 @@ void UnlockApp::prepareShow()
connect(screensaverWindow, SIGNAL(hidden()), this, SLOT(getFocus()));
}
}
QTimer::singleShot(0, this, SLOT(getFocus()));
// random state update, actually rather required on init only
QMetaObject::invokeMethod(this, "getFocus", Qt::QueuedConnection);
capsLocked();
}
......@@ -295,31 +302,80 @@ void UnlockApp::setTesting(bool enable)
bool UnlockApp::eventFilter(QObject *obj, QEvent *event)
{
Q_UNUSED(obj)
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
if (obj != this && event->type() == QEvent::Show) {
QDeclarativeView *view(0);
foreach (QDeclarativeView *v, m_views) {
if (v == obj) {
view = v;
break;
}
}
if (view && view->testAttribute(Qt::WA_WState_Created) && view->internalWinId()) {
// showing greeter view window, set property
static Atom tag = XInternAtom(QX11Info::display(), "_KDE_SCREEN_LOCKER", False);
XChangeProperty(QX11Info::display(), view->winId(), tag, tag, 32, PropModeReplace, 0, 0);
}
// no further processing
return false;
}
static bool ignoreNextEscape = false;
if (event->type() == QEvent::KeyPress) { // react if saver is visible
bool saverVisible = false;
foreach (ScreenSaverWindow *screensaverWindow, m_screensaverWindows) {
if (screensaverWindow->isVisible()) {
saverVisible = true;
break;
}
}
if (!saverVisible) {
return false; // we don't care
}
ignoreNextEscape = bool(static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape);
capsLocked();
foreach (ScreenSaverWindow *screensaverWindow, m_screensaverWindows) {
screensaverWindow->hide();
}
getFocus();
return true; // do not pass the key
} else if (event->type() == QEvent::KeyRelease) { // conditionally reshow the saver
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_CapsLock) {
capsLocked();
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_Escape) {
foreach (ScreenSaverWindow *screensaverWindow, m_screensaverWindows) {
screensaverWindow->show();
}
} else {
foreach (ScreenSaverWindow *screensaverWindow, m_screensaverWindows) {
screensaverWindow->hide();
}
getFocus();
return false;
}
if (ke->key() != Qt::Key_Escape) {
return false; // irrelevant
}
if (ignoreNextEscape) {
ignoreNextEscape = false;
return true; // it's Qt::Key_Escape;
}
bool saverVisible = true;
foreach (ScreenSaverWindow *screensaverWindow, m_screensaverWindows) {
if (!screensaverWindow->isVisible()) {
saverVisible = false;
break;
}
} else if (event->type() == QEvent::GraphicsSceneMousePress) {
QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent *>(event);
foreach (QDeclarativeView *view, m_views) {
if (view->geometry().contains(me->screenPos())) {
view->activateWindow();
view->grabKeyboard();
break;
}
}
if (saverVisible) {
return false; // we don't care
}
foreach (ScreenSaverWindow *screensaverWindow, m_screensaverWindows) {
screensaverWindow->show();
}
return true; // don't pass
} else if (event->type() == QEvent::GraphicsSceneMousePress) {
QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent *>(event);
foreach (QDeclarativeView *view, m_views) {
if (view->geometry().contains(me->screenPos())) {
view->activateWindow();
view->grabKeyboard();
break;
}
}
}
return false;
}
......
......@@ -49,7 +49,7 @@ protected:
private Q_SLOTS:
void viewStatusChanged(const QDeclarativeView::Status &status);
void prepareShow();
void desktopResized();
void resetRequestIgnore();
void suspendToRam();
void suspendToDisk();
......
......@@ -27,6 +27,7 @@
#include <QPaintEvent>
#include <QPainter>
#include <QTimer>
#include <QX11Info>
#include <KDebug>
#include <kmacroexpander.h>
......@@ -37,6 +38,11 @@
#include <KDesktopFile>
#include <KStandardDirs>
// X11
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <fixx11h.h>
namespace ScreenLocker
{
......@@ -155,6 +161,9 @@ void ScreenSaverWindow::mouseMoveEvent(QMouseEvent *event)
void ScreenSaverWindow::showEvent(QShowEvent *event)
{
m_reactivateTimer->stop();
static Atom tag = XInternAtom(QX11Info::display(), "_KDE_SCREEN_LOCKER", False);
if (testAttribute(Qt::WA_WState_Created) && internalWinId())
XChangeProperty(QX11Info::display(), winId(), tag, tag, 32, PropModeReplace, 0, 0);
startXScreenSaver();
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment