[RFC+PATCH] xp-like fast switching
Oswald Buddenhagen
ossi at kde.org
Fri Sep 20 02:42:28 BST 2002
hi,
this patch adds an "open new session" menu entry to the k-menu and
kdesktop's context menu and a button with the same functionality to the
unlock dialog (i took the opportunity to rewrite half of kdesktop_lock
:).
this needs a top-uptodate kdm from head.
i suppose this comes "somewhat" late for 3.1 :}, but never mind, this
stuff is a bit half-baked anyway. you have no possibility to switch to
other sessions except with the usual alt-ctrl-Fn combinations; you don't
even have an overview of the open sessions. so now i'm wondering, how to
implement this best.
- put a manager dialog into kdm. you'd use some cute hotkey or gui
elements like in the attached patch to make it pop up. an extended
version of this would additionally have some key combination like
alt-tab (are shift-alt-ctrl-(left|right) free?) to switch sessions
like windows and desktops.
- put the manager directly into kdesktop, kdesktop_lock and kicker, so
you could directly choose a session from the menues. this is more
obvious to the user, but
- we'd need basically the same code in three apps. any way to share
it?
- it would require bidirectional communication with kdm. no problem,
just that it's some work for me. :)
of course these two approaches are not mutually exclusive ...
if you have any opinions regarding the usefulness of any of them or
suggestions regarding implementation/gui details, you should speak up
now. :)
greetings
--
Hi! I'm a .signature virus! Copy me into your ~/.signature, please!
--
Chaos, panic, and disorder - my work here is done.
-------------- next part --------------
Index: kdesktop/krootwm.cc
===================================================================
RCS file: /home/kde/kdebase/kdesktop/krootwm.cc,v
retrieving revision 1.162
diff -u -r1.162 krootwm.cc
--- kdesktop/krootwm.cc 2002/09/11 08:57:17 1.162
+++ kdesktop/krootwm.cc 2002/09/20 01:07:18
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
+#include <stdlib.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -46,6 +47,7 @@
#include <kdebug.h>
#include <kwindowlistmenu.h>
#include <kmenubar.h>
+#include <qfile.h>
#include "krootwm.h"
#include "kdiconview.h"
@@ -162,6 +164,17 @@
this, SLOT( slotLogout() ), m_actionCollection, "logout" );
}
+ QStringList dmopt =
+ QStringList::split( QChar( ',' ),
+ QString::fromLatin1( ::getenv( "XDM_MANAGED" ) ) );
+ if ( dmopt.findIndex( "rsvd" ) < 0 )
+ xdmFifoName = QString::null;
+ else {
+ xdmFifoName = dmopt.first();
+ new KAction(i18n("Start New Session"), "fork", 0, this,
+ SLOT( slotNewSession() ), m_actionCollection, "newsession" );
+ }
+
initConfig();
}
@@ -267,6 +280,10 @@
if (action)
action->plug( file );
+ action = m_actionCollection->action("newsession");
+ if (action)
+ action->plug( file );
+
desk = new QPopupMenu;
if (m_bDesktopEnabled)
@@ -371,6 +388,10 @@
if (action)
action->plug( desktopMenu );
+ action = m_actionCollection->action("newsession");
+ if (action)
+ action->plug( desktopMenu );
+
connect( desktopMenu, SIGNAL( aboutToShow() ), this, SLOT( slotFileNewAboutToShow() ) );
if (menuBar) {
@@ -604,6 +625,13 @@
m_pDesktop->logout(KApplication::ShutdownConfirmDefault, KApplication::ShutdownTypeDefault);
}
+void KRootWm::slotNewSession() {
+ QFile fifo(xdmFifoName);
+ if (fifo.open(IO_WriteOnly | IO_Raw)) {
+ fifo.writeBlock( "reserve\n", 8 );
+ fifo.close();
+ }
+}
void KRootWm::slotMenuItemActivated(int /* item */ )
{
Index: kdesktop/krootwm.h
===================================================================
RCS file: /home/kde/kdebase/kdesktop/krootwm.h,v
retrieving revision 1.49
diff -u -r1.49 krootwm.h
--- kdesktop/krootwm.h 2002/08/02 21:46:48 1.49
+++ kdesktop/krootwm.h 2002/09/20 01:07:18
@@ -104,6 +104,7 @@
void slotWindowList();
void slotLock();
void slotLogout();
+ void slotNewSession();
private:
KDesktop* m_pDesktop;
@@ -141,6 +142,8 @@
KHelpMenu *help;
QPixmap defaultPixmap;
+
+ QString xdmFifoName;
static KRootWm * s_rootWm;
Index: kdesktop/lock/lockdlg.cc
===================================================================
RCS file: /home/kde/kdebase/kdesktop/lock/lockdlg.cc,v
retrieving revision 1.2
diff -u -r1.2 lockdlg.cc
--- kdesktop/lock/lockdlg.cc 2002/04/03 14:28:52 1.2
+++ kdesktop/lock/lockdlg.cc 2002/09/20 01:07:18
@@ -10,6 +10,8 @@
#include <pwd.h>
#include <sys/types.h>
#include <qlayout.h>
+#include <qframe.h>
+#include <qpushbutton.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kglobalsettings.h>
@@ -17,145 +19,72 @@
#include <kiconloader.h>
#include <kdesu/defaults.h>
#include <kpassdlg.h>
+#include <kdebug.h>
#include "lockdlg.h"
#include "lockdlg.moc"
#include <X11/Xutil.h>
#include <X11/keysym.h>
-#define MAX_PASSWORD_LENGTH 80
+#define PASSDLG_HIDE_TIMEOUT 10000
//===========================================================================
//
// Simple dialog for entering a password.
-// It does not handle password validation.
//
-PasswordDlg::PasswordDlg(QWidget *parent)
- : QFrame(parent)
+PasswordDlg::PasswordDlg(QWidget *parent, bool nsess)
+ : QDialog(parent, "password dialog", true, WStyle_Customize | WStyle_NoBorder)
{
- setFocusPolicy(StrongFocus);
- setFrameStyle(QFrame::Panel | QFrame::Raised);
- setLineWidth(2);
-
- KConfig *config = KGlobal::config();
- config->reparseConfiguration();
- KConfigGroupSaver cgs(config, "Passwords");
- QString val = config->readEntry("EchoMode", "x");
- if (val == "OneStar"
- || (val == "x" && defEchoMode == KPasswordEdit::OneStar))
- mStars = 1;
- else if (val == "ThreeStars"
- || (val == "x" && defEchoMode == KPasswordEdit::ThreeStars))
- mStars = 3;
- else
- mStars = 0;
+ QFrame *winFrame = new QFrame( this );
+ winFrame->setFrameStyle( QFrame::Panel | QFrame::Raised );
+ winFrame->setLineWidth( 2 );
- mBlink = false;
- mPassword = "";
+// setFocusPolicy(StrongFocus);
- QGridLayout *layout = new QGridLayout(this, 2, 3, 20, 10);
+ QGridLayout *layout = new QGridLayout(winFrame, 2, 3, 20, 10);
layout->setResizeMode(QLayout::Minimum);
layout->addColSpacing(1, 20);
- QLabel *pixlabel= new QLabel(this);
+ QLabel *pixlabel= new QLabel(winFrame);
pixlabel->setPixmap(QPixmap(locate("data", "kdesktop/pics/ksslogo.png")));
layout->addMultiCellWidget(pixlabel, 0, 1, 0, 0, QLayout::AlignTop);
QFont font = KGlobalSettings::generalFont();
- font.setPointSize(18);
- QString query = passwordQueryMsg(true);
- mLabel = new QLabel(query, this);
- mLabel->setFont(font);
+ mLabel = new QLabel(passwordQueryMsg(), winFrame);
mLabel->setAlignment(AlignCenter);
+ font.setPointSize(18);
+ mLabel->setFont(font);
+ mLabel->setFixedSize(mLabel->sizeHint());
layout->addWidget(mLabel, 0, 2);
+ mEntry = new KPasswordEdit( winFrame, "password edit" );
font.setPointSize(16);
- mEntry = new QLabel("*********************_", this);
mEntry->setFont(font);
- mEntry->setMinimumHeight(mEntry->sizeHint().height()+5);
- mEntry->setMinimumWidth(mEntry->sizeHint().width()+10);
- mEntry->setFrameStyle(QFrame::Panel | QFrame::Sunken);
- mEntry->setText("");
+ mEntry->installEventFilter(this);
layout->addWidget(mEntry, 1, 2);
- layout->activate();
-
- resize(layout->sizeHint());
-
- mFailedTimerId = 0;
- mBlinkTimerId = startTimer(300);
-}
-
-//---------------------------------------------------------------------------
-//
-// Reset the password to ""
-//
-void PasswordDlg::resetPassword()
-{
- mPassword = "";
- drawStars();
-}
-//---------------------------------------------------------------------------
-//
-// Show "Failed" in the dialog for 1.5 seconds
-//
-void PasswordDlg::showFailed()
-{
- mLabel->setText(i18n("Failed"));
- mFailedTimerId = startTimer(1500);
-}
-
-//---------------------------------------------------------------------------
-//
-// Keyboard events should be passed to this function directly.
-// We accept key presses this way because the keyboard is grabbed, so we
-// don't get any events. There's nicer ways of handling this, but this is
-// simplest.
-//
-void PasswordDlg::keyPressed(XKeyEvent *xKeyEvent)
-{
- KeySym keysym = 0;
- char buffer[10] = "";
- (void)XLookupString(xKeyEvent, buffer, 10, &keysym, 0);
+ if (nsess) {
+ mButton = new QPushButton(i18n("\nStart\n&new\nsession\n"), winFrame, "button");
+ layout->addMultiCellWidget(mButton, 0,1, 3,3, AlignCenter);
+ connect(mButton, SIGNAL(clicked()), SIGNAL(startNewSession()));
+ mButton->installEventFilter(this);
+ } else
+ mButton = 0;
- switch (keysym)
- {
- case XK_BackSpace:
- if (mPassword.length())
- {
- mPassword.truncate(mPassword.length() - 1);
- drawStars();
- }
- break;
-
- default:
- if (mPassword.length() < MAX_PASSWORD_LENGTH && !iscntrl(buffer[0]))
- {
- mPassword += buffer[0];
- drawStars();
- }
- break;
- }
-}
+ layout->activate();
-//---------------------------------------------------------------------------
-//
-// Draws the stars if mStars is true
-//
-void PasswordDlg::drawStars()
-{
- QString s("");
+ resize(layout->sizeHint());
- if (mStars)
- s.fill('*', mPassword.length() * mStars);
+ installEventFilter(this);
- if (mBlink)
- s += "_";
+ mFailedTimerId = 0;
+ mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT);
- mEntry->setText(s);
+ connect(&mPassProc, SIGNAL(processExited(KProcess *)),
+ SLOT(passwordChecked(KProcess *)));
}
//---------------------------------------------------------------------------
@@ -181,14 +110,9 @@
//
// This returns the string to use to ask the user for their password.
//
-QString PasswordDlg::passwordQueryMsg(bool name)
+QString PasswordDlg::passwordQueryMsg()
{
- QString retval("");
- if (name)
- {
- retval = currentUser();
- }
- return i18n("Enter Password") + "\n" + retval;
+ return i18n("Enter Password") + "\n" + currentUser();
}
//---------------------------------------------------------------------------
@@ -197,19 +121,155 @@
//
void PasswordDlg::timerEvent(QTimerEvent *ev)
{
- if (ev->timerId() == mBlinkTimerId)
+ if (ev->timerId() == mTimeoutTimerId)
{
- // Show/hide the password entry cursor.
- mBlink = !mBlink;
- drawStars();
+ reject();
}
else if (ev->timerId() == mFailedTimerId)
{
- // Show the normal password prompt.
- mLabel->setText(passwordQueryMsg(true));
- drawStars();
killTimer(mFailedTimerId);
mFailedTimerId = 0;
+ // Show the normal password prompt.
+ mLabel->setText(passwordQueryMsg());
+ mEntry->erase();
+ mEntry->setEnabled(true);
+ if( mButton )
+ mButton->setEnabled(true);
+ }
+}
+
+#undef KeyPress /* i hate X #defines */
+
+bool PasswordDlg::eventFilter( QObject *, QEvent *ev )
+{
+ if ( ev->type() == QEvent::KeyPress ) {
+ killTimer(mTimeoutTimerId);
+ mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT);
+ QKeyEvent *e = (QKeyEvent *)ev;
+ if ( ( e->state() == 0 &&
+ ( e->key() == Key_Enter || e->key() == Key_Return ) ) ||
+ ( e->state() & Keypad && e->key() == Key_Enter ) ) {
+ if ( focusWidget() == mButton )
+ mButton->animateClick();
+ else if ( focusWidget() == mEntry )
+ startCheckPassword();
+ return true;
+ }
+ } else if (ev->type() == QEvent::ContextMenu)
+ return true;
+ return false;
+}
+
+//---------------------------------------------------------------------------
+//
+// Starts the kcheckpass process to check the user's password.
+//
+// Serge Droz <serge.droz at pso.ch> 10.2000
+// Define ACCEPT_ENV if you want to pass an environment variable to
+// kcheckpass. Define ACCEPT_ARGS if you want to pass command line
+// arguments to kcheckpass
+#define ACCEPT_ENV
+//#define ACCEPT_ARGS
+void PasswordDlg::startCheckPassword()
+{
+ const char *passwd = mEntry->password();
+ if (passwd && *passwd)
+ {
+ if( mButton )
+ mButton->setEnabled(false);
+ mEntry->setEnabled(false);
+
+ QString kcp_binName = KStandardDirs::findExe("kcheckpass");
+
+ mPassProc.clearArguments();
+ mPassProc << kcp_binName;
+
+#ifdef HAVE_PAM
+# ifdef ACCEPT_ENV
+ setenv("KDE_PAM_ACTION", KSCREENSAVER_PAM_SERVICE, 1);
+# elif defined(ACCEPT_ARGS)
+ mPassProc << "-c" << KSCREENSAVER_PAM_SERVICE;
+# endif
+#endif
+ bool ret = mPassProc.start(KProcess::NotifyOnExit, KProcess::Stdin);
+#ifdef HAVE_PAM
+# ifdef ACCEPT_ENV
+ unsetenv("KDE_PAM_ACTION");
+# endif
+#endif
+ if (ret == false)
+ {
+ kdDebug(1204) << "kcheckpass failed to start" << endl;
+ mLabel->setText(i18n("Verification failed\nKill kdesktop_lock"));
+ mFailedTimerId = startTimer(10000);
+ return;
+ }
+
+ // write Password to stdin
+ mPassProc.writeStdin(passwd, strlen(passwd));
+ mPassProc.closeStdin();
+ }
+}
+
+//---------------------------------------------------------------------------
+//
+// The kcheckpass process has exited.
+//
+void PasswordDlg::passwordChecked(KProcess *proc)
+{
+ if (proc == &mPassProc)
+ {
+ /* the exit codes of kcheckpass:
+ 0: everything fine
+ 1: authentification failed
+ 2: passwd access failed [permissions/misconfig]
+ */
+ if (mPassProc.normalExit() && !mPassProc.exitStatus())
+ {
+/*
+XXX this needs to go into a separate routine at startup time
+ stopSaver();
+ if ( mPassProc.exitStatus() == 2 )
+ {
+ KMessageBox::error(0,
+ i18n( "<h1>Screen Locking Failed!</h1>"
+ "Your screen was not locked because the <i>kcheckpass</i> "
+ "program was not able to check your password. This is "
+ "usually the result of kcheckpass not being installed "
+ "correctly. If you installed KDE yourself, reinstall "
+ "kcheckpass as root. If you are using a pre-compiled "
+ "package, contact the packager." ),
+ i18n( "Screen Locking Failed" ) );
+ }
+ kapp->quit();
+*/
+ accept();
+ }
+ else
+ {
+ mLabel->setText(i18n("Failed"));
+ mFailedTimerId = startTimer(1500);
+ }
}
}
+// see the comment at the top of lockprocess.cpp
+// with certain unreasonable focus policies (focus under mouse, ehm),
+// KWin interferes and doesn't make the dialog focused, so we have
+// to focus it manually (moving mouse doesn't help because of mouse grab)
+// the right fix is of course override_redirect, so KWin won't get in the way
+// and we can call setActiveWindow() and setFocus() without waiting
+void PasswordDlg::show()
+{
+ QDialog::show();
+ QApplication::flushX();
+ for(;;)
+ { // wait for the window to get mapped
+ XWindowAttributes attrs;
+ if( XGetWindowAttributes( qt_xdisplay(), winId(), &attrs )
+ && attrs.map_state != IsUnmapped )
+ break;
+ }
+ setActiveWindow();
+ setFocus();
+}
Index: kdesktop/lock/lockdlg.h
===================================================================
RCS file: /home/kde/kdebase/kdesktop/lock/lockdlg.h,v
retrieving revision 1.1
diff -u -r1.1 lockdlg.h
--- kdesktop/lock/lockdlg.h 2002/03/02 22:53:37 1.1
+++ kdesktop/lock/lockdlg.h 2002/09/20 01:07:18
@@ -8,62 +8,48 @@
#ifndef __LOCKDLG_H__
#define __LOCKDLG_H__
-#include <qframe.h>
-#include <qlabel.h>
+#include <qlabel.h>
+#include <qdialog.h>
+#include <kprocess.h>
#include <X11/Xlib.h>
+class KPasswordEdit;
+class QPushButton;
+
//===========================================================================
//
// Simple dialog for entering a password.
// It does not handle password validation.
//
-class PasswordDlg : public QFrame
+class PasswordDlg : public QDialog
{
Q_OBJECT
+
public:
- PasswordDlg(QWidget *parent);
+ PasswordDlg(QWidget *parent, bool msess);
+ virtual void show();
- //-----------------------------------------------------------------------
- //
- // Reset the password to ""
- //
- void resetPassword();
-
- //-----------------------------------------------------------------------
- //
- // Show "Failed" in the dialog for 1.5 seconds
- //
- void showFailed();
-
- //-----------------------------------------------------------------------
- //
- // Keyboard events should be passed to this function directly.
- // We accept key presses this way because the keyboard is grabbed, so we
- // don't get any events. There's nicer ways of handling this, but this
- // is simplest.
- //
- void keyPressed(XKeyEvent *);
-
- //-----------------------------------------------------------------------
- //
- // return the password the user entered.
- //
- QString password() const { return mPassword; }
+signals:
+ void startNewSession();
protected:
- void drawStars();
- QString currentUser();
- QString passwordQueryMsg(bool name);
virtual void timerEvent(QTimerEvent *);
+ virtual bool eventFilter(QObject *, QEvent *);
+protected slots:
+ void passwordChecked(KProcess *);
+
private:
+ void startCheckPassword();
+ QString currentUser();
+ QString passwordQueryMsg();
+
int mFailedTimerId;
- int mBlinkTimerId;
+ int mTimeoutTimerId;
QLabel *mLabel;
- QLabel *mEntry;
- QString mPassword;
- int mStars;
- bool mBlink;
+ KPasswordEdit *mEntry;
+ QPushButton *mButton;
+ KProcess mPassProc;
};
#endif
Index: kdesktop/lock/lockprocess.cc
===================================================================
RCS file: /home/kde/kdebase/kdesktop/lock/lockprocess.cc,v
retrieving revision 1.6
diff -u -r1.6 lockprocess.cc
--- kdesktop/lock/lockprocess.cc 2002/08/07 08:36:17 1.6
+++ kdesktop/lock/lockprocess.cc 2002/09/20 01:07:19
@@ -14,6 +14,14 @@
//crashes (e.g. because it's set to multiple wallpapers and
//some image will be corrupted).
+
+// This stuff should be probably rewritten to use override_redirect
+// (WX11BypassWM) windows. This process grabs the mouse and the keyboard,
+// and basically pretends there's no WM anyway. If there will be some
+// more problems with focus, window showing or whatever related,
+// tell KWin developers.
+// See also PasswordDlg::show().
+
#include <config.h>
#include <stdlib.h>
@@ -36,6 +44,7 @@
#include "lockprocess.h"
#include "lockprocess.moc"
+#include "lockdlg.h"
#ifdef HAVE_SETPRIORITY
#include <sys/time.h>
@@ -47,10 +56,8 @@
#include <X11/keysym.h>
#include <X11/Xatom.h>
-#define PASSDLG_HIDE_TIMEOUT 10000
#define LOCK_GRACE_DEFAULT 5000
-int ignoreXError(Display *, XErrorEvent *);
static Window gVRoot = 0;
static Window gVRootData = 0;
static Atom gXA_VROOT;
@@ -95,11 +102,6 @@
KGlobal::dirs()->kde_default("apps") +
relPath);
- mState = Saving;
- mPassDlg = 0;
- mHidePassTimerId = 0;
- mCheckPassTimerId = 0;
- mCheckingPass = false;
mLockOnce = false;
// virtual root property
@@ -110,15 +112,13 @@
XGetWindowAttributes(qt_xdisplay(), winId(), &attrs);
mColorMap = attrs.colormap;
- connect(&mPassProc, SIGNAL(processExited(KProcess *)),
- SLOT(passwordChecked(KProcess *)));
connect(&mHackProc, SIGNAL(processExited(KProcess *)),
SLOT(hackExited(KProcess *)));
QStringList dmopt =
QStringList::split( QChar( ',' ),
QString::fromLatin1( ::getenv( "XDM_MANAGED" ) ) );
- if ( dmopt.isEmpty() || dmopt.first()[0] != QChar( '/' ) )
+ if (dmopt.findIndex( "rsvd" ) < 0)
mXdmFifoName = QString::null;
else
mXdmFifoName = dmopt.first();
@@ -132,7 +132,6 @@
//
LockProcess::~LockProcess()
{
- hidePassDlg();
}
static int sigterm_pipe[ 2 ];
@@ -206,10 +205,7 @@
//---------------------------------------------------------------------------
void LockProcess::quitSaver()
{
- if (mState == Saving)
- {
- stopSaver();
- }
+ stopSaver();
kapp->quit();
}
@@ -240,10 +236,7 @@
QTimer::singleShot(lockGrace, this, SLOT(actuallySetLock()));
}
- else
- {
- mLock = false;
- }
+ mLock = false;
mPriority = config.readNumEntry("Priority", 19);
if (mPriority < 0) mPriority = 0;
@@ -307,7 +300,7 @@
attr.colormap = DefaultColormapOfScreen(
ScreenOfDisplay(qt_xdisplay(), qt_xscreen()));
}
- attr.event_mask = KeyPressMask | ButtonPressMask | MotionNotify |
+ attr.event_mask = KeyPressMask | ButtonPressMask | PointerMotionMask |
VisibilityChangeMask | ExposureMask;
XChangeWindowAttributes(qt_xdisplay(), winId(),
CWEventMask | CWColormap, &attr);
@@ -345,6 +338,12 @@
}
//---------------------------------------------------------------------------
+static int ignoreXError(Display *, XErrorEvent *)
+{
+ return 0;
+}
+
+//---------------------------------------------------------------------------
//
// Save the current virtual root window
//
@@ -441,6 +440,9 @@
return (rv == GrabSuccess);
}
+#define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \
+ EnterWindowMask | LeaveWindowMask
+
//---------------------------------------------------------------------------
//
// Grab the mouse. Returns true on success
@@ -448,13 +450,8 @@
bool LockProcess::grabMouse()
{
int rv = XGrabPointer( qt_xdisplay(), QApplication::desktop()->winId(),
- True, ButtonPressMask
- | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask
- | PointerMotionMask | PointerMotionHintMask | Button1MotionMask
- | Button2MotionMask | Button3MotionMask | Button4MotionMask
- | Button5MotionMask | ButtonMotionMask | KeymapStateMask,
- GrabModeAsync, GrabModeAsync, None, blankCursor.handle(),
- CurrentTime );
+ True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None,
+ blankCursor.handle(), CurrentTime );
return (rv == GrabSuccess);
}
@@ -500,19 +497,23 @@
//---------------------------------------------------------------------------
//
-// Send KDM (or XDM, if it gets adapted) a command if we lock the screen
+// Send KDM (or XDM, if it gets adapted) a command
//
void LockProcess::xdmFifoCmd(const char *cmd)
{
- if (!mXdmFifoName.isNull() && (mLock || mLockOnce)) {
- QFile fifo(mXdmFifoName);
- if (fifo.open(IO_WriteOnly | IO_Raw)) {
- fifo.writeBlock( cmd, ::strlen(cmd) );
- fifo.close();
- }
+ QFile fifo(mXdmFifoName);
+ if (fifo.open(IO_WriteOnly | IO_Raw)) {
+ fifo.writeBlock( cmd, ::strlen(cmd) );
+ fifo.close();
}
}
+void LockProcess::xdmFifoLockCmd(const char *cmd)
+{
+ if (!mXdmFifoName.isNull() && (mLock || mLockOnce))
+ xdmFifoCmd(cmd);
+}
+
//---------------------------------------------------------------------------
//
// Start the screen saver.
@@ -524,15 +525,13 @@
kdWarning(1204) << "LockProcess::startSaver() grabInput() failed!!!!" << endl;
return;
}
- mState = Saving;
+ mBusy = false;
saveVRoot();
if (parent) {
QSocketNotifier *notifier = new QSocketNotifier(parent, QSocketNotifier::Read, this, "notifier");
connect(notifier, SIGNAL( activated (int)), SLOT( quitSaver()));
- notifier = new QSocketNotifier(parent, QSocketNotifier::Exception, this, "notifier_ex");
- connect(notifier, SIGNAL( activated (int)), SLOT( quitSaver()));
}
createSaverWindow();
move(0, 0);
@@ -542,7 +541,7 @@
raise();
XSync(qt_xdisplay(), False);
if (!child_saver)
- xdmFifoCmd("lock\n");
+ xdmFifoLockCmd("lock\n");
slotStart();
}
@@ -568,10 +567,9 @@
{
kdDebug(1204) << "LockProcess: stopping saver" << endl;
stopHack();
- xdmFifoCmd("unlock\n");
hideSaverWindow();
- hidePassDlg();
if (!child_saver) {
+ xdmFifoLockCmd("unlock\n");
ungrabInput();
const char *out = "GOAWAY!";
for (QValueList<int>::ConstIterator it = child_sockets.begin(); it != child_sockets.end(); ++it)
@@ -580,6 +578,11 @@
mLockOnce = false;
}
+void LockProcess::actuallySetLock()
+{
+ mLock = true;
+}
+
//---------------------------------------------------------------------------
//
bool LockProcess::startHack()
@@ -652,64 +655,25 @@
//
// Show the password dialog
//
-void LockProcess::showPassDlg()
+bool LockProcess::checkPass()
{
- if (mPassDlg)
- {
- hidePassDlg();
- }
- mPassDlg = new PasswordDlg(this);
- QDesktopWidget *desktop = KApplication::desktop();
+ PasswordDlg passDlg(this, !mXdmFifoName.isNull());
+ connect(&passDlg, SIGNAL(startNewSession()), SLOT(startNewSession()));
- QRect rect = mPassDlg->geometry();
- if (child_sockets.isEmpty()) {
+ QDesktopWidget *desktop = KApplication::desktop();
+ QRect rect = passDlg.geometry();
+ if (child_sockets.isEmpty())
rect.moveCenter( desktop->screenGeometry(desktop->screenNumber(QCursor::pos())).center());
- } else
+ else
rect.moveCenter( desktop->screenGeometry(qt_xscreen()).center());
- mPassDlg->move(rect.topLeft() );
-
- mPassDlg->show();
- setPassDlgTimeout(PASSDLG_HIDE_TIMEOUT);
-}
+ passDlg.move(rect.topLeft() );
-//---------------------------------------------------------------------------
-//
-// Hide the password dialog
-//
-void LockProcess::hidePassDlg()
-{
- if (mPassDlg)
- {
- delete mPassDlg;
- mPassDlg = 0;
- killPassDlgTimeout();
- }
-}
-
-//---------------------------------------------------------------------------
-//
-// Hide the password dialog in "t" seconds.
-//
-void LockProcess::setPassDlgTimeout(int t)
-{
- if (mHidePassTimerId)
- {
- killTimer(mHidePassTimerId);
- }
- mHidePassTimerId = startTimer(t);
-}
-
-//---------------------------------------------------------------------------
-//
-// Kill the password dialog hide timer.
-//
-void LockProcess::killPassDlgTimeout()
-{
- if (mHidePassTimerId)
- {
- killTimer(mHidePassTimerId);
- mHidePassTimerId = 0;
- }
+ XChangeActivePointerGrab( qt_xdisplay(), GRABEVENTS,
+ arrowCursor.handle(), CurrentTime);
+ bool rt = passDlg.exec();
+ XChangeActivePointerGrab( qt_xdisplay(), GRABEVENTS,
+ blankCursor.handle(), CurrentTime);
+ return rt;
}
//---------------------------------------------------------------------------
@@ -720,25 +684,25 @@
{
switch (event->type)
{
- case KeyPress:
- return handleKeyPress((XKeyEvent *)event);
+ case FocusIn:
+ case FocusOut:
+ // Hack to tell dialogs to take focus when the keyboard is grabbed
+ event->xfocus.mode = NotifyNormal;
+ break;
+ case KeyPress:
case ButtonPress:
case MotionNotify:
- if (mState == Saving)
+ if (mBusy)
+ break;
+ mBusy = true;
+ if (!(mLock || mLockOnce) || checkPass())
{
- if (mLock || mLockOnce)
- {
- showPassDlg();
- mState = Password;
- }
- else
- {
- stopSaver();
- kapp->quit();
- }
+ stopSaver();
+ kapp->quit();
}
- break;
+ mBusy = false;
+ return true;
case VisibilityNotify:
if (event->xvisibility.state != VisibilityUnobscured &&
@@ -754,175 +718,16 @@
// if (event->xconfigure.window != event->xconfigure.event)
// return true;
- if (mState == Saving || mState == Password)
- {
- raise();
- QApplication::flushX();
- }
+ raise();
+ QApplication::flushX();
break;
}
return false;
}
-
-//---------------------------------------------------------------------------
-//
-// Handle key press event.
-//
-bool LockProcess::handleKeyPress(XKeyEvent *xke)
-{
- switch (mState)
- {
- case Password:
- if (!mCheckingPass)
- {
- KeySym keysym = XLookupKeysym(xke, 0);
- switch (keysym)
- {
- case XK_Escape:
- hidePassDlg();
- mState = Saving;
- break;
-
- case XK_Return:
- case XK_KP_Enter:
- startCheckPassword();
- break;
-
- default:
- setPassDlgTimeout(PASSDLG_HIDE_TIMEOUT);
- mPassDlg->keyPressed(xke);
- }
- }
- break;
-
- case Saving:
- if (mLock || mLockOnce)
- {
- showPassDlg();
- mState = Password;
- }
- else
- {
- stopSaver();
- kapp->quit();
- }
- break;
- }
- return true;
-}
-
-//---------------------------------------------------------------------------
-//
-// Starts the kcheckpass process to check the user's password.
-//
-// Serge Droz <serge.droz at pso.ch> 10.2000
-// Define ACCEPT_ENV if you want to pass an environment variable to
-// kcheckpass. Define ACCEPT_ARGS if you want to pass command line
-// arguments to kcheckpass
-#define ACCEPT_ENV
-//#define ACCEPT_ARGS
-void LockProcess::startCheckPassword()
-{
- const char *passwd = mPassDlg->password().ascii();
- if (passwd)
- {
- QString kcp_binName = KStandardDirs::findExe("kcheckpass");
-
- mPassProc.clearArguments();
- mPassProc << kcp_binName;
-
-#ifdef HAVE_PAM
-# ifdef ACCEPT_ENV
- setenv("KDE_PAM_ACTION", KSCREENSAVER_PAM_SERVICE, 1);
-# elif defined(ACCEPT_ARGS)
- mPassProc << "-c" << KSCREENSAVER_PAM_SERVICE;
-# endif
-#endif
- bool ret = mPassProc.start(KProcess::NotifyOnExit, KProcess::Stdin);
-#ifdef HAVE_PAM
-# ifdef ACCEPT_ENV
- unsetenv("KDE_PAM_ACTION");
-# endif
-#endif
- if (ret == false)
- {
- kdDebug(1204) << "kcheckpass failed to start" << endl;
- return;
- }
-
- // write Password to stdin
- mPassProc.writeStdin(passwd, strlen(passwd));
- mPassProc.closeStdin();
-
- killPassDlgTimeout();
-
- mCheckingPass = true;
- }
-}
-
-//---------------------------------------------------------------------------
-//
-// The kcheckpass process has exited.
-//
-void LockProcess::passwordChecked(KProcess *proc)
-{
- if (proc == &mPassProc)
- {
- /* the exit codes of kcheckpass:
- 0: everything fine
- 1: authentification failed
- 2: passwd access failed [permissions/misconfig]
- */
- if (mPassProc.normalExit() && (mPassProc.exitStatus() != 1))
- {
- stopSaver();
- if ( mPassProc.exitStatus() == 2 )
- {
- KMessageBox::error(0,
- i18n( "<h1>Screen Locking Failed!</h1>"
- "Your screen was not locked because the <i>kcheckpass</i> "
- "program was not able to check your password. This is "
- "usually the result of kcheckpass not being installed "
- "correctly. If you installed KDE yourself, reinstall "
- "kcheckpass as root. If you are using a pre-compiled "
- "package, contact the packager." ),
- i18n( "Screen Locking Failed" ) );
- }
- kapp->quit();
- }
- else
- {
- mPassDlg->showFailed();
- mPassDlg->resetPassword();
- setPassDlgTimeout(PASSDLG_HIDE_TIMEOUT);
- }
-
- mCheckingPass = false;
- }
-}
-//---------------------------------------------------------------------------
-//
-// Handle our timer events.
-//
-void LockProcess::timerEvent(QTimerEvent *ev)
+void LockProcess::startNewSession()
{
- if (ev->timerId() == mHidePassTimerId && !mCheckingPass)
- {
- hidePassDlg();
- mState = Saving;
- }
-}
-
-//---------------------------------------------------------------------------
-int ignoreXError(Display *, XErrorEvent *)
-{
- return 0;
-}
-
-void LockProcess::actuallySetLock()
-{
- mLock = true;
+ xdmFifoCmd("reserve\n");
}
Index: kdesktop/lock/lockprocess.h
===================================================================
RCS file: /home/kde/kdebase/kdesktop/lock/lockprocess.h,v
retrieving revision 1.4
diff -u -r1.4 lockprocess.h
--- kdesktop/lock/lockprocess.h 2002/03/29 07:33:45 1.4
+++ kdesktop/lock/lockprocess.h 2002/09/20 01:07:19
@@ -10,8 +10,9 @@
#include <qwidget.h>
#include <kprocess.h>
-#include "lockdlg.h"
+#include <X11/Xlib.h>
+
//===========================================================================
//
// Screen saver handling process. Handles screensaver window,
@@ -34,23 +35,21 @@
void setChildren(QValueList<int> children) { child_sockets = children; }
void setParent(int fd) { parent = fd; }
-protected:
- virtual bool x11Event(XEvent *);
- virtual void timerEvent(QTimerEvent *);
-
public slots:
void quitSaver();
-protected slots:
- void passwordChecked(KProcess *);
+protected:
+ virtual bool x11Event(XEvent *);
+
+private slots:
void hackExited(KProcess *);
void slotStart();
void sigtermPipeSignal();
+ void startNewSession();
void actuallySetLock();
-protected:
+private:
void configure();
- enum State { Saving, Password };
void readSaver();
void createSaverWindow();
void hideSaverWindow();
@@ -62,36 +61,25 @@
bool grabInput();
void ungrabInput();
void xdmFifoCmd(const char *cmd);
+ void xdmFifoLockCmd(const char *cmd);
void startSaver();
void stopSaver();
bool startHack();
void stopHack();
- void showPassDlg();
- void hidePassDlg();
- void setPassDlgTimeout(int t);
- void killPassDlgTimeout();
- void startCheckPassword();
- bool handleKeyPress(XKeyEvent *xke);
void setupSignals();
+ bool checkPass();
-protected:
- bool mEnabled;
bool mLock;
int mPriority;
bool mLockOnce;
- State mState;
- PasswordDlg *mPassDlg;
+ bool mBusy;
Colormap mColorMap;
- int mHidePassTimerId;
- int mCheckPassTimerId;
- KProcess mPassProc;
KProcess mHackProc;
- bool mCheckingPass;
int mRootWidth;
int mRootHeight;
QString mSaverExec;
- QString mSaver;
- QString mXdmFifoName;
+ QString mSaver;
+ QString mXdmFifoName;
bool child_saver;
QValueList<int> child_sockets;
int parent;
Index: kdesktop/lock/main.cc
===================================================================
RCS file: /home/kde/kdebase/kdesktop/lock/main.cc,v
retrieving revision 1.4
diff -u -r1.4 main.cc
--- kdesktop/lock/main.cc 2002/03/07 16:01:39 1.4
+++ kdesktop/lock/main.cc 2002/09/20 01:07:19
@@ -93,7 +93,7 @@
if (putenv(strdup(env.data()))) {
fprintf(stderr,
- "%s: WARNING: unable to set DISPLAY environment vairable\n",
+ "%s: WARNING: unable to set DISPLAY environment variable\n",
argv[0]);
perror("putenv()");
}
Index: kicker/ui/k_mnu.cpp
===================================================================
RCS file: /home/kde/kdebase/kicker/ui/k_mnu.cpp,v
retrieving revision 1.65
diff -u -r1.65 k_mnu.cpp
--- kicker/ui/k_mnu.cpp 2002/08/25 06:45:15 1.65
+++ kicker/ui/k_mnu.cpp 2002/09/20 01:07:20
@@ -27,6 +27,7 @@
#include <qpainter.h>
#include <qstyle.h>
+#include <qfile.h>
#include <kaboutkde.h>
#include <kglobal.h>
@@ -277,10 +278,19 @@
// insertItem(SmallIconSet("panel"), i18n("Configure Panel"), panelOpMenu);
// subMenus.append(panelOpMenu);
- // lock and logout
if (kapp->authorize("lock_screen"))
insertItem(SmallIconSet("lock"), i18n("Lock Screen"), this, SLOT(slotLock()));
+ QStringList dmopt =
+ QStringList::split( QChar( ',' ),
+ QString::fromLatin1( ::getenv( "XDM_MANAGED" ) ) );
+ if ( dmopt.findIndex( "rsvd" ) < 0 )
+ xdmFifoName = QString::null;
+ else {
+ xdmFifoName = dmopt.first();
+ insertItem(SmallIconSet("fork"), i18n("Start New Session"), this, SLOT(slotNewSession()));
+ }
+
char *user = getlogin();
if (user == 0) user = getenv("LOGNAME");
QString username(user);
@@ -336,6 +346,15 @@
{
QApplication::syncX();
kapp->requestShutDown();
+}
+
+void PanelKMenu::slotNewSession()
+{
+ QFile fifo(xdmFifoName);
+ if (fifo.open(IO_WriteOnly | IO_Raw)) {
+ fifo.writeBlock( "reserve\n", 8 );
+ fifo.close();
+ }
}
void PanelKMenu::slotSaveSession()
Index: kicker/ui/k_mnu.h
===================================================================
RCS file: /home/kde/kdebase/kicker/ui/k_mnu.h,v
retrieving revision 1.21
diff -u -r1.21 k_mnu.h
--- kicker/ui/k_mnu.h 2002/05/13 18:00:21 1.21
+++ kicker/ui/k_mnu.h 2002/09/20 01:07:20
@@ -58,6 +58,7 @@
protected slots:
void slotLock();
void slotLogout();
+ void slotNewSession();
void slotSaveSession();
void slotRunCommand();
void paletteChanged();
@@ -74,6 +75,7 @@
bool loadSidePixmap();
private:
+ QString xdmFifoName;
QPixmap sidePixmap;
QPixmap sideTilePixmap;
int client_id;
More information about the kde-core-devel
mailing list