[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-active
Subject:    lockscreen and splash screen
From:       Marco Martin <notmart () gmail ! com>
Date:       2011-09-27 14:50:13
Message-ID: 201109271650.13867.notmart () gmail ! com
[Download RAW message or body]

Hi all,

I finally made work out of the box the new qml splash screen and the lock 
screen on the meego image, so here are some instructions, hoping it will be 
easy enough to adapt it to the opensuse image as well.

1) put the two humungous attached patches in the kde-workspace package (and 
add the extra installed files that will be there after the patches are 
applied)

2) package kde-artwork-active that is in svn under playground/base/plasma/kde-
artwork-active. It's svn because contains many fat binary files (the default 
wallpaper set should go there as well)

3) sync the contour-config package with the new stuff in config/ under plasma-
mobile: it kills krunner, sets the qml splash as default

4) cross fingers ;)

-- 
Marco Martin

["ksplash-qml.diff" (text/x-patch)]

diff --git a/ksplash/CMakeLists.txt b/ksplash/CMakeLists.txt
index 765a90c..0d0934b 100644
--- a/ksplash/CMakeLists.txt
+++ b/ksplash/CMakeLists.txt
@@ -2,3 +2,4 @@ add_subdirectory( ksplashx )
 add_subdirectory( simple )
 add_subdirectory( none )
 add_subdirectory( kcm )
+add_subdirectory( ksplashqml )
diff --git a/ksplash/kcm/installer.cpp b/ksplash/kcm/installer.cpp
index cada800..db2450b 100644
--- a/ksplash/kcm/installer.cpp
+++ b/ksplash/kcm/installer.cpp
@@ -184,7 +184,7 @@ SplashInstaller::~SplashInstaller()
 
 int SplashInstaller::addTheme(const QString &path, const QString &name)
 {
-  //kDebug() << "SplashInstaller::addTheme: " << path << " " << name;
+  qDebug() << "SplashInstaller::addTheme: " << path << " " << name;
   QString tmp(i18n( name.toUtf8() ));
   int i = mThemesList->count();
   while((i > 0) && (mThemesList->item(i-1)->text() > tmp))
@@ -434,7 +434,11 @@ void SplashInstaller::slotSetTheme(int id)
         infoTxt += "</qt>";
 
         QString pluginName( cnf.readEntry( "Engine", "KSplashX" ).trimmed() );
-        if( pluginName == "Simple" || pluginName == "None" || pluginName == \
"KSplashX" ) +        if( pluginName == "Simple"
+                || pluginName == "None"
+                || pluginName == "KSplashX"
+                || pluginName == "KSplashQML"
+                )
             enabled = true; // these are not plugins
         else if ((KServiceTypeTrader::self()->query("KSplash/Plugin", \
QString("[X-KSplash-PluginName] == '%1'").arg(pluginName))).isEmpty())  {
@@ -536,6 +540,7 @@ void SplashInstaller::slotTest()
     themeName = themeName.mid(r+1);
 
   // special handling for none and simple splashscreens
+  qDebug() << "the engine is " << mEngineOfSelected << "for" << themeName;
   if( mEngineOfSelected == "None" )
     return;
   else if( mEngineOfSelected == "Simple" )
@@ -554,6 +559,14 @@ void SplashInstaller::slotTest()
       KMessageBox::error(this,i18n("Failed to successfully test the splash \
screen."));  return;
   }
+  else if( mEngineOfSelected == "KSplashQML" )
+  {
+    KProcess proc;
+    proc << "ksplashqml" << themeName << "--test";
+    if (proc.execute())
+      KMessageBox::error(this,i18n("Failed to successfully test the splash \
screen.")); +    return;
+  }
   else // KSplashML engines
   {
     KProcess proc;
diff --git a/ksplash/ksplashqml/CMakeLists.txt b/ksplash/ksplashqml/CMakeLists.txt
new file mode 100644
index 0000000..fb1a4c7
--- /dev/null
+++ b/ksplash/ksplashqml/CMakeLists.txt
@@ -0,0 +1,18 @@
+project(ksplashqml)
+
+
+set(ksplashqml_SRCS
+    main.cpp
+    SplashApp.cpp
+    SplashWindow.cpp
+   )
+
+add_executable(ksplashqml ${ksplashqml_SRCS})
+
+target_link_libraries(ksplashqml
+   ${X11_LIBRARIES}
+   ${QT_QTDECLARATIVE_LIBRARY}
+   ${QT_QTUI_LIBRARY}
+   )
+
+install(TARGETS ksplashqml ${INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/ksplash/ksplashqml/SplashApp.cpp b/ksplash/ksplashqml/SplashApp.cpp
new file mode 100644
index 0000000..532bba8
--- /dev/null
+++ b/ksplash/ksplashqml/SplashApp.cpp
@@ -0,0 +1,116 @@
+/*
+ *   Copyright (C) 2010 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "SplashWindow.h"
+#include "SplashApp.h"
+
+#define TEST_STEP_INTERVAL 2000
+
+SplashApp::SplashApp(Display * display, int argc, char ** argv)
+    : QApplication(display, argc, argv),
+      m_display(display), m_stage(0), m_window(0),
+      m_testing(false)
+{
+    m_kde_splash_progress = XInternAtom(m_display, "_KDE_SPLASH_PROGRESS", False);
+    m_testing = arguments().contains("--test");
+    m_window = new SplashWindow(m_testing);
+
+    setStage(1);
+
+    int sw = WidthOfScreen(ScreenOfDisplay(display, DefaultScreen(display)));
+    int sh = HeightOfScreen(ScreenOfDisplay(display, DefaultScreen(display)));
+
+    m_window->setGeometry(0, 0, sw, sh);
+    m_window->show();
+
+    XSelectInput(display, DefaultRootWindow(display), SubstructureNotifyMask);
+
+    if (m_testing) {
+        m_timer.start(TEST_STEP_INTERVAL, this);
+    }
+}
+
+SplashApp::~SplashApp() {
+    delete m_window;
+}
+
+Display * SplashApp::display() const
+{
+    return m_display;
+}
+
+void SplashApp::timerEvent(QTimerEvent * event)
+{
+    if (event->timerId() == m_timer.timerId()) {
+        m_timer.stop();
+
+        setStage(m_stage + 1);
+
+        m_timer.start(TEST_STEP_INTERVAL, this);
+    }
+}
+
+bool SplashApp::x11EventFilter(XEvent * xe)
+{
+    char * message;
+    switch (xe->type) {
+        case ClientMessage:
+            if (xe->xclient.message_type == m_kde_splash_progress) {
+                message = xe->xclient.data.b;
+
+                int stage;
+
+                if (strcmp(message, "initial") == 0 && m_stage < 0)
+                    stage = 0; // not actually used
+                else if (strcmp(message, "kded") == 0 && m_stage < 1)
+                    stage = 1;
+                else if (strcmp(message, "confupdate") == 0 && m_stage < 2)
+                    stage = 2;
+                else if (strcmp(message, "kcminit") == 0 && m_stage < 3)
+                    stage = 3;
+                else if (strcmp(message, "ksmserver") == 0 && m_stage < 4)
+                    stage = 4;
+                else if (strcmp(message, "wm") == 0 && m_stage < 5)
+                    stage = 5;
+                else if (strcmp(message, "desktop") == 0 && m_stage < 6)
+                    stage = 6;
+
+                setStage(stage);
+            }
+    }
+    return false;
+
+}
+
+int SplashApp::x11ProcessEvent(XEvent * xe)
+{
+    Q_UNUSED(xe)
+    return 0;
+}
+
+void SplashApp::setStage(int stage)
+{
+    if (m_stage == 6) {
+        QApplication::exit(EXIT_SUCCESS);
+    }
+
+    m_stage = stage;
+    m_window->setStage(stage);
+}
+
diff --git a/ksplash/ksplashqml/SplashApp.h b/ksplash/ksplashqml/SplashApp.h
new file mode 100644
index 0000000..bc3fbdf
--- /dev/null
+++ b/ksplash/ksplashqml/SplashApp.h
@@ -0,0 +1,55 @@
+/*
+ *   Copyright (C) 2010 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SPLASH_APP_H_
+#define SPLASH_APP_H_
+
+#include <QObject>
+#include <QApplication>
+#include <QBasicTimer>
+
+#include <X11/Xlib.h>
+
+class SplashWindow;
+
+class SplashApp: public QApplication {
+
+public:
+    SplashApp(Display * display, int argc, char ** argv);
+    ~SplashApp();
+
+    Display * display() const;
+
+    bool x11EventFilter(XEvent * xe);
+    int x11ProcessEvent(XEvent * xe);
+
+protected:
+    void timerEvent(QTimerEvent * event);
+    void setStage(int stage);
+
+private:
+    Display * m_display;
+    int m_stage;
+    Atom m_kde_splash_progress;
+    SplashWindow * m_window;
+    bool m_testing;
+    QBasicTimer m_timer;
+};
+
+#endif // SPLASH_APP_H_
diff --git a/ksplash/ksplashqml/SplashWindow.cpp \
b/ksplash/ksplashqml/SplashWindow.cpp new file mode 100644
index 0000000..9999e4b
--- /dev/null
+++ b/ksplash/ksplashqml/SplashWindow.cpp
@@ -0,0 +1,77 @@
+/*
+ *   Copyright (C) 2010 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "SplashWindow.h"
+
+#include <QApplication>
+#include <QDeclarativeContext>
+#include <QGraphicsObject>
+#include <QKeyEvent>
+#include <QMouseEvent>
+
+#include "SystemInfo.h"
+
+SplashWindow::SplashWindow(bool testing)
+    : QDeclarativeView(),
+      m_stage(0),
+      m_testing(testing)
+{
+    setWindowFlags(
+            Qt::FramelessWindowHint |
+            Qt::WindowStaysOnTopHint
+        );
+
+    if (m_testing) {
+        setWindowState(Qt::WindowFullScreen);
+    }
+
+    rootContext()->setContextProperty("screenSize", size());
+    setSource(QUrl(themeDir(QApplication::arguments().at(1)) + "/main.qml"));
+    setStyleSheet("background: #000000; border: none");
+}
+
+void SplashWindow::setStage(int stage)
+{
+    m_stage = stage;
+
+    rootObject()->setProperty("stage", stage);
+}
+
+void SplashWindow::resizeEvent(QResizeEvent *event)
+{
+    Q_UNUSED(event)
+    rootContext()->setContextProperty("screenSize", size());
+    centerOn(rootObject());
+}
+
+void SplashWindow::keyPressEvent(QKeyEvent *event)
+{
+    QDeclarativeView::keyPressEvent(event);
+    if (m_testing && !event->isAccepted() && event->key() == Qt::Key_Escape) {
+        close();
+    }
+}
+
+void SplashWindow::mousePressEvent(QMouseEvent *event)
+{
+    QDeclarativeView::mousePressEvent(event);
+    if (m_testing && !event->isAccepted()) {
+        close();
+    }
+}
diff --git a/ksplash/ksplashqml/SplashWindow.h b/ksplash/ksplashqml/SplashWindow.h
new file mode 100644
index 0000000..9680c1e
--- /dev/null
+++ b/ksplash/ksplashqml/SplashWindow.h
@@ -0,0 +1,46 @@
+/*
+ *   Copyright (C) 2010 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SPLASH_WINDOW_H_
+#define SPLASH_WINDOW_H_
+
+#include <QDeclarativeView>
+
+class QResizeEvent;
+class QMouseEvent;
+class QKeyEvent;
+
+class SplashWindow: public QDeclarativeView
+{
+public:
+    SplashWindow(bool testing);
+
+    void setStage(int stage);
+
+protected:
+    virtual void resizeEvent (QResizeEvent *event);
+    virtual void keyPressEvent(QKeyEvent *event);
+    virtual void mousePressEvent(QMouseEvent *event);
+
+private:
+    int m_stage;
+    bool m_testing;
+};
+
+#endif // SPLASH_WINDOW_H_
diff --git a/ksplash/ksplashqml/SystemInfo.h b/ksplash/ksplashqml/SystemInfo.h
new file mode 100644
index 0000000..b2d5fda
--- /dev/null
+++ b/ksplash/ksplashqml/SystemInfo.h
@@ -0,0 +1,60 @@
+/*
+ *   Copyright (C) 2010 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef SYSTEM_INFO_H_
+#define SYSTEM_INFO_H_
+
+#include <stdlib.h>
+#include <config-workspace.h>
+
+#include <QDir>
+#include <QString>
+
+QString homeDir()
+{
+    const char * kdehome = getenv("KDEHOME");
+    const char * home = getenv("HOME");
+    if (kdehome && kdehome[0]) {
+        return QString() + home + "/" + KDE_DEFAULT_HOME;
+    }
+
+    return kdehome;
+}
+
+QString systemDir()
+{
+    return KDE_DATADIR;
+}
+
+QString themeDir(QString theme)
+{
+    QString path;
+
+    path = homeDir() + "/share/apps/ksplash/Themes/" + theme;
+
+    if (!QDir(path).exists()) {
+        path = systemDir() + "/ksplash/Themes/" + theme;
+    }
+
+    return path;
+}
+
+#endif // SYSTEM_INFO_H_
+
+
diff --git a/ksplash/ksplashqml/main.cpp b/ksplash/ksplashqml/main.cpp
new file mode 100644
index 0000000..ed409e2
--- /dev/null
+++ b/ksplash/ksplashqml/main.cpp
@@ -0,0 +1,66 @@
+/*
+ *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "SplashApp.h"
+
+#include <iostream>
+#include <X11/Xlib.h>
+
+int main(int argc, char **argv)
+{
+    bool test = false;
+    bool printPid = false;
+
+    for (int i = 1; i < argc; i++) {
+        if (strcmp("--test", argv[i]) == 0)
+            test = true;
+        else if (strcmp("--pid", argv[i]) == 0)
+            printPid = true;
+    }
+
+    // lets fork and all that...
+
+    if (!test) {
+        pid_t pid = fork();
+        if (pid < -1) {
+            return -1;
+        }
+
+        if (pid != 0) {
+            // this is the parent process, returning pid of the fork
+            if (printPid) {
+                std::cout << pid << std::endl;
+            }
+
+            return 0;
+        }
+
+        // close stdin,stdout,stderr, otherwise startkde will block
+        close(0);
+        close(1);
+        close(2);
+    }
+
+    Display * display = XOpenDisplay(NULL);
+
+    SplashApp app(display, argc, argv);
+
+    return app.exec();
+}
+
diff --git a/ksplash/ksplashqml/themes/CMakeLists.txt \
b/ksplash/ksplashqml/themes/CMakeLists.txt new file mode 100644
index 0000000..818070c
--- /dev/null
+++ b/ksplash/ksplashqml/themes/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(qmltest)
+add_subdirectory(qmldefault)
diff --git a/ksplash/ksplashqml/themes/qmldefault/CMakeLists.txt \
b/ksplash/ksplashqml/themes/qmldefault/CMakeLists.txt new file mode 100644
index 0000000..6f28f3b
--- /dev/null
+++ b/ksplash/ksplashqml/themes/qmldefault/CMakeLists.txt
@@ -0,0 +1,7 @@
+install(FILES Preview.png Theme.rc main.qml DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmldefault) +
+install(FILES images/kdegear.png DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmldefault/images) +install(FILES \
images/kdeletter.png DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmldefault/images) +install(FILES \
images/kdemask.png DESTINATION ${DATA_INSTALL_DIR}/ksplash/Themes/qmldefault/images) \
+install(FILES images/kdelogo.png DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmldefault/images) +install(FILES \
images/kdelogo-contrast.png DESTINATION \
                ${DATA_INSTALL_DIR}/ksplash/Themes/qmldefault/images)
diff --git a/ksplash/ksplashqml/themes/qmldefault/Preview.png \
b/ksplash/ksplashqml/themes/qmldefault/Preview.png new file mode 100644
index 0000000..532adf7
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmldefault/Preview.png differ
diff --git a/ksplash/ksplashqml/themes/qmldefault/Theme.rc \
b/ksplash/ksplashqml/themes/qmldefault/Theme.rc new file mode 100644
index 0000000..4dc90f8
--- /dev/null
+++ b/ksplash/ksplashqml/themes/qmldefault/Theme.rc
@@ -0,0 +1,9 @@
+[KSplash Theme: qmldefault]
+Name = Minimalistic splash screen
+Description = Animated KDE logo on a black background
+Version = 1.0
+Author = Ivan Cukic <ivan.cukic at kde.org>
+Homepage = http://www.kde.org
+
+# Theme behaviour settings.
+Engine = KSplashQML
diff --git a/ksplash/ksplashqml/themes/qmldefault/images/kdegear.png \
b/ksplash/ksplashqml/themes/qmldefault/images/kdegear.png new file mode 100644
index 0000000..66a50c2
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmldefault/images/kdegear.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmldefault/images/kdeletter.png \
b/ksplash/ksplashqml/themes/qmldefault/images/kdeletter.png new file mode 100644
index 0000000..cabe17c
Binary files /dev/null and \
                b/ksplash/ksplashqml/themes/qmldefault/images/kdeletter.png differ
diff --git a/ksplash/ksplashqml/themes/qmldefault/images/kdelogo-contrast.png \
b/ksplash/ksplashqml/themes/qmldefault/images/kdelogo-contrast.png new file mode \
100644 index 0000000..fe60715
Binary files /dev/null and \
                b/ksplash/ksplashqml/themes/qmldefault/images/kdelogo-contrast.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmldefault/images/kdelogo.png \
b/ksplash/ksplashqml/themes/qmldefault/images/kdelogo.png new file mode 100644
index 0000000..d637b37
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmldefault/images/kdelogo.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmldefault/images/kdemask.png \
b/ksplash/ksplashqml/themes/qmldefault/images/kdemask.png new file mode 100644
index 0000000..50319fc
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmldefault/images/kdemask.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmldefault/main.qml \
b/ksplash/ksplashqml/themes/qmldefault/main.qml new file mode 100644
index 0000000..90a5494
--- /dev/null
+++ b/ksplash/ksplashqml/themes/qmldefault/main.qml
@@ -0,0 +1,189 @@
+/*   vim:set foldenable foldmethod=marker:
+ *
+ *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+import Qt 4.7
+
+Item {
+    id: main
+
+    width: screenSize.width
+    height: screenSize.height
+    // width: 300
+    // height: 300
+
+    /* property declarations --------------------------{{{ */
+    property int stage
+    property int iconSize: (screenSize.width <= 1024) ? 64 : 128
+    /* }}} */
+
+    /* signal declarations ----------------------------{{{ */
+
+    /* }}} */
+
+    /* JavaScript functions ---------------------------{{{ */
+    onStageChanged: {
+        if (stage == 1) {
+            background.opacity = 1
+            gear.opacity = 0.5
+        }
+        if (stage == 2) {
+            gear.opacity = 1
+            mask.opacity = 1
+            letter.opacity = 1
+        }
+        if (stage == 3) {
+        }
+        if (stage == 4) {
+        }
+        if (stage == 5) {
+            logo.opacity = 1
+        }
+        if (stage == 6) {
+        }
+    }
+    /* }}} */
+
+    /* object properties ------------------------------{{{ */
+
+    /* }}} */
+
+    /* child objects ----------------------------------{{{ */
+
+    Rectangle {
+        color: "black"
+        anchors.fill: parent
+    }
+
+    Rectangle {
+        id: background
+
+        gradient: Gradient {
+            GradientStop { position: 0.0; color: "#55555f" }
+            GradientStop { position: 1.0; color: "#000000" }
+        }
+
+        anchors {
+            top: parent.top
+            left: parent.left
+            right: parent.right
+        }
+
+        height: gear.y - 32
+
+        opacity: 0
+        Behavior on opacity { NumberAnimation { duration: 1000; easing { type: \
Easing.InOutQuad } } } +    }
+
+    Image {
+        id: gear
+
+        height: iconSize
+        width: iconSize
+        smooth: true
+
+        x: (parent.width - width) / 2
+        y: (parent.height - height) / 2
+
+        source: "images/kdegear.png"
+
+        opacity: 0
+        Behavior on opacity { NumberAnimation { duration: 1000; easing { type: \
Easing.InOutQuad } } } +
+        NumberAnimation {
+            id: animateRotation
+            target: gear
+            properties: "rotation"
+            from: 0
+            to: 360
+            duration: 5000
+
+            loops: Animation.Infinite
+            running: true
+        }
+
+    }
+
+    Image {
+        id: mask
+
+        height: iconSize
+        width: iconSize
+        smooth: true
+
+        x: (parent.width - width) / 2
+        y: (parent.height - height) / 2
+
+        source: "images/kdemask.png"
+
+        opacity: 0
+        Behavior on opacity { NumberAnimation { duration: 1000; easing { type: \
Easing.InOutQuad } } } +    }
+
+    Image {
+        id: letter
+
+        height: iconSize
+        width: iconSize
+        smooth: true
+
+        x: (parent.width - width) / 2
+        y: (parent.height - height) / 2
+
+        source: "images/kdeletter.png"
+
+        opacity: 0
+        Behavior on opacity { NumberAnimation { duration: 1000; easing { type: \
Easing.InOutQuad } } } +    }
+
+    Image {
+        id: logo
+
+        height: iconSize
+        width: iconSize
+        smooth: true
+
+        x: (parent.width - width) / 2
+        y: (parent.height - height) / 2 - 1
+
+        source: "images/kdelogo-contrast.png"
+
+        opacity: 0
+        Behavior on opacity { NumberAnimation { duration: 1000; easing { type: \
Easing.InOutQuad } } } +
+        Text {
+            text: "KDE Workspaces 4.7 'Friday'"
+            color: "white"
+
+            x: logo.width + 8
+            y: (logo.height - height) / 2
+        }
+    }
+
+    /* }}} */
+
+    /* stages -----------------------------------------{{{ */
+
+    /* }}} */
+
+    /* transitions ------------------------------------{{{ */
+
+    /* }}} */
+}
+
diff --git a/ksplash/ksplashqml/themes/qmltest/CMakeLists.txt \
b/ksplash/ksplashqml/themes/qmltest/CMakeLists.txt new file mode 100644
index 0000000..9b2e59d
--- /dev/null
+++ b/ksplash/ksplashqml/themes/qmltest/CMakeLists.txt
@@ -0,0 +1,9 @@
+install(FILES Preview.png Theme.rc main.qml DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmltest) +
+install(FILES images/background.jpg DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmltest/images) +install(FILES \
images/configuring.png DESTINATION ${DATA_INSTALL_DIR}/ksplash/Themes/qmltest/images) \
+install(FILES images/desktop.png DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmltest/images) +install(FILES images/globe.png \
DESTINATION ${DATA_INSTALL_DIR}/ksplash/Themes/qmltest/images) +install(FILES \
images/hardware.png DESTINATION ${DATA_INSTALL_DIR}/ksplash/Themes/qmltest/images) \
+install(FILES images/kde.png DESTINATION \
${DATA_INSTALL_DIR}/ksplash/Themes/qmltest/images) +install(FILES images/plasma.png \
                DESTINATION ${DATA_INSTALL_DIR}/ksplash/Themes/qmltest/images)
diff --git a/ksplash/ksplashqml/themes/qmltest/Preview.png \
b/ksplash/ksplashqml/themes/qmltest/Preview.png new file mode 100644
index 0000000..398c037
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/Preview.png differ
diff --git a/ksplash/ksplashqml/themes/qmltest/Theme.rc \
b/ksplash/ksplashqml/themes/qmltest/Theme.rc new file mode 100644
index 0000000..8088c20
--- /dev/null
+++ b/ksplash/ksplashqml/themes/qmltest/Theme.rc
@@ -0,0 +1,9 @@
+[KSplash Theme: QMLtest]
+Name = Default Splash Screen
+Description = Air and Horos Splash Screen
+Version = 1.0
+Author = Nuno Pinheiro <nuno@oxygen-icons.org>, Riccardo Iaconelli \
<riccardo@kde.org> and Marco Martin <notmart@gmail.com> +Homepage = \
http://www.kde.org +
+# Theme behaviour settings.
+Engine = KSplashQML
diff --git a/ksplash/ksplashqml/themes/qmltest/images/background.jpg \
b/ksplash/ksplashqml/themes/qmltest/images/background.jpg new file mode 100644
index 0000000..8d3027c
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/images/background.jpg \
                differ
diff --git a/ksplash/ksplashqml/themes/qmltest/images/configuring.png \
b/ksplash/ksplashqml/themes/qmltest/images/configuring.png new file mode 100644
index 0000000..9ea5cec
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/images/configuring.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmltest/images/desktop.png \
b/ksplash/ksplashqml/themes/qmltest/images/desktop.png new file mode 100644
index 0000000..98153f2
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/images/desktop.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmltest/images/globe.png \
b/ksplash/ksplashqml/themes/qmltest/images/globe.png new file mode 100644
index 0000000..193c46f
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/images/globe.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmltest/images/hardware.png \
b/ksplash/ksplashqml/themes/qmltest/images/hardware.png new file mode 100644
index 0000000..68351d1
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/images/hardware.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmltest/images/kde.png \
b/ksplash/ksplashqml/themes/qmltest/images/kde.png new file mode 100644
index 0000000..3efaaf8
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/images/kde.png differ
diff --git a/ksplash/ksplashqml/themes/qmltest/images/plasma.png \
b/ksplash/ksplashqml/themes/qmltest/images/plasma.png new file mode 100644
index 0000000..facbd77
Binary files /dev/null and b/ksplash/ksplashqml/themes/qmltest/images/plasma.png \
                differ
diff --git a/ksplash/ksplashqml/themes/qmltest/main.qml \
b/ksplash/ksplashqml/themes/qmltest/main.qml new file mode 100644
index 0000000..e0b8a1b
--- /dev/null
+++ b/ksplash/ksplashqml/themes/qmltest/main.qml
@@ -0,0 +1,164 @@
+/*   vim:set foldenable foldmethod=marker:
+ *
+ *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details
+ *
+ *   You should have received a copy of the GNU General Public
+ *   License along with this program; if not, write to the
+ *   Free Software Foundation, Inc.,
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+import Qt 4.7 as QML
+
+QML.Item {
+    id: main
+
+    width: screenSize.width
+    height: screenSize.height
+
+    /* property declarations --------------------------{{{ */
+    property int stage
+    /* }}} */
+
+    /* signal declarations ----------------------------{{{ */
+
+    /* }}} */
+
+    /* JavaScript functions ---------------------------{{{ */
+    onStageChanged: {
+        if (stage == 2) {
+            stage1.x = (main.width - stage1.width) / 2
+            stage1.opacity = 1
+        }
+        if (stage == 3) {
+            stage1.x = - stage1.width
+            stage2.x = (main.width - stage2.width) / 2
+            stage1.opacity = 0
+            stage2.opacity = 1
+        }
+        if (stage == 4) {
+            stage2.x = - stage2.width
+            stage3.x = (main.width - stage3.width) / 2
+            stage2.opacity = 0
+            stage3.opacity = 1
+        }
+        if (stage == 5) {
+            stage3.x = - stage3.width
+            stage4.x = (main.width - stage4.width) / 2
+            stage3.opacity = 0
+            stage4.opacity = 1
+        }
+        if (stage == 6) {
+            stage4.x = - stage4.width
+            stage5.x = (main.width - stage5.width) / 2
+            stage4.opacity = 0
+            stage5.opacity = 1
+            stage5.width = 128
+            stage5.height = 128
+        }
+    }
+    /* }}} */
+
+    /* object properties ------------------------------{{{ */
+
+    /* }}} */
+
+    /* child objects ----------------------------------{{{ */
+    QML.Image {
+        anchors.fill: parent
+
+        source: "images/background.jpg"
+    }
+
+    QML.Rectangle {
+        width: parent.width
+        height: 100
+        x: 0
+        y: (parent.height - height) / 2
+        color: "#ffffff"
+        opacity: 0.2
+    }
+
+    QML.Image {
+        id: stage1
+        x: main.width + width
+        y: (main.height - height) / 2
+        source: "images/hardware.png"
+        QML.Behavior on x { QML.NumberAnimation { duration: 1000; easing { type: \
QML.Easing.InOutQuad } } } +        opacity: 0
+        QML.Behavior on opacity { QML.NumberAnimation { duration: 1000; easing { \
type: QML.Easing.InOutQuad } } } +
+        QML.Image { y: 128; x: parent.x - main.width / 2; height: 128; width: 128; \
opacity: 0.2 * parent.opacity; source: parent.source } +    }
+
+    QML.Image {
+        id: stage2
+        x: main.width + width
+        y: (main.height - height) / 2
+        source: "images/configuring.png"
+        QML.Behavior on x { QML.NumberAnimation { duration: 1000; easing { type: \
QML.Easing.InOutQuad } } } +        opacity: 0
+        QML.Behavior on opacity { QML.NumberAnimation { duration: 1000; easing { \
type: QML.Easing.InOutQuad } } } +
+        QML.Image { y: 128; x: parent.x - main.width / 2; height: 128; width: 128; \
opacity: 0.2 * parent.opacity; source: parent.source } +    }
+
+    QML.Image {
+        id: stage3
+        x: main.width + width
+        y: (main.height - height) / 2
+        source: "images/globe.png"
+        QML.Behavior on x { QML.NumberAnimation { duration: 1000; easing { type: \
QML.Easing.InOutQuad } } } +        opacity: 0
+        QML.Behavior on opacity { QML.NumberAnimation { duration: 1000; easing { \
type: QML.Easing.InOutQuad } } } +
+        QML.Image { y: 128; x: parent.x - main.width / 2; height: 128; width: 128; \
opacity: 0.2 * parent.opacity; source: parent.source } +    }
+
+    QML.Image {
+        id: stage4
+        x: main.width + width
+        y: (main.height - height) / 2
+        source: "images/desktop.png"
+        QML.Behavior on x { QML.NumberAnimation { duration: 1000; easing { type: \
QML.Easing.InOutQuad } } } +        opacity: 0
+        QML.Behavior on opacity { QML.NumberAnimation { duration: 1000; easing { \
type: QML.Easing.InOutQuad } } } +
+        QML.Image { y: 128; x: parent.x - main.width / 2; height: 128; width: 128; \
opacity: 0.2 * parent.opacity; source: parent.source } +    }
+
+    QML.Image {
+        id: stage5
+        x: main.width + width
+        y: (main.height - height) / 2
+        source: "images/kde.png"
+        QML.Behavior on x { QML.NumberAnimation { duration: 1000; easing { type: \
QML.Easing.InOutQuad } } } +        QML.Behavior on width { QML.NumberAnimation { \
duration: 1000; easing { type: QML.Easing.InOutQuad } } } +        QML.Behavior on \
height { QML.NumberAnimation { duration: 1000; easing { type: QML.Easing.InOutQuad } \
} } +        opacity: 0
+        QML.Behavior on opacity { QML.NumberAnimation { duration: 1000; easing { \
type: QML.Easing.InOutQuad } } } +
+        // QML.Image { y: 128; x: parent.x - main.width / 2; height: 128; width: \
128; opacity: 0.2 * parent.opacity; source: parent.source } +    }
+
+    /* }}} */
+
+    /* stages -----------------------------------------{{{ */
+
+    /* }}} */
+
+    /* transitions ------------------------------------{{{ */
+
+    /* }}} */
+}
+
diff --git a/kwin/composite.cpp b/kwin/composite.cpp
index a8bb42e..323d589 100644
--- a/kwin/composite.cpp
+++ b/kwin/composite.cpp
@@ -836,7 +836,10 @@ bool Unmanaged::shouldUnredirect() const
 {
     // the pixmap is needed for the login effect, a nicer solution would be the \
                login effect increasing
     // refcount for the window pixmap (which would prevent unredirect), avoiding \
                this hack
-    if (resourceClass() == "ksplashx" || resourceClass() == "ksplashsimple")
+    if (resourceClass() == "ksplashx"
+            || resourceClass() == "ksplashsimple"
+            || resourceClass() == "ksplashqml"
+            )
         return false;
 // it must cover whole display or one xinerama screen, and be the topmost there
     if (geometry() == workspace()->clientArea(FullArea, geometry().center(), \
                workspace()->currentDesktop())
diff --git a/kwin/effects/fade/fade.cpp b/kwin/effects/fade/fade.cpp
index 17f39a8..1a54eb0 100644
--- a/kwin/effects/fade/fade.cpp
+++ b/kwin/effects/fade/fade.cpp
@@ -194,6 +194,7 @@ bool FadeEffect::isFadeWindow(EffectWindow* w)
         e = w->data(WindowAddedGrabRole).value<void*>();
     if (w->windowClass() == "ksplashx ksplashx"
             || w->windowClass() == "ksplashsimple ksplashsimple"
+            || w->windowClass() == "qt-subapplication ksplashqml"
             || (e && e != this)) {
         // see login effect
         return false;
diff --git a/kwin/effects/login/login.cpp b/kwin/effects/login/login.cpp
index 63d8479..a9da287 100644
--- a/kwin/effects/login/login.cpp
+++ b/kwin/effects/login/login.cpp
@@ -111,7 +111,8 @@ bool LoginEffect::isLoginSplash(EffectWindow* w)
     // TODO there should be probably a better way (window type?)
     // see also fade effect and composite.cpp
     if (w->windowClass() == "ksplashx ksplashx"
-            || w->windowClass() == "ksplashsimple ksplashsimple") {
+            || w->windowClass() == "ksplashsimple ksplashsimple"
+            || w->windowClass() == "qt-subapplication ksplashqml") {
         return true;
     }
     return false;
diff --git a/startkde.cmake b/startkde.cmake
index 627dadb..1070785 100644
--- a/startkde.cmake
+++ b/startkde.cmake
@@ -151,6 +151,9 @@ if test -z "$dl"; then
     KSplashX)
       ksplash_pid=`ksplashx "${ksplashrc_ksplash_theme}" --pid`
       ;;
+    KSplashQML)
+      ksplash_pid=`ksplashqml "${ksplashrc_ksplash_theme}" --pid`
+      ;;
     None)
       ;;
     Simple)
@@ -356,11 +359,11 @@ fi
 # if KDEWM is not set, ksmserver will ensure kwin is started.
 # kwrapper4 is used to reduce startup time and memory usage
 # kwrapper4 does not return useful error codes such as the exit code of ksmserver.
-# We only check for 255 which means that the ksmserver process could not be 
-# started, any problems thereafter, e.g. ksmserver failing to initialize, 
+# We only check for 255 which means that the ksmserver process could not be
+# started, any problems thereafter, e.g. ksmserver failing to initialize,
 # will remain undetected.
 test -n "$KDEWM" && KDEWM="--windowmanager $KDEWM"
-kwrapper4 ksmserver $KDEWM 
+kwrapper4 ksmserver $KDEWM
 if test $? -eq 255; then
   # Startup error
   echo 'startkde: Could not start ksmserver. Check your installation.'  1>&2


["kwin-screenlocker.diff" (text/x-patch)]

diff --git a/kwin/CMakeLists.txt b/kwin/CMakeLists.txt
index 45651c1..1405aa6 100644
--- a/kwin/CMakeLists.txt
+++ b/kwin/CMakeLists.txt
@@ -46,21 +46,29 @@ OPTION(KWIN_BUILD_DECORATIONS "Enable building of KWin \
decorations." ON)  OPTION(KWIN_BUILD_KCMS "Enable building of KWin configuration \
modules." ON)  OPTION(KWIN_MOBILE_EFFECTS "Only build effects relevant for mobile \
devices" OFF)  
+# screensaver/locking stuff:
+macro_bool_to_01(X11_Xscreensaver_FOUND HAVE_XSCREENSAVER)
+macro_log_feature(HAVE_XSCREENSAVER "libxss" "XScreenSaver Library" \
"http://www.x.org/" FALSE "" "Needed to enable screensaver status check") +
 # for things that are also used by kwin libraries
 configure_file(libkwineffects/kwinconfig.h.cmake \
${CMAKE_CURRENT_BINARY_DIR}/libkwineffects/kwinconfig.h )  # for kwin internal things
 configure_file(config-kwin.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kwin.h )
-
+# for screensaver/locking
+configure_file(screenlocker/config-xautolock.h.cmake \
${CMAKE_CURRENT_BINARY_DIR}/screenlocker/config-xautolock.h)  
 ########### global ###############
 
 include_directories(
     ${CMAKE_CURRENT_BINARY_DIR}/libkwineffects
     ${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_CURRENT_BINARY_DIR}/screenlocker
     ${CMAKE_CURRENT_SOURCE_DIR}/libkwineffects
     ${CMAKE_CURRENT_SOURCE_DIR}/libkdecorations
     ${CMAKE_CURRENT_SOURCE_DIR}/effects
     ${CMAKE_CURRENT_SOURCE_DIR}/tabbox
+    ${CMAKE_CURRENT_SOURCE_DIR}/screenlocker/
+    ${CMAKE_CURRENT_SOURCE_DIR}/screenlocker/screensaver
     ${KDEBASE_WORKSPACE_SOURCE_DIR}/libs/kephal
     ${KDEBASE_WORKSPACE_SOURCE_DIR}/libs/kworkspace
     )
@@ -159,8 +167,23 @@ set(kwin_KDEINIT_SRCS
 
    # floating
    tilinglayouts/floating/floating.cpp
+
+   # screensaver activation
+   screenlocker/screenlocker.cpp
+   screenlocker/screensaver/saverengine.cpp
+   screenlocker/screensaver/xautolock.cpp
+   screenlocker/screensaver/xautolock_diy.c
+   screenlocker/screensaver/xautolock_engine.c
    )
 
