Home · All Classes · Main Classes · Deprecated

mapplication.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (directui@nokia.com)
00006 **
00007 ** This file is part of libmeegotouch.
00008 **
00009 ** If you have questions regarding the use of this file, please contact
00010 ** Nokia at directui@nokia.com.
00011 **
00012 ** This library is free software; you can redistribute it and/or
00013 ** modify it under the terms of the GNU Lesser General Public
00014 ** License version 2.1 as published by the Free Software Foundation
00015 ** and appearing in the file LICENSE.LGPL included in the packaging
00016 ** of this file.
00017 **
00018 ****************************************************************************/
00019 
00020 #include <qglobal.h>
00021 #include <cstdlib>
00022 #include <QCoreApplication>
00023 
00024 #include "mapplication.h"
00025 #include "mcomponentdata.h"
00026 #include "mondisplaychangeevent.h"
00027 #include "mapplicationwindow.h"
00028 #include "mwindow_p.h"
00029 #include <MDebug>
00030 #include "mapplication_p.h"
00031 #include "morientationtracker.h"
00032 #include "morientationtracker_p.h"
00033 
00034 /* Must be last, as it conflicts with some of the Qt defined types */
00035 #ifdef Q_WS_X11
00036 #include <QX11Info>
00037 #include <X11/Xlib.h>
00038 #include <X11/Xatom.h>
00039 #endif //Q_WS_X11
00040 
00041 #ifdef HAVE_XDAMAGE
00042 #include <X11/extensions/Xdamage.h>
00043 #endif //HAVE_XDAMAGE
00044 
00045 MApplicationPrivate::MApplicationPrivate():
00046         componentData(NULL),
00047         xDamageEventBase(0),
00048         xDamageErrorBase(0),
00049         q_ptr(NULL)
00050 {
00051 #ifdef HAVE_XDAMAGE
00052     XDamageQueryExtension(QX11Info::display(), &xDamageEventBase, &xDamageErrorBase);
00053 #endif //HAVE_XDAMAGE
00054 
00055 #ifdef Q_WS_X11
00056     visibleAtom = XInternAtom(QX11Info::display(),
00057                               "_MEEGOTOUCH_VISIBLE_IN_SWITCHER", False);
00058     stateAtom = XInternAtom(QX11Info::display(),
00059                             "_NET_WM_STATE", False);
00060     skipAtom = XInternAtom(QX11Info::display(),
00061                               "_NET_WM_STATE_SKIP_TASKBAR", False);
00062 #endif
00063 }
00064 
00065 MApplicationPrivate::~MApplicationPrivate()
00066 {
00067     delete componentData;
00068 }
00069 #ifdef Q_WS_X11
00070 void MApplicationPrivate::setWindowVisibility(MWindow * window, bool visible)
00071 {
00072     MOnDisplayChangeEvent ev(visible, QRectF(QPointF(0, 0), window->visibleSceneSize()));
00073     MApplication::instance()->sendEvent(window, &ev);
00074 }
00075 
00076 int MApplicationPrivate::handleXError(Display *, XErrorEvent *)
00077 {
00078     return 0;
00079 }
00080 
00081 
00082 void MApplicationPrivate::setX11PrestartPropertyForWindows(bool set)
00083 {
00084     Q_FOREACH(MWindow * win, MApplication::windows()) {
00085         win->d_ptr->setX11PrestartProperty(set);
00086     }
00087 }
00088 
00089 void MApplicationPrivate::removeWindowsFromSwitcher(bool remove)
00090 {
00091     Q_FOREACH(MWindow * win, MApplication::windows()) {
00092         removeWindowFromSwitcher(win->effectiveWinId(), remove);
00093     }
00094 }
00095 
00096 void MApplicationPrivate::removeWindowFromSwitcher(Window window, bool remove)
00097 {
00098     Display *dpy  = QX11Info::display();
00099     Atom stateAtom = XInternAtom(dpy, "_NET_WM_STATE", True);
00100     if (stateAtom != None) {
00101         Atom skipAtom = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", True);
00102         MWindow *win = windowForId(window);
00103         if (remove) {
00104             win->d_ptr->removeWindowFromSwitcherInProgress = true;
00105             XChangeProperty(dpy, window, stateAtom,
00106                             XA_ATOM, 32, PropModeAppend,
00107                             reinterpret_cast<unsigned char *>(&skipAtom), 1);
00108         } else if (win && !win->d_ptr->skipTaskbar) {
00109             // Do not remove SKIP_TASKBAR if it was requested from outside
00110             XEvent ev;
00111             memset(&ev, 0, sizeof(ev));
00112             ev.xclient.type         = ClientMessage;
00113             ev.xclient.display      = dpy;
00114             ev.xclient.window       = window;
00115             ev.xclient.message_type = XInternAtom(dpy, "_NET_WM_STATE", False);
00116             ev.xclient.format       = 32;
00117             ev.xclient.data.l[0]    = 0;
00118             ev.xclient.data.l[1]    = skipAtom;
00119             ev.xclient.data.l[2]    = 0;
00120 
00121             win->d_ptr->removeWindowFromSwitcherInProgress = true;
00122             XSendEvent(dpy, QX11Info::appRootWindow(), False, SubstructureRedirectMask | SubstructureNotifyMask,
00123                        &ev);
00124             XSync(dpy, False);
00125         }
00126     }
00127 }
00128 
00129 MWindow * MApplicationPrivate::windowForId(Window window)
00130 {
00131     Q_FOREACH(MWindow * p, MComponentData::windows()) {
00132         if (p && p->effectiveWinId() == static_cast<unsigned int>(window)) {
00133             return p;
00134         }
00135     }
00136     return NULL;
00137 }
00138 #endif
00139 
00140 MApplication *MApplication::instance()
00141 {
00142     return qobject_cast<MApplication *>(QCoreApplication::instance());
00143 }
00144 
00145 MApplication::MApplication(int &argc, char **argv, const QString &appIdentifier, MApplicationService *service)
00146     : QApplication(argc, argv),
00147       d_ptr(new MApplicationPrivate)
00148 {
00149     Q_D(MApplication);
00150     d->q_ptr = this;
00151 
00152     d->init(argc, argv, appIdentifier, service);
00153 }
00154 
00155 MApplication::MApplication(int &argc, char **argv, MApplicationService *service) :
00156     QApplication(argc, argv),
00157     d_ptr(new MApplicationPrivate)
00158 {
00159     Q_D(MApplication);
00160     d->q_ptr = this;
00161 
00162     d->init(argc, argv, QString(), service);
00163 }
00164 
00165 void MApplicationPrivate::init(int &argc, char **argv, const QString &appIdentifier, MApplicationService *newService)
00166 {
00167     componentData = new MComponentData(argc, argv, appIdentifier, newService);
00168 }
00169 
00170 void MApplicationPrivate::releasePrestart()
00171 {
00172     if (MApplication::isPrestarted()) {
00173 
00174         MComponentData::setPrestarted(false);
00175 
00176         // Call the virtual handler and emit the signal
00177         MApplication *mApp = MApplication::instance();
00178         if (mApp) {
00179             mApp->releasePrestart();
00180             emit mApp->prestartReleased();
00181         }
00182 
00183 #ifdef Q_WS_X11
00184         // Ensure that windows are visible in the switcher again
00185         if (prestartModeIsLazyShutdown()) {
00186             removeWindowsFromSwitcher(false);
00187         }
00188         setX11PrestartPropertyForWindows(false);
00189 #endif
00190     }
00191 }
00192 
00193 void MApplicationPrivate::restorePrestart()
00194 {
00195     if (!MApplication::isPrestarted() && prestartModeIsLazyShutdown()) {
00196 
00197         MComponentData::setPrestarted(true);
00198 
00199         // Call the virtual handler and emit the signal
00200         MApplication *mApp = MApplication::instance();
00201         if (mApp) {
00202             mApp->restorePrestart();
00203             emit mApp->prestartRestored();
00204         }
00205 
00206 #ifdef Q_WS_X11
00207         // Explicitly remove windows from the switcher because they
00208         // are hidden but should look like closed
00209         removeWindowsFromSwitcher(true);
00210         setX11PrestartPropertyForWindows(true);
00211 #endif
00212     }
00213 }
00214 
00215 void MApplicationPrivate::hideWindows()
00216 {
00217     Q_FOREACH(MWindow * win, MApplication::windows()) {
00218         win->hide();
00219         win->lower();
00220     }
00221 }
00222 
00223 void MApplication::setPrestarted(bool enable)
00224 {
00225     if (enable) {
00226         MApplicationPrivate::restorePrestart();
00227     } else {
00228         MApplicationPrivate::releasePrestart();
00229     }
00230 }
00231 
00232 bool MApplicationPrivate::prestartModeIsLazyShutdown()
00233 {
00234     return MApplication::prestartMode() == M::LazyShutdown ||
00235             MApplication::prestartMode() == M::LazyShutdownMultiWindow;
00236 }
00237 
00238 bool MApplicationPrivate::prestartModeIsMultiWindowed()
00239 {
00240     return MApplication::prestartMode() == M::TerminateOnCloseMultiWindow ||
00241             MApplication::prestartMode() == M::LazyShutdownMultiWindow;
00242 }
00243 
00244 MApplication::~MApplication()
00245 {
00246     delete d_ptr;
00247 }
00248 
00249 QString MApplication::deviceName()
00250 {
00251     return MComponentData::deviceName();
00252 }
00253 
00254 bool MApplication::softwareRendering()
00255 {
00256     return MComponentData::softwareRendering();
00257 }
00258 
00259 bool MApplication::fullScreen()
00260 {
00261     return MComponentData::fullScreen();
00262 }
00263 
00264 bool MApplication::showBoundingRect()
00265 {
00266     return MComponentData::showBoundingRect();
00267 }
00268 
00269 bool MApplication::showFps()
00270 {
00271     return MComponentData::showFps();
00272 }
00273 
00274 bool MApplication::logFps()
00275 {
00276     return MComponentData::logFps();
00277 }
00278 
00279 bool MApplication::showSize()
00280 {
00281     return MComponentData::showSize();
00282 }
00283 
00284 bool MApplication::showPosition()
00285 {
00286     return MComponentData::showPosition();
00287 }
00288 
00289 bool MApplication::showMargins()
00290 {
00291     return MComponentData::showMargins();
00292 }
00293 
00294 bool MApplication::showObjectNames()
00295 {
00296     return MComponentData::showObjectNames();
00297 }
00298 
00299 bool MApplication::showStyleNames()
00300 {
00301     return MComponentData::showStyleNames();
00302 }
00303 
00304 bool MApplication::showCursor()
00305 {
00306     return MComponentData::showCursor();
00307 }
00308 
00309 bool MApplication::emulateTwoFingerGestures()
00310 {
00311     return MComponentData::emulateTwoFingerGestures();
00312 }
00313 
00314 void MApplication::setShowPosition(bool show)
00315 {
00316     MComponentData::setShowPosition(show);
00317 }
00318 
00319 void MApplication::setShowSize(bool show)
00320 {
00321     MComponentData::setShowSize(show);
00322 }
00323 
00324 void MApplication::setShowMargins(bool show)
00325 {
00326     MComponentData::setShowMargins(show);
00327 }
00328 
00329 void MApplication::setShowObjectNames(bool show)
00330 {
00331     MComponentData::setShowObjectNames(show);
00332 }
00333 
00334 void MApplication::setShowStyleNames(bool show)
00335 {
00336     MComponentData::setShowStyleNames(show);
00337 }
00338 
00339 void MApplication::setShowBoundingRect(bool show)
00340 {
00341     MComponentData::setShowBoundingRect(show);
00342 }
00343 
00344 void MApplication::setShowFps(bool show)
00345 {
00346     MComponentData::setShowFps(show);
00347 }
00348 
00349 void MApplication::setLogFps(bool show)
00350 {
00351     MComponentData::setLogFps(show);
00352 }
00353 
00354 void MApplication::setShowCursor(bool show)
00355 {
00356     MComponentData::setShowCursor(show);
00357 }
00358 
00359 MApplicationWindow *MApplication::activeApplicationWindow()
00360 {
00361     return MComponentData::activeApplicationWindow();
00362 }
00363 
00364 MWindow *MApplication::activeWindow()
00365 {
00366     return MComponentData::activeWindow();
00367 }
00368 
00369 QList<MWindow *> MApplication::windows()
00370 {
00371     return MComponentData::windows();
00372 }
00373 
00374 MFeedbackPlayer *MApplication::feedbackPlayer()
00375 {
00376     return MComponentData::feedbackPlayer();
00377 }
00378 
00379 bool MApplication::isLoadMInputContextEnabled()
00380 {
00381     return MComponentData::isLoadMInputContextEnabled();
00382 }
00383 
00384 void MApplication::setLoadMInputContext(bool enable)
00385 {
00386     MComponentData::setLoadMInputContext(enable);
00387 }
00388 
00389 #ifdef Q_WS_X11
00390 bool MApplication::x11EventFilter(XEvent *event)
00391 {
00392     Q_D(MApplication);
00393 
00394     if (event->type == VisibilityNotify) {
00395         XVisibilityEvent *xevent = (XVisibilityEvent *) event;
00396         d->handleXVisibilityEvent(xevent);
00397 
00398     } else if (event->type == PropertyNotify) {
00399         XPropertyEvent *xevent = (XPropertyEvent *) event;
00400         d->handleXPropertyEvent(xevent);
00401     }
00402 #ifdef HAVE_XDAMAGE
00403     else if (event->type == d->xDamageEventBase + XDamageNotify) {
00404 
00405         XDamageNotifyEvent *xevent = (XDamageNotifyEvent *) event;
00406         XserverRegion parts;
00407         XRectangle *rects;
00408         int n_rect;
00409 
00410         // It is possible that the Damage has already been destroyed so register an error handler to suppress X errors
00411         XErrorHandler errh = XSetErrorHandler(MApplicationPrivate::handleXError);
00412 
00413         // Get the damaged rectangles from the damage event
00414         parts = XFixesCreateRegion(QX11Info::display(), 0, 0);
00415         // TODO does subtracting 0 regions really make any sense?
00416         XDamageSubtract(QX11Info::display(), xevent->damage, None, parts);
00417         rects = XFixesFetchRegion(QX11Info::display(), parts, &n_rect);
00418         XFixesDestroyRegion(QX11Info::display(), parts);
00419 
00420         // Create separate damage event signals from the damaged rectangles
00421         for (int i = 0; i < n_rect; ++i)
00422             emit damageEvent(xevent->damage, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
00423 
00424         // Free the rectangles and reset the original error handler
00425         XFree(rects);
00426         XSetErrorHandler(errh);
00427 
00428         return true;
00429     }
00430 #else //HAVE_XDAMAGE
00431     Q_UNUSED(d);
00432 #endif //HAVE_XDAMAGE
00433 
00434     return false;
00435 }
00436 
00437 void MApplicationPrivate::handleXVisibilityEvent(XVisibilityEvent *xevent)
00438 {
00439     switch (xevent->state) {
00440     case VisibilityFullyObscured:
00441         // Listen only to synthetic events by compositor
00442         if (xevent->send_event)
00443         {
00444             MWindow * window = MApplicationPrivate::windowForId(xevent->window);
00445             if (window) {
00446                 window->d_ptr->fullyObscured = true;
00447                 if (!window->d_ptr->visibleInSwitcher) {
00448                     setWindowVisibility(window, false);
00449                 }
00450             }
00451         }
00452         break;
00453 
00454         // Always listen to these events, because if compositor is not running
00455         // we are not getting any synthetic events at all and the window would never get
00456         // the display entered signal.
00457     case VisibilityUnobscured:
00458     case VisibilityPartiallyObscured:
00459         {
00460             MWindow * window = MApplicationPrivate::windowForId(xevent->window);
00461             if (window) {
00462                 window->d_ptr->fullyObscured = false;
00463                 setWindowVisibility(window, true);
00464             }
00465         }
00466         break;
00467     default:
00468         break;
00469     }
00470 }
00471 
00472 void MApplicationPrivate::handleXPropertyEvent(XPropertyEvent *xevent)
00473 {
00474     if (MOrientationTracker::instance()->d_func()->handleX11PropertyEvent(xevent))
00475         return;
00476 
00477     // _MEEGOTOUCH_VISIBLE_IN_SWITCHER is set by Home Screen for
00478     // windows that are in the switcher and visible. Set/unset the
00479     // flag for corresponding window because we need to combine this
00480     // information with VisibilityNotify's.
00481 
00482     // Applications can set themselves _NET_WM_STATE_SKIP_TASKBAR to avoid window
00483     // being displayed in taskbar. We need to handle this situation too.
00484 
00485     MWindow *window = windowForId(xevent->window);
00486     if (window && xevent->state == PropertyNewValue) {
00487         Atom           type;
00488         int            format;
00489         long           max_len = 1024;
00490         unsigned long  nItems;
00491         unsigned long  bytesAfter;
00492         unsigned char *data = NULL;
00493 
00494         if (xevent->atom == visibleAtom) {
00495             // Read value of the property. Should be 1 or 0.
00496             if (XGetWindowProperty(QX11Info::display(), xevent->window, visibleAtom,
00497                                    0, 1, False, XA_CARDINAL, &type, &format, &nItems,
00498                                    &bytesAfter, &data) == Success && data) {
00499                 const bool obscured = window->d_ptr->fullyObscured;
00500                 bool visible = *data;
00501                 window->d_ptr->visibleInSwitcher = visible;
00502 
00503                 if (visible) {
00504                     setWindowVisibility(window, true);
00505                 } else if (obscured){
00506                     setWindowVisibility(window, false);
00507                 }
00508 
00509                 XFree(data);
00510             }
00511         } else if (xevent->atom == stateAtom) {
00512             /* Check if it comes from MTF itself */
00513             if (window->d_ptr->removeWindowFromSwitcherInProgress) {
00514                 window->d_ptr->removeWindowFromSwitcherInProgress = false;
00515             } else {
00516                 /* Check if SKIP_TASKBAR was set or removed */
00517                 window->d_ptr->skipTaskbar = false;
00518                 if (XGetWindowProperty(QX11Info::display(), xevent->window, stateAtom, 0,
00519                                        max_len, False, XA_ATOM, &type, &format, &nItems,
00520                                        &bytesAfter, &data) == Success && data) {
00521                     for (unsigned long i = 0; i < nItems; i++) {
00522                         if (data[i] == skipAtom) {
00523                             window->d_ptr->skipTaskbar = true;
00524                             break;
00525                         }
00526                     }
00527                     XFree (data);
00528                 }
00529             }
00530         }
00531     }
00532 }
00533 
00534 #endif
00535 
00536 QString MApplication::appName()
00537 {
00538     return MComponentData::appName();
00539 }
00540 
00541 QString MApplication::binaryName()
00542 {
00543     return MComponentData::binaryName();
00544 }
00545 
00546 void MApplicationPrivate::stdExit(int status)
00547 {
00548     std::exit(status);
00549 }
00550 
00551 void MApplication::setPrestartMode(M::PrestartMode mode)
00552 {
00553     // Set prestart mode only if the app was started with -prestart.
00554     // This way we can later check if the app was originally prestarted or not.
00555     // Prevent application from exiting after the last window has been closed if
00556     // lazy shutdown was set.
00557 
00558     if (MComponentData::prestarted()) {
00559         MComponentData::setPrestartMode(mode);
00560         if (MApplicationPrivate::prestartModeIsLazyShutdown()) {
00561             MApplication::setQuitOnLastWindowClosed(false);
00562         }
00563     }
00564 }
00565 
00566 M::PrestartMode MApplication::prestartMode()
00567 {
00568     return MComponentData::prestartMode();
00569 }
00570 
00571 void MApplication::releasePrestart()
00572 {
00573     // Show the window only if we are not in a multi-windowed mode.
00574     // In that case the user must re-implement this, because we don't know which
00575     // window needs to be shown.
00576 
00577     if (!MApplicationPrivate::prestartModeIsMultiWindowed()) {
00578         if (MApplication::activeWindow()) {
00579             MApplication::activeWindow()->show();
00580             MApplication::activeWindow()->activateWindow();
00581             MApplication::activeWindow()->raise();
00582         }
00583     }
00584 }
00585 
00586 void MApplication::restorePrestart()
00587 {
00588     if (MApplicationPrivate::prestartModeIsLazyShutdown()) {
00589         MApplicationPrivate::hideWindows();
00590     }
00591 }
00592 
00593 bool MApplication::isPrestarted()
00594 {
00595     return (MComponentData::prestartMode() != M::NoPrestart) && MComponentData::prestarted();
00596 }
00597 
00598 #ifdef __arm__
00599 /*
00600  * When in "runfast" mode, single-precision VFP instructions execute in the
00601  * NEON pipeline. If using gcc, adding the flags -ffast-math -fno-math-errno,
00602  * and avoiding double precision is advisable, assuming results are still
00603  * accurate enough.
00604  */
00605 static int set_runfast()
00606 {
00607 #if defined(__VFP_FP__) && !defined(__SOFTFP__)
00608     int tmp;
00609     __asm__ volatile(
00610         "fmrx       %[tmp], fpscr\n\t"
00611         "orr        %[tmp], %[tmp], #(1 << 24)\n\t" /* flush-to-zero */
00612         "orr        %[tmp], %[tmp], #(1 << 25)\n\t" /* default NaN */
00613         "bic        %[tmp], %[tmp], #((1 << 15) | (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8))\n\t" /* clear exception bits */
00614         "fmxr       fpscr, %[tmp]\n\t"
00615         : [tmp] "=r"(tmp));
00616     return tmp;
00617 #else
00618     return 0;
00619 #endif
00620 }
00621 
00622 /*
00623  * IEEE standard floating point calculation
00624  */
00625 static int set_ieee()
00626 {
00627 #if defined(__VFP_FP__) && !defined(__SOFTFP__)
00628     int tmp;
00629     __asm__ volatile(
00630         "fmrx       %[tmp], fpscr\n\t"
00631         "bic        %[tmp], %[tmp], #(1 << 24)\n\t" /* flush-to-zero */
00632         "bic        %[tmp], %[tmp], #(1 << 25)\n\t" /* default NaN */
00633         "fmxr       fpscr, %[tmp]\n\t"
00634         : [tmp] "=r"(tmp));
00635     return tmp;
00636 #else
00637     return 0;
00638 #endif
00639 }
00640 
00641 void MApplication::fastFloatMath(bool val)
00642 {
00643     if (val) {
00644         set_runfast();
00645     } else {
00646         set_ieee();
00647     }
00648 }
00649 
00650 #endif

Copyright © 2010 Nokia Corporation Generated on Thu Nov 4 2010 18:14:19 (PDT)
Doxygen 1.7.1
MeeGo Touch