homescreenapp/stateplugins/hshomescreenstateplugin/src/hsidlestate.cpp
changeset 55 03646e8da489
parent 51 4785f57bf3d4
child 60 30f14686fb04
child 62 341166945d65
equal deleted inserted replaced
51:4785f57bf3d4 55:03646e8da489
    44 #include "hswidgethost.h"
    44 #include "hswidgethost.h"
    45 #include "hswallpaper.h"
    45 #include "hswallpaper.h"
    46 #include "hsselectbackgroundstate.h"
    46 #include "hsselectbackgroundstate.h"
    47 #include "hstrashbinwidget.h"
    47 #include "hstrashbinwidget.h"
    48 #include "hspageindicator.h"
    48 #include "hspageindicator.h"
    49 #include "hswidgetpositioningonorientationchange.h"
       
    50 #include "hsmenueventfactory.h"
    49 #include "hsmenueventfactory.h"
    51 #include "hshomescreenstatecommon.h"
    50 #include "hshomescreenstatecommon.h"
    52 #include "hstitleresolver.h"
    51 #include "hstitleresolver.h"
    53 #include "hsmenuservice.h"
    52 #include "hsmenuservice.h"
    54 #include "hsgui.h"
    53 #include "hsgui.h"
   135     mSceneMenu(0)
   134     mSceneMenu(0)
   136 #ifdef Q_OS_SYMBIAN
   135 #ifdef Q_OS_SYMBIAN
   137     ,mSettingsMgr(0)
   136     ,mSettingsMgr(0)
   138 #endif
   137 #endif
   139 {
   138 {
   140     mTapAndHoldDistance = HsConfiguration::tapAndHoldDistance();
       
   141     mPageChangeZoneWidth = HsConfiguration::pageChangeZoneWidth();
       
   142     setupStates();
   139     setupStates();
   143     mTimer.setSingleShot(true);
   140     mTimer.setSingleShot(true);
   144     mTitleResolver = new HsTitleResolver(this);
   141     mTitleResolver = new HsTitleResolver(this);
   145 
   142 
   146     // TODO: Uncomment when updated API available
   143     // TODO: Uncomment when updated API available
   477     Checks if touch point in the active widget is located inside the left
   474     Checks if touch point in the active widget is located inside the left
   478     page change zone.
   475     page change zone.
   479 */
   476 */
   480 bool HsIdleState::isInLeftPageChangeZone()
   477 bool HsIdleState::isInLeftPageChangeZone()
   481 {
   478 {
   482     return mTouchScenePos.x() < mPageChangeZoneWidth;
   479     return mTouchScenePos.x() < HsConfiguration::pageChangeZoneWidth();
   483 }
   480 }
   484 
   481 
   485 /*!
   482 /*!
   486     Checks if touch point in the active widget is located inside the right
   483     Checks if touch point in the active widget is located inside the right
   487     page change zone.
   484     page change zone.
   488 */
   485 */
   489 bool HsIdleState::isInRightPageChangeZone()
   486 bool HsIdleState::isInRightPageChangeZone()
   490 {
   487 {
   491     qreal pageWidth = HsScene::mainWindow()->layoutRect().width();
   488     qreal pageWidth = HsScene::mainWindow()->layoutRect().width();
   492     return mTouchScenePos.x() > pageWidth - mPageChangeZoneWidth;
   489     return mTouchScenePos.x() > pageWidth - HsConfiguration::pageChangeZoneWidth();;
   493 }
   490 }
   494 
   491 
   495 /*!
   492 /*!
   496     Inserts new page at index position \a pageIndex in the scene.
   493     Inserts new page at index position \a pageIndex in the scene.
   497 */
   494 */
   632 
   629 
   633         mNavigationAction = new HbAction(this);
   630         mNavigationAction = new HbAction(this);
   634         mNavigationAction->setIcon(HbIcon(gApplicationLibraryIconName));
   631         mNavigationAction->setIcon(HbIcon(gApplicationLibraryIconName));
   635         connect(mNavigationAction, SIGNAL(triggered()), SIGNAL(event_applicationLibrary()));
   632         connect(mNavigationAction, SIGNAL(triggered()), SIGNAL(event_applicationLibrary()));
   636         idleView->setNavigationAction(mNavigationAction);
   633         idleView->setNavigationAction(mNavigationAction);
   637 
   634         
   638         // TODO: Workaround to Qt/Hb layouting bugs.
       
   639         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
       
   640         HsGui::setIdleView(idleView);
   635         HsGui::setIdleView(idleView);
   641 
   636 
   642         if (mPageChangeAnimation) {
   637         if (mPageChangeAnimation) {
   643             delete mPageChangeAnimation;
   638             delete mPageChangeAnimation;
   644             mPageChangeAnimation = NULL;
   639             mPageChangeAnimation = NULL;
   700     if (widgets.isEmpty()) {
   695     if (widgets.isEmpty()) {
   701         return;
   696         return;
   702     }
   697     }
   703 
   698 
   704     foreach (HsWidgetHost *widget, widgets) {
   699     foreach (HsWidgetHost *widget, widgets) {
   705         widget->initializeWidget();
   700         widget->startWidget();
   706         widget->showWidget();
       
   707     }
   701     }
   708 
   702 
   709     page->layoutNewWidgets();
   703     page->layoutNewWidgets();
   710 
   704 
   711 }
   705 }
   726 */
   720 */
   727 void HsIdleState::action_idle_connectOrientationChangeEventHandler()
   721 void HsIdleState::action_idle_connectOrientationChangeEventHandler()
   728 {
   722 {
   729     connect(HsScene::mainWindow(),
   723     connect(HsScene::mainWindow(),
   730         SIGNAL(orientationChanged(Qt::Orientation)),
   724         SIGNAL(orientationChanged(Qt::Orientation)),
   731         SLOT(onOrientationChanged(Qt::Orientation)));
   725         SLOT(action_idle_showActivePage()));
   732 }
   726 }
   733 
   727 
   734 /*!
   728 /*!
   735     Installs the event filter.
   729     Installs the event filter.
   736 */
   730 */
   783 */
   777 */
   784 void HsIdleState::action_idle_disconnectOrientationChangeEventHandler()
   778 void HsIdleState::action_idle_disconnectOrientationChangeEventHandler()
   785 {
   779 {
   786     disconnect(HsScene::mainWindow(),
   780     disconnect(HsScene::mainWindow(),
   787         SIGNAL(orientationChanged(Qt::Orientation)),
   781         SIGNAL(orientationChanged(Qt::Orientation)),
   788         this, SLOT(onOrientationChanged(Qt::Orientation)));
   782         this, SLOT(action_idle_showActivePage()));
   789 }
   783 }
   790 
   784 
   791 /*!
   785 /*!
   792     Disconnects the event filter.
   786     Disconnects the event filter.
   793 */
   787 */
   984     HsWidgetHost *widget = scene->activeWidget();
   978     HsWidgetHost *widget = scene->activeWidget();
   985 
   979 
   986     if (mUiWidget->trashBin()->isUnderMouse()) {
   980     if (mUiWidget->trashBin()->isUnderMouse()) {
   987         HbInstantFeedback::play(HsConfiguration::widgetDropToTrashbinFeedbackType());
   981         HbInstantFeedback::play(HsConfiguration::widgetDropToTrashbinFeedbackType());
   988         widget->page()->removeWidget(widget);
   982         widget->page()->removeWidget(widget);
   989         widget->uninitializeWidget();
   983         widget->remove();
   990         widget->deleteFromDatabase();
       
   991         widget->deleteLater();
       
   992         scene->setActiveWidget(0);
   984         scene->setActiveWidget(0);
   993     } else {
   985     } else {
   994         if (widget->page() != page) {
   986         if (widget->page() != page) {
   995             widget->page()->removeWidget(widget);
   987             widget->page()->removeWidget(widget);
   996             page->addExistingWidget(widget);
   988             page->addExistingWidget(widget);
   997             if (HsScene::orientation() == Qt::Horizontal) {
   989             if (HsScene::orientation() == Qt::Horizontal) {
   998                 widget->deleteWidgetPresentation(Qt::Vertical);
   990                 widget->removePresentation(Qt::Vertical);
   999             } else {
   991             } else {
  1000                 widget->deleteWidgetPresentation(Qt::Horizontal);
   992                 widget->removePresentation(Qt::Horizontal);
  1001             }
   993             }
  1002         }
   994         }
  1003 
   995 
  1004         QRectF widgetRect = widget->geometry();
   996         QRectF widgetRect = widget->geometry();
  1005         QRectF pageRect = page->rect();
   997         QRectF pageRect = page->rect();
  1010         if( widgetX != widgetRect.x() || widgetY != widgetRect.y()) {
  1002         if( widgetX != widgetRect.x() || widgetY != widgetRect.y()) {
  1011             HbInstantFeedback::play(HsConfiguration::widgetRepositionFeedbackType());
  1003             HbInstantFeedback::play(HsConfiguration::widgetRepositionFeedbackType());
  1012         }
  1004         }
  1013         widget->setPos(widgetX, widgetY);
  1005         widget->setPos(widgetX, widgetY);
  1014 
  1006 
  1015         widget->setWidgetPresentation();
  1007         widget->savePresentation();
  1016         page->updateZValues();
  1008         page->updateZValues();
  1017     }
  1009     }
  1018     mAllowZoneAnimation = true;
  1010     mAllowZoneAnimation = true;
  1019 
  1011 
  1020     widget->setParentItem(HsScene::instance()->activePage());
  1012     widget->setParentItem(HsScene::instance()->activePage());
  1059     QList<HsPage *> pages = HsScene::instance()->pages();
  1051     QList<HsPage *> pages = HsScene::instance()->pages();
  1060     QSizeF pageSize = pages.first()->size();
  1052     QSizeF pageSize = pages.first()->size();
  1061 
  1053 
  1062     int pageIndex = HsScene::instance()->activePageIndex();
  1054     int pageIndex = HsScene::instance()->activePageIndex();
  1063 
  1055 
  1064     if (mDeltaX < -pageSize.width() / 3) {
  1056     if (mDeltaX < -HsConfiguration::pageChangePanDistanceInPixels()) {
  1065         pageIndex = qMin(pageIndex + 1, pages.count() - 1);
  1057         pageIndex = qMin(pageIndex + 1, pages.count() - 1);
  1066     } else if (pageSize.width() / 3 < mDeltaX) {
  1058     } else if (HsConfiguration::pageChangePanDistanceInPixels() < mDeltaX) {
  1067         pageIndex = qMax(pageIndex - 1, 0);
  1059         pageIndex = qMax(pageIndex - 1, 0);
  1068     }
  1060     }
  1069 
  1061 
  1070     HsScene::instance()->setActivePageIndex(pageIndex);
  1062     HsScene::instance()->setActivePageIndex(pageIndex);
  1071 
  1063 
  1114     Adds a new page to the scene.
  1106     Adds a new page to the scene.
  1115 */
  1107 */
  1116 void HsIdleState::action_addPage_addPage()
  1108 void HsIdleState::action_addPage_addPage()
  1117 {
  1109 {
  1118     HsScene *scene = HsScene::instance();
  1110     HsScene *scene = HsScene::instance();
  1119     int pageIndex = scene->pages().count();
  1111 	  int pageIndex = scene->activePageIndex() + 1;
  1120     addPageToScene(pageIndex);
  1112     addPageToScene(pageIndex);
  1121     scene->setActivePageIndex(pageIndex);
  1113     scene->setActivePageIndex(pageIndex);
  1122     startPageChangeAnimation(pageIndex, HsConfiguration::newPageAddedAnimationDuration());
  1114     startPageChangeAnimation(pageIndex, HsConfiguration::newPageAddedAnimationDuration());
  1123     mUiWidget->pageIndicator()->addItem(pageIndex);
  1115     mUiWidget->pageIndicator()->addItem(pageIndex);
  1124     mUiWidget->showPageIndicator();
  1116     mUiWidget->showPageIndicator();
  1134 
  1126 
  1135     if (!page->widgets().isEmpty()) {
  1127     if (!page->widgets().isEmpty()) {
  1136 #ifndef HOMESCREEN_TEST //We don't want to test message box.
  1128 #ifndef HOMESCREEN_TEST //We don't want to test message box.
  1137         //Confirm removal of page having content
  1129         //Confirm removal of page having content
  1138         HbMessageBox *box = new HbMessageBox(HbMessageBox::MessageTypeQuestion);
  1130         HbMessageBox *box = new HbMessageBox(HbMessageBox::MessageTypeQuestion);
       
  1131         box->setAttribute(Qt::WA_DeleteOnClose);
  1139         box->setHeadingWidget(new HbLabel
  1132         box->setHeadingWidget(new HbLabel
  1140                                 (hbTrId(hsLocTextId_Title_RemovePage)));
  1133                                 (hbTrId(hsLocTextId_Title_RemovePage)));
  1141         box->setText(hbTrId(hsLocTextId_Confirmation_RemovePage));
  1134         box->setText(hbTrId(hsLocTextId_Confirmation_RemovePage));
  1142         box->setPrimaryAction(new HbAction(hbTrId(hsLocTextId_ConfirmationButton_Ok)));
  1135         
  1143         box->setSecondaryAction(new HbAction(hbTrId(hsLocTextId_ConfirmationButton_Cancel)));
  1136         QAction *buttonOk = box->actions().at(0);
  1144         box->setAttribute(Qt::WA_DeleteOnClose);
  1137         //We are keen only from OK button. Cancel is not connected to any slot.
       
  1138         connect(buttonOk, SIGNAL(triggered()), SLOT(onRemovePageConfirmationOk()));
  1145 
  1139 
  1146         HsScene::mainWindow()->setInteractive(true);
  1140         HsScene::mainWindow()->setInteractive(true);
  1147 
  1141 
  1148         box->open(this,SLOT(onRemovePageMessageBoxClosed(HbAction*)));
  1142         box->open();
  1149 #endif //HOMESCREEN_TEST
  1143 #endif //HOMESCREEN_TEST
  1150     } else {
  1144     } else {
  1151         //Empty page can be removed without confirmation
  1145         //Empty page can be removed without confirmation
  1152         removeActivePage();
  1146         removeActivePage();
  1153     }
  1147     }
  1215 
  1209 
  1216     filtered = true;
  1210     filtered = true;
  1217 
  1211 
  1218     QPointF point =
  1212     QPointF point =
  1219         event->scenePos() - event->buttonDownScenePos(Qt::LeftButton);
  1213         event->scenePos() - event->buttonDownScenePos(Qt::LeftButton);
  1220     if (mTapAndHoldDistance < point.manhattanLength()) {
  1214     if (HsConfiguration::tapAndHoldDistance() < point.manhattanLength()) {
  1221         // Threshold area for tap exceeded. This is pan or swipe
  1215         // Threshold area for tap exceeded. This is pan or swipe
  1222         mTimer.stop();
  1216         mTimer.stop();
  1223         if (HsScene::instance()->activeWidget()->isPannable(event)) {
  1217         if (HsScene::instance()->activeWidget()->isPannable(event)) {
  1224             // let widget get first press
  1218             // let widget get first press
  1225             mUiWidget->sendDelayedPress();
  1219             mUiWidget->sendDelayedPress();
  1276 
  1270 
  1277     filtered = true;
  1271     filtered = true;
  1278 
  1272 
  1279     QPointF point =
  1273     QPointF point =
  1280         event->scenePos() - event->buttonDownScenePos(Qt::LeftButton);
  1274         event->scenePos() - event->buttonDownScenePos(Qt::LeftButton);
  1281     if (mTapAndHoldDistance < point.manhattanLength()) {
  1275     if (HsConfiguration::tapAndHoldDistance() < point.manhattanLength()) {
  1282         mTimer.stop();
  1276         mTimer.stop();
  1283         mUiWidget->clearDelayedPress();
  1277         mUiWidget->clearDelayedPress();
  1284         emit event_moveScene();
  1278         emit event_moveScene();
  1285     }
  1279     }
  1286 }
  1280 }
  1326     //Move widget to new position:
  1320     //Move widget to new position:
  1327     mTouchScenePos = event->scenePos();
  1321     mTouchScenePos = event->scenePos();
  1328     QPointF delta(event->scenePos() - event->lastScenePos());
  1322     QPointF delta(event->scenePos() - event->lastScenePos());
  1329     widgetRect.moveTopLeft(widgetRect.topLeft() + delta);
  1323     widgetRect.moveTopLeft(widgetRect.topLeft() + delta);
  1330 
  1324 
  1331     //Widget can be moved over the pages left border if not in the first page.
  1325     //Widget can be moved over the pages left border
  1332     //In the first page widget cannot cross the page's left border at all.
       
  1333     qreal lowerBoundX = -widgetRect.width();
  1326     qreal lowerBoundX = -widgetRect.width();
  1334     HsPage *page = scene->activePage();
  1327     HsPage *page = scene->activePage();
  1335     if (page == scene->pages().first()) {
       
  1336         lowerBoundX = 0;
       
  1337     }
       
  1338 
       
  1339     //Widget can be moved over the pages right border if not in the last page when maximum amount
       
  1340     //of pages exist. Widget cannot cross the lastest page's right border at all.
       
  1341     QRectF pageRect = HsGui::idleView()->rect();
  1328     QRectF pageRect = HsGui::idleView()->rect();
  1342     qreal upperBoundX = pageRect.width() + widgetRect.width();
  1329     //Widget can be moved over the pages right border
  1343     if (page == scene->pages().last() && scene->pages().count() == scene->maximumPageCount()) {
  1330     qreal upperBoundX = pageRect.width();
  1344         upperBoundX = pageRect.width() - widgetRect.width();
  1331 
  1345     }
  1332     //Notice that chrome height is 64 pixels
  1346 
  1333     qreal lowerBoundY = qreal(64) - widgetRect.height();
  1347     //Widget cannot cross over top or bottom edges of the page.
  1334     //Widget can be moved over the pages down border
       
  1335     qreal upperBoundY = pageRect.height();
       
  1336 
       
  1337     qreal widgetX = qBound(lowerBoundX, widgetRect.x(), upperBoundX);
       
  1338     qreal widgetY = qBound(lowerBoundY, widgetRect.y(), upperBoundY);
  1348     /* if using ItemClipsChildrenToShape-flag in widgethost then
  1339     /* if using ItemClipsChildrenToShape-flag in widgethost then
  1349        setPos does not update position here, however setGeometry does it, QT bug?
  1340        setPos does not update position here, however setGeometry does it, QT bug?
  1350     */
  1341     */
  1351     qreal widgetX = qBound(lowerBoundX, widgetRect.x(), upperBoundX);
       
  1352     qreal widgetY = qBound(qreal(64), widgetRect.y(), pageRect.height() - widgetRect.height());
       
  1353     widget->setGeometry(widgetX, widgetY, widgetRect.width(), widgetRect.height());
  1342     widget->setGeometry(widgetX, widgetY, widgetRect.width(), widgetRect.height());
  1354 
  1343 
  1355     int bounceFeedbackEffectDistance = HsConfiguration::bounceFeedbackEffectDistance();
  1344     int bounceFeedbackEffectDistance = HsConfiguration::bounceFeedbackEffectDistance();
  1356     //Handle effects:
  1345     //Handle effects:
  1357     //User is indicated by a tactile feedback if he/she is trying to move
  1346     //User is indicated by a tactile feedback if he/she is trying to move
  1358     //widget over the first or the last page.
  1347     //widget over the first or the last page.
  1359     if( (page == scene->pages().first() && widgetRect.x() < bounceFeedbackEffectDistance ) ||
  1348     if( (page == scene->pages().first() && mTouchScenePos.x() < bounceFeedbackEffectDistance ) ||
  1360         (page == scene->pages().last() && scene->pages().count() == scene->maximumPageCount()
  1349         (page == scene->pages().last() && scene->pages().count() == scene->maximumPageCount()
  1361          && widgetRect.x()+ widgetRect.width() > pageRect.width() - bounceFeedbackEffectDistance)) {
  1350          && mTouchScenePos.x() > pageRect.width() - bounceFeedbackEffectDistance)) {
  1362              HbInstantFeedback::play(HsConfiguration::widgetMoveBlockedFeedbackType());
  1351              HbInstantFeedback::play(HsConfiguration::widgetMoveBlockedFeedbackType());
  1363             // TODO: use code below when Orbit has updated ContinuousFeedback API
  1352             // TODO: use code below when Orbit has updated ContinuousFeedback API
  1364             //if (!mContinuousFeedback->isPlaying()) {
  1353             //if (!mContinuousFeedback->isPlaying()) {
  1365             //    mContinuousFeedback->play();
  1354             //    mContinuousFeedback->play();
  1366             //}
  1355             //}
  1432     filtered = true;
  1421     filtered = true;
  1433 
  1422 
  1434     mDeltaX = event->scenePos().x() - event->buttonDownScenePos(Qt::LeftButton).x();
  1423     mDeltaX = event->scenePos().x() - event->buttonDownScenePos(Qt::LeftButton).x();
  1435 
  1424 
  1436     emit event_waitInput();
  1425     emit event_waitInput();
  1437 }
       
  1438 
       
  1439 /*!
       
  1440     Handles orientation change events. \a orientation is the
       
  1441     new orientation.
       
  1442 */
       
  1443 void HsIdleState::onOrientationChanged(Qt::Orientation orientation)
       
  1444 {
       
  1445     QList<HsPage *> pages = HsScene::instance()->pages();
       
  1446     QList<HsWidgetHost *> widgets;
       
  1447     HsWidgetHost *widget = 0;
       
  1448 
       
  1449     QRectF pageRect = HsScene::mainWindow()->layoutRect();
       
  1450 
       
  1451     // TODO: Temporary workaround for the Orbit bug.
       
  1452     if (orientation == Qt::Horizontal) {
       
  1453         pageRect = QRectF(0, 0, 640, 360);
       
  1454     } else {
       
  1455         pageRect = QRectF(0, 0, 360, 640);
       
  1456     }
       
  1457     // End of the workaround.
       
  1458 
       
  1459     const int chromeHeight = 64; // TODO: get this somewhere
       
  1460 
       
  1461     for (int i = 0; i < pages.count(); ++i) {
       
  1462         widgets = pages[i]->widgets();
       
  1463         for (int j = 0; j < widgets.count(); ++j) {
       
  1464             widget = widgets[j];
       
  1465             HsWidgetPresentationData presentation = widget->widgetPresentation(orientation);
       
  1466             if (presentation.widgetId < 0) {
       
  1467                 QList<QRectF> geometries =
       
  1468                     HsWidgetPositioningOnOrientationChange::instance()->convert(
       
  1469                         QRectF(0, chromeHeight,
       
  1470                             pageRect.height(),
       
  1471                             pageRect.width() - chromeHeight),
       
  1472                         QList<QRectF>() << widget->geometry(),
       
  1473                         QRectF(0, chromeHeight,
       
  1474                             pageRect.width(),
       
  1475                             pageRect.height() - chromeHeight));
       
  1476                 widget->setGeometry(geometries.first());
       
  1477                 widget->setWidgetPresentation();
       
  1478             } else {
       
  1479                 widget->setPos(presentation.x, presentation.y);
       
  1480                 widget->setZValue(presentation.zValue);
       
  1481             }
       
  1482         }
       
  1483     }
       
  1484     // TODO: Workaround to Qt/Hb layouting bugs.
       
  1485     QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
       
  1486     action_idle_showActivePage();
       
  1487 }
  1426 }
  1488 
  1427 
  1489 /*!
  1428 /*!
  1490     Handles tap-and-hold events for the widgetInteraction state.
  1429     Handles tap-and-hold events for the widgetInteraction state.
  1491 */
  1430 */
  1592 }
  1531 }
  1593 
  1532 
  1594 /*!
  1533 /*!
  1595     Handles the close of remove page confirmation dialog for page having content.
  1534     Handles the close of remove page confirmation dialog for page having content.
  1596 */
  1535 */
  1597 void HsIdleState::onRemovePageMessageBoxClosed(HbAction *action)
  1536 void HsIdleState::onRemovePageConfirmationOk()
  1598 {
  1537 {
  1599     HbMessageBox *dlg = static_cast<HbMessageBox*>(sender());
  1538     removeActivePage();
  1600     if(action == dlg->primaryAction()) {
       
  1601         //Page removal accepted
       
  1602         removeActivePage();
       
  1603     }
       
  1604 }
  1539 }
  1605 
  1540 
  1606 /*!
  1541 /*!
  1607     Handles the close of the scene menu.
  1542     Handles the close of the scene menu.
  1608 
  1543 
  1619     if(!menu->activeAction()) {
  1554     if(!menu->activeAction()) {
  1620         //mSceneMenu = 0;  //Menu deletes itself at the close
  1555         //mSceneMenu = 0;  //Menu deletes itself at the close
  1621         emit event_waitInput();
  1556         emit event_waitInput();
  1622     }
  1557     }
  1623 }
  1558 }
  1624 
       
  1625 // Undefine the helper macros.
       
  1626 #undef ENTRY_ACTION
       
  1627 #undef EXIT_ACTION
       
  1628 #undef CONNECT_MOUSE_EVENT_HANDLER
       
  1629 #undef DISCONNECT_MOUSE_EVENT_HANDLER