author | zecke <zecke> | 2003-09-03 18:58:20 (UTC) |
---|---|---|
committer | zecke <zecke> | 2003-09-03 18:58:20 (UTC) |
commit | 3038503f6ffc2d58b00650d5feae23cc8e842bcb (patch) (side-by-side diff) | |
tree | 33b2b319307b9a5abda47b51c31329131295d703 | |
parent | 577cdc4f2ce81eaceb132af08d8ab6fe12b4eadc (diff) | |
download | opie-3038503f6ffc2d58b00650d5feae23cc8e842bcb.zip opie-3038503f6ffc2d58b00650d5feae23cc8e842bcb.tar.gz opie-3038503f6ffc2d58b00650d5feae23cc8e842bcb.tar.bz2 |
Failure free restart of the launcher and a comment
why we do that
-rw-r--r-- | core/launcher/serverapp.cpp | 19 | ||||
-rw-r--r-- | core/launcher/systray.cpp | 8 | ||||
-rw-r--r-- | core/launcher/systray.h | 1 |
3 files changed, 28 insertions, 0 deletions
diff --git a/core/launcher/serverapp.cpp b/core/launcher/serverapp.cpp index 522ef07..28316a4 100644 --- a/core/launcher/serverapp.cpp +++ b/core/launcher/serverapp.cpp @@ -470,344 +470,363 @@ void ServerApplication::launcherMessage( const QCString & msg, const QByteArray bool ServerApplication::screenLocked() { return loggedin == 0; } void ServerApplication::login(bool at_poweron) { if ( !loggedin ) { Global::terminateBuiltin("calibrate"); // No tr Password::authenticate(at_poweron); loggedin=1; #ifndef QT_NO_COP QCopEnvelope e( "QPE/Desktop", "unlocked()" ); #endif } } #if defined(QPE_HAVE_TOGGLELIGHT) #include <qtopia/config.h> #include <sys/ioctl.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <linux/ioctl.h> #include <time.h> #endif #if 0 static bool blanked=FALSE; static void blankScreen() { #ifdef QWS QWidget w(0, 0, Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool | Qt::WStyle_StaysOnTop | Qt::WPaintUnclipped); w.resize( qt_screen->width(), qt_screen->height() ); w.move(0, 0); QPainter p(&w); p.fillRect(w.rect(), QBrush(QColor(255,255,255)) ); p.end(); w.repaint(); blanked = TRUE; #endif } static void darkScreen() { /* ### Screen blanking ODevice */ #if 0 qpe_setBacklight(0); // force off #endif } #endif namespace { void execAutoStart(const QDateTime& suspendTime ) { QString appName; int delay; QDateTime now = QDateTime::currentDateTime(); Config cfg( "autostart" ); cfg.setGroup( "AutoStart" ); appName = cfg.readEntry( "Apps", "" ); delay = cfg.readNumEntry( "Delay", 0 ); // If the time between suspend and resume was longer then the // value saved as delay, start the app if ( suspendTime.secsTo( now ) >= ( delay * 60 ) && !appName.isEmpty() ) { QCopEnvelope e( "QPE/System", "execute(QString)" ); e << QString( appName ); } } } void ServerApplication::togglePower() { static bool excllock = false; if ( excllock ) return ; excllock = true; bool wasloggedin = loggedin; loggedin = 0; m_suspendTime = QDateTime::currentDateTime(); #ifdef QWS if ( Password::needToAuthenticate ( true ) && qt_screen ) { // Should use a big black window instead. // But this would not show up fast enough QGfx *g = qt_screen-> screenGfx ( ); g-> fillRect ( 0, 0, qt_screen-> width ( ), qt_screen-> height ( )); delete g; } #endif ODevice::inst ( )-> suspend ( ); ServerApplication::switchLCD ( true ); // force LCD on without slow qcop call QWSServer::screenSaverActivate ( false ); { QCopEnvelope( "QPE/Card", "mtabChanged()" ); // might have changed while asleep } if ( wasloggedin ) login ( true ); execAutoStart(m_suspendTime); //qcopBridge->closeOpenConnections(); excllock = false; } void ServerApplication::toggleLight() { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "setBacklight(int)"); e << -2; // toggle #endif } /* * We still listen to key events but handle them in * a special class */ bool ServerApplication::eventFilter( QObject *o, QEvent *e) { if ( e->type() != QEvent::KeyPress && e->type() != QEvent::KeyRelease ) return QPEApplication::eventFilter( o, e ); QKeyEvent *ke = static_cast<QKeyEvent*>( e ); if ( kf->checkButtonAction( true, ke->key(), e->type() == QEvent::KeyPress, ke-> isAutoRepeat() )) return true; return QPEApplication::eventFilter( o, e ); } #ifdef Q_WS_QWS bool ServerApplication::qwsEventFilter( QWSEvent *e ) { checkMemory(); if ( e->type == QWSEvent::Mouse ) { QWSMouseEvent *me = (QWSMouseEvent *)e; static bool up = TRUE; if ( me->simpleData.state&LeftButton ) { if ( up ) { up = FALSE; screenClick(TRUE); } } else if ( !up ) { up = TRUE; screenClick(FALSE); } }else if ( e->type == QWSEvent::Key ) { QWSKeyEvent * ke = static_cast<QWSKeyEvent*>( e ); if ( kf->checkButtonAction( false, ke-> simpleData.keycode, ke-> simpleData.is_press, ke-> simpleData.is_auto_repeat ) ) return true; } return QPEApplication::qwsEventFilter( e ); } #endif /* ### FIXME libqtopia Plugin Safe Mode */ void ServerApplication::showSafeMode() { #if 0 if ( QMessageBox::warning(0, tr("Safe Mode"), tr("<P>A system startup error occurred, " "and the system is now in Safe Mode. " "Plugins are not loaded in Safe Mode. " "You can use the Plugin Manager to " "disable plugins that cause system error."), tr("OK"), tr("Plugin Manager..."), 0) == 1 ) { Global::execute( "pluginmanager" ); } #endif } void ServerApplication::clearSafeMode() { #if 0 // If we've been running OK for a while then we won't bother going into // safe mode immediately on the next crash. Config cfg( "PluginLoader" ); cfg.setGroup( "Global" ); QString mode = cfg.readEntry( "Mode", "Normal" ); if ( mode == "MaybeSafe" ) { cfg.writeEntry( "Mode", "Normal" ); } #endif } void ServerApplication::shutdown() { if ( type() != GuiServer ) return; ShutdownImpl *sd = new ShutdownImpl( 0, 0, WDestructiveClose ); connect( sd, SIGNAL(shutdown(ShutdownImpl::Type)), this, SLOT(shutdown(ShutdownImpl::Type)) ); sd->showMaximized(); } void ServerApplication::shutdown( ShutdownImpl::Type t ) { char *opt = 0; switch ( t ) { case ShutdownImpl::ShutdownSystem: opt = "-h"; // fall through case ShutdownImpl::RebootSystem: if ( opt == 0 ) opt = "-r"; if ( execl( "/sbin/shutdown", "shutdown", opt, "now", ( void* ) 0) < 0 ) perror("shutdown"); // ::syslog ( LOG_ERR, "Erroring execing shutdown\n" ); break; case ShutdownImpl::RestartDesktop: restart(); break; case ShutdownImpl::TerminateDesktop: prepareForTermination( FALSE ); // This is a workaround for a Qt bug // clipboard applet has to stop its poll timer, or Qt/E // will hang on quit() right before it emits aboutToQuit() emit aboutToQuit ( ); quit(); break; } } void ServerApplication::restart() { if ( allowRestart ) { + + /* + * Applets and restart is a problem. Some applets delete + * their widgets even if ownership gets transfered to the + * parent (Systray ) but deleting the applet may be unsafe + * as well ( double deletion ). Some have topLevel widgets + * and when we dlclose and then delete the widget we will + * crash and an crash during restart is not nice + */ +#ifdef ALL_APPLETS_ON_THIS_WORLD_ARE_FIXED + /* same as above */ + emit aboutToQuit(); prepareForTermination(TRUE); doRestart = TRUE; quit(); +#else + prepareForTermination( true ); + for ( int fd = 3; fd < 100; fd++ ) + close( fd ); + execl( ( qpeDir() + "/bin/qpe" ).latin1(), "qpe", 0 ); + exit( 1 ); +#endif } } void ServerApplication::rereadVolumes() { Config cfg( "qpe" ); cfg. setGroup ( "Volume" ); m_screentap_sound = cfg. readBoolEntry ( "TouchSound" ); m_keyclick_sound = cfg. readBoolEntry ( "KeySound" ); m_alarm_sound = cfg. readBoolEntry ( "AlarmSound" ); } void ServerApplication::checkMemory() { #if defined(QPE_HAVE_MEMALERTER) static bool ignoreNormal=TRUE; static bool existingMessage=FALSE; if(existingMessage) return; // don't show a second message while still on first existingMessage = TRUE; switch ( memstate ) { case MemUnknown: break; case MemLow: memstate = MemUnknown; if ( !recoverMemory() ) { QMessageBox::warning( 0 , tr("Memory Status"), tr("Memory Low\nPlease save data.") ); ignoreNormal = FALSE; } break; case MemNormal: memstate = MemUnknown; if ( !ignoreNormal ) { ignoreNormal = TRUE; QMessageBox::information ( 0 , tr("Memory Status"), "Memory OK" ); } break; case MemVeryLow: memstate = MemUnknown; QMessageBox::critical( 0 , tr("Memory Status"), tr("Critical Memory Shortage\n" "Please end this application\n" "immediately.") ); recoverMemory(); } existingMessage = FALSE; #endif } bool ServerApplication::recoverMemory() { return FALSE; } void ServerApplication::keyClick(int , bool press, bool ) { if ( press && m_keyclick_sound ) ODevice::inst() -> keySound(); } void ServerApplication::screenClick(bool press) { if ( press && m_screentap_sound ) ODevice::inst() -> touchSound(); } void ServerApplication::soundAlarm() { if ( me ()->m_alarm_sound ) ODevice::inst()->alarmSound(); } ServerApplication *ServerApplication::me ( ) { return static_cast<ServerApplication*>( qApp ); } #include "serverapp.moc" diff --git a/core/launcher/systray.cpp b/core/launcher/systray.cpp index 64356ca..6122770 100644 --- a/core/launcher/systray.cpp +++ b/core/launcher/systray.cpp @@ -1,141 +1,149 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include <qtopia/qpeapplication.h> #include <qtopia/qlibrary.h> #include <qtopia/config.h> #include <qlayout.h> #include <qdir.h> #include <qmessagebox.h> #include <qtranslator.h> #include "systray.h" #include <stdlib.h> /* ### Single build floppies ### */ #if 0 #ifdef QT_NO_COMPONENTS #include "../plugins/applets/clockapplet/clockappletimpl.h" #endif #endif SysTray::SysTray( QWidget *parent ) : QFrame( parent ), layout(0) { //setFrameStyle( QFrame::Panel | QFrame::Sunken ); loadApplets(); } SysTray::~SysTray() { clearApplets(); } static int compareAppletPositions(const void *a, const void *b) { const TaskbarApplet* aa = *(const TaskbarApplet**)a; const TaskbarApplet* ab = *(const TaskbarApplet**)b; int d = ab->iface->position() - aa->iface->position(); if ( d ) return d; return QString::compare(ab->name,aa->name); } void SysTray::loadApplets() { hide(); clearApplets(); addApplets(); } void SysTray::clearApplets() { #ifndef QT_NO_COMPONENTS + /* + * Note on clearing. SOme applets delete their + * applets themselves some don't do it + * and on restart this can crash. If we delete it + * here we might end up in a double deletion. We could + * use QGuardedPtr but that would be one QOBject + * for every applet more but only useful for restart + */ QValueList<TaskbarApplet>::Iterator mit; for ( mit = appletList.begin(); mit != appletList.end(); ++mit ) { (*mit).iface->release(); (*mit).library->unload(); delete (*mit).library; } #endif appletList.clear(); if ( layout ) delete layout; layout = new QHBoxLayout( this, 0, 1 ); layout->setAutoAdd(TRUE); } void SysTray::addApplets() { hide(); #ifndef QT_NO_COMPONENTS Config cfg( "Taskbar" ); cfg.setGroup( "Applets" ); QStringList exclude = cfg.readListEntry( "ExcludeApplets", ',' ); QString lang = getenv( "LANG" ); QString path = QPEApplication::qpeDir() + "/plugins/applets"; QDir dir( path, "lib*.so" ); QStringList list = dir.entryList(); QStringList::Iterator it; int napplets=0; TaskbarApplet* *applets = new TaskbarApplet*[list.count()]; for ( it = list.begin(); it != list.end(); ++it ) { if ( exclude.find( *it ) != exclude.end() ) continue; TaskbarAppletInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if (( lib->queryInterface( IID_TaskbarApplet, (QUnknownInterface**)&iface ) == QS_OK ) && iface ) { TaskbarApplet *applet = new TaskbarApplet; applets[napplets++] = applet; applet->library = lib; applet->iface = iface; QTranslator *trans = new QTranslator(qApp); QString type = (*it).left( (*it).find(".") ); QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/"+type+".qm"; if ( trans->load( tfn )) qApp->installTranslator( trans ); else delete trans; } else { exclude += *it; delete lib; } } cfg.writeEntry( "ExcludeApplets", exclude, ',' ); qsort(applets,napplets,sizeof(applets[0]),compareAppletPositions); while (napplets--) { TaskbarApplet *applet = applets[napplets]; applet->applet = applet->iface->applet( this ); appletList.append(*applet); } delete [] applets; #else /* ## FIXME single app */ TaskbarApplet * const applet = new TaskbarApplet(); applet->iface = new ClockAppletImpl(); applet->applet = applet->iface->applet( this ); appletList.append( applet ); #endif show(); } diff --git a/core/launcher/systray.h b/core/launcher/systray.h index 77c581f..b989d58 100644 --- a/core/launcher/systray.h +++ b/core/launcher/systray.h @@ -1,61 +1,62 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __SYSTRAY_H__ #define __SYSTRAY_H__ #ifndef QT_NO_COMPONENT #include <qtopia/taskbarappletinterface.h> #endif #include <qframe.h> #include <qvaluelist.h> +#include <qguardedptr.h> class QHBoxLayout; class QLibrary; struct TaskbarApplet { #ifndef QT_NO_COMPONENT QLibrary *library; TaskbarAppletInterface *iface; #endif QWidget *applet; QString name; }; class SysTray : public QFrame { Q_OBJECT public: SysTray( QWidget *parent ); ~SysTray(); void clearApplets(); void addApplets(); private: void loadApplets(); QHBoxLayout *layout; QValueList<TaskbarApplet> appletList; }; #endif // __SYSTRAY_H__ |