<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">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 &lt;http://www.gnu.org/licenses/&gt;.
 #include "tabbox.h"
 #include "workspace.h"
 #include "kwinglutils.h"
+#include "screenlocker/screenlocker.h"
 
 #include &lt;QFile&gt;
 
@@ -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()-&gt;decorationCloseButtonCorner();
+    }
+    return QVariant(); // an invalid one
+}
+
 void EffectsHandlerImpl::slotShowOutline(const QRect&amp; 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()-&gt;screenLocker()-&gt;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&amp; 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&lt;EffectWindow*&gt; 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&lt; Effect* &gt; m_activeEffects;
+    QList&lt; Effect* &gt;::iterator m_currentDrawWindowIterator;
+    QList&lt; Effect* &gt;::iterator m_currentPaintWindowIterator;
+    QList&lt; Effect* &gt;::iterator m_currentPaintEffectFrameIterator;
+    QList&lt; Effect* &gt;::iterator m_currentPaintScreenIterator;
+    QList&lt; Effect* &gt;::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 &amp;d
         } else if (winData-&gt;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-&gt;highlight = qMin(1.0, winData-&gt;highlight + time / m_fadeDuration);
+        else if (!isInMotion &amp;&amp; w-&gt;isDesktop())
+            winData-&gt;highlight = 0.3;
         else
             winData-&gt;highlight = qMax(0.0, winData-&gt;highlight - time / m_fadeDuration);
 
@@ -317,7 +320,7 @@ void PresentWindowsEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &amp;d
         if (w-&gt;isDesktop() &amp;&amp; !w-&gt;isOnCurrentDesktop())
             w-&gt;disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
 
-        if (m_motionManager.isManaging(w))
+        if (isInMotion)
             data.setTransformed(); // We will be moving this window
     }
     effects-&gt;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-&gt;opacity;
