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

List:       kde-active
Subject:    Re: lockscreen and splash screen
From:       Marco Martin <notmart () gmail ! com>
Date:       2011-09-29 19:07:51
Message-ID: 201109292107.51645.notmart () gmail ! com
[Download RAW message or body]

On Wednesday 28 September 2011, Sebastian Kgler wrote:
> > 3) sync the contour-config package with the new stuff in config/ under
> > plasma- mobile: it kills krunner, sets the qml splash as default
> > 
> > 4) cross fingers ;)
> 
> I've packaged it in KDE:Active, the screenlocker works fine (with your
> first set of patches), I'm having problems with the QML splashs screen
> though, it seems to "hang" after loading the initial image, but doesn't
> blend into the next picture.

can you try this new diff?
the splash screen should always go away now

Cheers,
Marco Martin

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

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



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


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

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