From c97349f53a15c930ce1f5f53ef37c44318a1981a Mon Sep 17 00:00:00 2001
From: tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>
Date: Wed, 7 Apr 2010 04:18:36 +0000
Subject: Added initial support for pipe-based root-only control of all running
 kdesktop_lock processes Right now this allows a background authentication
 process to display pop-up status messages on all screens

git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1111946 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
---
 kdesktop/lock/Makefile.am    |   4 +-
 kdesktop/lock/infodlg.cc     | 117 +++++++++++++++++++++++++++++++++++++
 kdesktop/lock/infodlg.h      |  51 +++++++++++++++++
 kdesktop/lock/lockprocess.cc | 133 ++++++++++++++++++++++++++++++++++++++-----
 kdesktop/lock/lockprocess.h  |  13 ++++-
 5 files changed, 301 insertions(+), 17 deletions(-)
 create mode 100644 kdesktop/lock/infodlg.cc
 create mode 100644 kdesktop/lock/infodlg.h

diff --git a/kdesktop/lock/Makefile.am b/kdesktop/lock/Makefile.am
index 4af8d4fae..e9963ffab 100644
--- a/kdesktop/lock/Makefile.am
+++ b/kdesktop/lock/Makefile.am
@@ -8,9 +8,9 @@ kdesktop_lock_LDADD    = ../libkdesktopsettings.la ../../kdmlib/libdmctl.la $(LI
 
 bin_PROGRAMS = kdesktop_lock
 
-kdesktop_lock_SOURCES = lockprocess.cc lockdlg.cc autologout.cc main.cc
+kdesktop_lock_SOURCES = lockprocess.cc lockdlg.cc infodlg.cc autologout.cc main.cc
 
-noinst_HEADERS = lockprocess.h lockdlg.h autologout.h main.h
+noinst_HEADERS = lockprocess.h lockdlg.h infodlg.h autologout.h main.h
 
 METASOURCES = AUTO
 
diff --git a/kdesktop/lock/infodlg.cc b/kdesktop/lock/infodlg.cc
new file mode 100644
index 000000000..86351dd7b
--- /dev/null
+++ b/kdesktop/lock/infodlg.cc
@@ -0,0 +1,117 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright (c) 2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+
+#include <config.h>
+
+#include "infodlg.h"
+
+#include <dmctl.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kdesu/defaults.h>
+#include <kpassdlg.h>
+#include <kdebug.h>
+#include <kuser.h>
+#include <dcopref.h>
+#include <kmessagebox.h>
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qmessagebox.h>
+#include <qsimplerichtext.h>
+#include <qlabel.h>
+#include <qstringlist.h>
+#include <qfontmetrics.h>
+#include <qstyle.h>
+#include <qapplication.h>
+#include <qlistview.h>
+#include <qheader.h>
+#include <qcheckbox.h>
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <fixx11h.h>
+
+#ifndef AF_LOCAL
+# define AF_LOCAL	AF_UNIX
+#endif
+
+//===========================================================================
+//
+// Simple dialog for displaying an unlock status or recurring error message
+//
+InfoDlg::InfoDlg(LockProcess *parent)
+    : QDialog(parent, "information dialog", true, WX11BypassWM),
+      mUnlockingFailed(false)
+{
+    frame = new QFrame( this );
+    frame->setFrameStyle( QFrame::Panel | QFrame::Raised );
+    frame->setLineWidth( 2 );
+
+    mpixLabel = new QLabel( frame, "pixlabel" );
+    mpixLabel->setPixmap(DesktopIcon("unlock"));
+
+    KUser user;
+
+    mStatusLabel = new QLabel( "<b> </b>", frame );
+    mStatusLabel->setAlignment( QLabel::AlignCenter );
+
+    QVBoxLayout *unlockDialogLayout = new QVBoxLayout( this );
+    unlockDialogLayout->addWidget( frame );
+
+    QHBoxLayout *layStatus = new QHBoxLayout( 0, 0, KDialog::spacingHint());
+    layStatus->addWidget( mStatusLabel );
+
+    frameLayout = new QGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() );
+    frameLayout->addMultiCellWidget( mpixLabel, 0, 2, 0, 0, AlignTop );
+    frameLayout->addLayout( layStatus, 1, 1 );
+
+    installEventFilter(this);
+}
+
+InfoDlg::~InfoDlg()
+{
+    hide();
+}
+
+void InfoDlg::updateLabel(QString &txt)
+{
+    mStatusLabel->setPaletteForegroundColor(Qt::black);
+    mStatusLabel->setText("<b>" + txt + "</b>");
+}
+
+void InfoDlg::setUnlockIcon()
+{
+    mpixLabel->setPixmap(DesktopIcon("unlock"));
+}
+
+void InfoDlg::setWarningIcon()
+{
+    mpixLabel->setPixmap(DesktopIcon("messagebox_warning"));
+}
+
+void InfoDlg::show()
+{
+    QDialog::show();
+    QApplication::flushX();
+}
+
+#include "infodlg.moc"
diff --git a/kdesktop/lock/infodlg.h b/kdesktop/lock/infodlg.h
new file mode 100644
index 000000000..2eedf6269
--- /dev/null
+++ b/kdesktop/lock/infodlg.h
@@ -0,0 +1,51 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright (c) 2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+//
+
+#ifndef __INFODLG_H__
+#define __INFODLG_H__
+
+#include <qdialog.h>
+#include <qstringlist.h>
+
+class QFrame;
+class QGridLayout;
+class QLabel;
+class KPushButton;
+class QListView;
+
+//===========================================================================
+//
+// Simple dialog for displaying an info message.
+// It does not handle password validation.
+//
+class InfoDlg : public QDialog
+{
+    Q_OBJECT
+
+public:
+    InfoDlg(LockProcess *parent);
+    ~InfoDlg();
+    virtual void show();
+
+    void updateLabel( QString &txt );
+    void setUnlockIcon();
+    void setWarningIcon();
+
+private:
+    QFrame      *frame;
+    QGridLayout *frameLayout;
+    QLabel      *mStatusLabel;
+    QLabel      *mpixLabel;
+    int         mCapsLocked;
+    bool        mUnlockingFailed;
+    QStringList layoutsList;
+    QStringList::iterator currLayout;
+    int         sPid, sFd;
+};
+
+#endif
+
diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc
index a813b6899..75465bb34 100644
--- a/kdesktop/lock/lockprocess.cc
+++ b/kdesktop/lock/lockprocess.cc
@@ -19,6 +19,7 @@
 
 #include "lockprocess.h"
 #include "lockdlg.h"
