Ignore:
Timestamp:
Dec 16, 2009, 1:52:19 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Implemented QSessionManager and removed the QT_NO_SESSIONMANAGER define (closes #100).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/kernel/qapplication_pm.cpp

    r412 r428  
    5454#include "qpixmapcache.h"
    5555#include "qdesktopwidget.h"
     56#include "qsessionmanager.h"
    5657
    5758#include "qset.h"
     
    7778#if !defined (QT_NO_SESSIONMANAGER)
    7879
     80//#define DEBUG_SESSIONMANAGER
     81
    7982// Session management
    80 static bool     sm_blockUserInput    = FALSE;
    81 
    82 //#define DEBUG_SESSIONMANAGER
     83static bool     sm_blockUserInput    = false;
     84static bool     sm_smActive          = false;
     85static bool     sm_cancel            = false;
     86static bool     sm_gracefulShutdown  = false;
     87static bool     sm_quitSkipped       = false;
     88
     89extern QSessionManager *qt_session_manager_self; // defined in qapplication.cpp
     90extern bool qt_about_to_destroy_wnd; // defined in qwidget_pm.cpp
    8391
    8492#endif
     
    765773        switch(msg) {
    766774
     775#if !defined(QT_NO_SESSIONMANAGER)
     776        case WM_SAVEAPPLICATION: {
     777#if defined(DEBUG_SESSIONMANAGER)
     778            qDebug("WM_SAVEAPPLICATION: sm_gracefulShutdown %d, "
     779                   "qt_about_to_destroy_wnd %d, (mp1 %p, mp2 %p)",
     780                   sm_gracefulShutdown, qt_about_to_destroy_wnd, mp1, mp2);
     781#endif
     782            // PM seems to post this message to all top-level windows on system
     783            // shutdown, so react only to the first one. Also, this message is
     784            // always sent by WinDestroyWindow(), where it must be also ignored.
     785            if (!qt_about_to_destroy_wnd && !sm_smActive &&
     786                 !sm_gracefulShutdown) {
     787                sm_smActive = true;
     788                sm_gracefulShutdown = true;
     789                sm_blockUserInput = true; // prevent user-interaction outside interaction windows
     790                sm_cancel = false;
     791                sm_quitSkipped = false;
     792                if (qt_session_manager_self)
     793                    qApp->commitData(*qt_session_manager_self);
     794                sm_smActive = false; // session management has been finished
     795                if (sm_cancel) {
     796#if defined(DEBUG_SESSIONMANAGER)
     797                    qDebug("WM_SAVEAPPLICATION: sm_cancel %d", sm_cancel);
     798#endif
     799                    // @todo propagate the patch that does the below to XWP
     800                    // and enable the code when it appears upstream (see #100)
     801#if 0
     802                    // Here we try to cancel the Extended XWorkplace shutdown.
     803                    // If it's XWorkplace who sent us WM_SAVEAPPLICATION, then
     804                    // it probably passed us non-NULL parameters so that
     805                    // mp1 = its window handle and mp2 = WM_COMMAND code to
     806                    // cancel the shutdown procedure.
     807                    HWND shutdownHwnd = HWNDFROMMP(mp1);
     808                    if (WinIsWindow(0, shutdownHwnd)) {
     809                        WinPostMsg(shutdownHwnd, WM_COMMAND, mp2, 0);
     810                        // Ensure we will get WM_QUIT anyway, even if XWP was
     811                        // not that fast to post it yet (we need it to correctly
     812                        // finish the graceful shutdown procedure)
     813                        sm_quitSkipped = true;
     814                    }
     815#endif
     816                }
     817                // repost WM_QUIT to ourselves because we might have ignored
     818                // it in qt_app_canQuit(), so will not get one anymore
     819                if (sm_quitSkipped)
     820                    WinPostMsg(hwnd, WM_QUIT, 0, 0);
     821            }
     822            // PMREF recommends to pass it to WinDefWindowProc()
     823            return WinDefWindowProc(hwnd, msg, mp1, mp2);
     824        }
     825#endif
     826
    767827        case WM_SYSVALUECHANGED: {
    768828            // This message is sent to all top-level widgets, handle only once
     
    785845            }
    786846            #undef MY_IS_SV
     847            break;
     848        }
     849
     850        case WM_SYSCOLORCHANGE: {
     851            // This message is sent to all top-level widgets, handle only once
     852            QWidgetList list = QApplication::topLevelWidgets();
     853            bool firstWidget = list.first()->winId() == hwnd;
     854            if (!firstWidget)
     855                break;
     856            if (qApp->type() == QApplication::Tty)
     857                break;
     858            if (QApplication::desktopSettingsAware())
     859                    qt_set_pm_resources();
    787860            break;
    788861        }
     
    22222295}
    22232296
     2297/*****************************************************************************
     2298  PM session management
     2299 *****************************************************************************/
     2300
     2301#if !defined(QT_NO_SESSIONMANAGER)
     2302
     2303bool QApplicationPrivate::canQuit()
     2304{
     2305#if defined (DEBUG_SESSIONMANAGER)
     2306    qDebug("QApplicationPrivate::canQuit: sm_smActive %d,"
     2307           "qt_about_to_destroy_wnd %d, sm_gracefulShutdown %d, sm_cancel %d",
     2308           sm_smActive, qt_about_to_destroy_wnd,
     2309           sm_gracefulShutdown, sm_cancel);
     2310#endif
     2311
     2312    bool quit = false;
     2313
     2314    // We can get multiple WM_QUIT messages while the "session termination
     2315    // procedure" (i.e. the QApplication::commitData() call) is still in
     2316    // progress. Ignore them.
     2317    if (!sm_smActive) {
     2318        if (sm_gracefulShutdown) {
     2319            // this is WM_QUIT after WM_SAVEAPPLICATION (either posted by the OS
     2320            // or by ourselves), confirm the quit depending on what the user wants
     2321            sm_quitSkipped = false;
     2322            quit = !sm_cancel;
     2323            if (sm_cancel) {
     2324                // the shutdown has been canceled, reset the flag to let the
     2325                // graceful shutdown happen again later
     2326                sm_gracefulShutdown = false;
     2327            }
     2328        } else {
     2329            // sm_gracefulShutdown is false, so allowsInteraction() and friends
     2330            // will return FALSE during commitData() (assuming that WM_QUIT w/o
     2331            // WM_SAVEAPPLICATION is an emergency termination)
     2332            sm_smActive = true;
     2333            sm_blockUserInput = true; // prevent user-interaction outside interaction windows
     2334            sm_cancel = false;
     2335            if (qt_session_manager_self)
     2336                qApp->commitData(*qt_session_manager_self);
     2337            sm_smActive = false;
     2338            quit = true; // ignore sm_cancel
     2339        }
     2340    } else {
     2341        // if this is a WM_QUIT received during WM_SAVEAPPLICATION handling,
     2342        // remember we've skipped (refused) it
     2343        if (sm_gracefulShutdown)
     2344            sm_quitSkipped = true;
     2345    }
     2346
     2347#if defined (DEBUG_SESSIONMANAGER)
     2348    qDebug("QApplicationPrivate::canQuit: returns %d", quit);
     2349#endif
     2350
     2351    return quit;
     2352}
     2353
     2354bool QSessionManager::allowsInteraction()
     2355{
     2356    // Allow interation only when the system is being normally shutdown
     2357    // and informs us using WM_SAVEAPPLICATION. When we receive WM_QUIT directly
     2358    // (so sm_gracefulShutdown is false), interaction is disallowed.
     2359    if (sm_smActive && sm_gracefulShutdown) {
     2360        sm_blockUserInput = false;
     2361        return true;
     2362    }
     2363
     2364    return false;
     2365}
     2366
     2367bool QSessionManager::allowsErrorInteraction()
     2368{
     2369    // Allow interation only when the system is being normally shutdown
     2370    // and informs us using WM_SAVEAPPLICATION. When we receive WM_QUIT directly
     2371    // (so sm_gracefulShutdown is false), interaction is disallowed.
     2372    if (sm_smActive && sm_gracefulShutdown) {
     2373        sm_blockUserInput = false;
     2374        return true;
     2375    }
     2376
     2377    return false;
     2378}
     2379
     2380void QSessionManager::release()
     2381{
     2382    if (sm_smActive && sm_gracefulShutdown)
     2383        sm_blockUserInput = true;
     2384}
     2385
     2386void QSessionManager::cancel()
     2387{
     2388    if (sm_smActive && sm_gracefulShutdown)
     2389        sm_cancel = true;
     2390}
     2391
     2392#endif // QT_NO_SESSIONMANAGER
     2393
     2394/*****************************************************************************
     2395  PM struct/message debug helpers
     2396 *****************************************************************************/
    22242397
    22252398/*!
     
    22542427    return QString(QLatin1String("<no-widget>"));
    22552428}
    2256 
    2257 /*****************************************************************************
    2258   PM struct/message debug helpers
    2259  *****************************************************************************/
    22602429
    22612430typedef QLatin1String QCStr;
Note: See TracChangeset for help on using the changeset viewer.