branches/KDE/3.5/kdelibs/kio/misc/kwalletd
Luboš Luňák
l.lunak at kde.org
Tue Aug 29 16:09:38 BST 2006
SVN commit 578532 by lunakl:
Replace the wallet dialog hacks that were supposed to work around #91940
and caused #113057 with slightly better hacks. If somebody notices
some problems with kwallet dialogs after this change please yell.
CCMAIL: kde-core-devel at kde.org
BUG: 113057
M +50 -26 kwalletd.cpp
M +7 -2 kwalletd.h
--- branches/KDE/3.5/kdelibs/kio/misc/kwalletd/kwalletd.cpp #578531:578532
@@ -50,10 +50,6 @@
#include <assert.h>
-#ifdef Q_WS_X11
-#include <X11/Xlib.h>
-#endif
-
extern "C" {
KDE_EXPORT KDEDModule *create_kwalletd(const QCString &name) {
return new KWalletD(name);
@@ -67,6 +63,7 @@
tType = Unknown;
transaction = 0L;
client = 0L;
+ modal = false;
}
~KWalletTransaction() {
@@ -83,6 +80,7 @@
QCString appid;
uint wId;
QString wallet;
+ bool modal;
};
@@ -149,7 +147,7 @@
switch (xact->tType) {
case KWalletTransaction::Open:
- res = doTransactionOpen(xact->appid, xact->wallet, xact->wId);
+ res = doTransactionOpen(xact->appid, xact->wallet, xact->wId, xact->modal);
replyType = "int";
if (!xact->returnObject.isEmpty()) {
DCOPRef(xact->rawappid, xact->returnObject).send("walletOpenResult", res);
@@ -232,6 +230,7 @@
DCOPRef(appid, returnObject).send("walletOpenResult", 0);
QTimer::singleShot(0, this, SLOT(processTransactions()));
+ checkActiveDialog();
}
@@ -266,18 +265,53 @@
xact->wallet = wallet;
xact->wId = wId;
xact->tType = KWalletTransaction::Open;
+ xact->modal = true; // mark dialogs as modal, the app has blocking wait
QTimer::singleShot(0, this, SLOT(processTransactions()));
+ checkActiveDialog();
return 0; // process later
}
-int KWalletD::doTransactionOpen(const QCString& appid, const QString& wallet, uint wId) {
+// Sets up a dialog that will be shown by kwallet.
+void KWalletD::setupDialog( QWidget* dialog, WId wId, const QCString& appid, bool modal ) {
+ if( wId != 0 )
+ KWin::setMainWindow( dialog, wId ); // correct, set dialog parent
+ else {
+ if( appid.isEmpty())
+ kdWarning() << "Using kwallet without parent window!" << endl;
+ else
+ kdWarning() << "Application '" << appid << "' using kwallet without parent window!" << endl;
+ // allow dialog activation even if it interrupts, better than trying hacks
+ // with keeping the dialog on top or on all desktops
+ kapp->updateUserTimestamp();
+ }
+ if( modal )
+ KWin::setState( dialog->winId(), NET::Modal );
+ else
+ KWin::clearState( dialog->winId(), NET::Modal );
+ activeDialog = dialog;
+}
+
+// If there's a dialog already open and another application tries some operation that'd lead to
+// opening a dialog, that application will be blocked by this dialog. A proper solution would
+// be to set the second application's window also as a parent for the active dialog, so that
+// KWin properly handles focus changes and so on, but there's currently no support for multiple
+// dialog parents. Hopefully to be done in KDE4, for now just use all kinds of bad hacks to make
+// sure the user doesn't overlook the active dialog.
+void KWalletD::checkActiveDialog() {
+ if( !activeDialog || !activeDialog->isShown())
+ return;
+ kapp->updateUserTimestamp();
+ KWin::setState( activeDialog->winId(), NET::KeepAbove );
+ KWin::setOnAllDesktops( activeDialog->winId(), true );
+ KWin::forceActiveWindow( activeDialog->winId());
+}
+
+int KWalletD::doTransactionOpen(const QCString& appid, const QString& wallet, uint wId, bool modal) {
if (_firstUse && !wallets().contains(KWallet::Wallet::LocalWallet())) {
// First use wizard
KWalletWizard *wiz = new KWalletWizard(0);
-#ifdef Q_WS_X11
- XSetTransientForHint(qt_xdisplay(), wiz->winId(), wId);
-#endif
+ setupDialog( wiz, wId, appid, modal );
int rc = wiz->exec();
if (rc == QDialog::Accepted) {
KConfig cfg("kwalletrc");
@@ -317,12 +351,12 @@
cfg.sync();
}
- int rc = internalOpen(appid, wallet, false, wId);
+ int rc = internalOpen(appid, wallet, false, wId, modal);
return rc;
}
-int KWalletD::internalOpen(const QCString& appid, const QString& wallet, bool isPath, WId w) {
+int KWalletD::internalOpen(const QCString& appid, const QString& wallet, bool isPath, WId w, bool modal) {
int rc = -1;
bool brandNew = false;
@@ -402,11 +436,7 @@
const char *p = 0L;
while (!b->isOpen()) {
assert(kpd); // kpd can't be null if isOpen() is false
-#ifdef Q_WS_X11
- XSetTransientForHint(qt_xdisplay(), kpd->winId(), w);
-#endif
- KWin::setState( kpd->winId(), NET::KeepAbove );
- KWin::setOnAllDesktops(kpd->winId(), true);
+ setupDialog( kpd, w, appid, modal );
if (kpd->exec() == KDialog::Accepted) {
p = kpd->password();
int rc = b->open(QByteArray().duplicate(p, strlen(p)));
@@ -489,12 +519,7 @@
} else {
dialog->setLabel(i18n("<qt>The application '<b>%1</b>' has requested access to the open wallet '<b>%2</b>'.").arg(QStyleSheet::escape(QString(appid))).arg(QStyleSheet::escape(wallet)));
}
-#ifdef Q_WS_X11
- XSetTransientForHint(qt_xdisplay(), dialog->winId(), w);
-#endif
- KWin::setState(dialog->winId(), NET::KeepAbove);
- KWin::setOnAllDesktops(dialog->winId(), true);
-
+ setupDialog( dialog, w, appid, false );
response = dialog->exec();
delete dialog;
}
@@ -560,6 +585,7 @@
_transactions.append(xact);
QTimer::singleShot(0, this, SLOT(processTransactions()));
+ checkActiveDialog();
}
@@ -576,7 +602,7 @@
}
if (!it.current()) {
- handle = doTransactionOpen(appid, wallet, wId);
+ handle = doTransactionOpen(appid, wallet, wId,false);
if (-1 == handle) {
KMessageBox::sorryWId(wId, i18n("Unable to open wallet. The wallet must be opened in order to change the password."), i18n("KDE Wallet Service"));
return;
@@ -596,9 +622,7 @@
kpd->setPrompt(i18n("<qt>Please choose a new password for the wallet '<b>%1</b>'.").arg(QStyleSheet::escape(wallet)));
kpd->setCaption(i18n("KDE Wallet Service"));
kpd->setAllowEmptyPasswords(true);
-#ifdef Q_WS_X11
- XSetTransientForHint(qt_xdisplay(), kpd->winId(), wId);
-#endif
+ setupDialog( kpd, wId, appid, false );
if (kpd->exec() == KDialog::Accepted) {
const char *p = kpd->password();
if (p) {
--- branches/KDE/3.5/kdelibs/kio/misc/kwalletd/kwalletd.h #578531:578532
@@ -26,6 +26,7 @@
#include <qintdict.h>
#include <qstring.h>
#include <qwidget.h>
+#include <qguardedptr.h>
#include "kwalletbackend.h"
#include <time.h>
@@ -150,7 +151,7 @@
void processTransactions();
private:
- int internalOpen(const QCString& appid, const QString& wallet, bool isPath = false, WId w = 0);
+ int internalOpen(const QCString& appid, const QString& wallet, bool isPath = false, WId w = 0, bool modal = false);
bool isAuthorizedApp(const QCString& appid, const QString& wallet, WId w);
// This also validates the handle. May return NULL.
KWallet::Backend* getWallet(const QCString& appid, int handle);
@@ -169,8 +170,11 @@
QCString friendlyDCOPPeerName();
void doTransactionChangePassword(const QCString& appid, const QString& wallet, uint wId);
- int doTransactionOpen(const QCString& appid, const QString& wallet, uint wId);
+ int doTransactionOpen(const QCString& appid, const QString& wallet, uint wId, bool modal);
+ void setupDialog( QWidget* dialog, WId wId, const QCString& appid, bool modal );
+ void checkActiveDialog();
+
QIntDict<KWallet::Backend> _wallets;
QMap<QCString,QValueList<int> > _handles;
QMap<QString,QCString> _passwords;
@@ -184,6 +188,7 @@
KTimeout *_timeouts;
QPtrList<KWalletTransaction> _transactions;
+ QGuardedPtr< QWidget > activeDialog;
};
More information about the kde-core-devel
mailing list