| Home · All Classes · Main Classes · Deprecated |
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 |