-        data.brightness *= interpolate(0.7, 1.0, winData-&gt;highlight);
+        data.brightness *= interpolate(0.40, 1.0, winData-&gt;highlight);
 
         if (m_motionManager.isManaging(w)) {
+            if (w-&gt;isDesktop())
+                effects-&gt;paintWindow(w, mask, region, data);
             m_motionManager.apply(w, data);
+            QRect rect = m_motionManager.transformedGeometry(w).toRect();
+
+            if (winData-&gt;highlight &gt; 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-&gt;clientArea(FullScreenArea, w);
+                QSizeF effSize(w-&gt;width()*data.xScale, w-&gt;height()*data.yScale);
+                float tScale = sqrt((area.width()*area.height()) / (16.0*effSize.width()*effSize.height()));
+                if (tScale &lt; 1.05)
+                    tScale = 1.05;
+                if (effSize.width()*tScale &gt; area.width())
+                    tScale = area.width() / effSize.width();
+                if (effSize.height()*tScale &gt; area.height())
+                    tScale = area.height() / effSize.height();
+                const float scale = interpolate(1.0, tScale, winData-&gt;highlight);
+                if (scale &gt; 1.0) {
+                    if (scale &lt; tScale) // don't use lanczos during transition
+                        mask &amp;= ~PAINT_WINDOW_LANCZOS;
+
+                    const QPoint ac = area.center();
+                    const QPoint wc = rect.center();
+
+                    data.xScale *= scale;
+                    data.yScale *= scale;
+                    const int tx = -w-&gt;width()*data.xScale*(scale-1.0)*(0.5+(wc.x() - ac.x())/area.width());
+                    const int ty = -w-&gt;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 &amp;= ~PAINT_WINDOW_LANCZOS;
             }
             if (m_dragInProgress &amp;&amp; m_dragWindow == w) {
                 QPoint diff = cursorPos() - m_dragStart;
@@ -350,7 +388,7 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, QRegion region
             }
             effects-&gt;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-&gt;isVisible()) {
             const QPoint widgetPos = m_closeView-&gt;mapFromGlobal(me-&gt;pos());
-            const QPointF scenePos = m_closeView-&gt;mapToScene(widgetPos);
+//             const QPointF scenePos = m_closeView-&gt;mapToScene(widgetPos);
             QMouseEvent event(me-&gt;type(), widgetPos, me-&gt;pos(), me-&gt;button(), me-&gt;buttons(), me-&gt;modifiers());
             m_closeView-&gt;windowInputMouseEvent(&amp;event);
             return;
@@ -1546,6 +1584,7 @@ void PresentWindowsEffect::setActive(bool active, bool closingTab)
     }
     m_activated = active;
     if (m_activated) {
+        m_closeButtonCorner = (Qt::Corner)effects-&gt;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-&gt;setElevatedWindow(m_highlightedWindow, false);
         // Fade in/out all windows
         EffectWindow *activeWindow = effects-&gt;activeWindow();
         if (m_tabBoxEnabled)
@@ -1752,32 +1793,65 @@ void PresentWindowsEffect::setHighlightedWindow(EffectWindow *w)
         return;
 
     m_closeView-&gt;hide();
-    if (m_highlightedWindow)
+    if (m_highlightedWindow) {
+        effects-&gt;setElevatedWindow(m_highlightedWindow, false);
         m_highlightedWindow-&gt;addRepaintFull(); // Trigger the first repaint
+    }
     m_highlightedWindow = w;
-    if (m_highlightedWindow)
+    if (m_highlightedWindow) {
+        effects-&gt;setElevatedWindow(m_highlightedWindow, true);
         m_highlightedWindow-&gt;addRepaintFull(); // Trigger the first repaint
+    }
 
     if (m_tabBoxEnabled &amp;&amp; m_highlightedWindow)
         effects-&gt;setTabBoxWindow(w);
     updateCloseWindow();
 }
 
+void PresentWindowsEffect::elevateCloseWindow()
+{
+    if (EffectWindow *cw = effects-&gt;findWindow(m_closeView-&gt;winId()))
+            effects-&gt;setElevatedWindow(cw, true);
+}
+
 void PresentWindowsEffect::updateCloseWindow()
 {
     if (m_doNotCloseWindows)
         return;
+    if (!m_highlightedWindow || m_highlightedWindow-&gt;isDesktop()) {
+        m_closeView-&gt;hide();
+        return;
+    }
     if (m_closeView-&gt;isVisible())
         return;
-    if (!m_highlightedWindow) {
+
+    const QRectF rect(m_motionManager.targetGeometry(m_highlightedWindow));
+    if (2*m_closeView-&gt;sceneRect().width() &gt; rect.width() &amp;&amp; 2*m_closeView-&gt;sceneRect().height() &gt; rect.height()) {
+        // not for tiny windows (eg. with many windows) - they might become unselectable
         m_closeView-&gt;hide();
         return;
     }
-    const QRectF rect = m_motionManager.targetGeometry(m_highlightedWindow);
-    m_closeView-&gt;setGeometry(rect.x() + rect.width() - m_closeView-&gt;sceneRect().width(), rect.y(),
-                             m_closeView-&gt;sceneRect().width(), m_closeView-&gt;sceneRect().height());
-    if (rect.contains(effects-&gt;cursorPos()))
-        m_closeView-&gt;delayedShow();
+    QRect cvr(QPoint(0,0), m_closeView-&gt;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-&gt;setGeometry(cvr);
+    if (rect.contains(effects-&gt;cursorPos())) {
+        m_closeView-&gt;show();
+        m_closeView-&gt;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-&gt;hide();
 }
@@ -1972,7 +2046,7 @@ void PresentWindowsEffect::globalShortcutChangedClass(const QKeySequence&amp; 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-&gt;setSceneRect(QRectF(QPointF(0, 0), QSizeF(width, height)));
     setScene(scene);
 
-    // setup the timer
-    m_delayedShowTimer-&gt;setSingleShot(true);
-    m_delayedShowTimer-&gt;setInterval(500);
-    connect(m_delayedShowTimer, SIGNAL(timeout()), SLOT(show()));
+    // setup the timer - attempt to prevent accidental clicks
+    m_armTimer-&gt;setSingleShot(true);
+    m_armTimer-&gt;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-&gt;isActive())
+    if (!isEnabled())
         return;
     if (e-&gt;type() == QEvent::MouseMove) {
         mouseMoveEvent(e);
@@ -2041,17 +2115,15 @@ void CloseWindowView::drawBackground(QPainter* painter, const QRectF&amp; rect)
     m_frame-&gt;paintFrame(painter);
 }
 
-void CloseWindowView::hide()
+void CloseWindowView::arm()
 {
-    m_delayedShowTimer-&gt;stop();
-    QWidget::hide();
+    setEnabled(true);
 }
 
-void CloseWindowView::delayedShow()
+void CloseWindowView::disarm()
 {
-    if (isVisible() || m_delayedShowTimer-&gt;isActive())
-        return;
-    m_delayedShowTimer-&gt;start();
+    setEnabled(false);
+    m_armTimer-&gt;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&amp; 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 &lt;asouza@kde.org&gt;                  *
+ *                                                                         *
+ *   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 &gt; unlockArea.x &amp;&amp; lockerImage.y &gt; unlockArea.y);
+                var size = (lockerImage.x &lt; unlockArea.width &amp;&amp; lockerImage.y &lt; unlockArea.height);
+
+                if (pos &amp;&amp; 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 &lt;mgraesslin@kde.org&gt;
+
+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 &lt;http://www.gnu.org/licenses/&gt;.
+*********************************************************************/
+#include "screenlocker.h"
+#include &lt;QKeyEvent&gt;
+#include &lt;QMouseEvent&gt;
+#include &lt;QDeclarativeView&gt;
+#include &lt;QDeclarativeEngine&gt;
+#include &lt;QGraphicsObject&gt;
+#include &lt;KStandardDirs&gt;
+#ifdef KWIN_HAVE_OPENGL
+#include &lt;kwinglutils.h&gt;
+#endif
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+#include &lt;kwinxrenderutils.h&gt;
+#endif
+#include &lt;kdeclarative.h&gt;
+
+namespace KWin
+{
+
+KWIN_EFFECT(screenlocker, ScreenLockerEffect)
+
+class EffectDeclarativeView : public QDeclarativeView
+{
+public:
+    void windowInputMouseEvent(QEvent *e)
+    {
+        QMouseEvent *ev = static_cast&lt;QMouseEvent *&gt;(e);
+
+        if (e-&gt;type() == QEvent::MouseMove) {
+            mouseMoveEvent(ev);
+        } else if (e-&gt;type() == QEvent::MouseButtonPress) {
+            mousePressEvent(ev);
+        } else if (e-&gt;type() == QEvent::MouseButtonDblClick) {
+            mouseDoubleClickEvent(ev);
+        } else if (e-&gt;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 &amp;importPath, KGlobal::dirs()-&gt;findDirs("module", "imports")) {
+        m_declarativeView-&gt;engine()-&gt;addImportPath(importPath);
+    }
+    KDeclarative kdeclarative;
+    kdeclarative.setDeclarativeEngine(m_declarativeView-&gt;engine());
+    kdeclarative.initialize();
+    //binds things like kconfig and icons
+    kdeclarative.setupBindings();
+    m_declarativeView-&gt;setSource(QUrl(KStandardDirs::locate("data", "kwin/lockscreen/main.qml")));
+    m_declarativeView-&gt;setResizeMode(QDeclarativeView::SizeRootObjectToView);
+    m_declarativeView-&gt;setWindowFlags(Qt::X11BypassWindowManagerHint);
+    m_declarativeView-&gt;setAttribute(Qt::WA_TranslucentBackground);
+    m_declarativeView-&gt;setFrameShape(QFrame::NoFrame);
+
+    connect(m_declarativeView-&gt;rootObject(), SIGNAL(unlockRequested()), this, SLOT(slotRequestUnlock()));
+    //m_declarativeView-&gt;hide();
+}
+
+ScreenLockerEffect::~ScreenLockerEffect()
+{
+    delete m_declarativeView;
+}
+
+void ScreenLockerEffect::paintScreen(int mask, QRegion region, ScreenPaintData &amp;data)
+{
+    effects-&gt;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-&gt;compositingType() == OpenGLCompositing) {
+            paintGL();
+        } else if (effects-&gt;compositingType() == XRenderCompositing) {
+            paintXrender();
+        }
+        EffectWindow *w = effects-&gt;findWindow(m_declarativeView-&gt;winId());
+        if (w) {
+            WindowPaintData d(w);
+            effects-&gt;drawWindow(w, PAINT_WINDOW_OPAQUE, infiniteRegion(), d);
+        }
+    }
+}
+
+void ScreenLockerEffect::paintGL()
+{
+#ifdef KWIN_HAVE_OPENGL
+    GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
+    vbo-&gt;reset();
+    vbo-&gt;setUseColor(true);
+    if (ShaderManager::instance()-&gt;isValid()) {
+        ShaderManager::instance()-&gt;pushShader(ShaderManager::ColorShader);
+    }
+    vbo-&gt;setColor(Qt::black);
+    QVector&lt;float&gt; verts;
+    const QRect r(0, 0, displayWidth(), displayHeight());
+    verts.reserve(12);
+    verts &lt;&lt; r.x() + r.width() &lt;&lt; r.y();
+    verts &lt;&lt; r.x() &lt;&lt; r.y();
+    verts &lt;&lt; r.x() &lt;&lt; r.y() + r.height();
+    verts &lt;&lt; r.x() &lt;&lt; r.y() + r.height();
+    verts &lt;&lt; r.x() + r.width() &lt;&lt; r.y() + r.height();
+    verts &lt;&lt; r.x() + r.width() &lt;&lt; r.y();
+    vbo-&gt;setData(6, 2, verts.data(), NULL);
+    vbo-&gt;render(GL_TRIANGLES);
+    if (ShaderManager::instance()-&gt;isValid()) {
+        ShaderManager::instance()-&gt;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-&gt;xrenderBufferPicture(),
+                         &amp;col, 0, 0, displayWidth(), displayHeight());
+#endif
+}
+
+void ScreenLockerEffect::slotRequestLock()
+{
+    if (!effects-&gt;isScreenLockerReferenced()) {
+        m_declarativeView-&gt;setGeometry(effects-&gt;clientArea(FullScreenArea, effects-&gt;activeScreen(), effects-&gt;currentDesktop()));
+        m_declarativeView-&gt;show(); 
+        // create input window and grab mouse
+        Window w = effects-&gt;createFullScreenInputWindow(this, Qt::PointingHandCursor);
+        if (!w) {
+            return;
+        }
+        if (!effects-&gt;grabKeyboard(this)) {
+            effects-&gt;destroyInputWindow(w);
+            return;
+        }
+        effects-&gt;refScreenLocker(this);
+        effects-&gt;setActiveFullScreenEffect(this);
+        m_locked = true;
+        m_inputWindow = w;
+        
+        effects-&gt;addRepaintFull();
+    }
+}
+
+void ScreenLockerEffect::grabbedKeyboardEvent(QKeyEvent *e)
+{
+    if (!m_locked) {
+        return;
+    }
+    // TODO: implement a proper unlock behavior
+    if (e-&gt;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&lt; QMouseEvent* &gt;(e);
+    QMouseEvent event(me-&gt;type(), me-&gt;pos(), me-&gt;pos(), me-&gt;button(), me-&gt;buttons(), me-&gt;modifiers());
+    m_declarativeView-&gt;windowInputMouseEvent(&amp;event);
+    // TODO: implement proper behavior by triggering the unlock screen
+}
+
+void ScreenLockerEffect::doUnlock()
+{
+    m_locked = false;
+    effects-&gt;destroyInputWindow(m_inputWindow);
+    m_inputWindow = 0;
+    effects-&gt;setActiveFullScreenEffect(NULL);
+    effects-&gt;ungrabKeyboard();
+    effects-&gt;unrefScreenLocker(this);
+    m_declarativeView-&gt;hide();
+    effects-&gt;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 &lt;mgraesslin@kde.org&gt;
+
+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 &lt;http://www.gnu.org/licenses/&gt;.
+*********************************************************************/
+#ifndef KWIN_SCREENLOCKER_EFFECT_H
+#define KWIN_SCREENLOCKER_EFFECT_H
+#include &lt;kwineffects.h&gt;
+
+
+namespace KWin
+{
+
+class EffectDeclarativeView;
+
+class ScreenLockerEffect : public Effect
+{
+    Q_OBJECT
+public:
+    ScreenLockerEffect();
+    virtual ~ScreenLockerEffect();
+    virtual void paintScreen(int mask, QRegion region, ScreenPaintData &amp;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&lt; KDecoration* &gt;(deco));
 }
 
+Qt::Corner KDecorationFactory::closeButtonCorner()
+{
+    if (d-&gt;closeButtonCorner)
+        return d-&gt;closeButtonCorner;
+    return options()-&gt;titleButtonsLeft().contains('X') ? Qt::TopLeftCorner : Qt::TopRightCorner;
+}
+
+void KDecorationFactory::setCloseButtonCorner(Qt::Corner cnr)
+{
+    d-&gt;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 &amp; 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 ) &lt;&lt; 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&amp; data) = 0;
     virtual void buildQuads(EffectWindow* w, WindowQuadList&amp; 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&amp; 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&lt; EffectPair &gt; 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 @@
+&lt;!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"&gt;
+&lt;node&gt;
+  &lt;interface name="org.freedesktop.ScreenSaver"&gt;
+    &lt;signal name="ActiveChanged"&gt;
+      &lt;arg type="b"/&gt;
+    &lt;/signal&gt;
+    &lt;method name="Lock"&gt;
+    &lt;/method&gt;
+    &lt;method name="SimulateUserActivity"&gt;
+    &lt;/method&gt;
+    &lt;method name="GetActive"&gt;
+      &lt;arg type="b" direction="out"/&gt;
+    &lt;/method&gt;
+    &lt;method name="GetActiveTime"&gt;
+      &lt;arg name="seconds" type="u" direction="out"/&gt;
+    &lt;/method&gt;
+    &lt;method name="GetSessionIdleTime"&gt;
+      &lt;arg name="seconds" type="u" direction="out"/&gt;
+    &lt;/method&gt;
+    &lt;method name="SetActive"&gt;
+      &lt;arg type="b" direction="out"/&gt;
+      &lt;arg name="e" type="b" direction="in"/&gt;
+    &lt;/method&gt;
+    &lt;method name="Inhibit"&gt;
+      &lt;arg name="application_name" type="s" direction="in"/&gt;
+      &lt;arg name="reason_for_inhibit" type="s" direction="in"/&gt;
+      &lt;arg name="cookie" type="u" direction="out"/&gt;
+    &lt;/method&gt;
+    &lt;method name="UnInhibit"&gt;
+      &lt;arg name="cookie" type="u" direction="in"/&gt;
+    &lt;/method&gt;
+    &lt;method name="Throttle"&gt;
+      &lt;arg name="application_name" type="s" direction="in"/&gt;
+      &lt;arg name="reason_for_inhibit" type="s" direction="in"/&gt;
+      &lt;arg name="cookie" type="u" direction="out"/&gt;
+    &lt;/method&gt;
+    &lt;method name="UnThrottle"&gt;
+      &lt;arg name="cookie" type="u" direction="in"/&gt;
+    &lt;/method&gt;
+  &lt;/interface&gt;
+&lt;/node&gt;
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 @@
+&lt;!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"&gt;
+&lt;node&gt;
+  &lt;interface name="org.kde.screensaver"&gt;
+    &lt;!-- start in plasma setup mode --&gt;
+    &lt;method name="setupPlasma" /&gt;
+    &lt;!-- Re-read configuration --&gt;
+    &lt;method name="configure" /&gt;
+    &lt;!-- Private API. Don't use. --&gt;
+    &lt;method name="saverLockReady" /&gt;
+  &lt;/interface&gt;
+&lt;/node&gt;
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 @@
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;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" &gt;
+  &lt;include&gt;kglobalsettings.h&lt;/include&gt;
+  &lt;kcfgfile name="kscreensaverrc" /&gt;
+  &lt;group name="ScreenSaver"&gt;
+    &lt;entry name="ScreenSaverEnabled" key="Enabled" type="Bool"&gt;
+      &lt;default&gt;false&lt;/default&gt;
+      &lt;label&gt;Enable screen saver&lt;/label&gt;
+      &lt;whatsthis&gt;Enables the screen saver.&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="Timeout" type="Int"&gt;
+      &lt;default&gt;300&lt;/default&gt;
+      &lt;label&gt;Screen saver timeout&lt;/label&gt;
+      &lt;whatsthis&gt;Sets the seconds after which the screen saver is started.&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry name="SuspendWhenInvisible" key="SuspendWhenInvisible" type="Bool"&gt;
+      &lt;default&gt;true&lt;/default&gt;
+      &lt;label&gt;Suspend screen saver when DPMS kicks in&lt;/label&gt;
+      &lt;whatsthis&gt;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.&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="ActionTopLeft" type="Int"&gt;
+      &lt;default&gt;0&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="ActionTopRight" type="Int"&gt;
+      &lt;default&gt;0&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="ActionBottomLeft" type="Int"&gt;
+      &lt;default&gt;0&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="ActionBottomRight" type="Int"&gt;
+      &lt;default&gt;0&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="Lock" type="Bool"&gt;
+      &lt;default&gt;false&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="LockGrace" type="Int"&gt;
+      &lt;default&gt;5000&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="AutoLogout" type="Bool"&gt;
+      &lt;default&gt;false&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="AutoLogoutTimeout" type="Int"&gt;
+      &lt;default&gt;600&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="Priority" type="Int"&gt;
+      &lt;default&gt;19&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="Saver" type="String"&gt;
+      &lt;default&gt;&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="PluginsUnlock" type="StringList"&gt;
+      &lt;default&gt;&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="PluginOptions" type="StringList"&gt;
+      &lt;default&gt;&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+    &lt;entry key="PlasmaEnabled" type="Bool"&gt;
+      &lt;default&gt;false&lt;/default&gt;
+      &lt;label&gt;&lt;/label&gt;
+      &lt;whatsthis&gt;&lt;/whatsthis&gt;
+    &lt;/entry&gt;
+  &lt;/group&gt;
+&lt;/kcfg&gt;
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 &lt;howells@kde.org&gt;
+
+#include "lockprocess.h"
+#include "autologout.h"
+
+#include &lt;kapplication.h&gt;
+#include &lt;klocale.h&gt;
+#include &lt;kglobalsettings.h&gt;
+#include &lt;kconfig.h&gt;
+#include &lt;kiconloader.h&gt;
+#include &lt;kdebug.h&gt;
+#include &lt;kmessagebox.h&gt;
+#include &lt;kdialog.h&gt;
+#include &lt;ksmserver_interface.h&gt;
+
+#include &lt;QLayout&gt;
+#include &lt;QMessageBox&gt;
+#include &lt;QLabel&gt;
+#include &lt;QStyle&gt;
+#include &lt;QApplication&gt;
+#include &lt;QDialog&gt;
+#include &lt;QAbstractEventDispatcher&gt;
+#include &lt;QtGui/QProgressBar&gt;
+#include &lt;QtDBus/QtDBus&gt;
+
+#define COUNTDOWN 30
+
+AutoLogout::AutoLogout(LockProcess *parent) : QDialog(parent, Qt::X11BypassWindowManagerHint)
+{
+    QLabel *pixLabel = new QLabel( this );
+    pixLabel-&gt;setObjectName( QLatin1String( "pixlabel" ) );
+    pixLabel-&gt;setPixmap(DesktopIcon(QLatin1String( "application-exit" )));
+
+    QLabel *greetLabel = new QLabel(i18n("&lt;qt&gt;&lt;nobr&gt;&lt;b&gt;Automatic Log Out&lt;/b&gt;&lt;/nobr&gt;&lt;/qt&gt;"), this);
+    QLabel *infoLabel = new QLabel(i18n("&lt;qt&gt;To prevent being logged out, resume using this session by moving the mouse or pressing a key.&lt;/qt&gt;"), this);
+
+    mStatusLabel = new QLabel(QLatin1String( "&lt;b&gt; &lt;/b&gt;" ), this);
+    mStatusLabel-&gt;setAlignment(Qt::AlignCenter);
+
+    QLabel *mProgressLabel = new QLabel(i18n("Time Remaining:"), this);
+    mProgressRemaining = new QProgressBar(this);
+    mProgressRemaining-&gt;setTextVisible(false);
+
+    frameLayout = new QGridLayout(this);
+    frameLayout-&gt;setSpacing(KDialog::spacingHint());
+    frameLayout-&gt;setMargin(KDialog::marginHint() * 2);
+    frameLayout-&gt;addWidget(pixLabel, 0, 0, 3, 1, Qt::AlignCenter | Qt::AlignTop);
+    frameLayout-&gt;addWidget(greetLabel, 0, 1);
+    frameLayout-&gt;addWidget(mStatusLabel, 1, 1);
+    frameLayout-&gt;addWidget(infoLabel, 2, 1);
+    frameLayout-&gt;addWidget(mProgressLabel, 3, 1);
+    frameLayout-&gt;addWidget(mProgressRemaining, 4, 1);
+
+    // get the time remaining in seconds for the status label
+    mRemaining = COUNTDOWN * 25;
+
+    mProgressRemaining-&gt;setMaximum(COUNTDOWN * 25);
+
+    updateInfo(mRemaining);
+
+    mCountdownTimerId = startTimer(1000/25);
+
+    connect(qApp, SIGNAL(activity()), SLOT(slotActivity()));
+}
+
+AutoLogout::~AutoLogout()
+{
+    hide();
+}
+
+void AutoLogout::updateInfo(int timeout)
+{
+    mStatusLabel-&gt;setText(i18np("&lt;qt&gt;&lt;nobr&gt;You will be automatically logged out in 1 second&lt;/nobr&gt;&lt;/qt&gt;",
+                               "&lt;qt&gt;&lt;nobr&gt;You will be automatically logged out in %1 seconds&lt;/nobr&gt;&lt;/qt&gt;",
+                               timeout / 25) );
+    mProgressRemaining-&gt;setValue(timeout);
+}
+
+void AutoLogout::timerEvent(QTimerEvent *ev)
+{
+    if (ev-&gt;timerId() == mCountdownTimerId)
+    {
+        updateInfo(mRemaining);
+        --mRemaining;
+        if (mRemaining &lt; 0)
+        {
+            killTimer(mCountdownTimerId);
+            logout();
+        }
+    }
+}
+
+void AutoLogout::slotActivity()
+{
+    if (mRemaining &gt;= 0)
+        accept();
+}
+
+void AutoLogout::logout()
+{
+    QAbstractEventDispatcher::instance()-&gt;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 &lt;mjones@kde.org&gt;
+// Copyright 2003 Oswald Buddenhagen &lt;ossi@kde.org&gt;
+// Copyright 2004 Chris Howells &lt;howells@kde.org&gt;
+
+#ifndef AUTOLOGOUT_H
+#define AUTOLOGOUT_H
+
+#include &lt;QLayout&gt;
+
+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]=Å&nbsp;etÅ™iÄ obrazovky
+Comment[da]=PauseskÃ¦rm
+Comment[de]=Bildschirmschoner
+Comment[el]=Î&nbsp;ÏÎ¿Ï†ÏÎ»Î±Î¾Î· Î¿Î¸ÏŒÎ½Î·Ï‚
+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]=Å&nbsp;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]=à¹‚à¸›à¸£à¹à¸à¸£à¸¡à¸£à¸±à¸à¸©à¸²à¸ˆà¸­à¸&nbsp;à¸²à¸ž
+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]=Å&nbsp;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]=Å&nbsp;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]=à¹‚à¸›à¸£à¹à¸à¸£à¸¡à¸£à¸±à¸à¸©à¸²à¸ˆà¸­à¸&nbsp;à¸²à¸žà¹€à¸£à¸´à¹ˆà¸¡à¸—à¸³à¸‡à¸²à¸™à¹à¸¥à¹‰à¸§
+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]=Å&nbsp;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]=Å&nbsp;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]=à¹‚à¸›à¸£à¹à¸à¸£à¸¡à¸£à¸±à¸à¸©à¸²à¸ˆà¸­à¸&nbsp;à¸²à¸žà¹€à¸£à¸´à¹ˆà¸¡à¸à¸²à¸£à¸—à¸³à¸‡à¸²à¸™à¹à¸¥à¹‰à¸§
+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]=×ž×¡×š ×&nbsp;×¢×•×œ
+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]=í™”ë©´ ìž&nbsp;ê¹€
+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]=×”×ž×¡×š ×&nbsp;×&nbsp;×¢×œ
+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]=í™”ë©´ ìž&nbsp;ê¹€
+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]=Å&nbsp;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]=Å&nbsp;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]=à¹‚à¸›à¸£à¹à¸à¸£à¸¡à¸£à¸±à¸à¸©à¸²à¸ˆà¸­à¸&nbsp;à¸²à¸žà¸ˆà¸šà¸à¸²à¸£à¸—à¸³à¸‡à¸²à¸™à¹à¸¥à¹‰à¸§
+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]=Å&nbsp;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]=Å&nbsp;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]=à¹‚à¸›à¸£à¹à¸à¸£à¸¡à¸£à¸±à¸à¸©à¸²à¸ˆà¸­à¸&nbsp;à¸²à¸žà¸—à¸³à¸‡à¸²à¸™à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸´à¹‰à¸™à¹à¸¥à¹‰à¸§
+Comment[tr]=Ekran koruyucu bitti
+Comment[ug]=Ø¦ÛÙƒØ±Ø§Ù† Ù‚ÙˆØºØ¯Ù‰ØºÛ‡Ú† Ø¦Ø§Ø®Ù‰Ø±Ù„Ø§Ø´ØªÙ‰
+Comment[uk]=Ð&nbsp;Ð¾Ð±Ð¾Ñ‚Ñƒ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ñ‡Ð° ÐµÐºÑ€Ð°Ð½Ð° Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¾
+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]=í™”ë©´ ìž&nbsp;ê¸ˆ í’€ë¦¼
+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]=í™”ë©´ ìž&nbsp;ê¸ˆ í’€ë¦¼
+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]=×©×™×—×¨×•×¨ ×”×ž×¡×š ×&nbsp;×›×©×œ
+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]=í™”ë©´ ìž&nbsp;ê¸ˆ í’€ë¦¬ì§€ ì•ŠìŒ
+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]=×&nbsp;×™×¡×™×•×Ÿ ×›×•×©×œ ×œ×©×™×—×¨×•×¨ ×”×ž×¡×š
+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]=í™”ë©´ ìž&nbsp;ê¸ˆ í’€ë¦¬ì§€ ì•ŠìŒ
+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 &lt;mjones@kde.org&gt;
+// Copyright 2003 Chris Howells &lt;howells@kde.org&gt;
+// Copyright 2003 Oswald Buddenhagen &lt;ossi@kde.org&gt;
+
+#include &lt;config-unix.h&gt; // HAVE_PAM
+
+#include "lockprocess.h"
+#include "lockdlg.h"
+
+#include &lt;kcheckpass-enums.h&gt;
+#include &lt;kworkspace/kdisplaymanager.h&gt;
+
+#include &lt;KApplication&gt;
+#include &lt;KLocale&gt;
+#include &lt;KPushButton&gt;
+#include &lt;KSeparator&gt;
+#include &lt;KStandardDirs&gt;
+#include &lt;KGlobalSettings&gt;
+#include &lt;KConfig&gt;
+#include &lt;KIconLoader&gt;
+#include &lt;KNotification&gt;
+#include &lt;kdesu/defaults.h&gt;
+#include &lt;KPasswordDialog&gt;
+#include &lt;KDebug&gt;
+#include &lt;KUser&gt;
+#include &lt;KMessageBox&gt;
+#include &lt;KColorScheme&gt;
+
+#include &lt;QtDBus/QtDBus&gt;
+
+#include &lt;QLayout&gt;
+#include &lt;QPushButton&gt;
+// #include &lt;QMessageBox&gt;
+#include &lt;QLabel&gt;
+#include &lt;QFontMetrics&gt;
+#include &lt;QStyle&gt;
+#include &lt;QApplication&gt;
+#include &lt;QTreeWidget&gt;
+#include &lt;QHeaderView&gt;
+#include &lt;QCheckBox&gt;
+#include &lt;QGridLayout&gt;
+#include &lt;QEvent&gt;
+#include &lt;QFrame&gt;
+#include &lt;QHBoxLayout&gt;
+#include &lt;QBoxLayout&gt;
+#include &lt;QSocketNotifier&gt;
+#include &lt;QTimerEvent&gt;
+#include &lt;QVBoxLayout&gt;
+#include &lt;QFile&gt;
+
+#include &lt;ctype.h&gt;
+#include &lt;unistd.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;errno.h&gt;
+#include &lt;pwd.h&gt;
+#include &lt;stdio.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;sys/socket.h&gt;
+#include &lt;sys/wait.h&gt;
+
+#include &lt;X11/Xutil.h&gt;
+#include &lt;X11/keysym.h&gt;
+#include &lt;fixx11h.h&gt;
+#include &lt;QX11Info&gt;
+#include &lt;kauthorized.h&gt;
+
+#include &lt;KPluginLoader&gt;
+#include &lt;KPluginFactory&gt;
+
+#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 &amp;text)
+    : KDialog(parent, Qt::X11BypassWindowManagerHint),
+      mPlugin( plugin ),
+      mCapsLocked(-1),
+      mUnlockingFailed(false),
+      sNot(0)
+{
+    QWidget* w = mainWidget();
+
+    QLabel *pixLabel = new QLabel( w );
+    pixLabel-&gt;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("&lt;nobr&gt;&lt;b&gt;The session is locked&lt;/b&gt;&lt;/nobr&gt;&lt;br /&gt;") :
+            i18n("&lt;nobr&gt;&lt;b&gt;The session was locked by %1&lt;/b&gt;&lt;/nobr&gt;&lt;br /&gt;", fullName );
+    }
+    QLabel *greetLabel = new QLabel(greetString, w);
+
+    mStatusLabel = new QLabel( QLatin1String( "&lt;b&gt; &lt;/b&gt;" ), w );
+    mStatusLabel-&gt;setAlignment( Qt::AlignCenter );
+
+    greet = plugin-&gt;info-&gt;create(this, w, QString(),
+                                 KGreeterPlugin::Authenticate,
+                                 KGreeterPlugin::ExUnlock);
+
+    KSeparator *sep = new KSeparator( Qt::Horizontal, w );
+
+    ok = new KPushButton( KGuiItem(i18n("Unl&amp;ock"), QLatin1String( "object-unlocked" )), w );
+    cancel = new KPushButton( KStandardGuiItem::cancel(), w );
+    mNewSessButton = new KPushButton( KGuiItem(i18n("Sw&amp;itch User..."), QLatin1String( "fork" )), w );
+
+    // Using keyboard layout component
+    KPluginFactory *kxkbFactory = KPluginLoader(QLatin1String( "keyboard_layout_widget" )).factory();
+    QWidget *kxkbComponent = NULL;
+    if (kxkbFactory) {
+        kxkbComponent = kxkbFactory-&gt;create&lt;QWidget&gt;(this);
+    }
+    else {
+        kDebug() &lt;&lt; "can't load keyboard layout widget library";
+    }
+
+    QHBoxLayout *layStatus = new QHBoxLayout();
+    layStatus-&gt;addStretch();
+    layStatus-&gt;addWidget( mStatusLabel );
+    layStatus-&gt;addStretch();
+
+    if( kxkbComponent ) {
+	//TODO: without this the widget is off the parent area, but we need something better here
+        kxkbComponent-&gt;setFixedSize(48, 24);
+        layStatus-&gt;addWidget( kxkbComponent, 0, Qt::AlignRight );
+    }
+
+    QHBoxLayout *layButtons = new QHBoxLayout();
+    layButtons-&gt;addWidget( mNewSessButton );
+    layButtons-&gt;addStretch();
+    layButtons-&gt;addWidget( ok );
+    layButtons-&gt;addWidget( cancel );
+
+    frameLayout = new QGridLayout( w );
+    frameLayout-&gt;setSpacing( KDialog::spacingHint() );
+    frameLayout-&gt;setMargin( KDialog::marginHint() );
+    frameLayout-&gt;addWidget( pixLabel, 0, 0, 3, 1, Qt::AlignTop );
+    frameLayout-&gt;addWidget( greetLabel, 0, 1 );
+    frameLayout-&gt;addWidget( greet-&gt;getWidgets().first(), 1, 1 );
+    frameLayout-&gt;addLayout( layStatus, 2, 1 );
+    frameLayout-&gt;addWidget( sep, 3, 0, 1, 2 );
+    frameLayout-&gt;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-&gt;hide();
+
+    installEventFilter(this);
+
+    mFailedTimerId = 0;
+    mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT);
+    connect(qApp, SIGNAL(activity()), SLOT(slotActivity()) );
+
+    greet-&gt;start();
+
+    capsLocked();
+}
+
+PasswordDlg::~PasswordDlg()
+{
+    hide();
+    delete greet;
+}
+
+void PasswordDlg::updateLabel()
+{
+    if (mUnlockingFailed)
+    {
+        QPalette palette;
+        KColorScheme::adjustForeground(palette, KColorScheme::NormalText, QPalette::WindowText);
+        mStatusLabel-&gt;setPalette(palette);
+        mStatusLabel-&gt;setText(i18n("&lt;b&gt;Unlocking failed&lt;/b&gt;"));
+    }
+    else
+    if (mCapsLocked)
+    {
+        QPalette palette = mStatusLabel-&gt;palette();
+        KColorScheme::adjustForeground(palette, KColorScheme::NegativeText, QPalette::WindowText);
+        mStatusLabel-&gt;setPalette(palette);
+        mStatusLabel-&gt;setText(i18n("&lt;b&gt;Warning: Caps Lock on&lt;/b&gt;"));
+    }
+    else
+    {
+        mStatusLabel-&gt;setText(QLatin1String( "&lt;b&gt; &lt;/b&gt;" ));
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+// Handle timer events.
+//
+void PasswordDlg::timerEvent(QTimerEvent *ev)
+{
+    if (ev-&gt;timerId() == mTimeoutTimerId)
+    {
+        done(TIMEOUT_CODE);
+    }
+    else if (ev-&gt;timerId() == mFailedTimerId)
+    {
+        killTimer(mFailedTimerId);
+        mFailedTimerId = 0;
+        // Show the normal password prompt.
+        mUnlockingFailed = false;
+        updateLabel();
+        ok-&gt;setEnabled(true);
+        cancel-&gt;setEnabled(true);
+        mNewSessButton-&gt;setEnabled( true );
+        greet-&gt;revive();
+        greet-&gt;start();
+    }
+}
+
+bool PasswordDlg::eventFilter(QObject *, QEvent *ev)
+{
+    if (ev-&gt;type() == QEvent::KeyPress || ev-&gt;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 &lt; count; ) {
+      dord:
+        ret = ::read (sFd, (void *)((char *)buf + rlen), count - rlen);
+        if (ret &lt; 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 (&amp;val, sizeof(val));
+}
+
+bool PasswordDlg::GSendStr (const char *buf)
+{
+    int len = buf ? ::strlen (buf) + 1 : 0;
+    return GWrite (&amp;len, sizeof(len)) &amp;&amp; GWrite (buf, len);
+}
+
+bool PasswordDlg::GSendArr (int len, const char *buf)
+{
+    return GWrite (&amp;len, sizeof(len)) &amp;&amp; GWrite (buf, len);
+}
+
+bool PasswordDlg::GRecvInt (int *val)
+{
+    return GRead (val, sizeof(*val));
+}
+
+bool PasswordDlg::GRecvArr (char **ret)
+{
+    int len;
+    char *buf;
+
+    if (!GRecvInt(&amp;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-&gt;setEnabled( false );
+    sNot-&gt;deleteLater();
+    sNot = 0;
+    ::close( sFd );
+    int status;
+    while (::waitpid( sPid, &amp;status, 0 ) &lt; 0)
+        if (errno != EINTR) { // This should not happen ...
+            cantCheck();
+            return;
+        }
+    if (WIFEXITED(status))
+        switch (WEXITSTATUS(status)) {
+        case AuthOk:
+            greet-&gt;succeeded();
+            accept();
+            return;
+        case AuthBad:
+            greet-&gt;failed();
+            mUnlockingFailed = true;
+            updateLabel();
+            mFailedTimerId = startTimer(1500);
+            ok-&gt;setEnabled(false);
+            cancel-&gt;setEnabled(false);
+            mNewSessButton-&gt;setEnabled( false );
+            KNotification::event( QLatin1String( "unlockfailed" ) );
+            return;
+        case AuthAbort:
+            return;
+        }
+    cantCheck();
+}
+
+void PasswordDlg::handleVerify()
+{
+    int ret;
+    char *arr;
+
+    if (GRecvInt( &amp;ret )) {
+        switch (ret) {
+        case ConvGetBinary:
+            if (!GRecvArr( &amp;arr ))
+                break;
+            greet-&gt;binaryPrompt( arr, false );
+            if (arr)
+                ::free( arr );
+            return;
+        case ConvGetNormal:
+            if (!GRecvArr( &amp;arr ))
+                break;
+            greet-&gt;textPrompt( arr, true, false );
+            if (arr)
+                ::free( arr );
+            return;
+        case ConvGetHidden:
+            if (!GRecvArr( &amp;arr ))
+                break;
+            greet-&gt;textPrompt( arr, false, false );
+            if (arr)
+                ::free( arr );
+            return;
+        case ConvPutInfo:
+            if (!GRecvArr( &amp;arr ))
+                break;
+            if (!greet-&gt;textMessage( arr, false ))
+                static_cast&lt; LockProcess* &gt;(parent())-&gt;msgBox( this, QMessageBox::Information, QString::fromLocal8Bit( arr ) );
+            ::free( arr );
+            return;
+        case ConvPutError:
+            if (!GRecvArr( &amp;arr ))
+                break;
+            if (!greet-&gt;textMessage( arr, true ))
+                static_cast&lt; LockProcess* &gt;(parent())-&gt;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] &lt;&lt; 8) | (up[1] &lt;&lt; 16) | (up[0] &lt;&lt; 24);
+        if (!len)
+            GSendArr( 4, data );
+        else
+            GSendArr( len, data );
+    } else
+        GSendArr( 0, 0 );
+}
+
+void PasswordDlg::gplugSetUser( const QString &amp; )
+{
+    // ignore ...
+}
+
+void PasswordDlg::cantCheck()
+{
+    greet-&gt;failed();
+    static_cast&lt; LockProcess* &gt;(parent())-&gt;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-&gt;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()) &lt; 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-&gt;info-&gt;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 &amp;text )
+{
+    static_cast&lt; LockProcess* &gt;(parent())-&gt;msgBox( this, type, text );
+}
+
+bool PasswordDlg::gplugHasNode( const QString &amp; )
+{
+    return false;
+}
+
+void PasswordDlg::slotOK()
+{
+    greet-&gt;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-&gt;setModal( true );
+    dialog-&gt;setButtons( KDialog::Yes | KDialog::No );
+    dialog-&gt;setButtonGuiItem( KDialog::Yes, KGuiItem(i18n("&amp;Start New Session"), QLatin1String( "fork" )) );
+    dialog-&gt;setButtonGuiItem( KDialog::No, KStandardGuiItem::cancel() );
+    dialog-&gt;setDefaultButton( KDialog::Yes );
+    dialog-&gt;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("&amp;Do not ask again"), &amp;dontAskAgain,
+        KMessageBox::NoExec );
+
+    int ret = static_cast&lt; LockProcess* &gt;( parent())-&gt;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 &amp;sess, const QString &amp;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( &amp;dialog );
+    hbox-&gt;setSpacing( KDialog::spacingHint() );
+    hbox-&gt;setMargin( KDialog::marginHint() );
+
+    QBoxLayout *vbox1 = new QVBoxLayout( );
+    hbox-&gt;addItem( vbox1 );
+    QBoxLayout *vbox2 = new QVBoxLayout( );
+    hbox-&gt;addItem( vbox2 );
+
+    KPushButton *btn;
+
+    SessList sess;
+    if (dm.localSessions( sess )) {
+
+        lv = new QTreeWidget( &amp;dialog );
+        connect( lv, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), SLOT(slotSessionActivated()) );
+        connect( lv, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), &amp;dialog, SLOT(reject()) );
+        lv-&gt;setAllColumnsShowFocus( true );
+        lv-&gt;setHeaderLabels( QStringList() &lt;&lt; i18n("Session") &lt;&lt; i18n("Location") );
+        lv-&gt;header()-&gt;setResizeMode( 0, QHeaderView::Stretch );
+        lv-&gt;header()-&gt;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-&gt;setFlags( itm-&gt;flags() &amp; ~Qt::ItemIsEnabled );
+            if ((*it).self) {
+                lv-&gt;setCurrentItem( itm );
+                itm-&gt;setSelected( true );
+            }
+            ns++;
+        }
+        int fw = lv-&gt;frameWidth() * 2;
+        QSize hds( lv-&gt;header()-&gt;sizeHint() );
+        lv-&gt;setMinimumWidth( fw + hds.width() +
+            (ns &gt; 10 ? style()-&gt;pixelMetric(QStyle::PM_ScrollBarExtent) : 0 ) );
+        int ih = lv-&gt;itemDelegate()-&gt;sizeHint(
+            QStyleOptionViewItem(), lv-&gt;model()-&gt;index( 0, 0 ) ).height();
+        lv-&gt;setFixedHeight( fw + hds.height() +
+            ih * (ns &lt; 6 ? 6 : ns &gt; 10 ? 10 : ns) );
+        lv-&gt;header()-&gt;adjustSize();
+        vbox1-&gt;addWidget( lv );
+
+        btn = new KPushButton( KGuiItem(i18nc("session", "&amp;Activate"), QLatin1String( "fork" )), &amp;dialog );
+        connect( btn, SIGNAL(clicked()), SLOT(slotSessionActivated()) );
+        connect( btn, SIGNAL(clicked()), &amp;dialog, SLOT(reject()) );
+        vbox2-&gt;addWidget( btn );
+        vbox2-&gt;addStretch( 2 );
+    }
+
+    if (KAuthorized::authorizeKAction(QLatin1String( "start_new_session" )) &amp;&amp; (p = dm.numReserve()) &gt;= 0)
+    {
+        btn = new KPushButton( KGuiItem(i18n("Start &amp;New Session"), QLatin1String( "fork" )), &amp;dialog );
+        connect( btn, SIGNAL(clicked()), SLOT(slotStartNewSession()) );
+        connect( btn, SIGNAL(clicked()), &amp;dialog, SLOT(reject()) );
+        if (!p)
+            btn-&gt;setEnabled( false );
+        vbox2-&gt;addWidget( btn );
+        vbox2-&gt;addStretch( 1 );
+    }
+
+    btn = new KPushButton( KStandardGuiItem::cancel(), &amp;dialog );
+    connect( btn, SIGNAL(clicked()), &amp;dialog, SLOT(reject()) );
+    vbox2-&gt;addWidget( btn );
+
+    static_cast&lt; LockProcess* &gt;(parent())-&gt;execDialog( &amp;dialog );
+}
+
+void PasswordDlg::slotSessionActivated()
+{
+    LockListViewItem *itm = (LockListViewItem *)lv-&gt;currentItem();
+    if (itm &amp;&amp; itm-&gt;vt &gt; 0)
+        KDisplayManager().switchVT( itm-&gt;vt );
+}
+
+void PasswordDlg::capsLocked()
+{
+    unsigned int lmask;
+    Window dummy1, dummy2;
+    int dummy3, dummy4, dummy5, dummy6;
+    XQueryPointer(QX11Info::display(), DefaultRootWindow( QX11Info::display() ), &amp;dummy1, &amp;dummy2, &amp;dummy3, &amp;dummy4, &amp;dummy5, &amp;dummy6, &amp;lmask);
+    mCapsLocked = lmask &amp; 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 &lt;mjones@kde.org&gt;
+// Copyright 2003 Oswald Buddenhagen &lt;ossi@kde.org&gt;
+//
+
+#ifndef __LOCKDLG_H__
+#define __LOCKDLG_H__
+
+#include &lt;kgreeterplugin.h&gt;
+
+#include &lt;KDialog&gt;
+
+#include &lt;QLabel&gt;
+#include &lt;QTimerEvent&gt;
+#include &lt;QFrame&gt;
+#include &lt;QGridLayout&gt;
+#include &lt;QEvent&gt;
+
+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 &amp;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 &amp; );
+    virtual void gplugStart();
+    virtual void gplugChanged();
+    virtual void gplugActivity();
+    virtual void gplugMsgBox( QMessageBox::Icon type, const QString &amp;text );
+    virtual bool gplugHasNode( const QString &amp;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 &lt;mjones@kde.org&gt;
+// Copyright 2003 Oswald Buddenhagen &lt;ossi@kde.org&gt;
+// Copyright 2008 Chani Armitage &lt;chanika@gmail.com&gt;
+//
+
+//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 &lt;config-workspace.h&gt;
+#include &lt;config-X11.h&gt;
+#include &lt;config-krunner-lock.h&gt;
+#include "lockdlg.h"
+#include "autologout.h"
+#include "kscreensaversettings.h"
+
+#include &lt;kephal/screens.h&gt;
+
+#include &lt;kworkspace/kdisplaymanager.h&gt;
+
+#include &lt;KStandardDirs&gt;
+#include &lt;KApplication&gt;
+#include &lt;KServiceGroup&gt;
+#include &lt;KDebug&gt;
+#include &lt;KMessageBox&gt;
+#include &lt;KGlobalSettings&gt;
+#include &lt;KLocale&gt;
+#include &lt;KLibrary&gt;
+#include &lt;KNotification&gt;
+#include &lt;KPushButton&gt;
+#include &lt;KStandardGuiItem&gt;
+#include &lt;KAuthorized&gt;
+#include &lt;KDesktopFile&gt;
+#include &lt;kservicetypetrader.h&gt;
+#include &lt;kmacroexpander.h&gt;
+#include &lt;kshell.h&gt;
+#include &lt;kxerrorhandler.h&gt;
+
+#include &lt;QtGui/QFrame&gt;
+#include &lt;QLabel&gt;
+#include &lt;QLayout&gt;
+#include &lt;QCursor&gt;
+#include &lt;QTimer&gt;
+#include &lt;QFile&gt;
+#include &lt;QSocketNotifier&gt;
+#include &lt;QDesktopWidget&gt;
+#include &lt;QX11Info&gt;
+#include &lt;QTextStream&gt;
+#include &lt;QPainter&gt;
+#include &lt;QDBusConnection&gt;
+#include &lt;QDBusConnectionInterface&gt;
+#include &lt;QDBusInterface&gt;
+#include &lt;QDBusServiceWatcher&gt;
+
+#include &lt;QtCore/QStringBuilder&gt; // % operator for QString
+
+#include &lt;QDateTime&gt;
+
+#include &lt;stdlib.h&gt;
+#include &lt;assert.h&gt;
+#include &lt;signal.h&gt;
+#include &lt;unistd.h&gt;
+#ifdef HAVE_SETPRIORITY
+#include &lt;sys/time.h&gt;
+#include &lt;sys/resource.h&gt;
+#endif
+
+#include &lt;X11/Xlib.h&gt;
+#include &lt;X11/Xutil.h&gt;
+#include &lt;X11/keysym.h&gt;
+#include &lt;X11/Xatom.h&gt;
+
+#ifdef HAVE_DPMS
+extern "C" {
+#include &lt;X11/Xmd.h&gt;
+#ifndef Bool
+#define Bool BOOL
+#endif
+#include &lt;X11/extensions/dpms.h&gt;
+
+#ifndef HAVE_DPMSINFO_PROTO
+Status DPMSInfo ( Display *, CARD16 *, BOOL * );
+#endif
+}
+#endif
+
+#ifdef HAVE_XF86MISC
+#include &lt;X11/extensions/xf86misc.h&gt;
+#endif
+
+#ifdef HAVE_GLXCHOOSEVISUAL
+#include &lt;GL/glx.h&gt;
+#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 &lt;dlfcn.h&gt;
+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 &amp;&amp; w == DefaultRootWindow( dpy ))
+        kDebug() &lt;&lt; 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-&gt;installX11EventFilter(this);
+
+    // Get root window size
+    XWindowAttributes rootAttr;
+    QX11Info info;
+    XGetWindowAttributes(QX11Info::display(), RootWindow(QX11Info::display(),
+                                                         info.screen()), &amp;rootAttr);
+    kapp-&gt;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(&amp;mHackProc, SIGNAL(finished(int, QProcess::ExitStatus)),
+            SLOT(hackExited()));
+
+    mSuspendTimer.setSingleShot(true);
+    connect(&amp;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(), &amp;state, &amp;on);
+        if (on)
+        {
+            connect(&amp;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 -&gt; so take 10s
+            mCheckDPMS.start(10000);
+        }
+    }
+#endif
+
+    greetPlugin.library = 0;
+
+    mSuppressUnlock.setSingleShot(true);
+    connect(&amp;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(), &amp;r, &amp;p, &amp;real, &amp;nreal )
+        &amp;&amp; real != NULL ) {
+        KXErrorHandler err; // ignore X errors here
+        for( unsigned i = 0; i &lt; nreal; ++i ) {
+            XWindowAttributes winAttr;
+            if (XGetWindowAttributes(QX11Info::display(), real[ i ], &amp;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-&gt;done)
+            greetPlugin.info-&gt;done();
+        greetPlugin.library-&gt;unload();
+    }
+}
+
+static int signal_pipe[2];
+
+static void sigterm_handler(int)
+{
+    char tmp = 'T';
+    ::write( signal_pipe[1], &amp;tmp, 1);
+}
+
+static void sighup_handler(int)
+{
+    char tmp = 'H';
+    ::write( signal_pipe[1], &amp;tmp, 1);
+}
+
+static void sigusr1_handler(int)
+{
+    char tmp = '1';
+    ::write(signal_pipe[1], &amp;tmp, 1);
+}
+
+void LockProcess::timerEvent(QTimerEvent *ev)
+{
+    if (ev-&gt;timerId() == mAutoLogoutTimerId)
+    {
+        AutoLogout autologout(this);
+        execDialog(&amp;autologout);
+    }
+}
+
+void LockProcess::setupSignals()
+{
+    struct sigaction act;
+    sigemptyset(&amp;(act.sa_mask));
+    act.sa_flags = 0;
+    // ignore SIGINT
+    act.sa_handler=SIG_IGN;
+    sigaction(SIGINT, &amp;act, 0L);
+    // ignore SIGQUIT
+    //act.sa_handler=SIG_IGN;
+    sigaction(SIGQUIT, &amp;act, 0L);
+    // exit cleanly on SIGTERM
+    act.sa_handler= sigterm_handler;
+    sigaction(SIGTERM, &amp;act, 0L);
+    // SIGHUP forces lock
+    act.sa_handler= sighup_handler;
+    sigaction(SIGHUP, &amp;act, 0L);
+    // SIGUSR1 simulates user activity
+    act.sa_handler= sigusr1_handler;
+    sigaction(SIGUSR1, &amp;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], &amp;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 &amp;&amp; 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 &gt;= 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-&gt;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 &lt; 0)
+            mLockGrace = 0;
+        else if (mLockGrace &gt; 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 &lt; 0) mPriority = 0;
+    if (mPriority &gt; 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 &lt;&lt; QLatin1String( "classic" ) &lt;&lt; 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()-&gt;query( QLatin1String( "ScreenSaver" ),
+            QLatin1String( "DesktopEntryName == '" ) + entryName.toLower() + QLatin1Char( '\'' ) );
+        if( offers.isEmpty() )
+        {
+            kDebug(1204) &lt;&lt; "Cannot find screesaver: " &lt;&lt; mSaver;
+            return;
+        }
+        const QString file = KStandardDirs::locate("services", offers.first()-&gt;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 &amp;type, desktopGroup.readEntry("X-KDE-Type").split(QLatin1Char(';'))) {
+            if (type == QLatin1String("ManipulateScreen")) {
+                if (!manipulatescreen) {
+                    kDebug(1204) &lt;&lt; "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden";
+                    mForbidden = true;
+                }
+            } else if (type == QLatin1String("OpenGL")) {
+                mOpenGLVisual = true;
+                if (!opengl) {
+                    kDebug(1204) &lt;&lt; "Screensaver is type OpenGL and OpenGL is forbidden";
+                    mForbidden = true;
+                }
+            }
+        }
+
+        kDebug(1204) &lt;&lt; "mForbidden: " &lt;&lt; (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 &lt; sizeof( attribs ) / sizeof( attribs[ 0 ] );
+             ++i )
+        {
+            if( XVisualInfo* info = glXChooseVisual( x11Info().display(), x11Info().screen(), const_cast&lt;int*&gt;(attribs[ i ]) ))
+            {
+                visual = info-&gt;visual;
+                depth = info-&gt;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, &amp;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, &amp;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) &lt;&lt; "Saver window Id: " &lt;&lt; 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, &amp;rootReturn, &amp;parentReturn,
+      &amp;children, &amp;numChildren))
+  {
+    for (unsigned int i = 0; i &lt; 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, &amp;actual_type, &amp;actual_format, &amp;nitems, &amp;bytesafter,
+          &amp;newRoot) == Success) &amp;&amp; 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 , &amp;rootReturn, &amp;parentReturn,
+                                 &amp;children, &amp;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()-&gt;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()-&gt;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 &amp;&amp; !grabInput())
+    {
+        kWarning(1204) &lt;&lt; "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 &amp;&amp; !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) &lt;&lt; "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-&gt;sendEvent();
+        }
+        ungrabInput();
+        const char *out = "GOAWAY!";
+        for (QList&lt;int&gt;::ConstIterator it = child_sockets.constBegin(); it != child_sockets.constEnd(); ++it)
+            write(*it, out, sizeof(out));
+    }
+    KNotification *s = new KNotification( QLatin1String( "savingstopped" ) );
+    s-&gt;sendEvent();
+}
+
+// private static
+QVariant LockProcess::getConf(void *ctx, const char *key, const QVariant &amp;dflt)
+{
+    LockProcess *that = (LockProcess *)ctx;
+    QString fkey = QLatin1String( key ) % QLatin1Char( '=' );
+    for (QStringList::ConstIterator it = that-&gt;mPluginOptions.constBegin();
+         it != that-&gt;mPluginOptions.constEnd(); ++it)
+        if ((*it).startsWith( fkey ))
+            return (*it).mid( fkey.length() );
+    return dflt;
+}
+
+void LockProcess::cantLock( const QString &amp;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 &lt;i&gt;kcheckpass&lt;/i&gt;.");
+i18n("&lt;i&gt;kcheckpass&lt;/i&gt; 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-&gt;fileName().isEmpty()) {
+            kWarning(1204) &lt;&lt; "GreeterPlugin " &lt;&lt; *it &lt;&lt; " does not exist" ;
+            delete lib;
+            continue;
+        }
+        if (!lib-&gt;load()) {
+            kWarning(1204) &lt;&lt; "Cannot load GreeterPlugin " &lt;&lt; *it &lt;&lt; " (" &lt;&lt; lib-&gt;fileName() &lt;&lt; ")" ;
+            delete lib;
+            continue;
+        }
+        plugin.library = lib;
+        plugin.info = (KGreeterPluginInfo *)lib-&gt;resolveSymbol( "kgreeterplugin_info" );
+        if (!plugin.info ) {
+            kWarning(1204) &lt;&lt; "GreeterPlugin " &lt;&lt; *it &lt;&lt; " (" &lt;&lt; lib-&gt;fileName() &lt;&lt; ") is no valid greet widget plugin" ;
+            lib-&gt;unload();
+            delete lib;
+            continue;
+        }
+        if (plugin.info-&gt;method &amp;&amp; !mMethod.isEmpty() &amp;&amp; mMethod != QLatin1String(  plugin.info-&gt;method )) {
+            kDebug(1204) &lt;&lt; "GreeterPlugin " &lt;&lt; *it &lt;&lt; " (" &lt;&lt; lib-&gt;fileName() &lt;&lt; ") serves " &lt;&lt; plugin.info-&gt;method &lt;&lt; ", not " &lt;&lt; mMethod;
+            lib-&gt;unload();
+            delete lib;
+            continue;
+        }
+        if (!plugin.info-&gt;init( mMethod, getConf, this )) {
+            kDebug(1204) &lt;&lt; "GreeterPlugin " &lt;&lt; *it &lt;&lt; " (" &lt;&lt; lib-&gt;fileName() &lt;&lt; ") refuses to serve " &lt;&lt; mMethod;
+            lib-&gt;unload();
+            delete lib;
+            continue;
+        }
+        kDebug(1204) &lt;&lt; "GreeterPlugin " &lt;&lt; *it &lt;&lt; " (" &lt;&lt; plugin.info-&gt;method &lt;&lt; ", " &lt;&lt; plugin.info-&gt;name &lt;&lt; ") loaded";
+        greetPlugin = plugin;
+        return true;
+    }
+    cantLock( i18n("No appropriate greeter plugin configured.") );
+    return false;
+}
+
+//---------------------------------------------------------------------------
+//
+
+
+bool LockProcess::startHack()
+{
+    kDebug(1204) &lt;&lt; "Starting hack:" &lt;&lt; mSaverExec;
+
+    if (mSaverExec.isEmpty() || mForbidden)
+    {
+        hackExited();
+        return false;
+    }
+
+    QHash&lt;QChar, QString&gt; keyMap;
+    keyMap.insert(QLatin1Char( 'w' ), QString::number(winId()));
+    mHackProc &lt;&lt; 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() &lt;&lt; "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-&gt;isValid()) {
+        kDebug() &lt;&lt; "weird, plasma-overlay is already running";
+        mPlasmaDBus-&gt;call(QDBus::NoBlock, QLatin1String( "setup" ), mSetupMode);
+        return true;
+    }
+
+    kDebug () &lt;&lt; "...not found" &lt;&lt; "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-&gt;setProgram(QLatin1String( "plasma-overlay" ));
+    if (mSetupMode) {
+        *plasmaProc &lt;&lt; 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-&gt;start();
+    kDebug() &lt;&lt; "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() &lt;&lt; "You're Doing It Wrong!";
+        return;
+    }
+    if (mPlasmaDBus &amp;&amp; mPlasmaDBus-&gt;isValid()) {
+        //hooray, looks like it started ok
+        kDebug() &lt;&lt; "success!";
+        //...but just in case, make sure we're not waiting on it
+        mSetupMode = false;
+        return;
+    }
+
+    kDebug() &lt;&lt; "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 &amp;&amp; mPlasmaDBus)) {
+        return false; //no plasma, at least not yet
+    }
+    if (mPlasmaDBus-&gt;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 &amp;&amp; mPlasmaDBus-&gt;isValid()) {
+        mPlasmaDBus-&gt;call(QDBus::NoBlock, QLatin1String( "quit" ));
+    } else {
+        kDebug() &lt;&lt; "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() &lt;&lt; "plasma ran away?";
+            disablePlasma();
+        } else {
+            kDebug() &lt;&lt; "I'm confused!!";
+        }
+        return;
+    }
+
+    kDebug() &lt;&lt; "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-&gt;call(QDBus::NoBlock, QLatin1String( "setActive" ), true);
+    }
+}
+
+void LockProcess::deactivatePlasma()
+{
+    if (isPlasmaValid()) {
+        mPlasmaDBus-&gt;call(QDBus::NoBlock, QLatin1String( "setActive" ), false);
+    }
+    if (!mLocked &amp;&amp; mLockGrace &gt;=0) {
+        QTimer::singleShot(mLockGrace, this, SLOT(startLock())); //this is only ok because any activity will quit
+    }
+}
+
+void LockProcess::lockPlasma()
+{
+    if (isPlasmaValid()) {
+        mPlasmaDBus-&gt;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 &amp;&amp; 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 &amp;&amp; (!mDialogs.isEmpty() || !mVisibility ))
+        return; // no resuming with dialog visible or when not visible
+    if( mSuspended &amp;&amp; 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-&gt;call(QDBus::NoBlock, QLatin1String( "setActive" ), true);
+    }
+
+    PasswordDlg passDlg( this, &amp;greetPlugin);
+    const int ret = execDialog( &amp;passDlg );
+
+    if (isPlasmaValid()) {
+        if (ret == QDialog::Rejected) {
+            mSuppressUnlock.start(mSuppressUnlockTimeout);
+        } else if (ret == TIMEOUT_CODE) {
+            mPlasmaDBus-&gt;call(QDBus::NoBlock, QLatin1String( "setActive" ), false);
+        }
+    }
+
+    XWindowAttributes rootAttr;
+    XGetWindowAttributes(QX11Info::display(), QX11Info::appRootWindow(), &amp;rootAttr);
+    if(( rootAttr.your_event_mask &amp; SubstructureNotifyMask ) == 0 )
+    {
+        kWarning() &lt;&lt; "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 &amp;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, &amp;greetPlugin, reason);
+    const int ret = execDialog( &amp;passDlg );
+//    kDebug() &lt;&lt; ret;
+
+    //FIXME do we need to copy&amp;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(&amp;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, &amp;ev );
+}
+
+bool LockProcess::eventFilter(QObject *o, QEvent *e)
+{
+    if (e-&gt;type() == QEvent::Resize) {
+        QWidget *w = static_cast&lt;QWidget *&gt;(o);
+        mFrames.value(w)-&gt;resize(w-&gt;size());
+    }
+    return false;
+}
+
+int LockProcess::execDialog( QDialog *dlg )
+{
+
+    QFrame *winFrame = new QFrame( dlg );
+    winFrame-&gt;setFrameStyle( QFrame::WinPanel | QFrame::Raised );
+    winFrame-&gt;setLineWidth( 2 );
+    winFrame-&gt;lower();
+    mFrames.insert(dlg, winFrame);
+    dlg-&gt;installEventFilter(this);
+
+    dlg-&gt;adjustSize();
+
+    int screen = Kephal::ScreenUtils::primaryScreenId();
+    if (Kephal::ScreenUtils::numScreens() &gt; 1) {
+        screen = Kephal::ScreenUtils::screenId(QCursor::pos());
+    }
+
+    const QRect screenRect = Kephal::ScreenUtils::screenGeometry(screen);
+    QRect rect = dlg-&gt;geometry();
+    rect.moveCenter(screenRect.center());
+    dlg-&gt;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-&gt;winId());
+    const int rt = dlg-&gt;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-&gt;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()-&gt;winId());
+    }
+}
+
+//---------------------------------------------------------------------------
+//
+// X11 Event.
+//
+bool LockProcess::x11Event(XEvent *event)
+{
+    if (mEventRecursed)
+        return false;
+
+    bool ret = false;
+    switch (event-&gt;type)
+    {
+        case ButtonPress:
+            if (!mDialogs.isEmpty() &amp;&amp; event-&gt;xbutton.window == event-&gt;xbutton.root) {
+                //kDebug() &lt;&lt; "close" &lt;&lt; mDialogs.first()-&gt;effectiveWinId();
+                KDialog *dlg = qobject_cast&lt;KDialog*&gt;(mDialogs.first());
+                if (dlg) {
+                    //kDebug() &lt;&lt; "casting success";
+                    dlg-&gt;reject();
+                }
+                break;
+            }
+        case KeyPress:
+        case MotionNotify:
+            if (mBusy || !mDialogs.isEmpty()) {
+                //kDebug() &lt;&lt; "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() &amp;&amp; (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-&gt;type == KeyPress) {
+                    // Bounce the keypress to the dialog
+                    QByteArray chars;
+                    chars.resize(513);
+                    KeySym keysym;
+                    XLookupString(&amp;event-&gt;xkey, chars.data(), chars.size(), &amp;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-&gt;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-&gt;xvisibility.state == VisibilityFullyObscured);
+                if (!mVisibility) {
+                    mSuspendTimer.start(2000);
+                    kDebug(1204) &lt;&lt; "fully obscured";
+                } else {
+                    kDebug(1204) &lt;&lt; "not fully obscured";
+                    mSuspendTimer.stop();
+                    resume( false );
+                }
+                if (mForeignWindows.isEmpty() &amp;&amp; event-&gt;xvisibility.state != VisibilityUnobscured) {
+                    kDebug(1204) &lt;&lt; "no plasma; saver obscured";
+                    stayOnTop();
+                }
+            } else if (!mForeignWindows.isEmpty() &amp;&amp; event-&gt;xvisibility.window == mForeignWindows.last() &amp;&amp;
+                    event-&gt;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) &lt;&lt; "plasma obscured!";
+                stayOnTop();
+            }
+            break;
+
+        case ConfigureNotify: // from SubstructureNotifyMask on the root window
+            if(event-&gt;xconfigure.event == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event-&gt;xconfigure.window );
+                if( index &gt;= 0 ) {
+                    int index2 = event-&gt;xconfigure.above ? findWindowInfo( event-&gt;xconfigure.above ) : 0;
+                    if( index2 &lt; 0 )
+                        kDebug(1204) &lt;&lt; "Unknown above for ConfigureNotify";
+                    else { // move just above the other window
+                        if( index2 &lt; index )
+                            ++index2;
+                        windowInfo.move( index, index2 );
+                    }
+                } else
+                    kDebug(1204) &lt;&lt; "Unknown toplevel for ConfigureNotify";
+                //kDebug() &lt;&lt; "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-&gt;xmap.event == QX11Info::appRootWindow()) {
+                kDebug(1204) &lt;&lt; "MapNotify:" &lt;&lt; event-&gt;xmap.window;
+                if (!mDialogs.isEmpty() &amp;&amp; mDialogs.first()-&gt;winId() == event-&gt;xmap.window)
+                    mVisibleDialogs.append(event-&gt;xmap.window);
+                int index = findWindowInfo( event-&gt;xmap.window );
+                if( index &gt;= 0 )
+                    windowInfo[ index ].viewable = true;
+                else
+                    kDebug(1204) &lt;&lt; "Unknown toplevel for MapNotify";
+                KXErrorHandler err; // ignore X errors here
+                WindowType type = windowType(event-&gt;xmap.window);
+                if (type != IgnoreWindow) {
+                    if (mForeignWindows.contains(event-&gt;xmap.window)) {
+                        kDebug(1204) &lt;&lt; "uhoh! duplicate!";
+                    } else {
+                        //ordered youngest-on-top
+                        mForeignWindows.prepend(event-&gt;xmap.window);
+                    }
+                    if (type &amp; InputWindow) {
+                        kDebug(1204) &lt;&lt; "input window";
+                        if (mForeignInputWindows.contains(event-&gt;xmap.window)) {
+                            kDebug(1204) &lt;&lt; "uhoh! duplicate again"; //never happens
+                        } else {
+                            //ordered youngest-on-top
+                            mForeignInputWindows.prepend(event-&gt;xmap.window);
+                            fakeFocusIn(event-&gt;xmap.window);
+                        }
+                        mSetupMode = false; //no more waiting for plasma
+                    }
+                }
+                stayOnTop();
+            }
+            break;
+        case UnmapNotify:
+            if (event-&gt;xunmap.event == QX11Info::appRootWindow()) {
+                kDebug(1204) &lt;&lt; "UnmapNotify:" &lt;&lt; event-&gt;xunmap.window;
+                int index = findWindowInfo( event-&gt;xunmap.window );
+                if( index &gt;= 0 )
+                    windowInfo[ index ].viewable = false;
+                else
+                    kDebug(1204) &lt;&lt; "Unknown toplevel for MapNotify";
+                mVisibleDialogs.removeAll(event-&gt;xunmap.window);
+                mForeignWindows.removeAll(event-&gt;xunmap.window);
+                if (mForeignInputWindows.removeAll(event-&gt;xunmap.window)) {
+                    updateFocus();
+                }
+            }
+            break;
+        case CreateNotify:
+            if (event-&gt;xcreatewindow.parent == QX11Info::appRootWindow()) {
+                kDebug(1204) &lt;&lt; "CreateNotify:" &lt;&lt; event-&gt;xcreatewindow.window;
+                int index = findWindowInfo( event-&gt;xcreatewindow.window );
+                if( index &gt;= 0 )
+                    kDebug(1204) &lt;&lt; "Already existing toplevel for CreateNotify";
+                else {
+                    WindowInfo info;
+                    info.window = event-&gt;xcreatewindow.window;
+                    info.viewable = false;
+                    windowInfo.append( info );
+                }
+            }
+            break;
+        case DestroyNotify:
+            if (event-&gt;xdestroywindow.event == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event-&gt;xdestroywindow.window );
+                if( index &gt;= 0 )
+                    windowInfo.removeAt( index );
+                else
+                    kDebug(1204) &lt;&lt; "Unknown toplevel for DestroyNotify";
+            }
+            break;
+        case ReparentNotify:
+            if (event-&gt;xreparent.event == QX11Info::appRootWindow() &amp;&amp; event-&gt;xreparent.parent != QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event-&gt;xreparent.window );
+                if( index &gt;= 0 )
+                    windowInfo.removeAt( index );
+                else
+                    kDebug(1204) &lt;&lt; "Unknown toplevel for ReparentNotify away";
+            } else if (event-&gt;xreparent.parent == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event-&gt;xreparent.window );
+                if( index &gt;= 0 )
+                    kDebug(1204) &lt;&lt; "Already existing toplevel for ReparentNotify";
+                else {
+                    WindowInfo info;
+                    info.window = event-&gt;xreparent.window;
+                    info.viewable = false;
+                    windowInfo.append( info );
+                }
+            }
+            break;
+        case CirculateNotify:
+            if (event-&gt;xcirculate.event == QX11Info::appRootWindow()) {
+                int index = findWindowInfo( event-&gt;xcirculate.window );
+                if( index &gt;= 0 ) {
+                    windowInfo.move( index, event-&gt;xcirculate.place == PlaceOnTop ? windowInfo.size() - 1 : 0 );
+                } else
+                    kDebug(1204) &lt;&lt; "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-&gt;type == KeyPress || event-&gt;type == KeyRelease) {
+            mEventQueue.enqueue(*event);
+            ret = true;
+        }
+        if (!mVisibleDialogs.isEmpty())
+            while (!mEventQueue.isEmpty()) {
+                //kDebug() &lt;&lt; "forward to dialog";
+                XEvent ev2 = mEventQueue.dequeue();
+                ev2.xkey.window = ev2.xkey.subwindow = mVisibleDialogs.last();
+                mEventRecursed = true;
+                qApp-&gt;x11ProcessEvent( &amp;ev2 );
+                mEventRecursed = false;
+            }
+    } else {
+        mEventQueue.clear();
+        if (!mForeignInputWindows.isEmpty()) {
+            //when there are no dialogs, forward some events to plasma
+            switch (event-&gt;type) {
+            case KeyPress:
+            case KeyRelease:
+            case ButtonPress:
+            case ButtonRelease:
+            case MotionNotify: {
+                //kDebug() &lt;&lt; "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() &lt;&lt; "root is" &lt;&lt; winId();
+                //kDebug() &lt;&lt; "search window under pointer with" &lt;&lt; mForeignInputWindows.size() &lt;&lt; "windows";
+                KXErrorHandler err; // ignore X errors
+                foreach(WId window, mForeignInputWindows)
+                {
+                    if( XGetGeometry(QX11Info::display(), window, &amp;root_return,
+                                &amp;x_return, &amp;y_return,
+                                &amp;width_return, &amp;height_return,
+                                &amp;border_width_return, &amp;depth_return)
+                        &amp;&amp;
+                        (event-&gt;xkey.x&gt;=x_return &amp;&amp; event-&gt;xkey.x&lt;=x_return+(int)width_return)
+                        &amp;&amp;
+                        (event-&gt;xkey.y&gt;=y_return &amp;&amp; event-&gt;xkey.y&lt;=y_return+(int)height_return) )
+                    {
+                        //kDebug() &lt;&lt; "found window" &lt;&lt; window;
+                        targetWindow = window;
+                        ev2.xkey.window = ev2.xkey.subwindow = targetWindow;
+                        ev2.xkey.x = event-&gt;xkey.x - x_return;
+                        ev2.xkey.y = event-&gt;xkey.y - y_return;
+                        break;
+                    }
+                }
+                XSendEvent(QX11Info::display(), targetWindow, False, NoEventMask, &amp;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, &amp;actualType,
+            &amp;actualFormat, &amp;nitems, &amp;remaining, &amp;data);
+
+    //kDebug() &lt;&lt; (result == Success) &lt;&lt; (actualType == tag);
+    WindowType type = IgnoreWindow;
+    if (result == Success &amp;&amp; actualType == tag) {
+        if (nitems != 1 || actualFormat != 8) {
+            kDebug(1204) &lt;&lt; "malformed property";
+        } else {
+            kDebug(1204) &lt;&lt; "i can haz plasma window?" &lt;&lt; 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&lt; Window &gt; stack( mDialogs.count() + mForeignWindows.count() + 1 );
+    int count = 0;
+    // dialogs first
+    foreach( QWidget* w, mDialogs )
+        stack[ count++ ] = w-&gt;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&amp; info, windowInfo ) {
+        if( stack.contains( info.window )) {
+            found_ours = true;
+        } else if( found_ours &amp;&amp; info.viewable ) {
+            kDebug(1204) &lt;&lt; "found foreign window above screensaver";
+            needs_erase = true;
+            break;
+        }
+    }
+    // do the actual restacking if needed
+    XRaiseWindow( x11Info().display(), stack[ 0 ] );
+    if( count &gt; 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(), &amp;state, &amp;on);
+    //kDebug() &lt;&lt; "checkDPMSActive " &lt;&lt; on &lt;&lt; " " &lt;&lt; state;
+    if (state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff)
+        suspend();
+    else
+        resume( false );
+#endif
+}
+
+#if defined(HAVE_XF86MISC) &amp;&amp; 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(), &amp;dummy, &amp;dummy )
+            &amp;&amp; XF86MiscQueryVersion( QX11Info::display(), &amp;major, &amp;minor )
+            &amp;&amp; (major &gt; 0 || minor &gt;= 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 &amp;txt )
+{
+    QDialog box( parent, Qt::X11BypassWindowManagerHint );
+
+    QLabel *label1 = new QLabel( &amp;box );
+    label1-&gt;setPixmap( QMessageBox::standardIcon( type ) );
+    QLabel *label2 = new QLabel( txt, &amp;box );
+    KPushButton *button = new KPushButton( KStandardGuiItem::ok(), &amp;box );
+    button-&gt;setDefault( true );
+    button-&gt;setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+    connect( button, SIGNAL( clicked() ), &amp;box, SLOT( accept() ) );
+
+    QGridLayout *grid = new QGridLayout( &amp;box );
+    grid-&gt;setSpacing( 10 );
+    grid-&gt;addWidget( label1, 0, 0, Qt::AlignCenter );
+    grid-&gt;addWidget( label2, 0, 1, Qt::AlignCenter );
+    grid-&gt;addWidget( button, 1, 0, 1, 2, Qt::AlignCenter );
+
+    execDialog( &amp;box );
+}
+
+int LockProcess::findWindowInfo( Window w )
+{
+    for( int i = 0;
+         i &lt; 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 &lt;mjones@kde.org&gt;
+// Copyright 2003 Oswald Buddenhagen &lt;ossi@kde.org&gt;
+// Copyright 2008 Chani Armitage &lt;chanika@gmail.com&gt;
+//
+
+#ifndef LOCKPROCESS_H
+#define LOCKPROCESS_H
+
+#include &lt;KProcess&gt;
+
+#include &lt;QWidget&gt;
+#include &lt;QTimer&gt;
+#include &lt;QStack&gt;
+#include &lt;QList&gt;
+#include &lt;QHash&gt;
+#include &lt;QMessageBox&gt;
+#include &lt;QPixmap&gt;
+
+#include &lt;X11/Xlib.h&gt;
+#include &lt;fixx11h.h&gt;
+
+#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&lt;int&gt; children) { child_sockets = children; }
+    void setParent(int fd) { mParent = fd; }
+
+    void msgBox( QWidget *parent, QMessageBox::Icon type, const QString &amp;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 &amp;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 &amp;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 &amp;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&lt;int&gt; child_sockets;
+    int         mParent;
+    bool        mUseBlankOnly;
+    bool        mSuspended;
+    QTimer      mSuspendTimer;
+    bool        mVisibility;
+    bool        mDPMSDepend;
+    QTimer      mCheckDPMS;
+    QStack&lt; QWidget* &gt; mDialogs;
+    QHash&lt; QWidget*, QWidget* &gt; mFrames;
+    QList&lt;WId&gt;  mVisibleDialogs;
+    QQueue&lt;XEvent&gt; 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&lt;WId&gt;  mForeignWindows;
+    QList&lt;WId&gt;  mForeignInputWindows;
+    struct WindowInfo
+    {
+        Window window;
+        bool viewable;
+    };
+    QList&lt;WindowInfo&gt; 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 &lt;ossi@kde.org&gt;
+
+   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 &lt;kcmdlineargs.h&gt;
+#include &lt;klocale.h&gt;
+#include &lt;kglobal.h&gt;
+#include &lt;kdebug.h&gt;
+#include &lt;kglobalsettings.h&gt;
+#include &lt;QtDBus/QtDBus&gt;
+#include "kscreensaver_interface.h"
+
+#include &lt;QList&gt;
+
+#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
+#include &lt;unistd.h&gt;
+
+#include &lt;X11/Xlib.h&gt;
+#include &lt;fixx11h.h&gt;
+
+bool MyApp::x11EventFilter( XEvent *ev )
+{
+    if (ev-&gt;type == XKeyPress || ev-&gt;type == ButtonPress)
+        emit activity();
+    else if (ev-&gt;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-&gt;isSet("daemon")) {
+        daemonize = true;
+        if (pipe(daemonPipe))
+            kFatal() &lt;&lt; "pipe() failed";
+        switch (fork()) {
+        case -1:
+            kFatal() &lt;&lt; "fork() failed";
+        case 0:
+            break;
+        default:
+            if (read(daemonPipe[0], &amp;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&lt;int&gt; 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() &lt;&lt; "screen " &lt;&lt; number_of_screens &lt;&lt; " " &lt;&lt; kdesktop_screen_number &lt;&lt; " " &lt;&lt; display_name &lt;&lt; " " &lt;&lt; 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 &lt; 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() &lt;&lt; "env " &lt;&lt; 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() &lt;&lt; "app " &lt;&lt; kdesktop_screen_number &lt;&lt; " " &lt;&lt; starting_screen &lt;&lt; " " &lt;&lt; child &lt;&lt; " " &lt;&lt; child_sockets.count() &lt;&lt; " " &lt;&lt; parent_connection;
+    app.disableSessionManagement();
+    app.setQuitOnLastWindowClosed( false );
+    KGlobal::locale()-&gt;insertCatalog(QLatin1String( "libkworkspace" ));
+
+    LockProcess process(child, args-&gt;isSet("blank"));
+    if (!child)
+        process.setChildren(child_sockets);
+    else
+        process.setParent(parent_connection);
+
+    bool rt;
+    bool sig = false;
+    if (!child &amp;&amp; (args-&gt;isSet("forcelock"))) {
+        rt = process.lock(args-&gt;isSet("showunlock"));
+        sig = true;
+    }
+    else if( child || args-&gt;isSet( "dontlock" ))
+        rt = process.dontLock();
+    else if (args-&gt;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-&gt;clear();
+    if (daemonize) {
+        daemonBuf = 0;
+        write(daemonPipe[1], &amp;daemonBuf, 1);
+    }
+    return app.exec();
+}
+
+#include "main.moc"
+
+#define KDM_NO_SHUTDOWN
+#include &lt;kworkspace/kdisplaymanager.cpp&gt;
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 &lt;ossi@kde.org&gt;
+
+   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 &lt;kapplication.h&gt;
+
+#include &lt;time.h&gt;
+
+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 &lt;mgraesslin@kde.org&gt;
+
+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 &lt;http://www.gnu.org/licenses/&gt;.
+*********************************************************************/
+#include "screenlocker.h"
+#include "saverengine.h"
+#include "workspace.h"
+#include &lt;fixx11h.h&gt;
+#include "effects.h"
+// Qt
+#include &lt;QtDBus/QDBusInterface&gt;
+#include &lt;QtDBus/QDBusReply&gt;
+// KDE
+#include &lt;KDE/KAction&gt;
+#include &lt;KDE/KActionCollection&gt;
+#include &lt;KDE/KAuthorized&gt;
+#include &lt;KDE/KDebug&gt;
+#include &lt;KDE/KShortcut&gt;
+#include &lt;KDE/KLocalizedString&gt;
+
+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 &lt;&lt; QLatin1String("krunner") &lt;&lt; QLatin1String("Lock Session") &lt;&lt; "" &lt;&lt; "";
+        QDBusReply&lt;QList&lt;int&gt; &gt; reply = accelIface.call("shortcut", krunnerShortcutId);
+        int shortcut = -1;
+        if (reply.isValid() &amp;&amp; reply.value().size() == 1) {
+            shortcut = reply.value().at(0);
+            kDebug(1212) &lt;&lt; "Existing krunner shortcut for Lock Session found:" &lt;&lt; KShortcut(shortcut).toString();
+        }
+        accelIface.call(QDBus::NoBlock, "unRegister", krunnerShortcutId);
+
+        KAction *a = keys-&gt;addAction(QLatin1String("Lock Session"));
+        a-&gt;setText(i18n("Lock Session"));
+        a-&gt;setGlobalShortcut(KShortcut(Qt::ALT+Qt::CTRL+Qt::Key_L));
+        if (shortcut &gt;= 0) {
+            // if there was a krunner shortcut, use that
+            a-&gt;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()-&gt;compositingActive() &amp;&amp; static_cast&lt;EffectsHandlerImpl*&gt;(effects)-&gt;provides(Effect::ScreenLocking)) {
+        // try locking through an Effect
+        hasLock = static_cast&lt;EffectsHandlerImpl*&gt;(effects)-&gt;lockScreen();
+    }
+    if (!hasLock) {
+        // no Effect to lock the screen, try legacy X Screen Saver for locking
+        hasLock = !m_saverEngine-&gt;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 &lt;mgraesslin@kde.org&gt;
+
+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 &lt;http://www.gnu.org/licenses/&gt;.
+*********************************************************************/
+#ifndef KWIN_SCREENLOCKER_SCREENLOCKER_H
+#define KWIN_SCREENLOCKER_SCREENLOCKER_H
+
+#include &lt;QtCore/QObject&gt;
+
+// 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..e6ad800
--- /dev/null
+++ b/kwin/screenlocker/screensaver/saverengine.cpp
@@ -0,0 +1,513 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright 1999 Martin R. Jones &lt;mjones@kde.org&gt;
+//
+
+
+#include "saverengine.h"
+#include "kscreensaversettings.h"
+#include "screensaveradaptor.h"
+#include "kscreensaveradaptor.h"
+
+#include &lt;kaction.h&gt;
+#include &lt;kactioncollection.h&gt;
+#include &lt;kauthorized.h&gt;
+#include &lt;kglobalaccel.h&gt;
+#include &lt;kstandarddirs.h&gt;
+#include &lt;kapplication.h&gt;
+#include &lt;kservicegroup.h&gt;
+#include &lt;krandom.h&gt;
+#include &lt;kdebug.h&gt;
+#include &lt;klocale.h&gt;
+#include &lt;kprocess.h&gt;
+#include &lt;QFile&gt;
+#include &lt;QX11Info&gt;
+#include &lt;QDBusConnection&gt;
+#include &lt;QDBusInterface&gt;
+#include &lt;QDBusReply&gt;
+#include &lt;QDBusServiceWatcher&gt;
+#include &lt;assert.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;time.h&gt;
+#include &lt;signal.h&gt;
+
+#include "xautolock_c.h"
+#include "screenlocker.h"
+#include &lt;kkeysequencewidget.h&gt;
+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(), &amp;mXTimeout, &amp;mXInterval,
+                    &amp;mXBlanking, &amp;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-&gt;setConnection(QDBusConnection::sessionBus());
+    m_serviceWatcher-&gt;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&lt;QStringList&gt; 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() &lt;&lt; "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-&gt;lock();
+}
+
+bool SaverEngine::doLock()
+{
+    if (mState == Waiting)
+    {
+        return startLockProcess( ForceLock );
+    }
+    else
+    {
+        // XXX race condition here
+        ::kill(mLockProcess-&gt;pid(), SIGHUP);
+        return false;
+    }
+}
+
+void SaverEngine::processLockTransactions()
+{
+    QList&lt;QDBusMessage&gt;::ConstIterator it = mLockTransactions.constBegin(),
+                                      end = mLockTransactions.constEnd();
+    for ( ; it != end; ++it )
+    {
+        QDBusConnection::sessionBus().send(*it);
+    }
+    mLockTransactions.clear();
+}
+
+void SaverEngine::saverLockReady()
+{
+    if( mState != Preparing )
+    {
+        kDebug() &lt;&lt; "Got unexpected saverLockReady()";
+        return;
+    }
+    kDebug() &lt;&lt; "Saver Lock Ready";
+    processLockTransactions();
+    if (m_nr_throttled)
+        ::kill(mLockProcess-&gt;pid(), SIGSTOP);
+}
+
+void SaverEngine::SimulateUserActivity()
+{
+    XForceScreenSaver( QX11Info::display(), ScreenSaverReset );
+    if ( mXAutoLock &amp;&amp; mState == Waiting )
+    {
+        mXAutoLock-&gt;resetTrigger();
+    }
+    else if (mLockProcess)
+    {
+        ::kill(mLockProcess-&gt;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 &amp;&amp; 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-&gt;setTimeout(timeout);
+        mXAutoLock-&gt;setDPMS(true);
+#ifdef NOT_FREAKIN_UGLY
+        mXAutoLock-&gt;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-&gt;start();
+        kDebug() &lt;&lt; "Saver Engine started, timeout: " &lt;&lt; timeout;
+    }
+    else
+    {
+        delete mXAutoLock;
+        mXAutoLock = 0;
+        kDebug() &lt;&lt; "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()-&gt;readConfig();
+
+    enable( KScreenSaverSettings::screenSaverEnabled(), true );
+}
+
+//---------------------------------------------------------------------------
+//
+// Start the screen saver.
+//
+bool SaverEngine::startLockProcess( LockType lock_type )
+{
+    Q_ASSERT(mState == Waiting);
+
+    kDebug() &lt;&lt; "SaverEngine: starting saver";
+
+    QString path = KStandardDirs::findExe( QLatin1String( "kscreenlocker" ) );
+    if( path.isEmpty())
+    {
+        kDebug() &lt;&lt; "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 &lt;&lt; path;
+    switch( lock_type )
+    {
+    case ForceLock:
+        *mLockProcess &lt;&lt; QLatin1String( "--forcelock" );
+        break;
+    case DontLock:
+        *mLockProcess &lt;&lt; QLatin1String( "--dontlock" );
+        break;
+    case PlasmaSetup:
+        *mLockProcess &lt;&lt; QLatin1String( "--plasmasetup" );
+        break;
+    default:
+        break;
+    }
+
+    m_actived_time = time( 0 );
+    mLockProcess-&gt;start();
+    if (mLockProcess-&gt;waitForStarted() == false )
+    {
+        kDebug() &lt;&lt; "Failed to start kscreenlocker!";
+        delete mLockProcess;
+        mLockProcess = 0;
+        m_actived_time = -1;
+        return false;
+    }
+
+    if (mXAutoLock)
+    {
+        mXAutoLock-&gt;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 &amp;&amp; calledFromDBus()) {
+        mLockTransactions.append(message().createReply());
+        setDelayedReply(true);
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+//
+// Stop the screen saver.
+//
+void SaverEngine::stopLockProcess()
+{
+    Q_ASSERT(mState != Waiting);
+    kDebug() &lt;&lt; "SaverEngine: stopping lock process";
+
+    mLockProcess-&gt;kill();
+}
+
+void SaverEngine::lockProcessExited()
+{
+    Q_ASSERT(mState != Waiting);
+    kDebug() &lt;&lt; "SaverEngine: lock process exited";
+
+    delete mLockProcess;
+    mLockProcess = 0;
+
+    if (mXAutoLock)
+    {
+        mXAutoLock-&gt;start();
+    }
+
+    processLockTransactions();
+    emit ActiveChanged(false); // DBus signal
+    m_actived_time = -1;
+    mState = Waiting;
+    m_screenLocker-&gt;unlock();
+}
+
+//---------------------------------------------------------------------------
+//
+// XAutoLock has detected the required idle time.
+//
+void SaverEngine::idleTimeout()
+{
+    if( mState != Waiting )
+        return; // already saving
+
+    m_screenLocker-&gt;lock();
+}
+
+xautolock_corner_t SaverEngine::applyManualSettings(int action)
+{
+    if (action == 0)
+    {
+        kDebug() &lt;&lt; "no lock";
+        return ca_nothing;
+    }
+    else if (action == 1)
+    {
+        kDebug() &lt;&lt; "lock screen";
+        return ca_forceLock;
+    }
+    else if (action == 2)
+    {
+        kDebug() &lt;&lt; "prevent lock";
+        return ca_dontLock;
+    }
+    else
+    {
+        kDebug() &lt;&lt; "no lock nothing";
+        return ca_nothing;
+    }
+}
+
+uint SaverEngine::GetSessionIdleTime()
+{
+    return mXAutoLock ? mXAutoLock-&gt;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 &amp;/*application_name*/, const QString &amp;/*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-&gt;addWatchedService(sr.dbusid);
+    m_nr_inhibited++;
+    if (KScreenSaverSettings::screenSaverEnabled())
+        enable( false );
+    return sr.cookie;
+}
+
+void SaverEngine::UnInhibit(uint cookie)
+{
+    QMutableListIterator&lt;ScreenSaverRequest&gt; 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 &amp;/*application_name*/, const QString &amp;/*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-&gt;addWatchedService(sr.dbusid);
+    m_nr_throttled++;
+    if (mLockProcess)
+        // XXX race condition here (locker may be not ready yet)
+        ::kill(mLockProcess-&gt;pid(), SIGSTOP);
+    return sr.cookie;
+}
+
+void SaverEngine::UnThrottle(uint cookie)
+{
+    QMutableListIterator&lt;ScreenSaverRequest&gt; it( m_requests );
+    while ( it.hasNext() )
+    {
+        if ( it.next().cookie == cookie ) {
+            it.remove();
+            if ( !--m_nr_throttled )
+                if (mLockProcess)
+                    ::kill(mLockProcess-&gt;pid(), SIGCONT);
+        }
+    }
+}
+
+void SaverEngine::serviceUnregistered(const QString&amp; name)
+{
+    m_serviceWatcher-&gt;removeWatchedService( name );
+    QListIterator&lt;ScreenSaverRequest&gt; it( m_requests );
+    while ( it.hasNext() )
+    {
+        const ScreenSaverRequest &amp;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 &lt;mjones@kde.org&gt;
+//
+
+#ifndef SAVERENGINE_H
+#define SAVERENGINE_H
+
+#include &lt;QWidget&gt;
+#include &lt;QVector&gt;
+#include &lt;QDBusContext&gt;
+#include &lt;QDBusMessage&gt;
+
+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 &amp;application_name, const QString &amp;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 &amp;application_name, const QString &amp;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&amp;);
+
+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&lt;ScreenSaverRequest&gt; m_requests;
+    QDBusServiceWatcher *m_serviceWatcher;
+    uint        m_next_cookie;
+    
+    int        m_nr_throttled;
+    int        m_nr_inhibited;
+ 
+    QList&lt;QDBusMessage&gt; 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 &lt;mjones@kde.org&gt;
+// Copyright 2003 Lubos Lunak &lt;l.lunak@kde.org&gt;
+//
+// KDE screensaver engine
+//
+
+#include &lt;config-workspace.h&gt;
+
+#include "xautolock.h"
+#include "xautolock_c.h"
+
+#include &lt;kapplication.h&gt;
+#include &lt;kdebug.h&gt;
+
+#include &lt;QTimerEvent&gt;
+#include &lt;QX11Info&gt;
+
+#include &lt;X11/Xlib.h&gt;
+#include &lt;X11/Xutil.h&gt;
+
+#ifdef HAVE_DPMS
+extern "C" {
+#include &lt;X11/Xmd.h&gt;
+#ifndef Bool
+#define Bool BOOL
+#endif
+#include &lt;X11/extensions/dpms.h&gt;
+
+#ifndef HAVE_DPMSINFO_PROTO
+Status DPMSInfo ( Display *, CARD16 *, BOOL * );
+#endif
+}
+#endif
+
+#include &lt;ctime&gt;
+
+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(), &amp;dummy, &amp;dummy ))
+    {
+        mMitInfo = XScreenSaverAllocInfo();
+    }
+    else
+#endif
+    {
+        kapp-&gt;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(), &amp;state, &amp;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 &gt; newT)
+        mTrigger = newT;
+}
+
+//---------------------------------------------------------------------------
+//
+// Process new windows and check the mouse.
+//
+void XAutoLock::timerEvent(QTimerEvent *ev)
+{
+    if (ev-&gt;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 &lt; mMitInfo-&gt;idle)
+            mLastIdle = mMitInfo-&gt;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 &gt;= mTrigger)
+        activate = true;
+
+#ifdef HAVE_DPMS
+    BOOL on;
+    CARD16 state;
+    CARD16 timeout1, timeout2, timeout3;
+    DPMSInfo( QX11Info::display(), &amp;state, &amp;on );
+    DPMSGetTimeouts( QX11Info::display(), &amp;timeout1, &amp;timeout2, &amp;timeout3 );
+
+    // kDebug() &lt;&lt; "DPMSInfo " &lt;&lt; state &lt;&lt; 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 &amp;&amp; (!on || (timeout1 == 0 &amp;&amp; timeout2 == 0 &amp;&amp; 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 &amp;&amp; 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-&gt;type == KeyPress &amp;&amp; !ev-&gt;xkey.send_event
+#ifdef HAVE_XSCREENSAVER
+        &amp;&amp; !mMitInfo
+#endif
+        &amp;&amp; !QWidget::find( ev-&gt;xkey.window ))
+        return true;
+    return false;
+}
+
+bool XAutoLock::ignoreWindow( WId w )
+{
+    if( w != QX11Info::appRootWindow() &amp;&amp; QWidget::find( w ))
+        return true;
+    return false;
+}
+
+time_t XAutoLock::idleTime()
+{
+#ifdef HAVE_XSCREENSAVER
+    if (mMitInfo)
+        return mMitInfo-&gt;idle / 1000;
+#endif
+    return mElapsed - mLastReset;
+}
+
+extern "C"
+void xautolock_resetTriggers()
+{
+  self-&gt;resetTrigger();
+}
+
+extern "C"
+void xautolock_setTrigger( int t )
+{
+  self-&gt;setTrigger( t );
+}
+
+extern "C"
+int xautolock_ignoreWindow( Window w )
+{
+   return self-&gt;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 &lt;mjones@kde.org&gt;
+//
+
+#ifndef __XAUTOLOCK_H__
+#define __XAUTOLOCK_H__
+
+#include &lt;config-xautolock.h&gt;
+
+#include &lt;QWidget&gt;
+
+#include &lt;X11/Xlib.h&gt;
+#ifdef HAVE_XSCREENSAVER
+# include &lt;X11/extensions/scrnsaver.h&gt;
+#endif
+#include &lt;fixx11h.h&gt;
+
+//===========================================================================
+//
+// 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) &amp; 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 &lt;X11/Xlib.h&gt;
+#ifdef __cplusplus
+# include &lt;fixx11h.h&gt;
+#endif
+
+#define DEFAULT_TIMEOUT           600
+
+#define CHECK_INTERVAL           5000      /* ms */
+
+#define CREATION_DELAY             30      /* should be &gt; 10 and
+                                              &lt; 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) &amp; 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 &lt;X11/Xlib.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;time.h&gt;
+
+#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-&gt;window = window;
+  newItem-&gt;creationtime = time (0);
+  newItem-&gt;next = 0;
+
+  if (!queue.head) queue.head = newItem;
+  if ( queue.tail) queue.tail-&gt;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 &amp;&amp; current-&gt;creationtime + age &lt; now)
+    {
+      selectEvents (current-&gt;window, False);
+      queue.head = current-&gt;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, &amp;root, &amp;parent,
+                   &amp;children, &amp;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, &amp;attribs))
+#else
+    {
+    if (!XGetWindowAttributes (queue.display, window, &amp;attribs))
+#endif
+    {
+      return;
+    }
+
+#if 0
+    (void) XSelectInput (queue.display, window, 
+                           SubstructureNotifyMask
+                         | (  (  attribs.all_event_masks
+                               | attribs.do_not_propagate_mask)
+                            &amp; KeyPressMask));
+#else
+    {
+    int mask = SubstructureNotifyMask | attribs.your_event_mask;
+    if( !substructureOnly )
+        {
+        mask |=            (  (  attribs.all_event_masks
+                               | attribs.do_not_propagate_mask)
+                            &amp; 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, &amp;root, &amp;parent,
+                   &amp;children, &amp;nofChildren))
+  {
+    return;
+  }
+
+ /*
+  *  Now do the same thing for all children.
+  */
+  for (i = 0; i &lt; 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, &amp;event))
+    {
+      if (event.type == CreateNotify)
+      {
+        addToQueue (event.xcreatewindow.window);
+      }
+    }
+    else
+    {
+      (void) XNextEvent (queue.display, &amp;event);
+    }
+
+   /*
+    *  Reset the triggers if and only if the event is a
+    *  KeyPress event *and* was not generated by XSendEvent().
+    */
+    if (   event.type == KeyPress
+        &amp;&amp; !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-&gt;type == CreateNotify)
+      {
+        addToQueue (event-&gt;xcreatewindow.window);
+      }
+   /*
+    *  Reset the triggers if and only if the event is a
+    *  KeyPress event *and* was not generated by XSendEvent().
+    */
+    if (   event-&gt;type == KeyPress
+        &amp;&amp; !event-&gt;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 &lt; 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) &amp; 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, &amp;root, &amp;dummyWin, &amp;rootX, &amp;rootY,
+                      &amp;dummyInt, &amp;dummyInt, &amp;mask))
+  {
+   /*
+    *  Pointer has moved to another screen, so let's find out which one.
+    */
+    for (i = -1; ++i &lt; ScreenCount (d); ) 
+    {
+      if (root == RootWindow (d, i)) 
+      {
+        screen = ScreenOfDisplay (d, i);
+        break;
+      }
+    }
+  }
+
+  if (   rootX == prevRootX
+      &amp;&amp; rootY == prevRootY
+      &amp;&amp; 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 &lt;= cornerSize &amp;&amp; rootX &gt;= 0
+            &amp;&amp; rootY &lt;= cornerSize &amp;&amp; rootY &gt;= 0)
+        || (corner++,
+               rootX &gt;= WidthOfScreen  (screen) - cornerSize - 1
+            &amp;&amp; rootY &lt;= cornerSize)
+        || (corner++,
+               rootX &lt;= cornerSize
+            &amp;&amp; rootY &gt;= HeightOfScreen (screen) - cornerSize - 1)
+        || (corner++,
+               rootX &gt;= WidthOfScreen  (screen) - cornerSize - 1
+            &amp;&amp; rootY &gt;= 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 &lt;http://www.gnu.org/licenses/&gt;.
 #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()-&gt;readSettings();
+    keys = new KActionCollection(this);
+    KActionCollection* actionCollection = keys;
 
     KAction *kaction = qobject_cast&lt;KAction*&gt;(keys-&gt;action("Walk Through Desktops"));
     if (kaction != 0) {
@@ -626,6 +629,7 @@ void Workspace::readShortcuts()
         cutWalkThroughWindowsAlternativeReverse = kaction-&gt;globalShortcut();
         connect(kaction, SIGNAL(globalShortcutChanged(QKeySequence)), this, SLOT(slotWalkBackThroughWindowsAlternativeKeyChanged(QKeySequence)));
     }
+    m_screenLocker-&gt;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 &lt;http://www.gnu.org/licenses/&gt;.
 #include "tilinglayout.h"
 
 #include "scripting/scripting.h"
+#include "screenlocker/screenlocker.h"
 
 #include &lt;X11/extensions/shape.h&gt;
 #include &lt;X11/keysym.h&gt;
@@ -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 &lt;http://www.gnu.org/licenses/&gt;.
 #include "sm.h"
 
 #include &lt;X11/Xlib.h&gt;
-
 // 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-&gt;factory()-&gt;supports(AbilityProvidesShadow);
 }
 
+inline Qt::Corner Workspace::decorationCloseButtonCorner()
+{
+    if (!hasDecorationPlugin()) {
+        return Qt::TopRightCorner;
+    }
+    return mgr-&gt;factory()-&gt;closeButtonCorner();
+}
+
 inline bool Workspace::decorationHasAlpha() const
 {
     if (!hasDecorationPlugin()) {
</pre></body></html>