src/hbcore/inputfw/hbinputmainwindow.cpp
changeset 34 ed14f46c0e55
parent 7 923ff622b8b9
equal deleted inserted replaced
31:7516d6d86cf5 34:ed14f46c0e55
    26 
    26 
    27 #include <QGraphicsWidget>
    27 #include <QGraphicsWidget>
    28 #include <QGraphicsSceneMouseEvent>
    28 #include <QGraphicsSceneMouseEvent>
    29 #include <QStyleOptionGraphicsItem>
    29 #include <QStyleOptionGraphicsItem>
    30 #include <QInputContext>
    30 #include <QInputContext>
       
    31 #include <QPointer>
    31 
    32 
    32 #include "hbinputregioncollector_p.h"
    33 #include "hbinputregioncollector_p.h"
    33 #include "hbinstance.h"
    34 #include "hbinstance.h"
    34 #include "hbwidget.h"
    35 #include "hbwidget.h"
    35 #include "hbview.h"
    36 #include "hbview.h"
    36 #include "hbnamespace_p.h"
       
    37 #include "hbstackedlayout.h"
    37 #include "hbstackedlayout.h"
       
    38 #include "hbpopup.h"
    38 
    39 
    39 #if defined (Q_OS_SYMBIAN)
    40 #if defined (Q_OS_SYMBIAN)
    40 #include <coemain.h>
    41 #include <coemain.h>
    41 #include <coecntrl.h>
    42 #include <coecntrl.h>
    42 #include <e32cmn.h>
    43 #include <e32cmn.h>
    50 }
    51 }
    51 
    52 
    52 Q_DECLARE_TYPEINFO(TRect, Q_MOVABLE_TYPE);
    53 Q_DECLARE_TYPEINFO(TRect, Q_MOVABLE_TYPE);
    53 #endif
    54 #endif
    54 
    55 
       
    56 
       
    57 class HbProxyWindow: public QWidget
       
    58 {
       
    59 public:
       
    60     HbProxyWindow()
       
    61     {
       
    62         setGeometry(0,0,0,0);
       
    63     }
       
    64     void setWindow(QWidget* window)
       
    65     {
       
    66         this->window = window;
       
    67         if (window) {
       
    68             window->setParent(this);
       
    69         }
       
    70     }
       
    71     ~HbProxyWindow()
       
    72     {
       
    73         if (window) {
       
    74             window->setParent(0);
       
    75         }
       
    76     }
       
    77 private:
       
    78     QPointer<QWidget> window;
       
    79 };
       
    80 
       
    81 
    55 class HbInputTransparentWindow : public HbWidget
    82 class HbInputTransparentWindow : public HbWidget
    56 {
    83 {
    57 public:
    84 public:
    58 
    85 
    59     HbInputTransparentWindow(QGraphicsItem *parent = 0);
    86     HbInputTransparentWindow(QGraphicsItem *parent = 0);
    68 };
    95 };
    69 
    96 
    70 HbInputTransparentWindow::HbInputTransparentWindow(QGraphicsItem *parent) :
    97 HbInputTransparentWindow::HbInputTransparentWindow(QGraphicsItem *parent) :
    71     HbWidget(parent)
    98     HbWidget(parent)
    72 {
    99 {
    73 	setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
   100     setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
    74 }
   101 }
    75 
   102 
    76 
   103 
    77 /*!
   104 /*!
    78     Destructs the transparent window.
   105     Destructs the transparent window.
    88     painter->setCompositionMode(QPainter::CompositionMode_Source);
   115     painter->setCompositionMode(QPainter::CompositionMode_Source);
    89     painter->fillRect(option->exposedRect, QColor(0, 0, 0, 0));
   116     painter->fillRect(option->exposedRect, QColor(0, 0, 0, 0));
    90     painter->setCompositionMode(compositionMode);
   117     painter->setCompositionMode(compositionMode);
    91 }
   118 }
    92 
   119 
       
   120 class HbInputMainWindowPrivate
       
   121 {
       
   122 public:
       
   123  HbInputMainWindowPrivate(HbInputMainWindow *owner)
       
   124     :q_ptr(owner), mLastFocusedWidget(0), mSpellQueryLaunched(false), mProxyWindow(0), mIsInputWindowFocusLocked(false)
       
   125     {
       
   126     }
       
   127     ~HbInputMainWindowPrivate();
       
   128     void dismissNonModalDialogs();
       
   129     HbInputMainWindow *q_ptr;
       
   130     QPointer<QWidget> mLastFocusedWidget;
       
   131     QRegion mMask;
       
   132     bool mSpellQueryLaunched;
       
   133     QPointer<HbProxyWindow > mProxyWindow;
       
   134     bool mIsInputWindowFocusLocked;
       
   135 };
       
   136 
       
   137 /*
       
   138 Dismisses all non-modal dialogs with tap-outside dismiss policy which are attached to the region collector.
       
   139 */
       
   140 void HbInputMainWindowPrivate::dismissNonModalDialogs()
       
   141 {
       
   142     HbInputRegionCollectorPrivate *const regionColPrivate = HbInputRegionCollector::instance()->d_ptr;
       
   143     if (regionColPrivate->mEnabled && !regionColPrivate->mModalDialogs) {
       
   144         QList<HbWidgetFilterList> list = regionColPrivate->mInputWidgets;
       
   145         for (int i = 0; i < list.size(); ++i) {
       
   146             if (list.at(i).mIsVisible) {
       
   147                 HbPopup *popup = qobject_cast<HbPopup *>(list.at(i).mWidget);
       
   148                 // dismiss non-modal dialogs, which have tap-outside dismiss policy.
       
   149                 if (popup && (popup->dismissPolicy() & HbPopup::TapOutside) && !popup->isModal()) {
       
   150                     popup->close();
       
   151                 }
       
   152             }
       
   153         }
       
   154     }
       
   155 }
       
   156 
       
   157 HbInputMainWindowPrivate::~HbInputMainWindowPrivate()
       
   158 {
       
   159     delete mProxyWindow;
       
   160 }
       
   161 
    93 /*
   162 /*
    94 creates an instance of HbInputMainWindow.
   163 creates an instance of HbInputMainWindow.
    95 */
   164 */
    96 HbInputMainWindow *HbInputMainWindow::instance()
   165 HbInputMainWindow *HbInputMainWindow::instance()
    97 {
   166 {
    99     return mainWindow;
   168     return mainWindow;
   100 }
   169 }
   101 
   170 
   102 HbInputMainWindow::~HbInputMainWindow()
   171 HbInputMainWindow::~HbInputMainWindow()
   103 {
   172 {
   104     delete mProxyWindow;
   173     delete d_ptr;
   105 }
   174 }
   106 
   175 
   107 // constructor.
   176 // constructor.
   108 HbInputMainWindow::HbInputMainWindow()
   177 HbInputMainWindow::HbInputMainWindow()
   109 // HbMainWindow creates a background QGraphicsItem, which has the background image. we need to hide it that.
   178 // HbMainWindow creates a background QGraphicsItem, which has the background image. we need to hide it that.
   110     : HbMainWindow(0, Hb::WindowFlagTransparent), mLastFocusedWidget(0), mSpellQueryLaunched(false), mProxyWindow(0)
   179     : HbMainWindow(0, Hb::WindowFlagTransparent), d_ptr(new HbInputMainWindowPrivate(this))
   111 {
   180 {
   112     // We need a window which is of type Qt::Window flag at the same time does not show
   181     // We need a window which is of type Qt::Window flag at the same time does not show
   113     // any decorators Qt::Tool seems to be the option, and we want this window to be always on top so Qt::WindowStaysOnTopHint.
   182     // any decorators Qt::Tool seems to be the option, and we want this window to be always on top so Qt::WindowStaysOnTopHint.
   114     // And since transparency requires to have a frameless window we are setting that too.
   183     // And since transparency requires to have a frameless window we are setting that too.
   115     setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);
   184     setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);
   155 }
   224 }
   156 
   225 
   157 
   226 
   158 void HbInputMainWindow::updateRegion(QRegion region)
   227 void HbInputMainWindow::updateRegion(QRegion region)
   159 {
   228 {
   160     mMask = region;
   229     d_ptr->mMask = region;
   161 #if defined (Q_OS_SYMBIAN)
   230 #if defined (Q_OS_SYMBIAN)
   162     RWindowBase *rwindow = effectiveWinId()->DrawableWindow();
   231     RWindowBase *rwindow = effectiveWinId()->DrawableWindow();
   163     if (region.isEmpty()) {
   232     if (region.isEmpty()) {
   164         TRegionFix<1> tregion(TRect(TPoint(0, 0), TSize(0, 0)));
   233         TRegionFix<1> tregion(TRect(TPoint(0, 0), TSize(0, 0)));
   165         rwindow->SetShape(tregion);
   234         rwindow->SetShape(tregion);
   166     } else {
   235     } else {
   167         // Using QVector assumes the memory layout is the same as RRegion
   236         // Using QVector assumes the memory layout is the same as RRegion 
   168         QVector<QRect> rects = region.rects();
   237         QVector<QRect> rects = region.rects(); 
   169         QVector<TRect> trects(rects.count());
   238         QVector<TRect> trects(rects.count()); 
       
   239         RRegion rregion;
   170         for (int i = 0; i < trects.count(); ++i) {
   240         for (int i = 0; i < trects.count(); ++i) {
   171             trects[i] = qt_QRect2TRect(rects.at(i));
   241             rregion.AddRect(qt_QRect2TRect(rects.at(i)));
   172         }
   242         }
   173         RRegion rregion(trects.count(), trects.data());
   243         if (!rregion.CheckError())
   174         if (!rregion.CheckError()) {
   244             rwindow->SetShape(rregion); 
   175             rwindow->SetShape(rregion);
   245    }
   176         }
       
   177     }
       
   178 #else
   246 #else
   179     setMask(region);
   247     setMask(region);
   180 #endif
   248 #endif
   181 }
   249 }
   182 
   250 
   186 */
   254 */
   187 bool HbInputMainWindow::event(QEvent *e)
   255 bool HbInputMainWindow::event(QEvent *e)
   188 {
   256 {
   189     switch (e->type()) {
   257     switch (e->type()) {
   190     case QEvent::WindowActivate:
   258     case QEvent::WindowActivate:
   191         if (mLastFocusedWidget && !mSpellQueryLaunched) {
   259         if (d_ptr->mLastFocusedWidget && !d_ptr->mIsInputWindowFocusLocked) {
   192             qApp->setActiveWindow(mLastFocusedWidget);
   260             qApp->setActiveWindow(d_ptr->mLastFocusedWidget);
   193         }
   261         }
   194         break;
   262         break;
   195     default:
   263     default:
   196         break;
   264         break;
   197     }
   265     }
   203 and blocks the events to the application window by launching a widget which sits exactly in between the applicaion
   271 and blocks the events to the application window by launching a widget which sits exactly in between the applicaion
   204 and HbInputMainWindow.
   272 and HbInputMainWindow.
   205 */
   273 */
   206 bool HbInputMainWindow::eventFilter(QObject *obj, QEvent *event)
   274 bool HbInputMainWindow::eventFilter(QObject *obj, QEvent *event)
   207 {
   275 {
   208     if (event->type() == QEvent::DynamicPropertyChange) {
       
   209         const QString p = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
       
   210         if (p == "SpellQueryLaunched") {
       
   211             QVariant variant = obj->property("SpellQueryLaunched");
       
   212             if (variant.isValid()) {
       
   213                 mSpellQueryLaunched = variant.toBool();
       
   214                 if (mSpellQueryLaunched) {
       
   215                     qApp->setActiveWindow(this);
       
   216                     setFocus(Qt::OtherFocusReason);
       
   217                 } else {
       
   218                     if (mLastFocusedWidget) {
       
   219                         qApp->setActiveWindow(mLastFocusedWidget);
       
   220                     }
       
   221                 }
       
   222             }
       
   223             // return true as we are interested party!
       
   224             return true;
       
   225         }
       
   226     }
       
   227 
       
   228     // we need to only check for spontaneous events.
   276     // we need to only check for spontaneous events.
   229     if (event->spontaneous() && (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease)) {
   277     if (event->spontaneous() && (event->type() == QEvent::MouseButtonPress)) {
   230         QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
   278         QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
   231         if (mouseEvent) {
   279         if (mouseEvent) {
   232             // get the top level widget at the point, and see if that widget is a HbMainWindow,
   280             // when we have only non-modal dialogs launched inside HbInputMainWindow, for instance exactword popup.
   233             // If it is a HbMainWindow then do not do any thing, as events will propagate
   281             // in that case HbInputMainWindow's window region is such that it only has exactword popup and the 
   234             // correctly. But when it is clicked inside application window then send the event to
   282             // vkb. And clicking anywhere other than vkb and exactword popup will not be know to HbInputMainWindow.
   235             // viewport as we might want to close a popup.
   283             // With the help of this eventfilter we will come to know if there are any click events outside
   236             if (!mMask.contains(mouseEvent->globalPos())) {
   284             // of HbInputMainWindow's region and we should close all the non-modal with tapoutside dismiss policy.
   237                 qApp->sendEvent(viewport(), event);
   285             if (!d_ptr->mMask.contains(mouseEvent->globalPos())) {
       
   286                 d_ptr->dismissNonModalDialogs();
   238             }
   287             }
       
   288         }
       
   289     } else if(event->spontaneous() && event->type() == QEvent::WindowActivate) {
       
   290         if(d_ptr->mIsInputWindowFocusLocked && (qApp->activeWindow()!= this)) {
       
   291             qApp->setActiveWindow(this);
   239         }
   292         }
   240     }
   293     }
   241 
   294 
   242     return HbMainWindow::eventFilter(obj, event);
   295     return HbMainWindow::eventFilter(obj, event);
   243 }
   296 }
   248 lost.
   301 lost.
   249 */
   302 */
   250 void HbInputMainWindow::saveFocusWidget(QWidget * /*Old*/, QWidget *newFocus)
   303 void HbInputMainWindow::saveFocusWidget(QWidget * /*Old*/, QWidget *newFocus)
   251 {
   304 {
   252     if (newFocus && !this->isAncestorOf(newFocus)) {
   305     if (newFocus && !this->isAncestorOf(newFocus)) {
   253         mLastFocusedWidget = newFocus;
   306         d_ptr->mLastFocusedWidget = newFocus;
   254     }
   307     }
   255 }
   308 }
   256 
   309 
   257 void HbInputMainWindow::showInputWindow()
   310 void HbInputMainWindow::showInputWindow()
   258 {
   311 {
   273     }
   326     }
   274 #endif
   327 #endif
   275 
   328 
   276     HbInputRegionCollector::instance()->setEnabled(true);
   329     HbInputRegionCollector::instance()->setEnabled(true);
   277     if (win && win->windowModality() != Qt::NonModal) {
   330     if (win && win->windowModality() != Qt::NonModal) {
   278         if (!mProxyWindow) {
   331         if (!d_ptr->mProxyWindow) {
   279             mProxyWindow = new HbProxyWindow();
   332             d_ptr->mProxyWindow = new HbProxyWindow();
   280         }
   333         }
   281         mProxyWindow->setWindow(this);
   334         d_ptr->mProxyWindow->setWindow(this);
   282         // since the focused widget is inside a modal dialog which blocks events to other_window.
   335         // since the focused widget is inside a modal dialog which blocks events to other_window.
   283         // and since hbinputmainwindow also comes under the other_window. It does will not get the 
   336         // and since hbinputmainwindow also comes under the other_window. It does will not get the 
   284         // mouse click events.
   337         // mouse click events.
   285         mProxyWindow->setParent(win);
   338         d_ptr->mProxyWindow->setParent(win);
   286         // setParent resets the window flags, so we have to set the flags once again before show() is called.
   339         // setParent resets the window flags, so we have to set the flags once again before show() is called.
   287         setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);
   340         setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);
   288         show();
   341         show();
   289     } else {
   342     } else {
   290         if (mProxyWindow && mProxyWindow->isAncestorOf(this)) {
   343         if (d_ptr->mProxyWindow && d_ptr->mProxyWindow->isAncestorOf(this)) {
   291             mProxyWindow->setWindow(0);
   344             d_ptr->mProxyWindow->setParent(0);
       
   345             d_ptr->mProxyWindow->setWindow(0);
   292             setParent(0);
   346             setParent(0);
   293             // setParent resets the window flags, so we have to set the flags once again before show is called.
   347             // setParent resets the window flags, so we have to set the flags once again before show is called.
   294             setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);
   348             setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);
   295         }
   349         }
   296         show();
   350         show();
   304 #endif
   358 #endif
   305 }
   359 }
   306 
   360 
   307 void HbInputMainWindow::hideInputWindow()
   361 void HbInputMainWindow::hideInputWindow()
   308 {
   362 {
   309     if (mSpellQueryLaunched) {
   363     if (d_ptr->mIsInputWindowFocusLocked) {
   310         return;
   364         return;
   311     }
   365     }
   312 
   366 
   313     if (isVisible()) {
   367     if (isVisible()) {
   314         hide();
   368         hide();
   324     // installing event filter to the application.. this is needed to get
   378     // installing event filter to the application.. this is needed to get
   325     // the events happening in other vanilla windows.
   379     // the events happening in other vanilla windows.
   326     qApp->removeEventFilter(this);
   380     qApp->removeEventFilter(this);
   327 }
   381 }
   328 
   382 
       
   383 void HbInputMainWindow::lockFocus()
       
   384 {
       
   385     // lock only when HbinputMainWindow is active.
       
   386     if (!isVisible())
       
   387         return;
       
   388 
       
   389     d_ptr->mIsInputWindowFocusLocked = true;
       
   390     setFocus(Qt::OtherFocusReason);
       
   391     qApp->setActiveWindow(this);
       
   392 #if defined(Q_OS_SYMBIAN)
       
   393     // this is done to come on top of all the controls in symbian OS, done to overlap soft keys as well.
       
   394     RWindow *rWindow = static_cast<RWindow *>(effectiveWinId()->DrawableWindow());
       
   395     const int positionForeground(0);
       
   396     // Now window ordinal position works with latest symbian release. So giving back this window
       
   397     // a FEP priority. This will enable this window to come on top of any softkeys.
       
   398     rWindow->SetOrdinalPosition(positionForeground);
       
   399 #endif
       
   400 }
       
   401 
       
   402 void HbInputMainWindow::unlockFocus()
       
   403 {
       
   404     if (!isVisible())
       
   405         return;
       
   406 
       
   407     d_ptr->mIsInputWindowFocusLocked = false;
       
   408     if (d_ptr->mLastFocusedWidget) {
       
   409         qApp->setActiveWindow(d_ptr->mLastFocusedWidget);
       
   410     }
       
   411 }
       
   412 
   329 //EOF
   413 //EOF