From 145abc15d57fb29701a12e8a14dcb9c1fd72e9be Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Mon, 7 Dec 2020 22:58:44 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- kdesktop/lock/CMakeLists.txt | 4 +- kdesktop/lock/Makefile.am | 2 +- kdesktop/lock/autologout.cc | 132 -- kdesktop/lock/autologout.cpp | 132 ++ kdesktop/lock/infodlg.cc | 149 -- kdesktop/lock/infodlg.cpp | 149 ++ kdesktop/lock/lockdlg.cc | 1027 -------------- kdesktop/lock/lockdlg.cpp | 1027 ++++++++++++++ kdesktop/lock/lockprocess.cc | 3045 ----------------------------------------- kdesktop/lock/lockprocess.cpp | 3045 +++++++++++++++++++++++++++++++++++++++++ kdesktop/lock/main.cc | 563 -------- kdesktop/lock/main.cpp | 563 ++++++++ kdesktop/lock/querydlg.cc | 163 --- kdesktop/lock/querydlg.cpp | 163 +++ kdesktop/lock/sakdlg.cc | 155 --- kdesktop/lock/sakdlg.cpp | 155 +++ kdesktop/lock/securedlg.cc | 217 --- kdesktop/lock/securedlg.cpp | 217 +++ 18 files changed, 5454 insertions(+), 5454 deletions(-) delete mode 100644 kdesktop/lock/autologout.cc create mode 100644 kdesktop/lock/autologout.cpp delete mode 100644 kdesktop/lock/infodlg.cc create mode 100644 kdesktop/lock/infodlg.cpp delete mode 100644 kdesktop/lock/lockdlg.cc create mode 100644 kdesktop/lock/lockdlg.cpp delete mode 100644 kdesktop/lock/lockprocess.cc create mode 100644 kdesktop/lock/lockprocess.cpp delete mode 100644 kdesktop/lock/main.cc create mode 100644 kdesktop/lock/main.cpp delete mode 100644 kdesktop/lock/querydlg.cc create mode 100644 kdesktop/lock/querydlg.cpp delete mode 100644 kdesktop/lock/sakdlg.cc create mode 100644 kdesktop/lock/sakdlg.cpp delete mode 100644 kdesktop/lock/securedlg.cc create mode 100644 kdesktop/lock/securedlg.cpp (limited to 'kdesktop/lock') diff --git a/kdesktop/lock/CMakeLists.txt b/kdesktop/lock/CMakeLists.txt index 05e14e938..0a8f5603c 100644 --- a/kdesktop/lock/CMakeLists.txt +++ b/kdesktop/lock/CMakeLists.txt @@ -34,8 +34,8 @@ link_directories( set( target kdesktop_lock ) set( ${target}_SRCS - lockprocess.cc lockdlg.cc infodlg.cc querydlg.cc sakdlg.cc - securedlg.cc autologout.cc main.cc + lockprocess.cpp lockdlg.cpp infodlg.cpp querydlg.cpp sakdlg.cpp + securedlg.cpp autologout.cpp main.cpp ) tde_add_executable( ${target} AUTOMOC diff --git a/kdesktop/lock/Makefile.am b/kdesktop/lock/Makefile.am index c686e3ea9..4c2fb22a8 100644 --- a/kdesktop/lock/Makefile.am +++ b/kdesktop/lock/Makefile.am @@ -8,7 +8,7 @@ kdesktop_lock_LDADD = ../libkdesktopsettings.la ../../tdmlib/libdmctl.la $(LI bin_PROGRAMS = kdesktop_lock -kdesktop_lock_SOURCES = lockprocess.cc lockdlg.cc infodlg.cc querydlg.cc autologout.cc main.cc +kdesktop_lock_SOURCES = lockprocess.cpp lockdlg.cpp infodlg.cpp querydlg.cpp autologout.cpp main.cpp noinst_HEADERS = lockprocess.h lockdlg.h infodlg.h querydlg.h autologout.h main.h diff --git a/kdesktop/lock/autologout.cc b/kdesktop/lock/autologout.cc deleted file mode 100644 index 6e05c439d..000000000 --- a/kdesktop/lock/autologout.cc +++ /dev/null @@ -1,132 +0,0 @@ -//=========================================================================== -// -// This file is part of the TDE project -// -// Copyright (c) 2004 Chris Howells - -#include "lockprocess.h" -#include "autologout.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#define COUNTDOWN 30 - -extern bool trinity_desktop_lock_use_system_modal_dialogs; - -AutoLogout::AutoLogout(LockProcess *parent) : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))) -{ - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - setCaption(i18n("Automatic Logout Notification")); - - frame = new TQFrame(this); - if (trinity_desktop_lock_use_system_modal_dialogs) { - frame->setFrameStyle( TQFrame::NoFrame ); - } - else { - frame->setFrameStyle(TQFrame::Panel | TQFrame::Raised); - } - frame->setLineWidth(2); - - TQLabel *pixLabel = new TQLabel( frame, "pixlabel" ); - pixLabel->setPixmap(DesktopIcon("system-log-out")); - - TQLabel *greetLabel = new TQLabel(i18n("Automatic Log Out"), frame); - TQLabel *infoLabel = new TQLabel(i18n("To prevent being logged out, resume using this session by moving the mouse or pressing a key."), frame); - - mStatusLabel = new TQLabel(" ", frame); - mStatusLabel->setAlignment(TQLabel::AlignCenter); - - TQLabel *mProgressLabel = new TQLabel("Time Remaining:", frame); - mProgressRemaining = new TQProgressBar(frame); - mProgressRemaining->setPercentageVisible(false); - - TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); - unlockDialogLayout->addWidget( frame ); - - frameLayout = new TQGridLayout(frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint()); - frameLayout->addMultiCellWidget(pixLabel, 0, 2, 0, 0, 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->setTotalSteps(COUNTDOWN * 25); - - updateInfo(mRemaining); - - mCountdownTimerId = startTimer(1000/25); - - connect(tqApp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity())); - - setFixedSize( sizeHint() ); -} - -AutoLogout::~AutoLogout() -{ - hide(); -} - -void AutoLogout::updateInfo(int timeout) -{ - mStatusLabel->setText(i18n("You will be automatically logged out in 1 second", - "You will be automatically logged out in %n seconds", - timeout / 25) ); - mProgressRemaining->setProgress(timeout); -} - -void AutoLogout::timerEvent(TQTimerEvent *ev) -{ - if (ev->timerId() == mCountdownTimerId) { - updateInfo(mRemaining); - --mRemaining; - if (mRemaining < 0) { - logout(); - } - } -} - -void AutoLogout::slotActivity() -{ - accept(); -} - -void AutoLogout::logout() -{ - TQT_TQOBJECT(this)->killTimers(); - DCOPRef("ksmserver","ksmserver").send("logout", 0, 0, 0); -} - -void AutoLogout::show() -{ - TQDialog::show(); - TQApplication::flushX(); -} - -#include "autologout.moc" diff --git a/kdesktop/lock/autologout.cpp b/kdesktop/lock/autologout.cpp new file mode 100644 index 000000000..6e05c439d --- /dev/null +++ b/kdesktop/lock/autologout.cpp @@ -0,0 +1,132 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 2004 Chris Howells + +#include "lockprocess.h" +#include "autologout.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define COUNTDOWN 30 + +extern bool trinity_desktop_lock_use_system_modal_dialogs; + +AutoLogout::AutoLogout(LockProcess *parent) : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Automatic Logout Notification")); + + frame = new TQFrame(this); + if (trinity_desktop_lock_use_system_modal_dialogs) { + frame->setFrameStyle( TQFrame::NoFrame ); + } + else { + frame->setFrameStyle(TQFrame::Panel | TQFrame::Raised); + } + frame->setLineWidth(2); + + TQLabel *pixLabel = new TQLabel( frame, "pixlabel" ); + pixLabel->setPixmap(DesktopIcon("system-log-out")); + + TQLabel *greetLabel = new TQLabel(i18n("Automatic Log Out"), frame); + TQLabel *infoLabel = new TQLabel(i18n("To prevent being logged out, resume using this session by moving the mouse or pressing a key."), frame); + + mStatusLabel = new TQLabel(" ", frame); + mStatusLabel->setAlignment(TQLabel::AlignCenter); + + TQLabel *mProgressLabel = new TQLabel("Time Remaining:", frame); + mProgressRemaining = new TQProgressBar(frame); + mProgressRemaining->setPercentageVisible(false); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + frameLayout = new TQGridLayout(frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint()); + frameLayout->addMultiCellWidget(pixLabel, 0, 2, 0, 0, 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->setTotalSteps(COUNTDOWN * 25); + + updateInfo(mRemaining); + + mCountdownTimerId = startTimer(1000/25); + + connect(tqApp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity())); + + setFixedSize( sizeHint() ); +} + +AutoLogout::~AutoLogout() +{ + hide(); +} + +void AutoLogout::updateInfo(int timeout) +{ + mStatusLabel->setText(i18n("You will be automatically logged out in 1 second", + "You will be automatically logged out in %n seconds", + timeout / 25) ); + mProgressRemaining->setProgress(timeout); +} + +void AutoLogout::timerEvent(TQTimerEvent *ev) +{ + if (ev->timerId() == mCountdownTimerId) { + updateInfo(mRemaining); + --mRemaining; + if (mRemaining < 0) { + logout(); + } + } +} + +void AutoLogout::slotActivity() +{ + accept(); +} + +void AutoLogout::logout() +{ + TQT_TQOBJECT(this)->killTimers(); + DCOPRef("ksmserver","ksmserver").send("logout", 0, 0, 0); +} + +void AutoLogout::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "autologout.moc" diff --git a/kdesktop/lock/infodlg.cc b/kdesktop/lock/infodlg.cc deleted file mode 100644 index 3efaf060d..000000000 --- a/kdesktop/lock/infodlg.cc +++ /dev/null @@ -1,149 +0,0 @@ -//=========================================================================== -// -// This file is part of the TDE project -// -// Copyright (c) 2010 - 2015 Timothy Pearson - -#include - -#include "infodlg.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifndef AF_LOCAL -# define AF_LOCAL AF_UNIX -#endif - -extern bool trinity_desktop_lock_use_system_modal_dialogs; - -//=========================================================================== -// -// Simple dialog for displaying an unlock status or recurring error message -// -InfoDlg::InfoDlg(LockProcess *parent) - : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), - mUnlockingFailed(false) -{ - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - setCaption(i18n("Information")); - - frame = new TQFrame( this ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - frame->setFrameStyle( TQFrame::NoFrame ); - } - else { - frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); - } - frame->setLineWidth( 2 ); - - mpixLabel = new TQLabel( frame, "pixlabel" ); - mpixLabel->setPixmap(DesktopIcon("unlock")); - - KUser user; - - mStatusLabel = new TQLabel( " ", frame ); - mStatusLabel->setAlignment( TQLabel::AlignCenter ); - - TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); - unlockDialogLayout->addWidget( frame ); - - TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - layStatus->addWidget( mStatusLabel ); - - frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); - frameLayout->addMultiCellWidget( mpixLabel, 0, 2, 0, 0, Qt::AlignTop ); - frameLayout->addLayout( layStatus, 1, 1 ); - - installEventFilter(this); - setFixedSize( sizeHint() ); - } - -InfoDlg::~InfoDlg() -{ - hide(); -} - -void InfoDlg::updateLabel(TQString &txt) -{ - mStatusLabel->setPaletteForegroundColor(Qt::black); - mStatusLabel->setText("" + txt + ""); -} - -void InfoDlg::setUnlockIcon() -{ - mpixLabel->setPixmap(DesktopIcon("unlock")); -} - -void InfoDlg::setKDEIcon() -{ - mpixLabel->setPixmap(DesktopIcon("about_kde")); -} - -void InfoDlg::setInfoIcon() -{ - mpixLabel->setPixmap(DesktopIcon("messagebox_info")); -} - -void InfoDlg::setWarningIcon() -{ - mpixLabel->setPixmap(DesktopIcon("messagebox_warning")); -} - -void InfoDlg::setErrorIcon() -{ - mpixLabel->setPixmap(DesktopIcon("messagebox_critical")); -} - -void InfoDlg::show() -{ - TQDialog::show(); - TQApplication::flushX(); -} - -#include "infodlg.moc" diff --git a/kdesktop/lock/infodlg.cpp b/kdesktop/lock/infodlg.cpp new file mode 100644 index 000000000..3efaf060d --- /dev/null +++ b/kdesktop/lock/infodlg.cpp @@ -0,0 +1,149 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 2010 - 2015 Timothy Pearson + +#include + +#include "infodlg.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; + +//=========================================================================== +// +// Simple dialog for displaying an unlock status or recurring error message +// +InfoDlg::InfoDlg(LockProcess *parent) + : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Information")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + frame->setFrameStyle( TQFrame::NoFrame ); + } + else { + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + } + frame->setLineWidth( 2 ); + + mpixLabel = new TQLabel( frame, "pixlabel" ); + mpixLabel->setPixmap(DesktopIcon("unlock")); + + KUser user; + + mStatusLabel = new TQLabel( " ", frame ); + mStatusLabel->setAlignment( TQLabel::AlignCenter ); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( mpixLabel, 0, 2, 0, 0, Qt::AlignTop ); + frameLayout->addLayout( layStatus, 1, 1 ); + + installEventFilter(this); + setFixedSize( sizeHint() ); + } + +InfoDlg::~InfoDlg() +{ + hide(); +} + +void InfoDlg::updateLabel(TQString &txt) +{ + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText("" + txt + ""); +} + +void InfoDlg::setUnlockIcon() +{ + mpixLabel->setPixmap(DesktopIcon("unlock")); +} + +void InfoDlg::setKDEIcon() +{ + mpixLabel->setPixmap(DesktopIcon("about_kde")); +} + +void InfoDlg::setInfoIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_info")); +} + +void InfoDlg::setWarningIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_warning")); +} + +void InfoDlg::setErrorIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_critical")); +} + +void InfoDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "infodlg.moc" diff --git a/kdesktop/lock/lockdlg.cc b/kdesktop/lock/lockdlg.cc deleted file mode 100644 index d4b456a9e..000000000 --- a/kdesktop/lock/lockdlg.cc +++ /dev/null @@ -1,1027 +0,0 @@ -//=========================================================================== -// -// This file is part of the TDE project -// -// Copyright (c) 1999 Martin R. Jones -// Copyright (c) 2003 Chris Howells -// Copyright (c) 2003 Oswald Buddenhagen -// Copyright (c) 2010 - 2015 Timothy Pearson - -#include - -#include "lockprocess.h" -#include "lockdlg.h" -#include "kdesktopsettings.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef HAVE_KRB5 -#include -#endif - -#ifndef AF_LOCAL -# define AF_LOCAL AF_UNIX -#endif - -#define PASSDLG_HIDE_TIMEOUT dialogHideTimeout - -extern bool trinity_desktop_lock_autohide_lockdlg; -extern bool trinity_desktop_lock_delay_screensaver_start; -extern bool trinity_desktop_lock_use_system_modal_dialogs; -extern bool trinity_desktop_lock_use_sak; -extern bool trinity_desktop_lock_hide_cancel_button; - -int dialogHideTimeout = 10*1000; - -//=========================================================================== -// -// Simple dialog for entering a password. -// -PasswordDlg::PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin) - : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), - mPlugin( plugin ), - mCapsLocked(-1), - mUnlockingFailed(false), - validUserCardInserted(false), - showInfoMessages(true), - mCardLoginInProgress(false) -{ - init(plugin); -} - -// -// Simple dialog for entering a password. -// This version includes support for displaying the date and time the lock process was started -// -PasswordDlg::PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin, TQDateTime lockStartDateTime) - : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), - mPlugin( plugin ), - mCapsLocked(-1), - mUnlockingFailed(false), - showInfoMessages(true), - mCardLoginInProgress(false) -{ - m_lockStartDT = lockStartDateTime; - init(plugin); -} - -void PasswordDlg::init(GreeterPluginHandle *plugin) -{ - dialogHideTimeout = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::timeout()*1000:10*1000; - - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - setCaption(i18n("Desktop Session Locked")); - - frame = new TQFrame( this ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - frame->setFrameStyle( TQFrame::NoFrame ); - } - else { - frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); - } - frame->setLineWidth( 2 ); - - TQLabel *pixLabel = NULL; - if (!trinity_desktop_lock_use_system_modal_dialogs) { - pixLabel = new TQLabel( frame, "pixlabel" ); - pixLabel->setPixmap(DesktopIcon("system-lock-screen")); - } - - KUser user; - TQLabel *greetLabel; - if (trinity_desktop_lock_use_system_modal_dialogs) { - greetLabel = new TQLabel( user.fullName().isEmpty() ? - "" + i18n("This computer is in use and has been locked.") + "" : - "" + i18n("This computer is in use and has been locked.") + "
" + i18n("Only '%1' may unlock this session.").arg( user.fullName() ), frame ); - } - else { - greetLabel = new TQLabel( user.fullName().isEmpty() ? - i18n("The session is locked
") : - i18n("
The session was locked by %1
").arg( user.fullName() ), frame ); - } - - TQLabel *lockDTLabel = NULL; - if ((trinity_desktop_lock_use_system_modal_dialogs) && (!m_lockStartDT.isNull())) { - lockDTLabel = new TQLabel(i18n("This session has been locked since %1").arg(m_lockStartDT.toString()), frame); - } - - mStatusLabel = new TQLabel( " ", frame ); - mStatusLabel->setAlignment( TQLabel::AlignCenter ); - - mLayoutButton = new TQPushButton( frame ); - mLayoutButton->setFlat( true ); - - KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); - - mNewSessButton = new KPushButton( KGuiItem(i18n("Sw&itch User..."), "fork"), frame ); - ok = new KPushButton( i18n("Unl&ock"), frame ); - ok->setDefault(true); - - bool show_cancel_button = !trinity_desktop_lock_hide_cancel_button - || trinity_desktop_lock_use_sak - || !trinity_desktop_lock_use_system_modal_dialogs; - if (show_cancel_button) { - cancel = new KPushButton( KStdGuiItem::cancel(), frame ); - } - else { - cancel = NULL; - } - - greet = plugin->info->create( this, 0, this, mLayoutButton, TQString::null, - KGreeterPlugin::Authenticate, KGreeterPlugin::ExUnlock ); - - TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); - unlockDialogLayout->addWidget( frame ); - - TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - layStatus->addWidget( mStatusLabel ); - layStatus->addWidget( mLayoutButton ); - - TQHBoxLayout *layButtons = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - layButtons->addWidget( mNewSessButton ); - layButtons->addStretch(); - layButtons->addWidget(ok); - if (show_cancel_button) { - layButtons->addWidget(cancel); - } - - if (trinity_desktop_lock_use_system_modal_dialogs) { - KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); - - if (!m_lockStartDT.isNull()) { - frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); - frameLayout->addMultiCellWidget( theader, 0, 0, 0, 2, Qt::AlignTop ); - frameLayout->addWidget( greetLabel, 1, 1 ); - frameLayout->addWidget( lockDTLabel, 2, 1 ); - frameLayout->addItem( greet->getLayoutItem(), 3, 1 ); - frameLayout->addLayout( layStatus, 4, 1 ); - frameLayout->addMultiCellWidget( sep, 5, 5, 0, 1 ); - frameLayout->addMultiCellLayout( layButtons, 6, 6, 0, 1 ); - } - else { - frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); - frameLayout->addMultiCellWidget( theader, 0, 0, 0, 2, Qt::AlignTop ); - frameLayout->addWidget( greetLabel, 1, 1 ); - frameLayout->addItem( greet->getLayoutItem(), 2, 1 ); - frameLayout->addLayout( layStatus, 3, 1 ); - frameLayout->addMultiCellWidget( sep, 4, 4, 0, 1 ); - frameLayout->addMultiCellLayout( layButtons, 5, 5, 0, 1 ); - } - } - else { - frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); - frameLayout->addMultiCellWidget( pixLabel, 0, 2, 0, 0, Qt::AlignTop ); - frameLayout->addWidget( greetLabel, 0, 1 ); - frameLayout->addItem( greet->getLayoutItem(), 1, 1 ); - frameLayout->addLayout( layStatus, 2, 1 ); - frameLayout->addMultiCellWidget( sep, 3, 3, 0, 1 ); - frameLayout->addMultiCellLayout( layButtons, 4, 4, 0, 1 ); - } - - if (show_cancel_button) { - setTabOrder( ok, cancel ); - setTabOrder( cancel, mNewSessButton ); - } - else { - setTabOrder( ok, mNewSessButton ); - } - setTabOrder( mNewSessButton, mLayoutButton ); - - connect(mLayoutButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(layoutClicked())); - if (show_cancel_button) { - connect(cancel, TQT_SIGNAL(clicked()), TQT_SLOT(reject())); - } - connect(ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotOK())); - connect(mNewSessButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotSwitchUser())); - - if (!DM().isSwitchable() || !kapp->authorize("switch_user")) { - mNewSessButton->hide(); - } - - installEventFilter(this); - setFixedSize( sizeHint() ); - - mFailedTimerId = 0; - mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT); - connect(tqApp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity()) ); - - greet->setInfoMessageDisplay(showInfoMessages); - greet->start(); - - DCOPRef kxkb("kxkb", "kxkb"); - if( !kxkb.isNull() ) { - DCOPReply reply = kxkb.call("getLayoutsList"); - if (reply.isValid()) { - layoutsList = reply; - } - reply = kxkb.call("getCurrentLayout"); - TQString currentLayout; - if (reply.isValid()) { - reply.get(currentLayout); - } - if( !currentLayout.isEmpty() && layoutsList.count() > 1 ) { - currLayout = layoutsList.find(currentLayout); - if (currLayout == layoutsList.end()) - setLayoutText("err"); - else - setLayoutText(*currLayout); - } - else { - mLayoutButton->hide(); - } - } - else { - mLayoutButton->hide(); // no kxkb running - } - capsLocked(); - - if (static_cast< LockProcess* >(parent())->cryptographicCardDevice()) { - attemptCardLogin(); - } -} - -PasswordDlg::~PasswordDlg() -{ - hide(); - frameLayout->removeItem( greet->getLayoutItem() ); - delete greet; -} - -void PasswordDlg::reject() -{ - if (!trinity_desktop_lock_hide_cancel_button - || trinity_desktop_lock_use_sak - || !trinity_desktop_lock_use_system_modal_dialogs - || trinity_desktop_lock_autohide_lockdlg) { - TQDialog::reject(); - } -} - -void PasswordDlg::layoutClicked() -{ - if( ++currLayout == layoutsList.end() ) { - currLayout = layoutsList.begin(); - } - - DCOPRef kxkb("kxkb", "kxkb"); - setLayoutText( kxkb.call("setLayout", *currLayout) ? *currLayout : "err" ); - -} - -void PasswordDlg::setLayoutText( const TQString &txt ) -{ - mLayoutButton->setText( txt ); - TQSize sz = mLayoutButton->fontMetrics().size( 0, txt ); - int mrg = mLayoutButton->style().pixelMetric( TQStyle::PM_ButtonMargin ) * 2; - mLayoutButton->setFixedSize( sz.width() + mrg, sz.height() + mrg ); -} - -void PasswordDlg::updateLabel() -{ - if (mUnlockingFailed) { - mStatusLabel->setPaletteForegroundColor(Qt::black); - mStatusLabel->setText(i18n("Unlocking failed")); -// mStatusLabel->show(); - } - else if (mCapsLocked) { - mStatusLabel->setPaletteForegroundColor(Qt::red); - mStatusLabel->setText(i18n("Warning: Caps Lock on")); -// mStatusLabel->show(); - } - else { - mStatusLabel->setText(" "); -// mStatusLabel->hide(); - } -} - -//--------------------------------------------------------------------------- -// -// Handle timer events. -// -void PasswordDlg::timerEvent(TQTimerEvent *ev) -{ - if (ev->timerId() == mTimeoutTimerId) { - if (trinity_desktop_lock_autohide_lockdlg) { - // Force dialog rejection regardless of the value of trinity_desktop_lock_hide_cancel_button - TQDialog::reject(); - } - else { - slotActivity(); - } - } - else if (ev->timerId() == mFailedTimerId) { - killTimer(mFailedTimerId); - mFailedTimerId = 0; - // Show the normal password prompt. - mUnlockingFailed = false; - updateLabel(); - ok->setEnabled(true); - if (cancel) { - cancel->setEnabled(true); - } - mNewSessButton->setEnabled( true ); - greet->revive(); - greet->start(); - } -} - -bool PasswordDlg::eventFilter(TQObject *, TQEvent *ev) -{ - if (ev->type() == TQEvent::KeyPress || ev->type() == TQEvent::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; - return GRead (buf, len); -} - -void PasswordDlg::reapVerify() -{ - ::close( sFd ); - int status; - pid_t retpid = ::waitpid( sPid, &status, 0 ); - if (retpid < 0) { - // FIXME - // ERROR - } - else { - if (WIFEXITED(status)) { - switch (WEXITSTATUS(status)) { - case AuthOk: - { - KUser userinfo; - TQString fileName = userinfo.homeDir() + "/.tde_card_login_state"; - TQFile flagFile(fileName); - if (validUserCardInserted) { - // Card was likely used to log in - if (flagFile.open(IO_WriteOnly)) { - flagFile.writeBlock("1\n", 2); - flagFile.close(); - } - } - else { - // Card was not used to log in - flagFile.remove(); - } - - // Signal success - greet->succeeded(); - accept(); - return; - } - case AuthBad: - greet->failed(); - mUnlockingFailed = true; - updateLabel(); - mFailedTimerId = startTimer(1500); - ok->setEnabled(false); - if (cancel) { - cancel->setEnabled(false); - } - mNewSessButton->setEnabled( false ); - return; - case AuthAbort: - return; - } - } - else if (WIFSIGNALED(status)) { - // FIXME - // ERROR - } - } - cantCheck(); -} - -void PasswordDlg::handleVerify() -{ - int ret; - char *arr; - - while (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; - if (arr && (arr[0] != 0)) { - // Reset password entry and change text - greet->start(); - greet->textPrompt( arr, false, false ); - - // Force relayout - setFixedSize( sizeHint().width(), sizeHint().height() + 1 ); - setFixedSize( sizeHint() ); - - // Check if cryptographic card login is being used - if (mCardLoginInProgress) { - // Attempt authentication if configured - TDECryptographicCardDevice* cdevice = static_cast(parent())->cryptographicCardDevice(); - if (cdevice) { - TQString autoPIN = cdevice->autoPIN(); - if (autoPIN != TQString::null) { - greet->setPassword(autoPIN); - TQTimer::singleShot(0, this, SLOT(slotOK())); - } - } - mCardLoginInProgress = false; - } - } - else { - 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( TQMessageBox::Information, TQString::fromLocal8Bit( arr ) ); - ::free( arr ); - continue; - case ConvPutError: - if (!GRecvArr( &arr )) - break; - if (!greet->textMessage( arr, true )) - static_cast< LockProcess* >(parent())->msgBox( TQMessageBox::Warning, TQString::fromLocal8Bit( arr ) ); - ::free( arr ); - continue; - } - break; - } - reapVerify(); -} - -////// greeter plugin callbacks - -void PasswordDlg::gplugReturnText( const char *text, int tag ) -{ - GSendStr( text ); - if (text) { - GSendInt( tag ); - } - handleVerify(); -} - -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 ); - } - handleVerify(); -} - -void PasswordDlg::gplugSetUser( const TQString & ) -{ - // ignore ... -} - -void PasswordDlg::cantCheck() -{ - greet->failed(); - static_cast< LockProcess* >(parent())->msgBox( TQMessageBox::Critical, - i18n("Cannot unlock the session because the authentication system failed to work;\n" - "you must kill kdesktop_lock (pid %1) manually.").arg(getpid()) ); - greet->revive(); -} - -//--------------------------------------------------------------------------- -// -// Starts the kcheckpass process to check the user's password. -// -void PasswordDlg::gplugStart() -{ - int sfd[2]; - char fdbuf[16]; - - 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("kcheckpass", "kcheckpass", -#ifdef HAVE_PAM - "-c", TDESCREENSAVER_PAM_SERVICE, -#endif - "-m", mPlugin->info->method, - "-S", fdbuf, - (char *)0); - exit(20); - } - ::close(sfd[1]); - sFd = sfd[0]; - handleVerify(); -} - -void PasswordDlg::gplugActivity() -{ - slotActivity(); -} - -void PasswordDlg::gplugMsgBox( TQMessageBox::Icon type, const TQString &text ) -{ - TQDialog dialog( this, 0, true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), dialog.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - dialog.setCaption(i18n("Authentication Subsystem Notice")); - TQFrame *winFrame = new TQFrame( &dialog ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - winFrame->setFrameStyle( TQFrame::NoFrame ); - } - else { - winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); - } - winFrame->setLineWidth( 2 ); - TQVBoxLayout *vbox = new TQVBoxLayout( &dialog ); - vbox->addWidget( winFrame ); - - TQLabel *label1 = new TQLabel( winFrame ); - label1->setPixmap( TQMessageBox::standardIcon( type ) ); - TQLabel *label2 = new TQLabel( text, winFrame ); - KPushButton *button = new KPushButton( KStdGuiItem::ok(), winFrame ); - button->setDefault( true ); - button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); - connect( button, TQT_SIGNAL( clicked() ), TQT_SLOT( accept() ) ); - - TQGridLayout *grid = new TQGridLayout( winFrame, 2, 2, 10 ); - grid->addWidget( label1, 0, 0, Qt::AlignCenter ); - grid->addWidget( label2, 0, 1, Qt::AlignCenter ); - grid->addMultiCellWidget( button, 1,1, 0,1, Qt::AlignCenter ); - - static_cast< LockProcess* >(parent())->execDialog( &dialog ); -} - -void PasswordDlg::slotOK() -{ - greet->next(); -} - - -void PasswordDlg::show() -{ - TQDialog::show(); - TQApplication::flushX(); - setFixedSize( sizeHint() ); -} - -void PasswordDlg::slotStartNewSession() -{ - if (!KMessageBox::shouldBeShownContinue( ":confirmNewSession" )) { - DM().startReserve(); - return; - } - - killTimer(mTimeoutTimerId); - mTimeoutTimerId = 0; - - TQDialog *dialog = new TQDialog( this, "warnbox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))); - - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), dialog->winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - dialog->setCaption(i18n("New Session")); - - TQFrame *winFrame = new TQFrame( dialog ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - winFrame->setFrameStyle( TQFrame::NoFrame ); - } - else { - winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); - } - winFrame->setLineWidth( 2 ); - TQVBoxLayout *vbox = new TQVBoxLayout( dialog ); - vbox->addWidget( winFrame ); - - TQLabel *label1 = new TQLabel( winFrame ); - label1->setPixmap( TQMessageBox::standardIcon( TQMessageBox::Warning ) ); - TQString qt_text = i18n("You have chosen to open another desktop session " - "instead of resuming the current one.
" - "The current session will be hidden " - "and a new login screen will be displayed.
" - "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 TDE Panel and Desktop menus have " - "actions for switching between sessions.") - .arg(7).arg(8); - TQLabel *label2 = new TQLabel( qt_text, winFrame ); - KPushButton *okbutton = new KPushButton( KGuiItem(i18n("&Start New Session"), "fork"), winFrame ); - okbutton->setDefault( true ); - connect( okbutton, TQT_SIGNAL( clicked() ), dialog, TQT_SLOT( accept() ) ); - KPushButton *cbutton = new KPushButton( KStdGuiItem::cancel(), winFrame ); - connect( cbutton, TQT_SIGNAL( clicked() ), dialog, TQT_SLOT( reject() ) ); - - TQBoxLayout *mbox = new TQVBoxLayout( winFrame, KDialog::marginHint(), KDialog::spacingHint() ); - - TQGridLayout *grid = new TQGridLayout( mbox, 2, 2, 2 * KDialog::spacingHint() ); - grid->setMargin( KDialog::marginHint() ); - grid->addWidget( label1, 0, 0, Qt::AlignCenter ); - grid->addWidget( label2, 0, 1, Qt::AlignCenter ); - TQCheckBox *cb = new TQCheckBox( i18n("&Do not ask again"), winFrame ); - grid->addMultiCellWidget( cb, 1,1, 0,1 ); - - TQBoxLayout *hbox = new TQHBoxLayout( mbox, KDialog::spacingHint() ); - hbox->addStretch( 1 ); - hbox->addWidget( okbutton ); - hbox->addStretch( 1 ); - hbox->addWidget( cbutton ); - hbox->addStretch( 1 ); - - // stolen from kmessagebox - int pref_width = 0; - int pref_height = 0; - // Calculate a proper size for the text. - { - TQSimpleRichText rt(qt_text, dialog->font()); - TQRect rect = TDEGlobalSettings::desktopGeometry(dialog); - - pref_width = rect.width() / 3; - rt.setWidth(pref_width); - int used_width = rt.widthUsed(); - pref_height = rt.height(); - if (used_width <= pref_width) { - while(true) { - int new_width = (used_width * 9) / 10; - rt.setWidth(new_width); - int new_height = rt.height(); - if (new_height > pref_height) { - break; - } - used_width = rt.widthUsed(); - if (used_width > new_width) { - break; - } - } - pref_width = used_width; - } - else { - if (used_width > (pref_width *2)) - pref_width = pref_width *2; - else - pref_width = used_width; - } - } - label2->setFixedSize(TQSize(pref_width+10, pref_height)); - - int ret = static_cast< LockProcess* >( parent())->execDialog( dialog ); - - delete dialog; - - if (ret == TQDialog::Accepted) { - if (cb->isChecked()) { - KMessageBox::saveDontShowAgainContinue( ":confirmNewSession" ); - } - DM().startReserve(); - } - - mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT); -} - -class LockListViewItem : public TQListViewItem { - public: - LockListViewItem( TQListView *parent, const TQString &sess, const TQString &loc, int _vt ) : TQListViewItem( parent ) - , vt( _vt ) - { - setText( 0, sess ); - setText( 1, loc ); - } - - int vt; -}; - -void PasswordDlg::slotSwitchUser() -{ - int p = 0; - DM dm; - - TQDialog dialog( this, "sessbox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); - - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), dialog.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - dialog.setCaption(i18n("Switch User")); - - TQFrame *winFrame = new TQFrame( &dialog ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - winFrame->setFrameStyle( TQFrame::NoFrame ); - } - else { - winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); - } - winFrame->setLineWidth( 2 ); - TQBoxLayout *vbox = new TQVBoxLayout( &dialog ); - vbox->addWidget( winFrame ); - - TQBoxLayout *hbox = new TQHBoxLayout( winFrame, KDialog::marginHint(), KDialog::spacingHint() ); - - TQBoxLayout *vbox1 = new TQVBoxLayout( hbox, KDialog::spacingHint() ); - TQBoxLayout *vbox2 = new TQVBoxLayout( hbox, KDialog::spacingHint() ); - - KPushButton *btn; - - SessList sess; - if (dm.localSessions( sess )) { - lv = new TQListView( winFrame ); - connect( lv, TQT_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint&, int)), TQT_SLOT(slotSessionActivated()) ); - connect( lv, TQT_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint&, int)), &dialog, TQT_SLOT(accept()) ); - lv->setAllColumnsShowFocus( true ); - lv->addColumn( i18n("Session") ); - lv->addColumn( i18n("Location") ); - lv->setColumnWidthMode( 0, TQListView::Maximum ); - lv->setColumnWidthMode( 1, TQListView::Maximum ); - TQListViewItem *itm = 0; - TQString user, loc; - int ns = 0; - for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) { - DM::sess2Str2( *it, user, loc ); - itm = new LockListViewItem( lv, user, loc, (*it).vt ); - if (!(*it).vt) { - itm->setEnabled( false ); - } - if ((*it).self) { - lv->setCurrentItem( itm ); - itm->setSelected( true ); - } - ns++; - } - int fw = lv->frameWidth() * 2; - TQSize hds( lv->header()->sizeHint() ); - lv->setMinimumWidth( fw + hds.width() + - (ns > 10 ? style().pixelMetric(TQStyle::PM_ScrollBarExtent) : 0 ) ); - lv->setFixedHeight( fw + hds.height() + - itm->height() * (ns < 6 ? 6 : ns > 10 ? 10 : ns) ); - lv->header()->adjustHeaderSize(); - vbox1->addWidget( lv ); - - btn = new KPushButton( KGuiItem(i18n("session", "&Activate"), "fork"), winFrame ); - connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotSessionActivated()) ); - connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(accept()) ); - vbox2->addWidget( btn ); - vbox2->addStretch( 2 ); - } - - if (kapp->authorize("start_new_session") && (p = dm.numReserve()) >= 0) { - btn = new KPushButton( KGuiItem(i18n("Start &New Session"), "fork"), winFrame ); - connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotStartNewSession()) ); - connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(accept()) ); - if (!p) - btn->setEnabled( false ); - vbox2->addWidget( btn ); - vbox2->addStretch( 1 ); - } - - btn = new KPushButton( KStdGuiItem::cancel(), winFrame ); - connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(reject()) ); - vbox2->addWidget( btn ); - - dialog.setFixedSize( dialog.sizeHint() ); - - int ret = static_cast< LockProcess* >(parent())->execDialog( &dialog ); - if (ret != TQDialog::Rejected) { - TQDialog::reject(); - } -} - -void PasswordDlg::slotSessionActivated() -{ - LockListViewItem *itm = (LockListViewItem *)lv->currentItem(); - if (itm && itm->vt > 0) { - DM().switchVT( itm->vt ); - } -} - -void PasswordDlg::capsLocked() -{ - unsigned int lmask; - Window dummy1, dummy2; - int dummy3, dummy4, dummy5, dummy6; - XQueryPointer(tqt_xdisplay(), DefaultRootWindow( tqt_xdisplay() ), &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &lmask); - mCapsLocked = lmask & LockMask; - updateLabel(); -} - -void PasswordDlg::attemptCardLogin() { -#ifdef HAVE_KRB5 - // Make sure card logins are enabled before attempting one - if (!LDAPManager::pkcsLoginEnabled()) { - return; - } -#else - // Don't enable card-based logins if Kerberos integration was disabled - return; -#endif - - if (mCardLoginInProgress) { - return; - } - mCardLoginInProgress = true; - - // FIXME - // pam_pkcs11 is extremely chatty with no apparent way to disable the unwanted messages - greet->setInfoMessageDisplay(false); - - validUserCardInserted = true; - greet->setPasswordPrompt(i18n("PIN:")); - - // Force relayout - setFixedSize(sizeHint().width(), sizeHint().height() + 1); - setFixedSize(sizeHint()); - - // Bypass initial password prompt - greet->start(); - greet->setPassword(""); - TQTimer::singleShot(0, this, SLOT(slotOK())); -} - -void PasswordDlg::resetCardLogin() { - validUserCardInserted = false; - greet->abort(); - greet->clear(); - greet->revive(); - greet->start(); - greet->setPasswordPrompt(TQString::null); - - // Force relayout - setFixedSize(sizeHint().width(), sizeHint().height() + 1); - setFixedSize(sizeHint()); - - // Restore information message display settings - greet->setInfoMessageDisplay(showInfoMessages); - - mCardLoginInProgress = false; -} - -#include "lockdlg.moc" diff --git a/kdesktop/lock/lockdlg.cpp b/kdesktop/lock/lockdlg.cpp new file mode 100644 index 000000000..d4b456a9e --- /dev/null +++ b/kdesktop/lock/lockdlg.cpp @@ -0,0 +1,1027 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 1999 Martin R. Jones +// Copyright (c) 2003 Chris Howells +// Copyright (c) 2003 Oswald Buddenhagen +// Copyright (c) 2010 - 2015 Timothy Pearson + +#include + +#include "lockprocess.h" +#include "lockdlg.h" +#include "kdesktopsettings.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_KRB5 +#include +#endif + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +#define PASSDLG_HIDE_TIMEOUT dialogHideTimeout + +extern bool trinity_desktop_lock_autohide_lockdlg; +extern bool trinity_desktop_lock_delay_screensaver_start; +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_use_sak; +extern bool trinity_desktop_lock_hide_cancel_button; + +int dialogHideTimeout = 10*1000; + +//=========================================================================== +// +// Simple dialog for entering a password. +// +PasswordDlg::PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin) + : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mPlugin( plugin ), + mCapsLocked(-1), + mUnlockingFailed(false), + validUserCardInserted(false), + showInfoMessages(true), + mCardLoginInProgress(false) +{ + init(plugin); +} + +// +// Simple dialog for entering a password. +// This version includes support for displaying the date and time the lock process was started +// +PasswordDlg::PasswordDlg(LockProcess *parent, GreeterPluginHandle *plugin, TQDateTime lockStartDateTime) + : TQDialog(parent, "password dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mPlugin( plugin ), + mCapsLocked(-1), + mUnlockingFailed(false), + showInfoMessages(true), + mCardLoginInProgress(false) +{ + m_lockStartDT = lockStartDateTime; + init(plugin); +} + +void PasswordDlg::init(GreeterPluginHandle *plugin) +{ + dialogHideTimeout = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::timeout()*1000:10*1000; + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Desktop Session Locked")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + frame->setFrameStyle( TQFrame::NoFrame ); + } + else { + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + } + frame->setLineWidth( 2 ); + + TQLabel *pixLabel = NULL; + if (!trinity_desktop_lock_use_system_modal_dialogs) { + pixLabel = new TQLabel( frame, "pixlabel" ); + pixLabel->setPixmap(DesktopIcon("system-lock-screen")); + } + + KUser user; + TQLabel *greetLabel; + if (trinity_desktop_lock_use_system_modal_dialogs) { + greetLabel = new TQLabel( user.fullName().isEmpty() ? + "" + i18n("This computer is in use and has been locked.") + "" : + "" + i18n("This computer is in use and has been locked.") + "
" + i18n("Only '%1' may unlock this session.").arg( user.fullName() ), frame ); + } + else { + greetLabel = new TQLabel( user.fullName().isEmpty() ? + i18n("The session is locked
") : + i18n("
The session was locked by %1
").arg( user.fullName() ), frame ); + } + + TQLabel *lockDTLabel = NULL; + if ((trinity_desktop_lock_use_system_modal_dialogs) && (!m_lockStartDT.isNull())) { + lockDTLabel = new TQLabel(i18n("This session has been locked since %1").arg(m_lockStartDT.toString()), frame); + } + + mStatusLabel = new TQLabel( " ", frame ); + mStatusLabel->setAlignment( TQLabel::AlignCenter ); + + mLayoutButton = new TQPushButton( frame ); + mLayoutButton->setFlat( true ); + + KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); + + mNewSessButton = new KPushButton( KGuiItem(i18n("Sw&itch User..."), "fork"), frame ); + ok = new KPushButton( i18n("Unl&ock"), frame ); + ok->setDefault(true); + + bool show_cancel_button = !trinity_desktop_lock_hide_cancel_button + || trinity_desktop_lock_use_sak + || !trinity_desktop_lock_use_system_modal_dialogs; + if (show_cancel_button) { + cancel = new KPushButton( KStdGuiItem::cancel(), frame ); + } + else { + cancel = NULL; + } + + greet = plugin->info->create( this, 0, this, mLayoutButton, TQString::null, + KGreeterPlugin::Authenticate, KGreeterPlugin::ExUnlock ); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + layStatus->addWidget( mLayoutButton ); + + TQHBoxLayout *layButtons = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layButtons->addWidget( mNewSessButton ); + layButtons->addStretch(); + layButtons->addWidget(ok); + if (show_cancel_button) { + layButtons->addWidget(cancel); + } + + if (trinity_desktop_lock_use_system_modal_dialogs) { + KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); + + if (!m_lockStartDT.isNull()) { + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 2, Qt::AlignTop ); + frameLayout->addWidget( greetLabel, 1, 1 ); + frameLayout->addWidget( lockDTLabel, 2, 1 ); + frameLayout->addItem( greet->getLayoutItem(), 3, 1 ); + frameLayout->addLayout( layStatus, 4, 1 ); + frameLayout->addMultiCellWidget( sep, 5, 5, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 6, 6, 0, 1 ); + } + else { + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 2, Qt::AlignTop ); + frameLayout->addWidget( greetLabel, 1, 1 ); + frameLayout->addItem( greet->getLayoutItem(), 2, 1 ); + frameLayout->addLayout( layStatus, 3, 1 ); + frameLayout->addMultiCellWidget( sep, 4, 4, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 5, 5, 0, 1 ); + } + } + else { + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( pixLabel, 0, 2, 0, 0, Qt::AlignTop ); + frameLayout->addWidget( greetLabel, 0, 1 ); + frameLayout->addItem( greet->getLayoutItem(), 1, 1 ); + frameLayout->addLayout( layStatus, 2, 1 ); + frameLayout->addMultiCellWidget( sep, 3, 3, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 4, 4, 0, 1 ); + } + + if (show_cancel_button) { + setTabOrder( ok, cancel ); + setTabOrder( cancel, mNewSessButton ); + } + else { + setTabOrder( ok, mNewSessButton ); + } + setTabOrder( mNewSessButton, mLayoutButton ); + + connect(mLayoutButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(layoutClicked())); + if (show_cancel_button) { + connect(cancel, TQT_SIGNAL(clicked()), TQT_SLOT(reject())); + } + connect(ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotOK())); + connect(mNewSessButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotSwitchUser())); + + if (!DM().isSwitchable() || !kapp->authorize("switch_user")) { + mNewSessButton->hide(); + } + + installEventFilter(this); + setFixedSize( sizeHint() ); + + mFailedTimerId = 0; + mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT); + connect(tqApp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity()) ); + + greet->setInfoMessageDisplay(showInfoMessages); + greet->start(); + + DCOPRef kxkb("kxkb", "kxkb"); + if( !kxkb.isNull() ) { + DCOPReply reply = kxkb.call("getLayoutsList"); + if (reply.isValid()) { + layoutsList = reply; + } + reply = kxkb.call("getCurrentLayout"); + TQString currentLayout; + if (reply.isValid()) { + reply.get(currentLayout); + } + if( !currentLayout.isEmpty() && layoutsList.count() > 1 ) { + currLayout = layoutsList.find(currentLayout); + if (currLayout == layoutsList.end()) + setLayoutText("err"); + else + setLayoutText(*currLayout); + } + else { + mLayoutButton->hide(); + } + } + else { + mLayoutButton->hide(); // no kxkb running + } + capsLocked(); + + if (static_cast< LockProcess* >(parent())->cryptographicCardDevice()) { + attemptCardLogin(); + } +} + +PasswordDlg::~PasswordDlg() +{ + hide(); + frameLayout->removeItem( greet->getLayoutItem() ); + delete greet; +} + +void PasswordDlg::reject() +{ + if (!trinity_desktop_lock_hide_cancel_button + || trinity_desktop_lock_use_sak + || !trinity_desktop_lock_use_system_modal_dialogs + || trinity_desktop_lock_autohide_lockdlg) { + TQDialog::reject(); + } +} + +void PasswordDlg::layoutClicked() +{ + if( ++currLayout == layoutsList.end() ) { + currLayout = layoutsList.begin(); + } + + DCOPRef kxkb("kxkb", "kxkb"); + setLayoutText( kxkb.call("setLayout", *currLayout) ? *currLayout : "err" ); + +} + +void PasswordDlg::setLayoutText( const TQString &txt ) +{ + mLayoutButton->setText( txt ); + TQSize sz = mLayoutButton->fontMetrics().size( 0, txt ); + int mrg = mLayoutButton->style().pixelMetric( TQStyle::PM_ButtonMargin ) * 2; + mLayoutButton->setFixedSize( sz.width() + mrg, sz.height() + mrg ); +} + +void PasswordDlg::updateLabel() +{ + if (mUnlockingFailed) { + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText(i18n("Unlocking failed")); +// mStatusLabel->show(); + } + else if (mCapsLocked) { + mStatusLabel->setPaletteForegroundColor(Qt::red); + mStatusLabel->setText(i18n("Warning: Caps Lock on")); +// mStatusLabel->show(); + } + else { + mStatusLabel->setText(" "); +// mStatusLabel->hide(); + } +} + +//--------------------------------------------------------------------------- +// +// Handle timer events. +// +void PasswordDlg::timerEvent(TQTimerEvent *ev) +{ + if (ev->timerId() == mTimeoutTimerId) { + if (trinity_desktop_lock_autohide_lockdlg) { + // Force dialog rejection regardless of the value of trinity_desktop_lock_hide_cancel_button + TQDialog::reject(); + } + else { + slotActivity(); + } + } + else if (ev->timerId() == mFailedTimerId) { + killTimer(mFailedTimerId); + mFailedTimerId = 0; + // Show the normal password prompt. + mUnlockingFailed = false; + updateLabel(); + ok->setEnabled(true); + if (cancel) { + cancel->setEnabled(true); + } + mNewSessButton->setEnabled( true ); + greet->revive(); + greet->start(); + } +} + +bool PasswordDlg::eventFilter(TQObject *, TQEvent *ev) +{ + if (ev->type() == TQEvent::KeyPress || ev->type() == TQEvent::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; + return GRead (buf, len); +} + +void PasswordDlg::reapVerify() +{ + ::close( sFd ); + int status; + pid_t retpid = ::waitpid( sPid, &status, 0 ); + if (retpid < 0) { + // FIXME + // ERROR + } + else { + if (WIFEXITED(status)) { + switch (WEXITSTATUS(status)) { + case AuthOk: + { + KUser userinfo; + TQString fileName = userinfo.homeDir() + "/.tde_card_login_state"; + TQFile flagFile(fileName); + if (validUserCardInserted) { + // Card was likely used to log in + if (flagFile.open(IO_WriteOnly)) { + flagFile.writeBlock("1\n", 2); + flagFile.close(); + } + } + else { + // Card was not used to log in + flagFile.remove(); + } + + // Signal success + greet->succeeded(); + accept(); + return; + } + case AuthBad: + greet->failed(); + mUnlockingFailed = true; + updateLabel(); + mFailedTimerId = startTimer(1500); + ok->setEnabled(false); + if (cancel) { + cancel->setEnabled(false); + } + mNewSessButton->setEnabled( false ); + return; + case AuthAbort: + return; + } + } + else if (WIFSIGNALED(status)) { + // FIXME + // ERROR + } + } + cantCheck(); +} + +void PasswordDlg::handleVerify() +{ + int ret; + char *arr; + + while (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; + if (arr && (arr[0] != 0)) { + // Reset password entry and change text + greet->start(); + greet->textPrompt( arr, false, false ); + + // Force relayout + setFixedSize( sizeHint().width(), sizeHint().height() + 1 ); + setFixedSize( sizeHint() ); + + // Check if cryptographic card login is being used + if (mCardLoginInProgress) { + // Attempt authentication if configured + TDECryptographicCardDevice* cdevice = static_cast(parent())->cryptographicCardDevice(); + if (cdevice) { + TQString autoPIN = cdevice->autoPIN(); + if (autoPIN != TQString::null) { + greet->setPassword(autoPIN); + TQTimer::singleShot(0, this, SLOT(slotOK())); + } + } + mCardLoginInProgress = false; + } + } + else { + 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( TQMessageBox::Information, TQString::fromLocal8Bit( arr ) ); + ::free( arr ); + continue; + case ConvPutError: + if (!GRecvArr( &arr )) + break; + if (!greet->textMessage( arr, true )) + static_cast< LockProcess* >(parent())->msgBox( TQMessageBox::Warning, TQString::fromLocal8Bit( arr ) ); + ::free( arr ); + continue; + } + break; + } + reapVerify(); +} + +////// greeter plugin callbacks + +void PasswordDlg::gplugReturnText( const char *text, int tag ) +{ + GSendStr( text ); + if (text) { + GSendInt( tag ); + } + handleVerify(); +} + +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 ); + } + handleVerify(); +} + +void PasswordDlg::gplugSetUser( const TQString & ) +{ + // ignore ... +} + +void PasswordDlg::cantCheck() +{ + greet->failed(); + static_cast< LockProcess* >(parent())->msgBox( TQMessageBox::Critical, + i18n("Cannot unlock the session because the authentication system failed to work;\n" + "you must kill kdesktop_lock (pid %1) manually.").arg(getpid()) ); + greet->revive(); +} + +//--------------------------------------------------------------------------- +// +// Starts the kcheckpass process to check the user's password. +// +void PasswordDlg::gplugStart() +{ + int sfd[2]; + char fdbuf[16]; + + 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("kcheckpass", "kcheckpass", +#ifdef HAVE_PAM + "-c", TDESCREENSAVER_PAM_SERVICE, +#endif + "-m", mPlugin->info->method, + "-S", fdbuf, + (char *)0); + exit(20); + } + ::close(sfd[1]); + sFd = sfd[0]; + handleVerify(); +} + +void PasswordDlg::gplugActivity() +{ + slotActivity(); +} + +void PasswordDlg::gplugMsgBox( TQMessageBox::Icon type, const TQString &text ) +{ + TQDialog dialog( this, 0, true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), dialog.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + dialog.setCaption(i18n("Authentication Subsystem Notice")); + TQFrame *winFrame = new TQFrame( &dialog ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + winFrame->setFrameStyle( TQFrame::NoFrame ); + } + else { + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + } + winFrame->setLineWidth( 2 ); + TQVBoxLayout *vbox = new TQVBoxLayout( &dialog ); + vbox->addWidget( winFrame ); + + TQLabel *label1 = new TQLabel( winFrame ); + label1->setPixmap( TQMessageBox::standardIcon( type ) ); + TQLabel *label2 = new TQLabel( text, winFrame ); + KPushButton *button = new KPushButton( KStdGuiItem::ok(), winFrame ); + button->setDefault( true ); + button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); + connect( button, TQT_SIGNAL( clicked() ), TQT_SLOT( accept() ) ); + + TQGridLayout *grid = new TQGridLayout( winFrame, 2, 2, 10 ); + grid->addWidget( label1, 0, 0, Qt::AlignCenter ); + grid->addWidget( label2, 0, 1, Qt::AlignCenter ); + grid->addMultiCellWidget( button, 1,1, 0,1, Qt::AlignCenter ); + + static_cast< LockProcess* >(parent())->execDialog( &dialog ); +} + +void PasswordDlg::slotOK() +{ + greet->next(); +} + + +void PasswordDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); + setFixedSize( sizeHint() ); +} + +void PasswordDlg::slotStartNewSession() +{ + if (!KMessageBox::shouldBeShownContinue( ":confirmNewSession" )) { + DM().startReserve(); + return; + } + + killTimer(mTimeoutTimerId); + mTimeoutTimerId = 0; + + TQDialog *dialog = new TQDialog( this, "warnbox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))); + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), dialog->winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + dialog->setCaption(i18n("New Session")); + + TQFrame *winFrame = new TQFrame( dialog ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + winFrame->setFrameStyle( TQFrame::NoFrame ); + } + else { + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + } + winFrame->setLineWidth( 2 ); + TQVBoxLayout *vbox = new TQVBoxLayout( dialog ); + vbox->addWidget( winFrame ); + + TQLabel *label1 = new TQLabel( winFrame ); + label1->setPixmap( TQMessageBox::standardIcon( TQMessageBox::Warning ) ); + TQString qt_text = i18n("You have chosen to open another desktop session " + "instead of resuming the current one.
" + "The current session will be hidden " + "and a new login screen will be displayed.
" + "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 TDE Panel and Desktop menus have " + "actions for switching between sessions.") + .arg(7).arg(8); + TQLabel *label2 = new TQLabel( qt_text, winFrame ); + KPushButton *okbutton = new KPushButton( KGuiItem(i18n("&Start New Session"), "fork"), winFrame ); + okbutton->setDefault( true ); + connect( okbutton, TQT_SIGNAL( clicked() ), dialog, TQT_SLOT( accept() ) ); + KPushButton *cbutton = new KPushButton( KStdGuiItem::cancel(), winFrame ); + connect( cbutton, TQT_SIGNAL( clicked() ), dialog, TQT_SLOT( reject() ) ); + + TQBoxLayout *mbox = new TQVBoxLayout( winFrame, KDialog::marginHint(), KDialog::spacingHint() ); + + TQGridLayout *grid = new TQGridLayout( mbox, 2, 2, 2 * KDialog::spacingHint() ); + grid->setMargin( KDialog::marginHint() ); + grid->addWidget( label1, 0, 0, Qt::AlignCenter ); + grid->addWidget( label2, 0, 1, Qt::AlignCenter ); + TQCheckBox *cb = new TQCheckBox( i18n("&Do not ask again"), winFrame ); + grid->addMultiCellWidget( cb, 1,1, 0,1 ); + + TQBoxLayout *hbox = new TQHBoxLayout( mbox, KDialog::spacingHint() ); + hbox->addStretch( 1 ); + hbox->addWidget( okbutton ); + hbox->addStretch( 1 ); + hbox->addWidget( cbutton ); + hbox->addStretch( 1 ); + + // stolen from kmessagebox + int pref_width = 0; + int pref_height = 0; + // Calculate a proper size for the text. + { + TQSimpleRichText rt(qt_text, dialog->font()); + TQRect rect = TDEGlobalSettings::desktopGeometry(dialog); + + pref_width = rect.width() / 3; + rt.setWidth(pref_width); + int used_width = rt.widthUsed(); + pref_height = rt.height(); + if (used_width <= pref_width) { + while(true) { + int new_width = (used_width * 9) / 10; + rt.setWidth(new_width); + int new_height = rt.height(); + if (new_height > pref_height) { + break; + } + used_width = rt.widthUsed(); + if (used_width > new_width) { + break; + } + } + pref_width = used_width; + } + else { + if (used_width > (pref_width *2)) + pref_width = pref_width *2; + else + pref_width = used_width; + } + } + label2->setFixedSize(TQSize(pref_width+10, pref_height)); + + int ret = static_cast< LockProcess* >( parent())->execDialog( dialog ); + + delete dialog; + + if (ret == TQDialog::Accepted) { + if (cb->isChecked()) { + KMessageBox::saveDontShowAgainContinue( ":confirmNewSession" ); + } + DM().startReserve(); + } + + mTimeoutTimerId = startTimer(PASSDLG_HIDE_TIMEOUT); +} + +class LockListViewItem : public TQListViewItem { + public: + LockListViewItem( TQListView *parent, const TQString &sess, const TQString &loc, int _vt ) : TQListViewItem( parent ) + , vt( _vt ) + { + setText( 0, sess ); + setText( 1, loc ); + } + + int vt; +}; + +void PasswordDlg::slotSwitchUser() +{ + int p = 0; + DM dm; + + TQDialog dialog( this, "sessbox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), dialog.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + dialog.setCaption(i18n("Switch User")); + + TQFrame *winFrame = new TQFrame( &dialog ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + winFrame->setFrameStyle( TQFrame::NoFrame ); + } + else { + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + } + winFrame->setLineWidth( 2 ); + TQBoxLayout *vbox = new TQVBoxLayout( &dialog ); + vbox->addWidget( winFrame ); + + TQBoxLayout *hbox = new TQHBoxLayout( winFrame, KDialog::marginHint(), KDialog::spacingHint() ); + + TQBoxLayout *vbox1 = new TQVBoxLayout( hbox, KDialog::spacingHint() ); + TQBoxLayout *vbox2 = new TQVBoxLayout( hbox, KDialog::spacingHint() ); + + KPushButton *btn; + + SessList sess; + if (dm.localSessions( sess )) { + lv = new TQListView( winFrame ); + connect( lv, TQT_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint&, int)), TQT_SLOT(slotSessionActivated()) ); + connect( lv, TQT_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint&, int)), &dialog, TQT_SLOT(accept()) ); + lv->setAllColumnsShowFocus( true ); + lv->addColumn( i18n("Session") ); + lv->addColumn( i18n("Location") ); + lv->setColumnWidthMode( 0, TQListView::Maximum ); + lv->setColumnWidthMode( 1, TQListView::Maximum ); + TQListViewItem *itm = 0; + TQString user, loc; + int ns = 0; + for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) { + DM::sess2Str2( *it, user, loc ); + itm = new LockListViewItem( lv, user, loc, (*it).vt ); + if (!(*it).vt) { + itm->setEnabled( false ); + } + if ((*it).self) { + lv->setCurrentItem( itm ); + itm->setSelected( true ); + } + ns++; + } + int fw = lv->frameWidth() * 2; + TQSize hds( lv->header()->sizeHint() ); + lv->setMinimumWidth( fw + hds.width() + + (ns > 10 ? style().pixelMetric(TQStyle::PM_ScrollBarExtent) : 0 ) ); + lv->setFixedHeight( fw + hds.height() + + itm->height() * (ns < 6 ? 6 : ns > 10 ? 10 : ns) ); + lv->header()->adjustHeaderSize(); + vbox1->addWidget( lv ); + + btn = new KPushButton( KGuiItem(i18n("session", "&Activate"), "fork"), winFrame ); + connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotSessionActivated()) ); + connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(accept()) ); + vbox2->addWidget( btn ); + vbox2->addStretch( 2 ); + } + + if (kapp->authorize("start_new_session") && (p = dm.numReserve()) >= 0) { + btn = new KPushButton( KGuiItem(i18n("Start &New Session"), "fork"), winFrame ); + connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotStartNewSession()) ); + connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(accept()) ); + if (!p) + btn->setEnabled( false ); + vbox2->addWidget( btn ); + vbox2->addStretch( 1 ); + } + + btn = new KPushButton( KStdGuiItem::cancel(), winFrame ); + connect( btn, TQT_SIGNAL(clicked()), &dialog, TQT_SLOT(reject()) ); + vbox2->addWidget( btn ); + + dialog.setFixedSize( dialog.sizeHint() ); + + int ret = static_cast< LockProcess* >(parent())->execDialog( &dialog ); + if (ret != TQDialog::Rejected) { + TQDialog::reject(); + } +} + +void PasswordDlg::slotSessionActivated() +{ + LockListViewItem *itm = (LockListViewItem *)lv->currentItem(); + if (itm && itm->vt > 0) { + DM().switchVT( itm->vt ); + } +} + +void PasswordDlg::capsLocked() +{ + unsigned int lmask; + Window dummy1, dummy2; + int dummy3, dummy4, dummy5, dummy6; + XQueryPointer(tqt_xdisplay(), DefaultRootWindow( tqt_xdisplay() ), &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6, &lmask); + mCapsLocked = lmask & LockMask; + updateLabel(); +} + +void PasswordDlg::attemptCardLogin() { +#ifdef HAVE_KRB5 + // Make sure card logins are enabled before attempting one + if (!LDAPManager::pkcsLoginEnabled()) { + return; + } +#else + // Don't enable card-based logins if Kerberos integration was disabled + return; +#endif + + if (mCardLoginInProgress) { + return; + } + mCardLoginInProgress = true; + + // FIXME + // pam_pkcs11 is extremely chatty with no apparent way to disable the unwanted messages + greet->setInfoMessageDisplay(false); + + validUserCardInserted = true; + greet->setPasswordPrompt(i18n("PIN:")); + + // Force relayout + setFixedSize(sizeHint().width(), sizeHint().height() + 1); + setFixedSize(sizeHint()); + + // Bypass initial password prompt + greet->start(); + greet->setPassword(""); + TQTimer::singleShot(0, this, SLOT(slotOK())); +} + +void PasswordDlg::resetCardLogin() { + validUserCardInserted = false; + greet->abort(); + greet->clear(); + greet->revive(); + greet->start(); + greet->setPasswordPrompt(TQString::null); + + // Force relayout + setFixedSize(sizeHint().width(), sizeHint().height() + 1); + setFixedSize(sizeHint()); + + // Restore information message display settings + greet->setInfoMessageDisplay(showInfoMessages); + + mCardLoginInProgress = false; +} + +#include "lockdlg.moc" diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc deleted file mode 100644 index fdde3fc9e..000000000 --- a/kdesktop/lock/lockprocess.cc +++ /dev/null @@ -1,3045 +0,0 @@ -//=========================================================================== -// -// This file is part of the TDE project -// -// Copyright (c) 1999 Martin R. Jones -// Copyright (c) 2003 Oswald Buddenhagen -// Copyright (c) 2010 - 2015 Timothy Pearson -// - -//kdesktop keeps running and checks user inactivity -//when it should show screensaver (and maybe lock the session), -//it starts kdesktop_lock, who does all the locking and who -//actually starts the screensaver - -//It's done this way to prevent screen unlocking when kdesktop -//crashes (e.g. because it's set to multiple wallpapers and -//some image will be corrupted). - -#include - -#include "lockprocess.h" -#include "lockdlg.h" -#include "infodlg.h" -#include "querydlg.h" -#include "sakdlg.h" -#include "securedlg.h" -#include "autologout.h" -#include "kdesktopsettings.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#ifdef HAVE_SETPRIORITY -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#ifdef HAVE_DPMS -extern "C" { -#include -#ifndef Bool -#define Bool BOOL -#endif -#include - -#ifndef HAVE_DPMSINFO_PROTO -Status DPMSInfo ( Display *, CARD16 *, BOOL * ); -#endif -} -#endif - -#ifdef HAVE_XF86MISC -#include -#endif - -#ifdef HAVE_GLXCHOOSEVISUAL -#include -#endif - -#define KDESKTOP_DEBUG_ID 1204 - -#define LOCK_GRACE_DEFAULT 5000 -#define AUTOLOGOUT_DEFAULT 600 - -#define DESKTOP_WALLPAPER_OBTAIN_TIMEOUT_MS 3000 - -// Setting this define is INSECURE -// Use it for debugging purposes ONLY -// #define KEEP_MOUSE_UNGRABBED 1 - -// These lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special multimedia keys -#define XF86XK_AudioMute 0x1008FF12 -#define XF86XK_AudioRaiseVolume 0x1008FF13 -#define XF86XK_AudioLowerVolume 0x1008FF11 -#define XF86XK_Display 0x1008FF59 - -// These lines are taken on 08/2013 from X.org (X11/XF86keysym.h), defining some special ACPI power keys -#define XF86XK_PowerOff 0x1008FF2A -#define XF86XK_Sleep 0x1008FF2F -#define XF86XK_Suspend 0x1008FFA7 -#define XF86XK_Hibernate 0x1008FFA8 - -#define DPMS_MONITOR_BLANKED(x) ((x == DPMSModeStandby) || (x == DPMSModeSuspend) || (x == DPMSModeOff)) - -static Window gVRoot = 0; -static Window gVRootData = 0; -static Atom gXA_VROOT; -static Atom gXA_SCREENSAVER_VERSION; - -Atom kde_wm_system_modal_notification = 0; -Atom kde_wm_transparent_to_desktop = 0; -Atom kde_wm_transparent_to_black = 0; - -static void segv_handler(int) -{ - kdError(KDESKTOP_DEBUG_ID) << "A fatal exception was encountered." - << " Trapping and ignoring it so as not to compromise desktop security..." - << kdBacktrace() << endl; - sleep(1); -} - -extern Atom tqt_wm_state; -extern bool trinity_desktop_lock_use_system_modal_dialogs; -extern bool trinity_desktop_lock_delay_screensaver_start; -extern bool trinity_desktop_lock_use_sak; -extern bool trinity_desktop_lock_hide_active_windows; -extern bool trinity_desktop_lock_hide_cancel_button; -extern bool trinity_desktop_lock_forced; - -extern LockProcess* trinity_desktop_lock_process; - -extern bool argb_visual; -extern pid_t kdesktop_pid; - -extern TQXLibWindowList trinity_desktop_lock_hidden_window_list; - -bool trinity_desktop_lock_autohide_lockdlg = TRUE; - -#define ENABLE_CONTINUOUS_LOCKDLG_DISPLAY \ -if (!mForceContinualLockDisplayTimer->isActive()) mForceContinualLockDisplayTimer->start(100, FALSE); \ -trinity_desktop_lock_autohide_lockdlg = FALSE; \ -mHackDelayStartupTimer->stop(); - -#define DISABLE_CONTINUOUS_LOCKDLG_DISPLAY \ -mForceContinualLockDisplayTimer->stop(); \ -trinity_desktop_lock_autohide_lockdlg = TRUE; \ -mHackDelayStartupTimer->stop(); - -//=========================================================================== -// -// Screen saver handling process. Handles screensaver window, -// starting screensaver hacks, and password entry. -// -LockProcess::LockProcess() - : TQWidget(0L, "saver window", ((WFlags)(WStyle_StaysOnTop|WStyle_Customize|WStyle_NoBorder))), - mOpenGLVisual(0), - mParent(0), - mShowLockDateTime(false), - mSuspended(false), - mVisibility(false), - mRestoreXF86Lock(false), - mForbidden(false), - mAutoLogout(false), - resizeTimer(NULL), - hackResumeTimer(NULL), - mVkbdProcess(NULL), - mKWinModule(NULL), - mPipeOpen(false), - mPipeOpen_out(false), - mInfoMessageDisplayed(false), - mDialogControlLock(false), - mForceReject(false), - currentDialog(NULL), - mEnsureScreenHiddenTimer(NULL), - mForceContinualLockDisplayTimer(NULL), - mEnsureVRootWindowSecurityTimer(NULL), - mHackDelayStartupTimer(NULL), - mHackDelayStartupTimeout(0), - mHackStartupEnabled(true), - mOverrideHackStartupEnabled(false), - mResizingDesktopLock(false), - mFullyOnlineSent(false), - mClosingWindows(false), - mInSecureDialog(false), - mHackActive(false), - m_rootPixmap(NULL), - mBackingStartupDelayTimer(0), - m_startupStatusDialog(NULL), - m_mouseDown(0), - m_mousePrevX(0), - m_mousePrevY(0), - m_dialogPrevX(0), - m_dialogPrevY(0), - m_notifyReadyRequested(false), - m_loginCardDevice(NULL), - m_maskWidget(NULL), - m_saverRootWindow(0) -{ -#ifdef KEEP_MOUSE_UNGRABBED - setNFlags(WX11DisableMove|WX11DisableClose|WX11DisableShade|WX11DisableMinimize|WX11DisableMaximize); -#endif - - setupSignals(); - - // Set up atoms - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - kde_wm_transparent_to_desktop = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENT_TO_DESKTOP", False); - kde_wm_transparent_to_black = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENT_TO_BLACK", False); - - kapp->installX11EventFilter(this); - - mForceContinualLockDisplayTimer = new TQTimer( this ); - mHackDelayStartupTimer = new TQTimer( this ); - mEnsureVRootWindowSecurityTimer = new TQTimer( this ); - - if (!argb_visual) { - // Try to get the root pixmap - if (!m_rootPixmap) m_rootPixmap = new KRootPixmap(this); - connect(m_rootPixmap, TQT_SIGNAL(backgroundUpdated(const TQPixmap &)), this, TQT_SLOT(slotPaintBackground(const TQPixmap &))); - m_rootPixmap->setCustomPainting(true); - m_rootPixmap->start(); - } - - // Get root window attributes - XWindowAttributes rootAttr; - XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); - { // trigger creation of QToolTipManager, it does XSelectInput() on the root window - TQWidget w; - TQToolTip::add( &w, "foo" ); - } - XSelectInput( tqt_xdisplay(), tqt_xrootwin(), SubstructureNotifyMask | rootAttr.your_event_mask ); - - // Add non-TDE path - TDEGlobal::dirs()->addResourceType("scrsav", - TDEGlobal::dirs()->kde_default("apps") + - "System/ScreenSavers/"); - - // Add KDE specific screensaver path - TQString relPath="System/ScreenSavers/"; - KServiceGroup::Ptr servGroup = KServiceGroup::baseGroup( "screensavers"); - if (servGroup) { - relPath=servGroup->relPath(); - kdDebug(KDESKTOP_DEBUG_ID) << "relPath=" << relPath << endl; - } - TDEGlobal::dirs()->addResourceType("scrsav", - TDEGlobal::dirs()->kde_default("apps") + - relPath); - - // virtual root property - gXA_VROOT = XInternAtom (tqt_xdisplay(), "__SWM_VROOT", False); - gXA_SCREENSAVER_VERSION = XInternAtom (tqt_xdisplay(), "_SCREENSAVER_VERSION", False); - - TQStringList dmopt = TQStringList::split(TQChar(','), - TQString::fromLatin1( ::getenv( "XDM_MANAGED" ))); - for (TQStringList::ConstIterator it = dmopt.begin(); it != dmopt.end(); ++it) { - if ((*it).startsWith("method=")) { - mMethod = (*it).mid(7); - } - } - - // Initialize SmartCard readers - TDEGenericDevice *hwdevice; - TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices(); - TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard); - for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) { - TDECryptographicCardDevice* cdevice = static_cast(hwdevice); - // connect(cdevice, SIGNAL(pinRequested(TQString,TDECryptographicCardDevice*)), this, SLOT(cryptographicCardPinRequested(TQString,TDECryptographicCardDevice*))); - connect(cdevice, TQT_SIGNAL(certificateListAvailable(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*))); - connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*))); - cdevice->enableCardMonitoring(true); - // cdevice->enablePINEntryCallbacks(true); - } - -#ifdef KEEP_MOUSE_UNGRABBED - setEnabled(false); -#endif - - greetPlugin.library = 0; - - TDECrash::setCrashHandler(segv_handler); -} - -//--------------------------------------------------------------------------- -// -// Destructor - usual cleanups. -// -LockProcess::~LockProcess() -{ - mControlPipeHandler->terminateThread(); - mControlPipeHandlerThread->wait(); - delete mControlPipeHandler; -// delete mControlPipeHandlerThread; - - if (resizeTimer != NULL) { - resizeTimer->stop(); - delete resizeTimer; - } - if (hackResumeTimer != NULL) { - hackResumeTimer->stop(); - delete hackResumeTimer; - } - if (mEnsureScreenHiddenTimer != NULL) { - mEnsureScreenHiddenTimer->stop(); - delete mEnsureScreenHiddenTimer; - } - if (mForceContinualLockDisplayTimer != NULL) { - mForceContinualLockDisplayTimer->stop(); - delete mForceContinualLockDisplayTimer; - } - if (mHackDelayStartupTimer != NULL) { - mHackDelayStartupTimer->stop(); - delete mHackDelayStartupTimer; - } - if (mEnsureVRootWindowSecurityTimer != NULL) { - mEnsureVRootWindowSecurityTimer->stop(); - delete mEnsureVRootWindowSecurityTimer; - } - - if (greetPlugin.library) { - if (greetPlugin.info->done) - greetPlugin.info->done(); - greetPlugin.library->unload(); - } - - if (m_rootPixmap) { - m_rootPixmap->stop(); - delete m_rootPixmap; - } - - mPipeOpen = false; - mPipeOpen_out = false; -} - -//--------------------------------------------------------------------------- -// -// Initialization for startup -// This is where instance settings should be set--all objects should have already been created in the constructor above -// -void LockProcess::init(bool child, bool useBlankOnly) -{ - // Get root window size - XWindowAttributes rootAttr; - XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); - mRootWidth = rootAttr.width; - mRootHeight = rootAttr.height; - generateBackingImages(); - - // Connect all signals - connect( mForceContinualLockDisplayTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(displayLockDialogIfNeeded()) ); - connect( mHackDelayStartupTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(closeDialogAndStartHack()) ); - connect( mEnsureVRootWindowSecurityTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(repaintRootWindowIfNeeded()) ); - connect(tqApp, TQT_SIGNAL(mouseInteraction(XEvent *)), TQT_SLOT(slotMouseActivity(XEvent *))); - connect(&mHackProc, TQT_SIGNAL(processExited(TDEProcess *)), TQT_SLOT(hackExited(TDEProcess *))); - connect(&mSuspendTimer, TQT_SIGNAL(timeout()), TQT_SLOT(suspend())); - -#ifdef HAVE_DPMS - //if the user decided that the screensaver should run independent from - //dpms, we shouldn't check for it, aleXXX - if (KDesktopSettings::dpmsDependent()) { - BOOL on; - CARD16 state; - if (DPMSInfo(tqt_xdisplay(), &state, &on)) { - if (on) { - connect(&mCheckDPMS, TQT_SIGNAL(timeout()), TQT_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 - -#if (TQT_VERSION-0 >= 0x030200) // XRANDR support - connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); -#endif - - if (!trinity_desktop_lock_use_system_modal_dialogs) { - setWFlags((WFlags)WX11BypassWM); - } - - child_saver = child; - mUseBlankOnly = useBlankOnly; - - mShowLockDateTime = KDesktopSettings::showLockDateTime(); - mlockDateTime = TQDateTime::currentDateTime(); - - mHackDelayStartupTimeout = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::timeout()*1000:10*1000; - mHackStartupEnabled = trinity_desktop_lock_use_system_modal_dialogs?KDesktopSettings::screenSaverEnabled():true; - - configure(); - - mControlPipeHandlerThread = new TQEventLoopThread(); - mControlPipeHandler = new ControlPipeHandlerObject(); - mControlPipeHandler->mParent = this; - mControlPipeHandler->moveToThread(mControlPipeHandlerThread); - TQObject::connect(mControlPipeHandler, SIGNAL(processCommand(TQString)), this, SLOT(processInputPipeCommand(TQString))); - TQTimer::singleShot(0, mControlPipeHandler, SLOT(run())); - mControlPipeHandlerThread->start(); -} - -static int signal_pipe[2]; - -static void sigterm_handler(int) -{ - if ((!trinity_desktop_lock_process) || (!trinity_desktop_lock_process->inSecureDialog())) { - // Exit uncleanly - char tmp = 'U'; - if (::write( signal_pipe[1], &tmp, 1) == -1) { - // Error handler to shut up gcc warnings - } - } -} - -static void sighup_handler(int) -{ - char tmp = 'H'; - if (::write( signal_pipe[1], &tmp, 1) == -1) { - // Error handler to shut up gcc warnings - } -} - -bool LockProcess::closeCurrentWindow() -{ - mClosingWindows = TRUE; - if (currentDialog != NULL) { - mForceReject = true; - if (dynamic_cast(currentDialog)) { - dynamic_cast(currentDialog)->closeDialogForced(); - } - else if (dynamic_cast(currentDialog)) { - dynamic_cast(currentDialog)->closeDialogForced(); - } - else { - currentDialog->close(); - } - } - - if( mDialogs.isEmpty() ) { - mClosingWindows = FALSE; - mForceReject = false; - return false; - } - else { - mClosingWindows = TRUE; - return true; - } -} - -void LockProcess::timerEvent(TQTimerEvent *ev) -{ - if (mAutoLogout && ev->timerId() == mAutoLogoutTimerId) { - killTimer(mAutoLogoutTimerId); - AutoLogout autologout(this); - execDialog(&autologout); - } -} - -void LockProcess::resizeEvent(TQResizeEvent *) -{ - // -} - -void LockProcess::setupSignals() -{ - struct sigaction act; - // ignore SIGINT - act.sa_handler=SIG_IGN; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGINT); - act.sa_flags = 0; - sigaction(SIGINT, &act, 0L); - // ignore SIGQUIT - act.sa_handler=SIG_IGN; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGQUIT); - act.sa_flags = 0; - sigaction(SIGQUIT, &act, 0L); - // exit uncleanly on SIGTERM - act.sa_handler= sigterm_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGTERM); - act.sa_flags = 0; - sigaction(SIGTERM, &act, 0L); - // SIGHUP forces lock - act.sa_handler= sighup_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGHUP); - act.sa_flags = 0; - sigaction(SIGHUP, &act, 0L); - - if (pipe(signal_pipe) == -1) { - // Error handler to shut up gcc warnings - } - TQSocketNotifier* notif = new TQSocketNotifier(signal_pipe[0], TQSocketNotifier::Read, TQT_TQOBJECT(this) ); - connect( notif, TQT_SIGNAL(activated(int)), TQT_SLOT(signalPipeSignal())); -} - - -void LockProcess::signalPipeSignal() -{ - char tmp; - if (::read( signal_pipe[0], &tmp, 1) == -1) { - // Error handler to shut up gcc warnings - } - if( tmp == 'T' ) { - quitSaver(); - } - else if( tmp == 'H' ) { - if( !mLocked ) - startLock(); - } - else if( tmp == 'U' ) { - // Exit uncleanly - quitSaver(); - exit(1); - } -} - -//--------------------------------------------------------------------------- -bool LockProcess::lock() -{ -#ifdef USE_SECURING_DESKTOP_NOTIFICATION - m_startupStatusDialog = new KSMModalDialog(this); - m_startupStatusDialog->setStatusMessage(i18n("Securing desktop session").append("...")); - m_startupStatusDialog->show(); - m_startupStatusDialog->setActiveWindow(); - tqApp->processEvents(); -#endif - - if (startSaver(true)) { - // 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; - if (startLock()) { - TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); - return true; - } - stopSaver(); - mBusy = false; - } - return false; -} -//--------------------------------------------------------------------------- -void LockProcess::slotDeadTimePassed() -{ - mBusy = false; -} - -//--------------------------------------------------------------------------- -bool LockProcess::defaultSave() -{ - mLocked = false; - mOverrideHackStartupEnabled = true; - if (startSaver()) { - if (mLockGrace >= 0) { - TQTimer::singleShot(mLockGrace, this, TQT_SLOT(startLock())); - } - return true; - } - mOverrideHackStartupEnabled = false; - return false; -} - -//--------------------------------------------------------------------------- -bool LockProcess::dontLock() -{ - mLocked = false; - return startSaver(); -} - -//--------------------------------------------------------------------------- -void LockProcess::quitSaver() -{ - DISABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (closeCurrentWindow()) { - TQTimer::singleShot( 0, this, SLOT(quitSaver()) ); - return; - } - stopSaver(); - kapp->quit(); -} - -//--------------------------------------------------------------------------- -void LockProcess::startSecureDialog() -{ - if ((backingPixmap.isNull()) && (mBackingStartupDelayTimer < 100)) { - TQTimer::singleShot(10, this, TQT_SLOT(startSecureDialog())); - mBackingStartupDelayTimer++; - return; - } - - setGeometry(0, 0, mRootWidth, mRootHeight); - saverReadyIfNeeded(); - - int ret; - SecureDlg inDlg( this ); - inDlg.setRetInt(&ret); - mBusy = true; - execDialog( &inDlg ); - mBusy = false; - bool forcecontdisp = mForceContinualLockDisplayTimer->isActive(); - if (forcecontdisp) { - DISABLE_CONTINUOUS_LOCKDLG_DISPLAY - } - mInSecureDialog = false; - if (ret == 0) { - mClosingWindows = 1; - kapp->quit(); - } - if (ret == 1) { - // 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; - trinity_desktop_lock_forced = true; - // Make sure the cursor is not showing busy status - setCursor( tqarrowCursor ); - if (startLock()) - { - if (trinity_desktop_lock_delay_screensaver_start) { - mBusy = false; - } - else { - TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); - } - if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - if (mHackStartupEnabled == true) { - startHack(); - } - else { - if (trinity_desktop_lock_use_system_modal_dialogs == true) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - startHack(); - } - } - } - return; - } - stopSaver(); - mBusy = false; - return; - } - if (ret == 2) { - mClosingWindows = 1; - if (system("ksysguard &") == -1) { - // Error handler to shut up gcc warnings - } - kapp->quit(); - } - if (ret == 3) { - mClosingWindows = 1; - DCOPRef("ksmserver","ksmserver").send("logout", (int)TDEApplication::ShutdownConfirmYes, (int)TDEApplication::ShutdownTypeNone, (int)TDEApplication::ShutdownModeInteractive); - kapp->quit(); - } - // FIXME - // Handle remaining case (switch user) - if (forcecontdisp) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - stopSaver(); -} - -bool LockProcess::runSecureDialog() -{ -#ifdef USE_SECURING_DESKTOP_NOTIFICATION - m_startupStatusDialog = new KSMModalDialog(this); - m_startupStatusDialog->setStatusMessage(i18n("Securing desktop session").append("...")); - m_startupStatusDialog->show(); - m_startupStatusDialog->setActiveWindow(); - tqApp->processEvents(); -#endif - - mInSecureDialog = true; - if (startSaver()) { - mBackingStartupDelayTimer = 0; - TQTimer::singleShot(0, this, TQT_SLOT(startSecureDialog())); - return true; - } - else { - mInSecureDialog = false; - return false; - } -} - -bool LockProcess::inSecureDialog() -{ - return mInSecureDialog; -} - -//--------------------------------------------------------------------------- -// -// Read and apply configuration. -// -void LockProcess::configure() -{ - // the configuration is stored in kdesktop's config file - if( KDesktopSettings::lock() ) { - mLockGrace = KDesktopSettings::lockGrace(); - if (mLockGrace < 0) - mLockGrace = 0; - else if (mLockGrace > 300000) - mLockGrace = 300000; // 5 minutes, keep the value sane - } - else - mLockGrace = -1; - - if ( KDesktopSettings::autoLogout() ) { - mAutoLogout = true; - mAutoLogoutTimeout = KDesktopSettings::autoLogoutTimeout(); - mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout * 1000); // in milliseconds - } - - mPriority = KDesktopSettings::priority(); - if (mPriority < 0) mPriority = 0; - if (mPriority > 19) mPriority = 19; - - mSaver = KDesktopSettings::saver(); - if (mSaver.isEmpty() || mUseBlankOnly) { - mSaver = "KBlankscreen.desktop"; - } - if (!trinity_desktop_lock_use_system_modal_dialogs) { - if (KDesktopSettings::screenSaverEnabled() == false) { - mSaver = ""; - mSaverExec = ""; - } - } - - readSaver(); - - mPlugins = KDesktopSettings::pluginsUnlock(); - if (mPlugins.isEmpty()) { - mPlugins = TQStringList("classic"); - } - mPluginOptions = KDesktopSettings::pluginOptions(); -} - -//--------------------------------------------------------------------------- -// -// Read the command line needed to run the screensaver given a .desktop file. -// -void LockProcess::readSaver() -{ - if (!mSaver.isEmpty()) { - TQString file = locate("scrsav", mSaver); - - bool opengl = kapp->authorize("opengl_screensavers"); - bool manipulatescreen = kapp->authorize("manipulatescreen_screensavers"); - KDesktopFile config(file, true); - if (config.readEntry("X-TDE-Type").utf8() != 0) { - TQString saverType = config.readEntry("X-TDE-Type").utf8(); - TQStringList saverTypes = TQStringList::split(";", saverType); - for (uint i = 0; i < saverTypes.count(); i++) { - if ((saverTypes[i] == "ManipulateScreen") && !manipulatescreen) { - kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden" << endl; - mForbidden = true; - } - if ((saverTypes[i] == "OpenGL") && !opengl) { - kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type OpenGL and OpenGL is forbidden" << endl; - mForbidden = true; - } - if (saverTypes[i] == "OpenGL") { - mOpenGLVisual = true; - } - } - } - - kdDebug(KDESKTOP_DEBUG_ID) << "mForbidden: " << (mForbidden ? "true" : "false") << endl; - - if (trinity_desktop_lock_use_system_modal_dialogs) { - if (config.hasActionGroup("InWindow")) { - config.setActionGroup("InWindow"); - mSaverExec = config.readPathEntry("Exec"); - } - } - else { - if (config.hasActionGroup("Root")) { - config.setActionGroup("Root"); - mSaverExec = config.readPathEntry("Exec"); - } - } - } -} - -//--------------------------------------------------------------------------- -// -// Create a window to draw our screen saver on. -// -void LockProcess::createSaverWindow() -{ - Visual* visual = CopyFromParent; - XSetWindowAttributes attrs; - XVisualInfo* info = NULL; - int flags = trinity_desktop_lock_use_system_modal_dialogs?0:CWOverrideRedirect; -#ifdef HAVE_GLXCHOOSEVISUAL - if( mOpenGLVisual ) { - static 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 ) { - int n_glxfb_configs; - GLXFBConfig *fbc = glXChooseFBConfig( x11Display(), x11Screen(), attribs[ i ], &n_glxfb_configs); - if (!fbc) { - n_glxfb_configs = 0; - } - for( int j = 0; j < n_glxfb_configs; j++ ) { - info = glXGetVisualFromFBConfig(x11Display(), fbc[j]); - if( info ) { - if (argb_visual) { - // Xorg can only use GPU compositing for ARGB32 8:8:8:8 visuals - // Ensure the selected visual is 8 bits per RGB - // Selecting a non-8-bit visual will result in stuttering and high - // CPU load, while Xorg tries to composite each frame on the CPU! - if ((info->depth < 32) || (info->bits_per_rgb != 8)) { - XFree( info ); - info = NULL; - continue; - } - } - visual = info->visual; - static Colormap colormap = 0; - if( colormap != 0 ) { - XFreeColormap( x11Display(), colormap ); - } - colormap = XCreateColormap( x11Display(), RootWindow( x11Display(), x11Screen()), visual, AllocNone ); - attrs.colormap = colormap; - flags |= CWColormap; - break; - } - } - if (flags & CWColormap) { - break; - } - } - if ( !info ) { - printf("[WARNING] Unable to locate matching X11 GLX Visual; this OpenGL application may not function correctly!\n"); - } - } -#endif - - attrs.override_redirect = 1; - hide(); - - if (argb_visual) { - // The GL visual selection can return a visual with invalid depth - // Check for this and use a fallback visual if needed - if (info && (info->depth < 32)) { - printf("[WARNING] Unable to locate matching X11 GLX Visual; this OpenGL application may not function correctly!\n"); - XFree( info ); - info = NULL; - flags &= ~CWColormap; - } - - attrs.background_pixel = 0; - attrs.border_pixel = 0; - flags |= CWBackPixel; - flags |= CWBorderPixel; - if (!(flags & CWColormap)) { - if (!info) { - info = new XVisualInfo; - if (!XMatchVisualInfo( x11Display(), x11Screen(), 32, TrueColor, info )) { - printf("[ERROR] Unable to locate matching X11 Visual; this application will not function correctly!\n"); - free(info); - info = NULL; - } - } - if (info) { - visual = info->visual; - attrs.colormap = XCreateColormap( x11Display(), RootWindow( x11Display(), x11Screen()), visual, AllocNone ); - flags |= CWColormap; - } - } - } - if (info) { - XFree( info ); - } - - m_saverRootWindow = XCreateWindow( x11Display(), RootWindow( x11Display(), x11Screen()), x(), y(), width(), height(), 0, x11Depth(), InputOutput, visual, flags, &attrs ); - create( m_saverRootWindow ); - - // Some xscreensaver hacks check for this property - const char *version = "KDE 2.0"; - XChangeProperty (tqt_xdisplay(), winId(), - gXA_SCREENSAVER_VERSION, XA_STRING, 8, PropModeReplace, - (unsigned char *) version, strlen(version)); - - XSetWindowAttributes attr; - attr.event_mask = KeyPressMask | ButtonPressMask | PointerMotionMask | VisibilityChangeMask | ExposureMask; - XChangeWindowAttributes(tqt_xdisplay(), winId(), CWEventMask, &attr); - - // Signal that we want to be transparent to the desktop, not to windows behind us... - XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_desktop, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - - // erase(); - - // set NoBackground so that the saver can capture the current - // screen state if necessary - // this is a security risk and has been deactivated--welcome to the 21st century folks! - // setBackgroundMode(TQWidget::NoBackground); - - setGeometry(0, 0, mRootWidth, mRootHeight); - saverReadyIfNeeded(); - - // HACK - // Hide all tooltips and notification windows - { - Window rootWindow = RootWindow(x11Display(), x11Screen()); - Window parent; - Window* children = NULL; - unsigned int noOfChildren = 0; - XWindowAttributes childAttr; - Window childTransient; - - if (XQueryTree(x11Display(), rootWindow, &rootWindow, &parent, &children, &noOfChildren) && noOfChildren>0 ) { - for (unsigned int i=0; istop(); - stopHack(); - DISABLE_CONTINUOUS_LOCKDLG_DISPLAY - mResizingDesktopLock = true; - - backingPixmap = TQPixmap(); - - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Temporarily hide the entire screen with a new override redirect window - if (m_maskWidget) { - m_maskWidget->setGeometry(0, 0, mRootWidth, mRootHeight); - } - else { - m_maskWidget = new TQWidget(0, 0, TQt::WStyle_StaysOnTop | TQt::WX11BypassWM); - m_maskWidget->setGeometry(0, 0, mRootWidth, mRootHeight); - m_maskWidget->setBackgroundColor(TQt::black); - m_maskWidget->erase(); - m_maskWidget->show(); - } - XSync(tqt_xdisplay(), False); - saverReadyIfNeeded(); - - if (mEnsureScreenHiddenTimer) { - mEnsureScreenHiddenTimer->stop(); - } - else { - mEnsureScreenHiddenTimer = new TQTimer( this ); - connect( mEnsureScreenHiddenTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotForcePaintBackground()) ); - } - mEnsureScreenHiddenTimer->start(DESKTOP_WALLPAPER_OBTAIN_TIMEOUT_MS, true); - } - - // Resize the background widget - setGeometry(0, 0, mRootWidth, mRootHeight); - XSync(tqt_xdisplay(), False); - saverReadyIfNeeded(); - - // Black out the background widget to hide ugly resize tiling artifacts - if (argb_visual) { - setTransparentBackgroundARGB(); - } - else { - setBackgroundColor(black); - } - erase(); - - // This slot needs to be able to execute very rapidly so as to prevent the user's desktop from ever - // being displayed, so we finish the hack restarting/display prettying operations in a separate timed slot - if (resizeTimer == NULL) { - resizeTimer = new TQTimer( this ); - connect( resizeTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(doDesktopResizeFinish()) ); - } - resizeTimer->start( 100, TRUE ); // 100 millisecond single shot timer; should allow display switching operations to finish before hack is started -} - -void LockProcess::doDesktopResizeFinish() -{ - while (mDialogControlLock == true) { - usleep(100000); - } - mDialogControlLock = true; - if (closeCurrentWindow()) { - TQTimer::singleShot( 0, this, SLOT(doDesktopResizeFinish()) ); - mDialogControlLock = false; - return; - } - mDialogControlLock = false; - - // Restart the hack as the window size is now different - if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_use_system_modal_dialogs) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - if (mHackStartupEnabled == true) { - startHack(); - } - else { - if (trinity_desktop_lock_use_system_modal_dialogs == true) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - startHack(); - } - } - } - - mResizingDesktopLock = false; - mBusy = false; -} - -//--------------------------------------------------------------------------- -// -// Hide the screensaver window -// -void LockProcess::hideSaverWindow() -{ - hide(); - lower(); - removeVRoot(winId()); - XDeleteProperty(tqt_xdisplay(), winId(), gXA_SCREENSAVER_VERSION); - if ( gVRoot ) { - unsigned long vroot_data[1] = { gVRootData }; - XChangeProperty(tqt_xdisplay(), gVRoot, gXA_VROOT, XA_WINDOW, 32, - PropModeReplace, (unsigned char *)vroot_data, 1); - gVRoot = 0; - } - XSync(tqt_xdisplay(), False); -} - -//--------------------------------------------------------------------------- -static int ignoreXError(Display *, XErrorEvent *) -{ - return 0; -} - -//--------------------------------------------------------------------------- -// -// Save the current virtual root window -// -void LockProcess::saveVRoot() -{ - Window rootReturn, parentReturn, *children; - unsigned int numChildren; - Window root = RootWindowOfScreen(ScreenOfDisplay(tqt_xdisplay(), tqt_xscreen())); - - gVRoot = 0; - gVRootData = 0; - - int (*oldHandler)(Display *, XErrorEvent *); - oldHandler = XSetErrorHandler(ignoreXError); - - if (XQueryTree(tqt_xdisplay(), 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(tqt_xdisplay(), 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); - } - - unsigned long rw = RootWindowOfScreen(ScreenOfDisplay(tqt_xdisplay(), tqt_xscreen())); - unsigned long vroot_data[1] = { vr }; - - Window rootReturn; - Window parentReturn; - Window *children = NULL; - unsigned int numChildren; - Window top = win; - while (1) { - if (XQueryTree(tqt_xdisplay(), top, &rootReturn, &parentReturn, &children, &numChildren) == 0) { - printf("[WARNING] XQueryTree() failed!\n"); fflush(stdout); - break; - } - if (children) { - XFree((char *)children); - } - if (parentReturn == rw) { - break; - } - else { - top = parentReturn; - } - } - - XChangeProperty(tqt_xdisplay(), top, gXA_VROOT, XA_WINDOW, 32, PropModeReplace, (unsigned char *)vroot_data, 1); -} - -//--------------------------------------------------------------------------- -// -// Remove the virtual root property -// -void LockProcess::removeVRoot(Window win) -{ - XDeleteProperty (tqt_xdisplay(), win, gXA_VROOT); -} - -//--------------------------------------------------------------------------- -// -// Grab the keyboard. Returns true on success -// -bool LockProcess::grabKeyboard() -{ - int rv = XGrabKeyboard( tqt_xdisplay(), TQApplication::desktop()->winId(), - True, GrabModeAsync, GrabModeAsync, CurrentTime ); - - if (rv != GrabSuccess) { - kdWarning(1204) << "LockProcess::grabKeyboard() failed: " << rv << endl; - } - return (rv == GrabSuccess); -} - -#define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ - EnterWindowMask | LeaveWindowMask - -//--------------------------------------------------------------------------- -// -// Grab the mouse. Returns true on success -// -bool LockProcess::grabMouse() -{ - HANDLE cursorHandle; - if (mHackActive) { - cursorHandle = TQCursor(tqblankCursor).handle(); - } - else { - cursorHandle = TQCursor(tqbusyCursor).handle(); - } - int rv = XGrabPointer( tqt_xdisplay(), TQApplication::desktop()->winId(), - True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None, - cursorHandle, CurrentTime ); - - if (rv != GrabSuccess) { - kdWarning(1204) << "LockProcess::grabMouse() failed: " << rv << endl; - } - return (rv == GrabSuccess); -} - -//--------------------------------------------------------------------------- -// -// Grab keyboard and mouse. Returns true on success. -// -bool LockProcess::grabInput() -{ - XSync(tqt_xdisplay(), False); - - if (!grabKeyboard()) { - usleep(100000); - if (!grabKeyboard()) { - return false; - } - } - -#ifndef KEEP_MOUSE_UNGRABBED - if (!grabMouse()) { - usleep(100000); - if (!grabMouse()) { - XUngrabKeyboard(tqt_xdisplay(), CurrentTime); - return false; - } - } -#endif - - lockXF86(); - - return true; -} - -//--------------------------------------------------------------------------- -// -// Release mouse an keyboard grab. -// -void LockProcess::ungrabInput() -{ - XUngrabKeyboard(tqt_xdisplay(), CurrentTime); - XUngrabPointer(tqt_xdisplay(), CurrentTime); - unlockXF86(); -} - -//--------------------------------------------------------------------------- -// -// Generate requisite backing images for ARGB mode -// -void LockProcess::generateBackingImages() -{ - if (argb_visual) { - mArgbTransparentBackgroundPixmap.resize(mRootWidth, mRootHeight); - TQPainter p; - p.begin( &mArgbTransparentBackgroundPixmap ); - p.fillRect( 0, 0, mArgbTransparentBackgroundPixmap.width(), mArgbTransparentBackgroundPixmap.height(), TQBrush(tqRgba(0, 0, 0, 0)) ); - p.end(); - } -} - -//--------------------------------------------------------------------------- -// -// Set a fully transparent ARGB background image. -// -void LockProcess::setTransparentBackgroundARGB() -{ - // eliminate nasty flicker on first show - setBackgroundPixmap( mArgbTransparentBackgroundPixmap ); -} - -void LockProcess::saverReadyIfNeeded() -{ - if (m_notifyReadyRequested) { - // Make sure the desktop is hidden before notifying the desktop that the saver is running - m_notifyReadyRequested = false; - saverReady(); - fullyOnline(); - } -} - -//--------------------------------------------------------------------------- -// -// Start the screen saver. -// -bool LockProcess::startSaver(bool notify_ready) -{ - if (!child_saver && !grabInput()) - { - kdWarning(KDESKTOP_DEBUG_ID) << "LockProcess::startSaver() grabInput() failed!!!!" << endl; - return false; - } - mBusy = false; - - // eliminate nasty flicker on first show - setTransparentBackgroundARGB(); - - saveVRoot(); - - if (mParent) { - TQSocketNotifier *notifier = new TQSocketNotifier(mParent, TQSocketNotifier::Read, TQT_TQOBJECT(this), "notifier"); - connect(notifier, TQT_SIGNAL( activated (int)), TQT_SLOT( quitSaver())); - } - createSaverWindow(); - move(0, 0); - show(); - - raise(); - XSync(tqt_xdisplay(), False); - setVRoot( winId(), winId() ); - - if (!trinity_desktop_lock_hide_active_windows) { - if (m_rootPixmap) m_rootPixmap->stop(); - TQPixmap rootWinSnapShot = TQPixmap::grabWindow(TQApplication::desktop()->winId()); - slotPaintBackground(rootWinSnapShot); - } - - if (((!(trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced)) && (!mInSecureDialog)) && (mHackStartupEnabled || mOverrideHackStartupEnabled)) { - if (argb_visual) { - setTransparentBackgroundARGB(); - } - else { - if (backingPixmap.isNull()) { - setBackgroundColor(black); - } - else { - setBackgroundPixmap(backingPixmap); - } - } - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - - if (notify_ready) { - m_notifyReadyRequested = false; - saverReady(); - fullyOnline(); - } - } - else { - if (notify_ready) { - m_notifyReadyRequested = true; - } - } - - if (mInSecureDialog == FALSE) { - if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - if (mHackStartupEnabled || mOverrideHackStartupEnabled) { - mOverrideHackStartupEnabled = false; - startHack(); - } - else { - if (trinity_desktop_lock_use_system_modal_dialogs == true) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - startHack(); - } - } - } - } - - return true; -} - -//--------------------------------------------------------------------------- -// -// Stop the screen saver. -// -void LockProcess::stopSaver() -{ - kdDebug(KDESKTOP_DEBUG_ID) << "LockProcess: stopping saver" << endl; - mHackProc.kill(SIGCONT); - stopHack(); - mSuspended = false; - hideSaverWindow(); - mVisibility = false; - if (!child_saver) { - if (mLocked) { - DM().setLock( false ); - } - ungrabInput(); - const char *out = "GOAWAY!"; - for (TQValueList::ConstIterator it = child_sockets.begin(); it != child_sockets.end(); ++it) { - if (write(*it, out, sizeof(out)) == -1) { - // Error handler to shut up gcc warnings - } - } - } -} - -// private static -TQVariant LockProcess::getConf(void *ctx, const char *key, const TQVariant &dflt) -{ - LockProcess *that = (LockProcess *)ctx; - TQString fkey = TQString::fromLatin1( key ) + '='; - for (TQStringList::ConstIterator it = that->mPluginOptions.begin(); it != that->mPluginOptions.end(); ++it) { - if ((*it).startsWith( fkey )) { - return (*it).mid( fkey.length() ); - } - } - return dflt; -} - -void LockProcess::cantLock( const TQString &txt) -{ - msgBox( TQMessageBox::Critical, i18n("Will not lock the session, as unlocking would be impossible:\n") + txt ); -} - -#if 0 // placeholders for later -i18n("Cannot start kcheckpass."); -i18n("kcheckpass is unable to operate. Possibly it is not SetUID root."); -#endif - -//--------------------------------------------------------------------------- -// -// Make the screen saver password protected. -// -bool LockProcess::startLock() -{ - for (TQStringList::ConstIterator it = mPlugins.begin(); it != mPlugins.end(); ++it) { - GreeterPluginHandle plugin; - TQString path = KLibLoader::self()->findLibrary( ((*it)[0] == '/' ? *it : "kgreet_" + *it ).latin1() ); - if (path.isEmpty()) { - kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " does not exist" << endl; - continue; - } - if (!(plugin.library = KLibLoader::self()->library( path.latin1() ))) { - kdWarning(KDESKTOP_DEBUG_ID) << "Cannot load GreeterPlugin " << *it << " (" << path << ")" << endl; - continue; - } - if (!plugin.library->hasSymbol( "kgreeterplugin_info" )) { - kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") is no valid greet widget plugin" << endl; - plugin.library->unload(); - continue; - } - plugin.info = (kgreeterplugin_info*)plugin.library->symbol( "kgreeterplugin_info" ); - if (plugin.info->method && !mMethod.isEmpty() && mMethod != plugin.info->method) { - kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") serves " << plugin.info->method << ", not " << mMethod << endl; - plugin.library->unload(); - continue; - } - if (!plugin.info->init( mMethod, getConf, this )) { - kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") refuses to serve " << mMethod << endl; - plugin.library->unload(); - continue; - } - kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded" << endl; - greetPlugin = plugin; - mLocked = true; - DM().setLock( true ); - return true; - } - cantLock( i18n("No appropriate greeter plugin configured.") ); - return false; -} - -//--------------------------------------------------------------------------- -// - -void LockProcess::closeDialogAndStartHack() -{ -#ifdef HAVE_DPMS - if (KDesktopSettings::dpmsDependent()) { - BOOL on; - CARD16 state; - if (DPMSInfo(tqt_xdisplay(), &state, &on)) { - //kdDebug() << "checkDPMSActive " << on << " " << state << endl; - if (DPMS_MONITOR_BLANKED(state)) { - // Make sure saver will attempt to start again after DPMS wakeup - // This is related to Bug 1475 - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - // Should not start saver here, because the DPMS check method below would turn it right back off! - // This is related to Bug 1475 - return; - } - } - } -#endif - - // Close any active dialogs - DISABLE_CONTINUOUS_LOCKDLG_DISPLAY - mSuspended = true; - if (closeCurrentWindow()) { - TQTimer::singleShot( 0, this, SLOT(closeDialogAndStartHack()) ); - } - else { - resume(true); - } -} - -void LockProcess::repaintRootWindowIfNeeded() -{ - if (trinity_desktop_lock_use_system_modal_dialogs) { - if (!mHackProc.isRunning()) { - if (argb_visual) { - setTransparentBackgroundARGB(); - erase(); - } - else { - if (backingPixmap.isNull()) { - setBackgroundColor(black); - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - } - else { - bitBlt(this, 0, 0, &backingPixmap); - } - } - } - if (currentDialog == NULL) { - raise(); - } - saverReadyIfNeeded(); - } -} - -bool LockProcess::startHack() -{ - mHackActive = TRUE; - - if ((mEnsureVRootWindowSecurityTimer) && (!mEnsureVRootWindowSecurityTimer->isActive())) { - mEnsureVRootWindowSecurityTimer->start(250, FALSE); - } - - if (currentDialog || (!mDialogs.isEmpty())) { - // no resuming with dialog visible or when not visible - if (argb_visual) { - setTransparentBackgroundARGB(); - } - else { - if (backingPixmap.isNull()) { - setBackgroundColor(black); - } - else { - setBackgroundPixmap(backingPixmap); - } - } - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - saverReadyIfNeeded(); - return false; - } - - setCursor( tqblankCursor ); - XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqblankCursor).handle(), CurrentTime); - - if (mSaverExec.isEmpty()) { - return false; - } - - if (mHackProc.isRunning()) { - stopHack(); - } - - mHackProc.clearArguments(); - - TQTextStream ts(&mSaverExec, IO_ReadOnly); - TQString word; - ts >> word; - TQString path = TDEStandardDirs::findExe(word); - - if (!path.isEmpty()) { - mHackProc << path; - - kdDebug(KDESKTOP_DEBUG_ID) << "Starting hack: " << path << endl; - - while (!ts.atEnd()) { - ts >> word; - if (word == "%w") - { - word = word.setNum(winId()); - } - mHackProc << word; - } - - if (!mForbidden) { - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Make sure we have a nice clean display to start with! - if (argb_visual) { - // Signal that we want to be transparent to a black background... - if (m_saverRootWindow) { - XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); - } - setTransparentBackgroundARGB(); - } - else { - if (backingPixmap.isNull()) { - setBackgroundColor(black); - } - else { - setBackgroundPixmap(backingPixmap); - } - } - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - saverReadyIfNeeded(); - mSuspended = false; - } - - XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqblankCursor).handle(), CurrentTime); - if (mHackProc.start() == true) { -#ifdef HAVE_SETPRIORITY - setpriority(PRIO_PROCESS, mHackProc.pid(), mPriority); -#endif - //bitBlt(this, 0, 0, &mOriginal); - DISABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced) { - // Close any active dialogs - if (closeCurrentWindow()) { - TQTimer::singleShot( 0, this, SLOT(closeCurrentWindow()) ); - } - } - if (m_startupStatusDialog) { m_startupStatusDialog->closeSMDialog(); m_startupStatusDialog=NULL; } - return true; - } - } - else { - // we aren't allowed to start the specified screensaver either because it didn't run for some reason - // according to the kiosk restrictions forbid it - usleep(100); - TQApplication::syncX(); - if (!trinity_desktop_lock_use_system_modal_dialogs) { - if (argb_visual) { - setTransparentBackgroundARGB(); - } - else { - if (backingPixmap.isNull()) { - setBackgroundColor(black); - } - else { - setBackgroundPixmap(backingPixmap); - } - } - } - if (argb_visual) { - setTransparentBackgroundARGB(); - erase(); - } - else { - if (backingPixmap.isNull()) { - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - } - else { - bitBlt(this, 0, 0, &backingPixmap); - } - } - if (trinity_desktop_lock_use_system_modal_dialogs) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - saverReadyIfNeeded(); - } - } - - if (m_startupStatusDialog) { - m_startupStatusDialog->closeSMDialog(); - m_startupStatusDialog=NULL; - } - - return false; -} - -//--------------------------------------------------------------------------- -// -void LockProcess::stopHack() -{ - if (mHackProc.isRunning()) { - mHackProc.kill(); - if (!mHackProc.wait(10)) { - mHackProc.kill(SIGKILL); - } - } - setCursor( tqarrowCursor ); - - mHackActive = FALSE; -} - -//--------------------------------------------------------------------------- -// -void LockProcess::hackExited(TDEProcess *) -{ - // Hack exited while we're supposed to be saving the screen. - // Make sure the saver window is black. - mHackActive = FALSE; - usleep(100); - TQApplication::syncX(); - if (!trinity_desktop_lock_use_system_modal_dialogs) { - if (argb_visual) { - setTransparentBackgroundARGB(); - } - else { - if (backingPixmap.isNull()) { - setBackgroundColor(black); - } - else { - setBackgroundPixmap(backingPixmap); - } - } - } - if (argb_visual) { - if (m_saverRootWindow) { - XDeleteProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black); - XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); - } - setTransparentBackgroundARGB(); - } - else { - if (backingPixmap.isNull()) { - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - } - else { - bitBlt(this, 0, 0, &backingPixmap); - } - } - if (!mSuspended) { - if (trinity_desktop_lock_use_system_modal_dialogs) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - } - saverReadyIfNeeded(); -} - -void LockProcess::displayLockDialogIfNeeded() -{ - if (m_startupStatusDialog) { - m_startupStatusDialog->closeSMDialog(); - m_startupStatusDialog = NULL; - } - if (!mInSecureDialog) { - if (trinity_desktop_lock_use_system_modal_dialogs) { - if (!mBusy) { - mBusy = true; - if (mLocked) { - if (checkPass()) { - mClosingWindows = true; - stopSaver(); - kapp->quit(); - } - } - mBusy = false; - } - } - } -} - -void LockProcess::suspend() -{ - if (!mSuspended) { - if (trinity_desktop_lock_use_system_modal_dialogs) { - mSuspended = true; - stopHack(); - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) { - mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - } - else { - TQString hackStatus; - mHackProc.kill(SIGSTOP); - mSuspended = true; -#if 0 - // wait for the stop signal to take effect - while (hackStatus != "T") { - char hackstat[8192]; - FILE *fp = fopen(TQString("/proc/%1/stat").arg(mHackProc.pid()).ascii(),"r"); - if (fp != NULL) { - fgets (hackstat, 8192, fp); - fclose (fp); - } - hackstat[8191] = 0; - hackStatus = hackstat; - hackStatus = hackStatus.remove(TQRegExp("(*) ", TRUE, TRUE)); - TQStringList hackStatusList = TQStringList::split(" ", hackStatus); - hackStatus = (*(hackStatusList.at(1))); - } -#endif - TQApplication::syncX(); - usleep(100000); // Allow certain bad graphics drivers (*cough* fglrx *cough*) time to actually sync up the display - } - TQApplication::syncX(); - mSavedScreen = TQPixmap::grabWindow( winId()); - } -} - -void LockProcess::resume( bool force ) -{ - if (trinity_desktop_lock_use_sak && (mHackDelayStartupTimer->isActive() || !mHackStartupEnabled)) { - return; - } - if( !force && (!mDialogs.isEmpty() || !mVisibility )) { - // no resuming with dialog visible or when not visible - if (trinity_desktop_lock_use_system_modal_dialogs) { - if (argb_visual) { - setTransparentBackgroundARGB(); - } - else { - if (backingPixmap.isNull()) { - setBackgroundColor(black); - } - else { - setBackgroundPixmap(backingPixmap); - } - } - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - } - else { - setGeometry(0, 0, mRootWidth, mRootHeight); - } - saverReadyIfNeeded(); - return; - } - if ((mSuspended) && (mHackProc.isRunning())) { - XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); - bitBlt( this, 0, 0, &mSavedScreen ); - TQApplication::syncX(); - mHackProc.kill(SIGCONT); - mSuspended = false; - } - else if (mSuspended && trinity_desktop_lock_use_system_modal_dialogs) { - startHack(); - } -} - -//--------------------------------------------------------------------------- -// -// Show the password dialog -// This is called only in the master process -// -bool LockProcess::checkPass() -{ - if (!mDialogs.isEmpty()) { - // Another dialog is already shown - // Abort! - return 0; - } - if (mInfoMessageDisplayed == false) { - if (mAutoLogout) { - killTimer(mAutoLogoutTimerId); - } - - // Make sure we never launch the SAK or login dialog if windows are being closed down - // Otherwise we can get stuck in an irrecoverable state where any attempt to show the login screen is instantly aborted - if (mClosingWindows) { - return 0; - } - - if (trinity_desktop_lock_use_sak) { - // Verify SAK operational status - TDEProcess* checkSAKProcess = new TDEProcess; - *checkSAKProcess << "tdmtsak" << "check"; - checkSAKProcess->start(TDEProcess::Block, TDEProcess::NoCommunication); - int retcode = checkSAKProcess->exitStatus(); - delete checkSAKProcess; - if (retcode != 0) { - trinity_desktop_lock_use_sak = false; - } - } - - if (trinity_desktop_lock_use_sak) { - // Wait for SAK press before continuing... - SAKDlg inDlg( this ); - execDialog( &inDlg ); - if (mClosingWindows) { - return 0; - } - } - - showVkbd(); - PasswordDlg passDlg( this, &greetPlugin, (mShowLockDateTime)?mlockDateTime:TQDateTime()); - int ret = execDialog( &passDlg ); - hideVkbd(); - - if (mForceReject == true) { - ret = TQDialog::Rejected; - } - mForceReject = false; - - XWindowAttributes rootAttr; - XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), - tqt_xscreen()), &rootAttr); - if(( rootAttr.your_event_mask & SubstructureNotifyMask ) == 0 ) { - kdWarning() << "ERROR: Something removed SubstructureNotifyMask from the root window!!!" << endl; - XSelectInput( tqt_xdisplay(), tqt_xrootwin(), - SubstructureNotifyMask | rootAttr.your_event_mask ); - } - - return ret == TQDialog::Accepted; - } - else { - return 0; - } -} - -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 = tqt_xdisplay(); - ev.xfocus.type = FocusIn; - ev.xfocus.window = window; - ev.xfocus.mode = NotifyNormal; - ev.xfocus.detail = NotifyAncestor; - XSendEvent( tqt_xdisplay(), window, False, NoEventMask, &ev ); -} - -void LockProcess::resumeUnforced() -{ - resume( false ); -} - -int LockProcess::execDialog( TQDialog *dlg ) -{ - currentDialog=dlg; - dlg->adjustSize(); - - TQRect rect = dlg->geometry(); - rect.moveCenter(TDEGlobalSettings::desktopGeometry(TQCursor::pos()).center()); - dlg->move( rect.topLeft() ); - - if (mDialogs.isEmpty()) { - suspend(); - XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqarrowCursor).handle(), CurrentTime); - } - mDialogs.prepend( dlg ); - fakeFocusIn( dlg->winId()); - if (trinity_desktop_lock_use_system_modal_dialogs) { - if (backingPixmap.isNull()) { - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - } - else { - bitBlt(this, 0, 0, &backingPixmap); - } - saverReadyIfNeeded(); - } - // dlg->exec may generate BadMatch errors, so make sure they are silently ignored - int (*oldHandler)(Display *, XErrorEvent *); - oldHandler = XSetErrorHandler(ignoreXError); - int rt = dlg->exec(); - XSetErrorHandler(oldHandler); - while (mDialogControlLock == true) { - usleep(100000); - } - currentDialog = NULL; - mDialogs.remove( dlg ); - if( mDialogs.isEmpty() ) { - HANDLE cursorHandle; - if (mHackActive) { - cursorHandle = TQCursor(tqblankCursor).handle(); - } - else { - cursorHandle = TQCursor(tqbusyCursor).handle(); - } - XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, cursorHandle, CurrentTime); - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Slight delay before screensaver resume to allow the dialog window to fully disappear - if (hackResumeTimer == NULL) { - hackResumeTimer = new TQTimer( this ); - connect( hackResumeTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(resumeUnforced()) ); - } - if (mResizingDesktopLock == false) { - hackResumeTimer->start( 10, TRUE ); - } - } - else { - resume( false ); - } - } - else { - fakeFocusIn( mDialogs.first()->winId()); - currentDialog = dynamic_cast(mDialogs.first()); - } - return rt; -} - -void LockProcess::slotForcePaintBackground() -{ - TQPixmap blankPixmap(mRootWidth, mRootHeight); - blankPixmap.fill(Qt::black); - slotPaintBackground(blankPixmap); - printf("[WARNING] Unable to obtain desktop wallpaper in a timely manner. High system load or possibly a TDE bug!\n"); fflush(stdout); -} - -void LockProcess::slotPaintBackground(const TQPixmap &rpm) -{ - if (argb_visual) { - if (mEnsureScreenHiddenTimer) { - mEnsureScreenHiddenTimer->stop(); - } - return; - } - - if (mEnsureScreenHiddenTimer) { - mEnsureScreenHiddenTimer->stop(); - } - else { - mEnsureScreenHiddenTimer = new TQTimer( this ); - connect( mEnsureScreenHiddenTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotForcePaintBackground()) ); - } - - // Only remove the mask widget once the resize is 100% complete! - if (m_maskWidget) { - delete m_maskWidget; - m_maskWidget = NULL; - XSync(tqt_xdisplay(), False); - } - - TQPixmap pm = rpm; - - if (TQPaintDevice::x11AppDepth() == 32) { - // Remove the alpha components from the image - TQImage correctedImage = pm.convertToImage(); - correctedImage = correctedImage.convertDepth(32); - correctedImage.setAlphaBuffer(true); - int w = correctedImage.width(); - int h = correctedImage.height(); - for (int y = 0; y < h; ++y) { - TQRgb *ls = (TQRgb *)correctedImage.scanLine( y ); - for (int x = 0; x < w; ++x) { - TQRgb l = ls[x]; - int r = int( tqRed( l ) ); - int g = int( tqGreen( l ) ); - int b = int( tqBlue( l ) ); - int a = int( 255 ); - ls[x] = tqRgba( r, g, b, a ); - } - } - pm.convertFromImage(correctedImage); - } - - backingPixmap = pm; - if ((trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced) || (!mHackStartupEnabled)) { - setBackgroundPixmap(backingPixmap); - setGeometry(0, 0, mRootWidth, mRootHeight); - erase(); - } -} - -void LockProcess::preparePopup() -{ - TQWidget *dlg = (TQWidget *)sender(); - mDialogs.prepend( dlg ); - fakeFocusIn( dlg->winId() ); -} - -void LockProcess::cleanupPopup() -{ - TQWidget *dlg = (TQWidget *)sender(); - mDialogs.remove( dlg ); - if ( mDialogs.isEmpty() ) { - fakeFocusIn( mDialogs.first()->winId() ); - } -} - -void LockProcess::doFunctionKeyBroadcast() { - // Provide a clean, pretty display switch by hiding the password dialog here - // This does NOT work with the SAK or system modal dialogs! - if ((!trinity_desktop_lock_use_system_modal_dialogs) && (!trinity_desktop_lock_use_sak)) { - mBusy=true; - TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); - if (mkeyCode == XKeysymToKeycode(tqt_xdisplay(), XF86XK_Display)) { - while (mDialogControlLock == true) { - usleep(100000); - } - mDialogControlLock = true; - currentDialog->close(); // DO NOT use closeCurrentWindow() here! - mDialogControlLock = false; - } - } - - DCOPRef ref( "*", "MainApplication-Interface"); - ref.send("sendFakeKey", DCOPArg(mkeyCode , "unsigned int")); -} - -//--------------------------------------------------------------------------- -// -// X11 Event. -// -bool LockProcess::x11Event(XEvent *event) -{ - // Allow certain very specific keypresses through - // Key: Reason: - // XF86Display You need to be able to see the screen when unlocking your computer - // XF86AudioMute Would be nice to be able to shut your computer up in an emergency while it is locked - // XF86AudioRaiseVolume Ditto - // XF86AudioLowerVolume Ditto - // XF86XK_PowerOff If someone has access to the power button, they can hard power off the machine anyway - // XF86XK_Sleep Ditto - // XF86XK_Suspend Ditto - // XF86XK_Hibernate Ditto - - //if ((event->type == KeyPress) || (event->type == KeyRelease)) { - if (event->type == KeyPress) { - // Multimedia keys - if ((event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Display)) || \ - (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioMute)) || \ - (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioRaiseVolume)) || \ - (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioLowerVolume))) { - mkeyCode = event->xkey.keycode; - TQTimer::singleShot( 100, this, TQT_SLOT(doFunctionKeyBroadcast()) ); - return true; - } - // ACPI power keys - if ((event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_PowerOff)) || \ - (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Sleep)) || \ - (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Suspend)) || \ - (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Hibernate))) { - mkeyCode = event->xkey.keycode; - TQTimer::singleShot( 100, this, TQT_SLOT(doFunctionKeyBroadcast()) ); - return true; - } - } - - switch (event->type) - { - case ButtonPress: - case MotionNotify: - case ButtonRelease: - if( forwardVkbdEvent( event )) { - return true; // filter out - } - // fall through - case KeyPress: - if ((mHackDelayStartupTimer) && (mHackDelayStartupTimer->isActive())) { - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - if (mBusy || !mDialogs.isEmpty()) { - break; - } - mBusy = true; - if (trinity_desktop_lock_delay_screensaver_start) { - if (mLocked) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) { - mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - } - if ((!mLocked) && (!mInSecureDialog)) { - stopSaver(); - kapp->quit(); - } - if (mAutoLogout) { - // we need to restart the auto logout countdown - killTimer(mAutoLogoutTimerId); - mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout); - } - } - else { - if (!mLocked || checkPass()) { - mClosingWindows = true; - stopSaver(); - kapp->quit(); - } - else if (mAutoLogout) { - // we need to restart the auto logout countdown - killTimer(mAutoLogoutTimerId); - mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout); - } - } - mBusy = false; - return true; - - case VisibilityNotify: - if( event->xvisibility.window == winId()) { - // mVisibility == false means the screensaver is not visible at all - // e.g. when switched to text console - mVisibility = !(event->xvisibility.state == VisibilityFullyObscured); - if(!mVisibility) { - mSuspendTimer.start(2000, true); - } - else { - mSuspendTimer.stop(); - if (mResizingDesktopLock == false) { - if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { - // Do nothing - } - else { - if (mHackStartupEnabled == true) { - resume( false ); - } - else { - if (trinity_desktop_lock_use_system_modal_dialogs == true) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - resume( false ); - } - } - } - } - } - if (event->xvisibility.state != VisibilityUnobscured) { - stayOnTop(); - } - } - break; - - case ConfigureNotify: // from SubstructureNotifyMask on the root window - if(event->xconfigure.event == tqt_xrootwin()) { - stayOnTop(); - } - for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); - it != mVkbdWindows.end(); - ++it ) { - if( (*it).id == event->xconfigure.window ) { - (*it).rect = TQRect( event->xconfigure.x, event->xconfigure.y, - event->xconfigure.width, event->xconfigure.height ); - break; - } - } - break; - case MapNotify: // from SubstructureNotifyMask on the root window - windowAdded( event->xmap.window, false ); - if( event->xmap.event == tqt_xrootwin()) { - stayOnTop(); - } - break; - case DestroyNotify: - for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) { - if( (*it).id == event->xdestroywindow.window ) { - mVkbdWindows.remove( it ); - break; - } - } - 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() && ( event->type == KeyPress || event->type == KeyRelease) - && event->xkey.window != mDialogs.first()->winId()) { - XEvent ev2 = *event; - ev2.xkey.window = ev2.xkey.subwindow = mDialogs.first()->winId(); - tqApp->x11ProcessEvent( &ev2 ); - return true; - } - - return false; -} - -void LockProcess::stayOnTop() -{ - if(!mDialogs.isEmpty() || !mVkbdWindows.isEmpty()) { - // 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 - if( !mVkbdWindows.isEmpty()) { - XRaiseWindow( tqt_xdisplay(), mVkbdWindows.first().id ); - } - else { - XRaiseWindow( tqt_xdisplay(), mDialogs.first()->winId()); // raise topmost - } - // and stack others below it - Window* stack = new Window[ mDialogs.count() + mVkbdWindows.count() + 1 ]; - int count = 0; - for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) { - stack[ count++ ] = (*it).id; - } - for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); it != mDialogs.end(); ++it ) { - stack[ count++ ] = (*it)->winId(); - } - stack[ count++ ] = winId(); - XRestackWindows( x11Display(), stack, count ); - delete[] stack; - } - else { - XRaiseWindow(tqt_xdisplay(), winId()); - } -} - -void LockProcess::checkDPMSActive() -{ -#ifdef HAVE_DPMS - if (KDesktopSettings::dpmsDependent()) { - BOOL on; - CARD16 state; - if (DPMSInfo(tqt_xdisplay(), &state, &on)) { - //kdDebug() << "checkDPMSActive " << on << " " << state << endl; - if (DPMS_MONITOR_BLANKED(state)) { - suspend(); - } - else if (mSuspended) { - if (mResizingDesktopLock == false) { - resume( true ); - } - } - } - } -#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 kdesktop_lock 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; - if( XF86MiscQueryVersion( tqt_xdisplay(), &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( tqt_xdisplay(), False ) != MiscExtGrabStateSuccess ) { - return; - } - // success - mRestoreXF86Lock = true; -} - -void LockProcess::unlockXF86() -{ - if( can_do_xf86_lock != Yes ) { - return; - } - if( !mRestoreXF86Lock ) { - return; - } - XF86MiscSetGrabKeysState( tqt_xdisplay(), True ); - mRestoreXF86Lock = false; -} -#else -void LockProcess::lockXF86() -{ - // -} - -void LockProcess::unlockXF86() -{ - // -} -#endif - -void LockProcess::msgBox( TQMessageBox::Icon type, const TQString &txt ) -{ - TQDialog box( 0, "messagebox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - XChangeProperty(tqt_xdisplay(), box.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - box.setCaption(i18n("Authentication Subsystem Notice")); - TQFrame *winFrame = new TQFrame( &box ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - winFrame->setFrameStyle( TQFrame::NoFrame ); - } - else { - winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); - } - winFrame->setLineWidth( 2 ); - TQLabel *label1 = new TQLabel( winFrame ); - label1->setPixmap( TQMessageBox::standardIcon( type ) ); - TQLabel *label2 = new TQLabel( txt, winFrame ); - KPushButton *button = new KPushButton( KStdGuiItem::ok(), winFrame ); - button->setDefault( true ); - button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); - connect( button, TQT_SIGNAL( clicked() ), &box, TQT_SLOT( accept() ) ); - - TQVBoxLayout *vbox = new TQVBoxLayout( &box ); - vbox->addWidget( winFrame ); - TQGridLayout *grid = new TQGridLayout( winFrame, 2, 2, 10 ); - grid->addWidget( label1, 0, 0, Qt::AlignCenter ); - grid->addWidget( label2, 0, 1, Qt::AlignCenter ); - grid->addMultiCellWidget( button, 1,1, 0,1, Qt::AlignCenter ); - - execDialog( &box ); -} - -static int run_vkbd = -1; -void LockProcess::showVkbd() -{ - if( run_vkbd == - 1 ) { -#ifdef WITH_HAL - int status = system( "hal-find-by-property --key system.formfactor.subtype --string tabletpc" ); -// status = 0; // enable for testing - run_vkbd = ( WIFEXITED( status ) && WEXITSTATUS( status ) == 0 && !TDEStandardDirs::findExe( "xvkbd" ).isEmpty()) ? 1 : 0; -#else // WITH_HAL - run_vkbd = (!TDEStandardDirs::findExe( "xvkbd" ).isEmpty()); -#endif // WITH_HAL - } - if( run_vkbd ) { - mVkbdWindows.clear(); - mVkbdLastEventWindow = None; - mKWinModule = new KWinModule( NULL, KWinModule::INFO_WINDOWS ); - connect( mKWinModule, TQT_SIGNAL( windowAdded( WId )), TQT_SLOT( windowAdded( WId ))); - mVkbdProcess = new TDEProcess; - *mVkbdProcess << "xvkbd" << "-compact" << "-geometry" << "-0-0" << "-xdm"; - mVkbdProcess->start(); - } -} - -void LockProcess::hideVkbd() -{ - if( mVkbdProcess != NULL ) { - mVkbdProcess->kill(); - delete mVkbdProcess; - mVkbdProcess = NULL; - delete mKWinModule; - mKWinModule = NULL; - mVkbdWindows.clear(); - } -} - -void LockProcess::windowAdded( WId w ) -{ - windowAdded( w, true ); -} - -void LockProcess::windowAdded( WId w, bool managed ) -{ - // KWin::windowInfo may generate BadWindow errors, so make sure they are silently ignored - int (*oldHandler)(Display *, XErrorEvent *); - oldHandler = XSetErrorHandler(ignoreXError); - KWin::WindowInfo info = KWin::windowInfo( w, 0, NET::WM2WindowClass ); - XSetErrorHandler(oldHandler); - - if( info.windowClassClass().lower() != "xvkbd" ) { - return; - } - // Unmanaged windows (i.e. popups) don't currently work anyway, since they - // don't have WM_CLASS set anyway. I could perhaps try tricks with X id - // ranges if really needed. - if( managed ) { - // withdraw the window, wait for it to be withdrawn, reparent it directly - // to root at the right position - XWithdrawWindow( tqt_xdisplay(), w, tqt_xscreen()); - for(;;) { - Atom type; - int format; - unsigned long length, after; - unsigned char *data; - int r = XGetWindowProperty( tqt_xdisplay(), w, tqt_wm_state, 0, 2, - false, AnyPropertyType, &type, &format, - &length, &after, &data ); - bool withdrawn = true; - if ( r == Success && data && format == 32 ) { - TQ_UINT32 *wstate = (TQ_UINT32*)data; - withdrawn = (*wstate == WithdrawnState ); - XFree( (char *)data ); - } - if( withdrawn ) { - break; - } - } - } - XSelectInput( tqt_xdisplay(), w, StructureNotifyMask ); - XWindowAttributes attr_geom; - if( !XGetWindowAttributes( tqt_xdisplay(), w, &attr_geom )) { - return; - } - int x = XDisplayWidth( tqt_xdisplay(), tqt_xscreen()) - attr_geom.width; - int y = XDisplayHeight( tqt_xdisplay(), tqt_xscreen()) - attr_geom.height; - if( managed ) { - XSetWindowAttributes attr; - if (!trinity_desktop_lock_use_system_modal_dialogs) { - attr.override_redirect = True; - XChangeWindowAttributes( tqt_xdisplay(), w, CWOverrideRedirect, &attr ); - } - XReparentWindow( tqt_xdisplay(), w, tqt_xrootwin(), x, y ); - XMapWindow( tqt_xdisplay(), w ); - } - VkbdWindow data; - data.id = w; - data.rect = TQRect( x, y, attr_geom.width, attr_geom.height ); - mVkbdWindows.prepend( data ); -} - -bool LockProcess::forwardVkbdEvent( XEvent* event ) -{ - if( mVkbdProcess == NULL ) { - return false; - } - TQPoint pos; - Time time; - switch( event->type ) - { - case ButtonPress: - case ButtonRelease: - pos = TQPoint( event->xbutton.x, event->xbutton.y ); - time = event->xbutton.time; - break; - case MotionNotify: - pos = TQPoint( event->xmotion.x, event->xmotion.y ); - time = event->xmotion.time; - break; - default: - return false; - } - // vkbd windows are kept topmost, so just find the first one in the position - for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) { - if( TQT_TQRECT_OBJECT((*it).rect).contains( pos )) { - // Find the subwindow where the event should actually go. - // Not exactly cheap in the number of X roundtrips but oh well. - Window window = (*it).id; - Window root, child; - int root_x, root_y, x, y; - unsigned int mask; - for(;;) { - if( !XQueryPointer( tqt_xdisplay(), window, &root, &child, &root_x, &root_y, &x, &y, &mask )) { - return false; - } - if( child == None ) { - break; - } - window = child; - } - switch( event->type ) - { - case ButtonPress: - case ButtonRelease: - event->xbutton.x = x; - event->xbutton.y = y; - event->xbutton.subwindow = None; - break; - case MotionNotify: - event->xmotion.x = x; - event->xmotion.y = y; - event->xmotion.subwindow = None; - break; - } - event->xany.window = window; - sendVkbdFocusInOut( window, time ); - XSendEvent( tqt_xdisplay(), window, False, 0, event ); - return true; - } - } - sendVkbdFocusInOut( None, time ); - return false; -} - -// Fake EnterNotify/LeaveNotify events as the mouse moves. They're not sent by X -// because of the grab and having them makes xvkbd highlight the buttons (but -// not needed otherwise it seems). -void LockProcess::sendVkbdFocusInOut( WId window, Time t ) -{ - if( mVkbdLastEventWindow == window ) { - return; - } - if( mVkbdLastEventWindow != None ) { - XEvent e; - e.xcrossing.type = LeaveNotify; - e.xcrossing.display = tqt_xdisplay(); - e.xcrossing.window = mVkbdLastEventWindow; - e.xcrossing.root = tqt_xrootwin(); - e.xcrossing.subwindow = None; - e.xcrossing.time = t; - e.xcrossing.x = 0; - e.xcrossing.y = 0; - e.xcrossing.x_root = -1; - e.xcrossing.y_root = -1; - e.xcrossing.mode = NotifyNormal; - e.xcrossing.detail = NotifyAncestor; - e.xcrossing.same_screen = True; - e.xcrossing.focus = False; - e.xcrossing.state = 0; - XSendEvent( tqt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); - } - mVkbdLastEventWindow = window; - if( mVkbdLastEventWindow != None ) { - XEvent e; - e.xcrossing.type = EnterNotify; - e.xcrossing.display = tqt_xdisplay(); - e.xcrossing.window = mVkbdLastEventWindow; - e.xcrossing.root = tqt_xrootwin(); - e.xcrossing.subwindow = None; - e.xcrossing.time = t; - e.xcrossing.x = 0; - e.xcrossing.y = 0; - e.xcrossing.x_root = 0; - e.xcrossing.y_root = 0; - e.xcrossing.mode = NotifyNormal; - e.xcrossing.detail = NotifyAncestor; - e.xcrossing.same_screen = True; - e.xcrossing.focus = False; - e.xcrossing.state = 0; - XSendEvent( tqt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); - } -} - -void LockProcess::slotMouseActivity(XEvent *event) -{ - bool inFrame = 0; - bool inDialog = 0; - XButtonEvent *be = (XButtonEvent *) event; - XMotionEvent *me = (XMotionEvent *) event; - if ((event->type == ButtonPress) && (!mDialogs.isEmpty())) { - // Get geometry including window frame/titlebar - TQRect fgeom = mDialogs.first()->frameGeometry(); - TQRect wgeom = mDialogs.first()->geometry(); - - if (((be->x_root > fgeom.x()) && (be->y_root > fgeom.y())) && ((be->x_root < (fgeom.x()+fgeom.width())) && (be->y_root < (fgeom.y()+fgeom.height())))) { - inFrame = 1; - } - if (((be->x_root > wgeom.x()) && (be->y_root > wgeom.y())) && ((be->x_root < (wgeom.x()+wgeom.width())) && (be->y_root < (wgeom.y()+wgeom.height())))) { - inDialog = 1; - } - - // Clicked inside dialog; set focus - if (inFrame == TRUE) { - WId window = mDialogs.first()->winId(); - XSetInputFocus(tqt_xdisplay(), window, RevertToParent, CurrentTime); - fakeFocusIn(window); - // Why this needs to be repeated I have no idea... - XSetInputFocus(tqt_xdisplay(), window, RevertToParent, CurrentTime); - fakeFocusIn(window); - } - - // Clicked inside window handle (or border); drag window - if ((inFrame == TRUE) && (inDialog == FALSE)) { - TQPoint oldPoint = mDialogs.first()->pos(); - m_mouseDown = 1; - m_dialogPrevX = oldPoint.x(); - m_dialogPrevY = oldPoint.y(); - m_mousePrevX = be->x_root; - m_mousePrevY = be->y_root; - XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqsizeAllCursor).handle(), CurrentTime); - } - } - - // Drag the window... - if (event->type == MotionNotify) { - if (m_mouseDown == TRUE) { - int deltaX = me->x_root - m_mousePrevX; - int deltaY = me->y_root - m_mousePrevY; - m_dialogPrevX = m_dialogPrevX + deltaX; - m_dialogPrevY = m_dialogPrevY + deltaY; - if (!mDialogs.isEmpty()) mDialogs.first()->move(m_dialogPrevX, m_dialogPrevY); - - m_mousePrevX = me->x_root; - m_mousePrevY = me->y_root; - } - } - - if (event->type == ButtonRelease) { - m_mouseDown = 0; - XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqarrowCursor).handle(), CurrentTime); - } -} - -void LockProcess::processInputPipeCommand(TQString inputcommand) { - TQCString command(inputcommand.ascii()); - TQString to_display; - TQString pin_entry; - - if (command[0] == 'C') { - while (mDialogControlLock == true) usleep(100000); - mDialogControlLock = true; - if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { - if (currentDialog != NULL) { - mForceReject = true; - closeCurrentWindow(); - } - } - mClosingWindows = false; - mInfoMessageDisplayed = false; - mDialogControlLock = false; - } - if (command[0] == 'T') { - to_display = command.data(); - to_display = to_display.remove(0,1); - // Lock out password dialogs and close any active dialog - while (mDialogControlLock == true) usleep(100000); - mDialogControlLock = true; - if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { - if (currentDialog != NULL) { - mForceReject = true; - closeCurrentWindow(); - } - } - mInfoMessageDisplayed = true; - mDialogControlLock = false; - // Display info message dialog - InfoDlg inDlg( this ); - inDlg.updateLabel(to_display); - inDlg.setUnlockIcon(); - execDialog( &inDlg ); - mForceReject = false; - mClosingWindows = false; - return; - } - if ((command[0] == 'E') || (command[0] == 'W') || (command[0] == 'I') || (command[0] == 'K')) { - to_display = command.data(); - to_display = to_display.remove(0,1); - // Lock out password dialogs and close any active dialog - while (mDialogControlLock == true) usleep(100000); - mDialogControlLock = true; - if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { - if (currentDialog != NULL) { - mForceReject = true; - closeCurrentWindow(); - } - } - mInfoMessageDisplayed = true; - mDialogControlLock = false; - // Display info message dialog - InfoDlg inDlg( this ); - inDlg.updateLabel(to_display); - if (command[0] == 'K') inDlg.setKDEIcon(); - if (command[0] == 'I') inDlg.setInfoIcon(); - if (command[0] == 'W') inDlg.setWarningIcon(); - if (command[0] == 'E') inDlg.setErrorIcon(); - execDialog( &inDlg ); - mForceReject = false; - mClosingWindows = false; - return; - } - if (command[0] == 'Q') { - to_display = command.data(); - to_display = to_display.remove(0,1); - // Lock out password dialogs and close any active dialog - while (mDialogControlLock == true) usleep(100000); - mDialogControlLock = true; - if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { - if (currentDialog != NULL) { - mForceReject = true; - closeCurrentWindow(); - } - } - mInfoMessageDisplayed = true; - mDialogControlLock = false; - // Display query dialog - QueryDlg qryDlg( this ); - qryDlg.updateLabel(to_display); - qryDlg.setUnlockIcon(); - mForceReject = false; - execDialog( &qryDlg ); - if (mForceReject == false) { - pin_entry = qryDlg.getEntry(); - mInfoMessageDisplayed=false; - if (mPipeOpen_out == true) { - TQCString pin_entry_local8 = pin_entry.local8Bit(); // local 8 bit length may differ from TQString length - if (write(mPipe_fd_out, pin_entry_local8.data(), pin_entry_local8.length()+1) == -1) { - // Error handler to shut up gcc warnings - } - if (write(mPipe_fd_out, "\n\r", 3) == -1) { - // Error handler to shut up gcc warnings - } - } - } - mForceReject = false; - mClosingWindows = false; - return; - } -} - -void LockProcess::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) { - TQString login_name = TQString::null; - X509CertificatePtrList certList = cdevice->cardX509Certificates(); - if (certList.count() > 0) { - KSSLCertificate* card_cert = NULL; - card_cert = KSSLCertificate::fromX509(certList[0]); - TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false); - for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) { - TQString lcpart = (*it).lower(); - if (lcpart.startsWith("cn=")) { - login_name = lcpart.right(lcpart.length() - strlen("cn=")); - } - } - delete card_cert; - } - - if (login_name != "") { - KUser user; - if (login_name == user.loginName()) { - // Pass login to the PAM stack... - m_loginCardDevice = cdevice; - if (dynamic_cast(currentDialog)) { - dynamic_cast(currentDialog)->closeDialogForced(); - TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin())); - } - else if (dynamic_cast(currentDialog)) { - dynamic_cast(currentDialog)->closeDialogForced(); - TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin())); - } - else if (dynamic_cast(currentDialog)) { - signalPassDlgToAttemptCardLogin(); - } - } - } -} - -void LockProcess::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) { - PasswordDlg* passDlg = dynamic_cast(currentDialog); - if (passDlg) { - passDlg->resetCardLogin(); - } - else { - m_loginCardDevice = NULL; - TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort())); - } -} - -void LockProcess::signalPassDlgToAttemptCardLogin() { - PasswordDlg* passDlg = dynamic_cast(currentDialog); - if (passDlg && m_loginCardDevice) { - passDlg->attemptCardLogin(); - } - else { - if (currentDialog && m_loginCardDevice) { - // Try again later - TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin())); - } - } -} - -void LockProcess::signalPassDlgToAttemptCardAbort() { - PasswordDlg* passDlg = dynamic_cast(currentDialog); - if (passDlg) { - passDlg->resetCardLogin(); - } - else { - if (currentDialog) { - // Try again later - TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort())); - } - } -} - -void LockProcess::cryptographicCardPinRequested(TQString prompt, TDECryptographicCardDevice* cdevice) { - TQCString password; - TQString pin_entry; - - QueryDlg qryDlg(this); - qryDlg.updateLabel(prompt); - qryDlg.setUnlockIcon(); - mForceReject = false; - execDialog(&qryDlg); - if (mForceReject == false) { - pin_entry = qryDlg.getEntry(); - cdevice->setProvidedPin(pin_entry); - } - else { - cdevice->setProvidedPin(TQString::null); - } -} - -TDECryptographicCardDevice* LockProcess::cryptographicCardDevice() { - return m_loginCardDevice; -} - -void LockProcess::fullyOnline() { - if (!mFullyOnlineSent) { - if (kdesktop_pid > 0) { - if (kill(kdesktop_pid, SIGUSR2) < 0) { - // The controlling kdesktop process probably died. Commit suicide... - // Exit uncleanly - exit(1); - } - else { - mFullyOnlineSent = true; - } - } - } -} - -void LockProcess::saverReady() { - DCOPRef ref( "kdesktop", "KScreensaverIface"); - ref.send( "saverLockReady" ); -} - -//=========================================================================== -// -// Control pipe handler -// -ControlPipeHandlerObject::ControlPipeHandlerObject() : TQObject() { - mParent = NULL; - mRunning = false; - mTerminate = false; - mThreadID = 0L; -} - -ControlPipeHandlerObject::~ControlPipeHandlerObject() { - // -} - -void ControlPipeHandlerObject::run(void) { - mThreadID = pthread_self(); - mRunning = true; - - sigset_t new_mask; - sigemptyset(&new_mask); - sigaddset(&new_mask, SIGUSR1); - - // Unblock SIGUSR1 - pthread_sigmask(SIG_UNBLOCK, &new_mask, NULL); - - int display_number = atoi(TQString(XDisplayString(tqt_xdisplay())).replace(":","").ascii()); - - if (display_number < 0) { - printf("[kdesktop_lock] Warning: unable to create control socket. Interactive logon modules may not function properly.\n"); - mRunning = false; - TQApplication::eventLoop()->exit(-1); - return; - } - - char fifo_file[PATH_MAX]; - char fifo_file_out[PATH_MAX]; - snprintf(fifo_file, PATH_MAX, FIFO_FILE, display_number); - snprintf(fifo_file_out, PATH_MAX, FIFO_FILE_OUT, display_number); - - /* Create the FIFOs if they do not exist */ - umask(0); - mkdir(FIFO_DIR,0644); - mknod(fifo_file, S_IFIFO|0644, 0); - chmod(fifo_file, 0644); - - mParent->mPipe_fd = open(fifo_file, O_RDONLY | O_NONBLOCK); - if (mParent->mPipe_fd > -1) { - mParent->mPipeOpen = true; - } - - mknod(fifo_file_out, S_IFIFO|0600, 0); - chmod(fifo_file_out, 0600); - - mParent->mPipe_fd_out = open(fifo_file_out, O_RDWR | O_NONBLOCK); - if (mParent->mPipe_fd_out > -1) { - mParent->mPipeOpen_out = true; - } - - if (!mParent->mPipeOpen) { - printf("[kdesktop_lock] Warning: unable to create control socket '%s'. Interactive logon modules may not function properly.\n", fifo_file); - mRunning = false; - TQApplication::eventLoop()->exit(-1); - return; - } - - int numread; - int retval; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(mParent->mPipe_fd, &rfds); - TQByteArray readbuf(128); - - while (mParent->mPipeOpen && !mTerminate) { - TQString inputcommand = ""; - - // Wait for mParent->mPipe_fd to receive input - retval = select(mParent->mPipe_fd + 1, &rfds, NULL, NULL, NULL); - if (retval < 0) { - // ERROR - } - else if (retval) { - // New data is available - readbuf[0]=' '; - numread = read(mParent->mPipe_fd, readbuf.data(), 128); - readbuf[numread] = 0; - if (numread > 0) { - inputcommand += readbuf; - emit processCommand(inputcommand); - } - } - } - - mRunning = false; - TQApplication::eventLoop()->exit(0); - return; -} - -void ControlPipeHandlerObject::terminateThread() { - if (mRunning) { - mTerminate = true; - pthread_kill(mThreadID, SIGUSR1); - } -} - -#include "lockprocess.moc" diff --git a/kdesktop/lock/lockprocess.cpp b/kdesktop/lock/lockprocess.cpp new file mode 100644 index 000000000..fdde3fc9e --- /dev/null +++ b/kdesktop/lock/lockprocess.cpp @@ -0,0 +1,3045 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 1999 Martin R. Jones +// Copyright (c) 2003 Oswald Buddenhagen +// Copyright (c) 2010 - 2015 Timothy Pearson +// + +//kdesktop keeps running and checks user inactivity +//when it should show screensaver (and maybe lock the session), +//it starts kdesktop_lock, who does all the locking and who +//actually starts the screensaver + +//It's done this way to prevent screen unlocking when kdesktop +//crashes (e.g. because it's set to multiple wallpapers and +//some image will be corrupted). + +#include + +#include "lockprocess.h" +#include "lockdlg.h" +#include "infodlg.h" +#include "querydlg.h" +#include "sakdlg.h" +#include "securedlg.h" +#include "autologout.h" +#include "kdesktopsettings.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#ifdef HAVE_SETPRIORITY +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_DPMS +extern "C" { +#include +#ifndef Bool +#define Bool BOOL +#endif +#include + +#ifndef HAVE_DPMSINFO_PROTO +Status DPMSInfo ( Display *, CARD16 *, BOOL * ); +#endif +} +#endif + +#ifdef HAVE_XF86MISC +#include +#endif + +#ifdef HAVE_GLXCHOOSEVISUAL +#include +#endif + +#define KDESKTOP_DEBUG_ID 1204 + +#define LOCK_GRACE_DEFAULT 5000 +#define AUTOLOGOUT_DEFAULT 600 + +#define DESKTOP_WALLPAPER_OBTAIN_TIMEOUT_MS 3000 + +// Setting this define is INSECURE +// Use it for debugging purposes ONLY +// #define KEEP_MOUSE_UNGRABBED 1 + +// These lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special multimedia keys +#define XF86XK_AudioMute 0x1008FF12 +#define XF86XK_AudioRaiseVolume 0x1008FF13 +#define XF86XK_AudioLowerVolume 0x1008FF11 +#define XF86XK_Display 0x1008FF59 + +// These lines are taken on 08/2013 from X.org (X11/XF86keysym.h), defining some special ACPI power keys +#define XF86XK_PowerOff 0x1008FF2A +#define XF86XK_Sleep 0x1008FF2F +#define XF86XK_Suspend 0x1008FFA7 +#define XF86XK_Hibernate 0x1008FFA8 + +#define DPMS_MONITOR_BLANKED(x) ((x == DPMSModeStandby) || (x == DPMSModeSuspend) || (x == DPMSModeOff)) + +static Window gVRoot = 0; +static Window gVRootData = 0; +static Atom gXA_VROOT; +static Atom gXA_SCREENSAVER_VERSION; + +Atom kde_wm_system_modal_notification = 0; +Atom kde_wm_transparent_to_desktop = 0; +Atom kde_wm_transparent_to_black = 0; + +static void segv_handler(int) +{ + kdError(KDESKTOP_DEBUG_ID) << "A fatal exception was encountered." + << " Trapping and ignoring it so as not to compromise desktop security..." + << kdBacktrace() << endl; + sleep(1); +} + +extern Atom tqt_wm_state; +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_delay_screensaver_start; +extern bool trinity_desktop_lock_use_sak; +extern bool trinity_desktop_lock_hide_active_windows; +extern bool trinity_desktop_lock_hide_cancel_button; +extern bool trinity_desktop_lock_forced; + +extern LockProcess* trinity_desktop_lock_process; + +extern bool argb_visual; +extern pid_t kdesktop_pid; + +extern TQXLibWindowList trinity_desktop_lock_hidden_window_list; + +bool trinity_desktop_lock_autohide_lockdlg = TRUE; + +#define ENABLE_CONTINUOUS_LOCKDLG_DISPLAY \ +if (!mForceContinualLockDisplayTimer->isActive()) mForceContinualLockDisplayTimer->start(100, FALSE); \ +trinity_desktop_lock_autohide_lockdlg = FALSE; \ +mHackDelayStartupTimer->stop(); + +#define DISABLE_CONTINUOUS_LOCKDLG_DISPLAY \ +mForceContinualLockDisplayTimer->stop(); \ +trinity_desktop_lock_autohide_lockdlg = TRUE; \ +mHackDelayStartupTimer->stop(); + +//=========================================================================== +// +// Screen saver handling process. Handles screensaver window, +// starting screensaver hacks, and password entry. +// +LockProcess::LockProcess() + : TQWidget(0L, "saver window", ((WFlags)(WStyle_StaysOnTop|WStyle_Customize|WStyle_NoBorder))), + mOpenGLVisual(0), + mParent(0), + mShowLockDateTime(false), + mSuspended(false), + mVisibility(false), + mRestoreXF86Lock(false), + mForbidden(false), + mAutoLogout(false), + resizeTimer(NULL), + hackResumeTimer(NULL), + mVkbdProcess(NULL), + mKWinModule(NULL), + mPipeOpen(false), + mPipeOpen_out(false), + mInfoMessageDisplayed(false), + mDialogControlLock(false), + mForceReject(false), + currentDialog(NULL), + mEnsureScreenHiddenTimer(NULL), + mForceContinualLockDisplayTimer(NULL), + mEnsureVRootWindowSecurityTimer(NULL), + mHackDelayStartupTimer(NULL), + mHackDelayStartupTimeout(0), + mHackStartupEnabled(true), + mOverrideHackStartupEnabled(false), + mResizingDesktopLock(false), + mFullyOnlineSent(false), + mClosingWindows(false), + mInSecureDialog(false), + mHackActive(false), + m_rootPixmap(NULL), + mBackingStartupDelayTimer(0), + m_startupStatusDialog(NULL), + m_mouseDown(0), + m_mousePrevX(0), + m_mousePrevY(0), + m_dialogPrevX(0), + m_dialogPrevY(0), + m_notifyReadyRequested(false), + m_loginCardDevice(NULL), + m_maskWidget(NULL), + m_saverRootWindow(0) +{ +#ifdef KEEP_MOUSE_UNGRABBED + setNFlags(WX11DisableMove|WX11DisableClose|WX11DisableShade|WX11DisableMinimize|WX11DisableMaximize); +#endif + + setupSignals(); + + // Set up atoms + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + kde_wm_transparent_to_desktop = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENT_TO_DESKTOP", False); + kde_wm_transparent_to_black = XInternAtom(tqt_xdisplay(), "_TDE_TRANSPARENT_TO_BLACK", False); + + kapp->installX11EventFilter(this); + + mForceContinualLockDisplayTimer = new TQTimer( this ); + mHackDelayStartupTimer = new TQTimer( this ); + mEnsureVRootWindowSecurityTimer = new TQTimer( this ); + + if (!argb_visual) { + // Try to get the root pixmap + if (!m_rootPixmap) m_rootPixmap = new KRootPixmap(this); + connect(m_rootPixmap, TQT_SIGNAL(backgroundUpdated(const TQPixmap &)), this, TQT_SLOT(slotPaintBackground(const TQPixmap &))); + m_rootPixmap->setCustomPainting(true); + m_rootPixmap->start(); + } + + // Get root window attributes + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); + { // trigger creation of QToolTipManager, it does XSelectInput() on the root window + TQWidget w; + TQToolTip::add( &w, "foo" ); + } + XSelectInput( tqt_xdisplay(), tqt_xrootwin(), SubstructureNotifyMask | rootAttr.your_event_mask ); + + // Add non-TDE path + TDEGlobal::dirs()->addResourceType("scrsav", + TDEGlobal::dirs()->kde_default("apps") + + "System/ScreenSavers/"); + + // Add KDE specific screensaver path + TQString relPath="System/ScreenSavers/"; + KServiceGroup::Ptr servGroup = KServiceGroup::baseGroup( "screensavers"); + if (servGroup) { + relPath=servGroup->relPath(); + kdDebug(KDESKTOP_DEBUG_ID) << "relPath=" << relPath << endl; + } + TDEGlobal::dirs()->addResourceType("scrsav", + TDEGlobal::dirs()->kde_default("apps") + + relPath); + + // virtual root property + gXA_VROOT = XInternAtom (tqt_xdisplay(), "__SWM_VROOT", False); + gXA_SCREENSAVER_VERSION = XInternAtom (tqt_xdisplay(), "_SCREENSAVER_VERSION", False); + + TQStringList dmopt = TQStringList::split(TQChar(','), + TQString::fromLatin1( ::getenv( "XDM_MANAGED" ))); + for (TQStringList::ConstIterator it = dmopt.begin(); it != dmopt.end(); ++it) { + if ((*it).startsWith("method=")) { + mMethod = (*it).mid(7); + } + } + + // Initialize SmartCard readers + TDEGenericDevice *hwdevice; + TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices(); + TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard); + for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) { + TDECryptographicCardDevice* cdevice = static_cast(hwdevice); + // connect(cdevice, SIGNAL(pinRequested(TQString,TDECryptographicCardDevice*)), this, SLOT(cryptographicCardPinRequested(TQString,TDECryptographicCardDevice*))); + connect(cdevice, TQT_SIGNAL(certificateListAvailable(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*))); + connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*))); + cdevice->enableCardMonitoring(true); + // cdevice->enablePINEntryCallbacks(true); + } + +#ifdef KEEP_MOUSE_UNGRABBED + setEnabled(false); +#endif + + greetPlugin.library = 0; + + TDECrash::setCrashHandler(segv_handler); +} + +//--------------------------------------------------------------------------- +// +// Destructor - usual cleanups. +// +LockProcess::~LockProcess() +{ + mControlPipeHandler->terminateThread(); + mControlPipeHandlerThread->wait(); + delete mControlPipeHandler; +// delete mControlPipeHandlerThread; + + if (resizeTimer != NULL) { + resizeTimer->stop(); + delete resizeTimer; + } + if (hackResumeTimer != NULL) { + hackResumeTimer->stop(); + delete hackResumeTimer; + } + if (mEnsureScreenHiddenTimer != NULL) { + mEnsureScreenHiddenTimer->stop(); + delete mEnsureScreenHiddenTimer; + } + if (mForceContinualLockDisplayTimer != NULL) { + mForceContinualLockDisplayTimer->stop(); + delete mForceContinualLockDisplayTimer; + } + if (mHackDelayStartupTimer != NULL) { + mHackDelayStartupTimer->stop(); + delete mHackDelayStartupTimer; + } + if (mEnsureVRootWindowSecurityTimer != NULL) { + mEnsureVRootWindowSecurityTimer->stop(); + delete mEnsureVRootWindowSecurityTimer; + } + + if (greetPlugin.library) { + if (greetPlugin.info->done) + greetPlugin.info->done(); + greetPlugin.library->unload(); + } + + if (m_rootPixmap) { + m_rootPixmap->stop(); + delete m_rootPixmap; + } + + mPipeOpen = false; + mPipeOpen_out = false; +} + +//--------------------------------------------------------------------------- +// +// Initialization for startup +// This is where instance settings should be set--all objects should have already been created in the constructor above +// +void LockProcess::init(bool child, bool useBlankOnly) +{ + // Get root window size + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); + mRootWidth = rootAttr.width; + mRootHeight = rootAttr.height; + generateBackingImages(); + + // Connect all signals + connect( mForceContinualLockDisplayTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(displayLockDialogIfNeeded()) ); + connect( mHackDelayStartupTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(closeDialogAndStartHack()) ); + connect( mEnsureVRootWindowSecurityTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(repaintRootWindowIfNeeded()) ); + connect(tqApp, TQT_SIGNAL(mouseInteraction(XEvent *)), TQT_SLOT(slotMouseActivity(XEvent *))); + connect(&mHackProc, TQT_SIGNAL(processExited(TDEProcess *)), TQT_SLOT(hackExited(TDEProcess *))); + connect(&mSuspendTimer, TQT_SIGNAL(timeout()), TQT_SLOT(suspend())); + +#ifdef HAVE_DPMS + //if the user decided that the screensaver should run independent from + //dpms, we shouldn't check for it, aleXXX + if (KDesktopSettings::dpmsDependent()) { + BOOL on; + CARD16 state; + if (DPMSInfo(tqt_xdisplay(), &state, &on)) { + if (on) { + connect(&mCheckDPMS, TQT_SIGNAL(timeout()), TQT_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 + +#if (TQT_VERSION-0 >= 0x030200) // XRANDR support + connect( kapp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( desktopResized())); +#endif + + if (!trinity_desktop_lock_use_system_modal_dialogs) { + setWFlags((WFlags)WX11BypassWM); + } + + child_saver = child; + mUseBlankOnly = useBlankOnly; + + mShowLockDateTime = KDesktopSettings::showLockDateTime(); + mlockDateTime = TQDateTime::currentDateTime(); + + mHackDelayStartupTimeout = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::timeout()*1000:10*1000; + mHackStartupEnabled = trinity_desktop_lock_use_system_modal_dialogs?KDesktopSettings::screenSaverEnabled():true; + + configure(); + + mControlPipeHandlerThread = new TQEventLoopThread(); + mControlPipeHandler = new ControlPipeHandlerObject(); + mControlPipeHandler->mParent = this; + mControlPipeHandler->moveToThread(mControlPipeHandlerThread); + TQObject::connect(mControlPipeHandler, SIGNAL(processCommand(TQString)), this, SLOT(processInputPipeCommand(TQString))); + TQTimer::singleShot(0, mControlPipeHandler, SLOT(run())); + mControlPipeHandlerThread->start(); +} + +static int signal_pipe[2]; + +static void sigterm_handler(int) +{ + if ((!trinity_desktop_lock_process) || (!trinity_desktop_lock_process->inSecureDialog())) { + // Exit uncleanly + char tmp = 'U'; + if (::write( signal_pipe[1], &tmp, 1) == -1) { + // Error handler to shut up gcc warnings + } + } +} + +static void sighup_handler(int) +{ + char tmp = 'H'; + if (::write( signal_pipe[1], &tmp, 1) == -1) { + // Error handler to shut up gcc warnings + } +} + +bool LockProcess::closeCurrentWindow() +{ + mClosingWindows = TRUE; + if (currentDialog != NULL) { + mForceReject = true; + if (dynamic_cast(currentDialog)) { + dynamic_cast(currentDialog)->closeDialogForced(); + } + else if (dynamic_cast(currentDialog)) { + dynamic_cast(currentDialog)->closeDialogForced(); + } + else { + currentDialog->close(); + } + } + + if( mDialogs.isEmpty() ) { + mClosingWindows = FALSE; + mForceReject = false; + return false; + } + else { + mClosingWindows = TRUE; + return true; + } +} + +void LockProcess::timerEvent(TQTimerEvent *ev) +{ + if (mAutoLogout && ev->timerId() == mAutoLogoutTimerId) { + killTimer(mAutoLogoutTimerId); + AutoLogout autologout(this); + execDialog(&autologout); + } +} + +void LockProcess::resizeEvent(TQResizeEvent *) +{ + // +} + +void LockProcess::setupSignals() +{ + struct sigaction act; + // ignore SIGINT + act.sa_handler=SIG_IGN; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGINT); + act.sa_flags = 0; + sigaction(SIGINT, &act, 0L); + // ignore SIGQUIT + act.sa_handler=SIG_IGN; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGQUIT); + act.sa_flags = 0; + sigaction(SIGQUIT, &act, 0L); + // exit uncleanly on SIGTERM + act.sa_handler= sigterm_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTERM); + act.sa_flags = 0; + sigaction(SIGTERM, &act, 0L); + // SIGHUP forces lock + act.sa_handler= sighup_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGHUP); + act.sa_flags = 0; + sigaction(SIGHUP, &act, 0L); + + if (pipe(signal_pipe) == -1) { + // Error handler to shut up gcc warnings + } + TQSocketNotifier* notif = new TQSocketNotifier(signal_pipe[0], TQSocketNotifier::Read, TQT_TQOBJECT(this) ); + connect( notif, TQT_SIGNAL(activated(int)), TQT_SLOT(signalPipeSignal())); +} + + +void LockProcess::signalPipeSignal() +{ + char tmp; + if (::read( signal_pipe[0], &tmp, 1) == -1) { + // Error handler to shut up gcc warnings + } + if( tmp == 'T' ) { + quitSaver(); + } + else if( tmp == 'H' ) { + if( !mLocked ) + startLock(); + } + else if( tmp == 'U' ) { + // Exit uncleanly + quitSaver(); + exit(1); + } +} + +//--------------------------------------------------------------------------- +bool LockProcess::lock() +{ +#ifdef USE_SECURING_DESKTOP_NOTIFICATION + m_startupStatusDialog = new KSMModalDialog(this); + m_startupStatusDialog->setStatusMessage(i18n("Securing desktop session").append("...")); + m_startupStatusDialog->show(); + m_startupStatusDialog->setActiveWindow(); + tqApp->processEvents(); +#endif + + if (startSaver(true)) { + // 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; + if (startLock()) { + TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); + return true; + } + stopSaver(); + mBusy = false; + } + return false; +} +//--------------------------------------------------------------------------- +void LockProcess::slotDeadTimePassed() +{ + mBusy = false; +} + +//--------------------------------------------------------------------------- +bool LockProcess::defaultSave() +{ + mLocked = false; + mOverrideHackStartupEnabled = true; + if (startSaver()) { + if (mLockGrace >= 0) { + TQTimer::singleShot(mLockGrace, this, TQT_SLOT(startLock())); + } + return true; + } + mOverrideHackStartupEnabled = false; + return false; +} + +//--------------------------------------------------------------------------- +bool LockProcess::dontLock() +{ + mLocked = false; + return startSaver(); +} + +//--------------------------------------------------------------------------- +void LockProcess::quitSaver() +{ + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(quitSaver()) ); + return; + } + stopSaver(); + kapp->quit(); +} + +//--------------------------------------------------------------------------- +void LockProcess::startSecureDialog() +{ + if ((backingPixmap.isNull()) && (mBackingStartupDelayTimer < 100)) { + TQTimer::singleShot(10, this, TQT_SLOT(startSecureDialog())); + mBackingStartupDelayTimer++; + return; + } + + setGeometry(0, 0, mRootWidth, mRootHeight); + saverReadyIfNeeded(); + + int ret; + SecureDlg inDlg( this ); + inDlg.setRetInt(&ret); + mBusy = true; + execDialog( &inDlg ); + mBusy = false; + bool forcecontdisp = mForceContinualLockDisplayTimer->isActive(); + if (forcecontdisp) { + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + } + mInSecureDialog = false; + if (ret == 0) { + mClosingWindows = 1; + kapp->quit(); + } + if (ret == 1) { + // 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; + trinity_desktop_lock_forced = true; + // Make sure the cursor is not showing busy status + setCursor( tqarrowCursor ); + if (startLock()) + { + if (trinity_desktop_lock_delay_screensaver_start) { + mBusy = false; + } + else { + TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); + } + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + if (mHackStartupEnabled == true) { + startHack(); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + startHack(); + } + } + } + return; + } + stopSaver(); + mBusy = false; + return; + } + if (ret == 2) { + mClosingWindows = 1; + if (system("ksysguard &") == -1) { + // Error handler to shut up gcc warnings + } + kapp->quit(); + } + if (ret == 3) { + mClosingWindows = 1; + DCOPRef("ksmserver","ksmserver").send("logout", (int)TDEApplication::ShutdownConfirmYes, (int)TDEApplication::ShutdownTypeNone, (int)TDEApplication::ShutdownModeInteractive); + kapp->quit(); + } + // FIXME + // Handle remaining case (switch user) + if (forcecontdisp) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + stopSaver(); +} + +bool LockProcess::runSecureDialog() +{ +#ifdef USE_SECURING_DESKTOP_NOTIFICATION + m_startupStatusDialog = new KSMModalDialog(this); + m_startupStatusDialog->setStatusMessage(i18n("Securing desktop session").append("...")); + m_startupStatusDialog->show(); + m_startupStatusDialog->setActiveWindow(); + tqApp->processEvents(); +#endif + + mInSecureDialog = true; + if (startSaver()) { + mBackingStartupDelayTimer = 0; + TQTimer::singleShot(0, this, TQT_SLOT(startSecureDialog())); + return true; + } + else { + mInSecureDialog = false; + return false; + } +} + +bool LockProcess::inSecureDialog() +{ + return mInSecureDialog; +} + +//--------------------------------------------------------------------------- +// +// Read and apply configuration. +// +void LockProcess::configure() +{ + // the configuration is stored in kdesktop's config file + if( KDesktopSettings::lock() ) { + mLockGrace = KDesktopSettings::lockGrace(); + if (mLockGrace < 0) + mLockGrace = 0; + else if (mLockGrace > 300000) + mLockGrace = 300000; // 5 minutes, keep the value sane + } + else + mLockGrace = -1; + + if ( KDesktopSettings::autoLogout() ) { + mAutoLogout = true; + mAutoLogoutTimeout = KDesktopSettings::autoLogoutTimeout(); + mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout * 1000); // in milliseconds + } + + mPriority = KDesktopSettings::priority(); + if (mPriority < 0) mPriority = 0; + if (mPriority > 19) mPriority = 19; + + mSaver = KDesktopSettings::saver(); + if (mSaver.isEmpty() || mUseBlankOnly) { + mSaver = "KBlankscreen.desktop"; + } + if (!trinity_desktop_lock_use_system_modal_dialogs) { + if (KDesktopSettings::screenSaverEnabled() == false) { + mSaver = ""; + mSaverExec = ""; + } + } + + readSaver(); + + mPlugins = KDesktopSettings::pluginsUnlock(); + if (mPlugins.isEmpty()) { + mPlugins = TQStringList("classic"); + } + mPluginOptions = KDesktopSettings::pluginOptions(); +} + +//--------------------------------------------------------------------------- +// +// Read the command line needed to run the screensaver given a .desktop file. +// +void LockProcess::readSaver() +{ + if (!mSaver.isEmpty()) { + TQString file = locate("scrsav", mSaver); + + bool opengl = kapp->authorize("opengl_screensavers"); + bool manipulatescreen = kapp->authorize("manipulatescreen_screensavers"); + KDesktopFile config(file, true); + if (config.readEntry("X-TDE-Type").utf8() != 0) { + TQString saverType = config.readEntry("X-TDE-Type").utf8(); + TQStringList saverTypes = TQStringList::split(";", saverType); + for (uint i = 0; i < saverTypes.count(); i++) { + if ((saverTypes[i] == "ManipulateScreen") && !manipulatescreen) { + kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden" << endl; + mForbidden = true; + } + if ((saverTypes[i] == "OpenGL") && !opengl) { + kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type OpenGL and OpenGL is forbidden" << endl; + mForbidden = true; + } + if (saverTypes[i] == "OpenGL") { + mOpenGLVisual = true; + } + } + } + + kdDebug(KDESKTOP_DEBUG_ID) << "mForbidden: " << (mForbidden ? "true" : "false") << endl; + + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (config.hasActionGroup("InWindow")) { + config.setActionGroup("InWindow"); + mSaverExec = config.readPathEntry("Exec"); + } + } + else { + if (config.hasActionGroup("Root")) { + config.setActionGroup("Root"); + mSaverExec = config.readPathEntry("Exec"); + } + } + } +} + +//--------------------------------------------------------------------------- +// +// Create a window to draw our screen saver on. +// +void LockProcess::createSaverWindow() +{ + Visual* visual = CopyFromParent; + XSetWindowAttributes attrs; + XVisualInfo* info = NULL; + int flags = trinity_desktop_lock_use_system_modal_dialogs?0:CWOverrideRedirect; +#ifdef HAVE_GLXCHOOSEVISUAL + if( mOpenGLVisual ) { + static 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 ) { + int n_glxfb_configs; + GLXFBConfig *fbc = glXChooseFBConfig( x11Display(), x11Screen(), attribs[ i ], &n_glxfb_configs); + if (!fbc) { + n_glxfb_configs = 0; + } + for( int j = 0; j < n_glxfb_configs; j++ ) { + info = glXGetVisualFromFBConfig(x11Display(), fbc[j]); + if( info ) { + if (argb_visual) { + // Xorg can only use GPU compositing for ARGB32 8:8:8:8 visuals + // Ensure the selected visual is 8 bits per RGB + // Selecting a non-8-bit visual will result in stuttering and high + // CPU load, while Xorg tries to composite each frame on the CPU! + if ((info->depth < 32) || (info->bits_per_rgb != 8)) { + XFree( info ); + info = NULL; + continue; + } + } + visual = info->visual; + static Colormap colormap = 0; + if( colormap != 0 ) { + XFreeColormap( x11Display(), colormap ); + } + colormap = XCreateColormap( x11Display(), RootWindow( x11Display(), x11Screen()), visual, AllocNone ); + attrs.colormap = colormap; + flags |= CWColormap; + break; + } + } + if (flags & CWColormap) { + break; + } + } + if ( !info ) { + printf("[WARNING] Unable to locate matching X11 GLX Visual; this OpenGL application may not function correctly!\n"); + } + } +#endif + + attrs.override_redirect = 1; + hide(); + + if (argb_visual) { + // The GL visual selection can return a visual with invalid depth + // Check for this and use a fallback visual if needed + if (info && (info->depth < 32)) { + printf("[WARNING] Unable to locate matching X11 GLX Visual; this OpenGL application may not function correctly!\n"); + XFree( info ); + info = NULL; + flags &= ~CWColormap; + } + + attrs.background_pixel = 0; + attrs.border_pixel = 0; + flags |= CWBackPixel; + flags |= CWBorderPixel; + if (!(flags & CWColormap)) { + if (!info) { + info = new XVisualInfo; + if (!XMatchVisualInfo( x11Display(), x11Screen(), 32, TrueColor, info )) { + printf("[ERROR] Unable to locate matching X11 Visual; this application will not function correctly!\n"); + free(info); + info = NULL; + } + } + if (info) { + visual = info->visual; + attrs.colormap = XCreateColormap( x11Display(), RootWindow( x11Display(), x11Screen()), visual, AllocNone ); + flags |= CWColormap; + } + } + } + if (info) { + XFree( info ); + } + + m_saverRootWindow = XCreateWindow( x11Display(), RootWindow( x11Display(), x11Screen()), x(), y(), width(), height(), 0, x11Depth(), InputOutput, visual, flags, &attrs ); + create( m_saverRootWindow ); + + // Some xscreensaver hacks check for this property + const char *version = "KDE 2.0"; + XChangeProperty (tqt_xdisplay(), winId(), + gXA_SCREENSAVER_VERSION, XA_STRING, 8, PropModeReplace, + (unsigned char *) version, strlen(version)); + + XSetWindowAttributes attr; + attr.event_mask = KeyPressMask | ButtonPressMask | PointerMotionMask | VisibilityChangeMask | ExposureMask; + XChangeWindowAttributes(tqt_xdisplay(), winId(), CWEventMask, &attr); + + // Signal that we want to be transparent to the desktop, not to windows behind us... + XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_desktop, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + + // erase(); + + // set NoBackground so that the saver can capture the current + // screen state if necessary + // this is a security risk and has been deactivated--welcome to the 21st century folks! + // setBackgroundMode(TQWidget::NoBackground); + + setGeometry(0, 0, mRootWidth, mRootHeight); + saverReadyIfNeeded(); + + // HACK + // Hide all tooltips and notification windows + { + Window rootWindow = RootWindow(x11Display(), x11Screen()); + Window parent; + Window* children = NULL; + unsigned int noOfChildren = 0; + XWindowAttributes childAttr; + Window childTransient; + + if (XQueryTree(x11Display(), rootWindow, &rootWindow, &parent, &children, &noOfChildren) && noOfChildren>0 ) { + for (unsigned int i=0; istop(); + stopHack(); + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + mResizingDesktopLock = true; + + backingPixmap = TQPixmap(); + + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Temporarily hide the entire screen with a new override redirect window + if (m_maskWidget) { + m_maskWidget->setGeometry(0, 0, mRootWidth, mRootHeight); + } + else { + m_maskWidget = new TQWidget(0, 0, TQt::WStyle_StaysOnTop | TQt::WX11BypassWM); + m_maskWidget->setGeometry(0, 0, mRootWidth, mRootHeight); + m_maskWidget->setBackgroundColor(TQt::black); + m_maskWidget->erase(); + m_maskWidget->show(); + } + XSync(tqt_xdisplay(), False); + saverReadyIfNeeded(); + + if (mEnsureScreenHiddenTimer) { + mEnsureScreenHiddenTimer->stop(); + } + else { + mEnsureScreenHiddenTimer = new TQTimer( this ); + connect( mEnsureScreenHiddenTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotForcePaintBackground()) ); + } + mEnsureScreenHiddenTimer->start(DESKTOP_WALLPAPER_OBTAIN_TIMEOUT_MS, true); + } + + // Resize the background widget + setGeometry(0, 0, mRootWidth, mRootHeight); + XSync(tqt_xdisplay(), False); + saverReadyIfNeeded(); + + // Black out the background widget to hide ugly resize tiling artifacts + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + setBackgroundColor(black); + } + erase(); + + // This slot needs to be able to execute very rapidly so as to prevent the user's desktop from ever + // being displayed, so we finish the hack restarting/display prettying operations in a separate timed slot + if (resizeTimer == NULL) { + resizeTimer = new TQTimer( this ); + connect( resizeTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(doDesktopResizeFinish()) ); + } + resizeTimer->start( 100, TRUE ); // 100 millisecond single shot timer; should allow display switching operations to finish before hack is started +} + +void LockProcess::doDesktopResizeFinish() +{ + while (mDialogControlLock == true) { + usleep(100000); + } + mDialogControlLock = true; + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(doDesktopResizeFinish()) ); + mDialogControlLock = false; + return; + } + mDialogControlLock = false; + + // Restart the hack as the window size is now different + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + if (mHackStartupEnabled == true) { + startHack(); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + startHack(); + } + } + } + + mResizingDesktopLock = false; + mBusy = false; +} + +//--------------------------------------------------------------------------- +// +// Hide the screensaver window +// +void LockProcess::hideSaverWindow() +{ + hide(); + lower(); + removeVRoot(winId()); + XDeleteProperty(tqt_xdisplay(), winId(), gXA_SCREENSAVER_VERSION); + if ( gVRoot ) { + unsigned long vroot_data[1] = { gVRootData }; + XChangeProperty(tqt_xdisplay(), gVRoot, gXA_VROOT, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)vroot_data, 1); + gVRoot = 0; + } + XSync(tqt_xdisplay(), False); +} + +//--------------------------------------------------------------------------- +static int ignoreXError(Display *, XErrorEvent *) +{ + return 0; +} + +//--------------------------------------------------------------------------- +// +// Save the current virtual root window +// +void LockProcess::saveVRoot() +{ + Window rootReturn, parentReturn, *children; + unsigned int numChildren; + Window root = RootWindowOfScreen(ScreenOfDisplay(tqt_xdisplay(), tqt_xscreen())); + + gVRoot = 0; + gVRootData = 0; + + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(ignoreXError); + + if (XQueryTree(tqt_xdisplay(), 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(tqt_xdisplay(), 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); + } + + unsigned long rw = RootWindowOfScreen(ScreenOfDisplay(tqt_xdisplay(), tqt_xscreen())); + unsigned long vroot_data[1] = { vr }; + + Window rootReturn; + Window parentReturn; + Window *children = NULL; + unsigned int numChildren; + Window top = win; + while (1) { + if (XQueryTree(tqt_xdisplay(), top, &rootReturn, &parentReturn, &children, &numChildren) == 0) { + printf("[WARNING] XQueryTree() failed!\n"); fflush(stdout); + break; + } + if (children) { + XFree((char *)children); + } + if (parentReturn == rw) { + break; + } + else { + top = parentReturn; + } + } + + XChangeProperty(tqt_xdisplay(), top, gXA_VROOT, XA_WINDOW, 32, PropModeReplace, (unsigned char *)vroot_data, 1); +} + +//--------------------------------------------------------------------------- +// +// Remove the virtual root property +// +void LockProcess::removeVRoot(Window win) +{ + XDeleteProperty (tqt_xdisplay(), win, gXA_VROOT); +} + +//--------------------------------------------------------------------------- +// +// Grab the keyboard. Returns true on success +// +bool LockProcess::grabKeyboard() +{ + int rv = XGrabKeyboard( tqt_xdisplay(), TQApplication::desktop()->winId(), + True, GrabModeAsync, GrabModeAsync, CurrentTime ); + + if (rv != GrabSuccess) { + kdWarning(1204) << "LockProcess::grabKeyboard() failed: " << rv << endl; + } + return (rv == GrabSuccess); +} + +#define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ + EnterWindowMask | LeaveWindowMask + +//--------------------------------------------------------------------------- +// +// Grab the mouse. Returns true on success +// +bool LockProcess::grabMouse() +{ + HANDLE cursorHandle; + if (mHackActive) { + cursorHandle = TQCursor(tqblankCursor).handle(); + } + else { + cursorHandle = TQCursor(tqbusyCursor).handle(); + } + int rv = XGrabPointer( tqt_xdisplay(), TQApplication::desktop()->winId(), + True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None, + cursorHandle, CurrentTime ); + + if (rv != GrabSuccess) { + kdWarning(1204) << "LockProcess::grabMouse() failed: " << rv << endl; + } + return (rv == GrabSuccess); +} + +//--------------------------------------------------------------------------- +// +// Grab keyboard and mouse. Returns true on success. +// +bool LockProcess::grabInput() +{ + XSync(tqt_xdisplay(), False); + + if (!grabKeyboard()) { + usleep(100000); + if (!grabKeyboard()) { + return false; + } + } + +#ifndef KEEP_MOUSE_UNGRABBED + if (!grabMouse()) { + usleep(100000); + if (!grabMouse()) { + XUngrabKeyboard(tqt_xdisplay(), CurrentTime); + return false; + } + } +#endif + + lockXF86(); + + return true; +} + +//--------------------------------------------------------------------------- +// +// Release mouse an keyboard grab. +// +void LockProcess::ungrabInput() +{ + XUngrabKeyboard(tqt_xdisplay(), CurrentTime); + XUngrabPointer(tqt_xdisplay(), CurrentTime); + unlockXF86(); +} + +//--------------------------------------------------------------------------- +// +// Generate requisite backing images for ARGB mode +// +void LockProcess::generateBackingImages() +{ + if (argb_visual) { + mArgbTransparentBackgroundPixmap.resize(mRootWidth, mRootHeight); + TQPainter p; + p.begin( &mArgbTransparentBackgroundPixmap ); + p.fillRect( 0, 0, mArgbTransparentBackgroundPixmap.width(), mArgbTransparentBackgroundPixmap.height(), TQBrush(tqRgba(0, 0, 0, 0)) ); + p.end(); + } +} + +//--------------------------------------------------------------------------- +// +// Set a fully transparent ARGB background image. +// +void LockProcess::setTransparentBackgroundARGB() +{ + // eliminate nasty flicker on first show + setBackgroundPixmap( mArgbTransparentBackgroundPixmap ); +} + +void LockProcess::saverReadyIfNeeded() +{ + if (m_notifyReadyRequested) { + // Make sure the desktop is hidden before notifying the desktop that the saver is running + m_notifyReadyRequested = false; + saverReady(); + fullyOnline(); + } +} + +//--------------------------------------------------------------------------- +// +// Start the screen saver. +// +bool LockProcess::startSaver(bool notify_ready) +{ + if (!child_saver && !grabInput()) + { + kdWarning(KDESKTOP_DEBUG_ID) << "LockProcess::startSaver() grabInput() failed!!!!" << endl; + return false; + } + mBusy = false; + + // eliminate nasty flicker on first show + setTransparentBackgroundARGB(); + + saveVRoot(); + + if (mParent) { + TQSocketNotifier *notifier = new TQSocketNotifier(mParent, TQSocketNotifier::Read, TQT_TQOBJECT(this), "notifier"); + connect(notifier, TQT_SIGNAL( activated (int)), TQT_SLOT( quitSaver())); + } + createSaverWindow(); + move(0, 0); + show(); + + raise(); + XSync(tqt_xdisplay(), False); + setVRoot( winId(), winId() ); + + if (!trinity_desktop_lock_hide_active_windows) { + if (m_rootPixmap) m_rootPixmap->stop(); + TQPixmap rootWinSnapShot = TQPixmap::grabWindow(TQApplication::desktop()->winId()); + slotPaintBackground(rootWinSnapShot); + } + + if (((!(trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced)) && (!mInSecureDialog)) && (mHackStartupEnabled || mOverrideHackStartupEnabled)) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + + if (notify_ready) { + m_notifyReadyRequested = false; + saverReady(); + fullyOnline(); + } + } + else { + if (notify_ready) { + m_notifyReadyRequested = true; + } + } + + if (mInSecureDialog == FALSE) { + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + if (mHackStartupEnabled || mOverrideHackStartupEnabled) { + mOverrideHackStartupEnabled = false; + startHack(); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + startHack(); + } + } + } + } + + return true; +} + +//--------------------------------------------------------------------------- +// +// Stop the screen saver. +// +void LockProcess::stopSaver() +{ + kdDebug(KDESKTOP_DEBUG_ID) << "LockProcess: stopping saver" << endl; + mHackProc.kill(SIGCONT); + stopHack(); + mSuspended = false; + hideSaverWindow(); + mVisibility = false; + if (!child_saver) { + if (mLocked) { + DM().setLock( false ); + } + ungrabInput(); + const char *out = "GOAWAY!"; + for (TQValueList::ConstIterator it = child_sockets.begin(); it != child_sockets.end(); ++it) { + if (write(*it, out, sizeof(out)) == -1) { + // Error handler to shut up gcc warnings + } + } + } +} + +// private static +TQVariant LockProcess::getConf(void *ctx, const char *key, const TQVariant &dflt) +{ + LockProcess *that = (LockProcess *)ctx; + TQString fkey = TQString::fromLatin1( key ) + '='; + for (TQStringList::ConstIterator it = that->mPluginOptions.begin(); it != that->mPluginOptions.end(); ++it) { + if ((*it).startsWith( fkey )) { + return (*it).mid( fkey.length() ); + } + } + return dflt; +} + +void LockProcess::cantLock( const TQString &txt) +{ + msgBox( TQMessageBox::Critical, i18n("Will not lock the session, as unlocking would be impossible:\n") + txt ); +} + +#if 0 // placeholders for later +i18n("Cannot start kcheckpass."); +i18n("kcheckpass is unable to operate. Possibly it is not SetUID root."); +#endif + +//--------------------------------------------------------------------------- +// +// Make the screen saver password protected. +// +bool LockProcess::startLock() +{ + for (TQStringList::ConstIterator it = mPlugins.begin(); it != mPlugins.end(); ++it) { + GreeterPluginHandle plugin; + TQString path = KLibLoader::self()->findLibrary( ((*it)[0] == '/' ? *it : "kgreet_" + *it ).latin1() ); + if (path.isEmpty()) { + kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " does not exist" << endl; + continue; + } + if (!(plugin.library = KLibLoader::self()->library( path.latin1() ))) { + kdWarning(KDESKTOP_DEBUG_ID) << "Cannot load GreeterPlugin " << *it << " (" << path << ")" << endl; + continue; + } + if (!plugin.library->hasSymbol( "kgreeterplugin_info" )) { + kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") is no valid greet widget plugin" << endl; + plugin.library->unload(); + continue; + } + plugin.info = (kgreeterplugin_info*)plugin.library->symbol( "kgreeterplugin_info" ); + if (plugin.info->method && !mMethod.isEmpty() && mMethod != plugin.info->method) { + kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") serves " << plugin.info->method << ", not " << mMethod << endl; + plugin.library->unload(); + continue; + } + if (!plugin.info->init( mMethod, getConf, this )) { + kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") refuses to serve " << mMethod << endl; + plugin.library->unload(); + continue; + } + kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded" << endl; + greetPlugin = plugin; + mLocked = true; + DM().setLock( true ); + return true; + } + cantLock( i18n("No appropriate greeter plugin configured.") ); + return false; +} + +//--------------------------------------------------------------------------- +// + +void LockProcess::closeDialogAndStartHack() +{ +#ifdef HAVE_DPMS + if (KDesktopSettings::dpmsDependent()) { + BOOL on; + CARD16 state; + if (DPMSInfo(tqt_xdisplay(), &state, &on)) { + //kdDebug() << "checkDPMSActive " << on << " " << state << endl; + if (DPMS_MONITOR_BLANKED(state)) { + // Make sure saver will attempt to start again after DPMS wakeup + // This is related to Bug 1475 + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + // Should not start saver here, because the DPMS check method below would turn it right back off! + // This is related to Bug 1475 + return; + } + } + } +#endif + + // Close any active dialogs + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + mSuspended = true; + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(closeDialogAndStartHack()) ); + } + else { + resume(true); + } +} + +void LockProcess::repaintRootWindowIfNeeded() +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (!mHackProc.isRunning()) { + if (argb_visual) { + setTransparentBackgroundARGB(); + erase(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + } + } + if (currentDialog == NULL) { + raise(); + } + saverReadyIfNeeded(); + } +} + +bool LockProcess::startHack() +{ + mHackActive = TRUE; + + if ((mEnsureVRootWindowSecurityTimer) && (!mEnsureVRootWindowSecurityTimer->isActive())) { + mEnsureVRootWindowSecurityTimer->start(250, FALSE); + } + + if (currentDialog || (!mDialogs.isEmpty())) { + // no resuming with dialog visible or when not visible + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + saverReadyIfNeeded(); + return false; + } + + setCursor( tqblankCursor ); + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqblankCursor).handle(), CurrentTime); + + if (mSaverExec.isEmpty()) { + return false; + } + + if (mHackProc.isRunning()) { + stopHack(); + } + + mHackProc.clearArguments(); + + TQTextStream ts(&mSaverExec, IO_ReadOnly); + TQString word; + ts >> word; + TQString path = TDEStandardDirs::findExe(word); + + if (!path.isEmpty()) { + mHackProc << path; + + kdDebug(KDESKTOP_DEBUG_ID) << "Starting hack: " << path << endl; + + while (!ts.atEnd()) { + ts >> word; + if (word == "%w") + { + word = word.setNum(winId()); + } + mHackProc << word; + } + + if (!mForbidden) { + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Make sure we have a nice clean display to start with! + if (argb_visual) { + // Signal that we want to be transparent to a black background... + if (m_saverRootWindow) { + XChangeProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); + } + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + saverReadyIfNeeded(); + mSuspended = false; + } + + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqblankCursor).handle(), CurrentTime); + if (mHackProc.start() == true) { +#ifdef HAVE_SETPRIORITY + setpriority(PRIO_PROCESS, mHackProc.pid(), mPriority); +#endif + //bitBlt(this, 0, 0, &mOriginal); + DISABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced) { + // Close any active dialogs + if (closeCurrentWindow()) { + TQTimer::singleShot( 0, this, SLOT(closeCurrentWindow()) ); + } + } + if (m_startupStatusDialog) { m_startupStatusDialog->closeSMDialog(); m_startupStatusDialog=NULL; } + return true; + } + } + else { + // we aren't allowed to start the specified screensaver either because it didn't run for some reason + // according to the kiosk restrictions forbid it + usleep(100); + TQApplication::syncX(); + if (!trinity_desktop_lock_use_system_modal_dialogs) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + } + if (argb_visual) { + setTransparentBackgroundARGB(); + erase(); + } + else { + if (backingPixmap.isNull()) { + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + } + if (trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + saverReadyIfNeeded(); + } + } + + if (m_startupStatusDialog) { + m_startupStatusDialog->closeSMDialog(); + m_startupStatusDialog=NULL; + } + + return false; +} + +//--------------------------------------------------------------------------- +// +void LockProcess::stopHack() +{ + if (mHackProc.isRunning()) { + mHackProc.kill(); + if (!mHackProc.wait(10)) { + mHackProc.kill(SIGKILL); + } + } + setCursor( tqarrowCursor ); + + mHackActive = FALSE; +} + +//--------------------------------------------------------------------------- +// +void LockProcess::hackExited(TDEProcess *) +{ + // Hack exited while we're supposed to be saving the screen. + // Make sure the saver window is black. + mHackActive = FALSE; + usleep(100); + TQApplication::syncX(); + if (!trinity_desktop_lock_use_system_modal_dialogs) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + } + if (argb_visual) { + if (m_saverRootWindow) { + XDeleteProperty(tqt_xdisplay(), m_saverRootWindow, kde_wm_transparent_to_black); + XClearArea(tqt_xdisplay(), m_saverRootWindow, 0, 0, 0, 0, True); + } + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + } + if (!mSuspended) { + if (trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + } + saverReadyIfNeeded(); +} + +void LockProcess::displayLockDialogIfNeeded() +{ + if (m_startupStatusDialog) { + m_startupStatusDialog->closeSMDialog(); + m_startupStatusDialog = NULL; + } + if (!mInSecureDialog) { + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (!mBusy) { + mBusy = true; + if (mLocked) { + if (checkPass()) { + mClosingWindows = true; + stopSaver(); + kapp->quit(); + } + } + mBusy = false; + } + } + } +} + +void LockProcess::suspend() +{ + if (!mSuspended) { + if (trinity_desktop_lock_use_system_modal_dialogs) { + mSuspended = true; + stopHack(); + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) { + mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + } + else { + TQString hackStatus; + mHackProc.kill(SIGSTOP); + mSuspended = true; +#if 0 + // wait for the stop signal to take effect + while (hackStatus != "T") { + char hackstat[8192]; + FILE *fp = fopen(TQString("/proc/%1/stat").arg(mHackProc.pid()).ascii(),"r"); + if (fp != NULL) { + fgets (hackstat, 8192, fp); + fclose (fp); + } + hackstat[8191] = 0; + hackStatus = hackstat; + hackStatus = hackStatus.remove(TQRegExp("(*) ", TRUE, TRUE)); + TQStringList hackStatusList = TQStringList::split(" ", hackStatus); + hackStatus = (*(hackStatusList.at(1))); + } +#endif + TQApplication::syncX(); + usleep(100000); // Allow certain bad graphics drivers (*cough* fglrx *cough*) time to actually sync up the display + } + TQApplication::syncX(); + mSavedScreen = TQPixmap::grabWindow( winId()); + } +} + +void LockProcess::resume( bool force ) +{ + if (trinity_desktop_lock_use_sak && (mHackDelayStartupTimer->isActive() || !mHackStartupEnabled)) { + return; + } + if( !force && (!mDialogs.isEmpty() || !mVisibility )) { + // no resuming with dialog visible or when not visible + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (argb_visual) { + setTransparentBackgroundARGB(); + } + else { + if (backingPixmap.isNull()) { + setBackgroundColor(black); + } + else { + setBackgroundPixmap(backingPixmap); + } + } + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + setGeometry(0, 0, mRootWidth, mRootHeight); + } + saverReadyIfNeeded(); + return; + } + if ((mSuspended) && (mHackProc.isRunning())) { + XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset ); + bitBlt( this, 0, 0, &mSavedScreen ); + TQApplication::syncX(); + mHackProc.kill(SIGCONT); + mSuspended = false; + } + else if (mSuspended && trinity_desktop_lock_use_system_modal_dialogs) { + startHack(); + } +} + +//--------------------------------------------------------------------------- +// +// Show the password dialog +// This is called only in the master process +// +bool LockProcess::checkPass() +{ + if (!mDialogs.isEmpty()) { + // Another dialog is already shown + // Abort! + return 0; + } + if (mInfoMessageDisplayed == false) { + if (mAutoLogout) { + killTimer(mAutoLogoutTimerId); + } + + // Make sure we never launch the SAK or login dialog if windows are being closed down + // Otherwise we can get stuck in an irrecoverable state where any attempt to show the login screen is instantly aborted + if (mClosingWindows) { + return 0; + } + + if (trinity_desktop_lock_use_sak) { + // Verify SAK operational status + TDEProcess* checkSAKProcess = new TDEProcess; + *checkSAKProcess << "tdmtsak" << "check"; + checkSAKProcess->start(TDEProcess::Block, TDEProcess::NoCommunication); + int retcode = checkSAKProcess->exitStatus(); + delete checkSAKProcess; + if (retcode != 0) { + trinity_desktop_lock_use_sak = false; + } + } + + if (trinity_desktop_lock_use_sak) { + // Wait for SAK press before continuing... + SAKDlg inDlg( this ); + execDialog( &inDlg ); + if (mClosingWindows) { + return 0; + } + } + + showVkbd(); + PasswordDlg passDlg( this, &greetPlugin, (mShowLockDateTime)?mlockDateTime:TQDateTime()); + int ret = execDialog( &passDlg ); + hideVkbd(); + + if (mForceReject == true) { + ret = TQDialog::Rejected; + } + mForceReject = false; + + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), + tqt_xscreen()), &rootAttr); + if(( rootAttr.your_event_mask & SubstructureNotifyMask ) == 0 ) { + kdWarning() << "ERROR: Something removed SubstructureNotifyMask from the root window!!!" << endl; + XSelectInput( tqt_xdisplay(), tqt_xrootwin(), + SubstructureNotifyMask | rootAttr.your_event_mask ); + } + + return ret == TQDialog::Accepted; + } + else { + return 0; + } +} + +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 = tqt_xdisplay(); + ev.xfocus.type = FocusIn; + ev.xfocus.window = window; + ev.xfocus.mode = NotifyNormal; + ev.xfocus.detail = NotifyAncestor; + XSendEvent( tqt_xdisplay(), window, False, NoEventMask, &ev ); +} + +void LockProcess::resumeUnforced() +{ + resume( false ); +} + +int LockProcess::execDialog( TQDialog *dlg ) +{ + currentDialog=dlg; + dlg->adjustSize(); + + TQRect rect = dlg->geometry(); + rect.moveCenter(TDEGlobalSettings::desktopGeometry(TQCursor::pos()).center()); + dlg->move( rect.topLeft() ); + + if (mDialogs.isEmpty()) { + suspend(); + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqarrowCursor).handle(), CurrentTime); + } + mDialogs.prepend( dlg ); + fakeFocusIn( dlg->winId()); + if (trinity_desktop_lock_use_system_modal_dialogs) { + if (backingPixmap.isNull()) { + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } + else { + bitBlt(this, 0, 0, &backingPixmap); + } + saverReadyIfNeeded(); + } + // dlg->exec may generate BadMatch errors, so make sure they are silently ignored + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(ignoreXError); + int rt = dlg->exec(); + XSetErrorHandler(oldHandler); + while (mDialogControlLock == true) { + usleep(100000); + } + currentDialog = NULL; + mDialogs.remove( dlg ); + if( mDialogs.isEmpty() ) { + HANDLE cursorHandle; + if (mHackActive) { + cursorHandle = TQCursor(tqblankCursor).handle(); + } + else { + cursorHandle = TQCursor(tqbusyCursor).handle(); + } + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, cursorHandle, CurrentTime); + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Slight delay before screensaver resume to allow the dialog window to fully disappear + if (hackResumeTimer == NULL) { + hackResumeTimer = new TQTimer( this ); + connect( hackResumeTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(resumeUnforced()) ); + } + if (mResizingDesktopLock == false) { + hackResumeTimer->start( 10, TRUE ); + } + } + else { + resume( false ); + } + } + else { + fakeFocusIn( mDialogs.first()->winId()); + currentDialog = dynamic_cast(mDialogs.first()); + } + return rt; +} + +void LockProcess::slotForcePaintBackground() +{ + TQPixmap blankPixmap(mRootWidth, mRootHeight); + blankPixmap.fill(Qt::black); + slotPaintBackground(blankPixmap); + printf("[WARNING] Unable to obtain desktop wallpaper in a timely manner. High system load or possibly a TDE bug!\n"); fflush(stdout); +} + +void LockProcess::slotPaintBackground(const TQPixmap &rpm) +{ + if (argb_visual) { + if (mEnsureScreenHiddenTimer) { + mEnsureScreenHiddenTimer->stop(); + } + return; + } + + if (mEnsureScreenHiddenTimer) { + mEnsureScreenHiddenTimer->stop(); + } + else { + mEnsureScreenHiddenTimer = new TQTimer( this ); + connect( mEnsureScreenHiddenTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotForcePaintBackground()) ); + } + + // Only remove the mask widget once the resize is 100% complete! + if (m_maskWidget) { + delete m_maskWidget; + m_maskWidget = NULL; + XSync(tqt_xdisplay(), False); + } + + TQPixmap pm = rpm; + + if (TQPaintDevice::x11AppDepth() == 32) { + // Remove the alpha components from the image + TQImage correctedImage = pm.convertToImage(); + correctedImage = correctedImage.convertDepth(32); + correctedImage.setAlphaBuffer(true); + int w = correctedImage.width(); + int h = correctedImage.height(); + for (int y = 0; y < h; ++y) { + TQRgb *ls = (TQRgb *)correctedImage.scanLine( y ); + for (int x = 0; x < w; ++x) { + TQRgb l = ls[x]; + int r = int( tqRed( l ) ); + int g = int( tqGreen( l ) ); + int b = int( tqBlue( l ) ); + int a = int( 255 ); + ls[x] = tqRgba( r, g, b, a ); + } + } + pm.convertFromImage(correctedImage); + } + + backingPixmap = pm; + if ((trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced) || (!mHackStartupEnabled)) { + setBackgroundPixmap(backingPixmap); + setGeometry(0, 0, mRootWidth, mRootHeight); + erase(); + } +} + +void LockProcess::preparePopup() +{ + TQWidget *dlg = (TQWidget *)sender(); + mDialogs.prepend( dlg ); + fakeFocusIn( dlg->winId() ); +} + +void LockProcess::cleanupPopup() +{ + TQWidget *dlg = (TQWidget *)sender(); + mDialogs.remove( dlg ); + if ( mDialogs.isEmpty() ) { + fakeFocusIn( mDialogs.first()->winId() ); + } +} + +void LockProcess::doFunctionKeyBroadcast() { + // Provide a clean, pretty display switch by hiding the password dialog here + // This does NOT work with the SAK or system modal dialogs! + if ((!trinity_desktop_lock_use_system_modal_dialogs) && (!trinity_desktop_lock_use_sak)) { + mBusy=true; + TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); + if (mkeyCode == XKeysymToKeycode(tqt_xdisplay(), XF86XK_Display)) { + while (mDialogControlLock == true) { + usleep(100000); + } + mDialogControlLock = true; + currentDialog->close(); // DO NOT use closeCurrentWindow() here! + mDialogControlLock = false; + } + } + + DCOPRef ref( "*", "MainApplication-Interface"); + ref.send("sendFakeKey", DCOPArg(mkeyCode , "unsigned int")); +} + +//--------------------------------------------------------------------------- +// +// X11 Event. +// +bool LockProcess::x11Event(XEvent *event) +{ + // Allow certain very specific keypresses through + // Key: Reason: + // XF86Display You need to be able to see the screen when unlocking your computer + // XF86AudioMute Would be nice to be able to shut your computer up in an emergency while it is locked + // XF86AudioRaiseVolume Ditto + // XF86AudioLowerVolume Ditto + // XF86XK_PowerOff If someone has access to the power button, they can hard power off the machine anyway + // XF86XK_Sleep Ditto + // XF86XK_Suspend Ditto + // XF86XK_Hibernate Ditto + + //if ((event->type == KeyPress) || (event->type == KeyRelease)) { + if (event->type == KeyPress) { + // Multimedia keys + if ((event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Display)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioMute)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioRaiseVolume)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_AudioLowerVolume))) { + mkeyCode = event->xkey.keycode; + TQTimer::singleShot( 100, this, TQT_SLOT(doFunctionKeyBroadcast()) ); + return true; + } + // ACPI power keys + if ((event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_PowerOff)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Sleep)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Suspend)) || \ + (event->xkey.keycode == XKeysymToKeycode(event->xkey.display, XF86XK_Hibernate))) { + mkeyCode = event->xkey.keycode; + TQTimer::singleShot( 100, this, TQT_SLOT(doFunctionKeyBroadcast()) ); + return true; + } + } + + switch (event->type) + { + case ButtonPress: + case MotionNotify: + case ButtonRelease: + if( forwardVkbdEvent( event )) { + return true; // filter out + } + // fall through + case KeyPress: + if ((mHackDelayStartupTimer) && (mHackDelayStartupTimer->isActive())) { + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + if (mBusy || !mDialogs.isEmpty()) { + break; + } + mBusy = true; + if (trinity_desktop_lock_delay_screensaver_start) { + if (mLocked) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) { + mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + } + if ((!mLocked) && (!mInSecureDialog)) { + stopSaver(); + kapp->quit(); + } + if (mAutoLogout) { + // we need to restart the auto logout countdown + killTimer(mAutoLogoutTimerId); + mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout); + } + } + else { + if (!mLocked || checkPass()) { + mClosingWindows = true; + stopSaver(); + kapp->quit(); + } + else if (mAutoLogout) { + // we need to restart the auto logout countdown + killTimer(mAutoLogoutTimerId); + mAutoLogoutTimerId = startTimer(mAutoLogoutTimeout); + } + } + mBusy = false; + return true; + + case VisibilityNotify: + if( event->xvisibility.window == winId()) { + // mVisibility == false means the screensaver is not visible at all + // e.g. when switched to text console + mVisibility = !(event->xvisibility.state == VisibilityFullyObscured); + if(!mVisibility) { + mSuspendTimer.start(2000, true); + } + else { + mSuspendTimer.stop(); + if (mResizingDesktopLock == false) { + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { + // Do nothing + } + else { + if (mHackStartupEnabled == true) { + resume( false ); + } + else { + if (trinity_desktop_lock_use_system_modal_dialogs == true) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + resume( false ); + } + } + } + } + } + if (event->xvisibility.state != VisibilityUnobscured) { + stayOnTop(); + } + } + break; + + case ConfigureNotify: // from SubstructureNotifyMask on the root window + if(event->xconfigure.event == tqt_xrootwin()) { + stayOnTop(); + } + for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); + it != mVkbdWindows.end(); + ++it ) { + if( (*it).id == event->xconfigure.window ) { + (*it).rect = TQRect( event->xconfigure.x, event->xconfigure.y, + event->xconfigure.width, event->xconfigure.height ); + break; + } + } + break; + case MapNotify: // from SubstructureNotifyMask on the root window + windowAdded( event->xmap.window, false ); + if( event->xmap.event == tqt_xrootwin()) { + stayOnTop(); + } + break; + case DestroyNotify: + for( TQValueList< VkbdWindow >::Iterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) { + if( (*it).id == event->xdestroywindow.window ) { + mVkbdWindows.remove( it ); + break; + } + } + 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() && ( event->type == KeyPress || event->type == KeyRelease) + && event->xkey.window != mDialogs.first()->winId()) { + XEvent ev2 = *event; + ev2.xkey.window = ev2.xkey.subwindow = mDialogs.first()->winId(); + tqApp->x11ProcessEvent( &ev2 ); + return true; + } + + return false; +} + +void LockProcess::stayOnTop() +{ + if(!mDialogs.isEmpty() || !mVkbdWindows.isEmpty()) { + // 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 + if( !mVkbdWindows.isEmpty()) { + XRaiseWindow( tqt_xdisplay(), mVkbdWindows.first().id ); + } + else { + XRaiseWindow( tqt_xdisplay(), mDialogs.first()->winId()); // raise topmost + } + // and stack others below it + Window* stack = new Window[ mDialogs.count() + mVkbdWindows.count() + 1 ]; + int count = 0; + for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) { + stack[ count++ ] = (*it).id; + } + for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); it != mDialogs.end(); ++it ) { + stack[ count++ ] = (*it)->winId(); + } + stack[ count++ ] = winId(); + XRestackWindows( x11Display(), stack, count ); + delete[] stack; + } + else { + XRaiseWindow(tqt_xdisplay(), winId()); + } +} + +void LockProcess::checkDPMSActive() +{ +#ifdef HAVE_DPMS + if (KDesktopSettings::dpmsDependent()) { + BOOL on; + CARD16 state; + if (DPMSInfo(tqt_xdisplay(), &state, &on)) { + //kdDebug() << "checkDPMSActive " << on << " " << state << endl; + if (DPMS_MONITOR_BLANKED(state)) { + suspend(); + } + else if (mSuspended) { + if (mResizingDesktopLock == false) { + resume( true ); + } + } + } + } +#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 kdesktop_lock 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; + if( XF86MiscQueryVersion( tqt_xdisplay(), &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( tqt_xdisplay(), False ) != MiscExtGrabStateSuccess ) { + return; + } + // success + mRestoreXF86Lock = true; +} + +void LockProcess::unlockXF86() +{ + if( can_do_xf86_lock != Yes ) { + return; + } + if( !mRestoreXF86Lock ) { + return; + } + XF86MiscSetGrabKeysState( tqt_xdisplay(), True ); + mRestoreXF86Lock = false; +} +#else +void LockProcess::lockXF86() +{ + // +} + +void LockProcess::unlockXF86() +{ + // +} +#endif + +void LockProcess::msgBox( TQMessageBox::Icon type, const TQString &txt ) +{ + TQDialog box( 0, "messagebox", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM)) ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + XChangeProperty(tqt_xdisplay(), box.winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + box.setCaption(i18n("Authentication Subsystem Notice")); + TQFrame *winFrame = new TQFrame( &box ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + winFrame->setFrameStyle( TQFrame::NoFrame ); + } + else { + winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); + } + winFrame->setLineWidth( 2 ); + TQLabel *label1 = new TQLabel( winFrame ); + label1->setPixmap( TQMessageBox::standardIcon( type ) ); + TQLabel *label2 = new TQLabel( txt, winFrame ); + KPushButton *button = new KPushButton( KStdGuiItem::ok(), winFrame ); + button->setDefault( true ); + button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) ); + connect( button, TQT_SIGNAL( clicked() ), &box, TQT_SLOT( accept() ) ); + + TQVBoxLayout *vbox = new TQVBoxLayout( &box ); + vbox->addWidget( winFrame ); + TQGridLayout *grid = new TQGridLayout( winFrame, 2, 2, 10 ); + grid->addWidget( label1, 0, 0, Qt::AlignCenter ); + grid->addWidget( label2, 0, 1, Qt::AlignCenter ); + grid->addMultiCellWidget( button, 1,1, 0,1, Qt::AlignCenter ); + + execDialog( &box ); +} + +static int run_vkbd = -1; +void LockProcess::showVkbd() +{ + if( run_vkbd == - 1 ) { +#ifdef WITH_HAL + int status = system( "hal-find-by-property --key system.formfactor.subtype --string tabletpc" ); +// status = 0; // enable for testing + run_vkbd = ( WIFEXITED( status ) && WEXITSTATUS( status ) == 0 && !TDEStandardDirs::findExe( "xvkbd" ).isEmpty()) ? 1 : 0; +#else // WITH_HAL + run_vkbd = (!TDEStandardDirs::findExe( "xvkbd" ).isEmpty()); +#endif // WITH_HAL + } + if( run_vkbd ) { + mVkbdWindows.clear(); + mVkbdLastEventWindow = None; + mKWinModule = new KWinModule( NULL, KWinModule::INFO_WINDOWS ); + connect( mKWinModule, TQT_SIGNAL( windowAdded( WId )), TQT_SLOT( windowAdded( WId ))); + mVkbdProcess = new TDEProcess; + *mVkbdProcess << "xvkbd" << "-compact" << "-geometry" << "-0-0" << "-xdm"; + mVkbdProcess->start(); + } +} + +void LockProcess::hideVkbd() +{ + if( mVkbdProcess != NULL ) { + mVkbdProcess->kill(); + delete mVkbdProcess; + mVkbdProcess = NULL; + delete mKWinModule; + mKWinModule = NULL; + mVkbdWindows.clear(); + } +} + +void LockProcess::windowAdded( WId w ) +{ + windowAdded( w, true ); +} + +void LockProcess::windowAdded( WId w, bool managed ) +{ + // KWin::windowInfo may generate BadWindow errors, so make sure they are silently ignored + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(ignoreXError); + KWin::WindowInfo info = KWin::windowInfo( w, 0, NET::WM2WindowClass ); + XSetErrorHandler(oldHandler); + + if( info.windowClassClass().lower() != "xvkbd" ) { + return; + } + // Unmanaged windows (i.e. popups) don't currently work anyway, since they + // don't have WM_CLASS set anyway. I could perhaps try tricks with X id + // ranges if really needed. + if( managed ) { + // withdraw the window, wait for it to be withdrawn, reparent it directly + // to root at the right position + XWithdrawWindow( tqt_xdisplay(), w, tqt_xscreen()); + for(;;) { + Atom type; + int format; + unsigned long length, after; + unsigned char *data; + int r = XGetWindowProperty( tqt_xdisplay(), w, tqt_wm_state, 0, 2, + false, AnyPropertyType, &type, &format, + &length, &after, &data ); + bool withdrawn = true; + if ( r == Success && data && format == 32 ) { + TQ_UINT32 *wstate = (TQ_UINT32*)data; + withdrawn = (*wstate == WithdrawnState ); + XFree( (char *)data ); + } + if( withdrawn ) { + break; + } + } + } + XSelectInput( tqt_xdisplay(), w, StructureNotifyMask ); + XWindowAttributes attr_geom; + if( !XGetWindowAttributes( tqt_xdisplay(), w, &attr_geom )) { + return; + } + int x = XDisplayWidth( tqt_xdisplay(), tqt_xscreen()) - attr_geom.width; + int y = XDisplayHeight( tqt_xdisplay(), tqt_xscreen()) - attr_geom.height; + if( managed ) { + XSetWindowAttributes attr; + if (!trinity_desktop_lock_use_system_modal_dialogs) { + attr.override_redirect = True; + XChangeWindowAttributes( tqt_xdisplay(), w, CWOverrideRedirect, &attr ); + } + XReparentWindow( tqt_xdisplay(), w, tqt_xrootwin(), x, y ); + XMapWindow( tqt_xdisplay(), w ); + } + VkbdWindow data; + data.id = w; + data.rect = TQRect( x, y, attr_geom.width, attr_geom.height ); + mVkbdWindows.prepend( data ); +} + +bool LockProcess::forwardVkbdEvent( XEvent* event ) +{ + if( mVkbdProcess == NULL ) { + return false; + } + TQPoint pos; + Time time; + switch( event->type ) + { + case ButtonPress: + case ButtonRelease: + pos = TQPoint( event->xbutton.x, event->xbutton.y ); + time = event->xbutton.time; + break; + case MotionNotify: + pos = TQPoint( event->xmotion.x, event->xmotion.y ); + time = event->xmotion.time; + break; + default: + return false; + } + // vkbd windows are kept topmost, so just find the first one in the position + for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) { + if( TQT_TQRECT_OBJECT((*it).rect).contains( pos )) { + // Find the subwindow where the event should actually go. + // Not exactly cheap in the number of X roundtrips but oh well. + Window window = (*it).id; + Window root, child; + int root_x, root_y, x, y; + unsigned int mask; + for(;;) { + if( !XQueryPointer( tqt_xdisplay(), window, &root, &child, &root_x, &root_y, &x, &y, &mask )) { + return false; + } + if( child == None ) { + break; + } + window = child; + } + switch( event->type ) + { + case ButtonPress: + case ButtonRelease: + event->xbutton.x = x; + event->xbutton.y = y; + event->xbutton.subwindow = None; + break; + case MotionNotify: + event->xmotion.x = x; + event->xmotion.y = y; + event->xmotion.subwindow = None; + break; + } + event->xany.window = window; + sendVkbdFocusInOut( window, time ); + XSendEvent( tqt_xdisplay(), window, False, 0, event ); + return true; + } + } + sendVkbdFocusInOut( None, time ); + return false; +} + +// Fake EnterNotify/LeaveNotify events as the mouse moves. They're not sent by X +// because of the grab and having them makes xvkbd highlight the buttons (but +// not needed otherwise it seems). +void LockProcess::sendVkbdFocusInOut( WId window, Time t ) +{ + if( mVkbdLastEventWindow == window ) { + return; + } + if( mVkbdLastEventWindow != None ) { + XEvent e; + e.xcrossing.type = LeaveNotify; + e.xcrossing.display = tqt_xdisplay(); + e.xcrossing.window = mVkbdLastEventWindow; + e.xcrossing.root = tqt_xrootwin(); + e.xcrossing.subwindow = None; + e.xcrossing.time = t; + e.xcrossing.x = 0; + e.xcrossing.y = 0; + e.xcrossing.x_root = -1; + e.xcrossing.y_root = -1; + e.xcrossing.mode = NotifyNormal; + e.xcrossing.detail = NotifyAncestor; + e.xcrossing.same_screen = True; + e.xcrossing.focus = False; + e.xcrossing.state = 0; + XSendEvent( tqt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); + } + mVkbdLastEventWindow = window; + if( mVkbdLastEventWindow != None ) { + XEvent e; + e.xcrossing.type = EnterNotify; + e.xcrossing.display = tqt_xdisplay(); + e.xcrossing.window = mVkbdLastEventWindow; + e.xcrossing.root = tqt_xrootwin(); + e.xcrossing.subwindow = None; + e.xcrossing.time = t; + e.xcrossing.x = 0; + e.xcrossing.y = 0; + e.xcrossing.x_root = 0; + e.xcrossing.y_root = 0; + e.xcrossing.mode = NotifyNormal; + e.xcrossing.detail = NotifyAncestor; + e.xcrossing.same_screen = True; + e.xcrossing.focus = False; + e.xcrossing.state = 0; + XSendEvent( tqt_xdisplay(), mVkbdLastEventWindow, False, 0, &e ); + } +} + +void LockProcess::slotMouseActivity(XEvent *event) +{ + bool inFrame = 0; + bool inDialog = 0; + XButtonEvent *be = (XButtonEvent *) event; + XMotionEvent *me = (XMotionEvent *) event; + if ((event->type == ButtonPress) && (!mDialogs.isEmpty())) { + // Get geometry including window frame/titlebar + TQRect fgeom = mDialogs.first()->frameGeometry(); + TQRect wgeom = mDialogs.first()->geometry(); + + if (((be->x_root > fgeom.x()) && (be->y_root > fgeom.y())) && ((be->x_root < (fgeom.x()+fgeom.width())) && (be->y_root < (fgeom.y()+fgeom.height())))) { + inFrame = 1; + } + if (((be->x_root > wgeom.x()) && (be->y_root > wgeom.y())) && ((be->x_root < (wgeom.x()+wgeom.width())) && (be->y_root < (wgeom.y()+wgeom.height())))) { + inDialog = 1; + } + + // Clicked inside dialog; set focus + if (inFrame == TRUE) { + WId window = mDialogs.first()->winId(); + XSetInputFocus(tqt_xdisplay(), window, RevertToParent, CurrentTime); + fakeFocusIn(window); + // Why this needs to be repeated I have no idea... + XSetInputFocus(tqt_xdisplay(), window, RevertToParent, CurrentTime); + fakeFocusIn(window); + } + + // Clicked inside window handle (or border); drag window + if ((inFrame == TRUE) && (inDialog == FALSE)) { + TQPoint oldPoint = mDialogs.first()->pos(); + m_mouseDown = 1; + m_dialogPrevX = oldPoint.x(); + m_dialogPrevY = oldPoint.y(); + m_mousePrevX = be->x_root; + m_mousePrevY = be->y_root; + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqsizeAllCursor).handle(), CurrentTime); + } + } + + // Drag the window... + if (event->type == MotionNotify) { + if (m_mouseDown == TRUE) { + int deltaX = me->x_root - m_mousePrevX; + int deltaY = me->y_root - m_mousePrevY; + m_dialogPrevX = m_dialogPrevX + deltaX; + m_dialogPrevY = m_dialogPrevY + deltaY; + if (!mDialogs.isEmpty()) mDialogs.first()->move(m_dialogPrevX, m_dialogPrevY); + + m_mousePrevX = me->x_root; + m_mousePrevY = me->y_root; + } + } + + if (event->type == ButtonRelease) { + m_mouseDown = 0; + XChangeActivePointerGrab( tqt_xdisplay(), GRABEVENTS, TQCursor(tqarrowCursor).handle(), CurrentTime); + } +} + +void LockProcess::processInputPipeCommand(TQString inputcommand) { + TQCString command(inputcommand.ascii()); + TQString to_display; + TQString pin_entry; + + if (command[0] == 'C') { + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + mClosingWindows = false; + mInfoMessageDisplayed = false; + mDialogControlLock = false; + } + if (command[0] == 'T') { + to_display = command.data(); + to_display = to_display.remove(0,1); + // Lock out password dialogs and close any active dialog + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + mInfoMessageDisplayed = true; + mDialogControlLock = false; + // Display info message dialog + InfoDlg inDlg( this ); + inDlg.updateLabel(to_display); + inDlg.setUnlockIcon(); + execDialog( &inDlg ); + mForceReject = false; + mClosingWindows = false; + return; + } + if ((command[0] == 'E') || (command[0] == 'W') || (command[0] == 'I') || (command[0] == 'K')) { + to_display = command.data(); + to_display = to_display.remove(0,1); + // Lock out password dialogs and close any active dialog + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + mInfoMessageDisplayed = true; + mDialogControlLock = false; + // Display info message dialog + InfoDlg inDlg( this ); + inDlg.updateLabel(to_display); + if (command[0] == 'K') inDlg.setKDEIcon(); + if (command[0] == 'I') inDlg.setInfoIcon(); + if (command[0] == 'W') inDlg.setWarningIcon(); + if (command[0] == 'E') inDlg.setErrorIcon(); + execDialog( &inDlg ); + mForceReject = false; + mClosingWindows = false; + return; + } + if (command[0] == 'Q') { + to_display = command.data(); + to_display = to_display.remove(0,1); + // Lock out password dialogs and close any active dialog + while (mDialogControlLock == true) usleep(100000); + mDialogControlLock = true; + if (mInfoMessageDisplayed || !trinity_desktop_lock_use_system_modal_dialogs) { + if (currentDialog != NULL) { + mForceReject = true; + closeCurrentWindow(); + } + } + mInfoMessageDisplayed = true; + mDialogControlLock = false; + // Display query dialog + QueryDlg qryDlg( this ); + qryDlg.updateLabel(to_display); + qryDlg.setUnlockIcon(); + mForceReject = false; + execDialog( &qryDlg ); + if (mForceReject == false) { + pin_entry = qryDlg.getEntry(); + mInfoMessageDisplayed=false; + if (mPipeOpen_out == true) { + TQCString pin_entry_local8 = pin_entry.local8Bit(); // local 8 bit length may differ from TQString length + if (write(mPipe_fd_out, pin_entry_local8.data(), pin_entry_local8.length()+1) == -1) { + // Error handler to shut up gcc warnings + } + if (write(mPipe_fd_out, "\n\r", 3) == -1) { + // Error handler to shut up gcc warnings + } + } + } + mForceReject = false; + mClosingWindows = false; + return; + } +} + +void LockProcess::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) { + TQString login_name = TQString::null; + X509CertificatePtrList certList = cdevice->cardX509Certificates(); + if (certList.count() > 0) { + KSSLCertificate* card_cert = NULL; + card_cert = KSSLCertificate::fromX509(certList[0]); + TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false); + for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) { + TQString lcpart = (*it).lower(); + if (lcpart.startsWith("cn=")) { + login_name = lcpart.right(lcpart.length() - strlen("cn=")); + } + } + delete card_cert; + } + + if (login_name != "") { + KUser user; + if (login_name == user.loginName()) { + // Pass login to the PAM stack... + m_loginCardDevice = cdevice; + if (dynamic_cast(currentDialog)) { + dynamic_cast(currentDialog)->closeDialogForced(); + TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin())); + } + else if (dynamic_cast(currentDialog)) { + dynamic_cast(currentDialog)->closeDialogForced(); + TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin())); + } + else if (dynamic_cast(currentDialog)) { + signalPassDlgToAttemptCardLogin(); + } + } + } +} + +void LockProcess::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) { + PasswordDlg* passDlg = dynamic_cast(currentDialog); + if (passDlg) { + passDlg->resetCardLogin(); + } + else { + m_loginCardDevice = NULL; + TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort())); + } +} + +void LockProcess::signalPassDlgToAttemptCardLogin() { + PasswordDlg* passDlg = dynamic_cast(currentDialog); + if (passDlg && m_loginCardDevice) { + passDlg->attemptCardLogin(); + } + else { + if (currentDialog && m_loginCardDevice) { + // Try again later + TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin())); + } + } +} + +void LockProcess::signalPassDlgToAttemptCardAbort() { + PasswordDlg* passDlg = dynamic_cast(currentDialog); + if (passDlg) { + passDlg->resetCardLogin(); + } + else { + if (currentDialog) { + // Try again later + TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort())); + } + } +} + +void LockProcess::cryptographicCardPinRequested(TQString prompt, TDECryptographicCardDevice* cdevice) { + TQCString password; + TQString pin_entry; + + QueryDlg qryDlg(this); + qryDlg.updateLabel(prompt); + qryDlg.setUnlockIcon(); + mForceReject = false; + execDialog(&qryDlg); + if (mForceReject == false) { + pin_entry = qryDlg.getEntry(); + cdevice->setProvidedPin(pin_entry); + } + else { + cdevice->setProvidedPin(TQString::null); + } +} + +TDECryptographicCardDevice* LockProcess::cryptographicCardDevice() { + return m_loginCardDevice; +} + +void LockProcess::fullyOnline() { + if (!mFullyOnlineSent) { + if (kdesktop_pid > 0) { + if (kill(kdesktop_pid, SIGUSR2) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + // Exit uncleanly + exit(1); + } + else { + mFullyOnlineSent = true; + } + } + } +} + +void LockProcess::saverReady() { + DCOPRef ref( "kdesktop", "KScreensaverIface"); + ref.send( "saverLockReady" ); +} + +//=========================================================================== +// +// Control pipe handler +// +ControlPipeHandlerObject::ControlPipeHandlerObject() : TQObject() { + mParent = NULL; + mRunning = false; + mTerminate = false; + mThreadID = 0L; +} + +ControlPipeHandlerObject::~ControlPipeHandlerObject() { + // +} + +void ControlPipeHandlerObject::run(void) { + mThreadID = pthread_self(); + mRunning = true; + + sigset_t new_mask; + sigemptyset(&new_mask); + sigaddset(&new_mask, SIGUSR1); + + // Unblock SIGUSR1 + pthread_sigmask(SIG_UNBLOCK, &new_mask, NULL); + + int display_number = atoi(TQString(XDisplayString(tqt_xdisplay())).replace(":","").ascii()); + + if (display_number < 0) { + printf("[kdesktop_lock] Warning: unable to create control socket. Interactive logon modules may not function properly.\n"); + mRunning = false; + TQApplication::eventLoop()->exit(-1); + return; + } + + char fifo_file[PATH_MAX]; + char fifo_file_out[PATH_MAX]; + snprintf(fifo_file, PATH_MAX, FIFO_FILE, display_number); + snprintf(fifo_file_out, PATH_MAX, FIFO_FILE_OUT, display_number); + + /* Create the FIFOs if they do not exist */ + umask(0); + mkdir(FIFO_DIR,0644); + mknod(fifo_file, S_IFIFO|0644, 0); + chmod(fifo_file, 0644); + + mParent->mPipe_fd = open(fifo_file, O_RDONLY | O_NONBLOCK); + if (mParent->mPipe_fd > -1) { + mParent->mPipeOpen = true; + } + + mknod(fifo_file_out, S_IFIFO|0600, 0); + chmod(fifo_file_out, 0600); + + mParent->mPipe_fd_out = open(fifo_file_out, O_RDWR | O_NONBLOCK); + if (mParent->mPipe_fd_out > -1) { + mParent->mPipeOpen_out = true; + } + + if (!mParent->mPipeOpen) { + printf("[kdesktop_lock] Warning: unable to create control socket '%s'. Interactive logon modules may not function properly.\n", fifo_file); + mRunning = false; + TQApplication::eventLoop()->exit(-1); + return; + } + + int numread; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(mParent->mPipe_fd, &rfds); + TQByteArray readbuf(128); + + while (mParent->mPipeOpen && !mTerminate) { + TQString inputcommand = ""; + + // Wait for mParent->mPipe_fd to receive input + retval = select(mParent->mPipe_fd + 1, &rfds, NULL, NULL, NULL); + if (retval < 0) { + // ERROR + } + else if (retval) { + // New data is available + readbuf[0]=' '; + numread = read(mParent->mPipe_fd, readbuf.data(), 128); + readbuf[numread] = 0; + if (numread > 0) { + inputcommand += readbuf; + emit processCommand(inputcommand); + } + } + } + + mRunning = false; + TQApplication::eventLoop()->exit(0); + return; +} + +void ControlPipeHandlerObject::terminateThread() { + if (mRunning) { + mTerminate = true; + pthread_kill(mThreadID, SIGUSR1); + } +} + +#include "lockprocess.moc" diff --git a/kdesktop/lock/main.cc b/kdesktop/lock/main.cc deleted file mode 100644 index f1407070c..000000000 --- a/kdesktop/lock/main.cc +++ /dev/null @@ -1,563 +0,0 @@ -/* This file is part of the TDE project - Copyright (C) 1999 David Faure - Copyright (c) 2003 Oswald Buddenhagen - Copyright (c) 2010-2015 Timothy Pearson - - 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 - -#include "lockprocess.h" -#include "main.h" -#include "kdesktopsettings.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && TQT_VERSION >= 0x030300 -#define COMPOSITE -#endif - -#ifdef COMPOSITE -# include -# include -# include -# include -#else -# include -# include -#endif - - -TQXLibWindowList trinity_desktop_lock_hidden_window_list; - -// [FIXME] Add GUI configuration checkboxes for these three settings (see kdesktoprc [ScreenSaver] UseUnmanagedLockWindows, DelaySaverStart, and UseTDESAK) -bool trinity_desktop_lock_use_system_modal_dialogs = FALSE; -bool trinity_desktop_lock_delay_screensaver_start = FALSE; -bool trinity_desktop_lock_use_sak = FALSE; -bool trinity_desktop_lock_hide_active_windows = FALSE; -bool trinity_desktop_lock_hide_cancel_button = FALSE; -bool trinity_desktop_lock_forced = FALSE; - -LockProcess* trinity_desktop_lock_process = NULL; - -bool signalled_forcelock; -bool signalled_dontlock; -bool signalled_securedialog; -bool signalled_blank; -bool signalled_run; -bool in_internal_mode = FALSE; - -bool argb_visual = FALSE; -pid_t kdesktop_pid = -1; -bool trinity_desktop_lock_settings_initialized = FALSE; - -static void sigusr1_handler(int) -{ - signalled_forcelock = TRUE; -} - -static void sigusr2_handler(int) -{ - signalled_dontlock = TRUE; -} - -static void sigusr3_handler(int) -{ - signalled_securedialog = TRUE; -} - -static void sigusr4_handler(int) -{ - signalled_blank = TRUE; -} - -static void sigusr5_handler(int) -{ - signalled_run = TRUE; -} - -static int trapXErrors(Display *, XErrorEvent *) -{ - return 0; -} - -bool MyApp::x11EventFilter( XEvent *ev ) -{ - if (ev->type == ButtonPress || ev->type == ButtonRelease || ev->type == MotionNotify) { - emit mouseInteraction(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(); - } - } - else if (ev->type == MapNotify) { - // HACK - // Hide all tooltips and notification windows - XMapEvent map_event = ev->xmap; - XWindowAttributes childAttr; - Window childTransient; - if (XGetWindowAttributes(map_event.display, map_event.window, &childAttr) && XGetTransientForHint(map_event.display, map_event.window, &childTransient)) { - if((childAttr.map_state == IsViewable) && (childAttr.override_redirect) && (childTransient)) { - if (!trinity_desktop_lock_hidden_window_list.contains(map_event.window)) { - trinity_desktop_lock_hidden_window_list.append(map_event.window); - } - XLowerWindow(map_event.display, map_event.window); - XFlush(map_event.display); - } - } - } - else if (ev->type == VisibilityNotify) { - // HACK - // Hide all tooltips and notification windows - XVisibilityEvent visibility_event = ev->xvisibility; - XWindowAttributes childAttr; - Window childTransient; - if ((visibility_event.state == VisibilityUnobscured) || (visibility_event.state == VisibilityPartiallyObscured)) { - if (XGetWindowAttributes(visibility_event.display, visibility_event.window, &childAttr) && XGetTransientForHint(visibility_event.display, visibility_event.window, &childTransient)) { - if((childAttr.map_state == IsViewable) && (childAttr.override_redirect) && (childTransient)) { - if (!trinity_desktop_lock_hidden_window_list.contains(visibility_event.window)) { - trinity_desktop_lock_hidden_window_list.append(visibility_event.window); - } - XLowerWindow(visibility_event.display, visibility_event.window); - XFlush(visibility_event.display); - } - } - } - } - else if (ev->type == CreateNotify) { - // HACK - // Close all tooltips and notification windows - XCreateWindowEvent create_event = ev->xcreatewindow; - XWindowAttributes childAttr; - Window childTransient; - - // XGetWindowAttributes may generate BadWindow errors, so make sure they are silently ignored - int (*oldHandler)(Display *, XErrorEvent *); - oldHandler = XSetErrorHandler(trapXErrors); - if (XGetWindowAttributes(create_event.display, create_event.window, &childAttr) && XGetTransientForHint(create_event.display, create_event.window, &childTransient)) { - if ((childAttr.override_redirect) && (childTransient)) { - if (!trinity_desktop_lock_hidden_window_list.contains(create_event.window)) { - trinity_desktop_lock_hidden_window_list.append(create_event.window); - } - XLowerWindow(create_event.display, create_event.window); - XFlush(create_event.display); - } - } - XSetErrorHandler(oldHandler); - } - else if (ev->type == DestroyNotify) { - XDestroyWindowEvent destroy_event = ev->xdestroywindow; - if (trinity_desktop_lock_hidden_window_list.contains(destroy_event.window)) { - trinity_desktop_lock_hidden_window_list.remove(destroy_event.window); - } - } -#if 0 - else if (ev->type == CreateNotify) { - // HACK - // Close all tooltips and notification windows - XCreateWindowEvent create_event = ev->xcreatewindow; - XWindowAttributes childAttr; - Window childTransient; - if (XGetWindowAttributes(create_event.display, create_event.window, &childAttr) && XGetTransientForHint(create_event.display, create_event.window, &childTransient)) { - if ((childAttr.override_redirect) && (childTransient)) { - XDestroyWindow(create_event.display, create_event.window); - } - } - } -#endif - return TDEApplication::x11EventFilter( ev ); -} - - -static TDECmdLineOptions options[] = -{ - { "forcelock", I18N_NOOP("Force session locking"), 0 }, - { "dontlock", I18N_NOOP("Only start screensaver"), 0 }, - { "securedialog", I18N_NOOP("Launch the secure dialog"), 0 }, - { "blank", I18N_NOOP("Only use the blank screensaver"), 0 }, - { "internal ", I18N_NOOP("TDE internal command for background process loading"), 0 }, - TDECmdLineLastOption -}; - -void restore_hidden_override_redirect_windows() { - TQXLibWindowList::iterator it; - for (it = trinity_desktop_lock_hidden_window_list.begin(); it != trinity_desktop_lock_hidden_window_list.end(); ++it) { - Window win = *it; - XRaiseWindow(tqt_xdisplay(), win); - } -} - -// ----------------------------------------------------------------------------- - -int main( int argc, char **argv ) -{ - TDELocale::setMainCatalogue("kdesktop"); - - TDECmdLineArgs::init( argc, argv, "kdesktop_lock", I18N_NOOP("KDesktop Locker"), I18N_NOOP("Session Locker for KDesktop"), "2.1" ); - TDECmdLineArgs::addCmdLineOptions( options ); - TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); - - putenv(strdup("SESSION_MANAGER=")); - - TDEApplication::disableAutoDcopRegistration(); // not needed - - XSetErrorHandler(trapXErrors); - - MyApp* app = NULL; - - while (1 == 1) { - sigset_t new_mask; - sigset_t orig_mask; - - // Block reception of all signals in this thread - sigfillset(&new_mask); - sigprocmask(SIG_BLOCK, &new_mask, NULL); - - signalled_forcelock = FALSE; - signalled_dontlock = FALSE; - signalled_securedialog = FALSE; - signalled_blank = FALSE; - signalled_run = FALSE; - - int kdesktop_screen_number = 0; - int starting_screen = 0; - - bool child = false; - int parent_connection = 0; // socket to the parent saver - TQValueList child_sockets; - - if (TDEGlobalSettings::isMultiHead()) { - Display *dpy = XOpenDisplay(NULL); - if (! dpy) { - fprintf(stderr, - "%s: FATAL ERROR: couldn't 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; - TQCString display_name = XDisplayString(dpy); - XCloseDisplay(dpy); - kdDebug() << "screen " << number_of_screens << " " << kdesktop_screen_number << " " << display_name << " " << starting_screen << endl; - dpy = 0; - - if ((pos = display_name.findRev('.')) != -1) { - display_name.remove(pos, 10); - } - - TQCString 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); - kdDebug() << "env " << env << endl; - - if (putenv(strdup(env.data()))) { - fprintf(stderr, - "%s: WARNING: unable to set DISPLAY environment variable\n", - argv[0]); - perror("putenv()"); - } - } - } - - if (!app) { -#ifdef COMPOSITE - app = new MyApp(TDEApplication::openX11RGBADisplay()); - argb_visual = app->isX11CompositionAvailable(); -#else - app = new MyApp; -#endif - } - - TDELockFile lock(locateLocal("tmp", TQString("kdesktop_lock_lockfile.%1").arg(getenv("DISPLAY")))); - lock.setStaleTime(0); - TDELockFile::LockResult lockRet = lock.lock(); - if (lockRet != TDELockFile::LockOK) { - // Terminate existing (stale) process if needed - int pid; - TQString hostName; - TQString appName; - if (lock.getLockInfo(pid, hostName, appName)) { - // Verify that the pid in question is an instance of kdesktop_lock - int len; - char procpath[PATH_MAX]; - char fullpath[PATH_MAX]; -#if defined(__dilos__) - snprintf(procpath, sizeof(procpath), "/proc/%d/path/a.out", pid); -#elif defined(__FreeBSD__) || defined (__DragonFly__) - snprintf(procpath, sizeof(procpath), "/compat/linux/proc/%d/exe", pid); -#else /* Linux way as default */ - snprintf(procpath, sizeof(procpath), "/proc/%d/exe", pid); -#endif - len = readlink( procpath, fullpath, sizeof(fullpath) ); - if (len >= 0) { - fullpath[len] = 0; - TQFileInfo fileInfo(fullpath); - if (fileInfo.baseName() == "kdesktop_lock") { - // Verify that pid in question is owned by current user before killing it - uid_t current_uid = geteuid(); - - struct stat info; - if (lstat(procpath, &info) == 0) { - if (info.st_uid == current_uid) { - kill(pid, SIGKILL); - } - } - } - } - } - } - - // Force a relock as a stale lockfile or process may have been dealt with above - if (!lock.isLocked()) { - lockRet = lock.lock(TDELockFile::LockNoBlock | TDELockFile::LockForce); - } - - kdDebug() << "app " << kdesktop_screen_number << " " << starting_screen << " " << child << " " << child_sockets.count() << " " << parent_connection << endl; - app->disableSessionManagement(); - TDEGlobal::locale()->insertCatalogue("libdmctl"); - - struct stat st; - KSimpleConfig* tdmconfig; - if( stat( KDE_CONFDIR "/tdm/tdmdistrc" , &st ) == 0) { - tdmconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/tdm/tdmdistrc" )); - } - else { - tdmconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/tdm/tdmrc" )); - } - tdmconfig->setGroup("X-:*-Greeter"); - - // Create new LockProcess, which also spawns threads inheriting the blocked signal mask - trinity_desktop_lock_process = new LockProcess; - - // Unblock reception of all signals in this thread - sigprocmask(SIG_UNBLOCK, &new_mask, NULL); - - // Start loading core functions, such as the desktop wallpaper interface - app->processEvents(); - - if (args->isSet( "internal" )) { - kdesktop_pid = atoi(args->getOption( "internal" )); - struct sigaction act; - - in_internal_mode = TRUE; - - // handle SIGUSR1 - act.sa_handler= sigusr1_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGUSR1); - act.sa_flags = 0; - sigaction(SIGUSR1, &act, 0L); - // handle SIGUSR2 - act.sa_handler= sigusr2_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGUSR2); - act.sa_flags = 0; - sigaction(SIGUSR2, &act, 0L); - // handle SIGWINCH (an ersatz SIGUSR3) - act.sa_handler= sigusr3_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGWINCH); - act.sa_flags = 0; - sigaction(SIGWINCH, &act, 0L); - // handle SIGTTIN (an ersatz SIGUSR4) - act.sa_handler= sigusr4_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGTTIN); - act.sa_flags = 0; - sigaction(SIGTTIN, &act, 0L); - // handle SIGTTOU (an ersatz SIGUSR5) - act.sa_handler= sigusr5_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGTTOU); - act.sa_flags = 0; - sigaction(SIGTTOU, &act, 0L); - - // initialize the signal masks - sigemptyset(&new_mask); - sigaddset(&new_mask,SIGUSR1); - sigaddset(&new_mask,SIGUSR2); - sigaddset(&new_mask,SIGWINCH); - sigaddset(&new_mask,SIGTTIN); - sigaddset(&new_mask,SIGTTOU); - - while (signalled_run == FALSE) { - // let kdesktop know the saver process is ready - if (kill(kdesktop_pid, SIGTTIN) < 0) { - // The controlling kdesktop process probably died. Commit suicide... - return 12; - } - - // Get root window attributes - XWindowAttributes rootAttr; - XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); - - // Disable reception of all X11 events on the root window - XSelectInput( tqt_xdisplay(), tqt_xrootwin(), 0 ); - app->processEvents(); - - // wait for SIGUSR1, SIGUSR2, SIGWINCH, SIGTTIN, or SIGTTOU - sigprocmask(SIG_BLOCK, &new_mask, &orig_mask); - if (signalled_run != TRUE) { - sigsuspend(&orig_mask); - } - sigprocmask(SIG_UNBLOCK, &new_mask, NULL); - - // Reenable reception of X11 events on the root window - XSelectInput( tqt_xdisplay(), tqt_xrootwin(), rootAttr.your_event_mask ); - } - - // Block reception of all signals in this thread - sigprocmask(SIG_BLOCK, &new_mask, NULL); - } - - // (re)load settings here so that they actually reflect reality - // we need to read from the right rc file - possibly taking screen number in account - if (!trinity_desktop_lock_settings_initialized) { - KDesktopSettings::instance("kdesktoprc"); - trinity_desktop_lock_settings_initialized = true; - } - else { - KDesktopSettings::self()->readConfig(); - } - trinity_desktop_lock_use_system_modal_dialogs = !KDesktopSettings::useUnmanagedLockWindows(); - trinity_desktop_lock_delay_screensaver_start = KDesktopSettings::delaySaverStart(); - if (trinity_desktop_lock_use_system_modal_dialogs) { -#ifdef BUILD_TSAK - trinity_desktop_lock_use_sak = tdmconfig->readBoolEntry("UseSAK", false) && KDesktopSettings::useTDESAK(); -#else - trinity_desktop_lock_use_sak = false; -#endif - } - else { - trinity_desktop_lock_use_sak = false; // If SAK is enabled with unmanaged windows, the SAK dialog will never close and will "burn in" the screen - trinity_desktop_lock_delay_screensaver_start = false; // If trinity_desktop_lock_delay_screensaver_start is true with unmanaged windows, the lock dialog may never appear - } - trinity_desktop_lock_hide_active_windows = KDesktopSettings::hideActiveWindowsFromSaver(); - trinity_desktop_lock_hide_cancel_button = KDesktopSettings::hideCancelButton(); - - delete tdmconfig; - - if (args->isSet( "forcelock" ) || (signalled_forcelock == TRUE)) { - trinity_desktop_lock_forced = TRUE; - } - - trinity_desktop_lock_process->init(child, (args->isSet( "blank" ) || (signalled_blank == TRUE))); - if (!child) { - trinity_desktop_lock_process->setChildren(child_sockets); - } - else { - trinity_desktop_lock_process->setParent(parent_connection); - } - - bool rt; - if( (((!child) && (args->isSet( "forcelock" ))) || (signalled_forcelock == TRUE))) { - rt = trinity_desktop_lock_process->lock(); - } - else if( child || (args->isSet( "dontlock" ) || (signalled_dontlock == TRUE))) { - rt = trinity_desktop_lock_process->dontLock(); - } - else if( child || (args->isSet( "securedialog" ) || (signalled_securedialog == TRUE))) { - int retcode = tde_sak_verify_calling_process(); - if (retcode == 0) { - rt = trinity_desktop_lock_process->runSecureDialog(); - } - else { - return 1; - } - } - else { - rt = trinity_desktop_lock_process->defaultSave(); - } - if (!rt) { - return 0; - } - - if (in_internal_mode == FALSE) { - trinity_desktop_lock_hidden_window_list.clear(); - int ret = app->exec(); - restore_hidden_override_redirect_windows(); - return ret; - } - else { - if (kill(kdesktop_pid, 0) < 0) { - // The controlling kdesktop process probably died. Commit suicide... - return 12; - } - trinity_desktop_lock_hidden_window_list.clear(); - app->exec(); - restore_hidden_override_redirect_windows(); - if (kill(kdesktop_pid, SIGUSR1) < 0) { - // The controlling kdesktop process probably died. Commit suicide... - return 12; - } - - delete trinity_desktop_lock_process; - trinity_desktop_lock_process = NULL; - - // FIXME - // We should not have to return (restart) at all, - // but it seems that some X11 connections are left active, - // preventing the lock process from restarting properly in the while() loop above. - return 0; - } - } -} - -#include "main.moc" diff --git a/kdesktop/lock/main.cpp b/kdesktop/lock/main.cpp new file mode 100644 index 000000000..f1407070c --- /dev/null +++ b/kdesktop/lock/main.cpp @@ -0,0 +1,563 @@ +/* This file is part of the TDE project + Copyright (C) 1999 David Faure + Copyright (c) 2003 Oswald Buddenhagen + Copyright (c) 2010-2015 Timothy Pearson + + 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 + +#include "lockprocess.h" +#include "main.h" +#include "kdesktopsettings.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && TQT_VERSION >= 0x030300 +#define COMPOSITE +#endif + +#ifdef COMPOSITE +# include +# include +# include +# include +#else +# include +# include +#endif + + +TQXLibWindowList trinity_desktop_lock_hidden_window_list; + +// [FIXME] Add GUI configuration checkboxes for these three settings (see kdesktoprc [ScreenSaver] UseUnmanagedLockWindows, DelaySaverStart, and UseTDESAK) +bool trinity_desktop_lock_use_system_modal_dialogs = FALSE; +bool trinity_desktop_lock_delay_screensaver_start = FALSE; +bool trinity_desktop_lock_use_sak = FALSE; +bool trinity_desktop_lock_hide_active_windows = FALSE; +bool trinity_desktop_lock_hide_cancel_button = FALSE; +bool trinity_desktop_lock_forced = FALSE; + +LockProcess* trinity_desktop_lock_process = NULL; + +bool signalled_forcelock; +bool signalled_dontlock; +bool signalled_securedialog; +bool signalled_blank; +bool signalled_run; +bool in_internal_mode = FALSE; + +bool argb_visual = FALSE; +pid_t kdesktop_pid = -1; +bool trinity_desktop_lock_settings_initialized = FALSE; + +static void sigusr1_handler(int) +{ + signalled_forcelock = TRUE; +} + +static void sigusr2_handler(int) +{ + signalled_dontlock = TRUE; +} + +static void sigusr3_handler(int) +{ + signalled_securedialog = TRUE; +} + +static void sigusr4_handler(int) +{ + signalled_blank = TRUE; +} + +static void sigusr5_handler(int) +{ + signalled_run = TRUE; +} + +static int trapXErrors(Display *, XErrorEvent *) +{ + return 0; +} + +bool MyApp::x11EventFilter( XEvent *ev ) +{ + if (ev->type == ButtonPress || ev->type == ButtonRelease || ev->type == MotionNotify) { + emit mouseInteraction(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(); + } + } + else if (ev->type == MapNotify) { + // HACK + // Hide all tooltips and notification windows + XMapEvent map_event = ev->xmap; + XWindowAttributes childAttr; + Window childTransient; + if (XGetWindowAttributes(map_event.display, map_event.window, &childAttr) && XGetTransientForHint(map_event.display, map_event.window, &childTransient)) { + if((childAttr.map_state == IsViewable) && (childAttr.override_redirect) && (childTransient)) { + if (!trinity_desktop_lock_hidden_window_list.contains(map_event.window)) { + trinity_desktop_lock_hidden_window_list.append(map_event.window); + } + XLowerWindow(map_event.display, map_event.window); + XFlush(map_event.display); + } + } + } + else if (ev->type == VisibilityNotify) { + // HACK + // Hide all tooltips and notification windows + XVisibilityEvent visibility_event = ev->xvisibility; + XWindowAttributes childAttr; + Window childTransient; + if ((visibility_event.state == VisibilityUnobscured) || (visibility_event.state == VisibilityPartiallyObscured)) { + if (XGetWindowAttributes(visibility_event.display, visibility_event.window, &childAttr) && XGetTransientForHint(visibility_event.display, visibility_event.window, &childTransient)) { + if((childAttr.map_state == IsViewable) && (childAttr.override_redirect) && (childTransient)) { + if (!trinity_desktop_lock_hidden_window_list.contains(visibility_event.window)) { + trinity_desktop_lock_hidden_window_list.append(visibility_event.window); + } + XLowerWindow(visibility_event.display, visibility_event.window); + XFlush(visibility_event.display); + } + } + } + } + else if (ev->type == CreateNotify) { + // HACK + // Close all tooltips and notification windows + XCreateWindowEvent create_event = ev->xcreatewindow; + XWindowAttributes childAttr; + Window childTransient; + + // XGetWindowAttributes may generate BadWindow errors, so make sure they are silently ignored + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(trapXErrors); + if (XGetWindowAttributes(create_event.display, create_event.window, &childAttr) && XGetTransientForHint(create_event.display, create_event.window, &childTransient)) { + if ((childAttr.override_redirect) && (childTransient)) { + if (!trinity_desktop_lock_hidden_window_list.contains(create_event.window)) { + trinity_desktop_lock_hidden_window_list.append(create_event.window); + } + XLowerWindow(create_event.display, create_event.window); + XFlush(create_event.display); + } + } + XSetErrorHandler(oldHandler); + } + else if (ev->type == DestroyNotify) { + XDestroyWindowEvent destroy_event = ev->xdestroywindow; + if (trinity_desktop_lock_hidden_window_list.contains(destroy_event.window)) { + trinity_desktop_lock_hidden_window_list.remove(destroy_event.window); + } + } +#if 0 + else if (ev->type == CreateNotify) { + // HACK + // Close all tooltips and notification windows + XCreateWindowEvent create_event = ev->xcreatewindow; + XWindowAttributes childAttr; + Window childTransient; + if (XGetWindowAttributes(create_event.display, create_event.window, &childAttr) && XGetTransientForHint(create_event.display, create_event.window, &childTransient)) { + if ((childAttr.override_redirect) && (childTransient)) { + XDestroyWindow(create_event.display, create_event.window); + } + } + } +#endif + return TDEApplication::x11EventFilter( ev ); +} + + +static TDECmdLineOptions options[] = +{ + { "forcelock", I18N_NOOP("Force session locking"), 0 }, + { "dontlock", I18N_NOOP("Only start screensaver"), 0 }, + { "securedialog", I18N_NOOP("Launch the secure dialog"), 0 }, + { "blank", I18N_NOOP("Only use the blank screensaver"), 0 }, + { "internal ", I18N_NOOP("TDE internal command for background process loading"), 0 }, + TDECmdLineLastOption +}; + +void restore_hidden_override_redirect_windows() { + TQXLibWindowList::iterator it; + for (it = trinity_desktop_lock_hidden_window_list.begin(); it != trinity_desktop_lock_hidden_window_list.end(); ++it) { + Window win = *it; + XRaiseWindow(tqt_xdisplay(), win); + } +} + +// ----------------------------------------------------------------------------- + +int main( int argc, char **argv ) +{ + TDELocale::setMainCatalogue("kdesktop"); + + TDECmdLineArgs::init( argc, argv, "kdesktop_lock", I18N_NOOP("KDesktop Locker"), I18N_NOOP("Session Locker for KDesktop"), "2.1" ); + TDECmdLineArgs::addCmdLineOptions( options ); + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + putenv(strdup("SESSION_MANAGER=")); + + TDEApplication::disableAutoDcopRegistration(); // not needed + + XSetErrorHandler(trapXErrors); + + MyApp* app = NULL; + + while (1 == 1) { + sigset_t new_mask; + sigset_t orig_mask; + + // Block reception of all signals in this thread + sigfillset(&new_mask); + sigprocmask(SIG_BLOCK, &new_mask, NULL); + + signalled_forcelock = FALSE; + signalled_dontlock = FALSE; + signalled_securedialog = FALSE; + signalled_blank = FALSE; + signalled_run = FALSE; + + int kdesktop_screen_number = 0; + int starting_screen = 0; + + bool child = false; + int parent_connection = 0; // socket to the parent saver + TQValueList child_sockets; + + if (TDEGlobalSettings::isMultiHead()) { + Display *dpy = XOpenDisplay(NULL); + if (! dpy) { + fprintf(stderr, + "%s: FATAL ERROR: couldn't 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; + TQCString display_name = XDisplayString(dpy); + XCloseDisplay(dpy); + kdDebug() << "screen " << number_of_screens << " " << kdesktop_screen_number << " " << display_name << " " << starting_screen << endl; + dpy = 0; + + if ((pos = display_name.findRev('.')) != -1) { + display_name.remove(pos, 10); + } + + TQCString 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); + kdDebug() << "env " << env << endl; + + if (putenv(strdup(env.data()))) { + fprintf(stderr, + "%s: WARNING: unable to set DISPLAY environment variable\n", + argv[0]); + perror("putenv()"); + } + } + } + + if (!app) { +#ifdef COMPOSITE + app = new MyApp(TDEApplication::openX11RGBADisplay()); + argb_visual = app->isX11CompositionAvailable(); +#else + app = new MyApp; +#endif + } + + TDELockFile lock(locateLocal("tmp", TQString("kdesktop_lock_lockfile.%1").arg(getenv("DISPLAY")))); + lock.setStaleTime(0); + TDELockFile::LockResult lockRet = lock.lock(); + if (lockRet != TDELockFile::LockOK) { + // Terminate existing (stale) process if needed + int pid; + TQString hostName; + TQString appName; + if (lock.getLockInfo(pid, hostName, appName)) { + // Verify that the pid in question is an instance of kdesktop_lock + int len; + char procpath[PATH_MAX]; + char fullpath[PATH_MAX]; +#if defined(__dilos__) + snprintf(procpath, sizeof(procpath), "/proc/%d/path/a.out", pid); +#elif defined(__FreeBSD__) || defined (__DragonFly__) + snprintf(procpath, sizeof(procpath), "/compat/linux/proc/%d/exe", pid); +#else /* Linux way as default */ + snprintf(procpath, sizeof(procpath), "/proc/%d/exe", pid); +#endif + len = readlink( procpath, fullpath, sizeof(fullpath) ); + if (len >= 0) { + fullpath[len] = 0; + TQFileInfo fileInfo(fullpath); + if (fileInfo.baseName() == "kdesktop_lock") { + // Verify that pid in question is owned by current user before killing it + uid_t current_uid = geteuid(); + + struct stat info; + if (lstat(procpath, &info) == 0) { + if (info.st_uid == current_uid) { + kill(pid, SIGKILL); + } + } + } + } + } + } + + // Force a relock as a stale lockfile or process may have been dealt with above + if (!lock.isLocked()) { + lockRet = lock.lock(TDELockFile::LockNoBlock | TDELockFile::LockForce); + } + + kdDebug() << "app " << kdesktop_screen_number << " " << starting_screen << " " << child << " " << child_sockets.count() << " " << parent_connection << endl; + app->disableSessionManagement(); + TDEGlobal::locale()->insertCatalogue("libdmctl"); + + struct stat st; + KSimpleConfig* tdmconfig; + if( stat( KDE_CONFDIR "/tdm/tdmdistrc" , &st ) == 0) { + tdmconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/tdm/tdmdistrc" )); + } + else { + tdmconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/tdm/tdmrc" )); + } + tdmconfig->setGroup("X-:*-Greeter"); + + // Create new LockProcess, which also spawns threads inheriting the blocked signal mask + trinity_desktop_lock_process = new LockProcess; + + // Unblock reception of all signals in this thread + sigprocmask(SIG_UNBLOCK, &new_mask, NULL); + + // Start loading core functions, such as the desktop wallpaper interface + app->processEvents(); + + if (args->isSet( "internal" )) { + kdesktop_pid = atoi(args->getOption( "internal" )); + struct sigaction act; + + in_internal_mode = TRUE; + + // handle SIGUSR1 + act.sa_handler= sigusr1_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGUSR1); + act.sa_flags = 0; + sigaction(SIGUSR1, &act, 0L); + // handle SIGUSR2 + act.sa_handler= sigusr2_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGUSR2); + act.sa_flags = 0; + sigaction(SIGUSR2, &act, 0L); + // handle SIGWINCH (an ersatz SIGUSR3) + act.sa_handler= sigusr3_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGWINCH); + act.sa_flags = 0; + sigaction(SIGWINCH, &act, 0L); + // handle SIGTTIN (an ersatz SIGUSR4) + act.sa_handler= sigusr4_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTTIN); + act.sa_flags = 0; + sigaction(SIGTTIN, &act, 0L); + // handle SIGTTOU (an ersatz SIGUSR5) + act.sa_handler= sigusr5_handler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTTOU); + act.sa_flags = 0; + sigaction(SIGTTOU, &act, 0L); + + // initialize the signal masks + sigemptyset(&new_mask); + sigaddset(&new_mask,SIGUSR1); + sigaddset(&new_mask,SIGUSR2); + sigaddset(&new_mask,SIGWINCH); + sigaddset(&new_mask,SIGTTIN); + sigaddset(&new_mask,SIGTTOU); + + while (signalled_run == FALSE) { + // let kdesktop know the saver process is ready + if (kill(kdesktop_pid, SIGTTIN) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + return 12; + } + + // Get root window attributes + XWindowAttributes rootAttr; + XGetWindowAttributes(tqt_xdisplay(), RootWindow(tqt_xdisplay(), tqt_xscreen()), &rootAttr); + + // Disable reception of all X11 events on the root window + XSelectInput( tqt_xdisplay(), tqt_xrootwin(), 0 ); + app->processEvents(); + + // wait for SIGUSR1, SIGUSR2, SIGWINCH, SIGTTIN, or SIGTTOU + sigprocmask(SIG_BLOCK, &new_mask, &orig_mask); + if (signalled_run != TRUE) { + sigsuspend(&orig_mask); + } + sigprocmask(SIG_UNBLOCK, &new_mask, NULL); + + // Reenable reception of X11 events on the root window + XSelectInput( tqt_xdisplay(), tqt_xrootwin(), rootAttr.your_event_mask ); + } + + // Block reception of all signals in this thread + sigprocmask(SIG_BLOCK, &new_mask, NULL); + } + + // (re)load settings here so that they actually reflect reality + // we need to read from the right rc file - possibly taking screen number in account + if (!trinity_desktop_lock_settings_initialized) { + KDesktopSettings::instance("kdesktoprc"); + trinity_desktop_lock_settings_initialized = true; + } + else { + KDesktopSettings::self()->readConfig(); + } + trinity_desktop_lock_use_system_modal_dialogs = !KDesktopSettings::useUnmanagedLockWindows(); + trinity_desktop_lock_delay_screensaver_start = KDesktopSettings::delaySaverStart(); + if (trinity_desktop_lock_use_system_modal_dialogs) { +#ifdef BUILD_TSAK + trinity_desktop_lock_use_sak = tdmconfig->readBoolEntry("UseSAK", false) && KDesktopSettings::useTDESAK(); +#else + trinity_desktop_lock_use_sak = false; +#endif + } + else { + trinity_desktop_lock_use_sak = false; // If SAK is enabled with unmanaged windows, the SAK dialog will never close and will "burn in" the screen + trinity_desktop_lock_delay_screensaver_start = false; // If trinity_desktop_lock_delay_screensaver_start is true with unmanaged windows, the lock dialog may never appear + } + trinity_desktop_lock_hide_active_windows = KDesktopSettings::hideActiveWindowsFromSaver(); + trinity_desktop_lock_hide_cancel_button = KDesktopSettings::hideCancelButton(); + + delete tdmconfig; + + if (args->isSet( "forcelock" ) || (signalled_forcelock == TRUE)) { + trinity_desktop_lock_forced = TRUE; + } + + trinity_desktop_lock_process->init(child, (args->isSet( "blank" ) || (signalled_blank == TRUE))); + if (!child) { + trinity_desktop_lock_process->setChildren(child_sockets); + } + else { + trinity_desktop_lock_process->setParent(parent_connection); + } + + bool rt; + if( (((!child) && (args->isSet( "forcelock" ))) || (signalled_forcelock == TRUE))) { + rt = trinity_desktop_lock_process->lock(); + } + else if( child || (args->isSet( "dontlock" ) || (signalled_dontlock == TRUE))) { + rt = trinity_desktop_lock_process->dontLock(); + } + else if( child || (args->isSet( "securedialog" ) || (signalled_securedialog == TRUE))) { + int retcode = tde_sak_verify_calling_process(); + if (retcode == 0) { + rt = trinity_desktop_lock_process->runSecureDialog(); + } + else { + return 1; + } + } + else { + rt = trinity_desktop_lock_process->defaultSave(); + } + if (!rt) { + return 0; + } + + if (in_internal_mode == FALSE) { + trinity_desktop_lock_hidden_window_list.clear(); + int ret = app->exec(); + restore_hidden_override_redirect_windows(); + return ret; + } + else { + if (kill(kdesktop_pid, 0) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + return 12; + } + trinity_desktop_lock_hidden_window_list.clear(); + app->exec(); + restore_hidden_override_redirect_windows(); + if (kill(kdesktop_pid, SIGUSR1) < 0) { + // The controlling kdesktop process probably died. Commit suicide... + return 12; + } + + delete trinity_desktop_lock_process; + trinity_desktop_lock_process = NULL; + + // FIXME + // We should not have to return (restart) at all, + // but it seems that some X11 connections are left active, + // preventing the lock process from restarting properly in the while() loop above. + return 0; + } + } +} + +#include "main.moc" diff --git a/kdesktop/lock/querydlg.cc b/kdesktop/lock/querydlg.cc deleted file mode 100644 index 1fc5d260c..000000000 --- a/kdesktop/lock/querydlg.cc +++ /dev/null @@ -1,163 +0,0 @@ -//=========================================================================== -// -// This file is part of the TDE project -// -// Copyright (c) 2010 - 2015 Timothy Pearson - -#include - -#include "querydlg.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifndef AF_LOCAL -# define AF_LOCAL AF_UNIX -#endif - -extern bool trinity_desktop_lock_use_system_modal_dialogs; - -//=========================================================================== -// -// Simple dialog for displaying a password/PIN entry dialog -// -QueryDlg::QueryDlg(LockProcess *parent) - : TQDialog(parent, "query dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), - mUnlockingFailed(false) -{ - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - setCaption(i18n("Information Needed")); - - frame = new TQFrame( this ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - frame->setFrameStyle( TQFrame::NoFrame ); - } - else { - frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); - } - frame->setLineWidth( 2 ); - - mpixLabel = new TQLabel( frame, "pixlabel" ); - mpixLabel->setPixmap(DesktopIcon("unlock")); - - KUser user; - - mStatusLabel = new TQLabel( " ", frame ); - //mStatusLabel->setAlignment( TQLabel::AlignCenter ); - mStatusLabel->setAlignment( TQLabel::AlignLeft ); - - KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); - - ok = new KPushButton( i18n("Unl&ock"), frame ); - - TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); - unlockDialogLayout->addWidget( frame ); - - TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - layStatus->addWidget( mStatusLabel ); - - TQHBoxLayout *layPin = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - pin_box = new KPasswordEdit( this, "pin_box" ); - layPin->addWidget( pin_box ); - pin_box->setFocus(); - - TQHBoxLayout *layButtons = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - layButtons->addStretch(); - layButtons->addWidget( ok ); - - frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); - frameLayout->addMultiCellWidget( mpixLabel, 0, 2, 0, 0, Qt::AlignTop ); - frameLayout->addLayout( layStatus, 0, 1 ); - frameLayout->addLayout( layPin, 2, 1 ); - frameLayout->addMultiCellWidget( sep, 3, 3, 0, 1 ); - frameLayout->addMultiCellLayout( layButtons, 4, 4, 0, 1 ); - - connect(ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotOK())); - - installEventFilter(this); - setFixedSize( sizeHint() ); -} - -QueryDlg::~QueryDlg() -{ - hide(); -} - -void QueryDlg::slotOK() -{ - close(); -} - -TQString QueryDlg::getEntry() -{ - return pin_box->password(); -} - -void QueryDlg::updateLabel(TQString &txt) -{ - mStatusLabel->setPaletteForegroundColor(Qt::black); - mStatusLabel->setText("" + txt + ""); -} - -void QueryDlg::setUnlockIcon() -{ - mpixLabel->setPixmap(DesktopIcon("unlock")); -} - -void QueryDlg::setWarningIcon() -{ - mpixLabel->setPixmap(DesktopIcon("messagebox_warning")); -} - -void QueryDlg::show() -{ - TQDialog::show(); - TQApplication::flushX(); -} - -#include "querydlg.moc" diff --git a/kdesktop/lock/querydlg.cpp b/kdesktop/lock/querydlg.cpp new file mode 100644 index 000000000..1fc5d260c --- /dev/null +++ b/kdesktop/lock/querydlg.cpp @@ -0,0 +1,163 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 2010 - 2015 Timothy Pearson + +#include + +#include "querydlg.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; + +//=========================================================================== +// +// Simple dialog for displaying a password/PIN entry dialog +// +QueryDlg::QueryDlg(LockProcess *parent) + : TQDialog(parent, "query dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Information Needed")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + frame->setFrameStyle( TQFrame::NoFrame ); + } + else { + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + } + frame->setLineWidth( 2 ); + + mpixLabel = new TQLabel( frame, "pixlabel" ); + mpixLabel->setPixmap(DesktopIcon("unlock")); + + KUser user; + + mStatusLabel = new TQLabel( " ", frame ); + //mStatusLabel->setAlignment( TQLabel::AlignCenter ); + mStatusLabel->setAlignment( TQLabel::AlignLeft ); + + KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); + + ok = new KPushButton( i18n("Unl&ock"), frame ); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + + TQHBoxLayout *layPin = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + pin_box = new KPasswordEdit( this, "pin_box" ); + layPin->addWidget( pin_box ); + pin_box->setFocus(); + + TQHBoxLayout *layButtons = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layButtons->addStretch(); + layButtons->addWidget( ok ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( mpixLabel, 0, 2, 0, 0, Qt::AlignTop ); + frameLayout->addLayout( layStatus, 0, 1 ); + frameLayout->addLayout( layPin, 2, 1 ); + frameLayout->addMultiCellWidget( sep, 3, 3, 0, 1 ); + frameLayout->addMultiCellLayout( layButtons, 4, 4, 0, 1 ); + + connect(ok, TQT_SIGNAL(clicked()), TQT_SLOT(slotOK())); + + installEventFilter(this); + setFixedSize( sizeHint() ); +} + +QueryDlg::~QueryDlg() +{ + hide(); +} + +void QueryDlg::slotOK() +{ + close(); +} + +TQString QueryDlg::getEntry() +{ + return pin_box->password(); +} + +void QueryDlg::updateLabel(TQString &txt) +{ + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText("" + txt + ""); +} + +void QueryDlg::setUnlockIcon() +{ + mpixLabel->setPixmap(DesktopIcon("unlock")); +} + +void QueryDlg::setWarningIcon() +{ + mpixLabel->setPixmap(DesktopIcon("messagebox_warning")); +} + +void QueryDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "querydlg.moc" diff --git a/kdesktop/lock/sakdlg.cc b/kdesktop/lock/sakdlg.cc deleted file mode 100644 index 803c77919..000000000 --- a/kdesktop/lock/sakdlg.cc +++ /dev/null @@ -1,155 +0,0 @@ -//=========================================================================== -// -// This file is part of the TDE project -// -// Copyright (c) 2010 - 2015 Timothy Pearson - -#include - -#include "sakdlg.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifndef AF_LOCAL -# define AF_LOCAL AF_UNIX -#endif - -extern bool trinity_desktop_lock_use_system_modal_dialogs; -extern bool trinity_desktop_lock_use_sak; - -//=========================================================================== -// -// Simple dialog for displaying an unlock status or recurring error message -// -SAKDlg::SAKDlg(LockProcess *parent) - : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), - mUnlockingFailed(false) -{ - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - setCaption(i18n("Desktop Session Locked")); - - frame = new TQFrame( this ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - frame->setFrameStyle( TQFrame::NoFrame ); - } - else { - frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); - } - frame->setLineWidth( 2 ); - - KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); - - KUser user; - - mStatusLabel = new TQLabel( " ", frame ); - mStatusLabel->setAlignment( TQLabel::AlignVCenter ); - - TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); - unlockDialogLayout->addWidget( frame ); - - TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - layStatus->addWidget( mStatusLabel ); - - frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); - frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, AlignTop | AlignLeft ); - frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter); - - mStatusLabel->setText("" + i18n("Press Ctrl+Alt+Del to begin.") + "

" + i18n("This process helps keep your password secure.") + "
" + i18n("It prevents unauthorized users from emulating the login screen.")); - - installEventFilter(this); - setFixedSize( sizeHint() ); - - mSAKProcess = new TDEProcess; - *mSAKProcess << "tdmtsak"; - connect(mSAKProcess, TQT_SIGNAL(processExited(TDEProcess*)), this, TQT_SLOT(slotSAKProcessExited())); - mSAKProcess->start(); -} - -void SAKDlg::slotSAKProcessExited() -{ - int retcode = mSAKProcess->exitStatus(); - if (retcode != 0) { - trinity_desktop_lock_use_sak = false; - } - hide(); -} - -SAKDlg::~SAKDlg() -{ - if ((mSAKProcess) && (mSAKProcess->isRunning())) { - mSAKProcess->kill(SIGKILL); - delete mSAKProcess; - } - hide(); -} - -void SAKDlg::closeDialogForced() -{ - TQDialog::reject(); -} - -void SAKDlg::reject() -{ - -} - -void SAKDlg::updateLabel(TQString &txt) -{ - mStatusLabel->setPaletteForegroundColor(Qt::black); - mStatusLabel->setText("" + txt + ""); -} - -void SAKDlg::show() -{ - TQDialog::show(); - TQApplication::flushX(); -} - -#include "sakdlg.moc" diff --git a/kdesktop/lock/sakdlg.cpp b/kdesktop/lock/sakdlg.cpp new file mode 100644 index 000000000..803c77919 --- /dev/null +++ b/kdesktop/lock/sakdlg.cpp @@ -0,0 +1,155 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 2010 - 2015 Timothy Pearson + +#include + +#include "sakdlg.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_use_sak; + +//=========================================================================== +// +// Simple dialog for displaying an unlock status or recurring error message +// +SAKDlg::SAKDlg(LockProcess *parent) + : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Desktop Session Locked")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + frame->setFrameStyle( TQFrame::NoFrame ); + } + else { + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + } + frame->setLineWidth( 2 ); + + KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); + + KUser user; + + mStatusLabel = new TQLabel( " ", frame ); + mStatusLabel->setAlignment( TQLabel::AlignVCenter ); + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mStatusLabel ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, AlignTop | AlignLeft ); + frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter); + + mStatusLabel->setText("" + i18n("Press Ctrl+Alt+Del to begin.") + "

" + i18n("This process helps keep your password secure.") + "
" + i18n("It prevents unauthorized users from emulating the login screen.")); + + installEventFilter(this); + setFixedSize( sizeHint() ); + + mSAKProcess = new TDEProcess; + *mSAKProcess << "tdmtsak"; + connect(mSAKProcess, TQT_SIGNAL(processExited(TDEProcess*)), this, TQT_SLOT(slotSAKProcessExited())); + mSAKProcess->start(); +} + +void SAKDlg::slotSAKProcessExited() +{ + int retcode = mSAKProcess->exitStatus(); + if (retcode != 0) { + trinity_desktop_lock_use_sak = false; + } + hide(); +} + +SAKDlg::~SAKDlg() +{ + if ((mSAKProcess) && (mSAKProcess->isRunning())) { + mSAKProcess->kill(SIGKILL); + delete mSAKProcess; + } + hide(); +} + +void SAKDlg::closeDialogForced() +{ + TQDialog::reject(); +} + +void SAKDlg::reject() +{ + +} + +void SAKDlg::updateLabel(TQString &txt) +{ + mStatusLabel->setPaletteForegroundColor(Qt::black); + mStatusLabel->setText("" + txt + ""); +} + +void SAKDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "sakdlg.moc" diff --git a/kdesktop/lock/securedlg.cc b/kdesktop/lock/securedlg.cc deleted file mode 100644 index fca79a707..000000000 --- a/kdesktop/lock/securedlg.cc +++ /dev/null @@ -1,217 +0,0 @@ -//=========================================================================== -// -// This file is part of the TDE project -// -// Copyright (c) 2010 - 2015 Timothy Pearson - -#include - -#include "securedlg.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifndef AF_LOCAL -# define AF_LOCAL AF_UNIX -#endif - -extern bool trinity_desktop_lock_use_system_modal_dialogs; -extern bool trinity_desktop_lock_use_sak; - -//=========================================================================== -// -// Simple dialog for displaying an unlock status or recurring error message -// -SecureDlg::SecureDlg(LockProcess *parent) - : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), - mUnlockingFailed(false), retInt(NULL) -{ - if (trinity_desktop_lock_use_system_modal_dialogs) { - // Signal that we do not want any window controls to be shown at all - Atom kde_wm_system_modal_notification; - kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); - XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); - } - setCaption(i18n("Secure Desktop Area")); - - frame = new TQFrame( this ); - if (trinity_desktop_lock_use_system_modal_dialogs) { - frame->setFrameStyle( TQFrame::NoFrame ); - } - else { - frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); - } - frame->setLineWidth( 2 ); - - KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); - - KUser user; - - mLogonStatus = new TQLabel( frame ); - TQString userString = user.fullName(); - if (userString == "") { - userString = user.loginName(); - } - if (userString != "") { - mLogonStatus->setText(i18n("'%1' is currently logged on").arg( user.fullName() )); - } - else { - mLogonStatus->setText(i18n("You are currently logged on")); // We should never get here, and this message is somewhat obtuse, but it is better than displaying two qotation marks with no text between them... - } - - KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); - - mLockButton = new TQPushButton( frame ); - mLockButton->setText(i18n("Lock Session")); - - mTaskButton = new TQPushButton( frame ); - mTaskButton->setText(i18n("Task Manager")); - - mShutdownButton = new TQPushButton( frame ); - mShutdownButton->setText(i18n("Logoff Menu")); - - mCancelButton = new TQPushButton( frame ); - mCancelButton->setText(i18n("Cancel")); - - mSwitchButton = new TQPushButton( frame ); - mSwitchButton->setText(i18n("Switch User")); - mSwitchButton->setEnabled(false); // FIXME - - TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); - unlockDialogLayout->addWidget( frame ); - - TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); - layStatus->addWidget( mLogonStatus ); - - TQGridLayout *layPBGrid = new TQGridLayout( 0, 0, KDialog::spacingHint()); - layPBGrid->addWidget( mLockButton, 0, 0 ); - layPBGrid->addWidget( mTaskButton, 0, 1 ); - layPBGrid->addWidget( mShutdownButton, 0, 2 ); - layPBGrid->addWidget( mCancelButton, 0, 3 ); - layPBGrid->addWidget( mSwitchButton, 1, 0 ); - - frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); - frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, AlignTop | AlignLeft ); - frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter); - frameLayout->addMultiCellWidget( sep, 2, 2, 0, 1 ); - frameLayout->addMultiCellLayout( layPBGrid, 3, 3, 0, 1, AlignLeft | AlignVCenter); - - connect(mCancelButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnCancel())); - connect(mLockButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnLock())); - connect(mTaskButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnTask())); - connect(mShutdownButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnShutdown())); - connect(mSwitchButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnSwitchUser())); - - TQSize dlgSz = sizeHint(); - int btnSize = dlgSz.width(); - btnSize = btnSize / 4; - btnSize = btnSize - (KDialog::spacingHint() / 2); - mLockButton->setFixedWidth(btnSize); - mTaskButton->setFixedWidth(btnSize); - mCancelButton->setFixedWidth(btnSize); - mShutdownButton->setFixedWidth(btnSize); - mSwitchButton->setFixedWidth(btnSize); - - installEventFilter(this); - setFixedSize( sizeHint() ); -} - -SecureDlg::~SecureDlg() -{ - hide(); -} - -void SecureDlg::slotBtnCancel() -{ - if (retInt) *retInt = 0; - hide(); -} - -void SecureDlg::slotBtnLock() -{ - if (retInt) *retInt = 1; - hide(); -} - -void SecureDlg::slotBtnTask() -{ - if (retInt) *retInt = 2; - hide(); -} - -void SecureDlg::slotBtnShutdown() -{ - if (retInt) *retInt = 3; - hide(); -} - -void SecureDlg::slotBtnSwitchUser() -{ - if (retInt) *retInt = 4; - hide(); -} - -void SecureDlg::setRetInt(int *i) -{ - retInt = i; -} - -void SecureDlg::closeDialogForced() -{ - if (retInt) *retInt = 0; - TQDialog::reject(); -} - -void SecureDlg::reject() -{ - closeDialogForced(); -} - -void SecureDlg::show() -{ - TQDialog::show(); - TQApplication::flushX(); -} - -#include "securedlg.moc" diff --git a/kdesktop/lock/securedlg.cpp b/kdesktop/lock/securedlg.cpp new file mode 100644 index 000000000..fca79a707 --- /dev/null +++ b/kdesktop/lock/securedlg.cpp @@ -0,0 +1,217 @@ +//=========================================================================== +// +// This file is part of the TDE project +// +// Copyright (c) 2010 - 2015 Timothy Pearson + +#include + +#include "securedlg.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_use_sak; + +//=========================================================================== +// +// Simple dialog for displaying an unlock status or recurring error message +// +SecureDlg::SecureDlg(LockProcess *parent) + : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false), retInt(NULL) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(tqt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Secure Desktop Area")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) { + frame->setFrameStyle( TQFrame::NoFrame ); + } + else { + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + } + frame->setLineWidth( 2 ); + + KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); + + KUser user; + + mLogonStatus = new TQLabel( frame ); + TQString userString = user.fullName(); + if (userString == "") { + userString = user.loginName(); + } + if (userString != "") { + mLogonStatus->setText(i18n("'%1' is currently logged on").arg( user.fullName() )); + } + else { + mLogonStatus->setText(i18n("You are currently logged on")); // We should never get here, and this message is somewhat obtuse, but it is better than displaying two qotation marks with no text between them... + } + + KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); + + mLockButton = new TQPushButton( frame ); + mLockButton->setText(i18n("Lock Session")); + + mTaskButton = new TQPushButton( frame ); + mTaskButton->setText(i18n("Task Manager")); + + mShutdownButton = new TQPushButton( frame ); + mShutdownButton->setText(i18n("Logoff Menu")); + + mCancelButton = new TQPushButton( frame ); + mCancelButton->setText(i18n("Cancel")); + + mSwitchButton = new TQPushButton( frame ); + mSwitchButton->setText(i18n("Switch User")); + mSwitchButton->setEnabled(false); // FIXME + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mLogonStatus ); + + TQGridLayout *layPBGrid = new TQGridLayout( 0, 0, KDialog::spacingHint()); + layPBGrid->addWidget( mLockButton, 0, 0 ); + layPBGrid->addWidget( mTaskButton, 0, 1 ); + layPBGrid->addWidget( mShutdownButton, 0, 2 ); + layPBGrid->addWidget( mCancelButton, 0, 3 ); + layPBGrid->addWidget( mSwitchButton, 1, 0 ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, AlignTop | AlignLeft ); + frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter); + frameLayout->addMultiCellWidget( sep, 2, 2, 0, 1 ); + frameLayout->addMultiCellLayout( layPBGrid, 3, 3, 0, 1, AlignLeft | AlignVCenter); + + connect(mCancelButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnCancel())); + connect(mLockButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnLock())); + connect(mTaskButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnTask())); + connect(mShutdownButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnShutdown())); + connect(mSwitchButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnSwitchUser())); + + TQSize dlgSz = sizeHint(); + int btnSize = dlgSz.width(); + btnSize = btnSize / 4; + btnSize = btnSize - (KDialog::spacingHint() / 2); + mLockButton->setFixedWidth(btnSize); + mTaskButton->setFixedWidth(btnSize); + mCancelButton->setFixedWidth(btnSize); + mShutdownButton->setFixedWidth(btnSize); + mSwitchButton->setFixedWidth(btnSize); + + installEventFilter(this); + setFixedSize( sizeHint() ); +} + +SecureDlg::~SecureDlg() +{ + hide(); +} + +void SecureDlg::slotBtnCancel() +{ + if (retInt) *retInt = 0; + hide(); +} + +void SecureDlg::slotBtnLock() +{ + if (retInt) *retInt = 1; + hide(); +} + +void SecureDlg::slotBtnTask() +{ + if (retInt) *retInt = 2; + hide(); +} + +void SecureDlg::slotBtnShutdown() +{ + if (retInt) *retInt = 3; + hide(); +} + +void SecureDlg::slotBtnSwitchUser() +{ + if (retInt) *retInt = 4; + hide(); +} + +void SecureDlg::setRetInt(int *i) +{ + retInt = i; +} + +void SecureDlg::closeDialogForced() +{ + if (retInt) *retInt = 0; + TQDialog::reject(); +} + +void SecureDlg::reject() +{ + closeDialogForced(); +} + +void SecureDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "securedlg.moc" -- cgit v1.2.1