+set(screensaver_dbusXML screenlocker/dbus/org.freedesktop.ScreenSaver.xml)
+set(kscreensaver_dbusXML screenlocker/dbus/org.kde.screensaver.xml)
+
+kde4_add_kcfg_files( kwin_KDEINIT_SRCS screenlocker/kcfg/kscreensaversettings.kcfgc \
) +
+qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS ${screensaver_dbusXML} saverengine.h \
SaverEngine) +qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS ${kscreensaver_dbusXML} \
saverengine.h SaverEngine kscreensaveradaptor KScreenSaverAdaptor) +
 qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml workspace.h KWin::Workspace \
)  
 qt4_add_dbus_interface( kwin_KDEINIT_SRCS
@@ -172,6 +195,10 @@ kde4_add_kdeinit_executable( kwin ${kwin_KDEINIT_SRCS})
 
 target_link_libraries(kdeinit_kwin ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} \
${QT_QTXML_LIBRARY} ${QT_QTSCRIPT_LIBRARY} kephal kworkspace kdecorations kwineffects \
${X11_LIBRARIES})  
+if(X11_Xscreensaver_FOUND)
+  target_link_libraries(kdeinit_kwin ${kwinLibs} ${X11_Xscreensaver_LIB})
+endif(X11_Xscreensaver_FOUND)
+
 if(OPENGL_FOUND AND NOT KWIN_HAVE_OPENGLES_COMPOSITING)
   add_subdirectory(opengltest)
   target_link_libraries(kdeinit_kwin ${OPENGL_gl_LIBRARY})
@@ -224,6 +251,8 @@ install(TARGETS kwinnvidiahack ${INSTALL_TARGETS_DEFAULT_ARGS} \
LIBRARY NAMELINK_  install( FILES kwin.kcfg  DESTINATION  ${KCFG_INSTALL_DIR} )
 install( FILES kwin.notifyrc  DESTINATION  ${DATA_INSTALL_DIR}/kwin )
 install( FILES org.kde.KWin.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR} )
+install( FILES ${screensaver_dbusXML} DESTINATION ${DBUS_INTERFACES_INSTALL_DIR} )
+install( FILES ${kscreensaver_dbusXML} DESTINATION ${DBUS_INTERFACES_INSTALL_DIR} )
 install( FILES tabbox/DefaultTabBoxLayouts.xml DESTINATION ${DATA_INSTALL_DIR}/kwin \
)  
 kde4_install_icons( ${ICON_INSTALL_DIR} )
diff --git a/kwin/effects.cpp b/kwin/effects.cpp
index f5863fc0..d537fa5 100644
--- a/kwin/effects.cpp
+++ b/kwin/effects.cpp
@@ -30,6 +30,7 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "tabbox.h"
 #include "workspace.h"
 #include "kwinglutils.h"
+#include "screenlocker/screenlocker.h"
 
 #include <QFile>
 
@@ -96,6 +97,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type)
     , next_window_quad_type(EFFECT_QUAD_TYPE_START)
     , mouse_poll_ref_count(0)
     , current_paint_effectframe(0)
+    , m_activeScreenLockEffect(NULL)
 {
     Workspace *ws = Workspace::self();
     connect(ws, SIGNAL(currentDesktopChanged(int)), this, \
SLOT(slotDesktopChanged(int))); @@ -1189,6 +1191,17 @@ EffectFrame* \
EffectsHandlerImpl::effectFrame(EffectFrameStyle style, bool static  return new \
EffectFrameImpl(style, staticSize, position, alignment);  }
 
+
+QVariant EffectsHandlerImpl::kwinOption(KWinOption kwopt)
+{
+    switch (kwopt)
+    {
+        case CloseButtonCorner:
+            return Workspace::self()->decorationCloseButtonCorner();
+    }
+    return QVariant(); // an invalid one
+}
+
 void EffectsHandlerImpl::slotShowOutline(const QRect& geometry)
 {
     emit showOutline(geometry);
@@ -1199,6 +1212,37 @@ void EffectsHandlerImpl::slotHideOutline()
     emit hideOutline();
 }
 
+static bool s_prepareLock = false;
+bool EffectsHandlerImpl::lockScreen()
+{
+    s_prepareLock = true;
+    emit requestScreenLock();
+    s_prepareLock = false;
+    return isScreenLockerReferenced();
+}
+
+void EffectsHandlerImpl::refScreenLocker(Effect* lockEffect)
+{
+    if (m_activeScreenLockEffect || !s_prepareLock) {
+        return;
+    }
+    m_activeScreenLockEffect = lockEffect;
+}
+
+void EffectsHandlerImpl::unrefScreenLocker(Effect* lockEffect)
+{
+    if (m_activeScreenLockEffect != lockEffect) {
+        return;
+    }
+    m_activeScreenLockEffect = NULL;
+    Workspace::self()->screenLocker()->unlock();
+}
+
+bool EffectsHandlerImpl::isScreenLockerReferenced() const
+{
+    return m_activeScreenLockEffect != NULL;
+}
+
 //****************************************
 // EffectWindowImpl
 //****************************************
diff --git a/kwin/effects.h b/kwin/effects.h
index abff777..3a626b1 100644
--- a/kwin/effects.h
+++ b/kwin/effects.h
@@ -151,6 +151,12 @@ public:
 
     virtual EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize, const \
QPoint& position, Qt::Alignment alignment) const;  
+    virtual QVariant kwinOption(KWinOption kwopt);
+
+    virtual void refScreenLocker(Effect *lockEffect);
+    virtual void unrefScreenLocker(Effect *lockEffect);
+    virtual bool isScreenLockerReferenced() const;
+
     // internal (used by kwin core or compositing code)
     void startPaint();
     bool borderActivated(ElectricBorder border);
@@ -167,6 +173,13 @@ public:
 
     QList<EffectWindow*> elevatedWindows() const;
 
+    /**
+     * Passes the request to lock the screen to the effects and returns whether an \
effect +     * will handle the screen locking.
+     * @returns @c true in case an effect handles the screen locking, @c false \
otherwise. +     **/
+    bool lockScreen();
+
 public Q_SLOTS:
     void slotClientGroupItemSwitched(EffectWindow* from, EffectWindow* to);
     void slotClientGroupItemAdded(EffectWindow* from, EffectWindow* to);
@@ -209,6 +222,15 @@ protected:
     int next_window_quad_type;
     int mouse_poll_ref_count;
     int current_paint_effectframe;
+
+private:
+    QList< Effect* > m_activeEffects;
+    QList< Effect* >::iterator m_currentDrawWindowIterator;
+    QList< Effect* >::iterator m_currentPaintWindowIterator;
+    QList< Effect* >::iterator m_currentPaintEffectFrameIterator;
+    QList< Effect* >::iterator m_currentPaintScreenIterator;
+    QList< Effect* >::iterator m_currentBuildQuadsIterator;
+    Effect *m_activeScreenLockEffect;
 };
 
 class EffectWindowImpl : public EffectWindow
diff --git a/kwin/effects/CMakeLists.txt b/kwin/effects/CMakeLists.txt
index 0312ac2..fa47082 100644
--- a/kwin/effects/CMakeLists.txt
+++ b/kwin/effects/CMakeLists.txt
@@ -7,7 +7,7 @@ kde4_no_enable_final(kwineffects)
 # Adds effect plugin with given name. Sources are given after the name
 macro( KWIN4_ADD_EFFECT name )
     kde4_add_plugin( kwin4_effect_${name} ${ARGN} )
-    target_link_libraries( kwin4_effect_${name} kwineffects ${KDE4_KDEUI_LIBS} \
kephal ${KDE4_PLASMA_LIBS} ${X11_Xfixes_LIB} ${X11_Xcursor_LIB}) +    \
target_link_libraries( kwin4_effect_${name} kwineffects ${KDE4_KDEUI_LIBS} kephal \
${KDE4_PLASMA_LIBS} ${X11_Xfixes_LIB} ${X11_Xcursor_LIB} ${QT_QTDECLARATIVE_LIBRARY} \
kdeclarative)  if (X11_Xfixes_FOUND)
         target_link_libraries(kwin4_effect_${name} ${X11_Xfixes_LIB})
     endif (X11_Xfixes_FOUND)
@@ -62,6 +62,7 @@ include( fade/CMakeLists.txt )
 include( login/CMakeLists.txt )
 include( outline/CMakeLists.txt )
 include( presentwindows/CMakeLists.txt )
+include( screenlocker/CMakeLists.txt )
 include( slidingpopups/CMakeLists.txt )
 include( taskbarthumbnail/CMakeLists.txt )
 
diff --git a/kwin/effects/presentwindows/presentwindows.cpp \
b/kwin/effects/presentwindows/presentwindows.cpp index a0e8306..bea897b 100755
--- a/kwin/effects/presentwindows/presentwindows.cpp
+++ b/kwin/effects/presentwindows/presentwindows.cpp
@@ -295,9 +295,12 @@ void PresentWindowsEffect::prePaintWindow(EffectWindow *w, \
WindowPrePaintData &d  } else if (winData->opacity != 1.0)
             data.setTranslucent();
 
+        const bool isInMotion = m_motionManager.isManaging(w);
         // Calculate window's brightness
         if (w == m_highlightedWindow || w == m_closeWindow || !m_activated)
             winData->highlight = qMin(1.0, winData->highlight + time / \
m_fadeDuration); +        else if (!isInMotion && w->isDesktop())
+            winData->highlight = 0.3;
         else
             winData->highlight = qMax(0.0, winData->highlight - time / \
m_fadeDuration);  
@@ -317,7 +320,7 @@ void PresentWindowsEffect::prePaintWindow(EffectWindow *w, \
WindowPrePaintData &d  if (w->isDesktop() && !w->isOnCurrentDesktop())
             w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
 
-        if (m_motionManager.isManaging(w))
+        if (isInMotion)
             data.setTransformed(); // We will be moving this window
     }
     effects->prePaintWindow(w, data, time);
@@ -333,15 +336,50 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int \
mask, QRegion region  return;
         }
 
+        mask |= PAINT_WINDOW_LANCZOS;
         // Apply opacity and brightness
         data.opacity *= winData->opacity;
-        data.brightness *= interpolate(0.7, 1.0, winData->highlight);
+        data.brightness *= interpolate(0.40, 1.0, winData->highlight);
 
         if (m_motionManager.isManaging(w)) {
+            if (w->isDesktop())
+                effects->paintWindow(w, mask, region, data);
             m_motionManager.apply(w, data);
+            QRect rect = m_motionManager.transformedGeometry(w).toRect();
+
+            if (winData->highlight > 0.0) {
+                // scale the window (interpolated by the highlight level) to at \
least 105% or to cover 1/16 of the screen size - yet keep it in screen bounds +       \
QRect area = effects->clientArea(FullScreenArea, w); +                QSizeF \
effSize(w->width()*data.xScale, w->height()*data.yScale); +                float \
tScale = sqrt((area.width()*area.height()) / \
(16.0*effSize.width()*effSize.height())); +                if (tScale < 1.05)
+                    tScale = 1.05;
+                if (effSize.width()*tScale > area.width())
+                    tScale = area.width() / effSize.width();
+                if (effSize.height()*tScale > area.height())
+                    tScale = area.height() / effSize.height();
+                const float scale = interpolate(1.0, tScale, winData->highlight);
+                if (scale > 1.0) {
+                    if (scale < tScale) // don't use lanczos during transition
+                        mask &= ~PAINT_WINDOW_LANCZOS;
+
+                    const QPoint ac = area.center();
+                    const QPoint wc = rect.center();
+
+                    data.xScale *= scale;
+                    data.yScale *= scale;
+                    const int tx = -w->width()*data.xScale*(scale-1.0)*(0.5+(wc.x() \
- ac.x())/area.width()); +                    const int ty = \
-w->height()*data.yScale*(scale-1.0)*(0.5+(wc.y() - ac.y())/area.height()); +         \
rect.translate(tx,ty); +                    rect.setWidth(rect.width()*scale);
+                    rect.setHeight(rect.height()*scale);
+                    data.xTranslate += tx;
+                    data.yTranslate += ty;
+                }
+            }
 
-            if (!m_motionManager.areWindowsMoving()) {
-                mask |= PAINT_WINDOW_LANCZOS;
+            if (m_motionManager.areWindowsMoving()) {
+                mask &= ~PAINT_WINDOW_LANCZOS;
             }
             if (m_dragInProgress && m_dragWindow == w) {
                 QPoint diff = cursorPos() - m_dragStart;
@@ -350,7 +388,7 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, \
QRegion region  }
             effects->paintWindow(w, mask, region, data);
 
-            QRect rect = m_motionManager.transformedGeometry(w).toRect();
+
             if (m_showIcons) {
                 QPoint point(rect.x() + rect.width() * 0.95,
                              rect.y() + rect.height() * 0.95);
@@ -484,7 +522,7 @@ void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent \
*e)  }
         if (m_closeView->isVisible()) {
             const QPoint widgetPos = m_closeView->mapFromGlobal(me->pos());
-            const QPointF scenePos = m_closeView->mapToScene(widgetPos);
+//             const QPointF scenePos = m_closeView->mapToScene(widgetPos);
             QMouseEvent event(me->type(), widgetPos, me->pos(), me->button(), \
me->buttons(), me->modifiers());  m_closeView->windowInputMouseEvent(&event);
             return;
@@ -1546,6 +1584,7 @@ void PresentWindowsEffect::setActive(bool active, bool \
closingTab)  }
     m_activated = active;
     if (m_activated) {
+        m_closeButtonCorner = \
(Qt::Corner)effects->kwinOption(KWin::CloseButtonCorner).toInt();  m_decalOpacity = \
0.0;  m_highlightedWindow = NULL;
         m_windowFilter.clear();
@@ -1648,6 +1687,8 @@ void PresentWindowsEffect::setActive(bool active, bool \
closingTab)  }
         }
     } else {
+        if (m_highlightedWindow)
+            effects->setElevatedWindow(m_highlightedWindow, false);
         // Fade in/out all windows
         EffectWindow *activeWindow = effects->activeWindow();
         if (m_tabBoxEnabled)
@@ -1752,32 +1793,65 @@ void PresentWindowsEffect::setHighlightedWindow(EffectWindow \
*w)  return;
 
     m_closeView->hide();
-    if (m_highlightedWindow)
+    if (m_highlightedWindow) {
+        effects->setElevatedWindow(m_highlightedWindow, false);
         m_highlightedWindow->addRepaintFull(); // Trigger the first repaint
+    }
     m_highlightedWindow = w;
-    if (m_highlightedWindow)
+    if (m_highlightedWindow) {
+        effects->setElevatedWindow(m_highlightedWindow, true);
         m_highlightedWindow->addRepaintFull(); // Trigger the first repaint
+    }
 
     if (m_tabBoxEnabled && m_highlightedWindow)
         effects->setTabBoxWindow(w);
     updateCloseWindow();
 }
 
+void PresentWindowsEffect::elevateCloseWindow()
+{
+    if (EffectWindow *cw = effects->findWindow(m_closeView->winId()))
+            effects->setElevatedWindow(cw, true);
+}
+
 void PresentWindowsEffect::updateCloseWindow()
 {
     if (m_doNotCloseWindows)
         return;
+    if (!m_highlightedWindow || m_highlightedWindow->isDesktop()) {
+        m_closeView->hide();
+        return;
+    }
     if (m_closeView->isVisible())
         return;
-    if (!m_highlightedWindow) {
+
+    const QRectF rect(m_motionManager.targetGeometry(m_highlightedWindow));
+    if (2*m_closeView->sceneRect().width() > rect.width() && \
2*m_closeView->sceneRect().height() > rect.height()) { +        // not for tiny \
windows (eg. with many windows) - they might become unselectable  \
m_closeView->hide();  return;
     }
-    const QRectF rect = m_motionManager.targetGeometry(m_highlightedWindow);
-    m_closeView->setGeometry(rect.x() + rect.width() - \
                m_closeView->sceneRect().width(), rect.y(),
-                             m_closeView->sceneRect().width(), \
                m_closeView->sceneRect().height());
-    if (rect.contains(effects->cursorPos()))
-        m_closeView->delayedShow();
+    QRect cvr(QPoint(0,0), m_closeView->sceneRect().size().toSize());
+    switch (m_closeButtonCorner)
+    {
+    case Qt::TopLeftCorner:
+    default:
+        cvr.moveTopLeft(rect.topLeft().toPoint()); break;
+    case Qt::TopRightCorner:
+        cvr.moveTopRight(rect.topRight().toPoint()); break;
+    case Qt::BottomLeftCorner:
+        cvr.moveBottomLeft(rect.bottomLeft().toPoint()); break;
+    case Qt::BottomRightCorner:
+        cvr.moveBottomRight(rect.bottomRight().toPoint()); break;
+    }
+    m_closeView->setGeometry(cvr);
+    if (rect.contains(effects->cursorPos())) {
+        m_closeView->show();
+        m_closeView->disarm();
+        // to wait for the next event cycle (or more if the show takes more time)
+        // TODO: make the closeWindow a graphicsviewitem? why should there be an \
extra scene to be used in an exiting scene?? +        QTimer::singleShot(50, this, \
SLOT(elevateCloseWindow())); +    }
     else
         m_closeView->hide();
 }
@@ -1972,7 +2046,7 @@ void PresentWindowsEffect::globalShortcutChangedClass(const \
                QKeySequence& seq)
 ************************************************/
 CloseWindowView::CloseWindowView(QWidget* parent)
     : QGraphicsView(parent)
-    , m_delayedShowTimer(new QTimer(this))
+    , m_armTimer(new QTimer(this))
 {
     setWindowFlags(Qt::X11BypassWindowManagerHint);
     setAttribute(Qt::WA_TranslucentBackground);
@@ -2013,15 +2087,15 @@ CloseWindowView::CloseWindowView(QWidget* parent)
     scene->setSceneRect(QRectF(QPointF(0, 0), QSizeF(width, height)));
     setScene(scene);
 
-    // setup the timer
-    m_delayedShowTimer->setSingleShot(true);
-    m_delayedShowTimer->setInterval(500);
-    connect(m_delayedShowTimer, SIGNAL(timeout()), SLOT(show()));
+    // setup the timer - attempt to prevent accidental clicks
+    m_armTimer->setSingleShot(true);
+    m_armTimer->setInterval(350); // 50ms until the window is elevated (seen!) and \
300ms more to be "realized" by the user. +    connect(m_armTimer, SIGNAL(timeout()), \
SLOT(arm()));  }
 
 void CloseWindowView::windowInputMouseEvent(QMouseEvent* e)
 {
-    if (m_delayedShowTimer->isActive())
+    if (!isEnabled())
         return;
     if (e->type() == QEvent::MouseMove) {
         mouseMoveEvent(e);
@@ -2041,17 +2115,15 @@ void CloseWindowView::drawBackground(QPainter* painter, const \
QRectF& rect)  m_frame->paintFrame(painter);
 }
 
-void CloseWindowView::hide()
+void CloseWindowView::arm()
 {
-    m_delayedShowTimer->stop();
-    QWidget::hide();
+    setEnabled(true);
 }
 
-void CloseWindowView::delayedShow()
+void CloseWindowView::disarm()
 {
-    if (isVisible() || m_delayedShowTimer->isActive())
-        return;
-    m_delayedShowTimer->start();
+    setEnabled(false);
+    m_armTimer->start();
 }
 
 
diff --git a/kwin/effects/presentwindows/presentwindows.h \
b/kwin/effects/presentwindows/presentwindows.h index 58c5266..e0c982e 100644
--- a/kwin/effects/presentwindows/presentwindows.h
+++ b/kwin/effects/presentwindows/presentwindows.h
@@ -46,8 +46,9 @@ public:
     void windowInputMouseEvent(QMouseEvent* e);
     virtual void drawBackground(QPainter* painter, const QRectF& rect);
 
-    void delayedShow();
-    void hide();
+    void disarm();
+public slots:
+    void arm();
 
 Q_SIGNALS:
     void close();
@@ -55,7 +56,7 @@ Q_SIGNALS:
 private:
     Plasma::PushButton* m_closeButton;
     Plasma::FrameSvg* m_frame;
-    QTimer* m_delayedShowTimer;
+    QTimer* m_armTimer;
 };
 
 /**
@@ -160,6 +161,7 @@ public slots:
 
 private slots:
     void closeWindow();
+    void elevateCloseWindow();
 
 protected:
     // Window rearranging
@@ -265,6 +267,7 @@ private:
 
     CloseWindowView* m_closeView;
     EffectWindow* m_closeWindow;
+    Qt::Corner m_closeButtonCorner;
 
     // drag to close
     QPoint m_dragStart;
diff --git a/kwin/effects/screenlocker/CMakeLists.txt \
b/kwin/effects/screenlocker/CMakeLists.txt new file mode 100644
index 0000000..21d9284
--- /dev/null
+++ b/kwin/effects/screenlocker/CMakeLists.txt
@@ -0,0 +1,13 @@
+#######################################
+# Effect
+
+# Source files
+set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources}
+    screenlocker/screenlocker.cpp
+    )
+
+# .desktop files
+install( FILES
+    screenlocker/screenlocker.desktop
+    DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
+
diff --git a/kwin/effects/screenlocker/qml/main.qml \
b/kwin/effects/screenlocker/qml/main.qml new file mode 100644
index 0000000..36be712
--- /dev/null
+++ b/kwin/effects/screenlocker/qml/main.qml
@@ -0,0 +1,151 @@
+/***************************************************************************
+ *   Copyright 2011 Artur Duque de Souza <asouza@kde.org>                  *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
+ ***************************************************************************/
+
+import QtQuick 1.0
+import org.kde.plasma.core 0.1 as PlasmaCore
+import org.kde.qtextracomponents 0.1
+
+
+Rectangle {
+    id: lockScreen
+    width: 800
+    height: 600
+    color: Qt.rgba(0, 0, 0, 0.8)
+
+    signal unlockRequested()
+
+    MouseArea {
+        anchors.fill: parent
+        onPressed: mouse.accepted = true
+    }
+
+    PlasmaCore.Theme {
+        id: theme
+    }
+
+    Behavior on opacity {
+        NumberAnimation {duration: 250}
+    }
+
+    Item {
+        id: lockArea
+        anchors {
+            bottom: parent.bottom
+            left: parent.left
+            right: parent.right
+        }
+        height: 120
+    }
+
+    Item {
+        id: unlockArea
+        anchors {
+            top: parent.top
+            bottom: lockArea.top
+            left: parent.left
+            right: parent.right
+        }
+
+
+        Text {
+            id: unlockText
+            text: i18n("Drag here to unlock")
+            color: "white"
+            anchors.centerIn: parent
+            font.pixelSize: 36
+            font.family: theme.font.family
+            font.bold: theme.font.bold
+            font.capitalization: theme.font.capitalization
+            font.italic: theme.font.italic
+            font.weight: theme.font.weight
+            font.underline: theme.font.underline
+            font.wordSpacing: theme.font.wordSpacing
+            opacity: 0
+
+            Behavior on opacity {
+                NumberAnimation { duration: 200 }
+            }
+        }
+
+    }
+
+
+    Image {
+        id: lockerImage
+        width: 64
+        height: 64
+        source: "unlock-normal.png"
+        state: "default"
+
+        anchors {
+            bottom: lockScreen.bottom
+            topMargin: 10
+            horizontalCenter: lockScreen.horizontalCenter
+        }
+
+        MouseArea {
+            anchors.fill: parent
+            drag.target: parent
+            onPressed: {
+                lockerImage.state = "drag"
+            }
+
+            onReleased: {
+                var pos = (lockerImage.x > unlockArea.x && lockerImage.y > \
unlockArea.y); +                var size = (lockerImage.x < unlockArea.width && \
lockerImage.y < unlockArea.height); +
+                if (pos && size) {
+                    lockScreen.unlockRequested()
+                }
+
+                lockerImage.state = "default"
+            }
+        }
+
+        states: [
+            State {
+                name: "drag"
+                PropertyChanges {
+                    target: lockerImage
+                    anchors.bottom: undefined
+                    anchors.horizontalCenter: undefined
+                    source: "unlock-pressed.png"
+                }
+                PropertyChanges {
+                    target: unlockText
+                    opacity: 0.6
+                }
+            },
+            State {
+                name: "default"
+                PropertyChanges {
+                    target: lockerImage
+                    anchors.bottom: lockScreen.bottom
+                    anchors.horizontalCenter: lockScreen.horizontalCenter
+                    source: "unlock-normal.png"
+                }
+                PropertyChanges {
+                    target: unlockText
+                    opacity: 0
+                }
+            }
+        ]
+    }
+}
+
diff --git a/kwin/effects/screenlocker/qml/unlock-normal.png \
b/kwin/effects/screenlocker/qml/unlock-normal.png new file mode 100644
index 0000000..e67472e
Binary files /dev/null and b/kwin/effects/screenlocker/qml/unlock-normal.png differ
diff --git a/kwin/effects/screenlocker/qml/unlock-pressed.png \
b/kwin/effects/screenlocker/qml/unlock-pressed.png new file mode 100644
index 0000000..cd8e0cf
Binary files /dev/null and b/kwin/effects/screenlocker/qml/unlock-pressed.png differ
diff --git a/kwin/effects/screenlocker/screenlocker.cpp \
b/kwin/effects/screenlocker/screenlocker.cpp new file mode 100644
index 0000000..df20014
--- /dev/null
+++ b/kwin/effects/screenlocker/screenlocker.cpp
@@ -0,0 +1,234 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#include "screenlocker.h"
+#include <QKeyEvent>
+#include <QMouseEvent>
+#include <QDeclarativeView>
+#include <QDeclarativeEngine>
+#include <QGraphicsObject>
+#include <KStandardDirs>
+#ifdef KWIN_HAVE_OPENGL
+#include <kwinglutils.h>
+#endif
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+#include <kwinxrenderutils.h>
+#endif
+#include <kdeclarative.h>
+
+namespace KWin
+{
+
+KWIN_EFFECT(screenlocker, ScreenLockerEffect)
+
+class EffectDeclarativeView : public QDeclarativeView
+{
+public:
+    void windowInputMouseEvent(QEvent *e)
+    {
+        QMouseEvent *ev = static_cast<QMouseEvent *>(e);
+
+        if (e->type() == QEvent::MouseMove) {
+            mouseMoveEvent(ev);
+        } else if (e->type() == QEvent::MouseButtonPress) {
+            mousePressEvent(ev);
+        } else if (e->type() == QEvent::MouseButtonDblClick) {
+            mouseDoubleClickEvent(ev);
+        } else if (e->type() == QEvent::MouseButtonRelease) {
+            mouseReleaseEvent(ev);
+        }
+    }
+};
+
+ScreenLockerEffect::ScreenLockerEffect()
+    : Effect()
+    , m_locked(false)
+    , m_inputWindow(0)
+{
+    connect(effects, SIGNAL(requestScreenLock()), SLOT(slotRequestLock()));
+    m_declarativeView = new EffectDeclarativeView;
+    foreach(const QString &importPath, KGlobal::dirs()->findDirs("module", \
"imports")) { +        m_declarativeView->engine()->addImportPath(importPath);
+    }
+    KDeclarative kdeclarative;
+    kdeclarative.setDeclarativeEngine(m_declarativeView->engine());
+    kdeclarative.initialize();
+    //binds things like kconfig and icons
+    kdeclarative.setupBindings();
+    m_declarativeView->setSource(QUrl(KStandardDirs::locate("data", \
"kwin/lockscreen/main.qml"))); +    \
m_declarativeView->setResizeMode(QDeclarativeView::SizeRootObjectToView); +    \
m_declarativeView->setWindowFlags(Qt::X11BypassWindowManagerHint); +    \
m_declarativeView->setAttribute(Qt::WA_TranslucentBackground); +    \
m_declarativeView->setFrameShape(QFrame::NoFrame); +
+    connect(m_declarativeView->rootObject(), SIGNAL(unlockRequested()), this, \
SLOT(slotRequestUnlock())); +    //m_declarativeView->hide();
+}
+
+ScreenLockerEffect::~ScreenLockerEffect()
+{
+    delete m_declarativeView;
+}
+
+void ScreenLockerEffect::paintScreen(int mask, QRegion region, ScreenPaintData \
&data) +{
+    effects->paintScreen(mask, region, data);
+    if (m_locked) {
+        // TODO: do our screen locking
+    }
+}
+
+void ScreenLockerEffect::postPaintScreen()
+{
+    if (m_locked) {
+        // paint screen black
+        // TODO: add cross fading
+        if (effects->compositingType() == OpenGLCompositing) {
+            paintGL();
+        } else if (effects->compositingType() == XRenderCompositing) {
+            paintXrender();
+        }
+        EffectWindow *w = effects->findWindow(m_declarativeView->winId());
+        if (w) {
+            WindowPaintData d(w);
+            effects->drawWindow(w, PAINT_WINDOW_OPAQUE, infiniteRegion(), d);
+        }
+    }
+}
+
+void ScreenLockerEffect::paintGL()
+{
+#ifdef KWIN_HAVE_OPENGL
+    GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
+    vbo->reset();
+    vbo->setUseColor(true);
+    if (ShaderManager::instance()->isValid()) {
+        ShaderManager::instance()->pushShader(ShaderManager::ColorShader);
+    }
+    vbo->setColor(Qt::black);
+    QVector<float> verts;
+    const QRect r(0, 0, displayWidth(), displayHeight());
+    verts.reserve(12);
+    verts << r.x() + r.width() << r.y();
+    verts << r.x() << r.y();
+    verts << r.x() << r.y() + r.height();
+    verts << r.x() << r.y() + r.height();
+    verts << r.x() + r.width() << r.y() + r.height();
+    verts << r.x() + r.width() << r.y();
+    vbo->setData(6, 2, verts.data(), NULL);
+    vbo->render(GL_TRIANGLES);
+    if (ShaderManager::instance()->isValid()) {
+        ShaderManager::instance()->popShader();
+    }
+#endif
+}
+
+void ScreenLockerEffect::paintXrender()
+{
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+    XRenderColor col;
+    col.alpha = 1;
+    col.red = 0;
+    col.green = 0;
+    col.blue = 0;
+    XRenderFillRectangle(display(), PictOpOver, effects->xrenderBufferPicture(),
+                         &col, 0, 0, displayWidth(), displayHeight());
+#endif
+}
+
+void ScreenLockerEffect::slotRequestLock()
+{
+    if (!effects->isScreenLockerReferenced()) {
+        m_declarativeView->setGeometry(effects->clientArea(FullScreenArea, \
effects->activeScreen(), effects->currentDesktop())); +        \
m_declarativeView->show();  +        // create input window and grab mouse
+        Window w = effects->createFullScreenInputWindow(this, \
Qt::PointingHandCursor); +        if (!w) {
+            return;
+        }
+        if (!effects->grabKeyboard(this)) {
+            effects->destroyInputWindow(w);
+            return;
+        }
+        effects->refScreenLocker(this);
+        effects->setActiveFullScreenEffect(this);
+        m_locked = true;
+        m_inputWindow = w;
+        
+        effects->addRepaintFull();
+    }
+}
+
+void ScreenLockerEffect::grabbedKeyboardEvent(QKeyEvent *e)
+{
+    if (!m_locked) {
+        return;
+    }
+    // TODO: implement a proper unlock behavior
+    if (e->key() == Qt::Key_Space) {
+        // magic key for testing
+        doUnlock();
+    }
+}
+
+void ScreenLockerEffect::slotRequestUnlock()
+{
+    doUnlock();
+}
+
+void ScreenLockerEffect::windowInputMouseEvent(Window w, QEvent *e)
+{
+    Q_UNUSED(w)
+    Q_UNUSED(e)
+    if (!m_locked) {
+        return;
+    }
+
+    QMouseEvent* me = static_cast< QMouseEvent* >(e);
+    QMouseEvent event(me->type(), me->pos(), me->pos(), me->button(), me->buttons(), \
me->modifiers()); +    m_declarativeView->windowInputMouseEvent(&event);
+    // TODO: implement proper behavior by triggering the unlock screen
+}
+
+void ScreenLockerEffect::doUnlock()
+{
+    m_locked = false;
+    effects->destroyInputWindow(m_inputWindow);
+    m_inputWindow = 0;
+    effects->setActiveFullScreenEffect(NULL);
+    effects->ungrabKeyboard();
+    effects->unrefScreenLocker(this);
+    m_declarativeView->hide();
+    effects->addRepaintFull();
+}
+
+bool ScreenLockerEffect::isActive() const
+{
+    return m_locked;
+}
+
+bool ScreenLockerEffect::provides(Effect::Feature feature)
+{
+    if (feature == ScreenLocking) {
+        return true;
+    }
+    return false;
+}
+
+} //namespace
diff --git a/kwin/effects/screenlocker/screenlocker.desktop \
b/kwin/effects/screenlocker/screenlocker.desktop new file mode 100644
index 0000000..3631f35
--- /dev/null
+++ b/kwin/effects/screenlocker/screenlocker.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Name=Screen Locker
+Icon=preferences-system-windows-effect-screenlocker
+Comment=Internal Helper Effect to perform screen locking
+
+Type=Service
+X-KDE-ServiceTypes=KWin/Effect
+X-KDE-PluginInfo-Author=Martin Gräßlin
+X-KDE-PluginInfo-Email=mgraesslin@kde.org
+X-KDE-PluginInfo-Name=kwin4_effect_screenlocker
+X-KDE-PluginInfo-Version=0.1.0
+X-KDE-PluginInfo-Category=Window Management
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=true
+X-KDE-Library=kwin4_effect_builtins
+X-KDE-Ordering=99
\ No newline at end of file
diff --git a/kwin/effects/screenlocker/screenlocker.h \
b/kwin/effects/screenlocker/screenlocker.h new file mode 100644
index 0000000..7a21a80
--- /dev/null
+++ b/kwin/effects/screenlocker/screenlocker.h
@@ -0,0 +1,57 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#ifndef KWIN_SCREENLOCKER_EFFECT_H
+#define KWIN_SCREENLOCKER_EFFECT_H
+#include <kwineffects.h>
+
+
+namespace KWin
+{
+
+class EffectDeclarativeView;
+
+class ScreenLockerEffect : public Effect
+{
+    Q_OBJECT
+public:
+    ScreenLockerEffect();
+    virtual ~ScreenLockerEffect();
+    virtual void paintScreen(int mask, QRegion region, ScreenPaintData &data);
+    virtual void postPaintScreen();
+    virtual bool provides(Feature feature);
+    virtual bool isActive() const;
+
+    virtual void windowInputMouseEvent(Window w, QEvent *e);
+    virtual void grabbedKeyboardEvent(QKeyEvent *e);
+
+public Q_SLOTS:
+    void slotRequestLock();
+    void slotRequestUnlock();
+
+private:
+    void doUnlock();
+    void paintGL();
+    void paintXrender();
+    bool m_locked;
+    Window m_inputWindow;
+    EffectDeclarativeView *m_declarativeView;
+};
+} // namespace
+#endif
diff --git a/kwin/libkdecorations/kdecorationfactory.cpp \
b/kwin/libkdecorations/kdecorationfactory.cpp index 05b33cf..142add7 100644
--- a/kwin/libkdecorations/kdecorationfactory.cpp
+++ b/kwin/libkdecorations/kdecorationfactory.cpp
@@ -28,12 +28,21 @@ DEALINGS IN THE SOFTWARE.
 
 #include "kdecorationbridge.h"
 
-KDecorationFactory::KDecorationFactory()
+class KDecorationFactoryPrivate {
+public:
+    KDecorationFactoryPrivate() {
+        closeButtonCorner = (Qt::Corner)0;
+    }
+    Qt::Corner closeButtonCorner;
+};
+
+KDecorationFactory::KDecorationFactory() : d(new KDecorationFactoryPrivate)
 {
 }
 
 KDecorationFactory::~KDecorationFactory()
 {
+    delete d;
     assert(_decorations.count() == 0);
 }
 
@@ -56,6 +65,18 @@ bool KDecorationFactory::exists(const KDecoration* deco) const
     return _decorations.contains(const_cast< KDecoration* >(deco));
 }
 