+#include "infodlg.h"
 #include "autologout.h"
 #include "kdesktopsettings.h"
 
@@ -56,6 +57,16 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+
+#include <linux/stat.h>
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
@@ -108,9 +119,13 @@ LockProcess::LockProcess(bool child, bool useBlankOnly)
       mVisibility(false),
       mRestoreXF86Lock(false),
       mForbidden(false),
-      mAutoLogout(false)
+      mAutoLogout(false),
+      mPipeOpen(false),
+      mInfoMessageDisplayed(false),
+      mForceReject(false)
 {
     setupSignals();
+    setupPipe();
 
     kapp->installX11EventFilter(this);
 
@@ -191,6 +206,9 @@ LockProcess::~LockProcess()
             greetPlugin.info->done();
         greetPlugin.library->unload();
     }
+
+    mPipeOpen = false;
+    //close(mPipe_fd);
 }
 
 static int signal_pipe[2];
@@ -217,6 +235,82 @@ void LockProcess::timerEvent(QTimerEvent *ev)
 	}
 }
 
+void LockProcess::setupPipe()
+{
+    /* Create the FIFO if it does not exist */
+    umask(0);
+    mkdir(FIFO_DIR,0600);
+    mknod(FIFO_FILE, S_IFIFO|0600, 0);
+
+    mPipe_fd = open(FIFO_FILE, O_RDONLY | O_NONBLOCK);
+    if (mPipe_fd > -1) {
+        mPipeOpen = true;
+        QTimer::singleShot( 100, this, SLOT(checkPipe()) );
+    }
+}
+
+void LockProcess::checkPipe()
+{
+    char readbuf[128];
+    int numread;
+    QString to_display;
+
+    if (mPipeOpen == true) {
+        readbuf[0]=' ';
+        numread = read(mPipe_fd, readbuf, 128);
+        readbuf[numread] = 0;
+        if (numread > 0) {
+            if (readbuf[0] == 'C') {
+                printf("Clearing info box!\n\r");
+                mInfoMessageDisplayed=false;
+                if (currentDialog != NULL) {
+                    mForceReject = true;
+                    currentDialog->close();
+                }
+            }
+            if (readbuf[0] == 'T') {
+                to_display = readbuf;
+                to_display = to_display.remove(0,1);
+                printf("Will display info message: %s\n", to_display.ascii());
+                // Lock out password dialogs and close any active dialog
+                mInfoMessageDisplayed=true;
+                if (currentDialog != NULL) {
+                    mForceReject = true;
+                    currentDialog->close();
+                }
+                // Display info message dialog
+                QTimer::singleShot( 100, this, SLOT(checkPipe()) );
+                InfoDlg inDlg( this );
+                inDlg.updateLabel(to_display);
+                inDlg.setUnlockIcon();
+                int ret = execDialog( &inDlg );
+                mForceReject = false;
+                return;
+            }
+            if (readbuf[0] == 'E') {
+                to_display = readbuf;
+                to_display = to_display.remove(0,1);
+                printf("Will display error message: %s\n", to_display.ascii());
+                // Lock out password dialogs and close any active dialog
+                mInfoMessageDisplayed=true;
+                if (currentDialog != NULL) {
+                    mForceReject = true;
+                    currentDialog->close();
+                }
+                // Display info message dialog
+                QTimer::singleShot( 100, this, SLOT(checkPipe()) );
+                InfoDlg inDlg( this );
+                inDlg.updateLabel(to_display);
+                inDlg.setWarningIcon();
+                int ret = execDialog( &inDlg );
+                mForceReject = false;
+                return;
+            }
+        }
+        QTimer::singleShot( 100, this, SLOT(checkPipe()) );
+    }
+}
+
 void LockProcess::setupSignals()
 {
     struct sigaction act;
@@ -907,24 +1001,33 @@ void LockProcess::resume( bool force )
 //
 bool LockProcess::checkPass()
 {
-    if (mAutoLogout)
-        killTimer(mAutoLogoutTimerId);
+    if (mInfoMessageDisplayed == false) {
+        if (mAutoLogout)
+            killTimer(mAutoLogoutTimerId);
 
-    PasswordDlg passDlg( this, &greetPlugin);
+        PasswordDlg passDlg( this, &greetPlugin);
 
-    int ret = execDialog( &passDlg );
+        int ret = execDialog( &passDlg );
+        if (mForceReject == true) {
+            ret = QDialog::Rejected;
+        }
+        mForceReject = false;
 
-    XWindowAttributes rootAttr;
-    XGetWindowAttributes(qt_xdisplay(), RootWindow(qt_xdisplay(),
+        XWindowAttributes rootAttr;
+        XGetWindowAttributes(qt_xdisplay(), RootWindow(qt_xdisplay(),
                         qt_xscreen()), &rootAttr);
-    if(( rootAttr.your_event_mask & SubstructureNotifyMask ) == 0 )
-    {
-        kdWarning() << "ERROR: Something removed SubstructureNotifyMask from the root window!!!" << endl;
-        XSelectInput( qt_xdisplay(), qt_xrootwin(),
-            SubstructureNotifyMask | rootAttr.your_event_mask );
-    }
+        if(( rootAttr.your_event_mask & SubstructureNotifyMask ) == 0 )
+        {
+            kdWarning() << "ERROR: Something removed SubstructureNotifyMask from the root window!!!" << endl;
+            XSelectInput( qt_xdisplay(), qt_xrootwin(),
+                SubstructureNotifyMask | rootAttr.your_event_mask );
+        }
 
-    return ret == QDialog::Accepted;
+        return ret == QDialog::Accepted;
+    }
+    else {
+        return 0;
+    }
 }
 
 static void fakeFocusIn( WId window )
@@ -945,6 +1048,7 @@ static void fakeFocusIn( WId window )
 
 int LockProcess::execDialog( QDialog *dlg )
 {
+    currentDialog=dlg;
     dlg->adjustSize();
 
     QRect rect = dlg->geometry();
@@ -967,6 +1071,7 @@ int LockProcess::execDialog( QDialog *dlg )
         resume( false );
     } else
         fakeFocusIn( mDialogs.first()->winId());
+    currentDialog = NULL;
     return rt;
 }
 
diff --git a/kdesktop/lock/lockprocess.h b/kdesktop/lock/lockprocess.h
index d7043e64d..18a624d57 100644
--- a/kdesktop/lock/lockprocess.h
+++ b/kdesktop/lock/lockprocess.h
@@ -29,6 +29,9 @@ struct GreeterPluginHandle {
     kgreeterplugin_info *info;
 };
 
+#define FIFO_DIR "/tmp/ksocket-global"
+#define FIFO_FILE "/tmp/ksocket-global/kdesktoplockcontrol"
+
 //===========================================================================
 //
 // Screen saver handling process.  Handles screensaver window,
@@ -53,11 +56,12 @@ public:
 
     void msgBox( QMessageBox::Icon type, const QString &txt );
     int execDialog( QDialog* dlg );
-    
+
 public slots:
     void quitSaver();
     void preparePopup();
     void cleanupPopup();
+    void checkPipe();
 
 protected:
     virtual bool x11Event(XEvent *);
@@ -89,6 +93,7 @@ private:
     bool startHack();
     void stopHack();
     void setupSignals();
+    void setupPipe();
     bool checkPass();
     void stayOnTop();
     void lockXF86();
@@ -125,6 +130,12 @@ private:
     int         mAutoLogoutTimerId;
     int         mAutoLogoutTimeout;
     bool        mAutoLogout;
+    bool        mInfoMessageDisplayed;
+    QDialog     *currentDialog;
+    bool        mForceReject;
+
+    bool        mPipeOpen;
+    int         mPipe_fd;
 };
 
 #endif
-- 
cgit v1.2.3

