src/gui/kernel/qwidget_s60.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qwidget_p.h"
       
    43 #include "qdesktopwidget.h"
       
    44 #include "qapplication.h"
       
    45 #include "qapplication_p.h"
       
    46 #include "private/qbackingstore_p.h"
       
    47 #include "qevent.h"
       
    48 #include "qt_s60_p.h"
       
    49 
       
    50 #include "qbitmap.h"
       
    51 #include "private/qwindowsurface_s60_p.h"
       
    52 
       
    53 #include <qinputcontext.h>
       
    54 
       
    55 #ifdef Q_WS_S60
       
    56 #include <aknappui.h>
       
    57 #endif
       
    58 
       
    59 // This is necessary in order to be able to perform delayed invokation on slots
       
    60 // which take arguments of type WId.  One example is
       
    61 // QWidgetPrivate::_q_delayedDestroy, which is used to delay destruction of
       
    62 // CCoeControl objects until after the CONE event handler has finished running.
       
    63 Q_DECLARE_METATYPE(WId)
       
    64 
       
    65 QT_BEGIN_NAMESPACE
       
    66 
       
    67 extern bool qt_nograb();
       
    68 
       
    69 QWidget *QWidgetPrivate::mouseGrabber = 0;
       
    70 QWidget *QWidgetPrivate::keyboardGrabber = 0;
       
    71 
       
    72 static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b)
       
    73 {
       
    74     if ( a.count() != b.count())
       
    75         return false;
       
    76     int index=0;
       
    77     while (index<a.count()) {
       
    78         if (a.at(index)->softKeyRole() != b.at(index)->softKeyRole())
       
    79             return false;
       
    80         if (a.at(index)->text().compare(b.at(index)->text())!=0)
       
    81             return false;
       
    82         index++;
       
    83     }
       
    84     return true;
       
    85 }
       
    86 
       
    87 void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
       
    88 {
       
    89     // Note: based on x11 implementation
       
    90 
       
    91     static const int XCOORD_MAX = 16383;
       
    92     static const int WRECT_MAX = 16383;
       
    93 
       
    94     Q_Q(QWidget);
       
    95 
       
    96     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
    97 
       
    98     /*
       
    99       There are up to four different coordinate systems here:
       
   100       Qt coordinate system for this widget.
       
   101       Symbian coordinate system for this widget (relative to wrect).
       
   102       Qt coordinate system for parent
       
   103       Symbian coordinate system for parent (relative to parent's wrect).
       
   104      */
       
   105 
       
   106     QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
       
   107     QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
       
   108     QRect wrect;
       
   109     //xrect is the Symbian geometry of my widget. (starts out in parent's Qt coord sys, and ends up in parent's Symbian coord sys)
       
   110     QRect xrect = data.crect;
       
   111 
       
   112     const QWidget *const parent = q->parentWidget();
       
   113     QRect parentWRect = parent->data->wrect;
       
   114 
       
   115     if (parentWRect.isValid()) {
       
   116         // parent is clipped, and we have to clip to the same limit as parent
       
   117         if (!parentWRect.contains(xrect)) {
       
   118             xrect &= parentWRect;
       
   119             wrect = xrect;
       
   120             //translate from parent's to my Qt coord sys
       
   121             wrect.translate(-data.crect.topLeft());
       
   122         }
       
   123         //translate from parent's Qt coords to parent's X coords
       
   124         xrect.translate(-parentWRect.topLeft());
       
   125 
       
   126     } else {
       
   127         // parent is not clipped, we may or may not have to clip
       
   128 
       
   129         if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
       
   130             // This is where the main optimization is: we are already
       
   131             // clipped, and if our clip is still valid, we can just
       
   132             // move our window, and do not need to move or clip
       
   133             // children
       
   134 
       
   135             QRect vrect = xrect & parent->rect();
       
   136             vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
       
   137             if (data.wrect.contains(vrect)) {
       
   138                 xrect = data.wrect;
       
   139                 xrect.translate(data.crect.topLeft());
       
   140                 if (data.winid)
       
   141                     data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height()));
       
   142                 return;
       
   143             }
       
   144         }
       
   145 
       
   146         if (!validRange.contains(xrect)) {
       
   147             // we are too big, and must clip
       
   148             xrect &=wrectRange;
       
   149             wrect = xrect;
       
   150             wrect.translate(-data.crect.topLeft());
       
   151             //parent's X coord system is equal to parent's Qt coord
       
   152             //sys, so we don't need to map xrect.
       
   153         }
       
   154     }
       
   155 
       
   156     // unmap if we are outside the valid window system coord system
       
   157     bool outsideRange = !xrect.isValid();
       
   158     bool mapWindow = false;
       
   159     if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
       
   160         q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
       
   161         if (outsideRange) {
       
   162             if (data.winid)
       
   163                 data.winid->DrawableWindow()->SetVisible(EFalse);
       
   164             q->setAttribute(Qt::WA_Mapped, false);
       
   165         } else if (!q->isHidden()) {
       
   166             mapWindow = true;
       
   167         }
       
   168     }
       
   169 
       
   170     if (outsideRange)
       
   171         return;
       
   172 
       
   173     bool jump = (data.wrect != wrect);
       
   174     data.wrect = wrect;
       
   175 
       
   176     // and now recursively for all children...
       
   177     for (int i = 0; i < children.size(); ++i) {
       
   178         QObject *object = children.at(i);
       
   179         if (object->isWidgetType()) {
       
   180             QWidget *w = static_cast<QWidget *>(object);
       
   181             if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
       
   182                 w->d_func()->setWSGeometry(jump);
       
   183         }
       
   184     }
       
   185 
       
   186     if (data.winid) {
       
   187         // move ourselves to the new position and map (if necessary) after
       
   188         // the movement. Rationale: moving unmapped windows is much faster
       
   189         // than moving mapped windows
       
   190         if (!parent->internalWinId())
       
   191             xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
       
   192 
       
   193         data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height()));
       
   194     }
       
   195 
       
   196     if (mapWindow and !dontShow) {
       
   197         q->setAttribute(Qt::WA_Mapped);
       
   198         if (q->internalWinId())
       
   199             q->internalWinId()->DrawableWindow()->SetVisible(ETrue);
       
   200     }
       
   201 
       
   202     if  (jump && data.winid) {
       
   203         RWindow *const window = static_cast<RWindow *>(data.winid->DrawableWindow());
       
   204         window->Invalidate(TRect(0, 0, wrect.width(), wrect.height()));
       
   205     }
       
   206 }
       
   207 
       
   208 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
       
   209 {
       
   210     Q_Q(QWidget);
       
   211 
       
   212     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   213 
       
   214     if ((q->windowType() == Qt::Desktop))
       
   215         return;
       
   216     if (extra) {                                // any size restrictions?
       
   217         w = qMin(w,extra->maxw);
       
   218         h = qMin(h,extra->maxh);
       
   219         w = qMax(w,extra->minw);
       
   220         h = qMax(h,extra->minh);
       
   221     }
       
   222 
       
   223     if (q->isWindow())
       
   224         topData()->normalGeometry = QRect(0, 0, -1, -1);
       
   225     else {
       
   226         uint s = data.window_state;
       
   227         s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
       
   228         data.window_state = s;
       
   229     }
       
   230 
       
   231     QPoint oldPos(q->pos());
       
   232     QSize oldSize(q->size());
       
   233     QRect oldGeom(data.crect);
       
   234 
       
   235     bool isResize = w != oldSize.width() || h != oldSize.height();
       
   236     if (!isMove && !isResize)
       
   237         return;
       
   238 
       
   239     if (isResize)
       
   240         data.window_state &= ~Qt::WindowMaximized;
       
   241 
       
   242     if (q->isWindow()) {
       
   243         if (w == 0 || h == 0) {
       
   244             q->setAttribute(Qt::WA_OutsideWSRange, true);
       
   245             if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
       
   246                 hide_sys();
       
   247             data.crect = QRect(x, y, w, h);
       
   248             data.window_state &= ~Qt::WindowFullScreen;
       
   249         } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
       
   250             q->setAttribute(Qt::WA_OutsideWSRange, false);
       
   251 
       
   252             // put the window in its place and show it
       
   253             q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
       
   254             data.crect.setRect(x, y, w, h);
       
   255             show_sys();
       
   256         } else {
       
   257             QRect r = QRect(x, y, w, h);
       
   258             data.crect = r;
       
   259             q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
       
   260             topData()->normalGeometry = data.crect;
       
   261         }
       
   262     } else {
       
   263         data.crect.setRect(x, y, w, h);
       
   264 
       
   265         QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
       
   266         const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
       
   267 
       
   268         if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
       
   269             // Top-level resize optimization does not work for native child widgets;
       
   270             // disable it for this particular widget.
       
   271             if (inTopLevelResize)
       
   272                 tlwExtra->inTopLevelResize = false;
       
   273             if (!isResize && maybeBackingStore())
       
   274                 moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
       
   275             else
       
   276                 invalidateBuffer_resizeHelper(oldPos, oldSize);
       
   277 
       
   278             if (inTopLevelResize)
       
   279                 tlwExtra->inTopLevelResize = true;
       
   280         }
       
   281         if (q->testAttribute(Qt::WA_WState_Created))
       
   282             setWSGeometry();
       
   283     }
       
   284 
       
   285     if (q->isVisible()) {
       
   286         if (isMove && q->pos() != oldPos) {
       
   287             QMoveEvent e(q->pos(), oldPos);
       
   288             QApplication::sendEvent(q, &e);
       
   289         }
       
   290         if (isResize) {
       
   291             bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
       
   292             const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
       
   293                                            && !extra->topextra->inTopLevelResize;
       
   294             if (setTopLevelResize)
       
   295                 extra->topextra->inTopLevelResize = true;
       
   296             QResizeEvent e(q->size(), oldSize);
       
   297             QApplication::sendEvent(q, &e);
       
   298             if (!q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
       
   299                 q->internalWinId()->DrawDeferred();
       
   300             if (setTopLevelResize)
       
   301                 extra->topextra->inTopLevelResize = false;
       
   302         }
       
   303     } else {
       
   304         if (isMove && q->pos() != oldPos)
       
   305             q->setAttribute(Qt::WA_PendingMoveEvent, true);
       
   306         if (isResize)
       
   307             q->setAttribute(Qt::WA_PendingResizeEvent, true);
       
   308     }
       
   309 }
       
   310 
       
   311 void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool destroyOldWindow)
       
   312 {
       
   313     Q_Q(QWidget);
       
   314 
       
   315     Qt::WindowType type = q->windowType();
       
   316     Qt::WindowFlags &flags = data.window_flags;
       
   317     QWidget *parentWidget = q->parentWidget();
       
   318 
       
   319     bool topLevel = (flags & Qt::Window);
       
   320     bool popup = (type == Qt::Popup);
       
   321     bool dialog = (type == Qt::Dialog
       
   322                    || type == Qt::Sheet
       
   323                    || (flags & Qt::MSWindowsFixedSizeDialogHint));
       
   324     bool desktop = (type == Qt::Desktop);
       
   325     //bool tool = (type == Qt::Tool || type == Qt::Drawer);
       
   326 
       
   327     if (popup)
       
   328         flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
       
   329 
       
   330     TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
       
   331     int sw = clientRect.Width();
       
   332     int sh = clientRect.Height();
       
   333 
       
   334     if (desktop) {
       
   335         TSize screenSize = S60->screenDevice()->SizeInPixels();
       
   336         data.crect.setRect(0, 0, screenSize.iWidth, screenSize.iHeight);
       
   337         q->setAttribute(Qt::WA_DontShowOnScreen);
       
   338     } else if (topLevel && !q->testAttribute(Qt::WA_Resized)){
       
   339         int width = sw;
       
   340         int height = sh;
       
   341         if (extra) {
       
   342             width = qMax(qMin(width, extra->maxw), extra->minw);
       
   343             height = qMax(qMin(height, extra->maxh), extra->minh);
       
   344         }
       
   345         data.crect.setSize(QSize(width, height));
       
   346     }
       
   347 
       
   348     CCoeControl *const destroyw = destroyOldWindow ? data.winid : 0;
       
   349 
       
   350     createExtra();
       
   351     if (window) {
       
   352         setWinId(window);
       
   353         TRect tr = window->Rect();
       
   354         data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
       
   355 
       
   356     } else if (topLevel) {
       
   357         if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen))
       
   358             data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY));
       
   359 
       
   360         QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
       
   361         QT_TRAP_THROWING(control->ConstructL(true, desktop));
       
   362 
       
   363         // Symbian windows are always created in an inactive state
       
   364         // We perform this assignment for the case where the window is being re-created
       
   365         // as aa result of a call to setParent_sys, on either this widget or one of its
       
   366         // ancestors.
       
   367         extra->activated = 0;
       
   368 
       
   369         if (!desktop) {
       
   370             TInt stackingFlags;
       
   371             if ((q->windowType() & Qt::Popup) == Qt::Popup) {
       
   372                 stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
       
   373             } else {
       
   374                 stackingFlags = ECoeStackFlagStandard;
       
   375             }
       
   376             control->MakeVisible(false);
       
   377             QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
       
   378             // Avoid keyboard focus to a hidden window.
       
   379             control->setFocusSafely(false);
       
   380 
       
   381             RDrawableWindow *const drawableWindow = control->DrawableWindow();
       
   382             // Request mouse move events.
       
   383             drawableWindow->PointerFilter(EPointerFilterEnterExit
       
   384                 | EPointerFilterMove | EPointerFilterDrag, 0);
       
   385             drawableWindow->EnableVisibilityChangeEvents();
       
   386 
       
   387             if (!isOpaque) {
       
   388                 RWindow *const window = static_cast<RWindow *>(drawableWindow);
       
   389                 const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA));
       
   390                 if (window->SetTransparencyAlphaChannel() == KErrNone)
       
   391                     window->SetBackgroundColor(TRgb(255, 255, 255, 0));
       
   392             }
       
   393         }
       
   394 
       
   395         q->setAttribute(Qt::WA_WState_Created);
       
   396 
       
   397         int x, y, w, h;
       
   398         data.crect.getRect(&x, &y, &w, &h);
       
   399         control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
       
   400 
       
   401         // We wait until the control is fully constructed before calling setWinId, because
       
   402         // this generates a WinIdChanged event.
       
   403         setWinId(control.take());
       
   404 
       
   405     } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget
       
   406 
       
   407         QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
       
   408         QT_TRAP_THROWING(control->ConstructL(!parentWidget));
       
   409 
       
   410         // Symbian windows are always created in an inactive state
       
   411         // We perform this assignment for the case where the window is being re-created
       
   412         // as aa result of a call to setParent_sys, on either this widget or one of its
       
   413         // ancestors.
       
   414         extra->activated = 0;
       
   415 
       
   416         TInt stackingFlags;
       
   417         if ((q->windowType() & Qt::Popup) == Qt::Popup) {
       
   418             stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
       
   419         } else {
       
   420             stackingFlags = ECoeStackFlagStandard;
       
   421         }
       
   422         control->MakeVisible(false);
       
   423         QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
       
   424         // Avoid keyboard focus to a hidden window.
       
   425         control->setFocusSafely(false);
       
   426 
       
   427         q->setAttribute(Qt::WA_WState_Created);
       
   428         int x, y, w, h;
       
   429         data.crect.getRect(&x, &y, &w, &h);
       
   430         control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
       
   431 
       
   432         RDrawableWindow *const drawableWindow = control->DrawableWindow();
       
   433         // Request mouse move events.
       
   434         drawableWindow->PointerFilter(EPointerFilterEnterExit
       
   435             | EPointerFilterMove | EPointerFilterDrag, 0);
       
   436 
       
   437         if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
       
   438             activateSymbianWindow(control.data());
       
   439 
       
   440         // We wait until the control is fully constructed before calling setWinId, because
       
   441         // this generates a WinIdChanged event.
       
   442         setWinId(control.take());
       
   443     }
       
   444 
       
   445     if (destroyw) {
       
   446         destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw);
       
   447 
       
   448         // Delay deletion of the control in case this function is called in the
       
   449         // context of a CONE event handler such as
       
   450         // CCoeControl::ProcessPointerEventL
       
   451         QMetaObject::invokeMethod(q, "_q_delayedDestroy",
       
   452             Qt::QueuedConnection, Q_ARG(WId, destroyw));
       
   453     }
       
   454 
       
   455     if (q->testAttribute(Qt::WA_AcceptTouchEvents))
       
   456         registerTouchWindow();
       
   457 }
       
   458 
       
   459 
       
   460 void QWidgetPrivate::show_sys()
       
   461 {
       
   462     Q_Q(QWidget);
       
   463 
       
   464     if (q->testAttribute(Qt::WA_OutsideWSRange))
       
   465         return;
       
   466 
       
   467     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   468 
       
   469     q->setAttribute(Qt::WA_Mapped);
       
   470 
       
   471     if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
       
   472         invalidateBuffer(q->rect());
       
   473         return;
       
   474     }
       
   475 
       
   476     if (q->internalWinId()) {
       
   477         if (!extra->activated)
       
   478              activateSymbianWindow();
       
   479 
       
   480          QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId());
       
   481 
       
   482         id->MakeVisible(true);
       
   483 
       
   484         if(q->isWindow())
       
   485             id->setFocusSafely(true);
       
   486 
       
   487         // Force setting of the icon after window is made visible,
       
   488         // this is needed even WA_SetWindowIcon is not set, as in that case we need
       
   489         // to reset to the application level window icon
       
   490         if(q->isWindow())
       
   491             setWindowIcon_sys(true);
       
   492     }
       
   493 
       
   494     invalidateBuffer(q->rect());
       
   495 }
       
   496 
       
   497 void QWidgetPrivate::activateSymbianWindow(WId wid)
       
   498 {
       
   499     Q_Q(QWidget);
       
   500 
       
   501     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   502     Q_ASSERT(q->testAttribute(Qt::WA_Mapped));
       
   503     Q_ASSERT(!extra->activated);
       
   504 
       
   505     if(!wid)
       
   506         wid = q->internalWinId();
       
   507 
       
   508     Q_ASSERT(wid);
       
   509 
       
   510     QT_TRAP_THROWING(wid->ActivateL());
       
   511     extra->activated = 1;
       
   512 }
       
   513 
       
   514 void QWidgetPrivate::hide_sys()
       
   515 {
       
   516     Q_Q(QWidget);
       
   517 
       
   518     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   519     deactivateWidgetCleanup();
       
   520     QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId());
       
   521 
       
   522     if (id) {
       
   523         //Incorrect optimisation - for popup windows, Qt's focus is moved before
       
   524         //hide_sys is called, resulting in the popup window keeping its elevated
       
   525         //position in the CONE control stack.
       
   526         //This can result in keyboard focus being in an invisible widget in some
       
   527         //conditions - e.g. QTBUG-4733
       
   528         //if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
       
   529             id->setFocusSafely(false);
       
   530         id->MakeVisible(false);
       
   531         if (QWidgetBackingStore *bs = maybeBackingStore())
       
   532             bs->releaseBuffer();
       
   533     } else {
       
   534         invalidateBuffer(q->rect());
       
   535     }
       
   536 
       
   537     q->setAttribute(Qt::WA_Mapped, false);
       
   538 }
       
   539 
       
   540 void QWidgetPrivate::setFocus_sys()
       
   541 {
       
   542     Q_Q(QWidget);
       
   543     if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup)
       
   544         if (!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged()
       
   545             static_cast<QSymbianControl *>(q->effectiveWinId())->setFocusSafely(true);
       
   546 }
       
   547 
       
   548 void QWidgetPrivate::raise_sys()
       
   549 {
       
   550     Q_Q(QWidget);
       
   551 
       
   552     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   553     if (q->internalWinId()) {
       
   554         q->internalWinId()->DrawableWindow()->SetOrdinalPosition(0);
       
   555 
       
   556         // If toplevel widget, raise app to foreground
       
   557         if (q->isWindow())
       
   558             S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup().Identifier(), 0);
       
   559     }
       
   560 }
       
   561 
       
   562 void QWidgetPrivate::lower_sys()
       
   563 {
       
   564     Q_Q(QWidget);
       
   565 
       
   566     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   567     if (q->internalWinId())
       
   568         q->internalWinId()->DrawableWindow()->SetOrdinalPosition(-1);
       
   569 
       
   570     if (!q->isWindow())
       
   571         invalidateBuffer(q->rect());
       
   572 }
       
   573 
       
   574 void QWidgetPrivate::setModal_sys()
       
   575 {
       
   576 
       
   577 }
       
   578 
       
   579 void QWidgetPrivate::stackUnder_sys(QWidget* w)
       
   580 {
       
   581     Q_Q(QWidget);
       
   582     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   583 
       
   584     if (q->internalWinId() && w->internalWinId()) {
       
   585         RDrawableWindow *const thisWindow = q->internalWinId()->DrawableWindow();
       
   586         RDrawableWindow *const otherWindow = w->internalWinId()->DrawableWindow();
       
   587         thisWindow->SetOrdinalPosition(otherWindow->OrdinalPosition() + 1);
       
   588     }
       
   589 
       
   590     if (!q->isWindow() || !w->internalWinId())
       
   591         invalidateBuffer(q->rect());
       
   592 }
       
   593 
       
   594 void QWidgetPrivate::reparentChildren()
       
   595 {
       
   596     Q_Q(QWidget);
       
   597 
       
   598     QObjectList chlist = q->children();
       
   599     for (int i = 0; i < chlist.size(); ++i) { // reparent children
       
   600         QObject *obj = chlist.at(i);
       
   601         if (obj->isWidgetType()) {
       
   602             QWidget *w = (QWidget *)obj;
       
   603             if (!w->testAttribute(Qt::WA_WState_Created))
       
   604                 continue;
       
   605             if (!w->isWindow()) {
       
   606                 w->d_func()->invalidateBuffer(w->rect());
       
   607                 WId parent = q->effectiveWinId();
       
   608                 WId child = w->effectiveWinId();
       
   609                 if (parent != child) {
       
   610                     // Child widget is native.  Because Symbian windows cannot be
       
   611                     // re-parented, we must re-create the window.
       
   612                     const WId window = 0;
       
   613                     const bool initializeWindow = false;
       
   614                     const bool destroyOldWindow = true;
       
   615                     w->d_func()->create_sys(window, initializeWindow, destroyOldWindow);
       
   616                 }
       
   617                 // ### TODO: We probably also need to update the component array here
       
   618                 w->d_func()->reparentChildren();
       
   619             } else {
       
   620                 bool showIt = w->isVisible();
       
   621                 QPoint old_pos = w->pos();
       
   622                 w->setParent(q, w->windowFlags());
       
   623                 w->move(old_pos);
       
   624                 if (showIt)
       
   625                     w->show();
       
   626             }
       
   627         }
       
   628     }
       
   629 }
       
   630 
       
   631 void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
       
   632 {
       
   633     Q_Q(QWidget);
       
   634 
       
   635     bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
       
   636 
       
   637     if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
       
   638         q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
       
   639 
       
   640     if (q->testAttribute(Qt::WA_DropSiteRegistered))
       
   641         q->setAttribute(Qt::WA_DropSiteRegistered, false);
       
   642 
       
   643     QSymbianControl *old_winid = static_cast<QSymbianControl *>(wasCreated ? data.winid : 0);
       
   644     if ((q->windowType() == Qt::Desktop))
       
   645         old_winid = 0;
       
   646     setWinId(0);
       
   647 
       
   648     // hide and reparent our own window away. Otherwise we might get
       
   649     // destroyed when emitting the child remove event below. See QWorkspace.
       
   650     if (wasCreated && old_winid) {
       
   651         old_winid->MakeVisible(false);
       
   652         if (old_winid->IsFocused()) // Avoid unnecessary calls to FocusChanged()
       
   653             old_winid->setFocusSafely(false);
       
   654         old_winid->SetParent(0);
       
   655     }
       
   656 
       
   657     QObjectPrivate::setParent_helper(parent);
       
   658     bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
       
   659 
       
   660     data.window_flags = f;
       
   661     data.fstrut_dirty = true;
       
   662     q->setAttribute(Qt::WA_WState_Created, false);
       
   663     q->setAttribute(Qt::WA_WState_Visible, false);
       
   664     q->setAttribute(Qt::WA_WState_Hidden, false);
       
   665     adjustFlags(data.window_flags, q);
       
   666     // keep compatibility with previous versions, we need to preserve the created state
       
   667     // (but we recreate the winId for the widget being reparented, again for compatibility)
       
   668     if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
       
   669         createWinId();
       
   670     if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
       
   671         q->setAttribute(Qt::WA_WState_Hidden);
       
   672     q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
       
   673 
       
   674     if (wasCreated)
       
   675         reparentChildren();
       
   676 
       
   677     if (old_winid) {
       
   678         CBase::Delete(old_winid);
       
   679     }
       
   680 
       
   681     if (q->testAttribute(Qt::WA_AcceptDrops)
       
   682         || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
       
   683         q->setAttribute(Qt::WA_DropSiteRegistered, true);
       
   684 
       
   685     invalidateBuffer(q->rect());
       
   686 }
       
   687 
       
   688 void QWidgetPrivate::setConstraints_sys()
       
   689 {
       
   690 
       
   691 }
       
   692 
       
   693 
       
   694 void QWidgetPrivate::s60UpdateIsOpaque()
       
   695 {
       
   696     Q_Q(QWidget);
       
   697 
       
   698     if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
       
   699         return;
       
   700 
       
   701     if ((data.window_flags & Qt::FramelessWindowHint) == 0)
       
   702         return;
       
   703 
       
   704     RWindow *const window = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow());
       
   705 
       
   706     if (!isOpaque) {
       
   707         const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA));
       
   708         if (window->SetTransparencyAlphaChannel() == KErrNone)
       
   709             window->SetBackgroundColor(TRgb(255, 255, 255, 0));
       
   710     } else
       
   711         window->SetTransparentRegion(TRegionFix<1>());
       
   712 }
       
   713 
       
   714 CFbsBitmap* qt_pixmapToNativeBitmap(QPixmap pixmap, bool invert)
       
   715 {
       
   716     CFbsBitmap* fbsBitmap = q_check_ptr(new CFbsBitmap);    // CBase derived object needs check on new
       
   717     TSize size(pixmap.size().width(), pixmap.size().height());
       
   718     TDisplayMode mode(EColor16MU);
       
   719 
       
   720     bool isNull = pixmap.isNull();
       
   721     int depth = pixmap.depth();
       
   722 
       
   723     // TODO: dummy assumptions from bit amounts for each color
       
   724     // Will fix later on when native pixmap is implemented
       
   725     switch(pixmap.depth()) {
       
   726     case 1:
       
   727         mode = EGray2;
       
   728         break;
       
   729     case 4:
       
   730         mode = EColor16;
       
   731         break;
       
   732     case 8:
       
   733         mode = EColor256;
       
   734         break;
       
   735     case 12:
       
   736         mode = EColor4K;
       
   737         break;
       
   738     case 16:
       
   739         mode = EColor64K;
       
   740         break;
       
   741     case 24:
       
   742         mode = EColor16M;
       
   743         break;
       
   744     case 32:
       
   745         case EColor16MU:
       
   746         break;
       
   747     default:
       
   748         qFatal("Unsupported pixmap depth");
       
   749         break;
       
   750     }
       
   751 
       
   752     qt_symbian_throwIfError(fbsBitmap->Create(size, mode));
       
   753     fbsBitmap->LockHeap();
       
   754     QImage image = pixmap.toImage();
       
   755 
       
   756     if (invert)
       
   757         image.invertPixels();
       
   758 
       
   759     int height = pixmap.size().height();
       
   760     for(int i=0;i<height;i++ )
       
   761         {
       
   762         TPtr8 scanline(image.scanLine(i), image.bytesPerLine(), image.bytesPerLine());
       
   763         fbsBitmap->SetScanLine( scanline, i );
       
   764         }
       
   765 
       
   766     fbsBitmap->UnlockHeap();
       
   767     return fbsBitmap;
       
   768 }
       
   769 
       
   770 void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
       
   771 {
       
   772 #ifdef Q_WS_S60
       
   773     Q_Q(QWidget);
       
   774 
       
   775     if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() )
       
   776         return;
       
   777 
       
   778     QTLWExtra* topData = this->topData();
       
   779     if (topData->iconPixmap && !forceReset)
       
   780         // already been set
       
   781         return;
       
   782 
       
   783     TRect cPaneRect;
       
   784     TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EContextPane, cPaneRect );
       
   785     CAknContextPane* contextPane = S60->contextPane();
       
   786     if (found && contextPane) { // We have context pane with valid metrics
       
   787         QIcon icon = q->windowIcon();
       
   788         if (!icon.isNull()) {
       
   789             // Valid icon -> set it as an context pane picture
       
   790             QSize size = icon.actualSize(QSize(cPaneRect.Size().iWidth, cPaneRect.Size().iHeight));
       
   791             QPixmap pm = icon.pixmap(size);
       
   792             QBitmap mask = pm.mask();
       
   793             if (mask.isNull()) {
       
   794                 mask = QBitmap(pm.size());
       
   795                 mask.fill(Qt::color1);
       
   796             }
       
   797 
       
   798             // Convert to CFbsBitmp
       
   799             // TODO: When QPixmap is adapted to use native CFbsBitmap,
       
   800             // it could be set directly to context pane
       
   801             CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false);
       
   802             CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true);
       
   803 
       
   804             contextPane->SetPicture(nBitmap,nMask);
       
   805         } else {
       
   806             // Icon set to null -> set context pane picture to default
       
   807             QT_TRAP_THROWING(contextPane->SetPictureToDefaultL());
       
   808         }
       
   809     } else {
       
   810         // Context pane does not exist, try setting small icon to title pane
       
   811         TRect titlePaneRect;
       
   812         TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, titlePaneRect );
       
   813         CAknTitlePane* titlePane = S60->titlePane();
       
   814         if (found && titlePane) { // We have title pane with valid metrics
       
   815             // The API to get title_pane graphics size is not public -> assume square space based
       
   816             // on titlebar font height. CAknBitmap would be optimum, wihtout setting the size, since
       
   817             // then title pane would automatically scale the bitmap. Unfortunately it is not public API
       
   818             // Also this function is leaving, although it is not named as such.
       
   819             const CFont * font;
       
   820             QT_TRAP_THROWING(font = AknLayoutUtils::FontFromId(EAknLogicalFontTitleFont));
       
   821             TSize iconSize(font->HeightInPixels(), font->HeightInPixels());
       
   822 
       
   823             QIcon icon = q->windowIcon();
       
   824             if (!icon.isNull()) {
       
   825                 // Valid icon -> set it as an title pane small picture
       
   826                 QSize size = icon.actualSize(QSize(iconSize.iWidth, iconSize.iHeight));
       
   827                 QPixmap pm = icon.pixmap(size);
       
   828                 QBitmap mask = pm.mask();
       
   829                 if (mask.isNull()) {
       
   830                     mask = QBitmap(pm.size());
       
   831                     mask.fill(Qt::color1);
       
   832                 }
       
   833 
       
   834                 // Convert to CFbsBitmp
       
   835                 // TODO: When QPixmap is adapted to use native CFbsBitmap,
       
   836                 // it could be set directly to context pane
       
   837                 CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false);
       
   838                 CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true);
       
   839 
       
   840                 titlePane->SetSmallPicture( nBitmap, nMask, ETrue );
       
   841             } else {
       
   842                 // Icon set to null -> set context pane picture to default
       
   843                 titlePane->SetSmallPicture( NULL, NULL, EFalse );
       
   844             }
       
   845         }
       
   846     }
       
   847 
       
   848 #else
       
   849         Q_UNUSED(forceReset)
       
   850 #endif
       
   851 }
       
   852 
       
   853 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
       
   854 {
       
   855 #ifdef Q_WS_S60
       
   856     Q_Q(QWidget);
       
   857     if (q->isWindow()) {
       
   858         Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   859         CAknTitlePane* titlePane = S60->titlePane();
       
   860         if (titlePane) {
       
   861             if (caption.isEmpty()) {
       
   862                 QT_TRAP_THROWING(titlePane->SetTextToDefaultL());
       
   863             } else {
       
   864                 QT_TRAP_THROWING(titlePane->SetTextL(qt_QString2TPtrC(caption)));
       
   865             }
       
   866         }
       
   867     }
       
   868 #else
       
   869     Q_UNUSED(caption)
       
   870 #endif
       
   871 }
       
   872 
       
   873 void QWidgetPrivate::setWindowIconText_sys(const QString & /*iconText */)
       
   874 {
       
   875 
       
   876 }
       
   877 
       
   878 void QWidgetPrivate::scroll_sys(int dx, int dy)
       
   879 {
       
   880     Q_Q(QWidget);
       
   881 
       
   882     scrollChildren(dx, dy);
       
   883     if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
       
   884         scrollRect(q->rect(), dx, dy);
       
   885     } else {
       
   886         Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   887         RDrawableWindow *const window = q->internalWinId()->DrawableWindow();
       
   888         window->Scroll(TPoint(dx, dy));
       
   889     }
       
   890 }
       
   891 
       
   892 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
       
   893 {
       
   894     Q_Q(QWidget);
       
   895 
       
   896     if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
       
   897         scrollRect(r, dx, dy);
       
   898     } else {
       
   899         Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
       
   900         RDrawableWindow *const window = q->internalWinId()->DrawableWindow();
       
   901         window->Scroll(TPoint(dx, dy), qt_QRect2TRect(r));
       
   902     }
       
   903 }
       
   904 
       
   905 /*!
       
   906     For this function to work in the emulator, you must add:
       
   907        TRANSPARENCY
       
   908     To a line in the wsini.ini file.
       
   909 */
       
   910 void QWidgetPrivate::setWindowOpacity_sys(qreal)
       
   911 {
       
   912     // ### TODO: Implement uniform window transparency
       
   913 }
       
   914 
       
   915 void QWidgetPrivate::updateFrameStrut()
       
   916 {
       
   917 
       
   918 }
       
   919 
       
   920 void QWidgetPrivate::updateSystemBackground()
       
   921 {
       
   922 
       
   923 }
       
   924 
       
   925 void QWidgetPrivate::registerDropSite(bool /* on */)
       
   926 {
       
   927 
       
   928 }
       
   929 
       
   930 void QWidgetPrivate::createTLSysExtra()
       
   931 {
       
   932     extra->topextra->backingStore = 0;
       
   933 }
       
   934 
       
   935 void QWidgetPrivate::deleteTLSysExtra()
       
   936 {
       
   937 }
       
   938 
       
   939 void QWidgetPrivate::createSysExtra()
       
   940 {
       
   941     extra->activated = 0;
       
   942     extra->disableBlit = 0;
       
   943 }
       
   944 
       
   945 void QWidgetPrivate::deleteSysExtra()
       
   946 {
       
   947     // this should only be non-zero if destroy() has not run due to constructor fail
       
   948     if (data.winid) {
       
   949         data.winid->ControlEnv()->AppUi()->RemoveFromStack(data.winid);
       
   950         // We need to delete the backing store here before the CCoeControl and RWindow is deleted.
       
   951         // The reason is that the backing store may be an EGL surface and if we delete the window
       
   952         // before we delete the surface, the implementation may try to access to the window and raise
       
   953         // a WSERV 3 panic.
       
   954         if (extra && extra->topextra) {
       
   955             delete extra->topextra->backingStore;
       
   956             extra->topextra->backingStore = 0;
       
   957         }
       
   958         delete data.winid;
       
   959         data.winid = 0;
       
   960     }
       
   961 }
       
   962 
       
   963 QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
       
   964 {
       
   965     return new QS60WindowSurface(q_func());
       
   966 }
       
   967 
       
   968 void QWidgetPrivate::setMask_sys(const QRegion& /* region */)
       
   969 {
       
   970 
       
   971 }
       
   972 
       
   973 void QWidgetPrivate::registerTouchWindow()
       
   974 {
       
   975 #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
       
   976     Q_Q(QWidget);
       
   977     if (q->testAttribute(Qt::WA_WState_Created) && q->windowType() != Qt::Desktop) {
       
   978         RWindow *rwindow = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow());
       
   979         rwindow->EnableAdvancedPointers();
       
   980     }
       
   981 #endif
       
   982 }
       
   983 
       
   984 int QWidget::metric(PaintDeviceMetric m) const
       
   985 {
       
   986     Q_D(const QWidget);
       
   987     int val;
       
   988     if (m == PdmWidth) {
       
   989         val = data->crect.width();
       
   990     } else if (m == PdmHeight) {
       
   991         val = data->crect.height();
       
   992     } else {
       
   993         CWsScreenDevice *scr = S60->screenDevice();
       
   994         switch(m) {
       
   995         case PdmDpiX:
       
   996         case PdmPhysicalDpiX:
       
   997             if (d->extra && d->extra->customDpiX) {
       
   998                 val = d->extra->customDpiX;
       
   999             } else {
       
  1000                 const QWidgetPrivate *p = d;
       
  1001                 while (p->parent) {
       
  1002                     p = static_cast<const QWidget *>(p->parent)->d_func();
       
  1003                     if (p->extra && p->extra->customDpiX) {
       
  1004                         val = p->extra->customDpiX;
       
  1005                         break;
       
  1006                     }
       
  1007                 }
       
  1008                 if (p == d || !(p->extra && p->extra->customDpiX))
       
  1009                     val = S60->defaultDpiX;
       
  1010             }
       
  1011             break;
       
  1012         case PdmDpiY:
       
  1013         case PdmPhysicalDpiY:
       
  1014             if (d->extra && d->extra->customDpiY) {
       
  1015                 val = d->extra->customDpiY;
       
  1016             } else {
       
  1017                 const QWidgetPrivate *p = d;
       
  1018                 while (p->parent) {
       
  1019                     p = static_cast<const QWidget *>(p->parent)->d_func();
       
  1020                     if (p->extra && p->extra->customDpiY) {
       
  1021                         val = p->extra->customDpiY;
       
  1022                         break;
       
  1023                     }
       
  1024                 }
       
  1025                 if (p == d || !(p->extra && p->extra->customDpiY))
       
  1026                     val = S60->defaultDpiY;
       
  1027             }
       
  1028             break;
       
  1029         case PdmWidthMM:
       
  1030         {
       
  1031             TInt twips = scr->HorizontalPixelsToTwips(data->crect.width());
       
  1032             val = (int)(twips * (25.4/KTwipsPerInch));
       
  1033             break;
       
  1034         }
       
  1035         case PdmHeightMM:
       
  1036         {
       
  1037             TInt twips = scr->VerticalPixelsToTwips(data->crect.height());
       
  1038             val = (int)(twips * (25.4/KTwipsPerInch));
       
  1039             break;
       
  1040         }
       
  1041         case PdmNumColors:
       
  1042             val = TDisplayModeUtils::NumDisplayModeColors(scr->DisplayMode());
       
  1043             break;
       
  1044         case PdmDepth:
       
  1045             val = TDisplayModeUtils::NumDisplayModeBitsPerPixel(scr->DisplayMode());
       
  1046             break;
       
  1047         default:
       
  1048             val = 0;
       
  1049             qWarning("QWidget::metric: Invalid metric command");
       
  1050         }
       
  1051     }
       
  1052     return val;
       
  1053 }
       
  1054 
       
  1055 QPaintEngine *QWidget::paintEngine() const
       
  1056 {
       
  1057     return 0;
       
  1058 }
       
  1059 
       
  1060 QPoint QWidget::mapToGlobal(const QPoint &pos) const
       
  1061 {
       
  1062     Q_D(const QWidget);
       
  1063     if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
       
  1064 
       
  1065         QPoint p = pos + data->crect.topLeft();
       
  1066         return (isWindow() || !parentWidget()) ?  p : parentWidget()->mapToGlobal(p);
       
  1067 
       
  1068     } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
       
  1069         QPoint tp = geometry().topLeft();
       
  1070         return pos + tp;
       
  1071     }
       
  1072 
       
  1073     // Native window case
       
  1074     const TPoint widgetScreenOffset = internalWinId()->PositionRelativeToScreen();
       
  1075     const QPoint globalPos = QPoint(widgetScreenOffset.iX, widgetScreenOffset.iY) + pos;
       
  1076     return globalPos;
       
  1077 }
       
  1078 
       
  1079 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
       
  1080 {
       
  1081     Q_D(const QWidget);
       
  1082     if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
       
  1083         QPoint p = (isWindow() || !parentWidget()) ?  pos : parentWidget()->mapFromGlobal(pos);
       
  1084         return p - data->crect.topLeft();
       
  1085     } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
       
  1086         QPoint tp = geometry().topLeft();
       
  1087         return pos - tp;
       
  1088     }
       
  1089 
       
  1090     // Native window case
       
  1091     const TPoint widgetScreenOffset = internalWinId()->PositionRelativeToScreen();
       
  1092     const QPoint widgetPos = pos - QPoint(widgetScreenOffset.iX, widgetScreenOffset.iY);
       
  1093     return widgetPos;
       
  1094 }
       
  1095 
       
  1096 void QWidget::setWindowState(Qt::WindowStates newstate)
       
  1097 {
       
  1098     Q_D(QWidget);
       
  1099 
       
  1100     Qt::WindowStates oldstate = windowState();
       
  1101     if (oldstate == newstate)
       
  1102         return;
       
  1103 
       
  1104     if (isWindow()) {
       
  1105 #ifdef Q_WS_S60
       
  1106         // Change window decoration visibility if switching to or from fullsccreen
       
  1107         // In addition decoration visibility is changed when the initial has been
       
  1108         // WindowNoState.
       
  1109         // The window decoration visibility has to be changed before doing actual
       
  1110         // window state change since in that order the availableGeometry will return
       
  1111         // directly the right size and we will avoid unnecessarty redraws
       
  1112         if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen) ||
       
  1113             oldstate == Qt::WindowNoState) {
       
  1114             CEikStatusPane* statusPane = S60->statusPane();
       
  1115             CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
       
  1116             if (newstate & Qt::WindowFullScreen) {
       
  1117                 if (statusPane)
       
  1118                     statusPane->MakeVisible(false);
       
  1119                 if (buttonGroup)
       
  1120                     buttonGroup->MakeVisible(false);
       
  1121             } else {
       
  1122                 if (statusPane)
       
  1123                     statusPane->MakeVisible(true);
       
  1124                 if (buttonGroup)
       
  1125                     buttonGroup->MakeVisible(true);
       
  1126             }
       
  1127 
       
  1128         }
       
  1129 #endif // Q_WS_S60
       
  1130 
       
  1131         createWinId();
       
  1132         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
       
  1133         QTLWExtra *top = d->topData();
       
  1134 
       
  1135         // Ensure the initial size is valid, since we store it as normalGeometry below.
       
  1136         if (!testAttribute(Qt::WA_Resized) && !isVisible())
       
  1137             adjustSize();
       
  1138 
       
  1139         if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
       
  1140             if ((newstate & Qt::WindowMaximized)) {
       
  1141                 const QRect normalGeometry = geometry();
       
  1142 
       
  1143                 const QRect r = top->normalGeometry;
       
  1144                 setGeometry(qApp->desktop()->availableGeometry(this));
       
  1145                 top->normalGeometry = r;
       
  1146 
       
  1147                 if (top->normalGeometry.width() < 0)
       
  1148                     top->normalGeometry = normalGeometry;
       
  1149             } else {
       
  1150                 // restore original geometry
       
  1151                 setGeometry(top->normalGeometry);
       
  1152             }
       
  1153         }
       
  1154         if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
       
  1155             if (newstate & Qt::WindowFullScreen) {
       
  1156                 const QRect normalGeometry = geometry();
       
  1157                 const QRect r = top->normalGeometry;
       
  1158                 setGeometry(qApp->desktop()->screenGeometry(this));
       
  1159 
       
  1160                 top->normalGeometry = r;
       
  1161                 if (top->normalGeometry.width() < 0)
       
  1162                     top->normalGeometry = normalGeometry;
       
  1163             } else {
       
  1164                 if (newstate & Qt::WindowMaximized) {
       
  1165                     const QRect r = top->normalGeometry;
       
  1166                     setGeometry(qApp->desktop()->availableGeometry(this));
       
  1167                     top->normalGeometry = r;
       
  1168                 } else {
       
  1169                     setGeometry(top->normalGeometry);
       
  1170                 }
       
  1171             }
       
  1172         }
       
  1173         if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
       
  1174             if (newstate & Qt::WindowMinimized) {
       
  1175                 if (isVisible()) {
       
  1176                     QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId());
       
  1177                     if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
       
  1178                         id->setFocusSafely(false);
       
  1179                     id->MakeVisible(false);
       
  1180                 }
       
  1181             } else {
       
  1182                 if (isVisible()) {
       
  1183                     QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId());
       
  1184                     id->MakeVisible(true);
       
  1185                     if (!id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
       
  1186                         id->setFocusSafely(true);
       
  1187                 }
       
  1188                 const QRect normalGeometry = geometry();
       
  1189                 const QRect r = top->normalGeometry;
       
  1190                 top->normalGeometry = r;
       
  1191                 if (top->normalGeometry.width() < 0)
       
  1192                     top->normalGeometry = normalGeometry;
       
  1193             }
       
  1194         }
       
  1195     }
       
  1196 
       
  1197     data->window_state = newstate;
       
  1198 
       
  1199     if (newstate & Qt::WindowActive)
       
  1200         activateWindow();
       
  1201 
       
  1202     QWindowStateChangeEvent e(oldstate);
       
  1203     QApplication::sendEvent(this, &e);
       
  1204 }
       
  1205 
       
  1206 
       
  1207 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
       
  1208 {
       
  1209     Q_D(QWidget);
       
  1210     if (!isWindow() && parentWidget())
       
  1211         parentWidget()->d_func()->invalidateBuffer(geometry());
       
  1212     d->deactivateWidgetCleanup();
       
  1213     QSymbianControl *id = static_cast<QSymbianControl *>(internalWinId());
       
  1214     if (testAttribute(Qt::WA_WState_Created)) {
       
  1215 
       
  1216 #ifndef QT_NO_IM
       
  1217         if (d->ic) {
       
  1218             delete d->ic;
       
  1219         } else {
       
  1220             QInputContext *ic = inputContext();
       
  1221             if (ic) {
       
  1222                 ic->widgetDestroyed(this);
       
  1223             }
       
  1224         }
       
  1225 #endif
       
  1226 
       
  1227         if (QWidgetPrivate::mouseGrabber == this)
       
  1228             releaseMouse();
       
  1229         if (QWidgetPrivate::keyboardGrabber == this)
       
  1230             releaseKeyboard();
       
  1231         setAttribute(Qt::WA_WState_Created, false);
       
  1232         QObjectList childList = children();
       
  1233         for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
       
  1234             register QObject *obj = childList.at(i);
       
  1235             if (obj->isWidgetType())
       
  1236                 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
       
  1237                                                     destroySubWindows);
       
  1238         }
       
  1239         if (destroyWindow && !(windowType() == Qt::Desktop) && id) {
       
  1240             if (id->IsFocused()) // Avoid unnecessry calls to FocusChanged()
       
  1241                 id->setFocusSafely(false);
       
  1242             id->ControlEnv()->AppUi()->RemoveFromStack(id);
       
  1243 
       
  1244             // Hack to activate window under destroyed one. With this activation
       
  1245             // the next visible window will get keyboard focus
       
  1246             WId wid = CEikonEnv::Static()->AppUi()->TopFocusedControl();
       
  1247             if (wid) {
       
  1248                 QWidget *widget = QWidget::find(wid);
       
  1249                 QApplication::setActiveWindow(widget);
       
  1250                 if (widget) {
       
  1251                     // Reset global window title for focusing window
       
  1252                     widget->d_func()->setWindowTitle_sys(widget->windowTitle());
       
  1253                 }
       
  1254             }
       
  1255         }
       
  1256     }
       
  1257 
       
  1258     QT_TRY {
       
  1259         d->setWinId(0);
       
  1260     } QT_CATCH (const std::bad_alloc &) {
       
  1261         // swallow - destructors must not throw
       
  1262     }
       
  1263 
       
  1264     if (destroyWindow) {
       
  1265         d->deleteSysExtra(); // deletes backingstore + window
       
  1266     }
       
  1267 }
       
  1268 
       
  1269 QWidget *QWidget::mouseGrabber()
       
  1270 {
       
  1271     return QWidgetPrivate::mouseGrabber;
       
  1272 }
       
  1273 
       
  1274 QWidget *QWidget::keyboardGrabber()
       
  1275 {
       
  1276     return QWidgetPrivate::keyboardGrabber;
       
  1277 }
       
  1278 
       
  1279 void QWidget::grabKeyboard()
       
  1280 {
       
  1281     if (!qt_nograb()) {
       
  1282         if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
       
  1283             QWidgetPrivate::keyboardGrabber->releaseKeyboard();
       
  1284 
       
  1285         // ### TODO: Native keyboard grab
       
  1286 
       
  1287         QWidgetPrivate::keyboardGrabber = this;
       
  1288     }
       
  1289 }
       
  1290 
       
  1291 void QWidget::releaseKeyboard()
       
  1292 {
       
  1293     if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
       
  1294         // ### TODO: Native keyboard release
       
  1295         QWidgetPrivate::keyboardGrabber = 0;
       
  1296     }
       
  1297 }
       
  1298 
       
  1299 void QWidget::grabMouse()
       
  1300 {
       
  1301     if (!qt_nograb()) {
       
  1302         if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
       
  1303             QWidgetPrivate::mouseGrabber->releaseMouse();
       
  1304         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
       
  1305         WId id = effectiveWinId();
       
  1306         id->SetPointerCapture(true);
       
  1307         QWidgetPrivate::mouseGrabber = this;
       
  1308 
       
  1309 #ifndef QT_NO_CURSOR
       
  1310         QApplication::setOverrideCursor(cursor());
       
  1311 #endif
       
  1312     }
       
  1313 }
       
  1314 
       
  1315 #ifndef QT_NO_CURSOR
       
  1316 void QWidget::grabMouse(const QCursor &cursor)
       
  1317 {
       
  1318     if (!qt_nograb()) {
       
  1319         if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
       
  1320             QWidgetPrivate::mouseGrabber->releaseMouse();
       
  1321         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
       
  1322         WId id = effectiveWinId();
       
  1323         id->SetPointerCapture(true);
       
  1324         QWidgetPrivate::mouseGrabber = this;
       
  1325 
       
  1326         QApplication::setOverrideCursor(cursor);
       
  1327     }
       
  1328 }
       
  1329 #endif
       
  1330 
       
  1331 void QWidget::releaseMouse()
       
  1332 {
       
  1333     if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
       
  1334         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
       
  1335         WId id = effectiveWinId();
       
  1336         id->SetPointerCapture(false);
       
  1337         QWidgetPrivate::mouseGrabber = 0;
       
  1338 #ifndef QT_NO_CURSOR
       
  1339         QApplication::restoreOverrideCursor();
       
  1340 #endif
       
  1341     }
       
  1342 }
       
  1343 
       
  1344 void QWidget::activateWindow()
       
  1345 {
       
  1346     Q_D(QWidget);
       
  1347 
       
  1348     QWidget *tlw = window();
       
  1349     if (tlw->isVisible()) {
       
  1350         window()->createWinId();
       
  1351         QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId());
       
  1352         id->setFocusSafely(true);
       
  1353     }
       
  1354 }
       
  1355 
       
  1356 #ifndef QT_NO_CURSOR
       
  1357 
       
  1358 void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
       
  1359 {
       
  1360     Q_UNUSED(cursor);
       
  1361     Q_Q(QWidget);
       
  1362     qt_symbian_set_cursor(q, false);
       
  1363 }
       
  1364 
       
  1365 void QWidgetPrivate::unsetCursor_sys()
       
  1366 {
       
  1367     Q_Q(QWidget);
       
  1368     qt_symbian_set_cursor(q, false);
       
  1369 }
       
  1370 #endif
       
  1371 
       
  1372 QT_END_NAMESPACE