+Qt::Corner KDecorationFactory::closeButtonCorner()
+{
+    if (d->closeButtonCorner)
+        return d->closeButtonCorner;
+    return options()->titleButtonsLeft().contains('X') ? Qt::TopLeftCorner : \
Qt::TopRightCorner; +}
+
+void KDecorationFactory::setCloseButtonCorner(Qt::Corner cnr)
+{
+    d->closeButtonCorner = cnr;
+}
+
 void KDecorationFactory::addDecoration(KDecoration* deco)
 {
     _decorations.append(deco);
diff --git a/kwin/libkdecorations/kdecorationfactory.h \
b/kwin/libkdecorations/kdecorationfactory.h index 978d4b2..44a5b7d 100644
--- a/kwin/libkdecorations/kdecorationfactory.h
+++ b/kwin/libkdecorations/kdecorationfactory.h
@@ -88,6 +88,21 @@ public:
      * after such actions.
      */
     bool exists(const KDecoration* deco) const;
+
+    /**
+     * Set & get the position of the close button - most decorations don't have to \
call this ever. +     *
+     * By default, the legacy position indicated by the options (top left or top \
right) will be +     * returned.
+     * Only if you need to provide a bottom corner or your decoration does not \
respect those +     * settings you will have to specify the exact corner (eg. used by \
the "present windows" +     * closer)
+     *
+     * @since 4.8
+     */
+    Qt::Corner closeButtonCorner();
+    void setCloseButtonCorner(Qt::Corner cnr);
+
     /**
      * @internal
      */
diff --git a/kwin/libkwineffects/kwineffects.h b/kwin/libkwineffects/kwineffects.h
index 87a676d..6f32068 100644
--- a/kwin/libkwineffects/kwineffects.h
+++ b/kwin/libkwineffects/kwineffects.h
@@ -166,7 +166,7 @@ X-KDE-Library=kwin4_effect_cooleffect
 
 #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
 #define KWIN_EFFECT_API_VERSION_MAJOR 0
-#define KWIN_EFFECT_API_VERSION_MINOR 180
+#define KWIN_EFFECT_API_VERSION_MINOR 181
 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
         KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
 
@@ -331,7 +331,8 @@ public:
 
     enum Feature {
         Nothing = 0, Resize, GeometryTip,
-        Outline
+        Outline,
+        ScreenLocking
     };
 
     /**
@@ -580,6 +581,7 @@ public:
     virtual void paintEffectFrame(EffectFrame* frame, QRegion region, double \
                opacity, double frameOpacity) = 0;
     virtual void drawWindow(EffectWindow* w, int mask, QRegion region, \
                WindowPaintData& data) = 0;
     virtual void buildQuads(EffectWindow* w, WindowQuadList& quadList) = 0;
+    virtual QVariant kwinOption(KWinOption kwopt) = 0;
     // Functions for handling input - e.g. when an Expose-like effect is shown, an \
                input window
     // covering the whole screen is created and all mouse events will be intercepted \
                by it.
     // The effect's windowInputMouseEvent() will get called with such events.
@@ -780,6 +782,42 @@ public:
     virtual EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize = true,
                                      const QPoint& position = QPoint(-1, -1), \
Qt::Alignment alignment = Qt::AlignCenter) const = 0;  
+
+    /**
+     * Allows effects to indicate that they are responsible for handling screen \
locking. +     * Only one effect at a time should reference the Screen Locker. It is \
assumed that +     * all effects want to collaborate and will check @link \
isScreenLockerReferenced before +     * trying to reference the screen locker.
+     * When the effect gets into a state that it wants to indicate that the screen \
got unlocked +     * it should use @link unrefScreenLocker to remove the reference on \
the screen locker and +     * to indicate that the screen got unlocked.
+     *
+     * An Effect may only call this method in a slot connected on the @link \
requestScreenLock signal. +     * Calling this method outside the handling of that \
signal will not do anything. +     *
+     * @param lockEffect The Effect which implements the lock.
+     * @since 4.8
+     * @see unrefScreenLocker
+     * @see isScreenLockerReferenced
+     **/
+    virtual void refScreenLocker(Effect *lockEffect) = 0;
+    /**
+     * Method to unlock the screen for an Effect which handles Screen Locking \
through +     * @link refScreenLocker.
+     * If the Effect had not referenced the Screen Locker this method will not \
unlock the screen. +     * @param lockEffect The Effect which implements the lock.
+     * @since 4.8
+     * @see refScreenLocker
+     **/
+    virtual void unrefScreenLocker(Effect *lockEffect) = 0;
+    /**
+     * @returns Whether an Effect referenced the Screen Lock.
+     * @since 4.8
+     * @see refScreenLocker
+     * @see unrefScreenLocker
+     **/
+    virtual bool isScreenLockerReferenced() const = 0;
+
     /**
      * Sends message over DCOP to reload given effect.
      * @param effectname effect's name without "kwin4_effect_" prefix.
@@ -1017,6 +1055,14 @@ Q_SIGNALS:
      * @since 4.7
      **/
     void hideOutline();
+    /**
+     * Signal emitted when the screen is about to be locked. An effect implementing \
a screen lock +     * may connect to this signal and call @link refScreenLocker in \
the slot handling the signal. +     * @since 4.8
+     * @see refScreenLocker
+     * @see isScreenLockerReferenced
+     **/
+    void requestScreenLock();
 
 protected:
     QVector< EffectPair > loaded_effects;
diff --git a/kwin/libkwineffects/kwinglobals.h b/kwin/libkwineffects/kwinglobals.h
index 2a4ea71..b33d3df 100644
--- a/kwin/libkwineffects/kwinglobals.h
+++ b/kwin/libkwineffects/kwinglobals.h
@@ -105,6 +105,10 @@ enum TabBoxMode {
     TabBoxWindowsAlternativeMode // Secondary window switching mode
 };
 
+enum KWinOption {
+    CloseButtonCorner
+};
+
 inline
 KWIN_EXPORT Display* display()
 {
diff --git a/kwin/screenlocker/config-xautolock.h.cmake \
b/kwin/screenlocker/config-xautolock.h.cmake new file mode 100644
index 0000000..eadb0a6
--- /dev/null
+++ b/kwin/screenlocker/config-xautolock.h.cmake
@@ -0,0 +1,2 @@
+/* Define if you have the XScreenSaver extension */
+#cmakedefine HAVE_XSCREENSAVER 1
diff --git a/kwin/screenlocker/dbus/org.freedesktop.ScreenSaver.xml \
b/kwin/screenlocker/dbus/org.freedesktop.ScreenSaver.xml new file mode 100644
index 0000000..5efd943
--- /dev/null
+++ b/kwin/screenlocker/dbus/org.freedesktop.ScreenSaver.xml
@@ -0,0 +1,41 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" \
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node>
+  <interface name="org.freedesktop.ScreenSaver">
+    <signal name="ActiveChanged">
+      <arg type="b"/>
+    </signal>
+    <method name="Lock">
+    </method>
+    <method name="SimulateUserActivity">
+    </method>
+    <method name="GetActive">
+      <arg type="b" direction="out"/>
+    </method>
+    <method name="GetActiveTime">
+      <arg name="seconds" type="u" direction="out"/>
+    </method>
+    <method name="GetSessionIdleTime">
+      <arg name="seconds" type="u" direction="out"/>
+    </method>
+    <method name="SetActive">
+      <arg type="b" direction="out"/>
+      <arg name="e" type="b" direction="in"/>
+    </method>
+    <method name="Inhibit">
+      <arg name="application_name" type="s" direction="in"/>
+      <arg name="reason_for_inhibit" type="s" direction="in"/>
+      <arg name="cookie" type="u" direction="out"/>
+    </method>
+    <method name="UnInhibit">
+      <arg name="cookie" type="u" direction="in"/>
+    </method>
+    <method name="Throttle">
+      <arg name="application_name" type="s" direction="in"/>
+      <arg name="reason_for_inhibit" type="s" direction="in"/>
+      <arg name="cookie" type="u" direction="out"/>
+    </method>
+    <method name="UnThrottle">
+      <arg name="cookie" type="u" direction="in"/>
+    </method>
+  </interface>
+</node>
diff --git a/kwin/screenlocker/dbus/org.kde.screensaver.xml \
b/kwin/screenlocker/dbus/org.kde.screensaver.xml new file mode 100644
index 0000000..e700b88
--- /dev/null
+++ b/kwin/screenlocker/dbus/org.kde.screensaver.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" \
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node>
+  <interface name="org.kde.screensaver">
+    <!-- start in plasma setup mode -->
+    <method name="setupPlasma" />
+    <!-- Re-read configuration -->
+    <method name="configure" />
+    <!-- Private API. Don't use. -->
+    <method name="saverLockReady" />
+  </interface>
+</node>
diff --git a/kwin/screenlocker/kcfg/kscreensaversettings.kcfg \
b/kwin/screenlocker/kcfg/kscreensaversettings.kcfg new file mode 100644
index 0000000..c8f76f3
--- /dev/null
+++ b/kwin/screenlocker/kcfg/kscreensaversettings.kcfg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+                           http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+  <include>kglobalsettings.h</include>
+  <kcfgfile name="kscreensaverrc" />
+  <group name="ScreenSaver">
+    <entry name="ScreenSaverEnabled" key="Enabled" type="Bool">
+      <default>false</default>
+      <label>Enable screen saver</label>
+      <whatsthis>Enables the screen saver.</whatsthis>
+    </entry>
+    <entry key="Timeout" type="Int">
+      <default>300</default>
+      <label>Screen saver timeout</label>
+      <whatsthis>Sets the seconds after which the screen saver is \
started.</whatsthis> +    </entry>
+    <entry name="SuspendWhenInvisible" key="SuspendWhenInvisible" type="Bool">
+      <default>true</default>
+      <label>Suspend screen saver when DPMS kicks in</label>
+      <whatsthis>Usually the screen saver is suspended when display power saving \
kicks in, +       as nothing can be seen on the screen anyway, obviously. However, \
some screen savers +       actually perform useful computations, so it is not \
desirable to suspend them.</whatsthis> +    </entry>
+    <entry key="ActionTopLeft" type="Int">
+      <default>0</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="ActionTopRight" type="Int">
+      <default>0</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="ActionBottomLeft" type="Int">
+      <default>0</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="ActionBottomRight" type="Int">
+      <default>0</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="Lock" type="Bool">
+      <default>false</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="LockGrace" type="Int">
+      <default>5000</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="AutoLogout" type="Bool">
+      <default>false</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="AutoLogoutTimeout" type="Int">
+      <default>600</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="Priority" type="Int">
+      <default>19</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="Saver" type="String">
+      <default></default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="PluginsUnlock" type="StringList">
+      <default></default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="PluginOptions" type="StringList">
+      <default></default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+    <entry key="PlasmaEnabled" type="Bool">
+      <default>false</default>
+      <label></label>
+      <whatsthis></whatsthis>
+    </entry>
+  </group>
+</kcfg>
diff --git a/kwin/screenlocker/kcfg/kscreensaversettings.kcfgc \
b/kwin/screenlocker/kcfg/kscreensaversettings.kcfgc new file mode 100644
index 0000000..af9133d
--- /dev/null
+++ b/kwin/screenlocker/kcfg/kscreensaversettings.kcfgc
@@ -0,0 +1,4 @@
+File=kscreensaversettings.kcfg
+ClassName=KScreenSaverSettings
+Singleton=true
+Mutators=true
diff --git a/kwin/screenlocker/lock/CMakeLists.txt \
b/kwin/screenlocker/lock/CMakeLists.txt new file mode 100644
index 0000000..76319be
--- /dev/null
+++ b/kwin/screenlocker/lock/CMakeLists.txt
@@ -0,0 +1,62 @@
+include_directories( ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/screenlocker \
${KDEBASE_WORKSPACE_SOURCE_DIR}/kcheckpass ${KDEBASE_WORKSPACE_SOURCE_DIR}/libs/kdm ) \
+ +########### next target ###############
+
+check_library_exists(Xxf86misc XF86MiscSetGrabKeysState "" \
HAVE_XF86MISCSETGRABKEYSSTATE) +if(WITH_OpenGL)
+check_library_exists(GL glXChooseVisual "" HAVE_GLXCHOOSEVISUAL)
+endif(WITH_OpenGL)
+
+configure_file(config-krunner-lock.h.cmake \
${CMAKE_CURRENT_BINARY_DIR}/config-krunner-lock.h) +
+set(kscreenlocker_SRCS
+   lockprocess.cc
+   lockdlg.cc
+   autologout.cc
+   main.cc )
+
+set(plasmaapp_dbusXML \
../../../plasma/screensaver/shell/org.kde.plasma-overlay.App.xml) \
+qt4_add_dbus_interface(kscreenlocker_SRCS ${plasmaapp_dbusXML} plasmaapp_interface) \
+ +set(lockprocess_dbusXML org.kde.screenlocker.LockProcess.xml)
+qt4_generate_dbus_interface(lockprocess.h ${lockprocess_dbusXML} OPTIONS -m)
+qt4_add_dbus_adaptor(kscreenlocker_SRCS \
${CMAKE_CURRENT_BINARY_DIR}/${lockprocess_dbusXML} lockprocess.h LockProcess) +
+set(ksmserver_xml  ${KDEBASE_WORKSPACE_SOURCE_DIR}/ksmserver/org.kde.KSMServerInterface.xml)
 +QT4_ADD_DBUS_INTERFACE(kscreenlocker_SRCS ${ksmserver_xml} ksmserver_interface)
+set(kscreensaver_xml  \
${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/screenlocker/dbus/org.kde.screensaver.xml) \
+QT4_ADD_DBUS_INTERFACE(kscreenlocker_SRCS ${kscreensaver_xml} \
kscreensaver_interface) +
+
+
+kde4_add_kcfg_files(kscreenlocker_SRCS \
${CMAKE_CURRENT_SOURCE_DIR}/../kcfg/kscreensaversettings.kcfgc) +
+
+
+kde4_add_executable(kscreenlocker ${kscreenlocker_SRCS})
+
+target_link_libraries(kscreenlocker kephal ${KDE4_KDEUI_LIBS} ${X11_LIBRARIES})
+
+find_library(DL_LIBRARY dl)
+if (DL_LIBRARY)
+  target_link_libraries(kscreenlocker ${DL_LIBRARY})
+endif(DL_LIBRARY)
+
+if (HAVE_XF86MISC)
+  target_link_libraries(kscreenlocker ${X11_Xxf86misc_LIB})
+endif (HAVE_XF86MISC)
+
+if(HAVE_GLXCHOOSEVISUAL)
+   target_link_libraries(kscreenlocker ${OPENGL_gl_LIBRARY})
+endif(HAVE_GLXCHOOSEVISUAL)
+
+install(TARGETS kscreenlocker DESTINATION ${LIBEXEC_INSTALL_DIR})
+
+install_pam_service(kscreensaver)
+
+
+########### install files ###############
+
+
+install( FILES kscreenlocker.notifyrc  DESTINATION  \
${DATA_INSTALL_DIR}/kscreenlocker ) +
diff --git a/kwin/screenlocker/lock/autologout.cc \
b/kwin/screenlocker/lock/autologout.cc new file mode 100644
index 0000000..c86e29a
--- /dev/null
+++ b/kwin/screenlocker/lock/autologout.cc
@@ -0,0 +1,118 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 2004 Chris Howells <howells@kde.org>
+
+#include "lockprocess.h"
+#include "autologout.h"
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <ksmserver_interface.h>
+
+#include <QLayout>
+#include <QMessageBox>
+#include <QLabel>
+#include <QStyle>
+#include <QApplication>
+#include <QDialog>
+#include <QAbstractEventDispatcher>
+#include <QtGui/QProgressBar>
+#include <QtDBus/QtDBus>
+
+#define COUNTDOWN 30
+
+AutoLogout::AutoLogout(LockProcess *parent) : QDialog(parent, \
Qt::X11BypassWindowManagerHint) +{
+    QLabel *pixLabel = new QLabel( this );
+    pixLabel->setObjectName( QLatin1String( "pixlabel" ) );
+    pixLabel->setPixmap(DesktopIcon(QLatin1String( "application-exit" )));
+
+    QLabel *greetLabel = new QLabel(i18n("<qt><nobr><b>Automatic Log \
Out</b></nobr></qt>"), this); +    QLabel *infoLabel = new QLabel(i18n("<qt>To \
prevent being logged out, resume using this session by moving the mouse or pressing a \
key.</qt>"), this); +
+    mStatusLabel = new QLabel(QLatin1String( "<b> </b>" ), this);
+    mStatusLabel->setAlignment(Qt::AlignCenter);
+
+    QLabel *mProgressLabel = new QLabel(i18n("Time Remaining:"), this);
+    mProgressRemaining = new QProgressBar(this);
+    mProgressRemaining->setTextVisible(false);
+
+    frameLayout = new QGridLayout(this);
+    frameLayout->setSpacing(KDialog::spacingHint());
+    frameLayout->setMargin(KDialog::marginHint() * 2);
+    frameLayout->addWidget(pixLabel, 0, 0, 3, 1, Qt::AlignCenter | Qt::AlignTop);
+    frameLayout->addWidget(greetLabel, 0, 1);
+    frameLayout->addWidget(mStatusLabel, 1, 1);
+    frameLayout->addWidget(infoLabel, 2, 1);
+    frameLayout->addWidget(mProgressLabel, 3, 1);
+    frameLayout->addWidget(mProgressRemaining, 4, 1);
+
+    // get the time remaining in seconds for the status label
+    mRemaining = COUNTDOWN * 25;
+
+    mProgressRemaining->setMaximum(COUNTDOWN * 25);
+
+    updateInfo(mRemaining);
+
+    mCountdownTimerId = startTimer(1000/25);
+
+    connect(qApp, SIGNAL(activity()), SLOT(slotActivity()));
+}
+
+AutoLogout::~AutoLogout()
+{
+    hide();
+}
+
+void AutoLogout::updateInfo(int timeout)
+{
+    mStatusLabel->setText(i18np("<qt><nobr>You will be automatically logged out in 1 \
second</nobr></qt>", +                               "<qt><nobr>You will be \
automatically logged out in %1 seconds</nobr></qt>", +                               \
timeout / 25) ); +    mProgressRemaining->setValue(timeout);
+}
+
+void AutoLogout::timerEvent(QTimerEvent *ev)
+{
+    if (ev->timerId() == mCountdownTimerId)
+    {
+        updateInfo(mRemaining);
+        --mRemaining;
+        if (mRemaining < 0)
+        {
+            killTimer(mCountdownTimerId);
+            logout();
+        }
+    }
+}
+
+void AutoLogout::slotActivity()
+{
+    if (mRemaining >= 0)
+        accept();
+}
+
+void AutoLogout::logout()
+{
+    QAbstractEventDispatcher::instance()->unregisterTimers(this);
+    org::kde::KSMServerInterface ksmserver(QLatin1String( "org.kde.ksmserver" ), \
QLatin1String( "/KSMServer" ), QDBusConnection::sessionBus()); +    ksmserver.logout( \
0, 0, 0 ); +}
+
+void AutoLogout::setVisible(bool visible)
+{
+    QDialog::setVisible(visible);
+
+    if (visible)
+        QApplication::flush();
+}
+
+#include "autologout.moc"
diff --git a/kwin/screenlocker/lock/autologout.h \
b/kwin/screenlocker/lock/autologout.h new file mode 100644
index 0000000..0c44405
--- /dev/null
+++ b/kwin/screenlocker/lock/autologout.h
@@ -0,0 +1,46 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+// Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
+// Copyright 2004 Chris Howells <howells@kde.org>
+
+#ifndef AUTOLOGOUT_H
+#define AUTOLOGOUT_H
+
+#include <QLayout>
+
+class LockProcess;
+class QGridLayout;
+class QLabel;
+class QDialog;
+class QProgressBar;
+
+class AutoLogout : public QDialog
+{
+    Q_OBJECT
+
+public:
+    AutoLogout(LockProcess *parent);
+    ~AutoLogout();
+    virtual void setVisible(bool visible);
+
+protected:
+    virtual void timerEvent(QTimerEvent *);
+
+private Q_SLOTS:
+    void slotActivity();
+
+private:
+    void        updateInfo(int);
+    QGridLayout *frameLayout;
+    QLabel      *mStatusLabel;
+    int         mCountdownTimerId;
+    int         mRemaining;
+    QTimer      countDownTimer;
+    QProgressBar *mProgressRemaining;
+    void logout();
+};
+
+#endif // AUTOLOGOUT_H
diff --git a/kwin/screenlocker/lock/config-krunner-lock.h.cmake \
b/kwin/screenlocker/lock/config-krunner-lock.h.cmake new file mode 100644
index 0000000..7bfdfd6
--- /dev/null
+++ b/kwin/screenlocker/lock/config-krunner-lock.h.cmake
@@ -0,0 +1,2 @@
+#cmakedefine HAVE_GLXCHOOSEVISUAL 1
+#cmakedefine HAVE_XF86MISCSETGRABKEYSSTATE 1
diff --git a/kwin/screenlocker/lock/kscreenlocker.notifyrc \
b/kwin/screenlocker/lock/kscreenlocker.notifyrc new file mode 100644
index 0000000..9a9bce8
--- /dev/null
+++ b/kwin/screenlocker/lock/kscreenlocker.notifyrc
@@ -0,0 +1,740 @@
+[Global]
+IconName=system-lock-screen
+Comment=Screen Saver
+Comment[ar]=حافظة الشاشة
+Comment[ast]=Curiapantalles
+Comment[bg]=Екранен предпазител
+Comment[bs]=Čuvar ekrana
+Comment[ca]=Estalvi de pantalla
+Comment[ca@valencia]=Estalvi de pantalla
+Comment[cs]= etřič obrazovky
+Comment[da]=Pauseskærm
+Comment[de]=Bildschirmschoner
+Comment[el]= ροφύλαξη οθόνης
+Comment[en_GB]=Screen Saver
+Comment[es]=Salvapantallas
+Comment[et]=Ekraanisäästja
+Comment[eu]=Pantaila babeslea
+Comment[fi]=Näytönsäästäjä
+Comment[fr]=Écran de veille
+Comment[ga]=Spárálaí Scáileáin
+Comment[gu]=સ્ક્રીનક્રિન સેવર
+Comment[he]=שומר מסך
+Comment[hi]=स्क्रीन सेवर
+Comment[hr]=Čuvar zaslona
+Comment[hu]=Képernyővédő
+Comment[ia]=Salvator de schermo
+Comment[id]=Penyimpan Layar
+Comment[is]=Skjáhvíla
+Comment[it]=Salvaschermo
+Comment[ja]=スクリーンセーバー
+Comment[kk]=Экран сақтағышы
+Comment[km]=ធាតុ​រក្សា​អេក្រង់​
+Comment[kn]=ತೆರೆ ರಕ್ಷಕ
+Comment[ko]=화면 보호기
+Comment[lt]=Ekrano užsklanda
+Comment[lv]=Ekrānsaudzētājs
+Comment[nb]=Pauseskjerm
+Comment[nds]=Pausschirm
+Comment[nl]=Schermbeveiliging
+Comment[nn]=Pause skjerm
+Comment[pa]=ਸਕਰੀਨ ਸੇਵਰ
+Comment[pl]=Wygaszacz ekranu
+Comment[pt]=Protector de Ecrã
+Comment[pt_BR]=Protetor de tela
+Comment[ro]=Protecție de ecran
+Comment[ru]=Хранитель экрана
+Comment[si]=තිර සුරැකුම
+Comment[sk]= etrič obrazovky
+Comment[sl]=Ohranjevalnik zaslona
+Comment[sr]=Чувар екрана
+Comment[sr@ijekavian]=Чувар екрана
+Comment[sr@ijekavianlatin]=Čuvar ekrana
+Comment[sr@latin]=Čuvar ekrana
+Comment[sv]=Skärmsläckare
+Comment[tg]=Пардаи экран
+Comment[th]=โปรแกรมรักษาจอ าพ
+Comment[tr]=Ekran Koruyucu
+Comment[ug]=ئېكران قوغدىغۇچ
+Comment[uk]=Зберігач екрана
+Comment[wa]=Sipårgneu di waitroûle
+Comment[x-test]=xxScreen Saverxx
+Comment[zh_CN]=屏幕保护程序
+Comment[zh_TW]=螢幕保護程式
+
+[Event/savingstarted]
+Name=Screen saver started
+Name[ar]=بدأت حافظة الشاشة
+Name[ast]=Curiapantalles aniciáu
+Name[bg]=Зареден е екранен предпазител
+Name[bs]=Čuvar ekrana pokrenut
+Name[ca]=S'ha iniciat l'estalvi de pantalla
+Name[ca@valencia]=S'ha iniciat l'estalvi de pantalla
+Name[cs]= etřič obrazovky spuštěn
+Name[csb]=Zrëszony wëgaszôcz ekranu
+Name[da]=Pauseskærm startet
+Name[de]=Der Bildschirmschoner wurde gestartet.
+Name[el]=Η προφύλαξη οθόνης ξεκίνησε
+Name[en_GB]=Screen saver started
+Name[eo]=Ekrankurtenon ŝaltis
+Name[es]=Salvapantallas iniciado
+Name[et]=Ekraanisäästja alustas tööd
+Name[eu]=Pantaila babeslea abiarazita
+Name[fi]=Näytönsäästäjä käynnistyi
+Name[fr]=Écran de veille démarré
+Name[fy]=Skermbefeiliging úteinsetten
+Name[ga]=Tosaíodh an spárálaí scáileáin
+Name[gl]=Iniciouse o protector de pantalla
+Name[gu]=સ્ક્રિન સેવર શરૂ થયું
+Name[he]=שומר המסך התחיל
+Name[hi]=स्क्रीन सेवर चालू
+Name[hr]=Zaštita zaslona pokrenuta
+Name[hu]=A képernyővédő elindult
+Name[ia]=Salvator de schermo startate
+Name[id]=Penyimpan layar dijalankan
+Name[is]=Skjásvæfa ræst
+Name[it]=Salvaschermo avviato
+Name[ja]=スクリーンセーバー開始
+Name[kk]=Экран сақтағышы ісін бастады
+Name[km]=បាន​ចាប់ផ្ដើម​ធាតុរក្សា​អេក្រង់
 +Name[kn]=ಸ್ಕ್ರೀನ್‌ ಸೇವರ್ \
ಪ್ರಾರಂಭಗೊಂಡಿದೆ +Name[ko]=화면 보호기 시작됨
+Name[lt]=Ekrano užsklanda paleista
+Name[lv]=Ekrāna saudzētājs palaists
+Name[mk]=Чуварот на екранот е стартуван
+Name[ml]=സ്ക്രീന്‍ സേവര്‍ തുടങ്ങി
+Name[nb]=Pauseskjerm startet
+Name[nds]=Pausschirm opropen
+Name[nl]=Schermbeveiliging gestart
+Name[nn]=Pauseskjermen er starta
+Name[pa]=ਸਕਰੀਨ-ਸੇਵਰ ਸ਼ੁਰੂ ਹੋਏ
+Name[pl]=Wygaszacz ekranu uruchomiony
+Name[pt]=O protector de ecrã foi iniciado
+Name[pt_BR]=O protetor de tela foi iniciado
+Name[ro]=Protecție de ecran pornită
+Name[ru]=Хранитель экрана запущен
+Name[si]=තිර සුරැකුම ආරම්ණ කරන ලදි
+Name[sk]= etrič obrazovky spustený
+Name[sl]=Zagon ohranjevalnika zaslona
+Name[sr]=Чувар екрана покренут
+Name[sr@ijekavian]=Чувар екрана покренут
+Name[sr@ijekavianlatin]=Čuvar ekrana pokrenut
+Name[sr@latin]=Čuvar ekrana pokrenut
+Name[sv]=Skärmsläckare startad
+Name[tg]=Пардаи экран сар шуд
+Name[th]=โปรแกรมรักษาจอ \
าพเริ่มทำงานแล้ว +Name[tr]=Ekran koruyucu \
başlatıldı +Name[ug]=ئېكران قوغدىغۇچ باشلاندى
+Name[uk]=Запущено зберігач екрана
+Name[wa]=Sipårgneu di waitroûle enondé
+Name[x-test]=xxScreen saver startedxx
+Name[zh_CN]=屏幕保护程序已启动
+Name[zh_TW]=螢幕保護程式已啟動
+Comment=The screen saver has been started
+Comment[ar]=بدأت حافظة الشاشة
+Comment[ast]=Entamóse'l curiapantalles
+Comment[bg]=Зареден е екранен предпазител
+Comment[bs]=Pokrenut je čuvar ekrana
+Comment[ca]=S'ha iniciat l'estalvi de pantalla
+Comment[ca@valencia]=S'ha iniciat l'estalvi de pantalla
+Comment[cs]= etřič obrazovky byl spuštěn
+Comment[csb]=Wëgaszôcz ekranu òstôł zrëszony
+Comment[da]=Pauseskærmen er blevet startet
+Comment[de]=Der Bildschirmschoner wurde gestartet.
+Comment[el]=Η προφύλαξη οθόνης έχει ξεκινήσει
+Comment[en_GB]=The screen saver has been started
+Comment[eo]=la Ekrankurteno lanĉiĝas
+Comment[es]=Se ha iniciado el salvapantallas
+Comment[et]=Ekraanisäästja alustas tööd
+Comment[eu]=Pantaila babeslea abiarazi da
+Comment[fi]=Näytönsäästäjä on käynnistynyt
+Comment[fr]=L'écran de veille a été démarré
+Comment[fy]=De skermbefeiliging is úteinsetten
+Comment[ga]=Tosaíodh an spárálaí scáileáin
+Comment[gl]=Iniciouse o protector de pantalla
+Comment[gu]=સ્ક્રિન સેવર શરૂ કરાયેલ છે
+Comment[he]=שומר מסך הופעל
+Comment[hr]=Zaštita zaslona je pokrenuta
+Comment[hu]=A képernyővédő elindult
+Comment[ia]=Le salvator de schermo ha essite startate
+Comment[id]=Penyimpan layar telah dijalankan
+Comment[is]=Skjáhvílan hefur verið ræst
+Comment[it]=Il salvaschermo è stato avviato
+Comment[ja]=スクリーンセーバーが開始されました
+Comment[kk]=Экран сақтағышы ісін бастады
+Comment[km]=ធាតុ​រក្សាអេក្រង់​ត្រូវ​បាន​ចាប់ផ្ដើម
 +Comment[kn]=ಸ್ಕ್ರೀನ್‌ ಸೇವರನ್ನು \
ಪ್ರಾರಂಭಿಸಲಾಗಿದೆ +Comment[ko]=화면 보호기 시작됨
+Comment[lt]=Ekrano užsklanda buvo paleista
+Comment[lv]=Ekrāna saudzētājs tika palaists
+Comment[mk]=Чуварот на екранот беше стартуван
+Comment[ml]=സ്ക്രീന്‍ സേവര്‍ \
തുടങ്ങിയിരിയ്ക്കുന്നു \
+Comment[nb]=Pauseskjermen er startet +Comment[nds]=De Pausschirm wöör opropen
+Comment[nl]=De schermbeveiliging is gestart
+Comment[nn]=Pauseskjermen er starta
+Comment[pa]=ਸਕਰੀਨਸੇਵਰ ਸ਼ੁਰੂ ਕੀਤਾ ਜਾ \
ਚੁੱਕਿਆ ਹੈ +Comment[pl]=Wygaszacz ekranu został uruchomiony
+Comment[pt]=O protector de ecrã foi iniciado
+Comment[pt_BR]=O protetor de tela foi iniciado
+Comment[ro]=Protecția de ecran a fost pornită
+Comment[ru]=Хранитель экрана запущен
+Comment[si]=තිර සුරැකුම ආරම්භ කර ඇත
+Comment[sk]= etrič obrazovky bol spustený
+Comment[sl]=Ohranjevalnik zaslona se je zagnal
+Comment[sr]=Покренут је чувар екрана
+Comment[sr@ijekavian]=Покренут је чувар екрана
+Comment[sr@ijekavianlatin]=Pokrenut je čuvar ekrana
+Comment[sr@latin]=Pokrenut je čuvar ekrana
+Comment[sv]=Skärmsläckaren har startats
+Comment[tg]=Ахлотдон холӣ карда шуд
+Comment[th]=โปรแกรมรักษาจอ \
าพเริ่มการทำงานแล้ว +Comment[tr]=Ekran koruyucu \
başlatıldı +Comment[ug]=ئېكران قوغدىغۇچ باشلاندى
+Comment[uk]=Запущено зберігач екрана
+Comment[wa]=Li spårgneu di waitroûle a stî enondé
+Comment[x-test]=xxThe screen saver has been startedxx
+Comment[zh_CN]=屏幕保护程序已经启动
+Comment[zh_TW]=螢幕保護程式已被啟動
+Action=None
+
+[Event/locked]
+Name=Screen locked
+Name[ar]=قُقلت الشاشة
+Name[ast]=Pantalla bloquiada
+Name[bg]=Екранът е заключен
+Name[bs]=Ekran zaključan
+Name[ca]=S'ha bloquejat la pantalla
+Name[ca@valencia]=S'ha bloquejat la pantalla
+Name[cs]=Obrazovka uzamčena
+Name[csb]=Zablokòwóny ekranu
+Name[da]=Skærmen er låst
+Name[de]=Bildschirm gesperrt
+Name[el]=Οθόνη κλειδώθηκε
+Name[en_GB]=Screen locked
+Name[eo]=Ekranŝloso
+Name[es]=Pantalla bloqueada
+Name[et]=Ekraan on lukustatud
+Name[eu]=Pantaila giltzatuta
+Name[fi]=Näyttö lukittu
+Name[fr]=Écran verrouillé
+Name[fy]=Skerm beskoattele
+Name[ga]=Tá an scáileán faoi ghlas
+Name[gl]=A pantalla está trancada
+Name[gu]=સ્ક્રિન તાળું મારેલ છે
+Name[he]=מסך  עול
+Name[hi]=स्क्रीन तालाबंद
+Name[hr]=Zaslon zaključan
+Name[hu]=A képernyő zárolt
+Name[ia]=Schermo blocate
+Name[id]=Layar dikunci
+Name[is]=Skjár læstur
+Name[it]=Schermo bloccato
+Name[ja]=スクリーンロック
+Name[kk]=Экран бұғатталды
+Name[km]=បាន​ចាក់សោ​អេក្រង់​
+Name[kn]=ತೆರೆ ಲಾಕ್ ಆಗಿದೆ
+Name[ko]=화면  김
+Name[lt]=Ekranas užrakintas
+Name[lv]=Ekrāns slēgts
+Name[mk]=Екранот е заклучен
+Name[ml]=സ്ക്രീന്‍ പൂട്ടി
+Name[nb]=Skjermen låst
+Name[nds]=Schirm afslaten
+Name[nl]=Scherm vergrendeld
+Name[nn]=Skjermen er låst
+Name[pa]=ਸਕਰੀਨ ਲਾਕ ਹੈ
+Name[pl]=Ekran zablokowany
+Name[pt]=Ecrã bloqueado
+Name[pt_BR]=Tela bloqueada
+Name[ro]=Ecran blocat
+Name[ru]=Экран заблокирован
+Name[si]=තිරය අගුලු දමන ලදි
+Name[sk]=Obrazovka zamknutá
+Name[sl]=Zaklep zaslona
+Name[sr]=Екран закључан
+Name[sr@ijekavian]=Екран закључан
+Name[sr@ijekavianlatin]=Ekran zaključan
+Name[sr@latin]=Ekran zaključan
+Name[sv]=Skärm låst
+Name[tg]=Пардаи экран қулф шуд
+Name[th]=หน้าจอถูกล็อคอยู่
+Name[tr]=Ekran kilitlendi
+Name[ug]=ئېكران قۇلۇپلاندى
+Name[uk]=Екран заблоковано
+Name[wa]=Waitroûle eclawêye
+Name[x-test]=xxScreen lockedxx
+Name[zh_CN]=屏幕已锁定
+Name[zh_TW]=螢幕已鎖定
+Comment=The screen has been locked
+Comment[ar]=تمّ قفل الشاشة
+Comment[ast]=Bloquióse la pantalla
+Comment[bg]=Екранът е заключен
+Comment[bs]=Ekran je upravo zaključan
+Comment[ca]=S'ha bloquejat la pantalla
+Comment[ca@valencia]=S'ha bloquejat la pantalla
+Comment[cs]=Obrazovka byla uzamčena
+Comment[csb]=Ekran òstôł zablokòwóny
+Comment[da]=Skærmen er blevet låst
+Comment[de]=Der Bildschirm wurde gesperrt.
+Comment[el]=Η οθόνη έχει κλειδωθεί
+Comment[en_GB]=The screen has been locked
+Comment[eo]=La ekrano ŝlosiĝis
+Comment[es]=Se ha bloqueado la pantalla
+Comment[et]=Ekraan on lukustatud
+Comment[eu]=Pantaila giltzatu egin da
+Comment[fi]=Näyttö on lukittunut
+Comment[fr]=L'écran a été verrouillé 
+Comment[fy]=It skerm is beskoattele
+Comment[ga]=Cuireadh an scáileán faoi ghlas
+Comment[gl]=A pantalla trancouse
+Comment[gu]=સ્ક્રિનને તાળું મારવામાં \
આવ્યું છે +Comment[he]=המסך   על
+Comment[hi]=स्क्रीन तालाबंद कर दिया  \
गया है +Comment[hr]=Zaslon je zaključan
+Comment[hu]=A képernyő zárolt
+Comment[ia]=Le schermo ha essite blocate
+Comment[id]=Layar telah dikunci
+Comment[is]=Skjánum hefur verið læst
+Comment[it]=Lo schermo è stato bloccato
+Comment[ja]=スクリーンがロックされました
+Comment[kk]=Экран бұғатталған
+Comment[km]=អេក្រង់​ត្រូវ​បាន​ចាក់សោ
+Comment[kn]=ಒಂದು ತೆರೆಯನ್ನು ಲಾಕ್‌ \
ಮಾಡಲಾಗಿದೆ +Comment[ko]=화면  김
+Comment[lt]=Ekranas buvo užrakintas
+Comment[lv]=Ekrāns tika slēgts
+Comment[mk]=Екранот беше заклучен
+Comment[ml]=സ്ക്രീന്‍ \
പൂട്ടിയിരിയ്ക്കുന്നു +Comment[nb]=Skjermen er \
nå låst +Comment[nds]=De Schirm wöör afslaten
+Comment[nl]=Het scherm is vergrendeld
+Comment[nn]=Skjermen er låst
+Comment[pa]=ਸਕਰੀਨ ਨੂੰ ਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ
+Comment[pl]=Ekran został zablokowany
+Comment[pt]=O ecrã foi bloqueado
+Comment[pt_BR]=A tela foi bloqueada
+Comment[ro]=Ecranul a fost blocat
+Comment[ru]=Экран заблокирован
+Comment[si]=තිරය අගුළු දමා ඇත
+Comment[sk]=Obrazovka bola zamknutá
+Comment[sl]=Zaslon je bil zaklenjen
+Comment[sr]=Екран је управо закључан
+Comment[sr@ijekavian]=Екран је управо закључан
+Comment[sr@ijekavianlatin]=Ekran je upravo zaključan
+Comment[sr@latin]=Ekran je upravo zaključan
+Comment[sv]=Skärmen har låsts
+Comment[tg]=Клавиша модификатора зафиксирована
+Comment[th]=หน้าจอถูกล็อคอยู่
+Comment[tr]=Ekran kilitlendi
+Comment[ug]=ئېكران قۇلۇپلانغان
+Comment[uk]=Екран було заблоковано
+Comment[wa]=Li waitroûle a stî eclawêye
+Comment[x-test]=xxThe screen has been lockedxx
+Comment[zh_CN]=屏幕已经被锁定
+Comment[zh_TW]=螢幕已被鎖定
+Action=None
+
+[Event/savingstopped]
+Name=Screen saver exited
+Name[ar]=خرجت حافظة الشاشة
+Name[ast]=Finó'l curiapantalles
+Name[bg]=Екранният предпазител е спрян
+Name[bs]=Čuvar ekrana napušten
+Name[ca]=S'ha sortit de l'estalvi de pantalla
+Name[ca@valencia]=S'ha eixit de l'estalvi de pantalla
+Name[cs]= etřič obrazovky ukončen
+Name[csb]=Wëgaszôcz ekranu òstôł zakùńczony
+Name[da]=Pauseskærm afslutter
+Name[de]=Der Bildschirmschoner wurde beendet.
+Name[el]=Η προφύλαξη οθόνης τερμάτισε
+Name[en_GB]=Screen saver exited
+Name[eo]=Ekrankurteno finiĝis
+Name[es]=El salvapantallas ha terminado
+Name[et]=Ekraanisäästja lõpetas töö
+Name[eu]=Pantaila babeslea amaituta
+Name[fi]=Näytönsäästäjä sulkeutui
+Name[fr]=Écran de veille terminé
+Name[fy]=Skermbefeiliging is der útgong
+Name[ga]=Scoireadh ón spárálaí scáileáin
+Name[gl]=O protector de pantalla saíu
+Name[he]=שומר המסך הפסיק
+Name[hi]=स्क्रीन सेवर बंद
+Name[hr]=Zaštita zaslona završila
+Name[hu]=A képernyővédő kilépett
+Name[ia]=Salvator de schermo exite
+Name[id]=Penyimpan layar keluar
+Name[is]=Hætt í skjásvæfu
+Name[it]=Salvaschermo terminato
+Name[ja]=スクリーンセーバー終了
+Name[kk]=Экран қорғаушысы  тоқтады
+Name[km]=បាន​ចេញ​ពី​ធាតុរក្សាអេក្រង់​
 +Name[kn]=ಸ್ಕ್ರೀನ್‌ ಸೇವರ್ \
ನಿರ್ಗಮಿಸಿದೆ +Name[ko]=화면 보호기 종료됨
+Name[lt]=Ekrano užsklanda išsijungė
+Name[lv]=Ekrāna saudzētājs apturēts
+Name[mk]=Чуварот на екранот излезе
+Name[ml]=സ്ക്രീന്‍ സേവറില്‍ നിന്നും \
പുറത്തു് കടന്നിരിയ്ക്കുന്നു \
+Name[nb]=Pauseskjermen avsluttet +Name[nds]=Pausschirm utmaakt
+Name[nl]=Schermbeveiliger geëindigd
+Name[nn]=Pauseskjermen er avslutta
+Name[pa]=ਸਕਰੀਨ ਸੇਵਰ ਬੰਦ
+Name[pl]=Wygaszacz ekranu zakończył się
+Name[pt]=O protector de ecrã terminou
+Name[pt_BR]=O protetor de tela terminou
+Name[ro]=Protecția de ecran a s-a terminat
+Name[ru]=Хранитель экрана завершил работу
+Name[si]=තිර සුරැකුම ඉවත් විය
+Name[sk]= etrič obrazovky skončil
+Name[sl]=Izhod iz ohranjevalnika zaslona
+Name[sr]=Чувар екрана напуштен
+Name[sr@ijekavian]=Чувар екрана напуштен
+Name[sr@ijekavianlatin]=Čuvar ekrana napušten
+Name[sr@latin]=Čuvar ekrana napušten
+Name[sv]=Skärmsläckare avslutades
+Name[tg]=Пардаи экран хомӯш шуд
+Name[th]=โปรแกรมรักษาจอ \
าพจบการทำงานแล้ว +Name[tr]=Ekran koruyucudan \
çıkıldı +Name[ug]=ئېكران قوغدىغۇچ ئاخىرلاشتى
+Name[uk]=Завершено роботу зберігача екрана
+Name[wa]=Sipårgneu di waitroûle a cwité
+Name[x-test]=xxScreen saver exitedxx
+Name[zh_CN]=屏幕保护程序已退出
+Name[zh_TW]=螢幕保護程式已離開
+Comment=The screen saver has finished
+Comment[ar]=حافظة الشاشة انتهت
+Comment[ast]=Finó'l curiapantalles
+Comment[bg]=Екранният предпазител е спрян
+Comment[bs]=Čuvar ekrana se upravo okončao
+Comment[ca]=L'estalvi de pantalla ha finalitzat
+Comment[ca@valencia]=L'estalvi de pantalla ha finalitzat
+Comment[cs]= etřič obrazovky byl ukončen
+Comment[csb]=Wëgaszôcz ekranu òstôł zakùńczony
+Comment[da]=Pauseskærmen er afsluttet
+Comment[de]=Der Bildschirmschoner wurde beendet.
+Comment[el]=Η προφύλαξη οθόνης έχει τελειώσει
+Comment[en_GB]=The screen saver has finished
+Comment[eo]=La ekrankurteno finiĝis
+Comment[es]=El salvapantallas ha terminado
+Comment[et]=Ekraanisäästja lõpetas töö
+Comment[eu]=Pantaila babeslea amaitu da
+Comment[fi]=Näytönsäästäjä on päättynyt
+Comment[fr]=L'écran de veille a terminé
+Comment[fy]=De skermbefeiliging is foltôge
+Comment[ga]=Tá an spárálaí scáileán críochnaithe
+Comment[gl]=O protector de pantalla rematou
+Comment[gu]=સ્ક્રિન સેવર પૂર્ણ થયું છે 
+Comment[he]=שומר המסך הפסיק
+Comment[hi]=स्क्रीन सेवर समाप्त हुआ
+Comment[hr]=Zaštita zaslona je završila
+Comment[hu]=A képernyővédő befejeződött
+Comment[ia]=Le salvator de schermo ha finite
+Comment[id]=Penyimpan layar telah selesai
+Comment[is]=Skjáhvílan hefur lokið sér af
+Comment[it]=Il salvaschermo si è concluso
+Comment[ja]=スクリーンセーバーが終了しました
+Comment[kk]=Экран қорғаушысы жұмысын тоқтатты
+Comment[km]=បាន​បញ្ចប់​ធាតុ​រក្សា​អេក្រង់
 +Comment[kn]=ತೆರೆ ರಕ್ಷಕ (ಸ್ಕ್ರೀನ್ ಸೇವರ್) \
ಅಂತ್ಯಗೊಂಡಿದೆ +Comment[ko]=화면 보호기 종료됨
+Comment[lt]=Ekrano užsklanda baigė darbą
+Comment[lv]=Ekrāna saudzētājs tika apturēts
+Comment[mk]=Чуварот на екранот заврши
+Comment[ml]=സ്ക്രീന്‍ സേവര്‍ \
അവസാനിച്ചു +Comment[nb]=Pauseskjermen er ferdig
+Comment[nds]=De Pausschirm wöör utmaakt
+Comment[nl]=De schermbeveiliging is geëindigd
+Comment[nn]=Pauseskjermen er ferdig
+Comment[pa]=ਸਕਰੀਨ ਸੇਵਰ ਮੁਕੰਮਲ
+Comment[pl]=Wygaszacz ekranu zakończył działanie
+Comment[pt]=O protector de ecrã terminou
+Comment[pt_BR]=O protetor de tela terminou
+Comment[ro]=Protecția de ecran s-a încheiat
+Comment[ru]=Хранитель экрана завершил работу
+Comment[si]=තිරසුරැකුම අවසන් විය
+Comment[sk]= etrič obrazovky bol ukončený
+Comment[sl]=Ohranjevalnik zaslona se je zaključil
+Comment[sr]=Чувар екрана се управо окончао
+Comment[sr@ijekavian]=Чувар екрана се управо окончао
+Comment[sr@ijekavianlatin]=Čuvar ekrana se upravo okončao
+Comment[sr@latin]=Čuvar ekrana se upravo okončao
+Comment[sv]=Skärmsläckaren har avslutats
+Comment[th]=โปรแกรมรักษาจอ \
าพทำงานเสร็จสิ้นแล้ว +Comment[tr]=Ekran \
koruyucu bitti +Comment[ug]=ئېكران قوغدىغۇچ ئاخىرلاشتى
+Comment[uk]= оботу зберігача екрана завершено
+Comment[wa]=Li spårgneu di waitroûle a cwité
+Comment[x-test]=xxThe screen saver has finishedxx
+Comment[zh_CN]=屏幕保护程序已运行完成
+Comment[zh_TW]=螢幕保護程式已完成
+Action=None
+
+[Event/unlocked]
+Name=Screen unlocked
+Name[ar]=فُكًَ قفل الشاشة
+Name[ast]=Pantalla desbloquiada
+Name[bg]=Екранът е отключен
+Name[bs]=Ekran otključan
+Name[ca]=Pantalla desbloquejada
+Name[ca@valencia]=Pantalla desbloquejada
+Name[cs]=Obrazovka odemknuta
+Name[csb]=Ekran òdblokòwóny
+Name[da]=Skærmen er låst op
+Name[de]=Bildschirm freigegeben
+Name[el]=Οθόνη ξεκλείδωτη
+Name[en_GB]=Screen unlocked
+Name[eo]=Ekrano malŝlosita
+Name[es]=Pantalla desbloqueada
+Name[et]=Ekraan on lahtilukustatud
+Name[eu]=Pantaila desblokeatuta
+Name[fi]=Näytön lukitus aukeni
+Name[fr]=Écran déverrouillé
+Name[fy]=Skerm ûntskoattele
+Name[ga]=Scáileán díghlasáilte
+Name[gl]=A pantalla desatrancouse
+Name[gu]=સ્ક્રિનનું તાળું ખૂલેલ છે
+Name[he]=המסך שוחרר
+Name[hi]=स्क्रीन तालाबंद
+Name[hr]=Zaslon otključan
+Name[hu]=A képernyő feloldva
+Name[ia]=Schermo disblocate
+Name[id]=Layar tidak dikunci
+Name[is]=Skjár aflæstur
+Name[it]=Schermo sbloccato
+Name[ja]=スクリーンロック解除
+Name[kk]=Экран бұғаты шешілді
+Name[km]=បាន​​ដោះសោ​អេក្រង់
+Name[kn]=ತೆರೆಯನ್ನು ಅನ್ ಲಾಕ್ \
ಮಾಡಲಾಗಿದೆ +Name[ko]=화면  금 풀림
+Name[lt]=Ekranas atrakintas
+Name[lv]=Ekrāns atslēgts
+Name[mk]=Екранот е отклучен
+Name[ml]=സ്ക്രീന്‍ തുറന്നു
+Name[nb]=Skjermen låst opp
+Name[nds]=Schirm opslaten
+Name[nl]=Scherm ontgrendeld
+Name[nn]=Skjermen er låst opp
+Name[pa]=ਸਕਰੀਨ ਅਣ-ਲਾਕ ਹੈ
+Name[pl]=Ekran odblokowany
+Name[pt]=Ecrã desbloqueado
+Name[pt_BR]=Tela desbloqueada
+Name[ro]=Ecran deblocat
+Name[ru]=Экран разблокирован
+Name[si]=තිරය අගුළු හැරිනි
+Name[sk]=Obrazovka odomknutá
+Name[sl]=Odklep zaslona
+Name[sr]=Екран откључан
+Name[sr@ijekavian]=Екран откључан
+Name[sr@ijekavianlatin]=Ekran otključan
+Name[sr@latin]=Ekran otključan
+Name[sv]=Skärm upplåst
+Name[tg]=Экран кушода шуд
+Name[th]=ปลดล็อคหน้าจอแล้ว
+Name[tr]=Ekranın kilidi açıldı
+Name[ug]=ئېكران قۇلۇپسىزلاندى
+Name[uk]=Екран розблоковано
+Name[wa]=Waitroûle dizeclawêye
+Name[x-test]=xxScreen unlockedxx
+Name[zh_CN]=屏幕已解锁
+Name[zh_TW]=螢幕已解除鎖定
+Comment=The screen has been unlocked
+Comment[ar]=تم قفل الشاشة
+Comment[ast]=Desbloquióse la pantalla
+Comment[bg]=Екранът е отключен
+Comment[bs]=Ekran je upravo otključan
+Comment[ca]=S'ha desbloquejat la pantalla
+Comment[ca@valencia]=S'ha desbloquejat la pantalla
+Comment[cs]=Obrazovka byla odemknuta
+Comment[csb]=Ekran òstôł òdblokòwóny
+Comment[da]=Skærmen er blevet låst op
+Comment[de]=Der Bildschirm wurde freigegeben.
+Comment[el]=Η οθόνη έχει ξεκλειδωθεί
+Comment[en_GB]=The screen has been unlocked
+Comment[eo]=La ekrano malŝlosiĝis
+Comment[es]=Se ha desbloqueado la pantalla
+Comment[et]=Ekraan on lahtilukustatud
+Comment[eu]=Pantaila desblokeatu da
+Comment[fi]=Näytön lukitus on avautunut
+Comment[fr]=L'écran a été déverrouillé
+Comment[fy]=It skerm is ûntskoattele
+Comment[ga]=Tá an scáileán díghlasáilte
+Comment[gl]=A pantalla desatrancouse
+Comment[he]=המסך שוחרר
+Comment[hr]=Zaslon je otključan
+Comment[hu]=A képernyő feloldva
+Comment[ia]=Le schermo ha essite disblocate
+Comment[id]=Layar telah tidak dikunci
+Comment[is]=Skjánum hefur verið aflæst
+Comment[it]=Lo schermo è stato sbloccato
+Comment[ja]=スクリーンのロックが解除されました
+Comment[kk]=Экраннан бұғаты шешілді
+Comment[km]=ធាតុរក្សាអេក្រង់​ត្រូ​វបានដោះសោ
 +Comment[kn]=ತೆರೆಯನ್ನು  ಅನ್ ಲಾಕ್ \
ಮಾಡಲಾಗಿದೆ +Comment[ko]=화면  금 풀림
+Comment[lt]=Ekranas buvo atrakintas
+Comment[lv]=Ekrāns tika atslēgts
+Comment[mk]=Екранот беше отклучен
+Comment[ml]=സ്ക്രീന്‍ \
തുറന്നിരിയ്ക്കുന്നു +Comment[nb]=Skjermen er \
blitt låst opp +Comment[nds]=De Schirm wöör opslaten
+Comment[nl]=Het scherm is ontgrendeld
+Comment[nn]=Skjermen er låst opp
+Comment[pa]=ਸਕਰੀਨ ਨੂੰ ਅਣ-ਲਾਕ ਕੀਤਾ ਗਿਆ
+Comment[pl]=Ekran został odblokowany
+Comment[pt]=O ecrã foi desbloqueado
+Comment[pt_BR]=A tela foi desbloqueada
+Comment[ro]=Ecranul a fost deblocat
+Comment[ru]=Экран разблокирован
+Comment[si]=තිරය අගුළු හැර ඇත
+Comment[sk]=Obrazovka bola odomknutá
+Comment[sl]=Zaslon je bil odklenjen
+Comment[sr]=Екран је управо откључан
+Comment[sr@ijekavian]=Екран је управо откључан
+Comment[sr@ijekavianlatin]=Ekran je upravo otključan
+Comment[sr@latin]=Ekran je upravo otključan
+Comment[sv]=Skärmen har låsts upp
+Comment[tg]=Клавиша модификатора зафиксирована
+Comment[th]=หน้าจอถูกปลดล็อคแล้ว
+Comment[tr]=Ekranın kilidi açıldı
+Comment[ug]=ئېكران قۇلۇپسىزلانغان
+Comment[uk]=Екран було розблоковано
+Comment[wa]=Li waitroûle a stî dizeclawêye
+Comment[x-test]=xxThe screen has been unlockedxx
+Comment[zh_CN]=屏幕已经被解锁
+Comment[zh_TW]=螢幕已解除鎖定
+Action=None
+
+[Event/unlockfailed]
+Name=Screen unlock failed
+Name[ar]=فشل فك قفل الشاشة
+Name[ast]=Nun pudo desbloquiase la pantalla
+Name[bg]=Грешка при отключване на екрана
+Name[bs]=Otključavanje ekrana neuspelo
+Name[ca]=Ha fallat el desbloqueig de la pantalla
+Name[ca@valencia]=Ha fallat el desbloqueig de la pantalla
+Name[cs]=Odemknutí obrazovky selhalo
+Name[csb]=Felënk òdblokòwaniô ekranu
+Name[da]=Det mislykkedes at låse skærmen op
+Name[de]=Entsperren des Bildschirms fehlgeschlagen
+Name[el]=Το ξεκλειδωμα της οθόνης απέτυχε
+Name[en_GB]=Screen unlock failed
+Name[eo]=Malŝlositado de ekrano fiaskis
+Name[es]=No se pudo desbloquear la pantalla
+Name[et]=Ekraani lahtilukustamine nurjus
+Name[eu]=Pantaila desblokeatzeak huts egin du
+Name[fi]=Näytön lukinnan poisto epäonnistui
+Name[fr]=Le déverrouillage de l'écran a échoué
+Name[fy]=Skerm ûntskoatteling is mislearre
+Name[ga]=Níorbh fhéidir an scáileán a dhíghlasáil
+Name[gl]=Fallou o desbloqueo da pantalla
+Name[gu]=સ્ક્રિનનું તાળું ખોલવામાં \
નિષ્ફળ +Name[he]=שיחרור המסך  כשל
+Name[hi]=स्क्रीन ताला नहीं खुला
+Name[hr]=Neuspjelo otključavanje zaslona
+Name[hu]=Nem sikerült feloldani a képernyőt
+Name[ia]=Disbloco de schermo falleva
+Name[id]=Gagal membuka kunci
+Name[is]=Aflæsing skjásins mistókst
+Name[it]=Sblocco dello schermo non riuscito
+Name[ja]=スクリーンのロック解除失敗
+Name[kk]=Экран бұғатын шешуі болмады
+Name[km]=បាន​បរាជ័យ​ក្នុងការ​ដោះសោ​អេក្រង់
 +Name[kn]=ತೆರೆಯನ್ನು ಅನ್ ಲಾಕ್ \
ಮಾಡುವುದು ವಿಫಲವಾಗಿದೆ +Name[ko]=화면  금 \
풀리지 않음 +Name[lt]=Ekrano atrakinimas nepavyko
+Name[lv]=Neizdevās atslēgt ekrānu
+Name[mk]=Не успеа отклучувањето на екранот
+Name[ml]=സ്ക്രീന്‍ തുറക്കുന്നതില്‍ \
പരാജയപ്പെട്ടു +Name[nb]=Det lyktes ikke å låse opp \
skjermen +Name[nds]=Opsluten vun den Schirm fehlslaan
+Name[nl]=Ontgrendelen van scherm is mislukt
+Name[nn]=Klarte ikkje låsa opp skjermen
+Name[pa]=ਸਕਰੀਨ ਖੋਲ੍ਹਣ ਲਈ ਫੇਲ੍ਹ
+Name[pl]=Odblokowanie ekranu nieudane
+Name[pt]=O desbloqueio do ecrã foi mal-sucedido
+Name[pt_BR]=O bloqueio de tela falhou
+Name[ro]=Deblocare ecranului a eșuat
+Name[ru]=Не удалось разблокировать экран
+Name[si]=තිරය අගුළු හැරීම අසාර්ථකයි
+Name[sk]=Odomknutie obrazovky zlyhalo
+Name[sl]=Spodletel odklep zaslona
+Name[sr]=Откључавање екрана неуспело
+Name[sr@ijekavian]=Откључавање екрана неуспјело
+Name[sr@ijekavianlatin]=Otključavanje ekrana neuspjelo
+Name[sr@latin]=Otključavanje ekrana neuspelo
+Name[sv]=Upplåsning av skärm misslyckades
+Name[tg]=Кушодани экран қатъ карда шуд
+Name[th]=ล้มเหลวในการปลดล็อคหน้าจอ
+Name[tr]=Ekran kilidi açılamadı
+Name[ug]=ئېكران قۇلۇپسىزلاش مەغلۇپ بولدى
+Name[uk]=Невдала спроба розблокування екрана
+Name[wa]=Li dizeclawaedje del waitroûle a fwait berwete
+Name[x-test]=xxScreen unlock failedxx
+Name[zh_CN]=屏幕解锁失败 
+Name[zh_TW]=螢幕解除鎖定失敗
+Comment=Failed attempt to unlock the screen
+Comment[ar]=محاولة فاشلة لفك قفل الشاشة
+Comment[ast]=Fallu al intentar desbloquiar la pantalla
+Comment[bg]=Грешка при опит за отключване на екрана
+Comment[bs]=Pokušaj otključavanja ekrana nije uspeo
+Comment[ca]=L'intent de desbloquejar la pantalla ha fallat
+Comment[ca@valencia]=L'intent de desbloquejar la pantalla ha fallat
+Comment[cs]=Pokus o odemknutí obrazovky selhal
+Comment[csb]=Felënk przëstãpù do òdblokòwaniô ekranu
+Comment[da]=Mislykket forsøg på at låse skærmen op
+Comment[de]=Das Entsperren des Bildschirms ist fehlgeschlagen.
+Comment[el]=Αποτυχής προσπάθεια ξεκλειδώματος \
οθόνης +Comment[en_GB]=Failed attempt to unlock the screen
+Comment[eo]=Provo de malŝlosi ekranon fiaskis
+Comment[es]=Error al intentar desbloquear la pantalla
+Comment[et]=Nurjunud katse ekraani lahti lukustada
+Comment[eu]=Pantaila desblokeatzeko saiakerak huts egin du
+Comment[fi]=Yritys näytön lukituksen poistamiseksi epäonnistui
+Comment[fr]=Tentative infructueuse de déverrouiller l'écran
+Comment[fy]=It is net slagge om it skerm te ûntskoatteljen
+Comment[ga]=Theip ar iarracht an scáileán a dhíghlasáil
+Comment[gl]=Fallou a tentativa de desbloquear a pantalla
+Comment[he]= יסיון כושל לשיחרור המסך
+Comment[hr]=Propao je pokušaj otključavanja zaslona
+Comment[hu]=Nem sikerült feloldani a képernyőt
+Comment[ia]=Tentativa fallite de disblocar le schermo
+Comment[id]=Gagal mencoba membuka kunci layar
+Comment[is]=Tilraun til að aflæsa skjánum mistókst
+Comment[it]=Tentanivo di sbloccare lo schermo non riuscito
+Comment[ja]=スクリーンのロックを解除できませんでした
+Comment[kk]=Экран бұғатын шешу әректі сәтсіз \
аяқталды +Comment[km]=បាន​បរាជ័យ​ក្នុង​ការ​ដោះសោ​អេក្រង់
 +Comment[kn]=ತೆರೆಯನ್ನು ಅನ್ ಲಾಕ್ ಮಾಡುವ \
ವಿಫಲ ಯತ್ನ +Comment[ko]=화면  금 풀리지 않음
+Comment[lt]=Nepavyko bandymas atrakinti ekraną
+Comment[lv]=Neizdevās atslēgt ekrānu
+Comment[mk]=Не успеа обидот да се отклучи екранот
+Comment[ml]=സ്ക്രീന്‍ തുറക്കാനുള്ള \
ശ്രമം പരാജയപ്പെട്ടിരിയ്ക്കുന്നു
 +Comment[nb]=Klarte ikke å låse opp skjermen
+Comment[nds]=Opsluten vun den Schirm hett nich funkscheneert
+Comment[nl]=Een mislukte poging om het scherm te ontgrendelen
+Comment[nn]=Forsøket på å låsa opp skjermen var mislukka
+Comment[pa]=ਸਕਰੀਨ ਅਣ-ਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ \
ਫੇਲ੍ਹ ਹੋਈ +Comment[pl]=Nieudana próba odblokowania ekranu
+Comment[pt]=Falhou a tentativa de desbloquear o ecrã
+Comment[pt_BR]=A tentativa de desbloquear a tela falhou
+Comment[ro]=Încercare eșuată de a debloca ecranul
+Comment[ru]=Не удалось разблокировать экран
+Comment[si]=තිරය අගුළු හැරිමේ උත්සාහය \
අසාර්ථකයි +Comment[sk]=Neúspešný pokus o odomknutie obrazovky
+Comment[sl]=Spodletel poskus odklepa zaslona
+Comment[sr]=Покушај откључавања екрана није успео
+Comment[sr@ijekavian]=Покушај откључавања екрана није \
успио +Comment[sr@ijekavianlatin]=Pokušaj otključavanja ekrana nije uspio
+Comment[sr@latin]=Pokušaj otključavanja ekrana nije uspeo
+Comment[sv]=Misslyckat försök att låsa upp skärmen
+Comment[th]=ล้มเหลวในการพยายามปลดล็อคหน้าจอ
 +Comment[tr]=Ekran kilidini açma denemesi başarısız oldu
+Comment[ug]=ئېكراننى قۇلۇپسىزلاندۇرالمىدى
+Comment[uk]=Спроба розблокування екрана \
завершилася невдало +Comment[wa]=Li saye di dizeclawaedje del \
waitroûle a fwait berwete +Comment[x-test]=xxFailed attempt to unlock the screenxx
+Comment[zh_CN]=尝试解锁屏幕失败
+Comment[zh_TW]=螢幕解除鎖定失敗
+Action=None
diff --git a/kwin/screenlocker/lock/lockdlg.cc b/kwin/screenlocker/lock/lockdlg.cc
new file mode 100644
index 0000000..14a9b34
--- /dev/null
+++ b/kwin/screenlocker/lock/lockdlg.cc
@@ -0,0 +1,667 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+// Copyright 2003 Chris Howells <howells@kde.org>
+// Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
+
+#include <config-unix.h> // HAVE_PAM
+
+#include "lockprocess.h"
+#include "lockdlg.h"
+
+#include <kcheckpass-enums.h>
+#include <kworkspace/kdisplaymanager.h>
+
+#include <KApplication>
+#include <KLocale>
+#include <KPushButton>
+#include <KSeparator>
+#include <KStandardDirs>
+#include <KGlobalSettings>
+#include <KConfig>
+#include <KIconLoader>
+#include <KNotification>
+#include <kdesu/defaults.h>
+#include <KPasswordDialog>
+#include <KDebug>
+#include <KUser>
+#include <KMessageBox>
+#include <KColorScheme>
+
+#include <QtDBus/QtDBus>
+
+#include <QLayout>
+#include <QPushButton>
+// #include <QMessageBox>
+#include <QLabel>
+#include <QFontMetrics>
+#include <QStyle>
+#include <QApplication>
+#include <QTreeWidget>
+#include <QHeaderView>
+#include <QCheckBox>
+#include <QGridLayout>
+#include <QEvent>
+#include <QFrame>
+#include <QHBoxLayout>
+#include <QBoxLayout>
+#include <QSocketNotifier>
+#include <QTimerEvent>
+#include <QVBoxLayout>
+#include <QFile>
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <fixx11h.h>
+#include <QX11Info>
+#include <kauthorized.h>
+
+#include <KPluginLoader>
+#include <KPluginFactory>
+
+#ifndef AF_LOCAL
+# define AF_LOCAL	AF_UNIX
+#endif
+
+#define PASSDLG_HIDE_TIMEOUT 10000
+
+//===========================================================================
+//
+// Simple dialog for entering a password.
+//
+PasswordDlg::PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin, const \
QString &text) +    : KDialog(parent, Qt::X11BypassWindowManagerHint),
+      mPlugin( plugin ),
+      mCapsLocked(-1),
+      mUnlockingFailed(false),
+      sNot(0)
+{
+    QWidget* w = mainWidget();
+
+    QLabel *pixLabel = new QLabel( w );
+    pixLabel->setPixmap(DesktopIcon(QLatin1String( "system-lock-screen" )));
+
+    KUser user; QString fullName=user.property(KUser::FullName).toString();
+    QString greetString = text;
+    if (text.isEmpty()) {
+        greetString = fullName.isEmpty() ?
+            i18n("<nobr><b>The session is locked</b></nobr><br />") :
+            i18n("<nobr><b>The session was locked by %1</b></nobr><br />", fullName \
); +    }
+    QLabel *greetLabel = new QLabel(greetString, w);
+
+    mStatusLabel = new QLabel( QLatin1String( "<b> </b>" ), w );
+    mStatusLabel->setAlignment( Qt::AlignCenter );
+
+    greet = plugin->info->create(this, w, QString(),
+                                 KGreeterPlugin::Authenticate,
+                                 KGreeterPlugin::ExUnlock);
+
+    KSeparator *sep = new KSeparator( Qt::Horizontal, w );
+
+    ok = new KPushButton( KGuiItem(i18n("Unl&ock"), QLatin1String( "object-unlocked" \
)), w ); +    cancel = new KPushButton( KStandardGuiItem::cancel(), w );
+    mNewSessButton = new KPushButton( KGuiItem(i18n("Sw&itch User..."), \
QLatin1String( "fork" )), w ); +
+    // Using keyboard layout component
+    KPluginFactory *kxkbFactory = KPluginLoader(QLatin1String( \
"keyboard_layout_widget" )).factory(); +    QWidget *kxkbComponent = NULL;
+    if (kxkbFactory) {
+        kxkbComponent = kxkbFactory->create<QWidget>(this);
+    }
+    else {
+        kDebug() << "can't load keyboard layout widget library";
+    }
+
+    QHBoxLayout *layStatus = new QHBoxLayout();
+    layStatus->addStretch();
+    layStatus->addWidget( mStatusLabel );
+    layStatus->addStretch();
+
+    if( kxkbComponent ) {
+	//TODO: without this the widget is off the parent area, but we need something \
better here +        kxkbComponent->setFixedSize(48, 24);
+        layStatus->addWidget( kxkbComponent, 0, Qt::AlignRight );
+    }
+
+    QHBoxLayout *layButtons = new QHBoxLayout();
+    layButtons->addWidget( mNewSessButton );
+    layButtons->addStretch();
+    layButtons->addWidget( ok );
+    layButtons->addWidget( cancel );
+
+    frameLayout = new QGridLayout( w );
+    frameLayout->setSpacing( KDialog::spacingHint() );
+    frameLayout->setMargin( KDialog::marginHint() );
+    frameLayout->addWidget( pixLabel, 0, 0, 3, 1, Qt::AlignTop );
+    frameLayout->addWidget( greetLabel, 0, 1 );
+    frameLayout->addWidget( greet->getWidgets().first(), 1, 1 );
+    frameLayout->addLayout( layStatus, 2, 1 );
+    frameLayout->addWidget( sep, 3, 0, 1, 2 );
+    frameLayout->addLayout( layButtons, 4, 0, 1, 2 );
+
+    setButtons(None);
+    connect(cancel, SIGNAL(clicked()), SLOT(reject()));
+    connect(ok, SIGNAL(clicked()), SLOT(slotOK()));
+    connect(mNewSessButton, SIGNAL(clicked()), SLOT(slotSwitchUser()));
+
+    if (!text.isEmpty() || !KDisplayManager().isSwitchable() || \
!KAuthorized::authorizeKAction(QLatin1String( "switch_user" ))) +        \
mNewSessButton->hide(); +
+    installEventFilter(this);
+
+    mFailedTimerId = 0;
+    mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT);
+    connect(qApp, SIGNAL(activity()), SLOT(slotActivity()) );
+
+    greet->start();
+
+    capsLocked();
+}
+
+PasswordDlg::~PasswordDlg()
+{
+    hide();
+    delete greet;
+}
+
+void PasswordDlg::updateLabel()
+{
+    if (mUnlockingFailed)
+    {
+        QPalette palette;
+        KColorScheme::adjustForeground(palette, KColorScheme::NormalText, \
QPalette::WindowText); +        mStatusLabel->setPalette(palette);
+        mStatusLabel->setText(i18n("<b>Unlocking failed</b>"));
+    }
+    else
+    if (mCapsLocked)
+    {
+        QPalette palette = mStatusLabel->palette();
+        KColorScheme::adjustForeground(palette, KColorScheme::NegativeText, \
QPalette::WindowText); +        mStatusLabel->setPalette(palette);
+        mStatusLabel->setText(i18n("<b>Warning: Caps Lock on</b>"));
+    }
+    else
+    {
+        mStatusLabel->setText(QLatin1String( "<b> </b>" ));
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+// Handle timer events.
+//
+void PasswordDlg::timerEvent(QTimerEvent *ev)
+{
+    if (ev->timerId() == mTimeoutTimerId)
+    {
+        done(TIMEOUT_CODE);
+    }
+    else if (ev->timerId() == mFailedTimerId)
+    {
+        killTimer(mFailedTimerId);
+        mFailedTimerId = 0;
+        // Show the normal password prompt.
+        mUnlockingFailed = false;
+        updateLabel();
+        ok->setEnabled(true);
+        cancel->setEnabled(true);
+        mNewSessButton->setEnabled( true );
+        greet->revive();
+        greet->start();
+    }
+}
+
+bool PasswordDlg::eventFilter(QObject *, QEvent *ev)
+{
+    if (ev->type() == QEvent::KeyPress || ev->type() == QEvent::KeyRelease)
+        capsLocked();
+    return false;
+}
+
+void PasswordDlg::slotActivity()
+{
+    if (mTimeoutTimerId) {
+        killTimer(mTimeoutTimerId);
+        mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT);
+    }
+}
+
+////// kckeckpass interface code
+
+int PasswordDlg::Reader (void *buf, int count)
+{
+    int ret, rlen;
+
+    for (rlen = 0; rlen < count; ) {
+      dord:
+        ret = ::read (sFd, (void *)((char *)buf + rlen), count - rlen);
+        if (ret < 0) {
+            if (errno == EINTR)
+                goto dord;
+            if (errno == EAGAIN)
+                break;
+            return -1;
+        }
+        if (!ret)
+            break;
+        rlen += ret;
+    }
+    return rlen;
+}
+
+bool PasswordDlg::GRead (void *buf, int count)
+{
+    return Reader (buf, count) == count;
+}
+
+bool PasswordDlg::GWrite (const void *buf, int count)
+{
+    return ::write (sFd, buf, count) == count;
+}
+
+bool PasswordDlg::GSendInt (int val)
+{
+    return GWrite (&val, sizeof(val));
+}
+
+bool PasswordDlg::GSendStr (const char *buf)
+{
+    int len = buf ? ::strlen (buf) + 1 : 0;
+    return GWrite (&len, sizeof(len)) && GWrite (buf, len);
+}
+
+bool PasswordDlg::GSendArr (int len, const char *buf)
+{
+    return GWrite (&len, sizeof(len)) && GWrite (buf, len);
+}
+
+bool PasswordDlg::GRecvInt (int *val)
+{
+    return GRead (val, sizeof(*val));
+}
+
+bool PasswordDlg::GRecvArr (char **ret)
+{
+    int len;
+    char *buf;
+
+    if (!GRecvInt(&len))
+        return false;
+    if (!len) {
+        *ret = 0;
+        return true;
+    }
+    if (!(buf = (char *)::malloc (len)))
+        return false;
+    *ret = buf;
+    if (GRead (buf, len)) {
+        return true;
+    } else {
+        ::free(buf);
+        *ret = 0;
+        return false;
+    }
+}
+
+void PasswordDlg::reapVerify()
+{
+    sNot->setEnabled( false );
+    sNot->deleteLater();
+    sNot = 0;
+    ::close( sFd );
+    int status;
+    while (::waitpid( sPid, &status, 0 ) < 0)
+        if (errno != EINTR) { // This should not happen ...
+            cantCheck();
+            return;
+        }
+    if (WIFEXITED(status))
+        switch (WEXITSTATUS(status)) {
+        case AuthOk:
+            greet->succeeded();
+            accept();
+            return;
+        case AuthBad:
+            greet->failed();
+            mUnlockingFailed = true;
+            updateLabel();
+            mFailedTimerId = startTimer(1500);
+            ok->setEnabled(false);
+            cancel->setEnabled(false);
+            mNewSessButton->setEnabled( false );
+            KNotification::event( QLatin1String( "unlockfailed" ) );
+            return;
+        case AuthAbort:
+            return;
+        }
+    cantCheck();
+}
+
+void PasswordDlg::handleVerify()
+{
+    int ret;
+    char *arr;
+
+    if (GRecvInt( &ret )) {
+        switch (ret) {
+        case ConvGetBinary:
+            if (!GRecvArr( &arr ))
+                break;
+            greet->binaryPrompt( arr, false );
+            if (arr)
+                ::free( arr );
+            return;
+        case ConvGetNormal:
+            if (!GRecvArr( &arr ))
+                break;
+            greet->textPrompt( arr, true, false );
+            if (arr)
+                ::free( arr );
+            return;
+        case ConvGetHidden:
+            if (!GRecvArr( &arr ))
+                break;
+            greet->textPrompt( arr, false, false );
+            if (arr)
+                ::free( arr );
+            return;
+        case ConvPutInfo:
+            if (!GRecvArr( &arr ))
+                break;
+            if (!greet->textMessage( arr, false ))
+                static_cast< LockProcess* >(parent())->msgBox( this, \
QMessageBox::Information, QString::fromLocal8Bit( arr ) ); +            ::free( arr \
); +            return;
+        case ConvPutError:
+            if (!GRecvArr( &arr ))
+                break;
+            if (!greet->textMessage( arr, true ))
+                static_cast< LockProcess* >(parent())->msgBox( this, \
QMessageBox::Warning, QString::fromLocal8Bit( arr ) ); +            ::free( arr );
+            return;
+        }
+    }
+    reapVerify();
+}
+
+////// greeter plugin callbacks
+
+void PasswordDlg::gplugReturnText( const char *text, int tag )
+{
+    GSendStr( text );
+    if (text)
+        GSendInt( tag );
+}
+
+void PasswordDlg::gplugReturnBinary( const char *data )
+{
+    if (data) {
+        unsigned const char *up = (unsigned const char *)data;
+        int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24);
+        if (!len)
+            GSendArr( 4, data );
+        else
+            GSendArr( len, data );
+    } else
+        GSendArr( 0, 0 );
+}
+
+void PasswordDlg::gplugSetUser( const QString & )
+{
+    // ignore ...
+}
+
+void PasswordDlg::cantCheck()
+{
+    greet->failed();
+    static_cast< LockProcess* >(parent())->msgBox( this, QMessageBox::Critical,
+        i18n("Cannot unlock the session because the authentication system failed to \
work;\n" +             "you must kill kscreenlocker (pid %1) manually.", getpid()) );
+    greet->revive();
+}
+
+//---------------------------------------------------------------------------
+//
+// Starts the kcheckpass process to check the user's password.
+//
+void PasswordDlg::gplugStart()
+{
+    int sfd[2];
+    char fdbuf[16];
+
+    if (sNot)
+        return;
+    if (::socketpair(AF_LOCAL, SOCK_STREAM, 0, sfd)) {
+        cantCheck();
+        return;
+    }
+    if ((sPid = ::fork()) < 0) {
+        ::close(sfd[0]);
+        ::close(sfd[1]);
+        cantCheck();
+        return;
+    }
+    if (!sPid) {
+        ::close(sfd[0]);
+        sprintf(fdbuf, "%d", sfd[1]);
+        execlp(QFile::encodeName(KStandardDirs::findExe(QLatin1String( "kcheckpass" \
))).data(), +               "kcheckpass",
+               "-m", mPlugin->info->method,
+               "-S", fdbuf,
+               (char *)0);
+        _exit(20);
+    }
+    ::close(sfd[1]);
+    sFd = sfd[0];
+    sNot = new QSocketNotifier(sFd, QSocketNotifier::Read, this);
+    connect(sNot, SIGNAL(activated(int)), SLOT(handleVerify()));
+}
+
+void PasswordDlg::gplugChanged()
+{
+}
+
+void PasswordDlg::gplugActivity()
+{
+    slotActivity();
+}
+
+void PasswordDlg::gplugMsgBox( QMessageBox::Icon type, const QString &text )
+{
+    static_cast< LockProcess* >(parent())->msgBox( this, type, text );
+}
+
+bool PasswordDlg::gplugHasNode( const QString & )
+{
+    return false;
+}
+
+void PasswordDlg::slotOK()
+{
+    greet->next();
+}
+
+
+void PasswordDlg::setVisible( bool visible )
+{
+    QDialog::setVisible( visible );
+
+    if ( visible )
+        QApplication::flush();
+}
+
+void PasswordDlg::slotStartNewSession()
+{
+    if (!KMessageBox::shouldBeShownContinue( QLatin1String( ":confirmNewSession" ) \
)) { +        KDisplayManager().startReserve();
+        return;
+    }
+
+    killTimer(mTimeoutTimerId);
+    mTimeoutTimerId = 0;
+
+    KDialog *dialog = new KDialog( this, Qt::X11BypassWindowManagerHint );
+    dialog->setModal( true );
+    dialog->setButtons( KDialog::Yes | KDialog::No );
+    dialog->setButtonGuiItem( KDialog::Yes, KGuiItem(i18n("&Start New Session"), \
QLatin1String( "fork" )) ); +    dialog->setButtonGuiItem( KDialog::No, \
KStandardGuiItem::cancel() ); +    dialog->setDefaultButton( KDialog::Yes );
+    dialog->setEscapeButton( KDialog::No );
+
+    bool dontAskAgain = false;
+
+    KMessageBox::createKMessageBox( dialog, QMessageBox::Warning,
+          i18n("You have chosen to open another desktop session "
+               "instead of resuming the current one.\n"
+               "The current session will be hidden "
+               "and a new login screen will be displayed.\n"
+               "An F-key is assigned to each session; "
+               "F%1 is usually assigned to the first session, "
+               "F%2 to the second session and so on. "
+               "You can switch between sessions by pressing "
+               "Ctrl, Alt and the appropriate F-key at the same time. "
+               "Additionally, the KDE Panel and Desktop menus have "
+               "actions for switching between sessions.",
+             7, 8),
+        QStringList(),
+        i18n("&Do not ask again"), &dontAskAgain,
+        KMessageBox::NoExec );
+
+    int ret = static_cast< LockProcess* >( parent())->execDialog( dialog );
+
+    delete dialog;
+
+    if (ret == KDialog::Yes) {
+        if (dontAskAgain)
+            KMessageBox::saveDontShowAgainContinue( QLatin1String( \
":confirmNewSession" ) ); +        KDisplayManager().startReserve();
+    }
+
+    mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT);
+}
+
+class LockListViewItem : public QTreeWidgetItem {
+public:
+    LockListViewItem( QTreeWidget *parent,
+                      const QString &sess, const QString &loc, int _vt )
+        : QTreeWidgetItem( parent )
+        , vt( _vt )
+    {
+        setText( 0, sess );
+        setText( 1, loc );
+    }
+
+    int vt;
+};
+
+void PasswordDlg::slotSwitchUser()
+{
+    int p = 0;
+    KDisplayManager dm;
+
+    QDialog dialog( this, Qt::X11BypassWindowManagerHint );
+    dialog.setModal( true );
+
+    QBoxLayout *hbox = new QHBoxLayout( &dialog );
+    hbox->setSpacing( KDialog::spacingHint() );
+    hbox->setMargin( KDialog::marginHint() );
+
+    QBoxLayout *vbox1 = new QVBoxLayout( );
+    hbox->addItem( vbox1 );
+    QBoxLayout *vbox2 = new QVBoxLayout( );
+    hbox->addItem( vbox2 );
+
+    KPushButton *btn;
+
+    SessList sess;
+    if (dm.localSessions( sess )) {
+
+        lv = new QTreeWidget( &dialog );
+        connect( lv, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), \
SLOT(slotSessionActivated()) ); +        connect( lv, \
SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), &dialog, SLOT(reject()) ); +       \
lv->setAllColumnsShowFocus( true ); +        lv->setHeaderLabels( QStringList() << \
i18n("Session") << i18n("Location") ); +        lv->header()->setResizeMode( 0, \
QHeaderView::Stretch ); +        lv->header()->setResizeMode( 1, QHeaderView::Stretch \
); +        QTreeWidgetItem *itm = 0;
+        QString user, loc;
+        int ns = 0;
+        for (SessList::ConstIterator it = sess.constBegin(); it != sess.constEnd(); \
++it) { +            KDisplayManager::sess2Str2( *it, user, loc );
+            itm = new LockListViewItem( lv, user, loc, (*it).vt );
+            if (!(*it).vt)
+                itm->setFlags( itm->flags() & ~Qt::ItemIsEnabled );
+            if ((*it).self) {
+                lv->setCurrentItem( itm );
+                itm->setSelected( true );
+            }
+            ns++;
+        }
+        int fw = lv->frameWidth() * 2;
+        QSize hds( lv->header()->sizeHint() );
+        lv->setMinimumWidth( fw + hds.width() +
+            (ns > 10 ? style()->pixelMetric(QStyle::PM_ScrollBarExtent) : 0 ) );
+        int ih = lv->itemDelegate()->sizeHint(
+            QStyleOptionViewItem(), lv->model()->index( 0, 0 ) ).height();
+        lv->setFixedHeight( fw + hds.height() +
+            ih * (ns < 6 ? 6 : ns > 10 ? 10 : ns) );
+        lv->header()->adjustSize();
+        vbox1->addWidget( lv );
+
+        btn = new KPushButton( KGuiItem(i18nc("session", "&Activate"), \
QLatin1String( "fork" )), &dialog ); +        connect( btn, SIGNAL(clicked()), \
SLOT(slotSessionActivated()) ); +        connect( btn, SIGNAL(clicked()), &dialog, \
SLOT(reject()) ); +        vbox2->addWidget( btn );
+        vbox2->addStretch( 2 );
+    }
+
+    if (KAuthorized::authorizeKAction(QLatin1String( "start_new_session" )) && (p = \
dm.numReserve()) >= 0) +    {
+        btn = new KPushButton( KGuiItem(i18n("Start &New Session"), QLatin1String( \
"fork" )), &dialog ); +        connect( btn, SIGNAL(clicked()), \
SLOT(slotStartNewSession()) ); +        connect( btn, SIGNAL(clicked()), &dialog, \
SLOT(reject()) ); +        if (!p)
+            btn->setEnabled( false );
+        vbox2->addWidget( btn );
+        vbox2->addStretch( 1 );
+    }
+
+    btn = new KPushButton( KStandardGuiItem::cancel(), &dialog );
+    connect( btn, SIGNAL(clicked()), &dialog, SLOT(reject()) );
+    vbox2->addWidget( btn );
+
+    static_cast< LockProcess* >(parent())->execDialog( &dialog );
+}
+
+void PasswordDlg::slotSessionActivated()
+{
+    LockListViewItem *itm = (LockListViewItem *)lv->currentItem();
+    if (itm && itm->vt > 0)
+        KDisplayManager().switchVT( itm->vt );
+}
+
+void PasswordDlg::capsLocked()
+{
+    unsigned int lmask;
+    Window dummy1, dummy2;
+    int dummy3, dummy4, dummy5, dummy6;
+    XQueryPointer(QX11Info::display(), DefaultRootWindow( QX11Info::display() ), \
&dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &lmask); +    mCapsLocked = \
lmask & LockMask; +    updateLabel();
+}
+
+#include "lockdlg.moc"
diff --git a/kwin/screenlocker/lock/lockdlg.h b/kwin/screenlocker/lock/lockdlg.h
new file mode 100644
index 0000000..f25e55f
--- /dev/null
+++ b/kwin/screenlocker/lock/lockdlg.h
@@ -0,0 +1,96 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+// Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
+//
+
+#ifndef __LOCKDLG_H__
+#define __LOCKDLG_H__
+
+#include <kgreeterplugin.h>
+
+#include <KDialog>
+
+#include <QLabel>
+#include <QTimerEvent>
+#include <QFrame>
+#include <QGridLayout>
+#include <QEvent>
+
+struct GreeterPluginHandle;
+class LockProcess;
+class QFrame;
+class QGridLayout;
+class QLabel;
+class KPushButton;
+class QSocketNotifier;
+class QTreeWidget;
+
+//===========================================================================
+//
+// Simple dialog for entering a password.
+// It does not handle password validation.
+//
+class PasswordDlg : public KDialog, public KGreeterPluginHandler
+{
+    Q_OBJECT
+
+public:
+    PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin, const QString \
&text = QString()); +    ~PasswordDlg();
+    virtual void setVisible(bool visible);
+
+    // from KGreetPluginHandler
+    virtual void gplugReturnText( const char *text, int tag );
+    virtual void gplugReturnBinary( const char *data );
+    virtual void gplugSetUser( const QString & );
+    virtual void gplugStart();
+    virtual void gplugChanged();
+    virtual void gplugActivity();
+    virtual void gplugMsgBox( QMessageBox::Icon type, const QString &text );
+    virtual bool gplugHasNode( const QString &id );
+
+protected:
+    virtual void timerEvent(QTimerEvent *);
+    virtual bool eventFilter(QObject *, QEvent *);
+
+private Q_SLOTS:
+    void slotSwitchUser();
+    void slotSessionActivated();
+    void slotStartNewSession();
+    void slotOK();
+    void slotActivity();
+    void handleVerify();
+
+private:
+    void capsLocked();
+    void updateLabel();
+    int Reader (void *buf, int count);
+    bool GRead (void *buf, int count);
+    bool GWrite (const void *buf, int count);
+    bool GSendInt (int val);
+    bool GSendStr (const char *buf);
+    bool GSendArr (int len, const char *buf);
+    bool GRecvInt (int *val);
+    bool GRecvArr (char **buf);
+    void reapVerify();
+    void cantCheck();
+    GreeterPluginHandle *mPlugin;
+    KGreeterPlugin *greet;
+    QFrame      *frame;
+    QGridLayout *frameLayout;
+    QLabel      *mStatusLabel;
+    KPushButton *mNewSessButton, *ok, *cancel;
+    int         mFailedTimerId;
+    int         mTimeoutTimerId;
+    int         mCapsLocked;
+    bool        mUnlockingFailed;
+    int         sPid, sFd;
+    QSocketNotifier *sNot;
+    QTreeWidget *lv;
+};
+
+#endif
+
diff --git a/kwin/screenlocker/lock/lockprocess.cc \
b/kwin/screenlocker/lock/lockprocess.cc new file mode 100644
index 0000000..65c7f1d
--- /dev/null
+++ b/kwin/screenlocker/lock/lockprocess.cc
@@ -0,0 +1,1808 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+// Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
+// Copyright 2008 Chani Armitage <chanika@gmail.com>
+//
+
+//krunner keeps running and checks user inactivity
+//when it should show screensaver (and maybe lock the session),
+//it starts kscreenlocker, who does all the locking and who
+//actually starts the screensaver
+
+//It's done this way to prevent screen unlocking when krunner
+//crashes
+
+#include "lockprocess.h"
+#include "lockprocessadaptor.h"
+
+#include <config-workspace.h>
+#include <config-X11.h>
+#include <config-krunner-lock.h>
+#include "lockdlg.h"
+#include "autologout.h"
+#include "kscreensaversettings.h"
+
+#include <kephal/screens.h>
+
+#include <kworkspace/kdisplaymanager.h>
+
+#include <KStandardDirs>
+#include <KApplication>
+#include <KServiceGroup>
+#include <KDebug>
+#include <KMessageBox>
+#include <KGlobalSettings>
+#include <KLocale>
+#include <KLibrary>
+#include <KNotification>
+#include <KPushButton>
+#include <KStandardGuiItem>
+#include <KAuthorized>
+#include <KDesktopFile>
+#include <kservicetypetrader.h>
+#include <kmacroexpander.h>
+#include <kshell.h>
+#include <kxerrorhandler.h>
+
+#include <QtGui/QFrame>
+#include <QLabel>
+#include <QLayout>
+#include <QCursor>
+#include <QTimer>
+#include <QFile>
+#include <QSocketNotifier>
+#include <QDesktopWidget>
+#include <QX11Info>
+#include <QTextStream>
+#include <QPainter>
+#include <QDBusConnection>
+#include <QDBusConnectionInterface>
+#include <QDBusInterface>
+#include <QDBusServiceWatcher>
+
+#include <QtCore/QStringBuilder> // % operator for QString
+
+#include <QDateTime>
+
+#include <stdlib.h>
+#include <assert.h>
+#include <signal.h>
+#include <unistd.h>
+#ifdef HAVE_SETPRIORITY
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+#ifdef HAVE_DPMS
+extern "C" {
+#include <X11/Xmd.h>
+#ifndef Bool
+#define Bool BOOL
+#endif
+#include <X11/extensions/dpms.h>
+
+#ifndef HAVE_DPMSINFO_PROTO
+Status DPMSInfo ( Display *, CARD16 *, BOOL * );
+#endif
+}
+#endif
+
+#ifdef HAVE_XF86MISC
+#include <X11/extensions/xf86misc.h>
+#endif
+
+#ifdef HAVE_GLXCHOOSEVISUAL
+#include <GL/glx.h>
+#endif
+
+#define LOCK_GRACE_DEFAULT          5000
+#define AUTOLOGOUT_DEFAULT          600
+
+static Window gVRoot = 0;
+static Window gVRootData = 0;
+static Atom   gXA_VROOT;
+static Atom   gXA_SCREENSAVER_VERSION;
+
+//#define CHECK_XSELECTINPUT
+#ifdef CHECK_XSELECTINPUT
+#include <dlfcn.h>
+static bool check_xselectinput = false;
+extern "C"
+int XSelectInput( Display* dpy, Window w, long e )
+{
+    typedef int (*ptr)(Display*, Window, long);
+    static ptr fun = NULL;
+    if( fun == NULL )
+        fun = (ptr)dlsym( RTLD_NEXT, "XSelectInput" );
+    if( check_xselectinput && w == DefaultRootWindow( dpy ))
+        kDebug() << kBacktrace();
+    return fun( dpy, w, e );
+}
+#endif
+
+static QLatin1String s_overlayServiceName("org.kde.plasma-overlay");
+
+//===========================================================================
+//
+// Screen saver handling process.  Handles screensaver window,
+// starting screensaver hacks, and password entry.f
+//
+LockProcess::LockProcess(bool child, bool useBlankOnly)
+    : QWidget(0L, Qt::X11BypassWindowManagerHint),
+      mInitialLock(false),
+      mLocked(false),
+      mBusy(false),
+      mPlasmaDBus(0),
+      mServiceWatcher(0),
+      mSetupMode(false),
+      mOpenGLVisual(false),
+      child_saver(child),
+      mParent(0),
+      mUseBlankOnly(useBlankOnly),
+      mSuspended(false),
+      mVisibility(false),
+      mEventRecursed(false),
+      mRestoreXF86Lock(false),
+      mForbidden(false),
+      mAutoLogoutTimerId(0)
+{
+    setObjectName(QLatin1String( "save window" ));
+    setupSignals();
+
+    new LockProcessAdaptor(this);
+    QDBusConnection::sessionBus().registerService(QLatin1String( \
"org.kde.screenlocker" )); +    \
QDBusConnection::sessionBus().registerObject(QLatin1String( "/LockProcess" ), this); \
+ +    kapp->installX11EventFilter(this);
+
+    // Get root window size
+    XWindowAttributes rootAttr;
+    QX11Info info;
+    XGetWindowAttributes(QX11Info::display(), RootWindow(QX11Info::display(),
+                                                         info.screen()), &rootAttr);
+    kapp->desktop(); // make Qt set its event mask on the root window first
+    XSelectInput( QX11Info::display(), QX11Info::appRootWindow(),
+                  SubstructureNotifyMask | rootAttr.your_event_mask );
+#ifdef CHECK_XSELECTINPUT
+    check_xselectinput = true;
+#endif
+    setGeometry(0, 0, rootAttr.width, rootAttr.height);
+
+    // virtual root property
+    gXA_VROOT = XInternAtom (QX11Info::display(), "__SWM_VROOT", False);
+    gXA_SCREENSAVER_VERSION = XInternAtom (QX11Info::display(), \
"_SCREENSAVER_VERSION", False); +
+    connect(&mHackProc, SIGNAL(finished(int, QProcess::ExitStatus)),
+            SLOT(hackExited()));
+
+    mSuspendTimer.setSingleShot(true);
+    connect(&mSuspendTimer, SIGNAL(timeout()), SLOT(suspend()));
+
+    const QStringList dmopt =
+        QString::fromLatin1( ::getenv( "XDM_MANAGED" )).split(QLatin1Char(','), \
QString::SkipEmptyParts); +    for (QStringList::ConstIterator it = \
dmopt.constBegin(); it != dmopt.constEnd(); ++it) +        if \
((*it).startsWith(QLatin1String( "method=" ))) +            mMethod = (*it).mid(7);
+
+    configure();
+
+#ifdef HAVE_DPMS
+    if (mDPMSDepend) {
+        BOOL on;
+        CARD16 state;
+        DPMSInfo(QX11Info::display(), &state, &on);
+        if (on)
+        {
+            connect(&mCheckDPMS, SIGNAL(timeout()), SLOT(checkDPMSActive()));
+            // we can save CPU if we stop it as quickly as possible
+            // but we waste CPU if we check too often -> so take 10s
+            mCheckDPMS.start(10000);
+        }
+    }
+#endif
+
+    greetPlugin.library = 0;
+
+    mSuppressUnlock.setSingleShot(true);
+    connect(&mSuppressUnlock, SIGNAL(timeout()), SLOT(deactivatePlasma()));
+
+    // read the initial information about all toplevel windows
+    Window r, p;
+    Window* real;
+    unsigned nreal;
+    if( XQueryTree( x11Info().display(), x11Info().appRootWindow(), &r, &p, &real, \
&nreal ) +        && real != NULL ) {
+        KXErrorHandler err; // ignore X errors here
+        for( unsigned i = 0; i < nreal; ++i ) {
+            XWindowAttributes winAttr;
+            if (XGetWindowAttributes(QX11Info::display(), real[ i ], &winAttr)) {
+                WindowInfo info;
+                info.window = real[ i ];
+                info.viewable = ( winAttr.map_state == IsViewable );
+                windowInfo.append( info ); // ordered bottom to top
+            }
+        }
+        XFree( real );
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+// Destructor - usual cleanups.
+//
+LockProcess::~LockProcess()
+{
+    if (greetPlugin.library) {
+        if (greetPlugin.info->done)
+            greetPlugin.info->done();
+        greetPlugin.library->unload();
+    }
+}
+
+static int signal_pipe[2];
+
+static void sigterm_handler(int)
+{
+    char tmp = 'T';
+    ::write( signal_pipe[1], &tmp, 1);
+}
+
+static void sighup_handler(int)
+{
+    char tmp = 'H';
+    ::write( signal_pipe[1], &tmp, 1);
+}
+
+static void sigusr1_handler(int)
+{
+    char tmp = '1';
+    ::write(signal_pipe[1], &tmp, 1);
+}
+
+void LockProcess::timerEvent(QTimerEvent *ev)
+{
+    if (ev->timerId() == mAutoLogoutTimerId)
+    {
+        AutoLogout autologout(this);
+        execDialog(&autologout);
+    }
+}
+
+void LockProcess::setupSignals()
+{
+    struct sigaction act;
+    sigemptyset(&(act.sa_mask));
+    act.sa_flags = 0;
+    // ignore SIGINT
+    act.sa_handler=SIG_IGN;
+    sigaction(SIGINT, &act, 0L);
+    // ignore SIGQUIT
+    //act.sa_handler=SIG_IGN;
+    sigaction(SIGQUIT, &act, 0L);
+    // exit cleanly on SIGTERM
+    act.sa_handler= sigterm_handler;
+    sigaction(SIGTERM, &act, 0L);
+    // SIGHUP forces lock
+    act.sa_handler= sighup_handler;
+    sigaction(SIGHUP, &act, 0L);
+    // SIGUSR1 simulates user activity
+    act.sa_handler= sigusr1_handler;
+    sigaction(SIGUSR1, &act, 0L);
+
+    pipe(signal_pipe);
+    QSocketNotifier* notif = new QSocketNotifier(signal_pipe[0], \
QSocketNotifier::Read, this); +    connect( notif, SIGNAL(activated(int)), \
SLOT(signalPipeSignal())); +}
+
+
+void LockProcess::signalPipeSignal()
+{
+    char tmp;
+    ::read( signal_pipe[0], &tmp, 1);
+    if (tmp == 'T') {
+        quitSaver();
+    } else if (tmp == '1') {
+        // In case SimulateUserActivity (SIGUSR1) is called during the dead-time \
(mBusy == true). +        mInitialLock = true;
+        if (!mBusy && mDialogs.isEmpty()) {
+            mBusy = true;
+            quit();
+            mBusy = false;
+        }
+    } else if (tmp == 'H') {
+        if( !mLocked )
+            startLock();
+    }
+}
+
+//---------------------------------------------------------------------------
+bool LockProcess::lock(bool initial)
+{
+    if (startSaver()) {
+        // In case of a forced lock we don't react to events during
+        // the dead-time to give the screensaver some time to activate.
+        // That way we don't accidentally show the password dialog before
+        // the screensaver kicks in because the user moved the mouse after
+        // selecting "lock screen", that looks really untidy.
+        mBusy = true;
+        mInitialLock = initial;
+        if (startLock())
+        {
+            QTimer::singleShot(1000, this, SLOT(slotDeadTimePassed()));
+            return true;
+        }
+        stopSaver();
+        mBusy = false;
+    }
+    return false;
+}
+//---------------------------------------------------------------------------
+void LockProcess::slotDeadTimePassed()
+{
+    if (mInitialLock)
+        quit();
+    mBusy = false;
+}
+
+//---------------------------------------------------------------------------
+bool LockProcess::defaultSave()
+{
+    mLocked = false;
+    if (startSaver()) {
+        if (mLockGrace >= 0)
+            QTimer::singleShot(mLockGrace, this, SLOT(startLock()));
+        return true;
+    }
+    return false;
+}
+
+bool LockProcess::startSetup()
+{
+    mPlasmaEnabled = true; //force it on in case the user didn't click apply yet
+    mLocked = false;
+    mSetupMode = true;
+    return startSaver();
+    //plasma startup will handle the suppressunlock bit
+}
+//---------------------------------------------------------------------------
+bool LockProcess::dontLock()
+{
+    mLocked = false;
+    return startSaver();
+}
+
+//---------------------------------------------------------------------------
+void LockProcess::quitSaver()
+{
+    stopSaver();
+    qApp->quit();
+}
+
+//---------------------------------------------------------------------------
+//
+// Read and apply configuration.
+//
+void LockProcess::configure()
+{
+    // the configuration is stored in krunner's config file
+    if( KScreenSaverSettings::lock() ) {
+        mLockGrace = KScreenSaverSettings::lockGrace();
+        if (mLockGrace < 0)
+            mLockGrace = 0;
+        else if (mLockGrace > 300000)
+            mLockGrace = 300000; // 5 minutes, keep the value sane
+    } else {
+        mLockGrace = -1;
+    }
+
+    mAutoLogoutTimeout = KScreenSaverSettings::autoLogout() ?
+                         KScreenSaverSettings::autoLogoutTimeout() : 0;
+
+#ifdef HAVE_DPMS
+    mDPMSDepend = KScreenSaverSettings::suspendWhenInvisible();
+#endif
+
+    mPriority = KScreenSaverSettings::priority();
+    if (mPriority < 0) mPriority = 0;
+    if (mPriority > 19) mPriority = 19;
+
+    mSaver = KScreenSaverSettings::saver();
+    if (mSaver.isEmpty() || mUseBlankOnly) {
+        mSaver = QLatin1String( "kblank.desktop" );
+    }
+
+    readSaver();
+
+    mPlasmaEnabled = KScreenSaverSettings::plasmaEnabled();
+
+    mSuppressUnlockTimeout = qMax(0, KScreenSaverSettings::timeout() * 1000);
+    mSuppressUnlockTimeout = qMax(mSuppressUnlockTimeout, 30 * 1000); //min. 30 secs \
FIXME is this a good idea? +
+    mPlugins = KScreenSaverSettings::pluginsUnlock();
+    if (mPlugins.isEmpty()) {
+        mPlugins << QLatin1String( "classic" ) << QLatin1String( "generic" );
+    }
+    mPluginOptions = KScreenSaverSettings::pluginOptions();
+}
+
+//---------------------------------------------------------------------------
+//
+// Read the command line needed to run the screensaver given a .desktop file.
+//
+void LockProcess::readSaver()
+{
+    if (!mSaver.isEmpty())
+    {
+        QString entryName = mSaver;
+        if( entryName.endsWith( QLatin1String( ".desktop" ) ))
+            entryName = entryName.left( entryName.length() - 8 ); // strip it
+        const KService::List offers = KServiceTypeTrader::self()->query( \
QLatin1String( "ScreenSaver" ), +            QLatin1String( "DesktopEntryName == '" ) \
+ entryName.toLower() + QLatin1Char( '\'' ) ); +        if( offers.isEmpty() )
+        {
+            kDebug(1204) << "Cannot find screesaver: " << mSaver;
+            return;
+        }
+        const QString file = KStandardDirs::locate("services", \
offers.first()->entryPath()); +
+        const bool opengl = KAuthorized::authorizeKAction(QLatin1String( \
"opengl_screensavers" )); +        const bool manipulatescreen = \
KAuthorized::authorizeKAction(QLatin1String( "manipulatescreen_screensavers" )); +    \
KDesktopFile config( file ); +        KConfigGroup desktopGroup = \
config.desktopGroup(); +        foreach (const QString &type, \
desktopGroup.readEntry("X-KDE-Type").split(QLatin1Char(';'))) { +            if (type \
== QLatin1String("ManipulateScreen")) { +                if (!manipulatescreen) {
+                    kDebug(1204) << "Screensaver is type ManipulateScreen and \
ManipulateScreen is forbidden"; +                    mForbidden = true;
+                }
+            } else if (type == QLatin1String("OpenGL")) {
+                mOpenGLVisual = true;
+                if (!opengl) {
+                    kDebug(1204) << "Screensaver is type OpenGL and OpenGL is \
forbidden"; +                    mForbidden = true;
+                }
+            }
+        }
+
+        kDebug(1204) << "mForbidden: " << (mForbidden ? "true" : "false");
+
+        if (config.hasActionGroup(QLatin1String( "Root" )))
+        {
+            mSaverExec = config.actionGroup(QLatin1String( "Root" \
)).readPathEntry("Exec", QString()); +        }
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+// Create a window to draw our screen saver on.
+//
+void LockProcess::createSaverWindow()
+{
+    Visual* visual = CopyFromParent;
+    int depth = CopyFromParent;
+    XSetWindowAttributes attrs;
+    int flags = CWOverrideRedirect;
+#ifdef HAVE_GLXCHOOSEVISUAL
+// this code is (partially) duplicated in kdebase/workspace/kcontrol/screensaver
+    if( mOpenGLVisual )
+    {
+        static const int attribs[][ 15 ] =
+        {
+        #define R GLX_RED_SIZE
+        #define G GLX_GREEN_SIZE
+        #define B GLX_BLUE_SIZE
+            { GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, GLX_DOUBLEBUFFER, \
GLX_STENCIL_SIZE, 1, None }, +            { GLX_RGBA, R, 4, G, 4, B, 4, \
GLX_DEPTH_SIZE, 4, GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1, None }, +            { \
GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, GLX_DOUBLEBUFFER, None }, +            \
{ GLX_RGBA, R, 4, G, 4, B, 4, GLX_DEPTH_SIZE, 4, GLX_DOUBLEBUFFER, None }, +          \
{ GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, GLX_STENCIL_SIZE, 1, None }, +       \
{ GLX_RGBA, R, 4, G, 4, B, 4, GLX_DEPTH_SIZE, 4, GLX_STENCIL_SIZE, 1, None }, +       \
{ GLX_RGBA, R, 8, G, 8, B, 8, GLX_DEPTH_SIZE, 8, None }, +            { GLX_RGBA, R, \
4, G, 4, B, 4, GLX_DEPTH_SIZE, 4, None }, +            { GLX_RGBA, GLX_DEPTH_SIZE, 8, \
GLX_DOUBLEBUFFER, GLX_STENCIL_SIZE, 1, None }, +            { GLX_RGBA, \
GLX_DEPTH_SIZE, 8, GLX_DOUBLEBUFFER, None }, +            { GLX_RGBA, GLX_DEPTH_SIZE, \
8, GLX_STENCIL_SIZE, 1, None }, +            { GLX_RGBA, GLX_DEPTH_SIZE, 8, None }
+        #undef R
+        #undef G
+        #undef B
+        };
+        for( unsigned int i = 0;
+             i < sizeof( attribs ) / sizeof( attribs[ 0 ] );
+             ++i )
+        {
+            if( XVisualInfo* info = glXChooseVisual( x11Info().display(), \
x11Info().screen(), const_cast<int*>(attribs[ i ]) )) +            {
+                visual = info->visual;
+                depth = info->depth;
+                static Colormap colormap = 0;
+                if( colormap != 0 )
+                    XFreeColormap( x11Info().display(), colormap );
+                colormap = XCreateColormap( x11Info().display(), RootWindow( \
x11Info().display(), x11Info().screen()), visual, AllocNone ); +                \
attrs.colormap = colormap; +                flags |= CWColormap;
+                XFree( info );
+                break;
+            }
+        }
+    }
+#endif
+    attrs.override_redirect = 1;
+    hide();
+    Window w = XCreateWindow( x11Info().display(), RootWindow( x11Info().display(), \
x11Info().screen()), +        x(), y(), width(), height(), 0, depth, InputOutput, \
visual, flags, &attrs ); +
+    create( w, false, true );
+
+    // Some xscreensaver hacks check for this property
+    const char *version = "KDE 4.0";
+    XChangeProperty (QX11Info::display(), winId(),
+                     gXA_SCREENSAVER_VERSION, XA_STRING, 8, PropModeReplace,
+                     (unsigned char *) version, strlen(version));
+
+
+    XSetWindowAttributes attr;
+    attr.event_mask = KeyPressMask | ButtonPressMask | PointerMotionMask |
+                        VisibilityChangeMask | ExposureMask;
+    XChangeWindowAttributes(QX11Info::display(), winId(),
+                            CWEventMask, &attr);
+
+    // erase();
+
+    // set NoBackground so that the saver can capture the current
+    // screen state if necessary
+    setAttribute(Qt::WA_PaintOnScreen, true);
+    setAttribute(Qt::WA_NoSystemBackground, true);
+    setAttribute(Qt::WA_PaintOutsidePaintEvent, true); // for bitBlt in resume()
+
+    setCursor( Qt::BlankCursor );
+
+    kDebug(1204) << "Saver window Id: " << winId();
+}
+
+//---------------------------------------------------------------------------
+//
+// Hide the screensaver window
+//
+void LockProcess::hideSaverWindow()
+{
+  hide();
+  lower();
+  removeVRoot(winId());
+  XDeleteProperty(QX11Info::display(), winId(), gXA_SCREENSAVER_VERSION);
+  if ( gVRoot ) {
+      unsigned long vroot_data[1] = { gVRootData };
+      XChangeProperty(QX11Info::display(), gVRoot, gXA_VROOT, XA_WINDOW, 32,
+                      PropModeReplace, (unsigned char *)vroot_data, 1);
+      gVRoot = 0;
+  }
+  XSync(QX11Info::display(), False);
+}
+
+//---------------------------------------------------------------------------
+static int ignoreXError(Display *, XErrorEvent *)
+{
+    return 0;
+}
+
+//---------------------------------------------------------------------------
+//
+// Save the current virtual root window
+//
+void LockProcess::saveVRoot()
+{
+  Window rootReturn, parentReturn, *children;
+  unsigned int numChildren;
+  QX11Info info;
+  Window root = RootWindowOfScreen(ScreenOfDisplay(QX11Info::display(), \
info.screen())); +
+  gVRoot = 0;
+  gVRootData = 0;
+
+  int (*oldHandler)(Display *, XErrorEvent *);
+  oldHandler = XSetErrorHandler(ignoreXError);
+
+  if (XQueryTree(QX11Info::display(), root, &rootReturn, &parentReturn,
+      &children, &numChildren))
+  {
+    for (unsigned int i = 0; i < numChildren; i++)
+    {
+      Atom actual_type;
+      int actual_format;
+      unsigned long nitems, bytesafter;
+      unsigned char *newRoot = 0;
+
+      if ((XGetWindowProperty(QX11Info::display(), children[i], gXA_VROOT, 0, 1,
+          False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter,
+          &newRoot) == Success) && newRoot)
+      {
+        gVRoot = children[i];
+        Window *dummy = (Window*)newRoot;
+        gVRootData = *dummy;
+        XFree ((char*) newRoot);
+        break;
+      }
+    }
+    if (children)
+    {
+      XFree((char *)children);
+    }
+  }
+
+  XSetErrorHandler(oldHandler);
+}
+
+//---------------------------------------------------------------------------
+//
+// Set the virtual root property
+//
+void LockProcess::setVRoot(Window win, Window vr)
+{
+    if (gVRoot)
+        removeVRoot(gVRoot);
+
+        QX11Info info;
+    unsigned long rw = RootWindowOfScreen(ScreenOfDisplay(QX11Info::display(), \
info.screen())); +    unsigned long vroot_data[1] = { vr };
+
+    Window rootReturn, parentReturn, *children;
+    unsigned int numChildren;
+    Window top = win;
+    while (1) {
+        if (!XQueryTree(QX11Info::display(), top , &rootReturn, &parentReturn,
+                                 &children, &numChildren))
+            return;
+        if (children)
+            XFree((char *)children);
+        if (parentReturn == rw) {
+            break;
+        } else
+            top = parentReturn;
+    }
+
+    XChangeProperty(QX11Info::display(), top, gXA_VROOT, XA_WINDOW, 32,
+                     PropModeReplace, (unsigned char *)vroot_data, 1);
+}
+
+//---------------------------------------------------------------------------
+//
+// Remove the virtual root property
+//
+void LockProcess::removeVRoot(Window win)
+{
+    XDeleteProperty (QX11Info::display(), win, gXA_VROOT);
+}
+
+//---------------------------------------------------------------------------
+//
+// Grab the keyboard. Returns true on success
+//
+bool LockProcess::grabKeyboard()
+{
+    int rv = XGrabKeyboard( QX11Info::display(), QApplication::desktop()->winId(),
+        True, GrabModeAsync, GrabModeAsync, CurrentTime );
+
+    return (rv == GrabSuccess);
+}
+
+#define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \
+                   EnterWindowMask | LeaveWindowMask
+
+//---------------------------------------------------------------------------
+//
+// Grab the mouse.  Returns true on success
+//
+bool LockProcess::grabMouse()
+{
+    int rv = XGrabPointer( QX11Info::display(), QApplication::desktop()->winId(),
+            True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None,
+            QCursor(Qt::BlankCursor).handle(), CurrentTime );
+
+    return (rv == GrabSuccess);
+}
+
+//---------------------------------------------------------------------------
+//
+// Grab keyboard and mouse.  Returns true on success.
+//
+bool LockProcess::grabInput()
+{
+    XSync(QX11Info::display(), False);
+
+    if (!grabKeyboard())
+    {
+        sleep(1);
+        if (!grabKeyboard())
+        {
+            return false;
+        }
+    }
+
+    if (!grabMouse())
+    {
+        sleep(1);
+        if (!grabMouse())
+        {
+            XUngrabKeyboard(QX11Info::display(), CurrentTime);
+            return false;
+        }
+    }
+
+    lockXF86();
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+//
+// Release mouse an keyboard grab.
+//
+void LockProcess::ungrabInput()
+{
+    XUngrabKeyboard(QX11Info::display(), CurrentTime);
+    XUngrabPointer(QX11Info::display(), CurrentTime);
+    unlockXF86();
+}
+
+//---------------------------------------------------------------------------
+//
+// Start the screen saver.
+//
+bool LockProcess::startSaver()
+{
+    if (!child_saver && !grabInput())
+    {
+        kWarning(1204) << "LockProcess::startSaver() grabInput() failed!!!!" ;
+        return false;
+    }
+    mBusy = false;
+
+    saveVRoot();
+
+    if (mParent) {
+        QSocketNotifier *notifier = new QSocketNotifier(mParent, \
QSocketNotifier::Read, this); +        connect(notifier, SIGNAL( activated (int)), \
SLOT( quitSaver())); +    }
+    if (mAutoLogoutTimeout && !mSetupMode)
+        mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout * 1000); // in \
milliseconds +    createSaverWindow();
+    move(0, 0);
+    show();
+    setCursor( Qt::BlankCursor );
+
+    raise();
+    XSync(QX11Info::display(), False);
+
+    setVRoot( winId(), winId() );
+    startHack();
+    startPlasma();
+    KNotification::event( QLatin1String( "savingstarted" ) );
+    return true;
+}
+
+//---------------------------------------------------------------------------
+//
+// Stop the screen saver.
+//
+void LockProcess::stopSaver()
+{
+    kDebug(1204) << "LockProcess: stopping saver";
+    resume( true );
+    stopPlasma();
+    stopHack();
+    hideSaverWindow();
+    mVisibility = false;
+    if (!child_saver) {
+        if (mLocked) {
+            KDisplayManager().setLock( false );
+            mLocked = false;
+            KNotification *u = new KNotification( QLatin1String( "unlocked" ) );
+	    u->sendEvent();
+        }
+        ungrabInput();
+        const char *out = "GOAWAY!";
+        for (QList<int>::ConstIterator it = child_sockets.constBegin(); it != \
child_sockets.constEnd(); ++it) +            write(*it, out, sizeof(out));
+    }
+    KNotification *s = new KNotification( QLatin1String( "savingstopped" ) );
+    s->sendEvent();
+}
+
+// private static
+QVariant LockProcess::getConf(void *ctx, const char *key, const QVariant &dflt)
+{
+    LockProcess *that = (LockProcess *)ctx;
+    QString fkey = QLatin1String( key ) % QLatin1Char( '=' );
+    for (QStringList::ConstIterator it = that->mPluginOptions.constBegin();
+         it != that->mPluginOptions.constEnd(); ++it)
+        if ((*it).startsWith( fkey ))
+            return (*it).mid( fkey.length() );
+    return dflt;
+}
+
+void LockProcess::cantLock( const QString &txt)
+{
+    msgBox( 0, QMessageBox::Critical, i18n("Will not lock the session, as unlocking \
would be impossible:\n") + txt ); +}
+
+#if 0 // placeholders for later
+i18n("Cannot start <i>kcheckpass</i>.");
+i18n("<i>kcheckpass</i> is unable to operate. Possibly it is not setuid root.");
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Make the screen saver password protected.
+//
+bool LockProcess::startLock()
+{
+    if (loadGreetPlugin()) {
+        mLocked = true;
+        KDisplayManager().setLock(true);
+        lockPlasma();
+        KNotification::event( QLatin1String( "locked" ) );
+        return true;
+    }
+    return false;
+}
+
+bool LockProcess::loadGreetPlugin()
+{
+    if (greetPlugin.library) {
+        //we were locked once before, so all the plugin loading's done already
+        //FIXME should I be unloading the plugin on unlock instead?
+        return true;
+    }
+    for (QStringList::ConstIterator it = mPlugins.constBegin(); it != \
mPlugins.constEnd(); ++it) { +        GreeterPluginHandle plugin;
+        KLibrary *lib = new KLibrary( (*it)[0] == QLatin1Char( '/' ) ? *it : \
QLatin1String( "kgreet_" ) + *it ); +        if (lib->fileName().isEmpty()) {
+            kWarning(1204) << "GreeterPlugin " << *it << " does not exist" ;
+            delete lib;
+            continue;
+        }
+        if (!lib->load()) {
+            kWarning(1204) << "Cannot load GreeterPlugin " << *it << " (" << \
lib->fileName() << ")" ; +            delete lib;
+            continue;
+        }
+        plugin.library = lib;
+        plugin.info = (KGreeterPluginInfo *)lib->resolveSymbol( \
"kgreeterplugin_info" ); +        if (!plugin.info ) {
+            kWarning(1204) << "GreeterPlugin " << *it << " (" << lib->fileName() << \
") is no valid greet widget plugin" ; +            lib->unload();
+            delete lib;
+            continue;
+        }
+        if (plugin.info->method && !mMethod.isEmpty() && mMethod != QLatin1String(  \
plugin.info->method )) { +            kDebug(1204) << "GreeterPlugin " << *it << " (" \
<< lib->fileName() << ") serves " << plugin.info->method << ", not " << mMethod; +    \
lib->unload(); +            delete lib;
+            continue;
+        }
+        if (!plugin.info->init( mMethod, getConf, this )) {
+            kDebug(1204) << "GreeterPlugin " << *it << " (" << lib->fileName() << ") \
refuses to serve " << mMethod; +            lib->unload();
+            delete lib;
+            continue;
+        }
+        kDebug(1204) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", \
" << plugin.info->name << ") loaded"; +        greetPlugin = plugin;
+        return true;
+    }
+    cantLock( i18n("No appropriate greeter plugin configured.") );
+    return false;
+}
+
+//---------------------------------------------------------------------------
+//
+
+
+bool LockProcess::startHack()
+{
+    kDebug(1204) << "Starting hack:" << mSaverExec;
+
+    if (mSaverExec.isEmpty() || mForbidden)
+    {
+        hackExited();
+        return false;
+    }
+
+    QHash<QChar, QString> keyMap;
+    keyMap.insert(QLatin1Char( 'w' ), QString::number(winId()));
+    mHackProc << KShell::splitArgs(KMacroExpander::expandMacrosShellQuote(mSaverExec, \
keyMap)); +
+    mHackProc.start();
+    if (mHackProc.waitForStarted())
+    {
+#ifdef HAVE_SETPRIORITY
+        setpriority(PRIO_PROCESS, mHackProc.pid(), mPriority);
+#endif
+        return true;
+    }
+
+    hackExited();
+    return false;
+}
+
+//---------------------------------------------------------------------------
+//
+void LockProcess::stopHack()
+{
+    if (mHackProc.state() != QProcess::NotRunning)
+    {
+        mHackProc.terminate();
+        if (!mHackProc.waitForFinished(10000))
+        {
+            mHackProc.kill();
+        }
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+void LockProcess::hackExited()
+{
+    // Hack exited while we're supposed to be saving the screen.
+    // Make sure the saver window is black.
+    XSetWindowBackground(QX11Info::display(), winId(), BlackPixel( \
QX11Info::display(), QX11Info::appScreen())); +    XClearWindow(QX11Info::display(), \
winId()); +}
+
+bool LockProcess::startPlasma()
+{
+    if (!mPlasmaEnabled) {
+        return false;
+    }
+
+    if (mSetupMode) {
+        mSuppressUnlock.start(mSuppressUnlockTimeout);
+        XChangeActivePointerGrab(QX11Info::display(), GRABEVENTS,
+                                 QCursor(Qt::ArrowCursor).handle(), CurrentTime);
+    }
+
+    kDebug() << "looking for plasma-overlay";
+    if (!mPlasmaDBus) {
+        //try to get it, in case it's already running somehow
+        //mPlasmaDBus = new QDBusInterface(s_overlayServiceName, "/MainApplication", \
QString(), +        mPlasmaDBus = new \
org::kde::plasmaoverlay::App(s_overlayServiceName, QLatin1String( "/App" ), +         \
QDBusConnection::sessionBus(), this); +        //FIXME this might-already-be-running \
stuff seems really really Wrong. +    }
+
+    if (mPlasmaDBus->isValid()) {
+        kDebug() << "weird, plasma-overlay is already running";
+        mPlasmaDBus->call(QDBus::NoBlock, QLatin1String( "setup" ), mSetupMode);
+        return true;
+    }
+
+    kDebug () << "...not found" << "starting plasma-overlay";
+    delete mPlasmaDBus;
+    mPlasmaDBus = 0;
+
+    if (!mServiceWatcher) {
+        mServiceWatcher = new QDBusServiceWatcher(s_overlayServiceName, \
QDBusConnection::sessionBus(), +                                                   \
QDBusServiceWatcher::WatchForOwnerChange, this); +        connect(mServiceWatcher, \
SIGNAL(serviceOwnerChanged(QString,QString,QString)), +                this, \
SLOT(newService(QString,QString,QString))); +    }
+
+    KProcess *plasmaProc = new KProcess;
+    plasmaProc->setProgram(QLatin1String( "plasma-overlay" ));
+    if (mSetupMode) {
+        *plasmaProc << QLatin1String( "--setup" );
+    }
+
+    //make sure it goes away when it's done (and not before)
+    connect(plasmaProc, SIGNAL(finished(int,QProcess::ExitStatus)), plasmaProc, \
SLOT(deleteLater())); +
+    plasmaProc->start();
+    kDebug() << "process begun";
+
+    //plasma gets 15 seconds to load, or we assume it failed
+    QTimer::singleShot(15 * 1000, this, SLOT(checkPlasma()));
+    return true;
+}
+
+void LockProcess::checkPlasma()
+{
+    if (!mPlasmaEnabled) {
+        kDebug() << "You're Doing It Wrong!";
+        return;
+    }
+    if (mPlasmaDBus && mPlasmaDBus->isValid()) {
+        //hooray, looks like it started ok
+        kDebug() << "success!";
+        //...but just in case, make sure we're not waiting on it
+        mSetupMode = false;
+        return;
+    }
+
+    kDebug() << "ohnoes. plasma = teh fail.";
+    disablePlasma();
+}
+
+bool LockProcess::isPlasmaValid()
+{
+    //FIXME I'm assuming that if it's valid, calls will succeed. so if that's not \
the case we'll +    //need to change things so that plasma's disabled properly if it \
fails +    //damn. isValid is not quite enough. a call may still fail, and then we \
need to bail. +    if (!(mPlasmaEnabled && mPlasmaDBus)) {
+        return false; //no plasma, at least not yet
+    }
+    if (mPlasmaDBus->isValid()) {
+        return true;
+    }
+    //oh crap, it ran away on us.
+    disablePlasma();
+    return false;
+}
+
+void LockProcess::disablePlasma()
+{
+    kDebug();
+    mPlasmaEnabled = false;
+    mSetupMode = false;
+    mSuppressUnlock.stop(); //FIXME we might need to start the lock timer ala \
deactivatePlasma() +    //actually we could be lazy and just call deactivatePlasma() \
TODO check that this'll really work +    delete mPlasmaDBus;
+    mPlasmaDBus=0;
+}
+
+void LockProcess::stopPlasma()
+{
+    if (mPlasmaDBus && mPlasmaDBus->isValid()) {
+        mPlasmaDBus->call(QDBus::NoBlock, QLatin1String( "quit" ));
+    } else {
+        kDebug() << "cannot stop plasma-overlay";
+    }
+}
+
+void LockProcess::newService(QString name, QString oldOwner, QString newOwner)
+{
+    Q_UNUSED(name);
+    Q_UNUSED(oldOwner);
+
+    if (mPlasmaDBus) {
+        if (newOwner.isEmpty()) {
+            kDebug() << "plasma ran away?";
+            disablePlasma();
+        } else {
+            kDebug() << "I'm confused!!";
+        }
+        return;
+    }
+
+    kDebug() << "plasma! yaay!";
+    mPlasmaDBus = new org::kde::plasmaoverlay::App(s_overlayServiceName, \
QLatin1String( "/App" ), QDBusConnection::sessionBus(), this); +
+    //XXX this isn't actually used any more iirc
+    connect(mPlasmaDBus, SIGNAL(hidden()), SLOT(unSuppressUnlock()));
+
+    if (!mDialogs.isEmpty()) {
+        //whoops, activation probably failed earlier
+        mPlasmaDBus->call(QDBus::NoBlock, QLatin1String( "setActive" ), true);
+    }
+}
+
+void LockProcess::deactivatePlasma()
+{
+    if (isPlasmaValid()) {
+        mPlasmaDBus->call(QDBus::NoBlock, QLatin1String( "setActive" ), false);
+    }
+    if (!mLocked && mLockGrace >=0) {
+        QTimer::singleShot(mLockGrace, this, SLOT(startLock())); //this is only ok \
because any activity will quit +    }
+}
+
+void LockProcess::lockPlasma()
+{
+    if (isPlasmaValid()) {
+        mPlasmaDBus->call(QDBus::NoBlock, QLatin1String( "lock" ));
+    }
+}
+
+void LockProcess::unSuppressUnlock()
+{
+    //note: suppressing unlock also now means suppressing quit-on-activity
+    //maybe some var renaming is in order.
+    mSuppressUnlock.stop();
+}
+
+void LockProcess::quit()
+{
+    mSuppressUnlock.stop();
+    if (!mLocked || checkPass()) {
+        quitSaver();
+    }
+}
+
+void LockProcess::suspend()
+{
+    if( !mSuspended && mHackProc.state() == QProcess::Running )
+    {
+        ::kill(mHackProc.pid(), SIGSTOP);
+        // We actually want to wait for the stopped hack's X commands
+        // having been handled, but that would require a custom
+        // protocol which would cause the hack to call XSync() and
+        // freeze itself. So just go to sleep and hope that the X
+        // server will have enough time ...
+        usleep(100000);
+        mSavedScreen = QPixmap::grabWindow( winId());
+        mSnapshotTimer.setSingleShot(true);
+        mSnapshotTimer.start(1000);
+    }
+    mSuspended = true;
+}
+
+void LockProcess::resume( bool force )
+{
+    if( !force && (!mDialogs.isEmpty() || !mVisibility ))
+        return; // no resuming with dialog visible or when not visible
+    if( mSuspended && mHackProc.state() == QProcess::Running )
+    {
+        QPainter p( this );
+        if (!mSavedScreen.isNull())
+            p.drawPixmap( 0, 0, mSavedScreen );
+        else
+            p.fillRect( rect(), Qt::black );
+        p.end();
+        QApplication::syncX();
+        mSavedScreen = QPixmap();
+        ::kill(mHackProc.pid(), SIGCONT);
+    }
+    mSuspended = false;
+}
+
+//---------------------------------------------------------------------------
+//
+// Show the password dialog
+// This is called only in the master process
+//
+bool LockProcess::checkPass()
+{
+    if (isPlasmaValid()) {
+        mPlasmaDBus->call(QDBus::NoBlock, QLatin1String( "setActive" ), true);
+    }
+
+    PasswordDlg passDlg( this, &greetPlugin);
+    const int ret = execDialog( &passDlg );
+
+    if (isPlasmaValid()) {
+        if (ret == QDialog::Rejected) {
+            mSuppressUnlock.start(mSuppressUnlockTimeout);
+        } else if (ret == TIMEOUT_CODE) {
+            mPlasmaDBus->call(QDBus::NoBlock, QLatin1String( "setActive" ), false);
+        }
+    }
+
+    XWindowAttributes rootAttr;
+    XGetWindowAttributes(QX11Info::display(), QX11Info::appRootWindow(), &rootAttr);
+    if(( rootAttr.your_event_mask & SubstructureNotifyMask ) == 0 )
+    {
+        kWarning() << "ERROR: Something removed SubstructureNotifyMask from the root \
window!!!" ; +        XSelectInput( QX11Info::display(), QX11Info::appRootWindow(),
+            SubstructureNotifyMask | rootAttr.your_event_mask );
+    }
+
+    return ret == QDialog::Accepted;
+}
+
+bool LockProcess::checkPass(const QString &reason)
+{
+    if (! mLocked) {
+        //we were never locked... how can we unlock?!
+        //if anyone finds a use case for checking the password while unlocked, \
they'll have to load +        //the greetplugin n'stuff
+        return false;
+    }
+    PasswordDlg passDlg(this, &greetPlugin, reason);
+    const int ret = execDialog( &passDlg );
+//    kDebug() << ret;
+
+    //FIXME do we need to copy&paste that SubstructureNotifyMask code above?
+    if (ret == QDialog::Accepted) {
+        //we don't quit on a custom checkpass, but we do unlock
+        //so that the user doesn't have to type their password twice
+        mLocked = false;
+        KDisplayManager().setLock(false);
+        KNotification::event( QLatin1String( "unlocked" ) );
+        //FIXME while suppressUnlock *should* always be running, if it isn't
+        //(say if someone's doing things they shouldn't with dbus) then it won't get \
started by this +        //which means that a successful unlock will never re-lock
+        //in fact, the next bit of activity would lead to the screensaver quitting.
+        //possible solutions:
+        //-treat this function like activity: quit if already unlocked, ensure \
suppress is started +        //if we're locked and the dialog's rejected
+        //-return true if already unlocked, without doing anything, same as above if \
locked +        //-let it quit, and tell people not to do such silly things :P
+        return true;
+    }
+    return false;
+}
+
+static void fakeFocusIn( WId window )
+{
+    // We have keyboard grab, so this application will
+    // get keyboard events even without having focus.
+    // Fake FocusIn to make Qt realize it has the active
+    // window, so that it will correctly show cursor in the dialog.
+    XEvent ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.xfocus.display = QX11Info::display();
+    ev.xfocus.type = FocusIn;
+    ev.xfocus.window = window;
+    ev.xfocus.mode = NotifyNormal;
+    ev.xfocus.detail = NotifyAncestor;
+    XSendEvent( QX11Info::display(), window, False, NoEventMask, &ev );
+}
+
+bool LockProcess::eventFilter(QObject *o, QEvent *e)
+{
+    if (e->type() == QEvent::Resize) {
+        QWidget *w = static_cast<QWidget *>(o);
+        mFrames.value(w)->resize(w->size());
+    }
+    return false;
+}
+
+int LockProcess::execDialog( QDialog *dlg )
+{
+
+    QFrame *winFrame = new QFrame( dlg );
+    winFrame->setFrameStyle( QFrame::WinPanel | QFrame::Raised );
+    winFrame->setLineWidth( 2 );
+    winFrame->lower();
+    mFrames.insert(dlg, winFrame);
+    dlg->installEventFilter(this);
+
+    dlg->adjustSize();
+
+    int screen = Kephal::ScreenUtils::primaryScreenId();
+    if (Kephal::ScreenUtils::numScreens() > 1) {
+        screen = Kephal::ScreenUtils::screenId(QCursor::pos());
+    }
+
+    const QRect screenRect = Kephal::ScreenUtils::screenGeometry(screen);
+    QRect rect = dlg->geometry();
+    rect.moveCenter(screenRect.center());
+    dlg->move(rect.topLeft());
+
+    if (mDialogs.isEmpty())
+    {
+        if (mAutoLogoutTimerId)
+            killTimer(mAutoLogoutTimerId);
+        suspend();
+        XChangeActivePointerGrab( QX11Info::display(), GRABEVENTS,
+                QCursor(Qt::ArrowCursor).handle(), CurrentTime);
+    }
+    mDialogs.prepend( dlg );
+    fakeFocusIn( dlg->winId());
+    const int rt = dlg->exec();
+    const int pos = mDialogs.indexOf( dlg );
+    if (pos != -1)
+        mDialogs.remove( pos );
+    if( mDialogs.isEmpty() ) {
+        resume( false );
+        if (mAutoLogoutTimerId)
+            mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout * 1000);
+    }
+    updateFocus();
+
+    dlg->removeEventFilter(this);
+    mFrames.remove(dlg);
+
+    return rt;
+}
+
+void LockProcess::updateFocus()
+{
+    if (mDialogs.isEmpty()) {
+        if (mForeignInputWindows.isEmpty()) {
+            XChangeActivePointerGrab( QX11Info::display(), GRABEVENTS,
+                    QCursor(Qt::BlankCursor).handle(), CurrentTime);
+        } else {
+            fakeFocusIn(mForeignInputWindows.first());
+        }
+    } else {
+        fakeFocusIn(mDialogs.first()->winId());
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+// X11 Event.
+//
+bool LockProcess::x11Event(XEvent *event)
+{
+    if (mEventRecursed)
+        return false;
+
+    bool ret = false;
+    switch (event->type)
+    {
+        case ButtonPress:
+            if (!mDialogs.isEmpty() && event->xbutton.window == event->xbutton.root) \
{ +                //kDebug() << "close" << mDialogs.first()->effectiveWinId();
+                KDialog *dlg = qobject_cast<KDialog*>(mDialogs.first());
+                if (dlg) {
+                    //kDebug() << "casting success";
+                    dlg->reject();
+                }
+                break;
+            }
+        case KeyPress:
+        case MotionNotify:
+            if (mBusy || !mDialogs.isEmpty()) {
+                //kDebug() << "busy";
+                //FIXME shouldn't we be resetting some timers?
+                break;
+            }
+            mBusy = true;
+            //something happened. do we quit, ask for a password or forward it to \
plasma? +            //if we're supposed to be forwarding, we check that there's \
actually a plasma window up +            //so that the user isn't trapped if plasma \
crashes or is slow to load. +            //however, if plasma started in setup mode, \
we don't want to let anything happen until +            //it has a chance to load.
+            //note: mSetupMode should end when we either get a winid or hit the \
checkPlasma timeout +            if (mSuppressUnlock.isActive() && (mSetupMode || \
!mForeignInputWindows.isEmpty())) { +                mSuppressUnlock.start(); //help, \
help, I'm being suppressed! +                if (mAutoLogoutTimerId) {
+                    killTimer(mAutoLogoutTimerId);
+                    mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout * 1000);
+                }
+            } else if (!mLocked) {
+                quitSaver();
+                mBusy = false;
+                return true; //it's better not to forward any input while quitting, \
right? +            } else {
+                if (event->type == KeyPress) {
+                    // Bounce the keypress to the dialog
+                    QByteArray chars;
+                    chars.resize(513);
+                    KeySym keysym;
+                    XLookupString(&event->xkey, chars.data(), chars.size(), &keysym, \
0); +                    switch (keysym) {
+                    // These would cause immediate failure
+                    case XK_Escape:
+                    case XK_Return:
+                    case XK_KP_Enter:
+                    // These just make no sense
+                    case XK_Tab:
+                    case XK_space:
+                        break;
+                    default:
+                        mEventQueue.enqueue(*event);
+                    }
+                }
+                if (checkPass()) {
+                    quitSaver();
+                    mBusy = false;
+                    return true; //it's better not to forward any input while \
quitting, right? +                }
+            }
+            mBusy = false;
+            ret = true;
+            break;
+
+        case VisibilityNotify:
+            if( event->xvisibility.window == winId())
+            {  // mVisibility == false means the screensaver is not visible at all
+               // e.g. when switched to text console
+               // ...or when plasma's over it non-compositely?
+               // hey, this gives me free "suspend saver when plasma obscures it"
+                mVisibility = !(event->xvisibility.state == \
VisibilityFullyObscured); +                if (!mVisibility) {
+                    mSuspendTimer.start(2000);
+                    kDebug(1204) << "fully obscured";
+                } else {
+                    kDebug(1204) << "not fully obscured";
+                    mSuspendTimer.stop();
+                    resume( false );
+                }
+                if (mForeignWindows.isEmpty() && event->xvisibility.state != \
VisibilityUnobscured) { +                    kDebug(1204) << "no plasma; saver \
obscured"; +                    stayOnTop();
+                }
+            } else if (!mForeignWindows.isEmpty() && event->xvisibility.window == \
mForeignWindows.last() && +                    event->xvisibility.state != \
VisibilityUnobscured) { +                //FIXME now that we have several plasma \
winids this doesn't feel valid +                //but I don't know what to do about \
it! +                kDebug(1204) << "plasma obscured!";
+                stayOnTop();
+            }
+            break;
+
+        case ConfigureNotify: // from SubstructureNotifyMask on the root window
+            if(event->xconfigure.event == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event->xconfigure.window );
+                if( index >= 0 ) {
+                    int index2 = event->xconfigure.above ? findWindowInfo( \
event->xconfigure.above ) : 0; +                    if( index2 < 0 )
+                        kDebug(1204) << "Unknown above for ConfigureNotify";
+                    else { // move just above the other window
+                        if( index2 < index )
+                            ++index2;
+                        windowInfo.move( index, index2 );
+                    }
+                } else
+                    kDebug(1204) << "Unknown toplevel for ConfigureNotify";
+                //kDebug() << "ConfigureNotify:";
+                //the stacking order changed, so let's change the stacking order \
again to what we want +                stayOnTop();
+            }
+            break;
+        case MapNotify: // from SubstructureNotifyMask on the root window
+            if( event->xmap.event == QX11Info::appRootWindow()) {
+                kDebug(1204) << "MapNotify:" << event->xmap.window;
+                if (!mDialogs.isEmpty() && mDialogs.first()->winId() == \
event->xmap.window) +                    mVisibleDialogs.append(event->xmap.window);
+                int index = findWindowInfo( event->xmap.window );
+                if( index >= 0 )
+                    windowInfo[ index ].viewable = true;
+                else
+                    kDebug(1204) << "Unknown toplevel for MapNotify";
+                KXErrorHandler err; // ignore X errors here
+                WindowType type = windowType(event->xmap.window);
+                if (type != IgnoreWindow) {
+                    if (mForeignWindows.contains(event->xmap.window)) {
+                        kDebug(1204) << "uhoh! duplicate!";
+                    } else {
+                        //ordered youngest-on-top
+                        mForeignWindows.prepend(event->xmap.window);
+                    }
+                    if (type & InputWindow) {
+                        kDebug(1204) << "input window";
+                        if (mForeignInputWindows.contains(event->xmap.window)) {
+                            kDebug(1204) << "uhoh! duplicate again"; //never happens
+                        } else {
+                            //ordered youngest-on-top
+                            mForeignInputWindows.prepend(event->xmap.window);
+                            fakeFocusIn(event->xmap.window);
+                        }
+                        mSetupMode = false; //no more waiting for plasma
+                    }
+                }
+                stayOnTop();
+            }
+            break;
+        case UnmapNotify:
+            if (event->xunmap.event == QX11Info::appRootWindow()) {
+                kDebug(1204) << "UnmapNotify:" << event->xunmap.window;
+                int index = findWindowInfo( event->xunmap.window );
+                if( index >= 0 )
+                    windowInfo[ index ].viewable = false;
+                else
+                    kDebug(1204) << "Unknown toplevel for MapNotify";
+                mVisibleDialogs.removeAll(event->xunmap.window);
+                mForeignWindows.removeAll(event->xunmap.window);
+                if (mForeignInputWindows.removeAll(event->xunmap.window)) {
+                    updateFocus();
+                }
+            }
+            break;
+        case CreateNotify:
+            if (event->xcreatewindow.parent == QX11Info::appRootWindow()) {
+                kDebug(1204) << "CreateNotify:" << event->xcreatewindow.window;
+                int index = findWindowInfo( event->xcreatewindow.window );
+                if( index >= 0 )
+                    kDebug(1204) << "Already existing toplevel for CreateNotify";
+                else {
+                    WindowInfo info;
+                    info.window = event->xcreatewindow.window;
+                    info.viewable = false;
+                    windowInfo.append( info );
+                }
+            }
+            break;
+        case DestroyNotify:
+            if (event->xdestroywindow.event == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event->xdestroywindow.window );
+                if( index >= 0 )
+                    windowInfo.removeAt( index );
+                else
+                    kDebug(1204) << "Unknown toplevel for DestroyNotify";
+            }
+            break;
+        case ReparentNotify:
+            if (event->xreparent.event == QX11Info::appRootWindow() && \
event->xreparent.parent != QX11Info::appRootWindow()) { +                int index = \
findWindowInfo( event->xreparent.window ); +                if( index >= 0 )
+                    windowInfo.removeAt( index );
+                else
+                    kDebug(1204) << "Unknown toplevel for ReparentNotify away";
+            } else if (event->xreparent.parent == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event->xreparent.window );
+                if( index >= 0 )
+                    kDebug(1204) << "Already existing toplevel for ReparentNotify";
+                else {
+                    WindowInfo info;
+                    info.window = event->xreparent.window;
+                    info.viewable = false;
+                    windowInfo.append( info );
+                }
+            }
+            break;
+        case CirculateNotify:
+            if (event->xcirculate.event == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event->xcirculate.window );
+                if( index >= 0 ) {
+                    windowInfo.move( index, event->xcirculate.place == PlaceOnTop ? \
windowInfo.size() - 1 : 0 ); +                } else
+                    kDebug(1204) << "Unknown toplevel for CirculateNotify";
+            }
+            break;
+    }
+
+    // We have grab with the grab window being the root window.
+    // This results in key events being sent to the root window,
+    // but they should be sent to the dialog if it's visible.
+    // It could be solved by setFocus() call, but that would mess
+    // the focus after this process exits.
+    // Qt seems to be quite hard to persuade to redirect the event,
+    // so let's simply dupe it with correct destination window,
+    // and ignore the original one.
+    if (!mDialogs.isEmpty()) {
+        if (event->type == KeyPress || event->type == KeyRelease) {
+            mEventQueue.enqueue(*event);
+            ret = true;
+        }
+        if (!mVisibleDialogs.isEmpty())
+            while (!mEventQueue.isEmpty()) {
+                //kDebug() << "forward to dialog";
+                XEvent ev2 = mEventQueue.dequeue();
+                ev2.xkey.window = ev2.xkey.subwindow = mVisibleDialogs.last();
+                mEventRecursed = true;
+                qApp->x11ProcessEvent( &ev2 );
+                mEventRecursed = false;
+            }
+    } else {
+        mEventQueue.clear();
+        if (!mForeignInputWindows.isEmpty()) {
+            //when there are no dialogs, forward some events to plasma
+            switch (event->type) {
+            case KeyPress:
+            case KeyRelease:
+            case ButtonPress:
+            case ButtonRelease:
+            case MotionNotify: {
+                //kDebug() << "forward to plasma";
+                XEvent ev2 = *event;
+                Window root_return;
+                int x_return, y_return;
+                unsigned int width_return, height_return, border_width_return, \
depth_return; +                WId targetWindow = 0;
+                //kDebug() << "root is" << winId();
+                //kDebug() << "search window under pointer with" << \
mForeignInputWindows.size() << "windows"; +                KXErrorHandler err; // \
ignore X errors +                foreach(WId window, mForeignInputWindows)
+                {
+                    if( XGetGeometry(QX11Info::display(), window, &root_return,
+                                &x_return, &y_return,
+                                &width_return, &height_return,
+                                &border_width_return, &depth_return)
+                        &&
+                        (event->xkey.x>=x_return && \
event->xkey.x<=x_return+(int)width_return) +                        &&
+                        (event->xkey.y>=y_return && \
event->xkey.y<=y_return+(int)height_return) ) +                    {
+                        //kDebug() << "found window" << window;
+                        targetWindow = window;
+                        ev2.xkey.window = ev2.xkey.subwindow = targetWindow;
+                        ev2.xkey.x = event->xkey.x - x_return;
+                        ev2.xkey.y = event->xkey.y - y_return;
+                        break;
+                    }
+                }
+                XSendEvent(QX11Info::display(), targetWindow, False, NoEventMask, \
&ev2); +                ret = true;
+                break; }
+            default:
+                break;
+            }
+        }
+    }
+
+    return ret;
+}
+
+LockProcess::WindowType LockProcess::windowType(WId id)
+{
+    Atom tag = XInternAtom(QX11Info::display(), "_KDE_SCREENSAVER_OVERRIDE", False);
+    Atom actualType;
+    int actualFormat;
+    unsigned long nitems, remaining;
+    unsigned char *data = 0;
+    Display *display = QX11Info::display();
+
+    int result = XGetWindowProperty(display, id, tag, 0, 1, False, tag, &actualType,
+            &actualFormat, &nitems, &remaining, &data);
+
+    //kDebug() << (result == Success) << (actualType == tag);
+    WindowType type = IgnoreWindow;
+    if (result == Success && actualType == tag) {
+        if (nitems != 1 || actualFormat != 8) {
+            kDebug(1204) << "malformed property";
+        } else {
+            kDebug(1204) << "i can haz plasma window?" << data[0];
+            switch (data[0]) {
+                case 0: //FIXME magic numbers
+                    type = SimpleWindow;
+                    break;
+                case 1:
+                    type = InputWindow;
+                    break;
+                case 2:
+                    type = DefaultWindow;
+                    break;
+            }
+        }
+    }
+    if (data) {
+        XFree(data);
+    }
+    return type;
+}
+
+void LockProcess::stayOnTop()
+{
+    // this restacking is written in a way so that
+    // if the stacking positions actually don't change,
+    // all restacking operations will be no-op,
+    // and no ConfigureNotify will be generated,
+    // thus avoiding possible infinite loops
+    QVector< Window > stack( mDialogs.count() + mForeignWindows.count() + 1 );
+    int count = 0;
+    // dialogs first
+    foreach( QWidget* w, mDialogs )
+        stack[ count++ ] = w->winId();
+    // now the plasma stuff below the dialogs
+    foreach( WId w, mForeignWindows )
+        stack[ count++ ] = w;
+    // finally, the saver window
+    stack[ count++ ] = winId();
+    // We actually have to check the current stacking order. When an \
override-redirect +    // window is shown or raised, it can get above the screensaver \
window and there's not +    // much to do to prevent it (only the compositing manager \
can prevent that). This +    // is detected by the screenlocker and handled here, but \
the contents of the window +    // may remain visible, since some screensavers don't \
react to Expose events and +    // don't repaint as necessary. Therefore, if a window \
is detected above any of the windows +    // related to screenlocking, I don't see \
any better possibility than to completely +    // erase the screenlocker window.
+    // It is important to first detect, then restack and then erase.
+    // Another catch here is that only viewable windows matter, but checking here \
whether +    // a window is viewable is a race condition, since a window may map, \
paint and unmap +    // before we reach this point, thus making this code fail to \
detect the need to do +    // a repaint. Therefore we track all relevant X events \
about mapping state of toplevel +    // windows (which ensures proper ordering) and \
here just consult the information. +    bool needs_erase = false;
+    bool found_ours = false;
+    foreach( const WindowInfo& info, windowInfo ) {
+        if( stack.contains( info.window )) {
+            found_ours = true;
+        } else if( found_ours && info.viewable ) {
+            kDebug(1204) << "found foreign window above screensaver";
+            needs_erase = true;
+            break;
+        }
+    }
+    // do the actual restacking if needed
+    XRaiseWindow( x11Info().display(), stack[ 0 ] );
+    if( count > 1 )
+        XRestackWindows( x11Info().display(), stack.data(), count );
+    if( needs_erase ) {
+        // if the snapshot was taken recently it is possible that the rogue
+        // window was snapshotted at well.
+        if (mSnapshotTimer.isActive())
+            mSavedScreen = QPixmap();
+        QPainter p( this );
+        if (!mSavedScreen.isNull())
+            p.drawPixmap( 0, 0, mSavedScreen );
+        else
+            p.fillRect( rect(), Qt::black );
+        p.end();
+        QApplication::syncX();
+    }
+}
+
+void LockProcess::checkDPMSActive()
+{
+#ifdef HAVE_DPMS
+    BOOL on;
+    CARD16 state;
+    DPMSInfo(QX11Info::display(), &state, &on);
+    //kDebug() << "checkDPMSActive " << on << " " << state;
+    if (state == DPMSModeStandby || state == DPMSModeSuspend || state == \
DPMSModeOff) +        suspend();
+    else
+        resume( false );
+#endif
+}
+
+#if defined(HAVE_XF86MISC) && defined(HAVE_XF86MISCSETGRABKEYSSTATE)
+// see http://cvsweb.xfree86.org/cvsweb/xc/programs/Xserver/hw/xfree86/common/xf86Events.c#rev3.113
 +// This allows enabling the "Allow{Deactivate/Closedown}Grabs" options in \
XF86Config, +// and kscreenlocker will still lock the session.
+static enum { Unknown, Yes, No } can_do_xf86_lock = Unknown;
+void LockProcess::lockXF86()
+{
+    if( can_do_xf86_lock == Unknown )
+    {
+        int major, minor, dummy;
+        if( XF86MiscQueryExtension( QX11Info::display(), &dummy, &dummy )
+            && XF86MiscQueryVersion( QX11Info::display(), &major, &minor )
+            && (major > 0 || minor >= 5) )
+            can_do_xf86_lock = Yes;
+        else
+            can_do_xf86_lock = No;
+    }
+    if( can_do_xf86_lock != Yes )
+        return;
+    if( mRestoreXF86Lock )
+        return;
+    if( XF86MiscSetGrabKeysState( QX11Info::display(), False ) != \
MiscExtGrabStateSuccess ) +        return;
+    // success
+    mRestoreXF86Lock = true;
+}
+
+void LockProcess::unlockXF86()
+{
+    if( can_do_xf86_lock != Yes )
+        return;
+    if( !mRestoreXF86Lock )
+        return;
+    XF86MiscSetGrabKeysState( QX11Info::display(), True );
+    mRestoreXF86Lock = false;
+}
+#else
+void LockProcess::lockXF86()
+{
+}
+
+void LockProcess::unlockXF86()
+{
+}
+#endif
+
+void LockProcess::msgBox( QWidget *parent, QMessageBox::Icon type, const QString \
&txt ) +{
+    QDialog box( parent, Qt::X11BypassWindowManagerHint );
+
+    QLabel *label1 = new QLabel( &box );
+    label1->setPixmap( QMessageBox::standardIcon( type ) );
+    QLabel *label2 = new QLabel( txt, &box );
+    KPushButton *button = new KPushButton( KStandardGuiItem::ok(), &box );
+    button->setDefault( true );
+    button->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, \
QSizePolicy::Preferred ) ); +    connect( button, SIGNAL( clicked() ), &box, SLOT( \
accept() ) ); +
+    QGridLayout *grid = new QGridLayout( &box );
+    grid->setSpacing( 10 );
+    grid->addWidget( label1, 0, 0, Qt::AlignCenter );
+    grid->addWidget( label2, 0, 1, Qt::AlignCenter );
+    grid->addWidget( button, 1, 0, 1, 2, Qt::AlignCenter );
+
+    execDialog( &box );
+}
+
+int LockProcess::findWindowInfo( Window w )
+{
+    for( int i = 0;
+         i < windowInfo.size();
+         ++i )
+        if( windowInfo[ i ].window == w )
+            return i;
+    return -1;
+}
+
+#include "lockprocess.moc"
diff --git a/kwin/screenlocker/lock/lockprocess.h \
b/kwin/screenlocker/lock/lockprocess.h new file mode 100644
index 0000000..8b6d9a8
--- /dev/null
+++ b/kwin/screenlocker/lock/lockprocess.h
@@ -0,0 +1,238 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+// Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
+// Copyright 2008 Chani Armitage <chanika@gmail.com>
+//
+
+#ifndef LOCKPROCESS_H
+#define LOCKPROCESS_H
+
+#include <KProcess>
+
+#include <QWidget>
+#include <QTimer>
+#include <QStack>
+#include <QList>
+#include <QHash>
+#include <QMessageBox>
+#include <QPixmap>
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+#include "plasmaapp_interface.h"
+
+class KLibrary;
+
+struct KGreeterPluginInfo;
+
+struct GreeterPluginHandle {
+    KLibrary *library;
+    KGreeterPluginInfo *info;
+};
+
+const int TIMEOUT_CODE = 2; //from PasswordDlg
+
+class QDBusServiceWatcher;
+
+//===========================================================================
+//
+// Screen saver handling process.  Handles screensaver window,
+// starting screensaver hacks, and password entry.
+//
+class LockProcess
+    : public QWidget
+{
+    Q_OBJECT
+    Q_CLASSINFO("D-Bus Interface", "org.kde.screenlocker.LockProcess")
+public:
+    explicit LockProcess(bool child_saver = false, bool useBlankOnly = false);
+    ~LockProcess();
+
+    /**
+     * start the screensaver locked
+     */
+    bool lock(bool initial = false);
+
+    /**
+     * start the screensaver unlocked
+     */
+    bool defaultSave();
+
+    /**
+     * start the screensaver in plasma setup mode
+     * if plasma is disabled this just acts like defaultSave
+     */
+    bool startSetup();
+
+    /**
+     * start the screensaver unlocked, and *never* automatically lock it
+     */
+    bool dontLock();
+
+    void setChildren(QList<int> children) { child_sockets = children; }
+    void setParent(int fd) { mParent = fd; }
+
+    void msgBox( QWidget *parent, QMessageBox::Icon type, const QString &txt );
+    int execDialog( QDialog* dlg );
+
+public Q_SLOTS:
+    void quitSaver();
+    //dbus methods
+    /**
+     * bring up the password dialog with @param reason displayed instead of the \
usual "this session +     * is locked" message.
+     * @return true if the password was entered correctly
+     * if this returns true, it will also unlock the screensaver without quitting.
+     * it will re-lock after the lock timeout in the settings
+     */
+    Q_SCRIPTABLE bool checkPass(const QString &reason);
+    /**
+     * this will unlock and quit the screensaver, asking for a password first if \
necessary +     */
+    Q_SCRIPTABLE void quit();
+    /**
+     * immediately lock the screen; it will now require a password to unlock.
+     */
+    Q_SCRIPTABLE bool startLock();
+
+protected:
+    virtual bool x11Event(XEvent *);
+    virtual void timerEvent(QTimerEvent *);
+    virtual bool eventFilter(QObject *o, QEvent *e);
+
+private Q_SLOTS:
+    void hackExited();
+    void signalPipeSignal();
+    void suspend();
+    void checkDPMSActive();
+    void slotDeadTimePassed();
+    /**
+     * check that plasma started properly (used for timeout)
+     * and disable it if it failed
+     */
+    void checkPlasma();
+    /**
+     * a new dbus service has come in
+     */
+    void newService(QString name, QString oldOwner, QString newOwner);
+    /**
+     * tell plasma we're in idle mode
+     */
+    void deactivatePlasma();
+    void lockPlasma();
+    /**
+     * immediately un-suppress the password dialog
+     * FIXME need a better name
+     */
+    void unSuppressUnlock();
+
+private:
+    void configure();
+    void readSaver();
+    void createSaverWindow();
+    void hideSaverWindow();
+    void saveVRoot();
+    void setVRoot(Window win, Window rw);
+    void removeVRoot(Window win);
+    bool grabKeyboard();
+    bool grabMouse();
+    bool grabInput();
+    void ungrabInput();
+    void cantLock(const QString &reason);
+    bool startSaver();
+    void stopSaver();
+    bool startHack();
+    void stopHack();
+    bool startPlasma();
+    void stopPlasma();
+    void setupSignals();
+    /**
+     * exec the password dialog
+     * @return true iff the password was checked and is valid
+     */
+    bool checkPass();
+    /**
+     * returns true if plasma is up and the dbus interface is valid
+     */
+    bool isPlasmaValid();
+    /**
+     * give up on plasma, probably because it crashed.
+     * this does *not* tell plasma to quit. it just stops using it.
+     */
+    void disablePlasma();
+    /**
+     * give a fakefocusin to the right window
+     */
+    void updateFocus();
+    void stayOnTop();
+    int findWindowInfo( Window window ); // returns index in windowInfo or -1
+    void lockXF86();
+    void unlockXF86();
+    void resume( bool force );
+    enum WindowType { IgnoreWindow = 0 /** regular window to be left below the saver \
*/, +                      SimpleWindow = 1 /** simple popup that can't handle direct \
input */, +                      InputWindow = 2  /** annoying dialog that needs \
direct input */, +                      DefaultWindow = 6/** input window that's also \
the plasma view */ +    };
+    /**
+     * @return the type of window, based on its X property
+     */
+    WindowType windowType(WId id);
+
+    static QVariant getConf(void *ctx, const char *key, const QVariant &dflt);
+    bool loadGreetPlugin();
+
+    bool        mInitialLock;
+    bool        mLocked;
+    int         mLockGrace;
+    int         mPriority;
+    bool        mBusy;
+    KProcess    mHackProc;
+    org::kde::plasmaoverlay::App *mPlasmaDBus;
+    QDBusServiceWatcher *mServiceWatcher;
+    bool        mPlasmaEnabled;
+    bool        mSetupMode;
+    QString     mSaverExec;
+    QString     mSaver;
+    bool        mOpenGLVisual;
+    bool        child_saver;
+    QList<int> child_sockets;
+    int         mParent;
+    bool        mUseBlankOnly;
+    bool        mSuspended;
+    QTimer      mSuspendTimer;
+    bool        mVisibility;
+    bool        mDPMSDepend;
+    QTimer      mCheckDPMS;
+    QStack< QWidget* > mDialogs;
+    QHash< QWidget*, QWidget* > mFrames;
+    QList<WId>  mVisibleDialogs;
+    QQueue<XEvent> mEventQueue;
+    bool        mEventRecursed;
+    bool        mRestoreXF86Lock;
+    bool        mForbidden;
+    QStringList mPlugins, mPluginOptions;
+    QString     mMethod;
+    GreeterPluginHandle greetPlugin;
+    QPixmap     mSavedScreen;
+    QTimer      mSnapshotTimer;
+    int         mAutoLogoutTimerId;
+    int         mAutoLogoutTimeout;
+    QTimer      mSuppressUnlock;
+    int         mSuppressUnlockTimeout;
+    QList<WId>  mForeignWindows;
+    QList<WId>  mForeignInputWindows;
+    struct WindowInfo
+    {
+        Window window;
+        bool viewable;
+    };
+    QList<WindowInfo> windowInfo;
+};
+
+#endif
+
diff --git a/kwin/screenlocker/lock/main.cc b/kwin/screenlocker/lock/main.cc
new file mode 100644
index 0000000..7b41024
--- /dev/null
+++ b/kwin/screenlocker/lock/main.cc
@@ -0,0 +1,204 @@
+/* This file is part of the KDE project
+   Copyright (C) 1999 David Faure
+   Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#include "lockprocess.h"
+#include "main.h"
+#include "kscreensaversettings.h"
+
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <QtDBus/QtDBus>
+#include "kscreensaver_interface.h"
+
+#include <QList>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+bool MyApp::x11EventFilter( XEvent *ev )
+{
+    if (ev->type == XKeyPress || ev->type == ButtonPress)
+        emit activity();
+    else if (ev->type == MotionNotify) {
+        time_t tick = time( 0 );
+        if (tick != lastTick) {
+            lastTick = tick;
+            emit activity();
+        }
+    }
+    return KApplication::x11EventFilter( ev );
+}
+
+
+// -----------------------------------------------------------------------------
+
+int main( int argc, char **argv )
+{
+    KCmdLineArgs::init(argc, argv, "kscreenlocker", "krunner", ki18n("KDE Screen \
Locker"), +                       "2.0" , ki18n("Session Locker for KDE Workspace"));
+
+    KCmdLineOptions options;
+    options.add("forcelock", ki18n("Force session locking"));
+    options.add("dontlock", ki18n("Only start screen saver"));
+    options.add("showunlock", ki18n("Immediately show the unlock dialog"));
+    options.add("blank", ki18n("Only use the blank screen saver"));
+    options.add("plasmasetup", ki18n("start with plasma unlocked for configuring"));
+    options.add("daemon", ki18n("Fork into the background after starting up"));
+    KCmdLineArgs::addCmdLineOptions( options );
+    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+    bool daemonize = false;
+    int daemonPipe[2];
+    char daemonBuf;
+    if (args->isSet("daemon")) {
+        daemonize = true;
+        if (pipe(daemonPipe))
+            kFatal() << "pipe() failed";
+        switch (fork()) {
+        case -1:
+            kFatal() << "fork() failed";
+        case 0:
+            break;
+        default:
+            if (read(daemonPipe[0], &daemonBuf, 1) != 1)
+                _exit(1);
+            _exit(0);
+        }
+    }
+
+    putenv(strdup("SESSION_MANAGER="));
+
+    //KApplication::disableAutoDcopRegistration();
+
+    int kdesktop_screen_number = 0;
+    int starting_screen = 0;
+
+    bool child = false;
+    int parent_connection = 0; // socket to the parent saver
+    QList<int> child_sockets;
+
+    if (KGlobalSettings::isMultiHead())
+    {
+        Display *dpy = XOpenDisplay(NULL);
+        if (! dpy) {
+            fprintf(stderr,
+                    "%s: FATAL ERROR: could not open display '%s'\n",
+                    argv[0], XDisplayName(NULL));
+            exit(1);
+        }
+
+        int number_of_screens = ScreenCount(dpy);
+        starting_screen = kdesktop_screen_number = DefaultScreen(dpy);
+        int pos;
+        QByteArray display_name = XDisplayString(dpy);
+        XCloseDisplay(dpy);
+        kDebug() << "screen " << number_of_screens << " " << kdesktop_screen_number \
<< " " << display_name << " " << starting_screen; +        dpy = 0;
+
+        if ((pos = display_name.lastIndexOf('.')) != -1)
+            display_name.remove(pos, 10);
+
+        QString env;
+        if (number_of_screens != 1) {
+            for (int i = 0; i < number_of_screens; i++) {
+                if (i != starting_screen) {
+                    int fd[2];
+                    if (pipe(fd)) {
+                        perror("pipe");
+                        break;
+                    }
+                    if (fork() == 0) {
+                        child = true;
+                        kdesktop_screen_number = i;
+                        parent_connection = fd[0];
+                        // break here because we are the child process, we don't
+                        // want to fork() anymore
+                        break;
+                    } else {
+                        child_sockets.append(fd[1]);
+                    }
+                }
+            }
+
+            env.sprintf("DISPLAY=%s.%d", display_name.data(),
+                        kdesktop_screen_number);
+            kDebug() << "env " << env;
+
+            if (putenv(strdup(env.toLatin1().data()))) {
+                fprintf(stderr,
+                        "%s: WARNING: unable to set DISPLAY environment variable\n",
+                        argv[0]);
+                perror("putenv()");
+            }
+        }
+    }
+
+    MyApp app;
+    kDebug() << "app " << kdesktop_screen_number << " " << starting_screen << " " << \
child << " " << child_sockets.count() << " " << parent_connection; +    \
app.disableSessionManagement(); +    app.setQuitOnLastWindowClosed( false );
+    KGlobal::locale()->insertCatalog(QLatin1String( "libkworkspace" ));
+
+    LockProcess process(child, args->isSet("blank"));
+    if (!child)
+        process.setChildren(child_sockets);
+    else
+        process.setParent(parent_connection);
+
+    bool rt;
+    bool sig = false;
+    if (!child && (args->isSet("forcelock"))) {
+        rt = process.lock(args->isSet("showunlock"));
+        sig = true;
+    }
+    else if( child || args->isSet( "dontlock" ))
+        rt = process.dontLock();
+    else if (args->isSet("plasmasetup")) {
+        rt = process.startSetup();
+    }
+    else
+        rt = process.defaultSave();
+    if (!rt)
+        return 1;
+
+    if( sig )
+    {
+        org::kde::screensaver kscreensaver(QLatin1String( "org.kde.screensaver" ), \
QLatin1String( "/ScreenSaver" ), QDBusConnection::sessionBus()); +        \
kscreensaver.saverLockReady(); +    }
+    args->clear();
+    if (daemonize) {
+        daemonBuf = 0;
+        write(daemonPipe[1], &daemonBuf, 1);
+    }
+    return app.exec();
+}
+
+#include "main.moc"
+
+#define KDM_NO_SHUTDOWN
+#include <kworkspace/kdisplaymanager.cpp>
diff --git a/kwin/screenlocker/lock/main.h b/kwin/screenlocker/lock/main.h
new file mode 100644
index 0000000..8a60353
--- /dev/null
+++ b/kwin/screenlocker/lock/main.h
@@ -0,0 +1,39 @@
+/* This file is part of the KDE project
+   Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MAIN_H
+#define _MAIN_H
+
+#include <kapplication.h>
+
+#include <time.h>
+
+class MyApp : public KApplication {
+    Q_OBJECT
+public:
+    MyApp() : KApplication(), lastTick( 0 ) {}
+protected:
+    bool x11EventFilter( XEvent * );
+Q_SIGNALS:
+    void activity();
+private:
+    time_t lastTick;
+};
+
+#endif
diff --git a/kwin/screenlocker/screenlocker.cpp b/kwin/screenlocker/screenlocker.cpp
new file mode 100644
index 0000000..7994b83
--- /dev/null
+++ b/kwin/screenlocker/screenlocker.cpp
@@ -0,0 +1,119 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#include "screenlocker.h"
+#include "saverengine.h"
+#include "workspace.h"
+#include <fixx11h.h>
+#include "effects.h"
+// Qt
+#include <QtDBus/QDBusInterface>
+#include <QtDBus/QDBusReply>
+// KDE
+#include <KDE/KAction>
+#include <KDE/KActionCollection>
+#include <KDE/KAuthorized>
+#include <KDE/KDebug>
+#include <KDE/KShortcut>
+#include <KDE/KLocalizedString>
+
+namespace KWin
+{
+namespace ScreenLocker
+{
+
+ScreenLocker::ScreenLocker::ScreenLocker(QObject *parent)
+    : QObject(parent)
+    , m_saverEngine(new SaverEngine(this))
+    , m_locked(false)
+{
+    // TODO: test whether lock file exists
+}
+
+ScreenLocker::~ScreenLocker()
+{
+}
+
+void ScreenLocker::initShortcuts(KActionCollection *keys)
+{
+    if (KAuthorized::authorize(QLatin1String("lock_screen"))) {
+        // first make krunner forget its old shortcut
+        // we do this directly using the D-Bus interface, as KGlobalAccel/KAction \
has +        // no nice way of doing this (other than registering and deregistering \
the +        // krunner shortcut every time)
+        QDBusInterface accelIface("org.kde.kglobalaccel", "/kglobalaccel", \
"org.kde.KGlobalAccel"); +        QStringList krunnerShortcutId;
+        krunnerShortcutId << QLatin1String("krunner") << QLatin1String("Lock \
Session") << "" << ""; +        QDBusReply<QList<int> > reply = \
accelIface.call("shortcut", krunnerShortcutId); +        int shortcut = -1;
+        if (reply.isValid() && reply.value().size() == 1) {
+            shortcut = reply.value().at(0);
+            kDebug(1212) << "Existing krunner shortcut for Lock Session found:" << \
KShortcut(shortcut).toString(); +        }
+        accelIface.call(QDBus::NoBlock, "unRegister", krunnerShortcutId);
+
+        KAction *a = keys->addAction(QLatin1String("Lock Session"));
+        a->setText(i18n("Lock Session"));
+        a->setGlobalShortcut(KShortcut(Qt::ALT+Qt::CTRL+Qt::Key_L));
+        if (shortcut >= 0) {
+            // if there was a krunner shortcut, use that
+            a->setGlobalShortcut(KShortcut(shortcut), KAction::ActiveShortcut, \
KAction::NoAutoloading); +        }
+        connect(a, SIGNAL(triggered(bool)), this, SLOT(lock()));
+    }
+}
+
+void ScreenLocker::lock()
+{
+    if (m_locked) {
+        return;
+    }
+    // TODO: create lock file
+    bool hasLock = false;
+    if (Workspace::self()->compositingActive() && \
static_cast<EffectsHandlerImpl*>(effects)->provides(Effect::ScreenLocking)) { +       \
// try locking through an Effect +        hasLock = \
static_cast<EffectsHandlerImpl*>(effects)->lockScreen(); +    }
+    if (!hasLock) {
+        // no Effect to lock the screen, try legacy X Screen Saver for locking
+        hasLock = !m_saverEngine->doLock();
+    }
+    if (!hasLock) {
+        // no working lock implementation
+        // TODO: remove lock file
+        return;
+    }
+    m_locked = true;
+    emit locked();
+}
+
+void ScreenLocker::unlock()
+{
+    if (!m_locked) {
+        return;
+    }
+    // TODO: remove lock file
+    // TODO: if compositing was enforced, remove the blocking
+    m_locked = false;
+    emit unlocked();
+}
+
+
+} // namespace ScreenLocker
+} // namespace KWin
diff --git a/kwin/screenlocker/screenlocker.h b/kwin/screenlocker/screenlocker.h
new file mode 100644
index 0000000..c156e39
--- /dev/null
+++ b/kwin/screenlocker/screenlocker.h
@@ -0,0 +1,92 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#ifndef KWIN_SCREENLOCKER_SCREENLOCKER_H
+#define KWIN_SCREENLOCKER_SCREENLOCKER_H
+
+#include <QtCore/QObject>
+
+// forward declarations
+class KActionCollection;
+class SaverEngine;
+
+namespace KWin
+{
+namespace ScreenLocker
+{
+
+/**
+ * @short Class handling screen locking.
+ *
+ * The classic Screen Saving is handled by the @link SaverEngine.
+ * This class only takes care of locking the screen. That is ensure that
+ * nothing is displayed on the screen.
+ *
+ * The D-Bus interface to screen locking is provided by the @link SaverEngine
+ * for backwards-compatibility. This class cannot implement the \
org.freedesktop.ScreenSaver + * interface as it does not provide the screen saving \
capabilities. + **/
+class ScreenLocker : public QObject
+{
+    Q_OBJECT
+public:
+    ScreenLocker(QObject *parent = NULL);
+    virtual ~ScreenLocker();
+
+    void initShortcuts(KActionCollection *keys);
+
+    /**
+     * Unlocks the screen. Inside KWin we trust each other and assume
+     * that the method will only be called when the screen got unlocked
+     * by a trusted authority. E.g. a KWin Effect or the SaverEngine.
+     **/
+    void unlock();
+    /**
+     * @returns Whether the screen is locked.
+     **/
+    bool isLocked() const {
+        return m_locked;
+    }
+
+Q_SIGNALS:
+    /**
+     * Emitted when the screen gets locked.
+     **/
+    void locked();
+    /**
+     * Emitted when the screen gets unlocked.
+     **/
+    void unlocked();
+
+public Q_SLOTS:
+    /**
+     * Locks the screen, either through a KWin effect (modern) or ScreenSaver Engine \
(legacy). +     **/
+    void lock();
+
+private:
+    // legacy screen saver engine.
+    SaverEngine *m_saverEngine;
+    // indicates whether the screen is locked
+    bool m_locked;
+};
+} // namespace ScreenLocker
+} // namespace KWin
+
+#endif
diff --git a/kwin/screenlocker/screensaver/saverengine.cpp \
b/kwin/screenlocker/screensaver/saverengine.cpp new file mode 100644
index 0000000..f709f8a
--- /dev/null
+++ b/kwin/screenlocker/screensaver/saverengine.cpp
@@ -0,0 +1,512 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+//
+
+
+#include "saverengine.h"
+#include "kscreensaversettings.h"
+#include "screensaveradaptor.h"
+#include "kscreensaveradaptor.h"
+
+#include <kaction.h>
+#include <kactioncollection.h>
+#include <kauthorized.h>
+#include <kglobalaccel.h>
+#include <kstandarddirs.h>
+#include <kapplication.h>
+#include <kservicegroup.h>
+#include <krandom.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <QFile>
+#include <QX11Info>
+#include <QDBusConnection>
+#include <QDBusInterface>
+#include <QDBusReply>
+#include <QDBusServiceWatcher>
+#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+
+#include "xautolock_c.h"
+#include "screenlocker.h"
+#include <kkeysequencewidget.h>
+extern xautolock_corner_t xautolock_corners[ 4 ];
+
+//===========================================================================
+//
+// Screen saver engine. Doesn't handle the actual screensaver window,
+// starting screensaver hacks, or password entry. That's done by
+// a newly started process.
+//
+SaverEngine::SaverEngine(KWin::ScreenLocker::ScreenLocker *locker)
+    : QWidget()
+    , m_screenLocker(locker)
+{
+    (void) new ScreenSaverAdaptor( this );
+    QDBusConnection::sessionBus().registerService( QLatin1String( \
"org.freedesktop.ScreenSaver" ) ) ; +    (void) new KScreenSaverAdaptor( this );
+    QDBusConnection::sessionBus().registerService( QLatin1String( \
"org.kde.screensaver" ) ) ; +    QDBusConnection::sessionBus().registerObject( \
QLatin1String( "/ScreenSaver" ), this ); +
+    // Save X screensaver parameters
+    XGetScreenSaver(QX11Info::display(), &mXTimeout, &mXInterval,
+                    &mXBlanking, &mXExposures);
+    // And disable it. The internal X screensaver is not used at all, but we use its
+    // internal idle timer (and it is also used by DPMS support in X). This timer \
must not +    // be altered by this code, since e.g. resetting the counter after \
activating our +    // screensaver would prevent DPMS from activating. We use the \
timer merely to detect +    // user activity.
+    XSetScreenSaver(QX11Info::display(), 0, mXInterval, mXBlanking, mXExposures);
+
+    mState = Waiting;
+    mXAutoLock = 0;
+    mLockProcess = 0;
+
+    m_nr_throttled = 0;
+    m_nr_inhibited = 0;
+    m_actived_time = -1;
+
+    m_serviceWatcher = new QDBusServiceWatcher(this);
+    m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
+    m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
+    connect(m_serviceWatcher, SIGNAL(serviceUnregistered(QString)),
+            this, SLOT(serviceUnregistered(QString)));
+
+    // Also receive updates triggered through the DBus (from powerdevil) see Bug \
#177123 +    QStringList modules;
+    QDBusInterface kdedInterface(QLatin1String( "org.kde.kded" ), QLatin1String( \
"/kded" ), QLatin1String( "org.kde.kded" )); +    QDBusReply<QStringList> reply = \
kdedInterface.call(QLatin1String( "loadedModules" )); +
+    if (!reply.isValid()) {
+        return;
+    }
+
+    modules = reply.value();
+
+    if (modules.contains(QLatin1String( "powerdevil" ))) {
+      if (!QDBusConnection::sessionBus().connect(QLatin1String( "org.kde.kded" ), \
QLatin1String( "/modules/powerdevil" ), QLatin1String( "org.kde.PowerDevil" ), +      \
QLatin1String( "DPMSconfigUpdated" ), this, SLOT(configure()))) { +            \
kDebug() << "error!"; +        }
+    }
+
+    // I make it a really random number to avoid
+    // some assumptions in clients, but just increase
+    // while gnome-ss creates a random number every time
+    m_next_cookie = KRandom::random() % 20000;
+    configure();
+}
+
+//---------------------------------------------------------------------------
+//
+// Destructor - usual cleanups.
+//
+SaverEngine::~SaverEngine()
+{
+    delete mXAutoLock;
+    // Just let mLockProcess leak, so the saver is not killed
+
+    // Restore X screensaver parameters
+    XSetScreenSaver(QX11Info::display(), mXTimeout, mXInterval, mXBlanking,
+                    mXExposures);
+}
+
+//---------------------------------------------------------------------------
+
+void SaverEngine::Lock()
+{
+    m_screenLocker->lock();
+}
+
+bool SaverEngine::doLock()
+{
+    if (mState == Waiting)
+    {
+        return startLockProcess( ForceLock );
+    }
+    else
+    {
+        // XXX race condition here
+        ::kill(mLockProcess->pid(), SIGHUP);
+        return false;
+    }
+}
+
+void SaverEngine::processLockTransactions()
+{
+    QList<QDBusMessage>::ConstIterator it = mLockTransactions.constBegin(),
+                                      end = mLockTransactions.constEnd();
+    for ( ; it != end; ++it )
+    {
+        QDBusConnection::sessionBus().send(*it);
+    }
+    mLockTransactions.clear();
+}
+
+void SaverEngine::saverLockReady()
+{
+    if( mState != Preparing )
+    {
+        kDebug() << "Got unexpected saverLockReady()";
+        return;
+    }
+    kDebug() << "Saver Lock Ready";
+    processLockTransactions();
+    if (m_nr_throttled)
+        ::kill(mLockProcess->pid(), SIGSTOP);
+}
+
+void SaverEngine::SimulateUserActivity()
+{
+    XForceScreenSaver( QX11Info::display(), ScreenSaverReset );
+    if ( mXAutoLock && mState == Waiting )
+    {
+        mXAutoLock->resetTrigger();
+    }
+    else if (mLockProcess)
+    {
+        ::kill(mLockProcess->pid(), SIGUSR1);
+    }
+}
+
+//---------------------------------------------------------------------------
+bool SaverEngine::save()
+{
+    if (mState == Waiting)
+    {
+        return startLockProcess( DefaultLock );
+    }
+    return false;
+}
+
+bool SaverEngine::setupPlasma()
+{
+    if (mState == Waiting)
+    {
+        return startLockProcess( PlasmaSetup );
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------
+bool SaverEngine::quit()
+{
+    if (mState == Saving || mState == Preparing)
+    {
+        stopLockProcess();
+        return true;
+    }
+    return false;
+}
+
+//---------------------------------------------------------------------------
+bool SaverEngine::isEnabled()
+{
+    return mXAutoLock != 0;
+}
+
+//---------------------------------------------------------------------------
+bool SaverEngine::enable( bool e, bool force )
+{
+    if ( !force && e == isEnabled() )
+        return true;
+
+    // If we aren't in a suitable state, we will not reconfigure.
+    if (mState != Waiting)
+        return false;
+
+    if (e)
+    {
+        if (!mXAutoLock)
+        {
+            mXAutoLock = new XAutoLock();
+            connect(mXAutoLock, SIGNAL(timeout()), SLOT(idleTimeout()));
+        }
+
+        int timeout = KScreenSaverSettings::timeout();
+        mXAutoLock->setTimeout(timeout);
+        mXAutoLock->setDPMS(true);
+#ifdef NOT_FREAKIN_UGLY
+        mXAutoLock->changeCornerLockStatus( mLockCornerTopLeft, mLockCornerTopRight, \
mLockCornerBottomLeft, mLockCornerBottomRight); +#else
+        xautolock_corners[0] = \
applyManualSettings(KScreenSaverSettings::actionTopLeft()); +        \
xautolock_corners[1] = applyManualSettings(KScreenSaverSettings::actionTopRight()); + \
xautolock_corners[2] = applyManualSettings(KScreenSaverSettings::actionBottomLeft()); \
+        xautolock_corners[3] = \
applyManualSettings(KScreenSaverSettings::actionBottomRight()); +#endif
+
+        mXAutoLock->start();
+        kDebug() << "Saver Engine started, timeout: " << timeout;
+    }
+    else
+    {
+        delete mXAutoLock;
+        mXAutoLock = 0;
+        kDebug() << "Saver Engine disabled";
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+bool SaverEngine::isBlanked()
+{
+  return (mState != Waiting);
+}
+
+//---------------------------------------------------------------------------
+//
+// Read and apply configuration.
+//
+void SaverEngine::configure()
+{
+    // create a new config obj to ensure we read the latest options
+    KScreenSaverSettings::self()->readConfig();
+
+    enable( KScreenSaverSettings::screenSaverEnabled(), true );
+}
+
+//---------------------------------------------------------------------------
+//
+// Start the screen saver.
+//
+bool SaverEngine::startLockProcess( LockType lock_type )
+{
+    Q_ASSERT(mState == Waiting);
+
+    kDebug() << "SaverEngine: starting saver";
+
+    QString path = KStandardDirs::findExe( QLatin1String( "kscreenlocker" ) );
+    if( path.isEmpty())
+    {
+        kDebug() << "Can't find kscreenlocker!";
+        return false;
+    }
+    mLockProcess = new KProcess; // No parent, so it is not auto-deleted
+    connect(mLockProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+            SLOT(lockProcessExited()));
+    *mLockProcess << path;
+    switch( lock_type )
+    {
+    case ForceLock:
+        *mLockProcess << QLatin1String( "--forcelock" );
+        break;
+    case DontLock:
+        *mLockProcess << QLatin1String( "--dontlock" );
+        break;
+    case PlasmaSetup:
+        *mLockProcess << QLatin1String( "--plasmasetup" );
+        break;
+    default:
+        break;
+    }
+
+    m_actived_time = time( 0 );
+    mLockProcess->start();
+    if (mLockProcess->waitForStarted() == false )
+    {
+        kDebug() << "Failed to start kscreenlocker!";
+        delete mLockProcess;
+        mLockProcess = 0;
+        m_actived_time = -1;
+        return false;
+    }
+
+    if (mXAutoLock)
+    {
+        mXAutoLock->stop();
+    }
+
+    emit ActiveChanged(true); // DBus signal
+    mState = Preparing;
+
+    // It takes a while for kscreenlocker to start and lock the screen.
+    // Therefore delay the DBus call until it tells krunner that the locking is in \
effect. +    // This is done only for --forcelock .
+    if (lock_type == ForceLock && calledFromDBus()) {
+        mLockTransactions.append(message().createReply());
+        setDelayedReply(true);
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+//
+// Stop the screen saver.
+//
+void SaverEngine::stopLockProcess()
+{
+    Q_ASSERT(mState != Waiting);
+    kDebug() << "SaverEngine: stopping lock process";
+
+    mLockProcess->kill();
+}
+
+void SaverEngine::lockProcessExited()
+{
+    Q_ASSERT(mState != Waiting);
+    kDebug() << "SaverEngine: lock process exited";
+
+    delete mLockProcess;
+    mLockProcess = 0;
+
+    if (mXAutoLock)
+    {
+        mXAutoLock->start();
+    }
+
+    processLockTransactions();
+    emit ActiveChanged(false); // DBus signal
+    m_actived_time = -1;
+    mState = Waiting;
+    m_screenLocker->unlock();
+}
+
+//---------------------------------------------------------------------------
+//
+// XAutoLock has detected the required idle time.
+//
+void SaverEngine::idleTimeout()
+{
+    if( mState != Waiting )
+        return; // already saving
+    startLockProcess( DefaultLock );
+}
+
+xautolock_corner_t SaverEngine::applyManualSettings(int action)
+{
+    if (action == 0)
+    {
+        kDebug() << "no lock";
+        return ca_nothing;
+    }
+    else if (action == 1)
+    {
+        kDebug() << "lock screen";
+        return ca_forceLock;
+    }
+    else if (action == 2)
+    {
+        kDebug() << "prevent lock";
+        return ca_dontLock;
+    }
+    else
+    {
+        kDebug() << "no lock nothing";
+        return ca_nothing;
+    }
+}
+
+uint SaverEngine::GetSessionIdleTime()
+{
+    return mXAutoLock ? mXAutoLock->idleTime() : 0;
+}
+
+uint SaverEngine::GetActiveTime()
+{
+    if ( m_actived_time == -1 )
+        return 0;
+    return time( 0 ) - m_actived_time;
+}
+
+bool SaverEngine::GetActive()
+{
+    return ( mState != Waiting );
+}
+
+bool SaverEngine::SetActive(bool state)
+{
+    if ( state )
+        return save();
+    else
+        return quit();
+}
+
+uint SaverEngine::Inhibit(const QString &/*application_name*/, const QString \
&/*reason*/) +{
+    ScreenSaverRequest sr;
+//     sr.appname = application_name;
+//     sr.reasongiven = reason;
+    sr.cookie = m_next_cookie++;
+    sr.dbusid = message().service();
+    sr.type = ScreenSaverRequest::Inhibit;
+    m_requests.append( sr );
+    m_serviceWatcher->addWatchedService(sr.dbusid);
+    m_nr_inhibited++;
+    if (KScreenSaverSettings::screenSaverEnabled())
+        enable( false );
+    return sr.cookie;
+}
+
+void SaverEngine::UnInhibit(uint cookie)
+{
+    QMutableListIterator<ScreenSaverRequest> it( m_requests );
+    while ( it.hasNext() )
+    {
+        if ( it.next().cookie == cookie ) {
+            it.remove();
+            if ( !--m_nr_inhibited )
+                if (KScreenSaverSettings::screenSaverEnabled())
+                    enable( true );
+        }
+    }
+}
+
+uint SaverEngine::Throttle(const QString &/*application_name*/, const QString \
&/*reason*/) +{
+    ScreenSaverRequest sr;
+//     sr.appname = application_name;
+//     sr.reasongiven = reason;
+    sr.cookie = m_next_cookie++;
+    sr.type = ScreenSaverRequest::Throttle;
+    sr.dbusid = message().service();
+    m_requests.append( sr );
+    m_serviceWatcher->addWatchedService(sr.dbusid);
+    m_nr_throttled++;
+    if (mLockProcess)
+        // XXX race condition here (locker may be not ready yet)
+        ::kill(mLockProcess->pid(), SIGSTOP);
+    return sr.cookie;
+}
+
+void SaverEngine::UnThrottle(uint cookie)
+{
+    QMutableListIterator<ScreenSaverRequest> it( m_requests );
+    while ( it.hasNext() )
+    {
+        if ( it.next().cookie == cookie ) {
+            it.remove();
+            if ( !--m_nr_throttled )
+                if (mLockProcess)
+                    ::kill(mLockProcess->pid(), SIGCONT);
+        }
+    }
+}
+
+void SaverEngine::serviceUnregistered(const QString& name)
+{
+    m_serviceWatcher->removeWatchedService( name );
+    QListIterator<ScreenSaverRequest> it( m_requests );
+    while ( it.hasNext() )
+    {
+        const ScreenSaverRequest &r = it.next();
+        if ( r.dbusid == name )
+        {
+            if ( r.type == ScreenSaverRequest::Throttle )
+                UnThrottle( r.cookie );
+            else
+                UnInhibit( r.cookie );
+        }
+    }
+}
+
+#include "saverengine.moc"
+
+
diff --git a/kwin/screenlocker/screensaver/saverengine.h \
b/kwin/screenlocker/screensaver/saverengine.h new file mode 100644
index 0000000..4efebec
--- /dev/null
+++ b/kwin/screenlocker/screensaver/saverengine.h
@@ -0,0 +1,195 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+//
+
+#ifndef SAVERENGINE_H
+#define SAVERENGINE_H
+
+#include <QWidget>
+#include <QVector>
+#include <QDBusContext>
+#include <QDBusMessage>
+
+class QDBusServiceWatcher;
+class KProcess;
+
+namespace KWin {
+namespace ScreenLocker {
+    class ScreenLocker;
+}
+}
+
+#include "xautolock.h"
+#include "xautolock_c.h"
+
+class ScreenSaverRequest
+{
+public:
+//     QString appname;
+//     QString reasongiven;
+    QString dbusid;
+    uint cookie;
+    enum { Inhibit,Throttle } type;
+};
+
+//===========================================================================
+/**
+ * Screen saver engine.  Handles screensaver window, starting screensaver
+ * hacks, and password entry.
+ */
+class SaverEngine : public QWidget, protected QDBusContext
+{
+    Q_OBJECT
+    Q_CLASSINFO("D-Bus Interface", "org.freedesktop.ScreenSaver")
+
+public:
+    SaverEngine(KWin::ScreenLocker::ScreenLocker *locker);
+    ~SaverEngine();
+
+    bool doLock();
+
+public Q_SLOTS:
+    /**
+     * Lock the screen now even if the screensaver does not lock by default.
+     */
+    void Lock();
+
+    /**
+     * Save the screen now. If the user has locking enabled, the screen is locked \
also. +     */
+    bool save();
+
+    /**
+     * Start the screensaver in plasma-setup mode.
+     * if plasma is not enabled, this just locks the screen.
+     */
+    bool setupPlasma();
+
+    /**
+     * Quit the screensaver if it is running
+     */
+    bool quit();
+
+    /**
+     * Simulate user activity
+     */
+    void SimulateUserActivity();
+
+    /**
+     * Return true if the screensaver is enabled
+     */
+    bool isEnabled();
+
+    /**
+     * Enable/disable the screensaver
+     * @return true if the action succeeded
+     */
+    bool enable( bool e, bool force = false );
+
+    /**
+     * Return true if the screen is currently blanked
+     */
+    bool isBlanked();
+
+    /**
+     * Read and apply configuration.
+     */
+    void configure();
+
+    /**
+     * Called by krunner_lock when locking is in effect.
+     */
+    void saverLockReady();
+
+    /**
+     * Request a change in the state of the screensaver.
+     * Set to TRUE to request that the screensaver activate.
+     * Active means that the screensaver has blanked the
+     * screen and may run a graphical theme.  This does
+     * not necessary mean that the screen is locked.
+     */
+    bool SetActive( bool state );
+
+    /// Returns the value of the current state of activity (See setActive)
+    bool GetActive();
+
+    /**
+     * Returns the number of seconds that the screensaver has
+     * been active.  Returns zero if the screensaver is not active.
+     */
+    uint GetActiveTime();
+
+    /**
+     * Returns the number of seconds that the session has
+     * been idle.  Returns zero if the session is not idle.
+     */
+    uint GetSessionIdleTime();
+
+    /**
+     * Request that saving the screen due to system idleness
+     * be blocked until UnInhibit is called or the
+     * calling process exits.
+     * The cookie is a random number used to identify the request
+     */
+    uint Inhibit(const QString &application_name, const QString \
&reason_for_inhibit); +    /// Cancel a previous call to Inhibit() identified by the \
cookie. +    void UnInhibit(uint cookie);
+
+    /**
+     * Request that running themes while the screensaver is active
+     * be blocked until UnThrottle is called or the
+     * calling process exits.
+     * The cookie is a random number used to identify the request
+     */
+    uint Throttle(const QString &application_name, const QString \
&reason_for_inhibit); +    /// Cancel a previous call to Throttle() identified by the \
cookie. +    void UnThrottle(uint cookie);
+
+Q_SIGNALS:
+    // DBus signals
+    void ActiveChanged(bool state);
+
+protected Q_SLOTS:
+    void idleTimeout();
+    void lockProcessExited();
+    void serviceUnregistered(const QString&);
+
+protected:
+    enum LockType { DontLock, DefaultLock, ForceLock, PlasmaSetup };
+    bool startLockProcess( LockType lock_type );
+    void stopLockProcess();
+    bool handleKeyPress(XKeyEvent *xke);
+    void processLockTransactions();
+    xautolock_corner_t applyManualSettings(int);
+
+private:
+    enum State { Waiting, Preparing, Saving };
+
+    State       mState;
+    XAutoLock   *mXAutoLock;
+    KProcess    *mLockProcess;
+
+    // the original X screensaver parameters
+    int         mXTimeout;
+    int         mXInterval;
+    int         mXBlanking;
+    int         mXExposures;
+
+    time_t      m_actived_time;
+    QList<ScreenSaverRequest> m_requests;
+    QDBusServiceWatcher *m_serviceWatcher;
+    uint        m_next_cookie;
+    
+    int        m_nr_throttled;
+    int        m_nr_inhibited;
+ 
+    QList<QDBusMessage> mLockTransactions;
+
+    KWin::ScreenLocker::ScreenLocker *m_screenLocker;
+};
+
+#endif
+
diff --git a/kwin/screenlocker/screensaver/xautolock.cpp \
b/kwin/screenlocker/screensaver/xautolock.cpp new file mode 100644
index 0000000..7124215
--- /dev/null
+++ b/kwin/screenlocker/screensaver/xautolock.cpp
@@ -0,0 +1,317 @@
+//----------------------------------------------------------------------------
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+// Copyright 2003 Lubos Lunak <l.lunak@kde.org>
+//
+// KDE screensaver engine
+//
+
+#include <config-workspace.h>
+
+#include "xautolock.h"
+#include "xautolock_c.h"
+
+#include <kapplication.h>
+#include <kdebug.h>
+
+#include <QTimerEvent>
+#include <QX11Info>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef HAVE_DPMS
+extern "C" {
+#include <X11/Xmd.h>
+#ifndef Bool
+#define Bool BOOL
+#endif
+#include <X11/extensions/dpms.h>
+
+#ifndef HAVE_DPMSINFO_PROTO
+Status DPMSInfo ( Display *, CARD16 *, BOOL * );
+#endif
+}
+#endif
+
+#include <ctime>
+
+xautolock_corner_t xautolock_corners[ 4 ];
+
+static XAutoLock* self = NULL;
+
+extern "C" {
+static int catchFalseAlarms(Display *, XErrorEvent *)
+{
+    return 0;
+}
+}
+
+//===========================================================================
+//
+// Detect user inactivity.
+// Named XAutoLock after the program that it is based on.
+//
+XAutoLock::XAutoLock()
+{
+    self = this;
+#ifdef HAVE_XSCREENSAVER
+    mMitInfo = 0;
+    int dummy;
+    if (XScreenSaverQueryExtension( QX11Info::display(), &dummy, &dummy ))
+    {
+        mMitInfo = XScreenSaverAllocInfo();
+    }
+    else
+#endif
+    {
+        kapp->installX11EventFilter( this );
+        int (*oldHandler)(Display *, XErrorEvent *);
+        oldHandler = XSetErrorHandler(catchFalseAlarms);
+        XSync(QX11Info::display(), False );
+        xautolock_initDiy( QX11Info::display());
+        XSync(QX11Info::display(), False );
+        XSetErrorHandler(oldHandler);
+    }
+
+    mTimeout = DEFAULT_TIMEOUT;
+    mDPMS = true;
+    resetTrigger();
+
+    mActive = false;
+
+    mTimerId = startTimer( CHECK_INTERVAL );
+    // This is an internal clock timer (in seconds), used instead of querying system \
time. +    // It is incremented manually, preventing from problems with clock jumps.
+    // In other words, this is the 'now' time and the reference point for other \
times here. +    mElapsed = 0;
+}
+
+//---------------------------------------------------------------------------
+//
+// Destructor.
+//
+XAutoLock::~XAutoLock()
+{
+    stop();
+    self = NULL;
+}
+
+//---------------------------------------------------------------------------
+//
+// The time in seconds of continuous inactivity.
+//
+void XAutoLock::setTimeout(int t)
+{
+    mTimeout = t;
+}
+
+void XAutoLock::setDPMS(bool s)
+{
+#ifdef HAVE_DPMS
+    BOOL on;
+    CARD16 state;
+    DPMSInfo( QX11Info::display(), &state, &on );
+    if (!on)
+        s = false;
+#endif
+    mDPMS = s;
+}
+
+//---------------------------------------------------------------------------
+//
+// Start watching Activity
+//
+void XAutoLock::start()
+{
+    mActive = true;
+    resetTrigger();
+}
+
+//---------------------------------------------------------------------------
+//
+// Stop watching Activity
+//
+void XAutoLock::stop()
+{
+    mActive = false;
+    resetTrigger();
+}
+
+//---------------------------------------------------------------------------
+//
+// Reset the trigger time.
+//
+void XAutoLock::resetTrigger()
+{
+    // Time of the last user activity (used only when the internal XScreensaver
+    // idle counter is not available).
+    mLastReset = mElapsed;
+    // Time when screensaver should be activated.
+    mTrigger = mElapsed + mTimeout;
+#ifdef HAVE_XSCREENSAVER
+    mLastIdle = 0;
+#endif
+    // Do not reset the internal X screensaver here (no XForceScreenSaver())
+}
+
+//---------------------------------------------------------------------------
+//
+// Move the trigger time in order to postpone (repeat) emitting of timeout().
+//
+void XAutoLock::postpone()
+{
+    mTrigger = mElapsed + 60; // delay by 60sec
+}
+
+//---------------------------------------------------------------------------
+//
+// Set the remaining time to 't', if it's shorter than already set.
+//
+void XAutoLock::setTrigger( int t )
+{
+    time_t newT = mElapsed + qMax(t, 0);
+    if (mTrigger > newT)
+        mTrigger = newT;
+}
+
+//---------------------------------------------------------------------------
+//
+// Process new windows and check the mouse.
+//
+void XAutoLock::timerEvent(QTimerEvent *ev)
+{
+    if (ev->timerId() != mTimerId)
+    {
+        return;
+    }
+    mElapsed += CHECK_INTERVAL / 1000;
+
+#ifdef HAVE_XSCREENSAVER
+    if (!mMitInfo)
+#endif
+    { // only the diy way needs special X handler
+        XSync( QX11Info::display(), False );
+        int (*oldHandler)(Display *, XErrorEvent *) =
+                XSetErrorHandler(catchFalseAlarms);
+
+        xautolock_processQueue();
+
+        XSetErrorHandler(oldHandler);
+    }
+
+#ifdef HAVE_XSCREENSAVER
+    if (mMitInfo)
+    {
+        Display *d = QX11Info::display();
+        // Check user idle time. If it is smaller than before, it is either
+        // clock jump or user activity, so reset the trigger time. Checking whether
+        // there is user inactivity timeout is done below using mTrigger and \
mElapsed. +        XScreenSaverQueryInfo(d, DefaultRootWindow(d), mMitInfo);
+        if (mLastIdle < mMitInfo->idle)
+            mLastIdle = mMitInfo->idle;
+        else
+            resetTrigger();
+    }
+#endif /* HAVE_XSCREENSAVER */
+
+    // This needs to be after the above check, so it overrides it.
+    xautolock_queryPointer( QX11Info::display());
+
+    bool activate = false;
+
+    // This is the test whether to activate screensaver. If we have reached the time
+    // and for the whole timeout period there was no activity (which would change \
mTrigger +    // again), activate.
+    if (mElapsed >= mTrigger)
+        activate = true;
+
+#ifdef HAVE_DPMS
+    BOOL on;
+    CARD16 state;
+    CARD16 timeout1, timeout2, timeout3;
+    DPMSInfo( QX11Info::display(), &state, &on );
+    DPMSGetTimeouts( QX11Info::display(), &timeout1, &timeout2, &timeout3 );
+
+    // kDebug() << "DPMSInfo " << state << on;
+    // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time
+    // that is always smaller than DPMS timeout (X bug I guess). So if DPMS
+    // saving is active, simply always activate our saving too, otherwise
+    // this could prevent locking from working.
+    // X.Org 7.4: With this version activating DPMS resets the screensaver idle \
timer, +    // so keep this. It probably makes sense to always do this anyway.
+    if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff)
+        activate = true;
+    // If we are DPMS-dependent and either DPMS is turned off completely or all
+    // three DPMS modes are turned off, don't activate (apps use this to turn off
+    // screensavers).
+    if(mDPMS && (!on || (timeout1 == 0 && timeout2 == 0 && timeout3 == 0 ))) {
+        activate = false;
+        resetTrigger();
+    }
+#endif
+
+    // Do not check whether internal X screensaver is enabled or disabled, since we
+    // have disabled it ourselves. Some apps might try to disable it too to prevent
+    // screensavers, but then our logic breaks[*]. Those apps need to disable DPMS \
anyway, +    // or they will still have problems, so the DPMS code above should be \
enough. +    // Besides, I doubt other screensaver implementations check this either.
+    // [*] We can't run with X screensaver enabled, since then sooner or later
+    // the internal screensaver will activate instead of our screensaver and we \
cannot +    // prevent its activation by resetting the idle counter since that would \
also +    // reset DPMS saving.
+
+    if(mActive && activate)
+        emit timeout();
+}
+
+bool XAutoLock::x11Event( XEvent* ev )
+{
+    xautolock_processEvent( ev );
+// don't futher process key events that were received only because XAutoLock wants \
them +    if( ev->type == KeyPress && !ev->xkey.send_event
+#ifdef HAVE_XSCREENSAVER
+        && !mMitInfo
+#endif
+        && !QWidget::find( ev->xkey.window ))
+        return true;
+    return false;
+}
+
+bool XAutoLock::ignoreWindow( WId w )
+{
+    if( w != QX11Info::appRootWindow() && QWidget::find( w ))
+        return true;
+    return false;
+}
+
+time_t XAutoLock::idleTime()
+{
+#ifdef HAVE_XSCREENSAVER
+    if (mMitInfo)
+        return mMitInfo->idle / 1000;
+#endif
+    return mElapsed - mLastReset;
+}
+
+extern "C"
+void xautolock_resetTriggers()
+{
+  self->resetTrigger();
+}
+
+extern "C"
+void xautolock_setTrigger( int t )
+{
+  self->setTrigger( t );
+}
+
+extern "C"
+int xautolock_ignoreWindow( Window w )
+{
+   return self->ignoreWindow( w );
+}
+
+#include "xautolock.moc"
diff --git a/kwin/screenlocker/screensaver/xautolock.h \
b/kwin/screenlocker/screensaver/xautolock.h new file mode 100644
index 0000000..3db3233
--- /dev/null
+++ b/kwin/screenlocker/screensaver/xautolock.h
@@ -0,0 +1,91 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones <mjones@kde.org>
+//
+
+#ifndef __XAUTOLOCK_H__
+#define __XAUTOLOCK_H__
+
+#include <config-xautolock.h>
+
+#include <QWidget>
+
+#include <X11/Xlib.h>
+#ifdef HAVE_XSCREENSAVER
+# include <X11/extensions/scrnsaver.h>
+#endif
+#include <fixx11h.h>
+
+//===========================================================================
+//
+// Detect user inactivity.
+// Named XAutoLock after the program that it is based on.
+//
+class XAutoLock : public QWidget
+{
+    Q_OBJECT
+public:
+    XAutoLock();
+    ~XAutoLock();
+
+    //-----------------------------------------------------------------------
+    //
+    // The time in seconds of continuous inactivity.
+    // Need to call start() again afterwards.
+    //
+    void setTimeout(int t);
+    
+    void setDPMS(bool s);
+    
+    //-----------------------------------------------------------------------
+    //
+    // Start watching Activity
+    //
+    void start();
+
+    //-----------------------------------------------------------------------
+    //
+    // Stop watching Activity
+    //
+    void stop();
+
+    //-----------------------------------------------------------------------
+    //
+    // Should be called only from a slot connected to the timeout() signal. Will
+    // result in the timeout() signal being emitted again with a delay (i.e. \
postponed). +    //
+    void postpone();
+
+    // internal
+    void resetTrigger();
+    // internal
+    void setTrigger( int );
+    // internal
+    bool ignoreWindow( WId );
+    // internal
+    time_t idleTime();
+    
+Q_SIGNALS:
+    void timeout();
+
+protected:
+    virtual void timerEvent(QTimerEvent *ev);
+    virtual bool x11Event( XEvent* );
+
+protected:
+    int     mTimerId;
+    int     mTimeout;
+    time_t  mTrigger;
+    bool    mActive;
+    time_t  mLastReset;
+    time_t  mElapsed;
+    bool    mDPMS;
+#ifdef HAVE_XSCREENSAVER
+    XScreenSaverInfo *mMitInfo;
+    ulong   mLastIdle;
+#endif
+};
+
+#endif
diff --git a/kwin/screenlocker/screensaver/xautolock_c.h \
b/kwin/screenlocker/screensaver/xautolock_c.h new file mode 100644
index 0000000..3b82f5c
--- /dev/null
+++ b/kwin/screenlocker/screensaver/xautolock_c.h
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ *
+ * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT)
+ *
+ * Content: This file is part of version 2.x of xautolock. It takes care
+ *          of most OS dependencies, and defines the program's default
+ *          settings.
+ *
+ *          Please send bug reports etc. to eyckmans@imec.be.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans.
+ *
+ * Versions 2.0 and above of xautolock are available under version 2 of the
+ * GNU GPL. Earlier versions are available under other conditions. For more
+ * information, see the License file.
+ *
+ *****************************************************************************/
+
+#ifndef __xautolock_c_h
+#define __xautolock_c_h
+
+#include <X11/Xlib.h>
+#ifdef __cplusplus
+# include <fixx11h.h>
+#endif
+
+#define DEFAULT_TIMEOUT           600
+
+#define CHECK_INTERVAL           5000      /* ms */
+
+#define CREATION_DELAY             30      /* should be > 10 and
+                                              < min (45,(MIN_MINUTES*30))  */
+#define TIME_CHANGE_LIMIT         120      /* if the time changes by more
+                                              than x secs then we will
+                                              assume someone has changed
+                                              date or machine has suspended */
+
+#define cornerSize                  5
+
+#define cornerDelay                 5
+
+#define cornerRedelay               5
+
+typedef enum { ca_nothing, ca_dontLock, ca_forceLock } xautolock_corner_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+void xautolock_processEvent( XEvent* ev );
+void xautolock_processQueue( void );
+void xautolock_queryPointer (Display* d);
+void xautolock_initDiy (Display* d);
+void xautolock_resetTriggers( void );
+void xautolock_setTrigger( int );
+int xautolock_ignoreWindow( Window );
+extern xautolock_corner_t xautolock_corners[ 4 ];
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/kwin/screenlocker/screensaver/xautolock_diy.c \
b/kwin/screenlocker/screensaver/xautolock_diy.c new file mode 100644
index 0000000..b9df2f8
--- /dev/null
+++ b/kwin/screenlocker/screensaver/xautolock_diy.c
@@ -0,0 +1,289 @@
+/*****************************************************************************
+ *
+ * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT)
+ *
+ * Content: This file is part of version 2.x of xautolock. It implements
+ *          the stuff used when the program is not using a screen saver
+ *          extension and thus has to use the good old "do it yourself"
+ *          approach for detecting user activity.
+ *
+ *          The basic idea is that we initially traverse the window tree,
+ *          selecting SubstructureNotify on all windows and adding each
+ *          window to a temporary list. About +- 30 seconds later, we 
+ *          scan this list, now asking for KeyPress events. The delay
+ *          is needed in order to interfere as little as possible with
+ *          the event propagation mechanism. Whenever a new window is 
+ *          created by an application, a similar process takes place. 
+ *
+ *          Please send bug reports etc. to eyckmans@imec.be.
+ * 
+ * --------------------------------------------------------------------------
+ * 
+ * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans.
+ * 
+ * Versions 2.0 and above of xautolock are available under version 2 of the
+ * GNU GPL. Earlier versions are available under other conditions. For more
+ * information, see the License file.
+ *
+ *****************************************************************************/
+
+#include <X11/Xlib.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "xautolock_c.h"
+
+static void selectEvents (Window window, Bool substructureOnly);
+
+/*
+ *  Window queue management.
+ */
+typedef struct item
+{
+  Window       window;
+  time_t       creationtime;
+  struct item* next;
+} xautolock_anItem, *xautolock_item;
+
+static struct 
+{
+  Display*     display;
+  struct item* head;
+  struct item* tail;
+} queue;
+
+static void
+addToQueue (Window window)
+{
+  xautolock_item newItem = malloc(sizeof(xautolock_anItem));
+
+  newItem->window = window;
+  newItem->creationtime = time (0);
+  newItem->next = 0;
+
+  if (!queue.head) queue.head = newItem;
+  if ( queue.tail) queue.tail->next = newItem;
+
+  queue.tail = newItem;
+}
+
+static void
+processQueue (time_t age)
+{
+  if (queue.head)
+  {
+    time_t now = time (0);
+    xautolock_item current = queue.head;
+
+    while (current && current->creationtime + age < now)
+    {
+      selectEvents (current->window, False);
+      queue.head = current->next;
+      free (current);
+      current = queue.head;
+    }
+
+    if (!queue.head) queue.tail = 0;
+  }
+}
+
+/*
+ *  Function for selecting all interesting events on a given 
+ *  (tree of) window(s).
+ */
+static void 
+selectEvents (Window window, Bool substructureOnly)
+{
+  Window            root;              /* root window of the window */
+  Window            parent;            /* parent of the window      */
+  Window*           children;          /* children of the window    */
+  unsigned          nofChildren = 0;   /* number of children        */
+  unsigned          i;                 /* loop counter              */
+  XWindowAttributes attribs;           /* attributes of the window  */
+
+  if( xautolock_ignoreWindow( window ))
+      return;
+ /*
+  *  Start by querying the server about the root and parent windows.
+  */
+  if (!XQueryTree (queue.display, window, &root, &parent,
+                   &children, &nofChildren))
+  {
+    return;
+  }
+
+  if (nofChildren) (void) XFree ((char*) children);
+
+ /*
+  *  Build the appropriate event mask. The basic idea is that we don't
+  *  want to interfere with the normal event propagation mechanism if
+  *  we don't have to.
+  *
+  *  On the root window, we need to ask for both substructureNotify 
+  *  and KeyPress events. On all other windows, we always need 
+  *  substructureNotify, but only need Keypress if some other client
+  *  also asked for them, or if they are not being propagated up the
+  *  window tree.
+  */
+#if 0
+  if (substructureOnly)
+  {
+    (void) XSelectInput (queue.display, window, SubstructureNotifyMask);
+  }
+  else
+  {
+    if (parent == None) /* the *real* rootwindow */
+    {
+      attribs.all_event_masks = 
+      attribs.do_not_propagate_mask = KeyPressMask;
+    }
+    else if (!XGetWindowAttributes (queue.display, window, &attribs))
+#else
+    {
+    if (!XGetWindowAttributes (queue.display, window, &attribs))
+#endif
+    {
+      return;
+    }
+
+#if 0
+    (void) XSelectInput (queue.display, window, 
+                           SubstructureNotifyMask
+                         | (  (  attribs.all_event_masks
+                               | attribs.do_not_propagate_mask)
+                            & KeyPressMask));
+#else
+    {
+    int mask = SubstructureNotifyMask | attribs.your_event_mask;
+    if( !substructureOnly )
+        {
+        mask |=            (  (  attribs.all_event_masks
+                               | attribs.do_not_propagate_mask)
+                            & KeyPressMask  );
+        }
+    (void) XSelectInput (queue.display, window, mask );
+    }
+#endif
+
+  }
+
+ /*
+  *  Now ask for the list of children again, since it might have changed
+  *  in between the last time and us selecting SubstructureNotifyMask.
+  *
+  *  There is a (very small) chance that we might process a subtree twice:
+  *  child windows that have been created after our XSelectinput() has
+  *  been processed but before we get to the XQueryTree() bit will be 
+  *  in this situation. This is harmless. It could be avoided by using
+  *  XGrabServer(), but that'd be an impolite thing to do, and since it
+  *  isn't required...
+  */
+  if (!XQueryTree (queue.display, window, &root, &parent,
+                   &children, &nofChildren))
+  {
+    return;
+  }
+
+ /*
+  *  Now do the same thing for all children.
+  */
+  for (i = 0; i < nofChildren; ++i)
+  {
+    selectEvents (children[i], substructureOnly);
+  }
+
+  if (nofChildren) (void) XFree ((char*) children);
+}
+
+#if 0
+/*
+ *  Function for processing any events that have come in since 
+ *  last time. It is crucial that this function does not block
+ *  in case nothing interesting happened.
+ */
+void
+processEvents (void)
+{
+  while (XPending (queue.display))
+  {
+    XEvent event;
+
+    if (XCheckMaskEvent (queue.display, SubstructureNotifyMask, &event))
+    {
+      if (event.type == CreateNotify)
+      {
+        addToQueue (event.xcreatewindow.window);
+      }
+    }
+    else
+    {
+      (void) XNextEvent (queue.display, &event);
+    }
+
+   /*
+    *  Reset the triggers if and only if the event is a
+    *  KeyPress event *and* was not generated by XSendEvent().
+    */
+    if (   event.type == KeyPress
+        && !event.xany.send_event)
+    {
+      resetTriggers ();
+    }
+  }
+
+ /*
+  *  Check the window queue for entries that are older than
+  *  CREATION_DELAY seconds.
+  */
+  processQueue ((time_t) CREATION_DELAY);
+}
+#else
+void xautolock_processEvent( XEvent* event )
+{
+      if (event->type == CreateNotify)
+      {
+        addToQueue (event->xcreatewindow.window);
+      }
+   /*
+    *  Reset the triggers if and only if the event is a
+    *  KeyPress event *and* was not generated by XSendEvent().
+    */
+    if (   event->type == KeyPress
+        && !event->xany.send_event)
+    {
+      xautolock_resetTriggers ();
+    }
+}
+
+void xautolock_processQueue()
+{
+ /*
+  *  Check the window queue for entries that are older than
+  *  CREATION_DELAY seconds.
+  */
+  processQueue ((time_t) CREATION_DELAY);
+}
+#endif
+
+
+/*
+ *  Function for initialising the whole shebang.
+ */
+void
+xautolock_initDiy (Display* d)
+{
+  int s;
+
+  queue.display = d;
+  queue.tail = 0;
+  queue.head = 0; 
+
+  for (s = -1; ++s < ScreenCount (d); )
+  {
+    Window root = RootWindowOfScreen (ScreenOfDisplay (d, s));
+    addToQueue (root);
+#if 0
+    selectEvents (root, True);
+#endif
+  }
+}
diff --git a/kwin/screenlocker/screensaver/xautolock_engine.c \
b/kwin/screenlocker/screensaver/xautolock_engine.c new file mode 100644
index 0000000..d6d0cf5
--- /dev/null
+++ b/kwin/screenlocker/screensaver/xautolock_engine.c
@@ -0,0 +1,137 @@
+/*****************************************************************************
+ *
+ * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT)
+ *
+ * Content: This file is part of version 2.x of xautolock. It implements
+ *          the program's core functions.
+ *
+ *          Please send bug reports etc. to eyckmans@imec.be.
+ *
+ * --------------------------------------------------------------------------
+ * 
+ * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans.
+ * 
+ * Versions 2.0 and above of xautolock are available under version 2 of the
+ * GNU GPL. Earlier versions are available under other conditions. For more
+ * information, see the License file.
+ * 
+ *****************************************************************************/
+
+#include "xautolock_c.h"
+
+/*
+ *  Function for monitoring pointer movements. This implements the 
+ *  `corners' feature and as a side effect also tracks pointer 
+ *  related user activity. The latter actually is only needed when
+ *  we're using the DIY mode of operations, but it's much simpler
+ *  to do it unconditionally.
+ */
+void 
+xautolock_queryPointer (Display* d)
+{
+  Window           dummyWin;         /* as it says                    */
+  int              dummyInt;         /* as it says                    */
+  unsigned         mask;             /* modifier mask                 */
+  int              rootX;            /* as it says                    */
+  int              rootY;            /* as it says                    */
+  int              corner;           /* corner index                  */
+  int              i;                /* loop counter                  */
+  static Window    root;             /* root window the pointer is on */
+  static Screen*   screen;           /* screen the pointer is on      */
+  static unsigned  prevMask = 0;     /* as it says                    */
+  static int       prevRootX = -1;   /* as it says                    */
+  static int       prevRootY = -1;   /* as it says                    */
+  static Bool      firstCall = True; /* as it says                    */
+
+ /*
+  *  Have a guess...
+  */
+  if (firstCall)
+  {
+    firstCall = False;
+    root = DefaultRootWindow (d);
+    screen = ScreenOfDisplay (d, DefaultScreen (d));
+  }
+
+ /*
+  *  Find out whether the pointer has moved. Using XQueryPointer for this
+  *  is gross, but it also is the only way never to mess up propagation
+  *  of pointer events.
+  */
+  if (!XQueryPointer (d, root, &root, &dummyWin, &rootX, &rootY,
+                      &dummyInt, &dummyInt, &mask))
+  {
+   /*
+    *  Pointer has moved to another screen, so let's find out which one.
+    */
+    for (i = -1; ++i < ScreenCount (d); ) 
+    {
+      if (root == RootWindow (d, i)) 
+      {
+        screen = ScreenOfDisplay (d, i);
+        break;
+      }
+    }
+  }
+
+  if (   rootX == prevRootX
+      && rootY == prevRootY
+      && mask == prevMask)
+  {
+  xautolock_corner_t* corners = xautolock_corners;
+   /*
+    *  If the pointer has not moved since the previous call and 
+    *  is inside one of the 4 corners, we act according to the
+    *  contents of the "corners" array.
+    *
+    *  If rootX and rootY are less than zero, don't lock even if
+    *  ca_forceLock is set in the upper-left corner. Why? 'cause
+    *  on initial server startup, if (and only if) the pointer is
+    *  never moved, XQueryPointer() can return values less than 
+    *  zero (only some servers, Openwindows 2.0 and 3.0 in 
+    *  particular).
+    */
+    if (   (corner = 0,
+               rootX <= cornerSize && rootX >= 0
+            && rootY <= cornerSize && rootY >= 0)
+        || (corner++,
+               rootX >= WidthOfScreen  (screen) - cornerSize - 1
+            && rootY <= cornerSize)
+        || (corner++,
+               rootX <= cornerSize
+            && rootY >= HeightOfScreen (screen) - cornerSize - 1)
+        || (corner++,
+               rootX >= WidthOfScreen  (screen) - cornerSize - 1
+            && rootY >= HeightOfScreen (screen) - cornerSize - 1))
+    {
+      switch (corners[corner])
+      {
+        case ca_forceLock:
+#if 0
+          xautolock_setTrigger( (useRedelay ? cornerRedelay : cornerDelay) - 1 );
+#else
+          xautolock_setTrigger( 0 );
+#endif
+          break;
+
+        case ca_dontLock:
+          xautolock_resetTriggers ();
+
+#ifdef __GNUC__
+        default: ; /* Makes gcc -Wall shut up. */
+#endif /* __GNUC__ */
+      }
+    }
+  }
+  else
+  {
+#if 0
+    useRedelay = False;
+#endif
+    prevRootX = rootX;
+    prevRootY = rootY;
+    prevMask = mask;
+
+    xautolock_resetTriggers ();
+  }
+}
diff --git a/kwin/useractions.cpp b/kwin/useractions.cpp
index d969def..7eba1c5 100644
--- a/kwin/useractions.cpp
+++ b/kwin/useractions.cpp
@@ -32,6 +32,7 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "effects.h"
 #include "tile.h"
 #include "tilinglayout.h"
+#include "screenlocker/screenlocker.h"
 
 #include "kactivityinfo.h"
 
@@ -564,6 +565,8 @@ void Workspace::readShortcuts()
 {
     // TODO: PORT ME (KGlobalAccel related)
     //KGlobalAccel::self()->readSettings();
+    keys = new KActionCollection(this);
+    KActionCollection* actionCollection = keys;
 
     KAction *kaction = qobject_cast<KAction*>(keys->action("Walk Through \
Desktops"));  if (kaction != 0) {
@@ -626,6 +629,7 @@ void Workspace::readShortcuts()
         cutWalkThroughWindowsAlternativeReverse = kaction->globalShortcut();
         connect(kaction, SIGNAL(globalShortcutChanged(QKeySequence)), this, \
SLOT(slotWalkBackThroughWindowsAlternativeKeyChanged(QKeySequence)));  }
+    m_screenLocker->initShortcuts(actionCollection);
     discardPopup(); // so that it's recreated next time
 }
 
diff --git a/kwin/workspace.cpp b/kwin/workspace.cpp
index 19508be..19cc1c3 100644
--- a/kwin/workspace.cpp
+++ b/kwin/workspace.cpp
@@ -61,6 +61,7 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "tilinglayout.h"
 
 #include "scripting/scripting.h"
+#include "screenlocker/screenlocker.h"
 
 #include <X11/extensions/shape.h>
 #include <X11/keysym.h>
@@ -161,6 +162,7 @@ Workspace::Workspace(bool restore)
     , transButton(NULL)
     , forceUnredirectCheck(true)
     , m_finishingCompositing(false)
+    , m_screenLocker(NULL)
 {
     (void) new KWinAdaptor(this);
 
@@ -223,6 +225,8 @@ Workspace::Workspace(bool restore)
     // need to create the tabbox before compositing scene is setup
     tab_box = new TabBox::TabBox(this);
     setupCompositing();
+    // ScreenLocker needs to be created after compositing
+    m_screenLocker = new ScreenLocker::ScreenLocker(this);
 
     // Compatibility
     long data = 1;
diff --git a/kwin/workspace.h b/kwin/workspace.h
index 83e1591..ba6ff53 100644
--- a/kwin/workspace.h
+++ b/kwin/workspace.h
@@ -41,7 +41,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "sm.h"
 
 #include <X11/Xlib.h>
-
 // TODO: Cleanup the order of things in this .h file
 
 class QMenu;
@@ -61,6 +60,10 @@ namespace Kephal
 }
 namespace KWin
 {
+namespace ScreenLocker
+{
+class ScreenLocker;
+}
 
 namespace TabBox
 {
@@ -450,6 +453,7 @@ public:
     bool rulesUpdatesDisabled() const;
 
     bool hasDecorationShadows() const;
+    Qt::Corner decorationCloseButtonCorner();
     bool decorationHasAlpha() const;
     bool decorationSupportsClientGrouping() const; // Returns true if the decoration \
supports tabs.  bool decorationSupportsFrameOverlap() const;
@@ -560,6 +564,13 @@ public:
 
     void raiseElectricBorderWindows();
 
+    ScreenLocker::ScreenLocker *screenLocker() {
+        return m_screenLocker;
+    }
+    const ScreenLocker::ScreenLocker *screenLocker() const {
+        return m_screenLocker;
+    }
+
 public slots:
     void addRepaintFull();
     void refresh();
@@ -1049,6 +1060,8 @@ private:
     QTimer compositeResetTimer; // for compressing composite resets
     bool m_finishingCompositing; // finishCompositing() sets this variable while \
shutting down  
+    ScreenLocker::ScreenLocker *m_screenLocker;
+
 private:
     friend bool performTransiencyCheck();
 };
@@ -1329,6 +1342,14 @@ inline bool Workspace::hasDecorationShadows() const
     return mgr->factory()->supports(AbilityProvidesShadow);
 }
 
+inline Qt::Corner Workspace::decorationCloseButtonCorner()
+{
+    if (!hasDecorationPlugin()) {
+        return Qt::TopRightCorner;
+    }
+    return mgr->factory()->closeButtonCorner();
+}
+
 inline bool Workspace::decorationHasAlpha() const
 {
     if (!hasDecorationPlugin()) {



_______________________________________________
Active mailing list
Active@kde.org
https://mail.kde.org/mailman/listinfo/active


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic