-rw-r--r-- | library/qpeapplication.cpp | 144 | ||||
-rw-r--r-- | library/qpeapplication.h | 3 |
2 files changed, 66 insertions, 81 deletions
diff --git a/library/qpeapplication.cpp b/library/qpeapplication.cpp index bf353d4..86aa53d 100644 --- a/library/qpeapplication.cpp +++ b/library/qpeapplication.cpp @@ -69,150 +69,150 @@ #endif #include "global.h" #include "resource.h" #if QT_VERSION <= 230 && defined(QT_NO_CODECS) #include "qutfcodec.h" #endif #include "config.h" #include "network.h" #ifdef QWS #include "fontmanager.h" #endif #include "alarmserver.h" #include "applnk.h" #include "qpemenubar.h" #include "textcodecinterface.h" #include "imagecodecinterface.h" #include <unistd.h> #include <sys/file.h> #include <sys/ioctl.h> #include <sys/soundcard.h> #include "qt_override_p.h" class QPEApplicationData { public: QPEApplicationData ( ) : presstimer( 0 ), presswidget( 0 ), rightpressed( false ), kbgrabbed( false ), notbusysent( false ), preloaded( false ), forceshow( false ), nomaximize( false ), keep_running( true ), qpe_main_widget( 0 ) { qcopq.setAutoDelete( TRUE ); } int presstimer; QWidget* presswidget; QPoint presspos; bool rightpressed : 1; bool kbgrabbed : 1; bool notbusysent : 1; bool preloaded : 1; bool forceshow : 1; bool nomaximize : 1; bool keep_running : 1; QStringList langs; QString appName; struct QCopRec { QCopRec( const QCString &ch, const QCString &msg, const QByteArray &d ) : channel( ch ), message( msg ), data( d ) { } QCString channel; QCString message; QByteArray data; }; QWidget* qpe_main_widget; - QGuardedPtr<QWidget> lastWidget; + QGuardedPtr<QWidget> lastraised; QList<QCopRec> qcopq; QString styleName; QString decorationName; void enqueueQCop( const QCString &ch, const QCString &msg, const QByteArray &data ) { qcopq.append( new QCopRec( ch, msg, data ) ); } void sendQCopQ() { QCopRec * r; #ifndef QT_NO_COP for ( QListIterator<QCopRec> it( qcopq ); ( r = it.current() ); ++it ) QCopChannel::sendLocally( r->channel, r->message, r->data ); #endif qcopq.clear(); } - static void show_mx(QWidget* mw, bool nomaximize) + static void show_mx(QWidget* mw, bool nomaximize, const QString & = QString::null ) { // ugly hack, remove that later after finding a sane solution // Addendum: Only Sharp currently has models with high resolution but (physically) small displays, // so this is only useful if QT_QWS_SIMPAD is NOT defined. E.g. SIMpad has 800x600 but has // a (physically) large enough display to use the small icons #ifndef QT_QWS_SIMPAD if ( QPEApplication::desktop() ->width() >= 600 && ( mw->inherits("QMainWindow") || mw->isA("QMainWindow") ) ) { ( ( QMainWindow* ) mw )->setUsesBigPixmaps( true ); } #endif if ( mw->layout() && mw->inherits("QDialog") ) { QPEApplication::showDialog((QDialog*)mw, nomaximize); } else { #ifdef Q_WS_QWS if ( !nomaximize ) mw->showMaximized(); else #endif mw->show(); } } static bool setWidgetCaptionFromAppName( QWidget* /*mw*/, const QString& /*appName*/, const QString& /*appsPath*/ ) { /* // This works but disable it for now until it is safe to apply // What is does is scan the .desktop files of all the apps for // the applnk that has the corresponding argv[0] as this program // then it uses the name stored in the .desktop file as the caption // for the main widget. This saves duplicating translations for // the app name in the program and in the .desktop files. AppLnkSet apps( appsPath ); QList<AppLnk> appsList = apps.children(); for ( QListIterator<AppLnk> it(appsList); it.current(); ++it ) { if ( (*it)->exec() == appName ) { mw->setCaption( (*it)->name() ); return TRUE; } } */ return FALSE; } void show(QWidget* mw, bool nomax) { setWidgetCaptionFromAppName( mw, appName, QPEApplication::qpeDir() + "apps" ); nomaximize = nomax; qpe_main_widget = mw; #ifndef QT_NO_COP sendQCopQ(); #endif if ( preloaded ) { if (forceshow) show_mx(mw, nomax); } else if ( keep_running ) { @@ -643,149 +643,152 @@ QPEApplication::QPEApplication( int & argc, char **argv, Type t ) a++; d->preloaded = TRUE; argc -= 1; } else if ( qstrcmp( argv[ a ], "-preload-show" ) == 0 ) { argv[ a ] = argv[ a + 1 ]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc -= 1; } } /* overide stored arguments */ setArgs( argc, argv ); #endif #else initApp( argc, argv ); #endif // qwsSetDecoration( new QPEDecoration() ); #ifndef QT_NO_TRANSLATION d->langs = Global::languageList(); for ( QStringList::ConstIterator it = d->langs.begin(); it != d->langs.end(); ++it ) { QString lang = *it; installTranslation( lang + "/libopie.qm"); installTranslation( lang + "/libqpe.qm" ); installTranslation( lang + "/" + d->appName + ".qm" ); //###language/font hack; should look it up somewhere #ifdef QWS if ( lang == "ja" || lang == "zh_CN" || lang == "zh_TW" || lang == "ko" ) { QFont fn = FontManager::unicodeFont( FontManager::Proportional ); setFont( fn ); } #endif } #endif applyStyle(); if ( type() == GuiServer ) { setVolume(); } installEventFilter( this ); QPEMenuToolFocusManager::initialize(); #ifdef QT_NO_QWS_CURSOR // if we have no cursor, probably don't want tooltips QToolTip::setEnabled( FALSE ); #endif } #ifdef QTOPIA_INTERNAL_INITAPP void QPEApplication::initApp( int argc, char **argv ) { + bool initial = pidChannel; // was set to 0 in the initializer delete pidChannel; d->keep_running = TRUE; d->preloaded = FALSE; d->forceshow = FALSE; QCString channel = QCString(argv[0]); channel.replace(QRegExp(".*/"),""); d->appName = channel; #if QT_VERSION > 235 qt_fbdpy->setIdentity( channel ); // In Qt/E 2.3.6 #endif channel = "QPE/Application/" + channel; pidChannel = new QCopChannel( channel, this); connect( pidChannel, SIGNAL(received(const QCString &, const QByteArray &)), this, SLOT(pidMessage(const QCString &, const QByteArray &))); + if (!initial) { processQCopFile(); d->keep_running = d->qcopq.isEmpty(); + } for (int a=0; a<argc; a++) { if ( qstrcmp(argv[a],"-preload")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; argc-=1; } else if ( qstrcmp(argv[a],"-preload-show")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc-=1; } } /* overide stored arguments */ setArgs(argc, argv); /* install translation here */ for ( QStringList::ConstIterator it = d->langs.begin(); it != d->langs.end(); ++it ) installTranslation( (*it) + "/" + d->appName + ".qm" ); } #endif static QPtrDict<void>* inputMethodDict = 0; static void createInputMethodDict() { if ( !inputMethodDict ) inputMethodDict = new QPtrDict<void>; } /*! Returns the currently set hint to the system as to whether widget \a w has any use for text input methods. \sa setInputMethodHint() InputMethodHint */ QPEApplication::InputMethodHint QPEApplication::inputMethodHint( QWidget * w ) { if ( inputMethodDict && w ) return ( InputMethodHint ) ( int ) inputMethodDict->find( w ); return Normal; } /*! \enum QPEApplication::InputMethodHint \value Normal the application sometimes needs text input (the default). \value AlwaysOff the application never needs text input. \value AlwaysOn the application always needs text input. */ /*! Hints to the system that widget \a w has use for text input methods as specified by \a mode. \sa inputMethodHint() InputMethodHint */ void QPEApplication::setInputMethodHint( QWidget * w, InputMethodHint mode ) { createInputMethodDict(); @@ -1301,219 +1304,204 @@ void QPEApplication::systemMessage( const QCString& msg, const QByteArray& data } else if ( msg == "setDateFormat(DateFormat)" ) { DateFormat tmp; stream >> tmp; emit dateFormatChanged( tmp ); } else if ( msg == "setVolume(int,int)" ) { int t, v; stream >> t >> v; setVolume( t, v ); emit volumeChanged( muted ); } else if ( msg == "volumeChange(bool)" ) { stream >> muted; setVolume(); emit volumeChanged( muted ); } else if ( msg == "setMic(int,int)" ) { // Added: 2002-02-08 by Jeremy Cowgar <jc@cowgar.com> int t, v; stream >> t >> v; setMic( t, v ); emit micChanged( micMuted ); } else if ( msg == "micChange(bool)" ) { // Added: 2002-02-08 by Jeremy Cowgar <jc@cowgar.com> stream >> micMuted; setMic(); emit micChanged( micMuted ); } else if ( msg == "setBass(int,int)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> int t, v; stream >> t >> v; setBass( t, v ); } else if ( msg == "bassChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setBass(); } else if ( msg == "setTreble(int,int)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> int t, v; stream >> t >> v; setTreble( t, v ); } else if ( msg == "trebleChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setTreble(); } else if ( msg == "getMarkedText()" ) { if ( type() == GuiServer ) { const ushort unicode = 'C'-'@'; const int scan = Key_C; qwsServer->processKeyEvent( unicode, scan, ControlButton, TRUE, FALSE ); qwsServer->processKeyEvent( unicode, scan, ControlButton, FALSE, FALSE ); } } else if ( msg == "newChannel(QString)") { QString myChannel = "QPE/Application/" + d->appName; QString channel; stream >> channel; if (channel == myChannel) { processQCopFile(); d->sendQCopQ(); } } #endif } -#include <qmetaobject.h> -QWidget *QPEApplication::nextWidget(QWidgetList* list, QWidget* _wid) { - QWidget *next = 0; - if ( list->isEmpty() || list->count() == 1 ) - next = _wid; - else{ - QWidget* wid; - uint idx = list->findRef( _wid ); - uint count = list->count(); - - /* one time through the list hacky we may not start with idx but end with it*/ - for (uint i = (idx + 1)%count; true; i=(i+1)%count ) { - wid = list->at(i); - if ( wid == _wid ) { - next = _wid; - break; - }else if ((( wid->inherits("QMainWindow") || - wid->inherits("QDialog") ) && - wid != qApp->desktop() && !wid->isHidden() ) || - ( wid == mainWidget() || wid == d->qpe_main_widget ) ){ - next = wid; - break; - } - } - } - delete list; - return next; -} + + /*! \internal */ -// ########## raise()ing main window should raise and set active -// ########## it and then all childen. This belongs in Qt/Embedded -/* - * slightly change in behaviour to kill the need of modality in Opie - * If any of the topLevelWidgets !isFullyObscured we highlight the next - * top level window - * 1)If visible and not modal we iterate over the list of top level widgets - * 2)If modal we we make the modal and its parent toplevel widget visible if available - * 3)else make topLevel visible - * - * send qcop if necessary and save current visible widget if not modal - */ bool QPEApplication::raiseAppropriateWindow() { bool r = FALSE; - QWidget *top = d->qpe_main_widget ? d->qpe_main_widget : mainWidget(); - /* 1. */ - if ( ( top && (top->isVisible() ) || ( d->lastWidget && d->lastWidget->isVisible() ) ) && - !activeModalWidget() ) { + // 1. Raise the main widget + QWidget *top = d->qpe_main_widget; + if ( !top ) top = mainWidget(); + + if ( top && d->keep_running ) { + if ( top->isVisible() ) r = TRUE; - /*wid will be valid and topLevelWidgets will be deleted properly.. */ - QWidget *wid = nextWidget( topLevelWidgets(), - d->lastWidget ? (QWidget*)d->lastWidget : top ); - /* keep the size window got but not for root*/ - if ( top == wid ) - d->show_mx(top, d->nomaximize ); - else - wid->show(); - - wid->raise(); - wid->setActiveWindow(); - d->lastWidget = wid; - }else if ( activeModalWidget() ) { - QWidget* mod = activeModalWidget(); - /* get the parent of the modal and its topLevelWidget as background widget */ - QWidget* par = activeModalWidget()->parentWidget() ? activeModalWidget()->parentWidget()->topLevelWidget() : 0; - if (par ) { - if (par == top ) - d->show_mx(par, d->nomaximize ); - else - par->show(); - par->raise(); - par->setActiveWindow(); - } - mod->show(); - mod->raise(); - mod->setActiveWindow(); - }else if (top){ - d->show_mx(top, d->nomaximize ); + else if (d->preloaded) { + // We are preloaded and not visible.. pretend we just started.. +#ifndef QT_NO_COP + QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); + e << d->appName; +#endif + } + + d->show_mx(top,d->nomaximize, d->appName); top->raise(); - top->setActiveWindow(); - d->lastWidget = top; } - if (!r && d->preloaded ) { + QWidget *topm = activeModalWidget(); + + // 2. Raise any parentless widgets (except top and topm, as they + // are raised before and after this loop). Order from most + // recently raised as deepest to least recently as top, so + // that repeated calls cycle through widgets. + QWidgetList *list = topLevelWidgets(); + if ( list ) { + bool foundlast = FALSE; + QWidget* topsub = 0; + if ( d->lastraised ) { + for (QWidget* w = list->first(); w; w = list->next()) { + if ( !w->parentWidget() && w != topm && w->isVisible() && !w->isDesktop() ) { + if ( w == d->lastraised ) + foundlast = TRUE; + if ( foundlast ) { + w->raise(); + topsub = w; + } + } + } + } + for (QWidget* w = list->first(); w; w = list->next()) { + if ( !w->parentWidget() && w != topm && w->isVisible() && !w->isDesktop() ) { + if ( w == d->lastraised ) + break; + w->raise(); + topsub = w; + } + } + d->lastraised = topsub; + delete list; + } + + // 3. Raise the active modal widget. + if ( topm && topm != top ) { + topm->show(); + topm->raise(); + // If we haven't already handled the fastAppShowing message + if (!top && d->preloaded) { +#ifndef QT_NO_COP QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); e << d->appName; +#endif + } + r = FALSE; } return r; } void QPEApplication::pidMessage( const QCString& msg, const QByteArray& data) { #ifdef Q_WS_QWS if ( msg == "quit()" ) { tryQuit(); } else if ( msg == "quitIfInvisible()" ) { if ( d->qpe_main_widget && !d->qpe_main_widget->isVisible() ) quit(); } else if ( msg == "close()" ) { hideOrQuit(); } else if ( msg == "disablePreload()" ) { d->preloaded = FALSE; d->keep_running = TRUE; /* so that quit will quit */ } else if ( msg == "enablePreload()" ) { if (d->qpe_main_widget) d->preloaded = TRUE; d->keep_running = TRUE; /* so next quit won't quit */ } else if ( msg == "raise()" ) { d->keep_running = TRUE; d->notbusysent = FALSE; raiseAppropriateWindow(); // Tell the system we're still chugging along... QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; } else if ( msg == "flush()" ) { emit flush(); // we need to tell the desktop QCopEnvelope e( "QPE/Desktop", "flushDone(QString)" ); e << d->appName; } else if ( msg == "reload()" ) { emit reload(); } else if ( msg == "setDocument(QString)" ) { d->keep_running = TRUE; QDataStream stream( data, IO_ReadOnly ); QString doc; stream >> doc; QWidget *mw = mainWidget(); if ( !mw ) mw = d->qpe_main_widget; if ( mw ) Global::setDocument( mw, doc ); } else if ( msg == "QPEProcessQCop()" ) { processQCopFile(); d->sendQCopQ(); }else { diff --git a/library/qpeapplication.h b/library/qpeapplication.h index 69e0058..729cf2b 100644 --- a/library/qpeapplication.h +++ b/library/qpeapplication.h @@ -54,131 +54,128 @@ public: static void setCurrentRotation(int r); static void setCurrentMode(int x, int y, int depth ); static void grabKeyboard(); static void ungrabKeyboard(); enum StylusMode { LeftOnly, RightOnHold // RightOnHoldLeftDelayed, etc. }; static void setStylusOperation( QWidget*, StylusMode ); static StylusMode stylusOperation( QWidget* ); enum InputMethodHint { Normal, AlwaysOff, AlwaysOn }; enum screenSaverHint { Disable = 0, DisableLightOff = 1, DisableSuspend = 2, Enable = 100 }; static void setInputMethodHint( QWidget *, InputMethodHint ); static InputMethodHint inputMethodHint( QWidget * ); void showMainWidget( QWidget*, bool nomax=FALSE ); void showMainDocumentWidget( QWidget*, bool nomax=FALSE ); static void showDialog( QDialog*, bool nomax=FALSE ); static int execDialog( QDialog*, bool nomax=FALSE ); /* Merge setTempScreenSaverMode */ #ifdef QTOPIA_INTERNAL_INITAPP void initApp( int argv, char **argv ); #endif static void setKeepRunning(); bool keepRunning() const; bool keyboardGrabbed() const; int exec(); signals: void clientMoused(); void timeChanged(); void clockChanged( bool pm ); void micChanged( bool muted ); void volumeChanged( bool muted ); void appMessage( const QCString& msg, const QByteArray& data); void weekChanged( bool startOnMonday ); void dateFormatChanged( DateFormat ); void flush(); void reload(); /* linkChanged signal */ private slots: void systemMessage( const QCString &msg, const QByteArray &data ); void pidMessage( const QCString &msg, const QByteArray &data ); void removeSenderFromStylusDict(); void hideOrQuit(); -private: - QWidget *nextWidget( QWidgetList*, QWidget* ); - protected: bool qwsEventFilter( QWSEvent * ); void internalSetStyle( const QString &style ); void prepareForTermination(bool willrestart); virtual void restart(); virtual void shutdown(); bool eventFilter( QObject *, QEvent * ); void timerEvent( QTimerEvent * ); bool raiseAppropriateWindow(); virtual void tryQuit(); #if QT_VERSION > 233 virtual void polish ( QWidget * ); // this is actually implemented in qt_override.cpp (!) #endif private: #ifndef QT_NO_TRANSLATION void installTranslation( const QString& baseName ); #endif void mapToDefaultAction( QWSKeyEvent *ke, int defKey ); void processQCopFile(); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) QCopChannel *sysChannel; QCopChannel *pidChannel; #endif QPEApplicationData *d; bool reserved_sh; }; inline void QPEApplication::showDialog( QDialog* d, bool nomax ) { QSize sh = d->sizeHint(); int w = QMAX(sh.width(),d->width()); int h = QMAX(sh.height(),d->height()); if ( !nomax && ( w > qApp->desktop()->width()*3/4 || h > qApp->desktop()->height()*3/4 ) ) { d->showMaximized(); } else { d->resize(w,h); d->show(); } } inline int QPEApplication::execDialog( QDialog* d, bool nomax ) { showDialog(d,nomax); return d->exec(); } enum Transformation { Rot0, Rot90, Rot180, Rot270 }; /* from qgfxtransformed_qws.cpp */ inline int TransToDeg ( Transformation t ) { int d = static_cast<int>( t ); return d * 90; } inline Transformation DegToTrans ( int d ) { |